diff --git a/.github/workflow_data/commit.sh b/.github/workflow_data/commit.sh
new file mode 100644
index 000000000..ddfe7040f
--- /dev/null
+++ b/.github/workflow_data/commit.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+export VERSION_TAG="$(python -c 'import fbt_options; print(fbt_options.DIST_SUFFIX, end="")')"
+echo "VERSION_TAG=${VERSION_TAG}" >> $GITHUB_ENV
diff --git a/.github/workflow_data/devbuild.py b/.github/workflow_data/devbuild.py
new file mode 100644
index 000000000..fd409bce2
--- /dev/null
+++ b/.github/workflow_data/devbuild.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+import nextcloud_client
+import datetime as dt
+import requests
+import json
+import os
+
+dev_share = os.environ["NC_HOST"] + "s/sGHsQB94a9x5CRs/download?path=/&files={files}"
+
+if __name__ == "__main__":
+ with open(os.environ["GITHUB_EVENT_PATH"], "r") as f:
+ event = json.load(f)
+
+ client = nextcloud_client.Client(os.environ["NC_HOST"])
+ client.login(os.environ["NC_USER"], os.environ["NC_PASS"])
+
+ for file in (
+ os.environ["ARTIFACT_TGZ"],
+ os.environ["ARTIFACT_SDK"],
+ ):
+ path = f"XFW-Dev/{file}"
+ # try:
+ # client.delete(path)
+ # except Exception:
+ # pass
+ client.put_file(path, file)
+
+ requests.post(
+ os.environ["BUILD_WEBHOOK"],
+ headers={"Accept": "application/json", "Content-Type": "application/json"},
+ json={
+ "content": None,
+ "embeds": [
+ {
+ "title": "Devbuild infos:",
+ "description": "",
+ "url": "",
+ "color": 16734443,
+ "fields": [
+ {
+ "name": "Changes since last commit:",
+ "value": f"[Compare {event['before'][:7]} to {event['after'][:7]}]({event['compare']})"
+ },
+ {
+ "name": "Changes since last release:",
+ "value": f"[Compare release to {event['after'][:7]}]({event['compare'].rsplit('/', 1)[0] + '/main...' + event['after']})"
+ },
+ {
+ "name": "Firmware download:",
+ "value": f"- [Download SDK for development]({dev_share.format(files=os.environ['ARTIFACT_SDK'])})\n- [Download Firmware TGZ]({dev_share.format(files=os.environ['ARTIFACT_TGZ'])})"
+ }
+ ],
+ "author": {
+ "name": "Build Succeeded!",
+ "icon_url": "https://cdn.discordapp.com/emojis/1080005692485795930.png"
+ },
+ "footer": {
+ "text": "Build go brrrr",
+ "icon_url": "https://cdn.discordapp.com/emojis/1059798228725403719.png"
+ },
+ "timestamp": dt.datetime.utcnow().isoformat()
+ }
+ ],
+ },
+ )
diff --git a/.github/workflow_data/hotfix.py b/.github/workflow_data/hotfix.py
index 5d09d9f9c..91a60868f 100644
--- a/.github/workflow_data/hotfix.py
+++ b/.github/workflow_data/hotfix.py
@@ -21,7 +21,8 @@ if __name__ == "__main__":
artifacts = {
os.environ['ARTIFACT_TGZ']: "application/gzip",
- os.environ['ARTIFACT_ZIP']: "application/zip"
+ os.environ['ARTIFACT_ZIP']: "application/zip",
+ os.environ['ARTIFACT_SDK']: "application/zip",
}
for asset in release["assets"]:
@@ -59,7 +60,7 @@ if __name__ == "__main__":
body = release["body"]
body = re.sub(
- r"(https://github\.com/ClaraCrazy/Flipper-Xtreme/releases/download/[A-Za-z0-9_-]+?/)[A-Za-z0-9_-]+",
+ r"(https://github\.com/Flipper-XFW/Xtreme-Firmware/releases/download/[A-Za-z0-9_-]+?/)[A-Za-z0-9_-]+",
r"\1" + os.environ['VERSION_TAG'],
body
)
diff --git a/.github/workflow_data/package.sh b/.github/workflow_data/package.sh
index 8ee999543..02fa15b48 100644
--- a/.github/workflow_data/package.sh
+++ b/.github/workflow_data/package.sh
@@ -3,12 +3,16 @@ export ARTIFACT_DIR="${VERSION_TAG}"
export ARTIFACT_TGZ="${VERSION_TAG}.tgz"
export ARTIFACT_ZIP="${VERSION_TAG}.zip"
+export ARTIFACT_SDK="${VERSION_TAG}-sdk.zip"
cd dist/${DEFAULT_TARGET}-*
mv ${DEFAULT_TARGET}-update-* ${ARTIFACT_DIR}
tar --format=ustar -czvf ../../${ARTIFACT_TGZ} ${ARTIFACT_DIR}
cd ${ARTIFACT_DIR}
7z a ../../../${ARTIFACT_ZIP} .
-cd ../../..
+cd ..
+mv flipper-z-${DEFAULT_TARGET}-sdk-*.zip ../../${ARTIFACT_SDK}
+cd ../..
echo "ARTIFACT_TGZ=${ARTIFACT_TGZ}" >> $GITHUB_ENV
echo "ARTIFACT_ZIP=${ARTIFACT_ZIP}" >> $GITHUB_ENV
+echo "ARTIFACT_SDK=${ARTIFACT_SDK}" >> $GITHUB_ENV
diff --git a/.github/workflow_data/release.md b/.github/workflow_data/release.md
index 7128cb454..f3fdab973 100644
--- a/.github/workflow_data/release.md
+++ b/.github/workflow_data/release.md
@@ -1,11 +1,11 @@
## ⬇️ Download
>### [🖥️ Web Updater (chrome)](https://flipper-xtre.me/update) [recommended]
->### [🐬 qFlipper Package (.tgz)](https://github.com/ClaraCrazy/Flipper-Xtreme/releases/download/{VERSION_TAG}/{ARTIFACT_TGZ})
+>### [🐬 qFlipper Package (.tgz)](https://github.com/Flipper-XFW/Xtreme-Firmware/releases/download/{VERSION_TAG}/{ARTIFACT_TGZ})
->### [📦 Zipped Archive (.zip)](https://github.com/ClaraCrazy/Flipper-Xtreme/releases/download/{VERSION_TAG}/{ARTIFACT_ZIP})
+>### [📦 Zipped Archive (.zip)](https://github.com/Flipper-XFW/Xtreme-Firmware/releases/download/{VERSION_TAG}/{ARTIFACT_ZIP})
-**Check the [install guide](https://github.com/ClaraCrazy/Flipper-Xtreme#install) if you're not sure, or [join our Discord](https://discord.gg/flipper-xtreme) if you have questions or encounter issues!**
+**Check the [install guide](https://github.com/Flipper-XFW/Xtreme-Firmware#install) if you're not sure, or [join our Discord](https://discord.gg/flipper-xtreme) if you have questions or encounter issues!**
## ❤️ Support
If you like what you're seeing, **please consider donating to us**. We won't ever put this behind a paywall, but we'd still appreciate a few bucks!
diff --git a/.github/workflow_data/version.sh b/.github/workflow_data/version.sh
index b2ba35187..955a78167 100644
--- a/.github/workflow_data/version.sh
+++ b/.github/workflow_data/version.sh
@@ -1,4 +1,11 @@
#!/bin/bash
-export VERSION_TAG="$(python -c 'import fbt_options; print(fbt_options.DIST_SUFFIX)')"
+export VERSION_TAG="$(python -c '''
+import datetime as dt
+with open(os.environ["GITHUB_EVENT_PATH"], "r") as f:
+ event = json.load(f)
+version = int(event["pull_request"]["title"].removeprefix("V").removesuffix(" Release").removesuffix(" Hotfix"))
+date = dt.datetime.now().strftime("%d%m%Y")
+print(f"XFW-{version:04}_{date}", end="")
+''')"
echo "VERSION_TAG=${VERSION_TAG}" >> $GITHUB_ENV
diff --git a/.github/workflow_data/webhook.py b/.github/workflow_data/webhook.py
index 08eab46fb..d1f9c08bb 100644
--- a/.github/workflow_data/webhook.py
+++ b/.github/workflow_data/webhook.py
@@ -16,7 +16,16 @@ if __name__ == "__main__":
match os.environ["GITHUB_EVENT_NAME"]:
case "push":
+ webhook = "BUILD_WEBHOOK"
count = len(event["commits"])
+ if count == 20:
+ count = int(requests.get(
+ event["compare"].replace("github.com", "api.github.com/repos"),
+ headers={
+ "Accept": "application/vnd.github.v3+json",
+ "Authorization": f"token {os.environ['GITHUB_TOKEN']}"
+ }
+ ).json()["total_commits"])
branch = event["ref"].removeprefix("refs/heads/")
change = (
"Force Push"
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 038954256..37515be68 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -9,6 +9,10 @@ on:
- '*'
pull_request:
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
env:
TARGETS: f7
DEFAULT_TARGET: f7
@@ -24,47 +28,38 @@ jobs:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
+ - name: "Read version tag"
+ run: bash .github/workflow_data/commit.sh
+
- name: 'Build the firmware'
run: |
set -e
for TARGET in ${TARGETS}; do
TARGET_HW="$(echo "${TARGET}" | sed 's/f//')"; \
- ./fbt TARGET_HW=$TARGET_HW updater_package
+ ./fbt TARGET_HW=$TARGET_HW DIST_SUFFIX=$VERSION_TAG updater_package
done
- name: "Check for uncommitted changes"
run: |
git diff --exit-code
- - name: 'Updater artifact'
+ - name: 'Dist artifact'
uses: actions/upload-artifact@v3
with:
- name: updater
+ name: dist
path: |
- dist/${{ env.DEFAULT_TARGET }}-*/${{ env.DEFAULT_TARGET }}-update-*/
+ dist/${{ env.DEFAULT_TARGET }}-*/
- # - name: 'Find Previous Comment'
- # if: ${{ github.event.pull_request }}
- # uses: peter-evans/find-comment@v1
- # id: fc
- # with:
- # issue-number: ${{ github.event.pull_request.number }}
- # comment-author: 'github-actions[bot]'
- # body-includes: 'Compiled firmware:'
+ - name: "Make tgz, zip and sdk"
+ run: bash .github/workflow_data/package.sh
- # - name: Artifact info
- # id: artifact-info
- # uses: dawidd6/action-download-artifact@v2
- # with:
- # dry_run: true
-
- # - name: 'Create or update comment'
- # if: ${{ github.event.pull_request}}
- # uses: peter-evans/create-or-update-comment@v1
- # with:
- # comment-id: ${{ steps.fc.outputs.comment-id }}
- # issue-number: ${{ github.event.pull_request.number }}
- # body: |
- # **Compiled firmware:**
- # - [📦 Update package](${{steps.artifact-info.outputs.artifacts[0].archive_download_url}})
- # edit-mode: replace
+ - name: Send devbuild webhook
+ if: "github.event_name == 'push' && github.ref_name == 'dev'"
+ env:
+ NC_HOST: "https://cloud.cynthialabs.net/"
+ NC_USER: "${{ secrets.NC_USER }}"
+ NC_PASS: "${{ secrets.NC_PASS }}"
+ BUILD_WEBHOOK: ${{ secrets.BUILD_WEBHOOK }}
+ run: |
+ python -m pip install pyncclient
+ python .github/workflow_data/devbuild.py
diff --git a/.github/workflows/hotfix.yml b/.github/workflows/hotfix.yml
index d8430d396..38076ae18 100644
--- a/.github/workflows/hotfix.yml
+++ b/.github/workflows/hotfix.yml
@@ -31,22 +31,22 @@ jobs:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
+ - name: "Read version tag"
+ run: bash .github/workflow_data/version.sh
+
- name: 'Build the firmware'
run: |
set -e
for TARGET in ${TARGETS}; do
TARGET_HW="$(echo "${TARGET}" | sed 's/f//')"; \
- ./fbt TARGET_HW=$TARGET_HW FORCE_NO_DIRTY=1 updater_package
+ ./fbt TARGET_HW=$TARGET_HW DIST_SUFFIX=$VERSION_TAG FORCE_NO_DIRTY=1 updater_package
done
- name: "Check for uncommitted changes"
run: |
git diff --exit-code
- - name: "Read version tag"
- run: bash .github/workflow_data/version.sh
-
- - name: "Make tgz and zip"
+ - name: "Make tgz, zip and sdk"
run: bash .github/workflow_data/package.sh
- name: "Upload hotfix"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0fce2a019..47c103807 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -12,7 +12,7 @@ jobs:
release:
if: |
github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name &&
- endsWith(github.event.pull_request.title, ' Release Candidate Changes') &&
+ endsWith(github.event.pull_request.title, ' Release') &&
github.event.review.author_association == 'OWNER' &&
startsWith(github.event.pull_request.title, 'V') &&
github.event.pull_request.base.ref == 'main' &&
@@ -31,22 +31,22 @@ jobs:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
+ - name: "Read version tag"
+ run: bash .github/workflow_data/version.sh
+
- name: 'Build the firmware'
run: |
set -e
for TARGET in ${TARGETS}; do
TARGET_HW="$(echo "${TARGET}" | sed 's/f//')"; \
- ./fbt TARGET_HW=$TARGET_HW FORCE_NO_DIRTY=1 updater_package
+ ./fbt TARGET_HW=$TARGET_HW DIST_SUFFIX=$VERSION_TAG FORCE_NO_DIRTY=1 updater_package
done
- name: "Check for uncommitted changes"
run: |
git diff --exit-code
- - name: "Read version tag"
- run: bash .github/workflow_data/version.sh
-
- - name: "Make tgz and zip"
+ - name: "Make tgz, zip and sdk"
run: bash .github/workflow_data/package.sh
- name: "Update release notes"
@@ -76,6 +76,7 @@ jobs:
files: |
${{ env.ARTIFACT_TGZ }}
${{ env.ARTIFACT_ZIP }}
+ ${{ env.ARTIFACT_SDK }}
name: "${{ env.VERSION_TAG }}"
tag_name: "${{ env.VERSION_TAG }}"
target_commitish: ${{ github.event.pull_request.base.ref }}
diff --git a/.github/workflows/webhook.yml b/.github/workflows/webhook.yml
index a4e380467..2b60a2532 100644
--- a/.github/workflows/webhook.yml
+++ b/.github/workflows/webhook.yml
@@ -39,5 +39,7 @@ jobs:
- name: Send webhook
env:
- DEV_WEBHOOK: "https://discord.com/api/webhooks/${{ secrets.DEV_WEBHOOK_ID }}/${{ secrets.DEV_WEBHOOK_TOKEN }}"
+ BUILD_WEBHOOK: ${{ secrets.BUILD_WEBHOOK }}
+ DEV_WEBHOOK: ${{ secrets.DEV_WEBHOOK }}
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: python .github/workflow_data/webhook.py
diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json
index f2522668d..1d2b55a2c 100644
--- a/.vscode/example/tasks.json
+++ b/.vscode/example/tasks.json
@@ -4,17 +4,29 @@
"version": "2.0.0",
"tasks": [
{
- "label": "[Release] Build",
+ "label": "[Release] Build Firmware",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0"
},
{
- "label": "[Debug] Build",
+ "label": "[Debug] Build Firmware",
"group": "build",
"type": "shell",
"command": "./fbt"
},
+ {
+ "label": "[FBT] Format",
+ "group": "build",
+ "type": "shell",
+ "command": "./fbt format"
+ },
+ {
+ "label": "[FBT] Clear",
+ "group": "build",
+ "type": "shell",
+ "command": "./fbt -c"
+ },
{
"label": "[Release] Flash (ST-Link)",
"group": "build",
@@ -123,17 +135,29 @@
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
},
+ {
+ "label": "[Debug] Build App",
+ "group": "build",
+ "type": "shell",
+ "command": "./fbt build APPSRC=${relativeFileDirname}"
+ },
+ {
+ "label": "[Release] Build App",
+ "group": "build",
+ "type": "shell",
+ "command": "./fbt COMPACT=1 DEBUG=0 build APPSRC=${relativeFileDirname}"
+ },
{
"label": "[Debug] Launch App on Flipper",
"group": "build",
"type": "shell",
- "command": "./fbt launch_app APPSRC=${relativeFileDirname}"
+ "command": "./fbt launch APPSRC=${relativeFileDirname}"
},
{
"label": "[Release] Launch App on Flipper",
"group": "build",
"type": "shell",
- "command": "./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=${relativeFileDirname}"
+ "command": "./fbt COMPACT=1 DEBUG=0 launch APPSRC=${relativeFileDirname}"
},
{
"label": "[Debug] Launch App on Flipper with Serial Console",
@@ -148,13 +172,13 @@
"label": "[Debug] Build and upload all FAPs to Flipper over USB",
"group": "build",
"type": "shell",
- "command": "./fbt faps_copy"
+ "command": "./fbt fap_deploy"
},
{
"label": "[Release] Build and upload all FAPs to Flipper over USB",
"group": "build",
"type": "shell",
- "command": "./fbt COMPACT=1 DEBUG=0 faps_copy"
+ "command": "./fbt COMPACT=1 DEBUG=0 fap_deploy"
},
{
// Press Ctrl+] to quit
@@ -163,7 +187,7 @@
"command": "./fbt cli",
"group": "none",
"isBackground": true,
- "options": {
+ "options": {
"env": {
"FBT_NO_SYNC": "0"
}
diff --git a/ReadMe.md b/ReadMe.md
index 2da02b530..1722a2d70 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -1,11 +1,11 @@
XFW - Xtreme Firmware for the Flipper Zero
-
+
This firmware is a complete overhaul of the [Official Firmware](https://github.com/flipperdevices/flipperzero-firmware), and also features lots of awesome code-bits from [Unleashed](https://github.com/DarkFlippers/unleashed-firmware).
@@ -24,7 +24,7 @@ The goal of this Firmware is to regularly bring out amazing updates based on wha
- Customizable: Dont like the Animations, want to turn on/off the Home screen icons (battery, SD card etc), change the flippers name or anything like that? You absolutely can. No need to mess with code or deal with weird manifest files. Its all done with an App.
-Note, the below mentioned changes are only a few things we did. For a full list click [here](https://github.com/ClaraCrazy/Flipper-Xtreme/wiki/Customization)
+Note, the below mentioned changes are only a few things we did. For a full list click [here](https://github.com/Flipper-XFW/Xtreme-Firmware/wiki/Customization)
-----
@@ -44,7 +44,7 @@ Also, perhaps a bigger height, with set width (yes distrotion issues ik) so it f
- Interface: Customize every bit of your Flipper, from the desktop animations, to the main menu apps, lockscreen style etc.
-- Protocols: Here you can toggle between USB & Bluetooth mode for BadKB, and manage custom Subghz frequencies.
+- Protocols: Here you can toggle between USB & Bluetooth mode for BadKB, and manage custom Subghz frequencies.
- Misc: All the other options that don't fit elsewhere. Change your Flipper's name, xp level, and configure the RGB backlight.
@@ -60,7 +60,7 @@ Also, perhaps a bigger height, with set width (yes distrotion issues ik) so it f
We created our own, new & improved Animation / Asset system, that we can finally reveal. It lets you to create and cycle through your own `Asset Packs` with only a few button presses, allowing you to easily load custom Animations and Icons like never before.
-You can easily create your own pack, or find some user made ones in the discord channel. Check here for a tutorial on creating your own. Essentially, we got our own Anims & Icons folders, inside each Asset Pack.
+You can easily create your own pack, or find some user made ones in the discord channel. Check here for a tutorial on creating your own. Essentially, we got our own Anims & Icons folders, inside each Asset Pack.
@@ -160,21 +160,21 @@ There are 3 methods to install Xtreme, we recommend you use the **Web Updater**,
> Web Updater (Chrome)
-> - Open the latest release page and click on the
Web Updater link
+> - Open the latest release page and click on the
Web Updater link
> - Make sure qFlipper is closed
> - Click
Connect and select your Flipper from the list
> - Click
Flash and wait for the update to complete
>
> qFlipper Package (.tgz)
-> - Download the qFlipper package (.tgz) from the latest release page
+> - Download the qFlipper package (.tgz) from the latest release page
> - Open qFlipper and connect your Flipper
> - Click
Install from file
> - Select the .tgz you downloaded and wait for the update to complete
>
> Zipped Archive (.zip)
-> - Download the zipped archive (.zip) from the latest release page
+> - Download the zipped archive (.zip) from the latest release page
> - Extract the archive. This is now your new Firmware folder
> - Open qFlipper, head to
SD/Update and simply move the firmware folder there
> - On the Flipper, hit the
Arrow Down button, this will get you to the file menu. In there simply search for your updates folder
@@ -192,31 +192,28 @@ There are 3 methods to install Xtreme, we recommend you use the **Web Updater**,
```bash
To download the needed tools:
-$ git clone --recursive https://github.com/ClaraCrazy/Flipper-Xtreme.git
-$ cd Flipper-Xtreme/
+$ git clone --recursive --jobs 8 https://github.com/Flipper-XFW/Xtreme-Firmware.git
+$ cd Xtreme-Firmware/
To flash directly to the Flipper (Needs to be connected via USB, qFlipper closed)
-$ ./fbt flash_usb
+$ ./fbt flash_usb_full
-To just compile firmware
+To compile a TGZ package
$ ./fbt updater_package
-If building FAPS:
-$ ./fbt fap_dist
-
-If building image assets:
-$ ./fbt resources icons dolphin_ext
+To build and launch a single app:
+$ ./fbt launch APPSRC=some_appid
```
----
Stargazers over time
-[](https://starchart.cc/ClaraCrazy/Flipper-Xtreme)
+[](https://starchart.cc/Flipper-XFW/Xtreme-Firmware)
----
Contributors
-[](https://github.com/ClaraCrazy/Flipper-Xtreme/graphs/contributors)
+[](https://github.com/Flipper-XFW/Xtreme-Firmware/graphs/contributors)
## ❤️ Support
diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c
index 4aec0b060..bc2f7887b 100644
--- a/applications/debug/unit_tests/nfc/nfc_test.c
+++ b/applications/debug/unit_tests/nfc/nfc_test.c
@@ -1,12 +1,10 @@
#include
#include
-#include
#include
#include
#include
#include
#include
-#include
#include
#include
@@ -224,153 +222,6 @@ MU_TEST(nfc_digital_signal_test) {
"NFC long digital signal test failed\r\n");
}
-static bool nfc_test_pulse_reader_toggle(
- uint32_t usec_low,
- uint32_t usec_high,
- uint32_t period_count,
- uint32_t tolerance) {
- furi_assert(nfc_test);
-
- bool success = false;
- uint32_t pulses = 0;
- const GpioPin* gpio_in = &gpio_ext_pa6;
- const GpioPin* gpio_out = &gpio_ext_pa7;
- PulseReader* reader = NULL;
-
- do {
- reader = pulse_reader_alloc(gpio_in, 512);
-
- if(!reader) {
- FURI_LOG_E(TAG, "failed to allocate pulse reader");
- break;
- }
-
- /* use TIM1 to create a specific number of pulses with defined duty cycle
- but first set the IO to high, so the low/high pulse can get detected */
- furi_hal_gpio_init(gpio_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
- furi_hal_gpio_write(gpio_out, true);
-
- LL_TIM_DeInit(TIM1);
-
- LL_TIM_SetCounterMode(TIM1, LL_TIM_COUNTERMODE_UP);
- LL_TIM_SetRepetitionCounter(TIM1, 0);
- LL_TIM_SetClockDivision(TIM1, LL_TIM_CLOCKDIVISION_DIV1);
- LL_TIM_SetClockSource(TIM1, LL_TIM_CLOCKSOURCE_INTERNAL);
- LL_TIM_DisableARRPreload(TIM1);
-
- LL_TIM_OC_DisablePreload(TIM1, LL_TIM_CHANNEL_CH1);
- LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_PWM2);
- LL_TIM_OC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH);
- LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH1);
- LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1N);
-
- LL_TIM_EnableAllOutputs(TIM1);
-
- /* now calculate the TIM1 period and compare values */
- uint32_t freq_div = 64 * (usec_low + usec_high);
- uint32_t prescaler = freq_div / 0x10000LU;
- uint32_t period = freq_div / (prescaler + 1);
- uint32_t compare = 64 * usec_low / (prescaler + 1);
-
- LL_TIM_SetPrescaler(TIM1, prescaler);
- LL_TIM_SetAutoReload(TIM1, period - 1);
- LL_TIM_SetCounter(TIM1, period - 1);
- LL_TIM_OC_SetCompareCH1(TIM1, compare);
-
- /* timer is ready to launch, now start the pulse reader */
- pulse_reader_set_timebase(reader, PulseReaderUnitMicrosecond);
- pulse_reader_start(reader);
-
- /* and quickly enable and switch over the GPIO to the generated signal */
- LL_TIM_EnableCounter(TIM1);
- furi_hal_gpio_init_ex(
- gpio_out, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn1TIM1);
-
- /* now it's time to parse the pulses received by the reader */
- uint32_t timer_pulses = period_count;
- uint32_t prev_cnt = 0;
-
- while(timer_pulses > 0) {
- /* whenever the counter gets reset, we went through a full period */
- uint32_t cur_cnt = LL_TIM_GetCounter(TIM1);
- if(cur_cnt < prev_cnt) {
- timer_pulses--;
- }
- prev_cnt = cur_cnt;
- }
- /* quickly halt the counter to keep a static signal */
- LL_TIM_DisableCounter(TIM1);
-
- do {
- /* as all edges were sampled asynchronously, the timeout can be zero */
- uint32_t length = pulse_reader_receive(reader, 0);
-
- /* in the last pulse, we expect a "no edge" return value. if seen that, test succeeded. */
- if(pulses > period_count * 2) {
- if(length != PULSE_READER_NO_EDGE) {
- FURI_LOG_E(
- TAG,
- "last pulse expected to be PULSE_READER_NO_EDGE, but was %lu.",
- length);
- break;
- }
- success = true;
- break;
- }
-
- /* else we shall never see "no edge" or "lost edge" */
- if(length == PULSE_READER_NO_EDGE) {
- FURI_LOG_E(TAG, "%lu. pulse not expected to be PULSE_READER_NO_EDGE", pulses);
- break;
- }
- if(length == PULSE_READER_LOST_EDGE) {
- FURI_LOG_E(TAG, "%lu. pulse not expected to be PULSE_READER_LOST_EDGE", pulses);
- break;
- }
-
- if(pulses > 0) {
- /* throw away the first pulse, which is the 1->0 from the first start and will be irrelevant for our test */
- bool phase = ((pulses - 1) % 2) == 1;
- uint32_t expected = phase ? usec_high : usec_low;
- uint32_t deviation = abs((int32_t)length - (int32_t)expected);
-
- if(deviation > tolerance) {
- FURI_LOG_E(
- TAG,
- "%lu. pulse expected %lu, but pulse was %lu.",
- pulses,
- expected,
- length);
- break;
- }
- }
- pulses++;
- } while(true);
- } while(false);
-
- if(reader != NULL) {
- pulse_reader_stop(reader);
- pulse_reader_free(reader);
- }
-
- LL_TIM_DeInit(TIM1);
- furi_hal_gpio_init_simple(gpio_in, GpioModeAnalog);
- furi_hal_gpio_init_simple(gpio_out, GpioModeAnalog);
-
- return success;
-}
-
-MU_TEST(nfc_pulse_reader_test) {
- mu_assert(nfc_test_pulse_reader_toggle(1500, 2500, 50, 10), "1 ms signal failed\r\n");
- mu_assert(nfc_test_pulse_reader_toggle(10000, 10000, 10, 10), "10 ms signal failed\r\n");
- mu_assert(nfc_test_pulse_reader_toggle(100000, 100000, 5, 50), "100 ms signal failed\r\n");
- mu_assert(nfc_test_pulse_reader_toggle(100, 900, 50, 10), "1 ms asymmetric signal failed\r\n");
- mu_assert(
- nfc_test_pulse_reader_toggle(3333, 6666, 10, 10), "10 ms asymmetric signal failed\r\n");
- mu_assert(
- nfc_test_pulse_reader_toggle(25000, 75000, 5, 10), "100 ms asymmetric signal failed\r\n");
-}
-
MU_TEST(mf_classic_dict_test) {
MfClassicDict* instance = NULL;
uint64_t key = 0;
@@ -705,7 +556,6 @@ MU_TEST(mf_classic_4k_7b_file_test) {
MU_TEST_SUITE(nfc) {
nfc_test_alloc();
- MU_RUN_TEST(nfc_pulse_reader_test);
MU_RUN_TEST(nfca_file_test);
MU_RUN_TEST(mf_mini_file_test);
MU_RUN_TEST(mf_classic_1k_4b_file_test);
diff --git a/applications/drivers/subghz/application.fam b/applications/drivers/subghz/application.fam
index aaf0e1bd9..2ee114833 100644
--- a/applications/drivers/subghz/application.fam
+++ b/applications/drivers/subghz/application.fam
@@ -4,5 +4,6 @@ App(
targets=["f7"],
entry_point="subghz_device_cc1101_ext_ep",
requires=["subghz"],
+ sdk_headers=["cc1101_ext/cc1101_ext_interconnect.h"],
fap_libs=["hwdrivers"],
)
diff --git a/applications/examples/example_thermo/README.md b/applications/examples/example_thermo/README.md
index 08240a1f8..d298de643 100644
--- a/applications/examples/example_thermo/README.md
+++ b/applications/examples/example_thermo/README.md
@@ -18,7 +18,7 @@ Before launching the application, connect the sensor to Flipper's external GPIO
In order to launch this demo, follow the steps below:
1. Make sure your Flipper has an SD card installed.
2. Connect your Flipper to the computer via a USB cable.
-3. Run `./fbt launch_app APPSRC=example_thermo` in your terminal emulator of choice.
+3. Run `./fbt launch APPSRC=example_thermo` in your terminal emulator of choice.
## Changing the data pin
It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below:
diff --git a/applications/external/asteroids/app.c b/applications/external/asteroids/app.c
index cd2f50357..fa116a3cd 100644
--- a/applications/external/asteroids/app.c
+++ b/applications/external/asteroids/app.c
@@ -28,9 +28,7 @@
#define MAXPOWERUPS 3 /* Max powerups allowed on screen */
#define POWERUPSTTL 400 /* Max powerup time to live, in ticks. */
#define SHIP_HIT_ANIMATION_LEN 15
-// Tick runs in thread, cant use APP_DATA_PATH()
-#define SAVING_DIRECTORY EXT_PATH("apps_data/asteroids")
-#define SAVING_FILENAME SAVING_DIRECTORY "/game_asteroids.save"
+#define SAVING_FILENAME APP_DATA_PATH("game_asteroids.save")
#ifndef PI
#define PI 3.14159265358979f
#endif
@@ -1147,7 +1145,6 @@ void game_tick(void* ctx) {
bool load_game(AsteroidsApp* app) {
Storage* storage = furi_record_open(RECORD_STORAGE);
- storage_common_mkdir(storage, SAVING_DIRECTORY);
storage_common_migrate(storage, EXT_PATH("apps/Games/game_asteroids.save"), SAVING_FILENAME);
File* file = storage_file_alloc(storage);
diff --git a/applications/external/barcode_gen/application.fam b/applications/external/barcode_gen/application.fam
index 19bb84122..dad2b30cf 100644
--- a/applications/external/barcode_gen/application.fam
+++ b/applications/external/barcode_gen/application.fam
@@ -8,9 +8,9 @@ App(
fap_category="Tools",
fap_icon="images/barcode_10.png",
fap_icon_assets="images",
- fap_icon_assets_symbol="barcode_app",
+ fap_file_assets="barcode_encoding_files",
fap_author="@Kingal1337",
fap_weburl="https://github.com/Kingal1337/flipper-barcode-generator",
- fap_version="1.0",
+ 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.h b/applications/external/barcode_gen/barcode_app.h
index 3150bff1f..bddc82235 100644
--- a/applications/external/barcode_gen/barcode_app.h
+++ b/applications/external/barcode_gen/barcode_app.h
@@ -23,20 +23,17 @@
#define BARCODE_HEIGHT 50
#define BARCODE_Y_START 3
-//the folder where the encodings are located
-#define BARCODE_DATA_FILE_DIR_PATH EXT_PATH("apps_data/barcode_data")
-
//the folder where the codabar encoding table is located
-#define CODABAR_DICT_FILE_PATH BARCODE_DATA_FILE_DIR_PATH "/codabar_encodings.txt"
+#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 BARCODE_DATA_FILE_DIR_PATH "/code39_encodings.txt"
+#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 BARCODE_DATA_FILE_DIR_PATH "/code128_encodings.txt"
+#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 BARCODE_DATA_FILE_DIR_PATH "/code128c_encodings.txt"
+#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")
diff --git a/assets/resources/apps_data/barcode_data/codabar_encodings.txt b/applications/external/barcode_gen/barcode_encoding_files/codabar_encodings.txt
similarity index 100%
rename from assets/resources/apps_data/barcode_data/codabar_encodings.txt
rename to applications/external/barcode_gen/barcode_encoding_files/codabar_encodings.txt
diff --git a/assets/resources/apps_data/barcode_data/code128_encodings.txt b/applications/external/barcode_gen/barcode_encoding_files/code128_encodings.txt
similarity index 100%
rename from assets/resources/apps_data/barcode_data/code128_encodings.txt
rename to applications/external/barcode_gen/barcode_encoding_files/code128_encodings.txt
diff --git a/assets/resources/apps_data/barcode_data/code128c_encodings.txt b/applications/external/barcode_gen/barcode_encoding_files/code128c_encodings.txt
similarity index 100%
rename from assets/resources/apps_data/barcode_data/code128c_encodings.txt
rename to applications/external/barcode_gen/barcode_encoding_files/code128c_encodings.txt
diff --git a/assets/resources/apps_data/barcode_data/code39_encodings.txt b/applications/external/barcode_gen/barcode_encoding_files/code39_encodings.txt
similarity index 100%
rename from assets/resources/apps_data/barcode_data/code39_encodings.txt
rename to applications/external/barcode_gen/barcode_encoding_files/code39_encodings.txt
diff --git a/applications/external/esp_flasher/application.fam b/applications/external/esp_flasher/application.fam
new file mode 100644
index 000000000..ff5d0774b
--- /dev/null
+++ b/applications/external/esp_flasher/application.fam
@@ -0,0 +1,29 @@
+App(
+ appid="esp_flasher",
+ name="[GPIO] ESP Flasher",
+ apptype=FlipperAppType.EXTERNAL,
+ entry_point="esp_flasher_app",
+ requires=["gui"],
+ stack_size=4 * 1024,
+ order=90,
+ fap_icon="wifi_10px.png",
+ fap_category="GPIO",
+ fap_private_libs=[
+ Lib(
+ name="esp-serial-flasher",
+ fap_include_paths=["include"],
+ sources=[
+ "src/esp_loader.c",
+ "src/esp_targets.c",
+ "src/md5_hash.c",
+ "src/protocol_common.c",
+ "src/protocol_uart.c",
+ "src/slip.c",
+ ],
+ cincludes=["lib/esp-serial-flasher/private_include"],
+ cdefines=["SERIAL_FLASHER_INTERFACE_UART=1", "MD5_ENABLED=1"],
+ ),
+ ],
+ cdefines=["SERIAL_FLASHER_INTERFACE_UART=1"],
+ fap_icon_assets="assets",
+)
diff --git a/applications/external/esp_flasher/assets/DolphinCommon_56x48.png b/applications/external/esp_flasher/assets/DolphinCommon_56x48.png
new file mode 100644
index 000000000..089aaed83
Binary files /dev/null and b/applications/external/esp_flasher/assets/DolphinCommon_56x48.png differ
diff --git a/applications/external/esp_flasher/assets/KeyBackspaceSelected_16x9.png b/applications/external/esp_flasher/assets/KeyBackspaceSelected_16x9.png
new file mode 100644
index 000000000..7cc0759a8
Binary files /dev/null and b/applications/external/esp_flasher/assets/KeyBackspaceSelected_16x9.png differ
diff --git a/applications/external/esp_flasher/assets/KeyBackspace_16x9.png b/applications/external/esp_flasher/assets/KeyBackspace_16x9.png
new file mode 100644
index 000000000..9946232d9
Binary files /dev/null and b/applications/external/esp_flasher/assets/KeyBackspace_16x9.png differ
diff --git a/applications/external/esp_flasher/assets/KeyKeyboardSelected_10x11.png b/applications/external/esp_flasher/assets/KeyKeyboardSelected_10x11.png
new file mode 100644
index 000000000..231880386
Binary files /dev/null and b/applications/external/esp_flasher/assets/KeyKeyboardSelected_10x11.png differ
diff --git a/applications/external/esp_flasher/assets/KeyKeyboard_10x11.png b/applications/external/esp_flasher/assets/KeyKeyboard_10x11.png
new file mode 100644
index 000000000..1f4c03478
Binary files /dev/null and b/applications/external/esp_flasher/assets/KeyKeyboard_10x11.png differ
diff --git a/applications/external/esp_flasher/assets/KeySaveSelected_24x11.png b/applications/external/esp_flasher/assets/KeySaveSelected_24x11.png
new file mode 100644
index 000000000..eeb3569d3
Binary files /dev/null and b/applications/external/esp_flasher/assets/KeySaveSelected_24x11.png differ
diff --git a/applications/external/esp_flasher/assets/KeySave_24x11.png b/applications/external/esp_flasher/assets/KeySave_24x11.png
new file mode 100644
index 000000000..e7dba987a
Binary files /dev/null and b/applications/external/esp_flasher/assets/KeySave_24x11.png differ
diff --git a/applications/external/esp_flasher/assets/Text_10x10.png b/applications/external/esp_flasher/assets/Text_10x10.png
new file mode 100644
index 000000000..8e8a6183d
Binary files /dev/null and b/applications/external/esp_flasher/assets/Text_10x10.png differ
diff --git a/applications/external/esp_flasher/assets/WarningDolphin_45x42.png b/applications/external/esp_flasher/assets/WarningDolphin_45x42.png
new file mode 100644
index 000000000..d766ffbb4
Binary files /dev/null and b/applications/external/esp_flasher/assets/WarningDolphin_45x42.png differ
diff --git a/applications/external/esp_flasher/esp_flasher_app.c b/applications/external/esp_flasher/esp_flasher_app.c
new file mode 100644
index 000000000..e29bb148f
--- /dev/null
+++ b/applications/external/esp_flasher/esp_flasher_app.c
@@ -0,0 +1,135 @@
+#include "esp_flasher_app_i.h"
+
+#include
+#include
+
+static bool esp_flasher_app_custom_event_callback(void* context, uint32_t event) {
+ furi_assert(context);
+ EspFlasherApp* app = context;
+ return scene_manager_handle_custom_event(app->scene_manager, event);
+}
+
+static bool esp_flasher_app_back_event_callback(void* context) {
+ furi_assert(context);
+ EspFlasherApp* app = context;
+ return scene_manager_handle_back_event(app->scene_manager);
+}
+
+static void esp_flasher_app_tick_event_callback(void* context) {
+ furi_assert(context);
+ EspFlasherApp* app = context;
+ scene_manager_handle_tick_event(app->scene_manager);
+}
+
+EspFlasherApp* esp_flasher_app_alloc() {
+ EspFlasherApp* app = malloc(sizeof(EspFlasherApp));
+
+ app->gui = furi_record_open(RECORD_GUI);
+ app->dialogs = furi_record_open(RECORD_DIALOGS);
+ app->storage = furi_record_open(RECORD_STORAGE);
+
+ app->view_dispatcher = view_dispatcher_alloc();
+ app->scene_manager = scene_manager_alloc(&esp_flasher_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, esp_flasher_app_custom_event_callback);
+ view_dispatcher_set_navigation_event_callback(
+ app->view_dispatcher, esp_flasher_app_back_event_callback);
+ view_dispatcher_set_tick_event_callback(
+ app->view_dispatcher, esp_flasher_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,
+ EspFlasherAppViewVarItemList,
+ variable_item_list_get_view(app->var_item_list));
+
+ app->text_box = text_box_alloc();
+ view_dispatcher_add_view(
+ app->view_dispatcher, EspFlasherAppViewConsoleOutput, text_box_get_view(app->text_box));
+ app->text_box_store = furi_string_alloc();
+ furi_string_reserve(app->text_box_store, ESP_FLASHER_TEXT_BOX_STORE_SIZE);
+
+ app->widget = widget_alloc();
+ view_dispatcher_add_view(
+ app->view_dispatcher, EspFlasherAppViewWidget, widget_get_view(app->widget));
+
+ // Submenu
+ app->submenu = submenu_alloc();
+ view_dispatcher_add_view(
+ app->view_dispatcher, EspFlasherAppViewSubmenu, submenu_get_view(app->submenu));
+
+ app->flash_worker_busy = false;
+
+ scene_manager_next_scene(app->scene_manager, EspFlasherSceneStart);
+
+ return app;
+}
+
+void esp_flasher_make_app_folder(EspFlasherApp* app) {
+ furi_assert(app);
+
+ if(!storage_simply_mkdir(app->storage, ESP_APP_FOLDER)) {
+ dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder");
+ }
+}
+
+void esp_flasher_app_free(EspFlasherApp* app) {
+ furi_assert(app);
+
+ // Views
+ view_dispatcher_remove_view(app->view_dispatcher, EspFlasherAppViewVarItemList);
+ view_dispatcher_remove_view(app->view_dispatcher, EspFlasherAppViewConsoleOutput);
+ view_dispatcher_remove_view(app->view_dispatcher, EspFlasherAppViewWidget);
+ view_dispatcher_remove_view(app->view_dispatcher, EspFlasherAppViewSubmenu);
+
+ widget_free(app->widget);
+ text_box_free(app->text_box);
+ furi_string_free(app->text_box_store);
+ submenu_free(app->submenu);
+ variable_item_list_free(app->var_item_list);
+
+ // View dispatcher
+ view_dispatcher_free(app->view_dispatcher);
+ scene_manager_free(app->scene_manager);
+
+ esp_flasher_uart_free(app->uart);
+
+ // Close records
+ furi_record_close(RECORD_GUI);
+ furi_record_close(RECORD_STORAGE);
+ furi_record_close(RECORD_DIALOGS);
+
+ free(app);
+}
+
+int32_t esp_flasher_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);
+
+ EspFlasherApp* esp_flasher_app = esp_flasher_app_alloc();
+
+ esp_flasher_make_app_folder(esp_flasher_app);
+
+ esp_flasher_app->uart = esp_flasher_usart_init(esp_flasher_app);
+
+ view_dispatcher_run(esp_flasher_app->view_dispatcher);
+
+ esp_flasher_app_free(esp_flasher_app);
+
+ if(furi_hal_power_is_otg_enabled()) {
+ furi_hal_power_disable_otg();
+ }
+
+ return 0;
+}
diff --git a/applications/external/esp_flasher/esp_flasher_app.h b/applications/external/esp_flasher/esp_flasher_app.h
new file mode 100644
index 000000000..413dd58a3
--- /dev/null
+++ b/applications/external/esp_flasher/esp_flasher_app.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ESP_FLASHER_APP_VERSION "v1.0"
+
+typedef struct EspFlasherApp EspFlasherApp;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/applications/external/esp_flasher/esp_flasher_app_i.h b/applications/external/esp_flasher/esp_flasher_app_i.h
new file mode 100644
index 000000000..9b8b81a29
--- /dev/null
+++ b/applications/external/esp_flasher/esp_flasher_app_i.h
@@ -0,0 +1,75 @@
+//** Includes sniffbt and sniffskim for compatible ESP32-WROOM hardware.
+// esp_flasher_scene_start.c also changed **//
+#pragma once
+
+#include "esp_flasher_app.h"
+#include "scenes/esp_flasher_scene.h"
+#include "esp_flasher_custom_event.h"
+#include "esp_flasher_uart.h"
+#include "file/sequential_file.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#define ESP_FLASHER_TEXT_BOX_STORE_SIZE (4096)
+
+#define ESP_APP_FOLDER_USER "apps_data/esp_flasher"
+#define ESP_APP_FOLDER EXT_PATH(ESP_APP_FOLDER_USER)
+
+typedef enum SelectedFlashOptions {
+ SelectedFlashS3Mode,
+ SelectedFlashBoot,
+ SelectedFlashPart,
+ SelectedFlashNvs,
+ SelectedFlashBootApp0,
+ SelectedFlashApp,
+ SelectedFlashCustom,
+ NUM_FLASH_OPTIONS
+} SelectedFlashOptions;
+
+struct EspFlasherApp {
+ Gui* gui;
+ ViewDispatcher* view_dispatcher;
+ SceneManager* scene_manager;
+
+ FuriString* text_box_store;
+ size_t text_box_store_strlen;
+ TextBox* text_box;
+ Storage* storage;
+ DialogsApp* dialogs;
+
+ VariableItemList* var_item_list;
+ Widget* widget;
+ Submenu* submenu;
+
+ EspFlasherUart* uart;
+
+ bool selected_flash_options[NUM_FLASH_OPTIONS];
+ int num_selected_flash_options;
+ char bin_file_path_boot[100];
+ char bin_file_path_part[100];
+ char bin_file_path_nvs[100];
+ char bin_file_path_boot_app0[100];
+ char bin_file_path_app[100];
+ char bin_file_path_custom[100];
+ FuriThread* flash_worker;
+ bool flash_worker_busy;
+};
+
+typedef enum {
+ EspFlasherAppViewVarItemList,
+ EspFlasherAppViewConsoleOutput,
+ EspFlasherAppViewTextInput,
+ EspFlasherAppViewWidget,
+ EspFlasherAppViewSubmenu,
+} EspFlasherAppView;
diff --git a/applications/external/esp_flasher/esp_flasher_custom_event.h b/applications/external/esp_flasher/esp_flasher_custom_event.h
new file mode 100644
index 000000000..07d362a6e
--- /dev/null
+++ b/applications/external/esp_flasher/esp_flasher_custom_event.h
@@ -0,0 +1,9 @@
+#pragma once
+
+typedef enum {
+ EspFlasherEventRefreshConsoleOutput = 0,
+ EspFlasherEventStartConsole,
+ EspFlasherEventStartKeyboard,
+ EspFlasherEventStartFlasher,
+ EspFlasherEventRefreshSubmenu
+} EspFlasherCustomEvent;
diff --git a/applications/external/esp_flasher/esp_flasher_uart.c b/applications/external/esp_flasher/esp_flasher_uart.c
new file mode 100644
index 000000000..7dd2904b5
--- /dev/null
+++ b/applications/external/esp_flasher/esp_flasher_uart.c
@@ -0,0 +1,106 @@
+#include "esp_flasher_app_i.h"
+#include "esp_flasher_uart.h"
+
+#define UART_CH (FuriHalUartIdUSART1)
+#define BAUDRATE (115200)
+
+struct EspFlasherUart {
+ EspFlasherApp* 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 esp_flasher_uart_set_handle_rx_data_cb(
+ EspFlasherUart* 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 esp_flasher_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+ EspFlasherUart* uart = (EspFlasherUart*)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) {
+ EspFlasherUart* 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 esp_flasher_uart_tx(uint8_t* data, size_t len) {
+ furi_hal_uart_tx(UART_CH, data, len);
+}
+
+EspFlasherUart*
+ esp_flasher_uart_init(EspFlasherApp* app, FuriHalUartId channel, const char* thread_name) {
+ EspFlasherUart* uart = malloc(sizeof(EspFlasherUart));
+
+ 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, esp_flasher_uart_on_irq_cb, uart);
+
+ return uart;
+}
+
+EspFlasherUart* esp_flasher_usart_init(EspFlasherApp* app) {
+ return esp_flasher_uart_init(app, UART_CH, "EspFlasherUartRxThread");
+}
+
+void esp_flasher_uart_free(EspFlasherUart* 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/esp_flasher/esp_flasher_uart.h b/applications/external/esp_flasher/esp_flasher_uart.h
new file mode 100644
index 000000000..9710c92b3
--- /dev/null
+++ b/applications/external/esp_flasher/esp_flasher_uart.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "furi_hal.h"
+
+#define RX_BUF_SIZE (2048)
+
+typedef struct EspFlasherUart EspFlasherUart;
+
+void esp_flasher_uart_set_handle_rx_data_cb(
+ EspFlasherUart* uart,
+ void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
+void esp_flasher_uart_tx(uint8_t* data, size_t len);
+EspFlasherUart* esp_flasher_usart_init(EspFlasherApp* app);
+void esp_flasher_uart_free(EspFlasherUart* uart);
diff --git a/applications/external/esp_flasher/esp_flasher_worker.c b/applications/external/esp_flasher/esp_flasher_worker.c
new file mode 100644
index 000000000..b5a647d4b
--- /dev/null
+++ b/applications/external/esp_flasher/esp_flasher_worker.c
@@ -0,0 +1,255 @@
+#include "esp_flasher_worker.h"
+
+FuriStreamBuffer* flash_rx_stream; // TODO make safe
+EspFlasherApp* global_app; // TODO make safe
+FuriTimer* timer; // TODO make
+
+static uint32_t _remaining_time = 0;
+static void _timer_callback(void* context) {
+ UNUSED(context);
+ if(_remaining_time > 0) {
+ _remaining_time--;
+ }
+}
+
+static esp_loader_error_t _flash_file(EspFlasherApp* app, char* filepath, uint32_t addr) {
+ // TODO cleanup
+ esp_loader_error_t err;
+ static uint8_t payload[1024];
+ File* bin_file = storage_file_alloc(app->storage);
+
+ char user_msg[256];
+
+ // open file
+ if(!storage_file_open(bin_file, filepath, FSAM_READ, FSOM_OPEN_EXISTING)) {
+ storage_file_close(bin_file);
+ storage_file_free(bin_file);
+ dialog_message_show_storage_error(app->dialogs, "Cannot open file");
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ uint64_t size = storage_file_size(bin_file);
+
+ loader_port_debug_print("Erasing flash...this may take a while\n");
+ err = esp_loader_flash_start(addr, size, sizeof(payload));
+ if(err != ESP_LOADER_SUCCESS) {
+ storage_file_close(bin_file);
+ storage_file_free(bin_file);
+ snprintf(user_msg, sizeof(user_msg), "Erasing flash failed with error %d\n", err);
+ loader_port_debug_print(user_msg);
+ return err;
+ }
+
+ loader_port_debug_print("Start programming\n");
+ uint64_t last_updated = size;
+ while(size > 0) {
+ if((last_updated - size) > 50000) {
+ // inform user every 50k bytes
+ // TODO: draw a progress bar next update
+ snprintf(user_msg, sizeof(user_msg), "%llu bytes left.\n", size);
+ loader_port_debug_print(user_msg);
+ last_updated = size;
+ }
+ size_t to_read = MIN(size, sizeof(payload));
+ uint16_t num_bytes = storage_file_read(bin_file, payload, to_read);
+ err = esp_loader_flash_write(payload, num_bytes);
+ if(err != ESP_LOADER_SUCCESS) {
+ snprintf(user_msg, sizeof(user_msg), "Packet could not be written! Error: %u\n", err);
+ storage_file_close(bin_file);
+ storage_file_free(bin_file);
+ loader_port_debug_print(user_msg);
+ return err;
+ }
+
+ size -= num_bytes;
+ }
+
+ loader_port_debug_print("Finished programming\n");
+
+ // TODO verify
+
+ storage_file_close(bin_file);
+ storage_file_free(bin_file);
+
+ return ESP_LOADER_SUCCESS;
+}
+
+typedef struct {
+ SelectedFlashOptions selected;
+ const char* description;
+ char* path;
+ uint32_t addr;
+} FlashItem;
+
+static void _flash_all_files(EspFlasherApp* app) {
+ esp_loader_error_t err;
+ const int num_steps = app->num_selected_flash_options;
+
+#define NUM_FLASH_ITEMS 6
+ FlashItem items[NUM_FLASH_ITEMS] = {
+ {SelectedFlashBoot,
+ "bootloader",
+ app->bin_file_path_boot,
+ app->selected_flash_options[SelectedFlashS3Mode] ? ESP_ADDR_BOOT_S3 : ESP_ADDR_BOOT},
+ {SelectedFlashPart, "partition table", app->bin_file_path_part, ESP_ADDR_PART},
+ {SelectedFlashNvs, "NVS", app->bin_file_path_nvs, ESP_ADDR_NVS},
+ {SelectedFlashBootApp0, "boot_app0", app->bin_file_path_boot_app0, ESP_ADDR_BOOT_APP0},
+ {SelectedFlashApp, "firmware", app->bin_file_path_app, ESP_ADDR_APP},
+ {SelectedFlashCustom, "custom data", app->bin_file_path_custom, 0x0},
+ /* if you add more entries, update NUM_FLASH_ITEMS above! */
+ };
+
+ char user_msg[256];
+
+ int current_step = 1;
+ for(FlashItem* item = &items[0]; item < &items[NUM_FLASH_ITEMS]; ++item) {
+ if(app->selected_flash_options[item->selected]) {
+ snprintf(
+ user_msg,
+ sizeof(user_msg),
+ "Flashing %s (%d/%d) to address 0x%lx\n",
+ item->description,
+ current_step++,
+ num_steps,
+ item->addr);
+ loader_port_debug_print(user_msg);
+ err = _flash_file(app, item->path, item->addr);
+ if(err) {
+ break;
+ }
+ }
+ }
+}
+
+static int32_t esp_flasher_flash_bin(void* context) {
+ EspFlasherApp* app = (void*)context;
+ esp_loader_error_t err;
+
+ app->flash_worker_busy = true;
+
+ // alloc global objects
+ flash_rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
+ timer = furi_timer_alloc(_timer_callback, FuriTimerTypePeriodic, app);
+
+ loader_port_debug_print("Connecting\n");
+ esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
+ err = esp_loader_connect(&connect_config);
+ if(err != ESP_LOADER_SUCCESS) {
+ char err_msg[256];
+ snprintf(
+ err_msg,
+ sizeof(err_msg),
+ "Cannot connect to target. Error: %u\nMake sure the device is in bootloader/reflash mode, then try again.\n",
+ err);
+ loader_port_debug_print(err_msg);
+ }
+
+#if 0 // still getting packet drops with this
+ // higher BR
+ if(!err) {
+ loader_port_debug_print("Increasing speed for faster flash\n");
+ err = esp_loader_change_transmission_rate(230400);
+ if (err != ESP_LOADER_SUCCESS) {
+ char err_msg[256];
+ snprintf(
+ err_msg,
+ sizeof(err_msg),
+ "Cannot change transmission rate. Error: %u\n",
+ err);
+ loader_port_debug_print(err_msg);
+ }
+ furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
+ }
+#endif
+
+ if(!err) {
+ loader_port_debug_print("Connected\n");
+ _flash_all_files(app);
+#if 0
+ loader_port_debug_print("Restoring transmission rate\n");
+ furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200);
+#endif
+ loader_port_debug_print("Done flashing. Please reset the board manually.\n");
+ }
+
+ // done
+ app->flash_worker_busy = false;
+
+ // cleanup
+ furi_stream_buffer_free(flash_rx_stream);
+ flash_rx_stream = NULL;
+ furi_timer_free(timer);
+ return 0;
+}
+
+void esp_flasher_worker_start_thread(EspFlasherApp* app) {
+ global_app = app;
+
+ app->flash_worker = furi_thread_alloc();
+ furi_thread_set_name(app->flash_worker, "EspFlasherFlashWorker");
+ furi_thread_set_stack_size(app->flash_worker, 2048);
+ furi_thread_set_context(app->flash_worker, app);
+ furi_thread_set_callback(app->flash_worker, esp_flasher_flash_bin);
+ furi_thread_start(app->flash_worker);
+}
+
+void esp_flasher_worker_stop_thread(EspFlasherApp* app) {
+ furi_thread_join(app->flash_worker);
+ furi_thread_free(app->flash_worker);
+}
+
+esp_loader_error_t loader_port_read(uint8_t* data, uint16_t size, uint32_t timeout) {
+ size_t read = furi_stream_buffer_receive(flash_rx_stream, data, size, pdMS_TO_TICKS(timeout));
+ if(read < size) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ } else {
+ return ESP_LOADER_SUCCESS;
+ }
+}
+
+esp_loader_error_t loader_port_write(const uint8_t* data, uint16_t size, uint32_t timeout) {
+ UNUSED(timeout);
+ esp_flasher_uart_tx((uint8_t*)data, size);
+ return ESP_LOADER_SUCCESS;
+}
+
+void loader_port_enter_bootloader(void) {
+ // unimplemented
+}
+
+void loader_port_delay_ms(uint32_t ms) {
+ furi_delay_ms(ms);
+}
+
+void loader_port_start_timer(uint32_t ms) {
+ _remaining_time = ms;
+ furi_timer_start(timer, pdMS_TO_TICKS(1));
+}
+
+uint32_t loader_port_remaining_time(void) {
+ return _remaining_time;
+}
+
+extern void esp_flasher_console_output_handle_rx_data_cb(
+ uint8_t* buf,
+ size_t len,
+ void* context); // TODO cleanup
+void loader_port_debug_print(const char* str) {
+ if(global_app)
+ esp_flasher_console_output_handle_rx_data_cb((uint8_t*)str, strlen(str), global_app);
+}
+
+void loader_port_spi_set_cs(uint32_t level) {
+ UNUSED(level);
+ // unimplemented
+}
+
+void esp_flasher_worker_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
+ UNUSED(context);
+ if(flash_rx_stream) {
+ furi_stream_buffer_send(flash_rx_stream, buf, len, 0);
+ } else {
+ // done flashing
+ if(global_app) esp_flasher_console_output_handle_rx_data_cb(buf, len, global_app);
+ }
+}
\ No newline at end of file
diff --git a/applications/external/esp_flasher/esp_flasher_worker.h b/applications/external/esp_flasher/esp_flasher_worker.h
new file mode 100644
index 000000000..00c43a301
--- /dev/null
+++ b/applications/external/esp_flasher/esp_flasher_worker.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "esp_flasher_app_i.h"
+#include "esp_flasher_uart.h"
+#define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */
+#include "esp_loader_io.h"
+
+#define ESP_ADDR_BOOT_S3 0x0
+#define ESP_ADDR_BOOT 0x1000
+#define ESP_ADDR_PART 0x8000
+#define ESP_ADDR_NVS 0x9000
+#define ESP_ADDR_BOOT_APP0 0xE000
+#define ESP_ADDR_APP 0x10000
+
+void esp_flasher_worker_start_thread(EspFlasherApp* app);
+void esp_flasher_worker_stop_thread(EspFlasherApp* app);
+void esp_flasher_worker_handle_rx_data_cb(uint8_t* buf, size_t len, void* context);
\ No newline at end of file
diff --git a/applications/external/esp_flasher/file/sequential_file.c b/applications/external/esp_flasher/file/sequential_file.c
new file mode 100644
index 000000000..d780deb12
--- /dev/null
+++ b/applications/external/esp_flasher/file/sequential_file.c
@@ -0,0 +1,46 @@
+#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/esp_flasher/file/sequential_file.h b/applications/external/esp_flasher/file/sequential_file.h
new file mode 100644
index 000000000..4fd4794c2
--- /dev/null
+++ b/applications/external/esp_flasher/file/sequential_file.h
@@ -0,0 +1,15 @@
+#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/esp_flasher/lib/esp-serial-flasher/CMakeCache.txt b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeCache.txt
new file mode 100644
index 000000000..9d4eeffb3
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeCache.txt
@@ -0,0 +1,366 @@
+# This is the CMakeCache file.
+# For build in directory: /home/cococode/flipperzero-firmware/lib/esp-serial-flasher
+# It was generated by CMake: /usr/bin/cmake
+# You can edit this file to change values found and used by cmake.
+# If you do not want to change any of the values, simply exit the editor.
+# If you do want to change a value, simply edit, save, and exit the editor.
+# The syntax for the file is as follows:
+# KEY:TYPE=VALUE
+# KEY is the name of a variable in the cache.
+# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
+# VALUE is the current value for the KEY.
+
+########################
+# EXTERNAL cache entries
+########################
+
+//Path to a program.
+CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line
+
+//Path to a program.
+CMAKE_AR:FILEPATH=/usr/bin/ar
+
+//Choose the type of build, options are: None Debug Release RelWithDebInfo
+// MinSizeRel ...
+CMAKE_BUILD_TYPE:STRING=
+
+//Enable/Disable color output during build.
+CMAKE_COLOR_MAKEFILE:BOOL=ON
+
+//CXX compiler
+CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++
+
+//A wrapper around 'ar' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9
+
+//A wrapper around 'ranlib' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9
+
+//Flags used by the CXX compiler during all build types.
+CMAKE_CXX_FLAGS:STRING=
+
+//Flags used by the CXX compiler during DEBUG builds.
+CMAKE_CXX_FLAGS_DEBUG:STRING=-g
+
+//Flags used by the CXX compiler during MINSIZEREL builds.
+CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
+
+//Flags used by the CXX compiler during RELEASE builds.
+CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
+
+//Flags used by the CXX compiler during RELWITHDEBINFO builds.
+CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
+
+//C compiler
+CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc
+
+//A wrapper around 'ar' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9
+
+//A wrapper around 'ranlib' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9
+
+//Flags used by the C compiler during all build types.
+CMAKE_C_FLAGS:STRING=
+
+//Flags used by the C compiler during DEBUG builds.
+CMAKE_C_FLAGS_DEBUG:STRING=-g
+
+//Flags used by the C compiler during MINSIZEREL builds.
+CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
+
+//Flags used by the C compiler during RELEASE builds.
+CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
+
+//Flags used by the C compiler during RELWITHDEBINFO builds.
+CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
+
+//Path to a program.
+CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND
+
+//Flags used by the linker during all build types.
+CMAKE_EXE_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during DEBUG builds.
+CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during MINSIZEREL builds.
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during RELEASE builds.
+CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during RELWITHDEBINFO builds.
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Enable/Disable output of compile commands during generation.
+CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF
+
+//Install path prefix, prepended onto install directories.
+CMAKE_INSTALL_PREFIX:PATH=/usr/local
+
+//Path to a program.
+CMAKE_LINKER:FILEPATH=/usr/bin/ld
+
+//Path to a program.
+CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make
+
+//Flags used by the linker during the creation of modules during
+// all build types.
+CMAKE_MODULE_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of modules during
+// DEBUG builds.
+CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of modules during
+// MINSIZEREL builds.
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of modules during
+// RELEASE builds.
+CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of modules during
+// RELWITHDEBINFO builds.
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Path to a program.
+CMAKE_NM:FILEPATH=/usr/bin/nm
+
+//Path to a program.
+CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy
+
+//Path to a program.
+CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump
+
+//Value Computed by CMake
+CMAKE_PROJECT_DESCRIPTION:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_NAME:STATIC=Project
+
+//Path to a program.
+CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib
+
+//Path to a program.
+CMAKE_READELF:FILEPATH=/usr/bin/readelf
+
+//Flags used by the linker during the creation of shared libraries
+// during all build types.
+CMAKE_SHARED_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during DEBUG builds.
+CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during MINSIZEREL builds.
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during RELEASE builds.
+CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during RELWITHDEBINFO builds.
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//If set, runtime paths are not added when installing shared libraries,
+// but are added when building.
+CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
+
+//If set, runtime paths are not added when using shared libraries.
+CMAKE_SKIP_RPATH:BOOL=NO
+
+//Flags used by the linker during the creation of static libraries
+// during all build types.
+CMAKE_STATIC_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during DEBUG builds.
+CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during MINSIZEREL builds.
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELEASE builds.
+CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELWITHDEBINFO builds.
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Path to a program.
+CMAKE_STRIP:FILEPATH=/usr/bin/strip
+
+//If this value is on, makefiles will be generated without the
+// .SILENT directive, and all commands will be echoed to the console
+// during the make. This is useful for debugging only. With Visual
+// Studio IDE projects all commands are done without /nologo.
+CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
+
+//Value Computed by CMake
+Project_BINARY_DIR:STATIC=/home/cococode/flipperzero-firmware/lib/esp-serial-flasher
+
+//Value Computed by CMake
+Project_SOURCE_DIR:STATIC=/home/cococode/flipperzero-firmware/lib/esp-serial-flasher
+
+
+########################
+# INTERNAL cache entries
+########################
+
+//ADVANCED property for variable: CMAKE_ADDR2LINE
+CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_AR
+CMAKE_AR-ADVANCED:INTERNAL=1
+//This is the directory where this CMakeCache.txt was created
+CMAKE_CACHEFILE_DIR:INTERNAL=/home/cococode/flipperzero-firmware/lib/esp-serial-flasher
+//Major version of cmake used to create the current loaded cache
+CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
+//Minor version of cmake used to create the current loaded cache
+CMAKE_CACHE_MINOR_VERSION:INTERNAL=16
+//Patch version of cmake used to create the current loaded cache
+CMAKE_CACHE_PATCH_VERSION:INTERNAL=3
+//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE
+CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1
+//Path to CMake executable.
+CMAKE_COMMAND:INTERNAL=/usr/bin/cmake
+//Path to cpack program executable.
+CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack
+//Path to ctest program executable.
+CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest
+//ADVANCED property for variable: CMAKE_CXX_COMPILER
+CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR
+CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB
+CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS
+CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
+CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
+CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
+CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
+CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER
+CMAKE_C_COMPILER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER_AR
+CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB
+CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS
+CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
+CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
+CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
+CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
+CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_DLLTOOL
+CMAKE_DLLTOOL-ADVANCED:INTERNAL=1
+//Executable file format
+CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
+CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
+CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
+CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS
+CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1
+//Name of external makefile project generator.
+CMAKE_EXTRA_GENERATOR:INTERNAL=
+//Name of generator.
+CMAKE_GENERATOR:INTERNAL=Unix Makefiles
+//Generator instance identifier.
+CMAKE_GENERATOR_INSTANCE:INTERNAL=
+//Name of generator platform.
+CMAKE_GENERATOR_PLATFORM:INTERNAL=
+//Name of generator toolset.
+CMAKE_GENERATOR_TOOLSET:INTERNAL=
+//Source directory with the top level CMakeLists.txt file for this
+// project
+CMAKE_HOME_DIRECTORY:INTERNAL=/home/cococode/flipperzero-firmware/lib/esp-serial-flasher
+//Install .so files without execute permission.
+CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1
+//ADVANCED property for variable: CMAKE_LINKER
+CMAKE_LINKER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MAKE_PROGRAM
+CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
+CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
+CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
+CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_NM
+CMAKE_NM-ADVANCED:INTERNAL=1
+//number of local generators
+CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1
+//ADVANCED property for variable: CMAKE_OBJCOPY
+CMAKE_OBJCOPY-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_OBJDUMP
+CMAKE_OBJDUMP-ADVANCED:INTERNAL=1
+//Platform information initialized
+CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_RANLIB
+CMAKE_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_READELF
+CMAKE_READELF-ADVANCED:INTERNAL=1
+//Path to CMake installation.
+CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.16
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
+CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
+CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
+CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
+CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_RPATH
+CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
+CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
+CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
+CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STRIP
+CMAKE_STRIP-ADVANCED:INTERNAL=1
+//uname command
+CMAKE_UNAME:INTERNAL=/usr/bin/uname
+//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
+CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
+
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeCCompiler.cmake b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeCCompiler.cmake
new file mode 100644
index 000000000..c5ece7b85
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeCCompiler.cmake
@@ -0,0 +1,76 @@
+set(CMAKE_C_COMPILER "/usr/bin/cc")
+set(CMAKE_C_COMPILER_ARG1 "")
+set(CMAKE_C_COMPILER_ID "GNU")
+set(CMAKE_C_COMPILER_VERSION "9.4.0")
+set(CMAKE_C_COMPILER_VERSION_INTERNAL "")
+set(CMAKE_C_COMPILER_WRAPPER "")
+set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11")
+set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert")
+set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes")
+set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros")
+set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert")
+
+set(CMAKE_C_PLATFORM_ID "Linux")
+set(CMAKE_C_SIMULATE_ID "")
+set(CMAKE_C_COMPILER_FRONTEND_VARIANT "")
+set(CMAKE_C_SIMULATE_VERSION "")
+
+
+
+set(CMAKE_AR "/usr/bin/ar")
+set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-9")
+set(CMAKE_RANLIB "/usr/bin/ranlib")
+set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9")
+set(CMAKE_LINKER "/usr/bin/ld")
+set(CMAKE_MT "")
+set(CMAKE_COMPILER_IS_GNUCC 1)
+set(CMAKE_C_COMPILER_LOADED 1)
+set(CMAKE_C_COMPILER_WORKS TRUE)
+set(CMAKE_C_ABI_COMPILED TRUE)
+set(CMAKE_COMPILER_IS_MINGW )
+set(CMAKE_COMPILER_IS_CYGWIN )
+if(CMAKE_COMPILER_IS_CYGWIN)
+ set(CYGWIN 1)
+ set(UNIX 1)
+endif()
+
+set(CMAKE_C_COMPILER_ENV_VAR "CC")
+
+if(CMAKE_COMPILER_IS_MINGW)
+ set(MINGW 1)
+endif()
+set(CMAKE_C_COMPILER_ID_RUN 1)
+set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
+set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
+set(CMAKE_C_LINKER_PREFERENCE 10)
+
+# Save compiler ABI information.
+set(CMAKE_C_SIZEOF_DATA_PTR "8")
+set(CMAKE_C_COMPILER_ABI "ELF")
+set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+
+if(CMAKE_C_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_C_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}")
+endif()
+
+if(CMAKE_C_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+endif()
+
+set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "")
+if(CMAKE_C_CL_SHOWINCLUDES_PREFIX)
+ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}")
+endif()
+
+
+
+
+
+set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include")
+set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s")
+set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib")
+set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeCXXCompiler.cmake b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeCXXCompiler.cmake
new file mode 100644
index 000000000..278ef39ee
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeCXXCompiler.cmake
@@ -0,0 +1,88 @@
+set(CMAKE_CXX_COMPILER "/usr/bin/c++")
+set(CMAKE_CXX_COMPILER_ARG1 "")
+set(CMAKE_CXX_COMPILER_ID "GNU")
+set(CMAKE_CXX_COMPILER_VERSION "9.4.0")
+set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "")
+set(CMAKE_CXX_COMPILER_WRAPPER "")
+set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14")
+set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20")
+set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters")
+set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates")
+set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates")
+set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17")
+set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20")
+
+set(CMAKE_CXX_PLATFORM_ID "Linux")
+set(CMAKE_CXX_SIMULATE_ID "")
+set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "")
+set(CMAKE_CXX_SIMULATE_VERSION "")
+
+
+
+set(CMAKE_AR "/usr/bin/ar")
+set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-9")
+set(CMAKE_RANLIB "/usr/bin/ranlib")
+set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9")
+set(CMAKE_LINKER "/usr/bin/ld")
+set(CMAKE_MT "")
+set(CMAKE_COMPILER_IS_GNUCXX 1)
+set(CMAKE_CXX_COMPILER_LOADED 1)
+set(CMAKE_CXX_COMPILER_WORKS TRUE)
+set(CMAKE_CXX_ABI_COMPILED TRUE)
+set(CMAKE_COMPILER_IS_MINGW )
+set(CMAKE_COMPILER_IS_CYGWIN )
+if(CMAKE_COMPILER_IS_CYGWIN)
+ set(CYGWIN 1)
+ set(UNIX 1)
+endif()
+
+set(CMAKE_CXX_COMPILER_ENV_VAR "CXX")
+
+if(CMAKE_COMPILER_IS_MINGW)
+ set(MINGW 1)
+endif()
+set(CMAKE_CXX_COMPILER_ID_RUN 1)
+set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP)
+set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
+
+foreach (lang C OBJC OBJCXX)
+ if (CMAKE_${lang}_COMPILER_ID_RUN)
+ foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
+ list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
+ endforeach()
+ endif()
+endforeach()
+
+set(CMAKE_CXX_LINKER_PREFERENCE 30)
+set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
+
+# Save compiler ABI information.
+set(CMAKE_CXX_SIZEOF_DATA_PTR "8")
+set(CMAKE_CXX_COMPILER_ABI "ELF")
+set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+
+if(CMAKE_CXX_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_CXX_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}")
+endif()
+
+if(CMAKE_CXX_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
+endif()
+
+set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "")
+if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX)
+ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}")
+endif()
+
+
+
+
+
+set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/9;/usr/include/x86_64-linux-gnu/c++/9;/usr/include/c++/9/backward;/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include")
+set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc")
+set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib")
+set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_C.bin b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_C.bin
new file mode 100755
index 000000000..35de1468e
Binary files /dev/null and b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_C.bin differ
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_CXX.bin b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_CXX.bin
new file mode 100755
index 000000000..9cba7ec76
Binary files /dev/null and b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_CXX.bin differ
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeSystem.cmake b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeSystem.cmake
new file mode 100644
index 000000000..0ad36cc9a
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CMakeSystem.cmake
@@ -0,0 +1,15 @@
+set(CMAKE_HOST_SYSTEM "Linux-5.10.16.3-microsoft-standard-WSL2")
+set(CMAKE_HOST_SYSTEM_NAME "Linux")
+set(CMAKE_HOST_SYSTEM_VERSION "5.10.16.3-microsoft-standard-WSL2")
+set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64")
+
+
+
+set(CMAKE_SYSTEM "Linux-5.10.16.3-microsoft-standard-WSL2")
+set(CMAKE_SYSTEM_NAME "Linux")
+set(CMAKE_SYSTEM_VERSION "5.10.16.3-microsoft-standard-WSL2")
+set(CMAKE_SYSTEM_PROCESSOR "x86_64")
+
+set(CMAKE_CROSSCOMPILING "FALSE")
+
+set(CMAKE_SYSTEM_LOADED 1)
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdC/CMakeCCompilerId.c b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdC/CMakeCCompilerId.c
new file mode 100644
index 000000000..d884b5090
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdC/CMakeCCompilerId.c
@@ -0,0 +1,671 @@
+#ifdef __cplusplus
+# error "A C++ compiler has been selected for C."
+#endif
+
+#if defined(__18CXX)
+# define ID_VOID_MAIN
+#endif
+#if defined(__CLASSIC_C__)
+/* cv-qualifiers did not exist in K&R C */
+# define const
+# define volatile
+#endif
+
+
+/* Version number components: V=Version, R=Revision, P=Patch
+ Version date components: YYYY=Year, MM=Month, DD=Day */
+
+#if defined(__INTEL_COMPILER) || defined(__ICC)
+# define COMPILER_ID "Intel"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+# endif
+ /* __INTEL_COMPILER = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+# if defined(__INTEL_COMPILER_UPDATE)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+# else
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+# endif
+# if defined(__INTEL_COMPILER_BUILD_DATE)
+ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+# endif
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+# elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(__PATHCC__)
+# define COMPILER_ID "PathScale"
+# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+# if defined(__PATHCC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+# endif
+
+#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+# define COMPILER_ID "Embarcadero"
+# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
+#elif defined(__BORLANDC__)
+# define COMPILER_ID "Borland"
+ /* __BORLANDC__ = 0xVRR */
+# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
+#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+# define COMPILER_ID "Watcom"
+ /* __WATCOMC__ = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__WATCOMC__)
+# define COMPILER_ID "OpenWatcom"
+ /* __WATCOMC__ = VVRP + 1100 */
+# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__SUNPRO_C)
+# define COMPILER_ID "SunPro"
+# if __SUNPRO_C >= 0x5100
+ /* __SUNPRO_C = 0xVRRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
+# else
+ /* __SUNPRO_CC = 0xVRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
+# endif
+
+#elif defined(__HP_cc)
+# define COMPILER_ID "HP"
+ /* __HP_cc = VVRRPP */
+# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000)
+# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100)
+
+#elif defined(__DECC)
+# define COMPILER_ID "Compaq"
+ /* __DECC_VER = VVRRTPPPP */
+# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000)
+# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100)
+# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000)
+
+#elif defined(__IBMC__) && defined(__COMPILER_VER__)
+# define COMPILER_ID "zOS"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__ibmxl__) && defined(__clang__)
+# define COMPILER_ID "XLClang"
+# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
+
+#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800
+# define COMPILER_ID "XL"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800
+# define COMPILER_ID "VisualAge"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__PGI)
+# define COMPILER_ID "PGI"
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
+
+#elif defined(_CRAYC)
+# define COMPILER_ID "Cray"
+# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
+#elif defined(__TI_COMPILER_VERSION__)
+# define COMPILER_ID "TI"
+ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
+#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version)
+# define COMPILER_ID "Fujitsu"
+
+#elif defined(__ghs__)
+# define COMPILER_ID "GHS"
+/* __GHS_VERSION_NUMBER = VVVVRP */
+# ifdef __GHS_VERSION_NUMBER
+# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+# endif
+
+#elif defined(__TINYC__)
+# define COMPILER_ID "TinyCC"
+
+#elif defined(__BCC__)
+# define COMPILER_ID "Bruce"
+
+#elif defined(__SCO_VERSION__)
+# define COMPILER_ID "SCO"
+
+#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+# define COMPILER_ID "ARMCC"
+#if __ARMCC_VERSION >= 1000000
+ /* __ARMCC_VERSION = VRRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#else
+ /* __ARMCC_VERSION = VRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#endif
+
+
+#elif defined(__clang__) && defined(__apple_build_version__)
+# define COMPILER_ID "AppleClang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
+#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+# define COMPILER_ID "ARMClang"
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
+# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
+#elif defined(__clang__)
+# define COMPILER_ID "Clang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+
+#elif defined(__GNUC__)
+# define COMPILER_ID "GNU"
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# if defined(__GNUC_MINOR__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(_MSC_VER)
+# define COMPILER_ID "MSVC"
+ /* _MSC_VER = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+# if defined(_MSC_FULL_VER)
+# if _MSC_VER >= 1400
+ /* _MSC_FULL_VER = VVRRPPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+# else
+ /* _MSC_FULL_VER = VVRRPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+# endif
+# endif
+# if defined(_MSC_BUILD)
+# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+# endif
+
+#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
+# define COMPILER_ID "ADSP"
+#if defined(__VISUALDSPVERSION__)
+ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
+# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
+# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
+#endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# define COMPILER_ID "IAR"
+# if defined(__VER__) && defined(__ICCARM__)
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__))
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# endif
+
+#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC)
+# define COMPILER_ID "SDCC"
+# if defined(__SDCC_VERSION_MAJOR)
+# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR)
+# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH)
+# else
+ /* SDCC = VRP */
+# define COMPILER_VERSION_MAJOR DEC(SDCC/100)
+# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(SDCC % 10)
+# endif
+
+
+/* These compilers are either not known or too old to define an
+ identification macro. Try to identify the platform and guess that
+ it is the native compiler. */
+#elif defined(__hpux) || defined(__hpua)
+# define COMPILER_ID "HP"
+
+#else /* unknown compiler */
+# define COMPILER_ID ""
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+#if defined(__CRAYXE) || defined(__CRAYXC)
+char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+#endif
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+/* Identify known platforms by name. */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+# define PLATFORM_ID "Linux"
+
+#elif defined(__CYGWIN__)
+# define PLATFORM_ID "Cygwin"
+
+#elif defined(__MINGW32__)
+# define PLATFORM_ID "MinGW"
+
+#elif defined(__APPLE__)
+# define PLATFORM_ID "Darwin"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define PLATFORM_ID "Windows"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD)
+# define PLATFORM_ID "FreeBSD"
+
+#elif defined(__NetBSD__) || defined(__NetBSD)
+# define PLATFORM_ID "NetBSD"
+
+#elif defined(__OpenBSD__) || defined(__OPENBSD)
+# define PLATFORM_ID "OpenBSD"
+
+#elif defined(__sun) || defined(sun)
+# define PLATFORM_ID "SunOS"
+
+#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+# define PLATFORM_ID "AIX"
+
+#elif defined(__hpux) || defined(__hpux__)
+# define PLATFORM_ID "HP-UX"
+
+#elif defined(__HAIKU__)
+# define PLATFORM_ID "Haiku"
+
+#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+# define PLATFORM_ID "BeOS"
+
+#elif defined(__QNX__) || defined(__QNXNTO__)
+# define PLATFORM_ID "QNX"
+
+#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+# define PLATFORM_ID "Tru64"
+
+#elif defined(__riscos) || defined(__riscos__)
+# define PLATFORM_ID "RISCos"
+
+#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+# define PLATFORM_ID "SINIX"
+
+#elif defined(__UNIX_SV__)
+# define PLATFORM_ID "UNIX_SV"
+
+#elif defined(__bsdos__)
+# define PLATFORM_ID "BSDOS"
+
+#elif defined(_MPRAS) || defined(MPRAS)
+# define PLATFORM_ID "MP-RAS"
+
+#elif defined(__osf) || defined(__osf__)
+# define PLATFORM_ID "OSF1"
+
+#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+# define PLATFORM_ID "SCO_SV"
+
+#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+# define PLATFORM_ID "ULTRIX"
+
+#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+# define PLATFORM_ID "Xenix"
+
+#elif defined(__WATCOMC__)
+# if defined(__LINUX__)
+# define PLATFORM_ID "Linux"
+
+# elif defined(__DOS__)
+# define PLATFORM_ID "DOS"
+
+# elif defined(__OS2__)
+# define PLATFORM_ID "OS2"
+
+# elif defined(__WINDOWS__)
+# define PLATFORM_ID "Windows3x"
+
+# else /* unknown platform */
+# define PLATFORM_ID
+# endif
+
+#elif defined(__INTEGRITY)
+# if defined(INT_178B)
+# define PLATFORM_ID "Integrity178"
+
+# else /* regular Integrity */
+# define PLATFORM_ID "Integrity"
+# endif
+
+#else /* unknown platform */
+# define PLATFORM_ID
+
+#endif
+
+/* For windows compilers MSVC and Intel we can determine
+ the architecture of the compiler being used. This is because
+ the compilers do not have flags that can change the architecture,
+ but rather depend on which compiler is being used
+*/
+#if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_M_IA64)
+# define ARCHITECTURE_ID "IA64"
+
+# elif defined(_M_X64) || defined(_M_AMD64)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# elif defined(_M_ARM64)
+# define ARCHITECTURE_ID "ARM64"
+
+# elif defined(_M_ARM)
+# if _M_ARM == 4
+# define ARCHITECTURE_ID "ARMV4I"
+# elif _M_ARM == 5
+# define ARCHITECTURE_ID "ARMV5I"
+# else
+# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+# endif
+
+# elif defined(_M_MIPS)
+# define ARCHITECTURE_ID "MIPS"
+
+# elif defined(_M_SH)
+# define ARCHITECTURE_ID "SHx"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__WATCOMC__)
+# if defined(_M_I86)
+# define ARCHITECTURE_ID "I86"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# if defined(__ICCARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__ICCRX__)
+# define ARCHITECTURE_ID "RX"
+
+# elif defined(__ICCRH850__)
+# define ARCHITECTURE_ID "RH850"
+
+# elif defined(__ICCRL78__)
+# define ARCHITECTURE_ID "RL78"
+
+# elif defined(__ICCRISCV__)
+# define ARCHITECTURE_ID "RISCV"
+
+# elif defined(__ICCAVR__)
+# define ARCHITECTURE_ID "AVR"
+
+# elif defined(__ICC430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__ICCV850__)
+# define ARCHITECTURE_ID "V850"
+
+# elif defined(__ICC8051__)
+# define ARCHITECTURE_ID "8051"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__ghs__)
+# if defined(__PPC64__)
+# define ARCHITECTURE_ID "PPC64"
+
+# elif defined(__ppc__)
+# define ARCHITECTURE_ID "PPC"
+
+# elif defined(__ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__x86_64__)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(__i386__)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+#else
+# define ARCHITECTURE_ID
+#endif
+
+/* Convert integer to decimal digit literals. */
+#define DEC(n) \
+ ('0' + (((n) / 10000000)%10)), \
+ ('0' + (((n) / 1000000)%10)), \
+ ('0' + (((n) / 100000)%10)), \
+ ('0' + (((n) / 10000)%10)), \
+ ('0' + (((n) / 1000)%10)), \
+ ('0' + (((n) / 100)%10)), \
+ ('0' + (((n) / 10)%10)), \
+ ('0' + ((n) % 10))
+
+/* Convert integer to hex digit literals. */
+#define HEX(n) \
+ ('0' + ((n)>>28 & 0xF)), \
+ ('0' + ((n)>>24 & 0xF)), \
+ ('0' + ((n)>>20 & 0xF)), \
+ ('0' + ((n)>>16 & 0xF)), \
+ ('0' + ((n)>>12 & 0xF)), \
+ ('0' + ((n)>>8 & 0xF)), \
+ ('0' + ((n)>>4 & 0xF)), \
+ ('0' + ((n) & 0xF))
+
+/* Construct a string literal encoding the version number components. */
+#ifdef COMPILER_VERSION_MAJOR
+char const info_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+ COMPILER_VERSION_MAJOR,
+# ifdef COMPILER_VERSION_MINOR
+ '.', COMPILER_VERSION_MINOR,
+# ifdef COMPILER_VERSION_PATCH
+ '.', COMPILER_VERSION_PATCH,
+# ifdef COMPILER_VERSION_TWEAK
+ '.', COMPILER_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct a string literal encoding the internal version number. */
+#ifdef COMPILER_VERSION_INTERNAL
+char const info_version_internal[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+ 'i','n','t','e','r','n','a','l','[',
+ COMPILER_VERSION_INTERNAL,']','\0'};
+#endif
+
+/* Construct a string literal encoding the version number components. */
+#ifdef SIMULATE_VERSION_MAJOR
+char const info_simulate_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+ SIMULATE_VERSION_MAJOR,
+# ifdef SIMULATE_VERSION_MINOR
+ '.', SIMULATE_VERSION_MINOR,
+# ifdef SIMULATE_VERSION_PATCH
+ '.', SIMULATE_VERSION_PATCH,
+# ifdef SIMULATE_VERSION_TWEAK
+ '.', SIMULATE_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
+
+
+
+#if !defined(__STDC__)
+# if (defined(_MSC_VER) && !defined(__clang__)) \
+ || (defined(__ibmxl__) || defined(__IBMC__))
+# define C_DIALECT "90"
+# else
+# define C_DIALECT
+# endif
+#elif __STDC_VERSION__ >= 201000L
+# define C_DIALECT "11"
+#elif __STDC_VERSION__ >= 199901L
+# define C_DIALECT "99"
+#else
+# define C_DIALECT "90"
+#endif
+const char* info_language_dialect_default =
+ "INFO" ":" "dialect_default[" C_DIALECT "]";
+
+/*--------------------------------------------------------------------------*/
+
+#ifdef ID_VOID_MAIN
+void main() {}
+#else
+# if defined(__CLASSIC_C__)
+int main(argc, argv) int argc; char *argv[];
+# else
+int main(int argc, char* argv[])
+# endif
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+ require += info_arch[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+#if defined(__CRAYXE) || defined(__CRAYXC)
+ require += info_cray[argc];
+#endif
+ require += info_language_dialect_default[argc];
+ (void)argv;
+ return require;
+}
+#endif
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdC/a.out b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdC/a.out
new file mode 100755
index 000000000..e82fab493
Binary files /dev/null and b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdC/a.out differ
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdCXX/CMakeCXXCompilerId.cpp b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdCXX/CMakeCXXCompilerId.cpp
new file mode 100644
index 000000000..69cfdba6b
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdCXX/CMakeCXXCompilerId.cpp
@@ -0,0 +1,660 @@
+/* This source file must have a .cpp extension so that all C++ compilers
+ recognize the extension without flags. Borland does not know .cxx for
+ example. */
+#ifndef __cplusplus
+# error "A C compiler has been selected for C++."
+#endif
+
+
+/* Version number components: V=Version, R=Revision, P=Patch
+ Version date components: YYYY=Year, MM=Month, DD=Day */
+
+#if defined(__COMO__)
+# define COMPILER_ID "Comeau"
+ /* __COMO_VERSION__ = VRR */
+# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
+# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
+
+#elif defined(__INTEL_COMPILER) || defined(__ICC)
+# define COMPILER_ID "Intel"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+# endif
+ /* __INTEL_COMPILER = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+# if defined(__INTEL_COMPILER_UPDATE)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+# else
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+# endif
+# if defined(__INTEL_COMPILER_BUILD_DATE)
+ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+# endif
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+# elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(__PATHCC__)
+# define COMPILER_ID "PathScale"
+# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+# if defined(__PATHCC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+# endif
+
+#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+# define COMPILER_ID "Embarcadero"
+# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
+#elif defined(__BORLANDC__)
+# define COMPILER_ID "Borland"
+ /* __BORLANDC__ = 0xVRR */
+# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
+#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+# define COMPILER_ID "Watcom"
+ /* __WATCOMC__ = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__WATCOMC__)
+# define COMPILER_ID "OpenWatcom"
+ /* __WATCOMC__ = VVRP + 1100 */
+# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__SUNPRO_CC)
+# define COMPILER_ID "SunPro"
+# if __SUNPRO_CC >= 0x5100
+ /* __SUNPRO_CC = 0xVRRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+# else
+ /* __SUNPRO_CC = 0xVRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+# endif
+
+#elif defined(__HP_aCC)
+# define COMPILER_ID "HP"
+ /* __HP_aCC = VVRRPP */
+# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
+# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100)
+
+#elif defined(__DECCXX)
+# define COMPILER_ID "Compaq"
+ /* __DECCXX_VER = VVRRTPPPP */
+# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
+# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100)
+# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000)
+
+#elif defined(__IBMCPP__) && defined(__COMPILER_VER__)
+# define COMPILER_ID "zOS"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__ibmxl__) && defined(__clang__)
+# define COMPILER_ID "XLClang"
+# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
+
+#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800
+# define COMPILER_ID "XL"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800
+# define COMPILER_ID "VisualAge"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__PGI)
+# define COMPILER_ID "PGI"
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
+
+#elif defined(_CRAYC)
+# define COMPILER_ID "Cray"
+# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
+#elif defined(__TI_COMPILER_VERSION__)
+# define COMPILER_ID "TI"
+ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
+#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version)
+# define COMPILER_ID "Fujitsu"
+
+#elif defined(__ghs__)
+# define COMPILER_ID "GHS"
+/* __GHS_VERSION_NUMBER = VVVVRP */
+# ifdef __GHS_VERSION_NUMBER
+# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+# endif
+
+#elif defined(__SCO_VERSION__)
+# define COMPILER_ID "SCO"
+
+#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+# define COMPILER_ID "ARMCC"
+#if __ARMCC_VERSION >= 1000000
+ /* __ARMCC_VERSION = VRRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#else
+ /* __ARMCC_VERSION = VRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#endif
+
+
+#elif defined(__clang__) && defined(__apple_build_version__)
+# define COMPILER_ID "AppleClang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
+#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+# define COMPILER_ID "ARMClang"
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
+# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
+#elif defined(__clang__)
+# define COMPILER_ID "Clang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+
+#elif defined(__GNUC__) || defined(__GNUG__)
+# define COMPILER_ID "GNU"
+# if defined(__GNUC__)
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# else
+# define COMPILER_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(_MSC_VER)
+# define COMPILER_ID "MSVC"
+ /* _MSC_VER = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+# if defined(_MSC_FULL_VER)
+# if _MSC_VER >= 1400
+ /* _MSC_FULL_VER = VVRRPPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+# else
+ /* _MSC_FULL_VER = VVRRPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+# endif
+# endif
+# if defined(_MSC_BUILD)
+# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+# endif
+
+#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
+# define COMPILER_ID "ADSP"
+#if defined(__VISUALDSPVERSION__)
+ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
+# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
+# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
+#endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# define COMPILER_ID "IAR"
+# if defined(__VER__) && defined(__ICCARM__)
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__))
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# endif
+
+
+/* These compilers are either not known or too old to define an
+ identification macro. Try to identify the platform and guess that
+ it is the native compiler. */
+#elif defined(__hpux) || defined(__hpua)
+# define COMPILER_ID "HP"
+
+#else /* unknown compiler */
+# define COMPILER_ID ""
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+#if defined(__CRAYXE) || defined(__CRAYXC)
+char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+#endif
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+/* Identify known platforms by name. */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+# define PLATFORM_ID "Linux"
+
+#elif defined(__CYGWIN__)
+# define PLATFORM_ID "Cygwin"
+
+#elif defined(__MINGW32__)
+# define PLATFORM_ID "MinGW"
+
+#elif defined(__APPLE__)
+# define PLATFORM_ID "Darwin"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define PLATFORM_ID "Windows"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD)
+# define PLATFORM_ID "FreeBSD"
+
+#elif defined(__NetBSD__) || defined(__NetBSD)
+# define PLATFORM_ID "NetBSD"
+
+#elif defined(__OpenBSD__) || defined(__OPENBSD)
+# define PLATFORM_ID "OpenBSD"
+
+#elif defined(__sun) || defined(sun)
+# define PLATFORM_ID "SunOS"
+
+#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+# define PLATFORM_ID "AIX"
+
+#elif defined(__hpux) || defined(__hpux__)
+# define PLATFORM_ID "HP-UX"
+
+#elif defined(__HAIKU__)
+# define PLATFORM_ID "Haiku"
+
+#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+# define PLATFORM_ID "BeOS"
+
+#elif defined(__QNX__) || defined(__QNXNTO__)
+# define PLATFORM_ID "QNX"
+
+#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+# define PLATFORM_ID "Tru64"
+
+#elif defined(__riscos) || defined(__riscos__)
+# define PLATFORM_ID "RISCos"
+
+#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+# define PLATFORM_ID "SINIX"
+
+#elif defined(__UNIX_SV__)
+# define PLATFORM_ID "UNIX_SV"
+
+#elif defined(__bsdos__)
+# define PLATFORM_ID "BSDOS"
+
+#elif defined(_MPRAS) || defined(MPRAS)
+# define PLATFORM_ID "MP-RAS"
+
+#elif defined(__osf) || defined(__osf__)
+# define PLATFORM_ID "OSF1"
+
+#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+# define PLATFORM_ID "SCO_SV"
+
+#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+# define PLATFORM_ID "ULTRIX"
+
+#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+# define PLATFORM_ID "Xenix"
+
+#elif defined(__WATCOMC__)
+# if defined(__LINUX__)
+# define PLATFORM_ID "Linux"
+
+# elif defined(__DOS__)
+# define PLATFORM_ID "DOS"
+
+# elif defined(__OS2__)
+# define PLATFORM_ID "OS2"
+
+# elif defined(__WINDOWS__)
+# define PLATFORM_ID "Windows3x"
+
+# else /* unknown platform */
+# define PLATFORM_ID
+# endif
+
+#elif defined(__INTEGRITY)
+# if defined(INT_178B)
+# define PLATFORM_ID "Integrity178"
+
+# else /* regular Integrity */
+# define PLATFORM_ID "Integrity"
+# endif
+
+#else /* unknown platform */
+# define PLATFORM_ID
+
+#endif
+
+/* For windows compilers MSVC and Intel we can determine
+ the architecture of the compiler being used. This is because
+ the compilers do not have flags that can change the architecture,
+ but rather depend on which compiler is being used
+*/
+#if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_M_IA64)
+# define ARCHITECTURE_ID "IA64"
+
+# elif defined(_M_X64) || defined(_M_AMD64)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# elif defined(_M_ARM64)
+# define ARCHITECTURE_ID "ARM64"
+
+# elif defined(_M_ARM)
+# if _M_ARM == 4
+# define ARCHITECTURE_ID "ARMV4I"
+# elif _M_ARM == 5
+# define ARCHITECTURE_ID "ARMV5I"
+# else
+# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+# endif
+
+# elif defined(_M_MIPS)
+# define ARCHITECTURE_ID "MIPS"
+
+# elif defined(_M_SH)
+# define ARCHITECTURE_ID "SHx"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__WATCOMC__)
+# if defined(_M_I86)
+# define ARCHITECTURE_ID "I86"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# if defined(__ICCARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__ICCRX__)
+# define ARCHITECTURE_ID "RX"
+
+# elif defined(__ICCRH850__)
+# define ARCHITECTURE_ID "RH850"
+
+# elif defined(__ICCRL78__)
+# define ARCHITECTURE_ID "RL78"
+
+# elif defined(__ICCRISCV__)
+# define ARCHITECTURE_ID "RISCV"
+
+# elif defined(__ICCAVR__)
+# define ARCHITECTURE_ID "AVR"
+
+# elif defined(__ICC430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__ICCV850__)
+# define ARCHITECTURE_ID "V850"
+
+# elif defined(__ICC8051__)
+# define ARCHITECTURE_ID "8051"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__ghs__)
+# if defined(__PPC64__)
+# define ARCHITECTURE_ID "PPC64"
+
+# elif defined(__ppc__)
+# define ARCHITECTURE_ID "PPC"
+
+# elif defined(__ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__x86_64__)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(__i386__)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+#else
+# define ARCHITECTURE_ID
+#endif
+
+/* Convert integer to decimal digit literals. */
+#define DEC(n) \
+ ('0' + (((n) / 10000000)%10)), \
+ ('0' + (((n) / 1000000)%10)), \
+ ('0' + (((n) / 100000)%10)), \
+ ('0' + (((n) / 10000)%10)), \
+ ('0' + (((n) / 1000)%10)), \
+ ('0' + (((n) / 100)%10)), \
+ ('0' + (((n) / 10)%10)), \
+ ('0' + ((n) % 10))
+
+/* Convert integer to hex digit literals. */
+#define HEX(n) \
+ ('0' + ((n)>>28 & 0xF)), \
+ ('0' + ((n)>>24 & 0xF)), \
+ ('0' + ((n)>>20 & 0xF)), \
+ ('0' + ((n)>>16 & 0xF)), \
+ ('0' + ((n)>>12 & 0xF)), \
+ ('0' + ((n)>>8 & 0xF)), \
+ ('0' + ((n)>>4 & 0xF)), \
+ ('0' + ((n) & 0xF))
+
+/* Construct a string literal encoding the version number components. */
+#ifdef COMPILER_VERSION_MAJOR
+char const info_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+ COMPILER_VERSION_MAJOR,
+# ifdef COMPILER_VERSION_MINOR
+ '.', COMPILER_VERSION_MINOR,
+# ifdef COMPILER_VERSION_PATCH
+ '.', COMPILER_VERSION_PATCH,
+# ifdef COMPILER_VERSION_TWEAK
+ '.', COMPILER_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct a string literal encoding the internal version number. */
+#ifdef COMPILER_VERSION_INTERNAL
+char const info_version_internal[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+ 'i','n','t','e','r','n','a','l','[',
+ COMPILER_VERSION_INTERNAL,']','\0'};
+#endif
+
+/* Construct a string literal encoding the version number components. */
+#ifdef SIMULATE_VERSION_MAJOR
+char const info_simulate_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+ SIMULATE_VERSION_MAJOR,
+# ifdef SIMULATE_VERSION_MINOR
+ '.', SIMULATE_VERSION_MINOR,
+# ifdef SIMULATE_VERSION_PATCH
+ '.', SIMULATE_VERSION_PATCH,
+# ifdef SIMULATE_VERSION_TWEAK
+ '.', SIMULATE_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
+
+
+
+#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L
+# if defined(__INTEL_CXX11_MODE__)
+# if defined(__cpp_aggregate_nsdmi)
+# define CXX_STD 201402L
+# else
+# define CXX_STD 201103L
+# endif
+# else
+# define CXX_STD 199711L
+# endif
+#elif defined(_MSC_VER) && defined(_MSVC_LANG)
+# define CXX_STD _MSVC_LANG
+#else
+# define CXX_STD __cplusplus
+#endif
+
+const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+#if CXX_STD > 201703L
+ "20"
+#elif CXX_STD >= 201703L
+ "17"
+#elif CXX_STD >= 201402L
+ "14"
+#elif CXX_STD >= 201103L
+ "11"
+#else
+ "98"
+#endif
+"]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+#if defined(__CRAYXE) || defined(__CRAYXC)
+ require += info_cray[argc];
+#endif
+ require += info_language_dialect_default[argc];
+ (void)argv;
+ return require;
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdCXX/a.out b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdCXX/a.out
new file mode 100755
index 000000000..34ec4a035
Binary files /dev/null and b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdCXX/a.out differ
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/CMakeOutput.log b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/CMakeOutput.log
new file mode 100644
index 000000000..50d59997f
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/CMakeOutput.log
@@ -0,0 +1,463 @@
+The system is: Linux - 5.10.16.3-microsoft-standard-WSL2 - x86_64
+Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded.
+Compiler: /usr/bin/cc
+Build flags:
+Id flags:
+
+The output was:
+0
+
+
+Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out"
+
+The C compiler identification is GNU, found in "/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdC/a.out"
+
+Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded.
+Compiler: /usr/bin/c++
+Build flags:
+Id flags:
+
+The output was:
+0
+
+
+Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out"
+
+The CXX compiler identification is GNU, found in "/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/3.16.3/CompilerIdCXX/a.out"
+
+Determining if the C compiler works passed with the following output:
+Change Dir: /home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/make cmTC_8695b/fast && /usr/bin/make -f CMakeFiles/cmTC_8695b.dir/build.make CMakeFiles/cmTC_8695b.dir/build
+make[1]: Entering directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_8695b.dir/testCCompiler.c.o
+/usr/bin/cc -o CMakeFiles/cmTC_8695b.dir/testCCompiler.c.o -c /home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp/testCCompiler.c
+Linking C executable cmTC_8695b
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_8695b.dir/link.txt --verbose=1
+/usr/bin/cc -rdynamic CMakeFiles/cmTC_8695b.dir/testCCompiler.c.o -o cmTC_8695b
+make[1]: Leaving directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp'
+
+
+
+Detecting C compiler ABI info compiled with the following output:
+Change Dir: /home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/make cmTC_8c7d9/fast && /usr/bin/make -f CMakeFiles/cmTC_8c7d9.dir/build.make CMakeFiles/cmTC_8c7d9.dir/build
+make[1]: Entering directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp'
+Building C object CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o
+/usr/bin/cc -v -o CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.16/Modules/CMakeCCompilerABI.c
+Using built-in specs.
+COLLECT_GCC=/usr/bin/cc
+OFFLOAD_TARGET_NAMES=nvptx-none:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu /usr/share/cmake-3.16/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccBr8JWY.s
+GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)
+ compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"
+#include "..." search starts here:
+#include <...> search starts here:
+ /usr/lib/gcc/x86_64-linux-gnu/9/include
+ /usr/local/include
+ /usr/include/x86_64-linux-gnu
+ /usr/include
+End of search list.
+GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)
+ compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+Compiler executable checksum: c0c95c0b4209efec1c1892d5ff24030b
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+ as -v --64 -o CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o /tmp/ccBr8JWY.s
+GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'
+Linking C executable cmTC_8c7d9
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_8c7d9.dir/link.txt --verbose=1
+/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o -o cmTC_8c7d9
+Using built-in specs.
+COLLECT_GCC=/usr/bin/cc
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
+OFFLOAD_TARGET_NAMES=nvptx-none:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_8c7d9' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/cc78SKyq.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_8c7d9 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_8c7d9' '-mtune=generic' '-march=x86-64'
+make[1]: Leaving directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp'
+
+
+
+Parsed C implicit include dir info from above output: rv=done
+ found start of include info
+ found start of implicit include info
+ add: [/usr/lib/gcc/x86_64-linux-gnu/9/include]
+ add: [/usr/local/include]
+ add: [/usr/include/x86_64-linux-gnu]
+ add: [/usr/include]
+ end of search list found
+ collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/9/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/9/include]
+ collapse include dir [/usr/local/include] ==> [/usr/local/include]
+ collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu]
+ collapse include dir [/usr/include] ==> [/usr/include]
+ implicit include dirs: [/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include]
+
+
+Parsed C implicit link information from above output:
+ link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)]
+ ignore line: [Change Dir: /home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp]
+ ignore line: []
+ ignore line: [Run Build Command(s):/usr/bin/make cmTC_8c7d9/fast && /usr/bin/make -f CMakeFiles/cmTC_8c7d9.dir/build.make CMakeFiles/cmTC_8c7d9.dir/build]
+ ignore line: [make[1]: Entering directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp']
+ ignore line: [Building C object CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o]
+ ignore line: [/usr/bin/cc -v -o CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.16/Modules/CMakeCCompilerABI.c]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/cc]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu]
+ ignore line: [Thread model: posix]
+ ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1) ]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64']
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu /usr/share/cmake-3.16/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccBr8JWY.s]
+ ignore line: [GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"]
+ ignore line: [#include "..." search starts here:]
+ ignore line: [#include <...> search starts here:]
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/include]
+ ignore line: [ /usr/local/include]
+ ignore line: [ /usr/include/x86_64-linux-gnu]
+ ignore line: [ /usr/include]
+ ignore line: [End of search list.]
+ ignore line: [GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [Compiler executable checksum: c0c95c0b4209efec1c1892d5ff24030b]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64']
+ ignore line: [ as -v --64 -o CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o /tmp/ccBr8JWY.s]
+ ignore line: [GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64']
+ ignore line: [Linking C executable cmTC_8c7d9]
+ ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_8c7d9.dir/link.txt --verbose=1]
+ ignore line: [/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o -o cmTC_8c7d9 ]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/cc]
+ ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu]
+ ignore line: [Thread model: posix]
+ ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1) ]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_8c7d9' '-mtune=generic' '-march=x86-64']
+ link line: [ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/cc78SKyq.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_8c7d9 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o]
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/collect2] ==> ignore
+ arg [-plugin] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so] ==> ignore
+ arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] ==> ignore
+ arg [-plugin-opt=-fresolution=/tmp/cc78SKyq.res] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [-plugin-opt=-pass-through=-lc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [--build-id] ==> ignore
+ arg [--eh-frame-hdr] ==> ignore
+ arg [-m] ==> ignore
+ arg [elf_x86_64] ==> ignore
+ arg [--hash-style=gnu] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-export-dynamic] ==> ignore
+ arg [-dynamic-linker] ==> ignore
+ arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
+ arg [-pie] ==> ignore
+ arg [-znow] ==> ignore
+ arg [-zrelro] ==> ignore
+ arg [-o] ==> ignore
+ arg [cmTC_8c7d9] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] ==> ignore
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/9] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib]
+ arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu]
+ arg [-L/lib/../lib] ==> dir [/lib/../lib]
+ arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu]
+ arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..]
+ arg [CMakeFiles/cmTC_8c7d9.dir/CMakeCCompilerABI.c.o] ==> ignore
+ arg [-lgcc] ==> lib [gcc]
+ arg [--push-state] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [--pop-state] ==> ignore
+ arg [-lc] ==> lib [c]
+ arg [-lgcc] ==> lib [gcc]
+ arg [--push-state] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [--pop-state] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> ignore
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9] ==> [/usr/lib/gcc/x86_64-linux-gnu/9]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> [/usr/lib]
+ collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu]
+ collapse library dir [/lib/../lib] ==> [/lib]
+ collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/../lib] ==> [/usr/lib]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> [/usr/lib]
+ implicit libs: [gcc;gcc_s;c;gcc;gcc_s]
+ implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib]
+ implicit fwks: []
+
+
+Determining if the CXX compiler works passed with the following output:
+Change Dir: /home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/make cmTC_9b51d/fast && /usr/bin/make -f CMakeFiles/cmTC_9b51d.dir/build.make CMakeFiles/cmTC_9b51d.dir/build
+make[1]: Entering directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp'
+Building CXX object CMakeFiles/cmTC_9b51d.dir/testCXXCompiler.cxx.o
+/usr/bin/c++ -o CMakeFiles/cmTC_9b51d.dir/testCXXCompiler.cxx.o -c /home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp/testCXXCompiler.cxx
+Linking CXX executable cmTC_9b51d
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_9b51d.dir/link.txt --verbose=1
+/usr/bin/c++ -rdynamic CMakeFiles/cmTC_9b51d.dir/testCXXCompiler.cxx.o -o cmTC_9b51d
+make[1]: Leaving directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp'
+
+
+
+Detecting CXX compiler ABI info compiled with the following output:
+Change Dir: /home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp
+
+Run Build Command(s):/usr/bin/make cmTC_b76ad/fast && /usr/bin/make -f CMakeFiles/cmTC_b76ad.dir/build.make CMakeFiles/cmTC_b76ad.dir/build
+make[1]: Entering directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp'
+Building CXX object CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o
+/usr/bin/c++ -v -o CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.16/Modules/CMakeCXXCompilerABI.cpp
+Using built-in specs.
+COLLECT_GCC=/usr/bin/c++
+OFFLOAD_TARGET_NAMES=nvptx-none:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/9/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.16/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccTEwRoV.s
+GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)
+ compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9"
+ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"
+ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"
+#include "..." search starts here:
+#include <...> search starts here:
+ /usr/include/c++/9
+ /usr/include/x86_64-linux-gnu/c++/9
+ /usr/include/c++/9/backward
+ /usr/lib/gcc/x86_64-linux-gnu/9/include
+ /usr/local/include
+ /usr/include/x86_64-linux-gnu
+ /usr/include
+End of search list.
+GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)
+ compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP
+
+GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
+Compiler executable checksum: 65fe925b83d3956b533de4aaba7dace0
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ as -v --64 -o CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccTEwRoV.s
+GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+Linking CXX executable cmTC_b76ad
+/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_b76ad.dir/link.txt --verbose=1
+/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_b76ad
+Using built-in specs.
+COLLECT_GCC=/usr/bin/c++
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
+OFFLOAD_TARGET_NAMES=nvptx-none:hsa
+OFFLOAD_TARGET_DEFAULT=1
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
+COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/
+LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_b76ad' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccnXxdBn.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_b76ad /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
+COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_b76ad' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
+make[1]: Leaving directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp'
+
+
+
+Parsed CXX implicit include dir info from above output: rv=done
+ found start of include info
+ found start of implicit include info
+ add: [/usr/include/c++/9]
+ add: [/usr/include/x86_64-linux-gnu/c++/9]
+ add: [/usr/include/c++/9/backward]
+ add: [/usr/lib/gcc/x86_64-linux-gnu/9/include]
+ add: [/usr/local/include]
+ add: [/usr/include/x86_64-linux-gnu]
+ add: [/usr/include]
+ end of search list found
+ collapse include dir [/usr/include/c++/9] ==> [/usr/include/c++/9]
+ collapse include dir [/usr/include/x86_64-linux-gnu/c++/9] ==> [/usr/include/x86_64-linux-gnu/c++/9]
+ collapse include dir [/usr/include/c++/9/backward] ==> [/usr/include/c++/9/backward]
+ collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/9/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/9/include]
+ collapse include dir [/usr/local/include] ==> [/usr/local/include]
+ collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu]
+ collapse include dir [/usr/include] ==> [/usr/include]
+ implicit include dirs: [/usr/include/c++/9;/usr/include/x86_64-linux-gnu/c++/9;/usr/include/c++/9/backward;/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include]
+
+
+Parsed CXX implicit link information from above output:
+ link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)]
+ ignore line: [Change Dir: /home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp]
+ ignore line: []
+ ignore line: [Run Build Command(s):/usr/bin/make cmTC_b76ad/fast && /usr/bin/make -f CMakeFiles/cmTC_b76ad.dir/build.make CMakeFiles/cmTC_b76ad.dir/build]
+ ignore line: [make[1]: Entering directory '/home/cococode/flipperzero-firmware/lib/esp-serial-flasher/CMakeFiles/CMakeTmp']
+ ignore line: [Building CXX object CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o]
+ ignore line: [/usr/bin/c++ -v -o CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.16/Modules/CMakeCXXCompilerABI.cpp]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/c++]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu]
+ ignore line: [Thread model: posix]
+ ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1) ]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /usr/share/cmake-3.16/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccTEwRoV.s]
+ ignore line: [GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9"]
+ ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"]
+ ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"]
+ ignore line: [#include "..." search starts here:]
+ ignore line: [#include <...> search starts here:]
+ ignore line: [ /usr/include/c++/9]
+ ignore line: [ /usr/include/x86_64-linux-gnu/c++/9]
+ ignore line: [ /usr/include/c++/9/backward]
+ ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/include]
+ ignore line: [ /usr/local/include]
+ ignore line: [ /usr/include/x86_64-linux-gnu]
+ ignore line: [ /usr/include]
+ ignore line: [End of search list.]
+ ignore line: [GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)]
+ ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP]
+ ignore line: []
+ ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072]
+ ignore line: [Compiler executable checksum: 65fe925b83d3956b533de4aaba7dace0]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ ignore line: [ as -v --64 -o CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccTEwRoV.s]
+ ignore line: [GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ ignore line: [Linking CXX executable cmTC_b76ad]
+ ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_b76ad.dir/link.txt --verbose=1]
+ ignore line: [/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_b76ad ]
+ ignore line: [Using built-in specs.]
+ ignore line: [COLLECT_GCC=/usr/bin/c++]
+ ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper]
+ ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa]
+ ignore line: [OFFLOAD_TARGET_DEFAULT=1]
+ ignore line: [Target: x86_64-linux-gnu]
+ ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu]
+ ignore line: [Thread model: posix]
+ ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1) ]
+ ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/]
+ ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/]
+ ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_b76ad' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
+ link line: [ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccnXxdBn.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_b76ad /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o]
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/collect2] ==> ignore
+ arg [-plugin] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so] ==> ignore
+ arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] ==> ignore
+ arg [-plugin-opt=-fresolution=/tmp/ccnXxdBn.res] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lc] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore
+ arg [-plugin-opt=-pass-through=-lgcc] ==> ignore
+ arg [--build-id] ==> ignore
+ arg [--eh-frame-hdr] ==> ignore
+ arg [-m] ==> ignore
+ arg [elf_x86_64] ==> ignore
+ arg [--hash-style=gnu] ==> ignore
+ arg [--as-needed] ==> ignore
+ arg [-export-dynamic] ==> ignore
+ arg [-dynamic-linker] ==> ignore
+ arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
+ arg [-pie] ==> ignore
+ arg [-znow] ==> ignore
+ arg [-zrelro] ==> ignore
+ arg [-o] ==> ignore
+ arg [cmTC_b76ad] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] ==> ignore
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/9] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib]
+ arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu]
+ arg [-L/lib/../lib] ==> dir [/lib/../lib]
+ arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu]
+ arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib]
+ arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..]
+ arg [CMakeFiles/cmTC_b76ad.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore
+ arg [-lstdc++] ==> lib [stdc++]
+ arg [-lm] ==> lib [m]
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [-lgcc] ==> lib [gcc]
+ arg [-lc] ==> lib [c]
+ arg [-lgcc_s] ==> lib [gcc_s]
+ arg [-lgcc] ==> lib [gcc]
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] ==> ignore
+ arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> ignore
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9] ==> [/usr/lib/gcc/x86_64-linux-gnu/9]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> [/usr/lib]
+ collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu]
+ collapse library dir [/lib/../lib] ==> [/lib]
+ collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
+ collapse library dir [/usr/lib/../lib] ==> [/usr/lib]
+ collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> [/usr/lib]
+ implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc]
+ implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib]
+ implicit fwks: []
+
+
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/cmake.check_cache b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/cmake.check_cache
new file mode 100644
index 000000000..3dccd7317
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeFiles/cmake.check_cache
@@ -0,0 +1 @@
+# This file is generated by cmake for dependency checking of the CMakeCache.txt file
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeLists.txt b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeLists.txt
new file mode 100644
index 000000000..7c83d2542
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/CMakeLists.txt
@@ -0,0 +1,119 @@
+cmake_minimum_required(VERSION 3.5)
+
+set(srcs
+ src/esp_targets.c
+ src/md5_hash.c
+ src/esp_loader.c
+ src/protocol_common.c
+)
+
+if (DEFINED ESP_PLATFORM)
+ if (${CONFIG_SERIAL_FLASHER_INTERFACE_UART})
+ list(APPEND srcs
+ src/protocol_uart.c
+ src/slip.c
+ port/esp32_port.c
+ )
+ elseif (${CONFIG_SERIAL_FLASHER_INTERFACE_SPI})
+ list(APPEND srcs
+ src/protocol_spi.c
+ port/esp32_spi_port.c
+ )
+ endif()
+ # Register component to esp-idf build system
+ if ("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.0")
+ # esp_timer component was introduced in v4.2
+ set(priv_requires driver)
+ if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.1")
+ list(APPEND priv_requires esp_timer)
+ endif()
+
+ idf_component_register(SRCS ${srcs}
+ INCLUDE_DIRS include port
+ PRIV_INCLUDE_DIRS private_include
+ PRIV_REQUIRES ${priv_requires})
+
+ set(target ${COMPONENT_LIB})
+ component_compile_options(-Wstrict-prototypes)
+ else()
+ # Remove when dropping support for IDF 3.3
+ set(COMPONENT_SRCS ${srcs})
+ set(COMPONENT_ADD_INCLUDEDIRS include port)
+ set(COMPONENT_PRIV_INCLUDEDIRS private_include)
+ register_component()
+ set(target ${COMPONENT_TARGET})
+ endif()
+
+else()
+ if (NOT DEFINED SERIAL_FLASHER_INTERFACE_UART AND NOT DEFINED SERIAL_FLASHER_INTERFACE_SPI)
+ set(SERIAL_FLASHER_INTERFACE_UART true)
+ endif()
+
+ if (DEFINED SERIAL_FLASHER_INTERFACE_UART)
+ list(APPEND srcs
+ src/protocol_uart.c
+ src/slip.c
+ )
+ elseif (DEFINED SERIAL_FLASHER_INTERFACE_SPI)
+ list(APPEND srcs src/protocol_spi.c)
+ endif()
+
+ # Create traditional CMake target
+ add_library(flasher ${srcs})
+
+ target_include_directories(flasher PUBLIC include port PRIVATE private_include)
+
+ if(PORT STREQUAL "STM32")
+ target_link_libraries(flasher PUBLIC stm_cube)
+ target_sources(flasher PRIVATE port/stm32_port.c)
+ elseif(PORT STREQUAL "RASPBERRY_PI")
+ find_library(pigpio_LIB pigpio)
+ target_link_libraries(flasher PUBLIC ${pigpio_LIB})
+ target_sources(flasher PRIVATE port/raspberry_port.c)
+ else()
+ message(FATAL_ERROR "Selected port is not supported")
+ endif()
+
+ set(target flasher)
+
+endif()
+
+if (DEFINED SERIAL_FLASHER_INTERFACE_UART OR CONFIG_SERIAL_FLASHER_INTERFACE_UART STREQUAL "y")
+ target_compile_definitions(${target}
+ PUBLIC
+ SERIAL_FLASHER_INTERFACE_UART
+ )
+ if (DEFINED MD5_ENABLED OR CONFIG_SERIAL_FLASHER_MD5_ENABLED)
+ target_compile_definitions(${target} PUBLIC MD5_ENABLED=1)
+ endif()
+elseif (DEFINED SERIAL_FLASHER_INTERFACE_SPI OR CONFIG_SERIAL_FLASHER_INTERFACE_SPI STREQUAL "y")
+ target_compile_definitions(${target}
+ PUBLIC
+ SERIAL_FLASHER_INTERFACE_SPI
+ )
+endif()
+
+if(DEFINED SERIAL_FLASHER_DEBUG_TRACE OR CONFIG_SERIAL_FLASHER_DEBUG_TRACE)
+ target_compile_definitions(${target} PUBLIC SERIAL_FLASHER_DEBUG_TRACE)
+endif()
+
+if(DEFINED CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS AND DEFINED CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS)
+ target_compile_definitions(${target}
+ PUBLIC
+ SERIAL_FLASHER_RESET_HOLD_TIME_MS=${CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS}
+ SERIAL_FLASHER_BOOT_HOLD_TIME_MS=${CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS}
+ )
+else()
+ if(NOT DEFINED SERIAL_FLASHER_RESET_HOLD_TIME_MS)
+ target_compile_definitions(${target}
+ PUBLIC
+ SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
+ )
+ endif()
+ if(NOT DEFINED SERIAL_FLASHER_BOOT_HOLD_TIME_MS)
+ target_compile_definitions(${target}
+ PUBLIC
+ SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
+ )
+ endif()
+endif()
\ No newline at end of file
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/Kconfig b/applications/external/esp_flasher/lib/esp-serial-flasher/Kconfig
new file mode 100644
index 000000000..41d776f11
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/Kconfig
@@ -0,0 +1,34 @@
+menu "ESP serial flasher"
+ config SERIAL_FLASHER_MD5_ENABLED
+ bool "Enable MD5 check"
+ default y
+ help
+ Select this option to enable MD5 hashsum check after flashing.
+
+ choice SERIAL_FLASHER_INTERFACE
+ prompt "Hardware interface to use for firmware download"
+ default SERIAL_FLASHER_INTERFACE_UART
+ help
+ esp-serial-flasher can work with UART and SPI interfaces.
+
+ config SERIAL_FLASHER_INTERFACE_UART
+ bool "UART"
+
+ config SERIAL_FLASHER_INTERFACE_SPI
+ bool "SPI (Only supports downloading to RAM, experimental)"
+
+ endchoice
+
+ config SERIAL_FLASHER_RESET_HOLD_TIME_MS
+ int "Time for which the reset pin is asserted when doing a hard reset"
+ default 100
+
+ config SERIAL_FLASHER_BOOT_HOLD_TIME_MS
+ int "Time for which the boot pin is asserted when doing a hard reset"
+ default 50
+
+ config SERIAL_FLASHER_DEBUG_TRACE
+ bool "Enable debug tracing output (only transfer data tracing is supported at the time)"
+ default n
+
+endmenu
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/idf_component.yml b/applications/external/esp_flasher/lib/esp-serial-flasher/idf_component.yml
new file mode 100644
index 000000000..e2166924c
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/idf_component.yml
@@ -0,0 +1,3 @@
+version: "0.2.0"
+description: Serial flasher component provides portable library for flashing or loading ram loadble app to Espressif SoCs from other host microcontroller
+url: https://github.com/espressif/esp-serial-flasher
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/include/esp_loader.h b/applications/external/esp_flasher/lib/esp-serial-flasher/include/esp_loader.h
new file mode 100644
index 000000000..43f4fb9d9
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/include/esp_loader.h
@@ -0,0 +1,313 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Used for backwards compatibility with the previous API */
+#define esp_loader_change_baudrate esp_loader_change_transmission_rate
+
+/**
+ * Macro which can be used to check the error code,
+ * and return in case the code is not ESP_LOADER_SUCCESS.
+ */
+#define RETURN_ON_ERROR(x) do { \
+ esp_loader_error_t _err_ = (x); \
+ if (_err_ != ESP_LOADER_SUCCESS) { \
+ return _err_; \
+ } \
+} while(0)
+
+/**
+ * @brief Error codes
+ */
+typedef enum {
+ ESP_LOADER_SUCCESS, /*!< Success */
+ ESP_LOADER_ERROR_FAIL, /*!< Unspecified error */
+ ESP_LOADER_ERROR_TIMEOUT, /*!< Timeout elapsed */
+ ESP_LOADER_ERROR_IMAGE_SIZE, /*!< Image size to flash is larger than flash size */
+ ESP_LOADER_ERROR_INVALID_MD5, /*!< Computed and received MD5 does not match */
+ ESP_LOADER_ERROR_INVALID_PARAM, /*!< Invalid parameter passed to function */
+ ESP_LOADER_ERROR_INVALID_TARGET, /*!< Connected target is invalid */
+ ESP_LOADER_ERROR_UNSUPPORTED_CHIP, /*!< Attached chip is not supported */
+ ESP_LOADER_ERROR_UNSUPPORTED_FUNC, /*!< Function is not supported on attached target */
+ ESP_LOADER_ERROR_INVALID_RESPONSE /*!< Internal error */
+} esp_loader_error_t;
+
+/**
+ * @brief Supported targets
+ */
+typedef enum {
+ ESP8266_CHIP = 0,
+ ESP32_CHIP = 1,
+ ESP32S2_CHIP = 2,
+ ESP32C3_CHIP = 3,
+ ESP32S3_CHIP = 4,
+ ESP32C2_CHIP = 5,
+ ESP32H4_CHIP = 6,
+ ESP32H2_CHIP = 7,
+ ESP_MAX_CHIP = 8,
+ ESP_UNKNOWN_CHIP = 8
+} target_chip_t;
+
+/**
+ * @brief Application binary header
+ */
+typedef struct {
+ uint8_t magic;
+ uint8_t segments;
+ uint8_t flash_mode;
+ uint8_t flash_size_freq;
+ uint32_t entrypoint;
+} esp_loader_bin_header_t;
+
+/**
+ * @brief Segment binary header
+ */
+typedef struct {
+ uint32_t addr;
+ uint32_t size;
+ uint8_t *data;
+} esp_loader_bin_segment_t;
+
+/**
+ * @brief SPI pin configuration arguments
+ */
+typedef union {
+ struct {
+ uint32_t pin_clk: 6;
+ uint32_t pin_q: 6;
+ uint32_t pin_d: 6;
+ uint32_t pin_cs: 6;
+ uint32_t pin_hd: 6;
+ uint32_t zero: 2;
+ };
+ uint32_t val;
+} esp_loader_spi_config_t;
+
+/**
+ * @brief Connection arguments
+ */
+typedef struct {
+ uint32_t sync_timeout; /*!< Maximum time to wait for response from serial interface. */
+ int32_t trials; /*!< Number of trials to connect to target. If greater than 1,
+ 100 millisecond delay is inserted after each try. */
+} esp_loader_connect_args_t;
+
+#define ESP_LOADER_CONNECT_DEFAULT() { \
+ .sync_timeout = 100, \
+ .trials = 10, \
+}
+
+/**
+ * @brief Connects to the target
+ *
+ * @param connect_args[in] Timing parameters to be used for connecting to target.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ */
+esp_loader_error_t esp_loader_connect(esp_loader_connect_args_t *connect_args);
+
+/**
+ * @brief Returns attached target chip.
+ *
+ * @warning This function can only be called after connection with target
+ * has been successfully established by calling esp_loader_connect().
+ *
+ * @return One of target_chip_t
+ */
+target_chip_t esp_loader_get_target(void);
+
+
+#ifdef SERIAL_FLASHER_INTERFACE_UART
+/**
+ * @brief Initiates flash operation
+ *
+ * @param offset[in] Address from which flash operation will be performed.
+ * @param image_size[in] Size of the whole binary to be loaded into flash.
+ * @param block_size[in] Size of buffer used in subsequent calls to esp_loader_flash_write.
+ *
+ * @note image_size is size of the whole image, whereas, block_size is chunk of data sent
+ * to the target, each time esp_loader_flash_write function is called.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ */
+esp_loader_error_t esp_loader_flash_start(uint32_t offset, uint32_t image_size, uint32_t block_size);
+
+/**
+ * @brief Writes supplied data to target's flash memory.
+ *
+ * @param payload[in] Data to be flashed into target's memory.
+ * @param size[in] Size of payload in bytes.
+ *
+ * @note size must not be greater that block_size supplied to previously called
+ * esp_loader_flash_start function. If size is less than block_size,
+ * remaining bytes of payload buffer will be padded with 0xff.
+ * Therefore, size of payload buffer has to be equal or greater than block_size.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ */
+esp_loader_error_t esp_loader_flash_write(void *payload, uint32_t size);
+
+/**
+ * @brief Ends flash operation.
+ *
+ * @param reboot[in] reboot the target if true.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ */
+esp_loader_error_t esp_loader_flash_finish(bool reboot);
+#endif /* SERIAL_FLASHER_INTERFACE_UART */
+
+
+/**
+ * @brief Initiates mem operation, initiates loading for program into target RAM
+ *
+ * @param offset[in] Address from which mem operation will be performed.
+ * @param size[in] Size of the whole binary to be loaded into mem.
+ * @param block_size[in] Size of buffer used in subsequent calls to esp_loader_mem_write.
+ *
+ * @note image_size is size of the whole image, whereas, block_size is chunk of data sent
+ * to the target, each time esp_mem_flash_write function is called.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ */
+esp_loader_error_t esp_loader_mem_start(uint32_t offset, uint32_t size, uint32_t block_size);
+
+
+/**
+ * @brief Writes supplied data to target's mem memory.
+ *
+ * @param payload[in] Data to be loaded into target's memory.
+ * @param size[in] Size of data in bytes.
+ *
+ * @note size must not be greater that block_size supplied to previously called
+ * esp_loader_mem_start function.
+ * Therefore, size of data buffer has to be equal or greater than block_size.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ */
+esp_loader_error_t esp_loader_mem_write(const void *payload, uint32_t size);
+
+
+/**
+ * @brief Ends mem operation, finish loading for program into target RAM
+ * and send the entrypoint of ram_loadable app
+ *
+ * @param entrypoint[in] entrypoint of ram program.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ */
+esp_loader_error_t esp_loader_mem_finish(uint32_t entrypoint);
+
+
+/**
+ * @brief Writes register.
+ *
+ * @param address[in] Address of register.
+ * @param reg_value[in] New register value.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ */
+esp_loader_error_t esp_loader_write_register(uint32_t address, uint32_t reg_value);
+
+/**
+ * @brief Reads register.
+ *
+ * @param address[in] Address of register.
+ * @param reg_value[out] Register value.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ */
+esp_loader_error_t esp_loader_read_register(uint32_t address, uint32_t *reg_value);
+
+/**
+ * @brief Change baud rate.
+ *
+ * @note Baud rate has to be also adjusted accordingly on host MCU, as
+ * target's baud rate is changed upon return from this function.
+ *
+ * @param transmission_rate[in] new baud rate to be set.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ * - ESP_LOADER_ERROR_UNSUPPORTED_FUNC Unsupported on the target
+ */
+esp_loader_error_t esp_loader_change_transmission_rate(uint32_t transmission_rate);
+
+/**
+ * @brief Verify target's flash integrity by checking MD5.
+ * MD5 checksum is computed from data pushed to target's memory by calling
+ * esp_loader_flash_write() function and compared against target's MD5.
+ * Target computes checksum based on offset and image_size passed to
+ * esp_loader_flash_start() function.
+ *
+ * @note This function is only available if MD5_ENABLED is set.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_INVALID_MD5 MD5 does not match
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout
+ * - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
+ * - ESP_LOADER_ERROR_UNSUPPORTED_FUNC Unsupported on the target
+ */
+#if MD5_ENABLED
+esp_loader_error_t esp_loader_flash_verify(void);
+#endif
+/**
+ * @brief Toggles reset pin.
+ */
+void esp_loader_reset_target(void);
+
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/include/esp_loader_io.h b/applications/external/esp_flasher/lib/esp-serial-flasher/include/esp_loader_io.h
new file mode 100644
index 000000000..2ff99b4f9
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/include/esp_loader_io.h
@@ -0,0 +1,112 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+ #pragma once
+
+#include
+#include "esp_loader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Changes the transmission rate of the used peripheral.
+ */
+esp_loader_error_t loader_port_change_transmission_rate(uint32_t transmission_rate);
+
+/**
+ * @brief Writes data over the io interface.
+ *
+ * @param data[in] Buffer with data to be written.
+ * @param size[in] Size of data in bytes.
+ * @param timeout[in] Timeout in milliseconds.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout elapsed
+ */
+esp_loader_error_t loader_port_write(const uint8_t *data, uint16_t size, uint32_t timeout);
+
+/**
+ * @brief Reads data from the io interface.
+ *
+ * @param data[out] Buffer into which received data will be written.
+ * @param size[in] Number of bytes to read.
+ * @param timeout[in] Timeout in milliseconds.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_TIMEOUT Timeout elapsed
+ */
+esp_loader_error_t loader_port_read(uint8_t *data, uint16_t size, uint32_t timeout);
+
+/**
+ * @brief Delay in milliseconds.
+ *
+ * @param ms[in] Number of milliseconds.
+ *
+ */
+void loader_port_delay_ms(uint32_t ms);
+
+/**
+ * @brief Starts timeout timer.
+ *
+ * @param ms[in] Number of milliseconds.
+ *
+ */
+void loader_port_start_timer(uint32_t ms);
+
+/**
+ * @brief Returns remaining time since timer was started by calling esp_loader_start_timer.
+ * 0 if timer has elapsed.
+ *
+ * @return Number of milliseconds.
+ *
+ */
+uint32_t loader_port_remaining_time(void);
+
+/**
+ * @brief Asserts bootstrap pins to enter boot mode and toggles reset pin.
+ *
+ * @note Reset pin should stay asserted for at least 20 milliseconds.
+ */
+void loader_port_enter_bootloader(void);
+
+/**
+ * @brief Toggles reset pin.
+ *
+ * @note Reset pin should stay asserted for at least 20 milliseconds.
+ */
+void loader_port_reset_target(void);
+
+/**
+ * @brief Function can be defined by user to print debug message.
+ *
+ * @note Empty weak function is used, otherwise.
+ *
+ */
+void loader_port_debug_print(const char *str);
+
+#ifdef SERIAL_FLASHER_INTERFACE_SPI
+/**
+ * @brief Sets the chip select to a defined level
+ */
+void loader_port_spi_set_cs(uint32_t level);
+#endif /* SERIAL_FLASHER_INTERFACE_SPI */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/include/serial_io.h b/applications/external/esp_flasher/lib/esp-serial-flasher/include/serial_io.h
new file mode 100644
index 000000000..e34939300
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/include/serial_io.h
@@ -0,0 +1,24 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+#warning Please replace serial_io.h with esp_loader_io.h and change the function names \
+ to match the new API
+
+/* Defines used to avoid breaking existing ports */
+#define loader_port_change_baudrate loader_port_change_transmission_rate
+#define loader_port_serial_write loader_port_write
+#define loader_port_serial_read loader_port_read
+
+#include "esp_loader_io.h"
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_port.c b/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_port.c
new file mode 100644
index 000000000..a6c8687c6
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_port.c
@@ -0,0 +1,181 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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 "esp32_port.h"
+#include "driver/uart.h"
+#include "driver/gpio.h"
+#include "esp_timer.h"
+#include "esp_log.h"
+#include "esp_idf_version.h"
+#include
+
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+static void transfer_debug_print(const uint8_t *data, uint16_t size, bool write)
+{
+ static bool write_prev = false;
+
+ if (write_prev != write) {
+ write_prev = write;
+ printf("\n--- %s ---\n", write ? "WRITE" : "READ");
+ }
+
+ for (uint32_t i = 0; i < size; i++) {
+ printf("%02x ", data[i]);
+ }
+}
+#endif
+
+static int64_t s_time_end;
+static int32_t s_uart_port;
+static int32_t s_reset_trigger_pin;
+static int32_t s_gpio0_trigger_pin;
+
+esp_loader_error_t loader_port_esp32_init(const loader_esp32_config_t *config)
+{
+ s_uart_port = config->uart_port;
+ s_reset_trigger_pin = config->reset_trigger_pin;
+ s_gpio0_trigger_pin = config->gpio0_trigger_pin;
+
+ // Initialize UART
+ uart_config_t uart_config = {
+ .baud_rate = config->baud_rate,
+ .data_bits = UART_DATA_8_BITS,
+ .parity = UART_PARITY_DISABLE,
+ .stop_bits = UART_STOP_BITS_1,
+ .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
+ .source_clk = UART_SCLK_DEFAULT,
+#endif
+ };
+
+ int rx_buffer_size = config->rx_buffer_size ? config->rx_buffer_size : 400;
+ int tx_buffer_size = config->tx_buffer_size ? config->tx_buffer_size : 400;
+ QueueHandle_t *uart_queue = config->uart_queue ? config->uart_queue : NULL;
+ int queue_size = config->queue_size ? config->queue_size : 0;
+
+ if ( uart_param_config(s_uart_port, &uart_config) != ESP_OK ) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+ if ( uart_set_pin(s_uart_port, config->uart_tx_pin, config->uart_rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE) != ESP_OK ) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+ if ( uart_driver_install(s_uart_port, rx_buffer_size, tx_buffer_size, queue_size, uart_queue, 0) != ESP_OK ) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ // Initialize boot pin selection pins
+ gpio_reset_pin(s_reset_trigger_pin);
+ gpio_set_pull_mode(s_reset_trigger_pin, GPIO_PULLUP_ONLY);
+ gpio_set_direction(s_reset_trigger_pin, GPIO_MODE_OUTPUT);
+
+ gpio_reset_pin(s_gpio0_trigger_pin);
+ gpio_set_pull_mode(s_gpio0_trigger_pin, GPIO_PULLUP_ONLY);
+ gpio_set_direction(s_gpio0_trigger_pin, GPIO_MODE_OUTPUT);
+
+ return ESP_LOADER_SUCCESS;
+}
+
+void loader_port_esp32_deinit(void)
+{
+ uart_driver_delete(s_uart_port);
+}
+
+
+esp_loader_error_t loader_port_write(const uint8_t *data, uint16_t size, uint32_t timeout)
+{
+ uart_write_bytes(s_uart_port, (const char *)data, size);
+ esp_err_t err = uart_wait_tx_done(s_uart_port, pdMS_TO_TICKS(timeout));
+
+ if (err == ESP_OK) {
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, size, true);
+#endif
+ return ESP_LOADER_SUCCESS;
+ } else if (err == ESP_ERR_TIMEOUT) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ } else {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+}
+
+
+esp_loader_error_t loader_port_read(uint8_t *data, uint16_t size, uint32_t timeout)
+{
+ int read = uart_read_bytes(s_uart_port, data, size, pdMS_TO_TICKS(timeout));
+
+ if (read < 0) {
+ return ESP_LOADER_ERROR_FAIL;
+ } else if (read < size) {
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, read, false);
+#endif
+ return ESP_LOADER_ERROR_TIMEOUT;
+ } else {
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, read, false);
+#endif
+ return ESP_LOADER_SUCCESS;
+ }
+}
+
+
+// Set GPIO0 LOW, then
+// assert reset pin for 50 milliseconds.
+void loader_port_enter_bootloader(void)
+{
+ gpio_set_level(s_gpio0_trigger_pin, 0);
+ loader_port_reset_target();
+ loader_port_delay_ms(SERIAL_FLASHER_BOOT_HOLD_TIME_MS);
+ gpio_set_level(s_gpio0_trigger_pin, 1);
+}
+
+
+void loader_port_reset_target(void)
+{
+ gpio_set_level(s_reset_trigger_pin, 0);
+ loader_port_delay_ms(SERIAL_FLASHER_RESET_HOLD_TIME_MS);
+ gpio_set_level(s_reset_trigger_pin, 1);
+}
+
+
+void loader_port_delay_ms(uint32_t ms)
+{
+ usleep(ms * 1000);
+}
+
+
+void loader_port_start_timer(uint32_t ms)
+{
+ s_time_end = esp_timer_get_time() + ms * 1000;
+}
+
+
+uint32_t loader_port_remaining_time(void)
+{
+ int64_t remaining = (s_time_end - esp_timer_get_time()) / 1000;
+ return (remaining > 0) ? (uint32_t)remaining : 0;
+}
+
+
+void loader_port_debug_print(const char *str)
+{
+ printf("DEBUG: %s\n", str);
+}
+
+esp_loader_error_t loader_port_change_transmission_rate(uint32_t baudrate)
+{
+ esp_err_t err = uart_set_baudrate(s_uart_port, baudrate);
+ return (err == ESP_OK) ? ESP_LOADER_SUCCESS : ESP_LOADER_ERROR_FAIL;
+}
\ No newline at end of file
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_port.h b/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_port.h
new file mode 100644
index 000000000..c098762d2
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_port.h
@@ -0,0 +1,59 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+ #pragma once
+
+#include "esp_loader_io.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+ uint32_t baud_rate; /*!< Initial baud rate, can be changed later */
+ uint32_t uart_port; /*!< UART port */
+ uint32_t uart_rx_pin; /*!< This pin will be configured as UART Rx pin */
+ uint32_t uart_tx_pin; /*!< This pin will be configured as UART Tx pin */
+ uint32_t reset_trigger_pin; /*!< This pin will be used to reset target chip */
+ uint32_t gpio0_trigger_pin; /*!< This pin will be used to toggle set IO0 of target chip */
+ uint32_t rx_buffer_size; /*!< Set to zero for default RX buffer size */
+ uint32_t tx_buffer_size; /*!< Set to zero for default TX buffer size */
+ uint32_t queue_size; /*!< Set to zero for default UART queue size */
+ QueueHandle_t *uart_queue; /*!< Set to NULL, if UART queue handle is not
+ necessary. Otherwise, it will be assigned here */
+} loader_esp32_config_t;
+
+/**
+ * @brief Initializes serial interface.
+ *
+ * @param baud_rate[in] Communication speed.
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_FAIL Initialization failure
+ */
+esp_loader_error_t loader_port_esp32_init(const loader_esp32_config_t *config);
+
+/**
+ * @brief Deinitialize serial interface.
+ */
+void loader_port_esp32_deinit(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_spi_port.c b/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_spi_port.c
new file mode 100644
index 000000000..55e8f3e57
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_spi_port.c
@@ -0,0 +1,298 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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 "esp32_spi_port.h"
+#include "esp_log.h"
+#include "driver/gpio.h"
+#include "esp_timer.h"
+#include "esp_log.h"
+#include "esp_idf_version.h"
+#include
+
+// #define SERIAL_DEBUG_ENABLE
+
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0)
+#define DMA_CHAN SPI_DMA_CH_AUTO
+#else
+#define DMA_CHAN 1
+#endif
+
+#define WORD_ALIGNED(ptr) ((size_t)ptr % sizeof(size_t) == 0)
+
+#ifdef SERIAL_DEBUG_ENABLE
+
+static void dec_to_hex_str(const uint8_t dec, uint8_t hex_str[3])
+{
+ static const uint8_t dec_to_hex[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ hex_str[0] = dec_to_hex[dec >> 4];
+ hex_str[1] = dec_to_hex[dec & 0xF];
+ hex_str[2] = '\0';
+}
+
+static void serial_debug_print(const uint8_t *data, uint16_t size, bool write)
+{
+ static bool write_prev = false;
+ uint8_t hex_str[3];
+
+ if(write_prev != write) {
+ write_prev = write;
+ printf("\n--- %s ---\n", write ? "WRITE" : "READ");
+ }
+
+ for(uint32_t i = 0; i < size; i++) {
+ dec_to_hex_str(data[i], hex_str);
+ printf("%s ", hex_str);
+ }
+}
+
+#else
+static void serial_debug_print(const uint8_t *data, uint16_t size, bool write) { }
+#endif
+
+static spi_host_device_t s_spi_bus;
+static spi_bus_config_t s_spi_config;
+static spi_device_handle_t s_device_h;
+static spi_device_interface_config_t s_device_config;
+static int64_t s_time_end;
+static uint32_t s_reset_trigger_pin;
+static uint32_t s_strap_bit0_pin;
+static uint32_t s_strap_bit1_pin;
+static uint32_t s_strap_bit2_pin;
+static uint32_t s_strap_bit3_pin;
+static uint32_t s_spi_cs_pin;
+
+esp_loader_error_t loader_port_esp32_spi_init(const loader_esp32_spi_config_t *config)
+{
+ /* Initialize the global static variables*/
+ s_spi_bus = config->spi_bus;
+ s_reset_trigger_pin = config->reset_trigger_pin;
+ s_strap_bit0_pin = config->strap_bit0_pin;
+ s_strap_bit1_pin = config->strap_bit1_pin;
+ s_strap_bit2_pin = config->strap_bit2_pin;
+ s_strap_bit3_pin = config->strap_bit3_pin;
+ s_spi_cs_pin = config->spi_cs_pin;
+
+ /* Configure and initialize the SPI bus*/
+ s_spi_config.mosi_io_num = config->spi_mosi_pin;
+ s_spi_config.miso_io_num = config->spi_miso_pin;
+ s_spi_config.sclk_io_num = config->spi_clk_pin;
+ s_spi_config.quadwp_io_num = config->spi_quadwp_pin;
+ s_spi_config.quadhd_io_num = config->spi_quadhd_pin;
+ s_spi_config.max_transfer_sz = 4096 * 4;
+
+ if (spi_bus_initialize(s_spi_bus, &s_spi_config, DMA_CHAN) != ESP_OK) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ /* Configure and add the device */
+ s_device_config.clock_speed_hz = config->frequency;
+ s_device_config.spics_io_num = -1; /* We're using the chip select pin as GPIO as we need to
+ chain multiple transactions with CS pulled down */
+ s_device_config.flags = SPI_DEVICE_HALFDUPLEX;
+ s_device_config.queue_size = 16;
+
+ if (spi_bus_add_device(s_spi_bus, &s_device_config, &s_device_h) != ESP_OK) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ /* Initialize the pins except for the strapping ones */
+ gpio_reset_pin(s_reset_trigger_pin);
+ gpio_set_pull_mode(s_reset_trigger_pin, GPIO_PULLUP_ONLY);
+ gpio_set_direction(s_reset_trigger_pin, GPIO_MODE_OUTPUT);
+ gpio_set_level(s_reset_trigger_pin, 1);
+
+ gpio_reset_pin(s_spi_cs_pin);
+ gpio_set_pull_mode(s_spi_cs_pin, GPIO_PULLUP_ONLY);
+ gpio_set_direction(s_spi_cs_pin, GPIO_MODE_OUTPUT);
+ gpio_set_level(s_spi_cs_pin, 1);
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+void loader_port_esp32_spi_deinit(void)
+{
+ gpio_reset_pin(s_reset_trigger_pin);
+ gpio_reset_pin(s_spi_cs_pin);
+ spi_bus_remove_device(s_device_h);
+ spi_bus_free(s_spi_bus);
+}
+
+
+void loader_port_spi_set_cs(const uint32_t level) {
+ gpio_set_level(s_spi_cs_pin, level);
+}
+
+
+esp_loader_error_t loader_port_write(const uint8_t *data, const uint16_t size, const uint32_t timeout)
+{
+ /* Due to the fact that the SPI driver uses DMA for larger transfers,
+ and the DMA requirements, the buffer must be word aligned */
+ if (data == NULL || !WORD_ALIGNED(data)) {
+ return ESP_LOADER_ERROR_INVALID_PARAM;
+ }
+
+ serial_debug_print(data, size, true);
+
+ spi_transaction_t transaction = {
+ .tx_buffer = data,
+ .rx_buffer = NULL,
+ .length = size * 8U,
+ .rxlength = 0,
+ };
+
+ esp_err_t err = spi_device_transmit(s_device_h, &transaction);
+
+ if (err == ESP_OK) {
+ serial_debug_print(data, size, false);
+ return ESP_LOADER_SUCCESS;
+ } else if (err == ESP_ERR_TIMEOUT) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ } else {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+}
+
+
+esp_loader_error_t loader_port_read(uint8_t *data, const uint16_t size, const uint32_t timeout)
+{
+ /* Due to the fact that the SPI driver uses DMA for larger transfers,
+ and the DMA requirements, the buffer must be word aligned */
+ if (data == NULL || !WORD_ALIGNED(data)) {
+ return ESP_LOADER_ERROR_INVALID_PARAM;
+ }
+
+ serial_debug_print(data, size, true);
+
+ spi_transaction_t transaction = {
+ .tx_buffer = NULL,
+ .rx_buffer = data,
+ .rxlength = size * 8,
+ };
+
+ esp_err_t err = spi_device_transmit(s_device_h, &transaction);
+
+ if (err == ESP_OK) {
+ serial_debug_print(data, size, false);
+ return ESP_LOADER_SUCCESS;
+ } else if (err == ESP_ERR_TIMEOUT) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ } else {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+}
+
+
+void loader_port_enter_bootloader(void)
+{
+ /*
+ We have to initialize the GPIO pins for the target strapping pins here,
+ as they may overlap with target SPI pins.
+ For instance in the case of ESP32C3 MISO and strapping bit 0 pins overlap.
+ */
+ spi_bus_remove_device(s_device_h);
+ spi_bus_free(s_spi_bus);
+
+ gpio_reset_pin(s_strap_bit0_pin);
+ gpio_set_pull_mode(s_strap_bit0_pin, GPIO_PULLUP_ONLY);
+ gpio_set_direction(s_strap_bit0_pin, GPIO_MODE_OUTPUT);
+
+ gpio_reset_pin(s_strap_bit1_pin);
+ gpio_set_pull_mode(s_strap_bit1_pin, GPIO_PULLUP_ONLY);
+ gpio_set_direction(s_strap_bit1_pin, GPIO_MODE_OUTPUT);
+
+ gpio_reset_pin(s_strap_bit2_pin);
+ gpio_set_pull_mode(s_strap_bit2_pin, GPIO_PULLUP_ONLY);
+ gpio_set_direction(s_strap_bit2_pin, GPIO_MODE_OUTPUT);
+
+ gpio_reset_pin(s_strap_bit3_pin);
+ gpio_set_pull_mode(s_strap_bit3_pin, GPIO_PULLUP_ONLY);
+ gpio_set_direction(s_strap_bit3_pin, GPIO_MODE_OUTPUT);
+
+ /* Set the strapping pins and perform the reset sequence */
+ gpio_set_level(s_strap_bit0_pin, 1);
+ gpio_set_level(s_strap_bit1_pin, 0);
+ gpio_set_level(s_strap_bit2_pin, 0);
+ gpio_set_level(s_strap_bit3_pin, 0);
+ loader_port_reset_target();
+ loader_port_delay_ms(SERIAL_FLASHER_BOOT_HOLD_TIME_MS);
+ gpio_set_level(s_strap_bit3_pin, 1);
+ gpio_set_level(s_strap_bit0_pin, 0);
+
+ /* Disable the strapping pins so they can be used by the slave later */
+ gpio_reset_pin(s_strap_bit0_pin);
+ gpio_reset_pin(s_strap_bit1_pin);
+ gpio_reset_pin(s_strap_bit2_pin);
+ gpio_reset_pin(s_strap_bit3_pin);
+
+ /* Restore the SPI bus pins */
+ spi_bus_initialize(s_spi_bus, &s_spi_config, DMA_CHAN);
+ spi_bus_add_device(s_spi_bus, &s_device_config, &s_device_h);
+}
+
+
+void loader_port_reset_target(void)
+{
+ gpio_set_level(s_reset_trigger_pin, 0);
+ loader_port_delay_ms(SERIAL_FLASHER_RESET_HOLD_TIME_MS);
+ gpio_set_level(s_reset_trigger_pin, 1);
+}
+
+
+void loader_port_delay_ms(const uint32_t ms)
+{
+ usleep(ms * 1000);
+}
+
+
+void loader_port_start_timer(const uint32_t ms)
+{
+ s_time_end = esp_timer_get_time() + ms * 1000;
+}
+
+
+uint32_t loader_port_remaining_time(void)
+{
+ int64_t remaining = (s_time_end - esp_timer_get_time()) / 1000;
+ return (remaining > 0) ? (uint32_t)remaining : 0;
+}
+
+
+void loader_port_debug_print(const char *str)
+{
+ printf("DEBUG: %s\n", str);
+}
+
+
+esp_loader_error_t loader_port_change_transmission_rate(const uint32_t frequency)
+{
+ if (spi_bus_remove_device(s_device_h) != ESP_OK) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ uint32_t old_frequency = s_device_config.clock_speed_hz;
+ s_device_config.clock_speed_hz = frequency;
+
+ if (spi_bus_add_device(s_spi_bus, &s_device_config, &s_device_h) != ESP_OK) {
+ s_device_config.clock_speed_hz = old_frequency;
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_spi_port.h b/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_spi_port.h
new file mode 100644
index 000000000..72304c5df
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/esp32_spi_port.h
@@ -0,0 +1,60 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+ #pragma once
+
+#include "esp_loader_io.h"
+#include "driver/spi_master.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+ spi_host_device_t spi_bus;
+ uint32_t frequency;
+ uint32_t spi_clk_pin;
+ uint32_t spi_miso_pin;
+ uint32_t spi_mosi_pin;
+ uint32_t spi_cs_pin;
+ uint32_t spi_quadwp_pin;
+ uint32_t spi_quadhd_pin;
+ uint32_t reset_trigger_pin;
+ uint32_t strap_bit0_pin;
+ uint32_t strap_bit1_pin;
+ uint32_t strap_bit2_pin;
+ uint32_t strap_bit3_pin;
+} loader_esp32_spi_config_t;
+
+/**
+ * @brief Initializes the SPI interface.
+ *
+ * @param config[in] Configuration structure
+ *
+ * @return
+ * - ESP_LOADER_SUCCESS Success
+ * - ESP_LOADER_ERROR_FAIL Initialization failure
+ */
+esp_loader_error_t loader_port_esp32_spi_init(const loader_esp32_spi_config_t *config);
+
+/**
+ * @brief Deinitializes the SPI interface.
+ */
+void loader_port_esp32_spi_deinit(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/raspberry_port.c b/applications/external/esp_flasher/lib/esp-serial-flasher/port/raspberry_port.c
new file mode 100644
index 000000000..d733db702
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/raspberry_port.c
@@ -0,0 +1,302 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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 "esp_loader_io.h"
+#include "protocol.h"
+#include
+#include "raspberry_port.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+static void transfer_debug_print(const uint8_t *data, uint16_t size, bool write)
+{
+ static bool write_prev = false;
+
+ if (write_prev != write) {
+ write_prev = write;
+ printf("\n--- %s ---\n", write ? "WRITE" : "READ");
+ }
+
+ for (uint32_t i = 0; i < size; i++) {
+ printf("%02x ", data[i]);
+ }
+}
+#endif
+
+static int serial;
+static int64_t s_time_end;
+static int32_t s_reset_trigger_pin;
+static int32_t s_gpio0_trigger_pin;
+
+
+static speed_t convert_baudrate(int baud)
+{
+ switch (baud) {
+ case 50: return B50;
+ case 75: return B75;
+ case 110: return B110;
+ case 134: return B134;
+ case 150: return B150;
+ case 200: return B200;
+ case 300: return B300;
+ case 600: return B600;
+ case 1200: return B1200;
+ case 1800: return B1800;
+ case 2400: return B2400;
+ case 4800: return B4800;
+ case 9600: return B9600;
+ case 19200: return B19200;
+ case 38400: return B38400;
+ case 57600: return B57600;
+ case 115200: return B115200;
+ case 230400: return B230400;
+ case 460800: return B460800;
+ case 500000: return B500000;
+ case 576000: return B576000;
+ case 921600: return B921600;
+ case 1000000: return B1000000;
+ case 1152000: return B1152000;
+ case 1500000: return B1500000;
+ case 2000000: return B2000000;
+ case 2500000: return B2500000;
+ case 3000000: return B3000000;
+ case 3500000: return B3500000;
+ case 4000000: return B4000000;
+ default: return -1;
+ }
+}
+
+static int serialOpen (const char *device, uint32_t baudrate)
+{
+ struct termios options;
+ int status, fd;
+
+ if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) {
+ printf("Error occured while opening serial port !\n");
+ return -1 ;
+ }
+
+ fcntl (fd, F_SETFL, O_RDWR) ;
+
+ // Get and modify current options:
+
+ tcgetattr (fd, &options);
+ speed_t baud = convert_baudrate(baudrate);
+
+ if(baud < 0) {
+ printf("Invalid baudrate!\n");
+ return -1;
+ }
+
+ cfmakeraw (&options) ;
+ cfsetispeed (&options, baud) ;
+ cfsetospeed (&options, baud) ;
+
+ options.c_cflag |= (CLOCAL | CREAD) ;
+ options.c_cflag &= ~(PARENB | CSTOPB | CSIZE) ;
+ options.c_cflag |= CS8 ;
+ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
+ options.c_oflag &= ~OPOST ;
+ options.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
+ options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable any special handling of received bytes
+
+ options.c_cc [VMIN] = 0 ;
+ options.c_cc [VTIME] = 10 ; // 1 Second
+
+ tcsetattr (fd, TCSANOW, &options) ;
+
+ ioctl (fd, TIOCMGET, &status);
+
+ status |= TIOCM_DTR ;
+ status |= TIOCM_RTS ;
+
+ ioctl (fd, TIOCMSET, &status);
+
+ usleep (10000) ; // 10mS
+
+ return fd ;
+}
+
+static esp_loader_error_t change_baudrate(int file_desc, int baudrate)
+{
+ struct termios options;
+ speed_t baud = convert_baudrate(baudrate);
+
+ if(baud < 0) {
+ return ESP_LOADER_ERROR_INVALID_PARAM;
+ }
+
+ tcgetattr (file_desc, &options);
+
+ cfmakeraw (&options) ;
+ cfsetispeed (&options, baud);
+ cfsetospeed (&options, baud);
+
+ tcsetattr (file_desc, TCSANOW, &options);
+
+ return ESP_LOADER_SUCCESS;
+}
+
+static void set_timeout(uint32_t timeout)
+{
+ struct termios options;
+
+ timeout /= 100;
+ timeout = MAX(timeout, 1);
+
+ tcgetattr(serial, &options);
+ options.c_cc[VTIME] = timeout;
+ tcsetattr(serial, TCSANOW, &options);
+}
+
+static esp_loader_error_t read_char(char *c, uint32_t timeout)
+{
+ set_timeout(timeout);
+ int read_bytes = read(serial, c, 1);
+
+ if (read_bytes == 1) {
+ return ESP_LOADER_SUCCESS;
+ } else if (read_bytes == 0) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ } else {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+}
+
+static esp_loader_error_t read_data(char *buffer, uint32_t size)
+{
+ for (int i = 0; i < size; i++) {
+ uint32_t remaining_time = loader_port_remaining_time();
+ RETURN_ON_ERROR( read_char(&buffer[i], remaining_time) );
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+esp_loader_error_t loader_port_raspberry_init(const loader_raspberry_config_t *config)
+{
+ s_reset_trigger_pin = config->reset_trigger_pin;
+ s_gpio0_trigger_pin = config->gpio0_trigger_pin;
+
+ serial = serialOpen(config->device, config->baudrate);
+ if (serial < 0) {
+ printf("Serial port could not be opened!\n");
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ if (gpioInitialise() < 0) {
+ printf("pigpio initialisation failed\n");
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ gpioSetMode(config->reset_trigger_pin, PI_OUTPUT);
+ gpioSetMode(config->gpio0_trigger_pin, PI_OUTPUT);
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+esp_loader_error_t loader_port_write(const uint8_t *data, uint16_t size, uint32_t timeout)
+{
+ int written = write(serial, data, size);
+
+ if (written < 0) {
+ return ESP_LOADER_ERROR_FAIL;
+ } else if (written < size) {
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, written, true);
+#endif
+ return ESP_LOADER_ERROR_TIMEOUT;
+ } else {
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, written, true);
+#endif
+ return ESP_LOADER_SUCCESS;
+ }
+}
+
+
+esp_loader_error_t loader_port_read(uint8_t *data, uint16_t size, uint32_t timeout)
+{
+ RETURN_ON_ERROR( read_data(data, size) );
+
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, size, false);
+#endif
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+// Set GPIO0 LOW, then assert reset pin for 50 milliseconds.
+void loader_port_enter_bootloader(void)
+{
+ gpioWrite(s_gpio0_trigger_pin, 0);
+ loader_port_reset_target();
+ loader_port_delay_ms(SERIAL_FLASHER_BOOT_HOLD_TIME_MS);
+ gpioWrite(s_gpio0_trigger_pin, 1);
+}
+
+
+void loader_port_reset_target(void)
+{
+ gpioWrite(s_reset_trigger_pin, 0);
+ loader_port_delay_ms(SERIAL_FLASHER_RESET_HOLD_TIME_MS);
+ gpioWrite(s_reset_trigger_pin, 1);
+}
+
+
+void loader_port_delay_ms(uint32_t ms)
+{
+ usleep(ms * 1000);
+}
+
+
+void loader_port_start_timer(uint32_t ms)
+{
+ s_time_end = clock() + (ms * (CLOCKS_PER_SEC / 1000));
+}
+
+
+uint32_t loader_port_remaining_time(void)
+{
+ int64_t remaining = (s_time_end - clock()) / 1000;
+ return (remaining > 0) ? (uint32_t)remaining : 0;
+}
+
+
+void loader_port_debug_print(const char *str)
+{
+ printf("DEBUG: %s\n", str);
+}
+
+esp_loader_error_t loader_port_change_transmission_rate(uint32_t baudrate)
+{
+ return change_baudrate(serial, baudrate);
+}
\ No newline at end of file
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/raspberry_port.h b/applications/external/esp_flasher/lib/esp-serial-flasher/port/raspberry_port.h
new file mode 100644
index 000000000..803ab72dd
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/raspberry_port.h
@@ -0,0 +1,36 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include "esp_loader_io.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ const char *device;
+ uint32_t baudrate;
+ uint32_t reset_trigger_pin;
+ uint32_t gpio0_trigger_pin;
+} loader_raspberry_config_t;
+
+esp_loader_error_t loader_port_raspberry_init(const loader_raspberry_config_t *config);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/stm32_port.c b/applications/external/esp_flasher/lib/esp-serial-flasher/port/stm32_port.c
new file mode 100644
index 000000000..716c9c91b
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/stm32_port.c
@@ -0,0 +1,140 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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
+#include
+#include
+#include
+#include
+#include "stm32_port.h"
+
+static UART_HandleTypeDef *uart;
+static GPIO_TypeDef* gpio_port_io0, *gpio_port_rst;
+static uint16_t gpio_num_io0, gpio_num_rst;
+
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+static void transfer_debug_print(const uint8_t *data, uint16_t size, bool write)
+{
+ static bool write_prev = false;
+
+ if (write_prev != write) {
+ write_prev = write;
+ printf("\n--- %s ---\n", write ? "WRITE" : "READ");
+ }
+
+ for (uint32_t i = 0; i < size; i++) {
+ printf("%02x ", data[i]);
+ }
+}
+#endif
+
+static uint32_t s_time_end;
+
+esp_loader_error_t loader_port_write(const uint8_t *data, uint16_t size, uint32_t timeout)
+{
+ HAL_StatusTypeDef err = HAL_UART_Transmit(uart, (uint8_t *)data, size, timeout);
+
+ if (err == HAL_OK) {
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, size, true);
+#endif
+ return ESP_LOADER_SUCCESS;
+ } else if (err == HAL_TIMEOUT) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ } else {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+}
+
+
+esp_loader_error_t loader_port_read(uint8_t *data, uint16_t size, uint32_t timeout)
+{
+ HAL_StatusTypeDef err = HAL_UART_Receive(uart, data, size, timeout);
+
+ if (err == HAL_OK) {
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, size, false);
+#endif
+ return ESP_LOADER_SUCCESS;
+ } else if (err == HAL_TIMEOUT) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ } else {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+}
+
+void loader_port_stm32_init(loader_stm32_config_t *config)
+
+{
+ uart = config->huart;
+ gpio_port_io0 = config->port_io0;
+ gpio_port_rst = config->port_rst;
+ gpio_num_io0 = config->pin_num_io0;
+ gpio_num_rst = config->pin_num_rst;
+}
+
+// Set GPIO0 LOW, then
+// assert reset pin for 100 milliseconds.
+void loader_port_enter_bootloader(void)
+{
+ HAL_GPIO_WritePin(gpio_port_io0, gpio_num_io0, GPIO_PIN_RESET);
+ loader_port_reset_target();
+ HAL_Delay(SERIAL_FLASHER_BOOT_HOLD_TIME_MS);
+ HAL_GPIO_WritePin(gpio_port_io0, gpio_num_io0, GPIO_PIN_SET);
+}
+
+
+void loader_port_reset_target(void)
+{
+ HAL_GPIO_WritePin(gpio_port_rst, gpio_num_rst, GPIO_PIN_RESET);
+ HAL_Delay(SERIAL_FLASHER_RESET_HOLD_TIME_MS);
+ HAL_GPIO_WritePin(gpio_port_rst, gpio_num_rst, GPIO_PIN_SET);
+}
+
+
+void loader_port_delay_ms(uint32_t ms)
+{
+ HAL_Delay(ms);
+}
+
+
+void loader_port_start_timer(uint32_t ms)
+{
+ s_time_end = HAL_GetTick() + ms;
+}
+
+
+uint32_t loader_port_remaining_time(void)
+{
+ int32_t remaining = s_time_end - HAL_GetTick();
+ return (remaining > 0) ? (uint32_t)remaining : 0;
+}
+
+
+void loader_port_debug_print(const char *str)
+{
+ printf("DEBUG: %s", str);
+}
+
+esp_loader_error_t loader_port_change_transmission_rate(uint32_t baudrate)
+{
+ uart->Init.BaudRate = baudrate;
+
+ if( HAL_UART_Init(uart) != HAL_OK ) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/stm32_port.h b/applications/external/esp_flasher/lib/esp-serial-flasher/port/stm32_port.h
new file mode 100644
index 000000000..a3a89a733
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/stm32_port.h
@@ -0,0 +1,38 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include "esp_loader_io.h"
+#include "stm32f4xx_hal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ UART_HandleTypeDef *huart;
+ GPIO_TypeDef *port_io0;
+ uint16_t pin_num_io0;
+ GPIO_TypeDef *port_rst;
+ uint16_t pin_num_rst;
+} loader_stm32_config_t;
+
+void loader_port_stm32_init(loader_stm32_config_t *config);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/zephyr_port.c b/applications/external/esp_flasher/lib/esp-serial-flasher/port/zephyr_port.c
new file mode 100644
index 000000000..21270ba0a
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/zephyr_port.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2022 KT-Elektronik, Klaucke und Partner GmbH
+ *
+ * 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 "zephyr_port.h"
+#include
+#include
+
+static const struct device *uart_dev;
+static struct gpio_dt_spec enable_spec;
+static struct gpio_dt_spec boot_spec;
+
+static struct tty_serial tty;
+static char tty_rx_buf[CONFIG_ESP_SERIAL_FLASHER_UART_BUFSIZE];
+static char tty_tx_buf[CONFIG_ESP_SERIAL_FLASHER_UART_BUFSIZE];
+
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+static void transfer_debug_print(const uint8_t *data, uint16_t size, bool write)
+{
+ static bool write_prev = false;
+
+ if (write_prev != write) {
+ write_prev = write;
+ printk("\n--- %s ---\n", write ? "WRITE" : "READ");
+ }
+
+ for (uint32_t i = 0; i < size; i++) {
+ printk("%02x ", data[i]);
+ }
+}
+#endif
+
+esp_loader_error_t configure_tty()
+{
+ if (tty_init(&tty, uart_dev) < 0 ||
+ tty_set_rx_buf(&tty, tty_rx_buf, sizeof(tty_rx_buf)) < 0 ||
+ tty_set_tx_buf(&tty, tty_tx_buf, sizeof(tty_tx_buf)) < 0) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+esp_loader_error_t loader_port_read(uint8_t *data, const uint16_t size, const uint32_t timeout)
+{
+ if (!device_is_ready(uart_dev) || data == NULL || size == 0) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ ssize_t total_read = 0;
+ ssize_t remaining = size;
+
+ tty_set_rx_timeout(&tty, timeout);
+ while (remaining > 0) {
+ const uint16_t chunk_size = remaining < CONFIG_ESP_SERIAL_FLASHER_UART_BUFSIZE ?
+ remaining : CONFIG_ESP_SERIAL_FLASHER_UART_BUFSIZE;
+ ssize_t read = tty_read(&tty, &data[total_read], chunk_size);
+ if (read < 0) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ }
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, read, false);
+#endif
+ total_read += read;
+ remaining -= read;
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+esp_loader_error_t loader_port_write(const uint8_t *data, const uint16_t size, const uint32_t timeout)
+{
+ if (!device_is_ready(uart_dev) || data == NULL || size == 0) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ ssize_t total_written = 0;
+ ssize_t remaining = size;
+
+ tty_set_tx_timeout(&tty, timeout);
+ while (remaining > 0) {
+ const uint16_t chunk_size = remaining < CONFIG_ESP_SERIAL_FLASHER_UART_BUFSIZE ?
+ remaining : CONFIG_ESP_SERIAL_FLASHER_UART_BUFSIZE;
+ ssize_t written = tty_write(&tty, &data[total_written], chunk_size);
+ if (written < 0) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ }
+#ifdef SERIAL_FLASHER_DEBUG_TRACE
+ transfer_debug_print(data, written, true);
+#endif
+ total_written += written;
+ remaining -= written;
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+esp_loader_error_t loader_port_zephyr_init(const loader_zephyr_config_t *config)
+{
+ uart_dev = config->uart_dev;
+ enable_spec = config->enable_spec;
+ boot_spec = config->boot_spec;
+ return configure_tty();
+}
+
+void loader_port_reset_target(void)
+{
+ gpio_pin_set_dt(&enable_spec, false);
+ loader_port_delay_ms(CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS);
+ gpio_pin_set_dt(&enable_spec, true);
+}
+
+void loader_port_enter_bootloader(void)
+{
+ gpio_pin_set_dt(&boot_spec, false);
+ loader_port_reset_target();
+ loader_port_delay_ms(CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS);
+ gpio_pin_set_dt(&boot_spec, true);
+}
+
+void loader_port_delay_ms(uint32_t ms)
+{
+ k_msleep(ms);
+}
+
+static uint64_t s_time_end;
+
+void loader_port_start_timer(uint32_t ms)
+{
+ s_time_end = sys_clock_timeout_end_calc(Z_TIMEOUT_MS(ms));
+}
+
+uint32_t loader_port_remaining_time(void)
+{
+ int64_t remaining = k_ticks_to_ms_floor64(s_time_end - k_uptime_ticks());
+ return (remaining > 0) ? (uint32_t)remaining : 0;
+}
+
+esp_loader_error_t loader_port_change_transmission_rate(uint32_t baudrate)
+{
+ struct uart_config uart_config;
+
+ if (!device_is_ready(uart_dev)) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ if (uart_config_get(uart_dev, &uart_config) != 0) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+ uart_config.baudrate = baudrate;
+
+ if (uart_configure(uart_dev, &uart_config) != 0) {
+ return ESP_LOADER_ERROR_FAIL;
+ }
+
+ /* bitrate-change can require tty re-configuration */
+ return configure_tty();
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/port/zephyr_port.h b/applications/external/esp_flasher/lib/esp-serial-flasher/port/zephyr_port.h
new file mode 100644
index 000000000..0b104e375
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/port/zephyr_port.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022 KT-Elektronik, Klaucke und Partner GmbH
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "esp_loader_io.h"
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ const struct device *uart_dev;
+ const struct gpio_dt_spec enable_spec;
+ const struct gpio_dt_spec boot_spec;
+} loader_zephyr_config_t;
+
+esp_loader_error_t loader_port_zephyr_init(const loader_zephyr_config_t *config);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/esp_targets.h b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/esp_targets.h
new file mode 100644
index 000000000..cf8af91fa
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/esp_targets.h
@@ -0,0 +1,33 @@
+/* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include "esp_loader.h"
+
+typedef struct {
+ uint32_t cmd;
+ uint32_t usr;
+ uint32_t usr1;
+ uint32_t usr2;
+ uint32_t w0;
+ uint32_t mosi_dlen;
+ uint32_t miso_dlen;
+} target_registers_t;
+
+esp_loader_error_t loader_detect_chip(target_chip_t *target, const target_registers_t **regs);
+esp_loader_error_t loader_read_spi_config(target_chip_t target_chip, uint32_t *spi_config);
+bool encryption_in_begin_flash_cmd(target_chip_t target);
\ No newline at end of file
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/md5_hash.h b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/md5_hash.h
new file mode 100644
index 000000000..eb5738c8b
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/md5_hash.h
@@ -0,0 +1,28 @@
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#pragma once
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+struct MD5Context {
+ uint32_t buf[4];
+ uint32_t bits[2];
+ uint8_t in[64];
+};
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/protocol.h b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/protocol.h
new file mode 100644
index 000000000..fb8b086fd
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/protocol.h
@@ -0,0 +1,230 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include
+#include "esp_loader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define STATUS_FAILURE 1
+#define STATUS_SUCCESS 0
+
+#define READ_DIRECTION 1
+#define WRITE_DIRECTION 0
+
+#define MD5_SIZE 32
+
+typedef enum __attribute__((packed))
+{
+ FLASH_BEGIN = 0x02,
+ FLASH_DATA = 0x03,
+ FLASH_END = 0x04,
+ MEM_BEGIN = 0x05,
+ MEM_END = 0x06,
+ MEM_DATA = 0x07,
+ SYNC = 0x08,
+ WRITE_REG = 0x09,
+ READ_REG = 0x0a,
+
+ SPI_SET_PARAMS = 0x0b,
+ SPI_ATTACH = 0x0d,
+ CHANGE_BAUDRATE = 0x0f,
+ FLASH_DEFL_BEGIN = 0x10,
+ FLASH_DEFL_DATA = 0x11,
+ FLASH_DEFL_END = 0x12,
+ SPI_FLASH_MD5 = 0x13,
+} command_t;
+
+typedef enum __attribute__((packed))
+{
+ RESPONSE_OK = 0x00,
+ INVALID_COMMAND = 0x05, // parameters or length field is invalid
+ COMMAND_FAILED = 0x06, // Failed to act on received message
+ INVALID_CRC = 0x07, // Invalid CRC in message
+ FLASH_WRITE_ERR = 0x08, // After writing a block of data to flash, the ROM loader reads the value back and the 8-bit CRC is compared to the data read from flash. If they don't match, this error is returned.
+ FLASH_READ_ERR = 0x09, // SPI read failed
+ READ_LENGTH_ERR = 0x0a, // SPI read request length is too long
+ DEFLATE_ERROR = 0x0b, // ESP32 compressed uploads only
+} error_code_t;
+
+typedef struct __attribute__((packed))
+{
+ uint8_t direction;
+ uint8_t command; // One of command_t
+ uint16_t size;
+ uint32_t checksum;
+} command_common_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t erase_size;
+ uint32_t packet_count;
+ uint32_t packet_size;
+ uint32_t offset;
+ uint32_t encrypted;
+} flash_begin_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t data_size;
+ uint32_t sequence_number;
+ uint32_t zero_0;
+ uint32_t zero_1;
+} data_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t stay_in_loader;
+} flash_end_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t total_size;
+ uint32_t blocks;
+ uint32_t block_size;
+ uint32_t offset;
+} mem_begin_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t stay_in_loader;
+ uint32_t entry_point_address;
+} mem_end_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint8_t sync_sequence[36];
+} sync_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t address;
+ uint32_t value;
+ uint32_t mask;
+ uint32_t delay_us;
+} write_reg_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t address;
+} read_reg_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t configuration;
+ uint32_t zero; // ESP32 ROM only
+} spi_attach_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t new_baudrate;
+ uint32_t old_baudrate;
+} change_baudrate_command_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t address;
+ uint32_t size;
+ uint32_t reserved_0;
+ uint32_t reserved_1;
+} spi_flash_md5_command_t;
+
+typedef struct __attribute__((packed))
+{
+ uint8_t direction;
+ uint8_t command; // One of command_t
+ uint16_t size;
+ uint32_t value;
+} common_response_t;
+
+typedef struct __attribute__((packed))
+{
+ uint8_t failed;
+ uint8_t error;
+} response_status_t;
+
+typedef struct __attribute__((packed))
+{
+ common_response_t common;
+ response_status_t status;
+} response_t;
+
+typedef struct __attribute__((packed))
+{
+ common_response_t common;
+ uint8_t md5[MD5_SIZE]; // ROM only
+ response_status_t status;
+} rom_md5_response_t;
+
+typedef struct __attribute__((packed))
+{
+ command_common_t common;
+ uint32_t id;
+ uint32_t total_size;
+ uint32_t block_size;
+ uint32_t sector_size;
+ uint32_t page_size;
+ uint32_t status_mask;
+} write_spi_command_t;
+
+esp_loader_error_t loader_initialize_conn(esp_loader_connect_args_t *connect_args);
+
+#ifdef SERIAL_FLASHER_INTERFACE_UART
+esp_loader_error_t loader_flash_begin_cmd(uint32_t offset, uint32_t erase_size, uint32_t block_size, uint32_t blocks_to_write, bool encryption);
+
+esp_loader_error_t loader_flash_data_cmd(const uint8_t *data, uint32_t size);
+
+esp_loader_error_t loader_flash_end_cmd(bool stay_in_loader);
+
+esp_loader_error_t loader_sync_cmd(void);
+
+esp_loader_error_t loader_spi_attach_cmd(uint32_t config);
+
+esp_loader_error_t loader_md5_cmd(uint32_t address, uint32_t size, uint8_t *md5_out);
+
+esp_loader_error_t loader_spi_parameters(uint32_t total_size);
+#endif /* SERIAL_FLASHER_INTERFACE_UART */
+
+esp_loader_error_t loader_mem_begin_cmd(uint32_t offset, uint32_t size, uint32_t blocks_to_write, uint32_t block_size);
+
+esp_loader_error_t loader_mem_data_cmd(const uint8_t *data, uint32_t size);
+
+esp_loader_error_t loader_mem_end_cmd(uint32_t entrypoint);
+
+esp_loader_error_t loader_write_reg_cmd(uint32_t address, uint32_t value, uint32_t mask, uint32_t delay_us);
+
+esp_loader_error_t loader_read_reg_cmd(uint32_t address, uint32_t *reg);
+
+esp_loader_error_t loader_change_baudrate_cmd(uint32_t baudrate);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/protocol_prv.h b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/protocol_prv.h
new file mode 100644
index 000000000..3b9575606
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/protocol_prv.h
@@ -0,0 +1,31 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include "esp_loader.h"
+#include "protocol.h"
+
+void log_loader_internal_error(error_code_t error);
+
+esp_loader_error_t send_cmd(const void *cmd_data, uint32_t size, uint32_t *reg_value);
+
+esp_loader_error_t send_cmd_with_data(const void *cmd_data, size_t cmd_size,
+ const void *data, size_t data_size);
+
+esp_loader_error_t send_cmd_md5(const void *cmd_data, size_t cmd_size, uint8_t md5_out[MD5_SIZE]);
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/slip.h b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/slip.h
new file mode 100644
index 000000000..00f1f7d0d
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/private_include/slip.h
@@ -0,0 +1,28 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "esp_loader.h"
+#include
+#include
+
+esp_loader_error_t SLIP_receive_data(uint8_t *buff, size_t size);
+
+esp_loader_error_t SLIP_receive_packet(uint8_t *buff, size_t size);
+
+esp_loader_error_t SLIP_send(const uint8_t *data, size_t size);
+
+esp_loader_error_t SLIP_send_delimiter(void);
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/src/esp_loader.c b/applications/external/esp_flasher/lib/esp-serial-flasher/src/esp_loader.c
new file mode 100644
index 000000000..6ef32673c
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/src/esp_loader.c
@@ -0,0 +1,415 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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 "protocol.h"
+#include "esp_loader_io.h"
+#include "esp_loader.h"
+#include "esp_targets.h"
+#include "md5_hash.h"
+#include
+#include
+
+#ifndef MAX
+#define MAX(a, b) ((a) > (b)) ? (a) : (b)
+#endif
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b)) ? (a) : (b)
+#endif
+
+#ifndef ROUNDUP
+#define ROUNDUP(a, b) (((int)a + (int)b - 1) / (int)b)
+#endif
+
+static const uint32_t DEFAULT_TIMEOUT = 1000;
+static const uint32_t DEFAULT_FLASH_TIMEOUT = 3000; // timeout for most flash operations
+static const uint32_t LOAD_RAM_TIMEOUT_PER_MB = 2000000; // timeout (per megabyte) for erasing a region
+
+typedef enum {
+ SPI_FLASH_READ_ID = 0x9F
+} spi_flash_cmd_t;
+
+static const target_registers_t *s_reg = NULL;
+static target_chip_t s_target = ESP_UNKNOWN_CHIP;
+
+#if MD5_ENABLED
+
+static const uint32_t MD5_TIMEOUT_PER_MB = 800;
+static struct MD5Context s_md5_context;
+static uint32_t s_start_address;
+static uint32_t s_image_size;
+
+static inline void init_md5(uint32_t address, uint32_t size)
+{
+ s_start_address = address;
+ s_image_size = size;
+ MD5Init(&s_md5_context);
+}
+
+static inline void md5_update(const uint8_t *data, uint32_t size)
+{
+ MD5Update(&s_md5_context, data, size);
+}
+
+static inline void md5_final(uint8_t digets[16])
+{
+ MD5Final(digets, &s_md5_context);
+}
+
+#else
+
+static inline void init_md5(uint32_t address, uint32_t size) { }
+static inline void md5_update(const uint8_t *data, uint32_t size) { }
+static inline void md5_final(uint8_t digets[16]) { }
+
+#endif
+
+
+static uint32_t timeout_per_mb(uint32_t size_bytes, uint32_t time_per_mb)
+{
+ uint32_t timeout = time_per_mb * (size_bytes / 1e6);
+ return MAX(timeout, DEFAULT_FLASH_TIMEOUT);
+}
+
+esp_loader_error_t esp_loader_connect(esp_loader_connect_args_t *connect_args)
+{
+ loader_port_enter_bootloader();
+
+ RETURN_ON_ERROR(loader_initialize_conn(connect_args));
+
+ RETURN_ON_ERROR(loader_detect_chip(&s_target, &s_reg));
+
+#ifdef SERIAL_FLASHER_INTERFACE_UART
+ esp_loader_error_t err;
+ uint32_t spi_config;
+ if (s_target == ESP8266_CHIP) {
+ err = loader_flash_begin_cmd(0, 0, 0, 0, s_target);
+ } else {
+ RETURN_ON_ERROR( loader_read_spi_config(s_target, &spi_config) );
+ loader_port_start_timer(DEFAULT_TIMEOUT);
+ err = loader_spi_attach_cmd(spi_config);
+ }
+ return err;
+#endif /* SERIAL_FLASHER_INTERFACE_UART */
+ return ESP_LOADER_SUCCESS;
+}
+
+target_chip_t esp_loader_get_target(void)
+{
+ return s_target;
+}
+
+#ifdef SERIAL_FLASHER_INTERFACE_UART
+static uint32_t s_flash_write_size = 0;
+
+static esp_loader_error_t spi_set_data_lengths(size_t mosi_bits, size_t miso_bits)
+{
+ if (mosi_bits > 0) {
+ RETURN_ON_ERROR( esp_loader_write_register(s_reg->mosi_dlen, mosi_bits - 1) );
+ }
+ if (miso_bits > 0) {
+ RETURN_ON_ERROR( esp_loader_write_register(s_reg->miso_dlen, miso_bits - 1) );
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+static esp_loader_error_t spi_set_data_lengths_8266(size_t mosi_bits, size_t miso_bits)
+{
+ uint32_t mosi_mask = (mosi_bits == 0) ? 0 : mosi_bits - 1;
+ uint32_t miso_mask = (miso_bits == 0) ? 0 : miso_bits - 1;
+ return esp_loader_write_register(s_reg->usr1, (miso_mask << 8) | (mosi_mask << 17));
+}
+
+static esp_loader_error_t spi_flash_command(spi_flash_cmd_t cmd, void *data_tx, size_t tx_size, void *data_rx, size_t rx_size)
+{
+ assert(rx_size <= 32); // Reading more than 32 bits back from a SPI flash operation is unsupported
+ assert(tx_size <= 64); // Writing more than 64 bytes of data with one SPI command is unsupported
+
+ uint32_t SPI_USR_CMD = (1 << 31);
+ uint32_t SPI_USR_MISO = (1 << 28);
+ uint32_t SPI_USR_MOSI = (1 << 27);
+ uint32_t SPI_CMD_USR = (1 << 18);
+ uint32_t CMD_LEN_SHIFT = 28;
+
+ // Save SPI configuration
+ uint32_t old_spi_usr;
+ uint32_t old_spi_usr2;
+ RETURN_ON_ERROR( esp_loader_read_register(s_reg->usr, &old_spi_usr) );
+ RETURN_ON_ERROR( esp_loader_read_register(s_reg->usr2, &old_spi_usr2) );
+
+ if (s_target == ESP8266_CHIP) {
+ RETURN_ON_ERROR( spi_set_data_lengths_8266(tx_size, rx_size) );
+ } else {
+ RETURN_ON_ERROR( spi_set_data_lengths(tx_size, rx_size) );
+ }
+
+ uint32_t usr_reg_2 = (7 << CMD_LEN_SHIFT) | cmd;
+ uint32_t usr_reg = SPI_USR_CMD;
+ if (rx_size > 0) {
+ usr_reg |= SPI_USR_MISO;
+ }
+ if (tx_size > 0) {
+ usr_reg |= SPI_USR_MOSI;
+ }
+
+ RETURN_ON_ERROR( esp_loader_write_register(s_reg->usr, usr_reg) );
+ RETURN_ON_ERROR( esp_loader_write_register(s_reg->usr2, usr_reg_2 ) );
+
+ if (tx_size == 0) {
+ // clear data register before we read it
+ RETURN_ON_ERROR( esp_loader_write_register(s_reg->w0, 0) );
+ } else {
+ uint32_t *data = (uint32_t *)data_tx;
+ uint32_t words_to_write = (tx_size + 31) / (8 * 4);
+ uint32_t data_reg_addr = s_reg->w0;
+
+ while (words_to_write--) {
+ uint32_t word = *data++;
+ RETURN_ON_ERROR( esp_loader_write_register(data_reg_addr, word) );
+ data_reg_addr += 4;
+ }
+ }
+
+ RETURN_ON_ERROR( esp_loader_write_register(s_reg->cmd, SPI_CMD_USR) );
+
+ uint32_t trials = 10;
+ while (trials--) {
+ uint32_t cmd_reg;
+ RETURN_ON_ERROR( esp_loader_read_register(s_reg->cmd, &cmd_reg) );
+ if ((cmd_reg & SPI_CMD_USR) == 0) {
+ break;
+ }
+ }
+
+ if (trials == 0) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ }
+
+ RETURN_ON_ERROR( esp_loader_read_register(s_reg->w0, data_rx) );
+
+ // Restore SPI configuration
+ RETURN_ON_ERROR( esp_loader_write_register(s_reg->usr, old_spi_usr) );
+ RETURN_ON_ERROR( esp_loader_write_register(s_reg->usr2, old_spi_usr2) );
+
+ return ESP_LOADER_SUCCESS;
+}
+
+static esp_loader_error_t detect_flash_size(size_t *flash_size)
+{
+ uint32_t flash_id = 0;
+
+ RETURN_ON_ERROR( spi_flash_command(SPI_FLASH_READ_ID, NULL, 0, &flash_id, 24) );
+ uint32_t size_id = flash_id >> 16;
+
+ if (size_id < 0x12 || size_id > 0x18) {
+ return ESP_LOADER_ERROR_UNSUPPORTED_CHIP;
+ }
+
+ *flash_size = 1 << size_id;
+
+ return ESP_LOADER_SUCCESS;
+}
+
+static uint32_t calc_erase_size(const target_chip_t target, const uint32_t offset,
+ const uint32_t image_size)
+{
+ if (target != ESP8266_CHIP) {
+ return image_size;
+ } else {
+ /* Needed to fix a bug in the ESP8266 ROM */
+ const uint32_t sectors_per_block = 16U;
+ const uint32_t sector_size = 4096U;
+
+ const uint32_t num_sectors = (image_size + sector_size - 1) / sector_size;
+ const uint32_t start_sector = offset / sector_size;
+
+ uint32_t head_sectors = sectors_per_block - (start_sector % sectors_per_block);
+
+ /* The ROM bug deletes extra num_sectors if we don't cross the block boundary
+ and extra head_sectors if we do */
+ if (num_sectors <= head_sectors) {
+ return ((num_sectors + 1) / 2) * sector_size;
+ } else {
+ return (num_sectors - head_sectors) * sector_size;
+ }
+ }
+}
+
+esp_loader_error_t esp_loader_flash_start(uint32_t offset, uint32_t image_size, uint32_t block_size)
+{
+ s_flash_write_size = block_size;
+
+ size_t flash_size = 0;
+ if (detect_flash_size(&flash_size) == ESP_LOADER_SUCCESS) {
+ if (image_size > flash_size) {
+ return ESP_LOADER_ERROR_IMAGE_SIZE;
+ }
+ loader_port_start_timer(DEFAULT_TIMEOUT);
+ RETURN_ON_ERROR( loader_spi_parameters(flash_size) );
+ } else {
+ loader_port_debug_print("Flash size detection failed, falling back to default");
+ }
+
+ init_md5(offset, image_size);
+
+ bool encryption_in_cmd = encryption_in_begin_flash_cmd(s_target);
+ const uint32_t erase_size = calc_erase_size(esp_loader_get_target(), offset, image_size);
+ const uint32_t blocks_to_write = (image_size + block_size - 1) / block_size;
+
+ const uint32_t erase_region_timeout_per_mb = 10000;
+ loader_port_start_timer(timeout_per_mb(erase_size, erase_region_timeout_per_mb));
+ return loader_flash_begin_cmd(offset, erase_size, block_size, blocks_to_write, encryption_in_cmd);
+}
+
+
+esp_loader_error_t esp_loader_flash_write(void *payload, uint32_t size)
+{
+ uint32_t padding_bytes = s_flash_write_size - size;
+ uint8_t *data = (uint8_t *)payload;
+ uint32_t padding_index = size;
+
+ if (size > s_flash_write_size) {
+ return ESP_LOADER_ERROR_INVALID_PARAM;
+ }
+
+ const uint8_t padding_pattern = 0xFF;
+ while (padding_bytes--) {
+ data[padding_index++] = padding_pattern;
+ }
+
+ md5_update(payload, (size + 3) & ~3);
+
+ loader_port_start_timer(DEFAULT_TIMEOUT);
+
+ return loader_flash_data_cmd(data, s_flash_write_size);
+}
+
+
+esp_loader_error_t esp_loader_flash_finish(bool reboot)
+{
+ loader_port_start_timer(DEFAULT_TIMEOUT);
+
+ return loader_flash_end_cmd(!reboot);
+}
+#endif /* SERIAL_FLASHER_INTERFACE_UART */
+
+esp_loader_error_t esp_loader_mem_start(uint32_t offset, uint32_t size, uint32_t block_size)
+{
+ uint32_t blocks_to_write = ROUNDUP(size, block_size);
+ loader_port_start_timer(timeout_per_mb(size, LOAD_RAM_TIMEOUT_PER_MB));
+ return loader_mem_begin_cmd(offset, size, blocks_to_write, block_size);
+}
+
+
+esp_loader_error_t esp_loader_mem_write(const void *payload, uint32_t size)
+{
+ const uint8_t *data = (const uint8_t *)payload;
+ loader_port_start_timer(timeout_per_mb(size, LOAD_RAM_TIMEOUT_PER_MB));
+ return loader_mem_data_cmd(data, size);
+}
+
+
+esp_loader_error_t esp_loader_mem_finish(uint32_t entrypoint)
+{
+ loader_port_start_timer(DEFAULT_TIMEOUT);
+ return loader_mem_end_cmd(entrypoint);
+}
+
+
+esp_loader_error_t esp_loader_read_register(uint32_t address, uint32_t *reg_value)
+{
+ loader_port_start_timer(DEFAULT_TIMEOUT);
+
+ return loader_read_reg_cmd(address, reg_value);
+}
+
+
+esp_loader_error_t esp_loader_write_register(uint32_t address, uint32_t reg_value)
+{
+ loader_port_start_timer(DEFAULT_TIMEOUT);
+
+ return loader_write_reg_cmd(address, reg_value, 0xFFFFFFFF, 0);
+}
+
+esp_loader_error_t esp_loader_change_transmission_rate(uint32_t transmission_rate)
+{
+ if (s_target == ESP8266_CHIP) {
+ return ESP_LOADER_ERROR_UNSUPPORTED_FUNC;
+ }
+
+ loader_port_start_timer(DEFAULT_TIMEOUT);
+
+ return loader_change_baudrate_cmd(transmission_rate);
+}
+
+#if MD5_ENABLED
+
+static void hexify(const uint8_t raw_md5[16], uint8_t hex_md5_out[32])
+{
+ static const uint8_t dec_to_hex[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+ for (int i = 0; i < 16; i++) {
+ *hex_md5_out++ = dec_to_hex[raw_md5[i] >> 4];
+ *hex_md5_out++ = dec_to_hex[raw_md5[i] & 0xF];
+ }
+}
+
+
+esp_loader_error_t esp_loader_flash_verify(void)
+{
+ if (s_target == ESP8266_CHIP) {
+ return ESP_LOADER_ERROR_UNSUPPORTED_FUNC;
+ }
+
+ uint8_t raw_md5[16] = {0};
+
+ /* Zero termination and new line character require 2 bytes */
+ uint8_t hex_md5[MD5_SIZE + 2] = {0};
+ uint8_t received_md5[MD5_SIZE + 2] = {0};
+
+ md5_final(raw_md5);
+ hexify(raw_md5, hex_md5);
+
+ loader_port_start_timer(timeout_per_mb(s_image_size, MD5_TIMEOUT_PER_MB));
+
+ RETURN_ON_ERROR( loader_md5_cmd(s_start_address, s_image_size, received_md5) );
+
+ bool md5_match = memcmp(hex_md5, received_md5, MD5_SIZE) == 0;
+
+ if (!md5_match) {
+ hex_md5[MD5_SIZE] = '\n';
+ received_md5[MD5_SIZE] = '\n';
+
+ loader_port_debug_print("Error: MD5 checksum does not match:\n");
+ loader_port_debug_print("Expected:\n");
+ loader_port_debug_print((char *)received_md5);
+ loader_port_debug_print("Actual:\n");
+ loader_port_debug_print((char *)hex_md5);
+
+ return ESP_LOADER_ERROR_INVALID_MD5;
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+#endif
+
+void esp_loader_reset_target(void)
+{
+ loader_port_reset_target();
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/src/esp_targets.c b/applications/external/esp_flasher/lib/esp-serial-flasher/src/esp_targets.c
new file mode 100644
index 000000000..8764d2369
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/src/esp_targets.c
@@ -0,0 +1,263 @@
+/* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+ *
+ * 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 "esp_targets.h"
+#include
+
+#define MAX_MAGIC_VALUES 2
+
+typedef esp_loader_error_t (*read_spi_config_t)(uint32_t efuse_base, uint32_t *spi_config);
+
+typedef struct {
+ target_registers_t regs;
+ uint32_t efuse_base;
+ uint32_t chip_magic_value[MAX_MAGIC_VALUES];
+ read_spi_config_t read_spi_config;
+ bool encryption_in_begin_flash_cmd;
+} esp_target_t;
+
+// This ROM address has a different value on each chip model
+#define CHIP_DETECT_MAGIC_REG_ADDR 0x40001000
+
+#define ESP8266_SPI_REG_BASE 0x60000200
+#define ESP32S2_SPI_REG_BASE 0x3f402000
+#define ESP32xx_SPI_REG_BASE 0x60002000
+#define ESP32_SPI_REG_BASE 0x3ff42000
+
+static esp_loader_error_t spi_config_esp32(uint32_t efuse_base, uint32_t *spi_config);
+static esp_loader_error_t spi_config_esp32xx(uint32_t efuse_base, uint32_t *spi_config);
+
+static const esp_target_t esp_target[ESP_MAX_CHIP] = {
+
+ // ESP8266
+ {
+ .regs = {
+ .cmd = ESP8266_SPI_REG_BASE + 0x00,
+ .usr = ESP8266_SPI_REG_BASE + 0x1c,
+ .usr1 = ESP8266_SPI_REG_BASE + 0x20,
+ .usr2 = ESP8266_SPI_REG_BASE + 0x24,
+ .w0 = ESP8266_SPI_REG_BASE + 0x40,
+ .mosi_dlen = 0,
+ .miso_dlen = 0,
+ },
+ .efuse_base = 0, // Not used
+ .chip_magic_value = { 0xfff0c101, 0 },
+ .read_spi_config = NULL, // Not used
+ },
+
+ // ESP32
+ {
+ .regs = {
+ .cmd = ESP32_SPI_REG_BASE + 0x00,
+ .usr = ESP32_SPI_REG_BASE + 0x1c,
+ .usr1 = ESP32_SPI_REG_BASE + 0x20,
+ .usr2 = ESP32_SPI_REG_BASE + 0x24,
+ .w0 = ESP32_SPI_REG_BASE + 0x80,
+ .mosi_dlen = ESP32_SPI_REG_BASE + 0x28,
+ .miso_dlen = ESP32_SPI_REG_BASE + 0x2c,
+ },
+ .efuse_base = 0x3ff5A000,
+ .chip_magic_value = { 0x00f01d83, 0 },
+ .read_spi_config = spi_config_esp32,
+ },
+
+ // ESP32S2
+ {
+ .regs = {
+ .cmd = ESP32S2_SPI_REG_BASE + 0x00,
+ .usr = ESP32S2_SPI_REG_BASE + 0x18,
+ .usr1 = ESP32S2_SPI_REG_BASE + 0x1c,
+ .usr2 = ESP32S2_SPI_REG_BASE + 0x20,
+ .w0 = ESP32S2_SPI_REG_BASE + 0x58,
+ .mosi_dlen = ESP32S2_SPI_REG_BASE + 0x24,
+ .miso_dlen = ESP32S2_SPI_REG_BASE + 0x28,
+ },
+ .efuse_base = 0x3f41A000,
+ .chip_magic_value = { 0x000007c6, 0 },
+ .read_spi_config = spi_config_esp32xx,
+ },
+
+ // ESP32C3
+ {
+ .regs = {
+ .cmd = ESP32xx_SPI_REG_BASE + 0x00,
+ .usr = ESP32xx_SPI_REG_BASE + 0x18,
+ .usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
+ .usr2 = ESP32xx_SPI_REG_BASE + 0x20,
+ .w0 = ESP32xx_SPI_REG_BASE + 0x58,
+ .mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
+ .miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
+ },
+ .efuse_base = 0x60008800,
+ .chip_magic_value = { 0x6921506f, 0x1b31506f },
+ .read_spi_config = spi_config_esp32xx,
+ },
+
+ // ESP32S3
+ {
+ .regs = {
+ .cmd = ESP32xx_SPI_REG_BASE + 0x00,
+ .usr = ESP32xx_SPI_REG_BASE + 0x18,
+ .usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
+ .usr2 = ESP32xx_SPI_REG_BASE + 0x20,
+ .w0 = ESP32xx_SPI_REG_BASE + 0x58,
+ .mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
+ .miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
+ },
+ .efuse_base = 0x60007000,
+ .chip_magic_value = { 0x00000009, 0 },
+ .read_spi_config = spi_config_esp32xx,
+ },
+
+ // ESP32C2
+ {
+ .regs = {
+ .cmd = ESP32xx_SPI_REG_BASE + 0x00,
+ .usr = ESP32xx_SPI_REG_BASE + 0x18,
+ .usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
+ .usr2 = ESP32xx_SPI_REG_BASE + 0x20,
+ .w0 = ESP32xx_SPI_REG_BASE + 0x58,
+ .mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
+ .miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
+ },
+ .efuse_base = 0x60008800,
+ .chip_magic_value = { 0x6f51306f, 0x7c41a06f },
+ .read_spi_config = spi_config_esp32xx,
+ },
+ // ESP32H4
+ {
+ .regs = {
+ .cmd = ESP32xx_SPI_REG_BASE + 0x00,
+ .usr = ESP32xx_SPI_REG_BASE + 0x18,
+ .usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
+ .usr2 = ESP32xx_SPI_REG_BASE + 0x20,
+ .w0 = ESP32xx_SPI_REG_BASE + 0x58,
+ .mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
+ .miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
+ },
+ .efuse_base = 0x6001A000,
+ .chip_magic_value = {0xca26cc22, 0x6881b06f}, // ESP32H4-BETA1, ESP32H4-BETA2
+ .read_spi_config = spi_config_esp32xx,
+ },
+ // ESP32H2
+ {
+ .regs = {
+ .cmd = ESP32xx_SPI_REG_BASE + 0x00,
+ .usr = ESP32xx_SPI_REG_BASE + 0x18,
+ .usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
+ .usr2 = ESP32xx_SPI_REG_BASE + 0x20,
+ .w0 = ESP32xx_SPI_REG_BASE + 0x58,
+ .mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
+ .miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
+ },
+ .efuse_base = 0x6001A000,
+ .chip_magic_value = {0xd7b73e80, 0},
+ .read_spi_config = spi_config_esp32xx,
+ },
+};
+
+const target_registers_t *get_esp_target_data(target_chip_t chip)
+{
+ return (const target_registers_t *)&esp_target[chip];
+}
+
+esp_loader_error_t loader_detect_chip(target_chip_t *target_chip, const target_registers_t **target_data)
+{
+ uint32_t magic_value;
+ RETURN_ON_ERROR( esp_loader_read_register(CHIP_DETECT_MAGIC_REG_ADDR, &magic_value) );
+
+ for (int chip = 0; chip < ESP_MAX_CHIP; chip++) {
+ for(int index = 0; index < MAX_MAGIC_VALUES; index++) {
+ if (magic_value == esp_target[chip].chip_magic_value[index]) {
+ *target_chip = (target_chip_t)chip;
+ *target_data = (target_registers_t *)&esp_target[chip];
+ return ESP_LOADER_SUCCESS;
+ }
+ }
+ }
+
+ return ESP_LOADER_ERROR_INVALID_TARGET;
+}
+
+esp_loader_error_t loader_read_spi_config(target_chip_t target_chip, uint32_t *spi_config)
+{
+ const esp_target_t *target = &esp_target[target_chip];
+ return target->read_spi_config(target->efuse_base, spi_config);
+}
+
+static inline uint32_t efuse_word_addr(uint32_t efuse_base, uint32_t n)
+{
+ return efuse_base + (n * 4);
+}
+
+// 30->GPIO32 | 31->GPIO33
+static inline uint8_t adjust_pin_number(uint8_t num)
+{
+ return (num >= 30) ? num + 2 : num;
+}
+
+
+static esp_loader_error_t spi_config_esp32(uint32_t efuse_base, uint32_t *spi_config)
+{
+ *spi_config = 0;
+
+ uint32_t reg5, reg3;
+ RETURN_ON_ERROR( esp_loader_read_register(efuse_word_addr(efuse_base, 5), ®5) );
+ RETURN_ON_ERROR( esp_loader_read_register(efuse_word_addr(efuse_base, 3), ®3) );
+
+ uint32_t pins = reg5 & 0xfffff;
+
+ if (pins == 0 || pins == 0xfffff) {
+ return ESP_LOADER_SUCCESS;
+ }
+
+ uint8_t clk = adjust_pin_number( (pins >> 0) & 0x1f );
+ uint8_t q = adjust_pin_number( (pins >> 5) & 0x1f );
+ uint8_t d = adjust_pin_number( (pins >> 10) & 0x1f );
+ uint8_t cs = adjust_pin_number( (pins >> 15) & 0x1f );
+ uint8_t hd = adjust_pin_number( (reg3 >> 4) & 0x1f );
+
+ if (clk == cs || clk == d || clk == q || q == cs || q == d || q == d) {
+ return ESP_LOADER_SUCCESS;
+ }
+
+ *spi_config = (hd << 24) | (cs << 18) | (d << 12) | (q << 6) | clk;
+
+ return ESP_LOADER_SUCCESS;
+}
+
+// Applies for esp32s2, esp32c3 and esp32c3
+static esp_loader_error_t spi_config_esp32xx(uint32_t efuse_base, uint32_t *spi_config)
+{
+ *spi_config = 0;
+
+ uint32_t reg1, reg2;
+ RETURN_ON_ERROR( esp_loader_read_register(efuse_word_addr(efuse_base, 18), ®1) );
+ RETURN_ON_ERROR( esp_loader_read_register(efuse_word_addr(efuse_base, 19), ®2) );
+
+ uint32_t pins = ((reg1 >> 16) | ((reg2 & 0xfffff) << 16)) & 0x3fffffff;
+
+ if (pins == 0 || pins == 0xffffffff) {
+ return ESP_LOADER_SUCCESS;
+ }
+
+ *spi_config = pins;
+ return ESP_LOADER_SUCCESS;
+}
+
+bool encryption_in_begin_flash_cmd(target_chip_t target)
+{
+ return target == ESP32_CHIP || target == ESP8266_CHIP;
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/src/md5_hash.c b/applications/external/esp_flasher/lib/esp-serial-flasher/src/md5_hash.c
new file mode 100644
index 000000000..4da76bcb5
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/src/md5_hash.c
@@ -0,0 +1,262 @@
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+
+#include "md5_hash.h"
+#include
+#include
+
+
+static void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
+
+
+/* ===== start - public domain MD5 implementation ===== */
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#ifndef WORDS_BIGENDIAN
+#define byteReverse(buf, len) /* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+ uint32_t t;
+ do {
+ t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(uint32_t *) buf = t;
+ buf += 4;
+ } while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+ uint32_t t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) {
+ ctx->bits[1]++; /* Carry from low to high */
+ }
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD5Transform((uint32_t *)ctx->buf, (uint32_t *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD5Transform((uint32_t *)ctx->buf, (uint32_t *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD5Transform((uint32_t *)ctx->buf, (uint32_t *) ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ((uint32_t *) ctx->in)[14] = ctx->bits[0];
+ ((uint32_t *) ctx->in)[15] = ctx->bits[1];
+
+ MD5Transform((uint32_t *)ctx->buf, (uint32_t *) ctx->in);
+ byteReverse((unsigned char *) ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(struct MD5Context)); /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
+{
+ register uint32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+/* ===== end - public domain MD5 implementation ===== */
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/src/protocol_common.c b/applications/external/esp_flasher/lib/esp-serial-flasher/src/protocol_common.c
new file mode 100644
index 000000000..8d1d9dd53
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/src/protocol_common.c
@@ -0,0 +1,301 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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 "protocol.h"
+#include "protocol_prv.h"
+#include "esp_loader_io.h"
+#include
+#include
+
+#define CMD_SIZE(cmd) ( sizeof(cmd) - sizeof(command_common_t) )
+
+static uint32_t s_sequence_number = 0;
+
+static uint8_t compute_checksum(const uint8_t *data, uint32_t size)
+{
+ uint8_t checksum = 0xEF;
+
+ while (size--) {
+ checksum ^= *data++;
+ }
+
+ return checksum;
+}
+
+void log_loader_internal_error(error_code_t error)
+{
+ loader_port_debug_print("Error: ");
+
+ switch (error) {
+ case INVALID_CRC: loader_port_debug_print("INVALID_CRC"); break;
+ case INVALID_COMMAND: loader_port_debug_print("INVALID_COMMAND"); break;
+ case COMMAND_FAILED: loader_port_debug_print("COMMAND_FAILED"); break;
+ case FLASH_WRITE_ERR: loader_port_debug_print("FLASH_WRITE_ERR"); break;
+ case FLASH_READ_ERR: loader_port_debug_print("FLASH_READ_ERR"); break;
+ case READ_LENGTH_ERR: loader_port_debug_print("READ_LENGTH_ERR"); break;
+ case DEFLATE_ERROR: loader_port_debug_print("DEFLATE_ERROR"); break;
+ default: loader_port_debug_print("UNKNOWN ERROR"); break;
+ }
+
+ loader_port_debug_print("\n");
+}
+
+
+esp_loader_error_t loader_flash_begin_cmd(uint32_t offset,
+ uint32_t erase_size,
+ uint32_t block_size,
+ uint32_t blocks_to_write,
+ bool encryption)
+{
+ uint32_t encryption_size = encryption ? sizeof(uint32_t) : 0;
+
+ flash_begin_command_t flash_begin_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = FLASH_BEGIN,
+ .size = CMD_SIZE(flash_begin_cmd) - encryption_size,
+ .checksum = 0
+ },
+ .erase_size = erase_size,
+ .packet_count = blocks_to_write,
+ .packet_size = block_size,
+ .offset = offset,
+ .encrypted = 0
+ };
+
+ s_sequence_number = 0;
+
+ return send_cmd(&flash_begin_cmd, sizeof(flash_begin_cmd) - encryption_size, NULL);
+}
+
+
+esp_loader_error_t loader_flash_data_cmd(const uint8_t *data, uint32_t size)
+{
+ data_command_t data_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = FLASH_DATA,
+ .size = CMD_SIZE(data_cmd) + size,
+ .checksum = compute_checksum(data, size)
+ },
+ .data_size = size,
+ .sequence_number = s_sequence_number++,
+ };
+
+ return send_cmd_with_data(&data_cmd, sizeof(data_cmd), data, size);
+}
+
+
+esp_loader_error_t loader_flash_end_cmd(bool stay_in_loader)
+{
+ flash_end_command_t end_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = FLASH_END,
+ .size = CMD_SIZE(end_cmd),
+ .checksum = 0
+ },
+ .stay_in_loader = stay_in_loader
+ };
+
+ return send_cmd(&end_cmd, sizeof(end_cmd), NULL);
+}
+
+
+esp_loader_error_t loader_mem_begin_cmd(uint32_t offset, uint32_t size, uint32_t blocks_to_write, uint32_t block_size)
+{
+
+ mem_begin_command_t mem_begin_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = MEM_BEGIN,
+ .size = CMD_SIZE(mem_begin_cmd),
+ .checksum = 0
+ },
+ .total_size = size,
+ .blocks = blocks_to_write,
+ .block_size = block_size,
+ .offset = offset
+ };
+
+ s_sequence_number = 0;
+
+ return send_cmd(&mem_begin_cmd, sizeof(mem_begin_cmd), NULL);
+}
+
+
+esp_loader_error_t loader_mem_data_cmd(const uint8_t *data, uint32_t size)
+{
+ data_command_t data_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = MEM_DATA,
+ .size = CMD_SIZE(data_cmd) + size,
+ .checksum = compute_checksum(data, size)
+ },
+ .data_size = size,
+ .sequence_number = s_sequence_number++,
+ };
+ return send_cmd_with_data(&data_cmd, sizeof(data_cmd), data, size);
+}
+
+esp_loader_error_t loader_mem_end_cmd(uint32_t entrypoint)
+{
+ mem_end_command_t end_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = MEM_END,
+ .size = CMD_SIZE(end_cmd),
+ },
+ .stay_in_loader = (entrypoint == 0),
+ .entry_point_address = entrypoint
+ };
+
+ return send_cmd(&end_cmd, sizeof(end_cmd), NULL);
+}
+
+
+esp_loader_error_t loader_sync_cmd(void)
+{
+ sync_command_t sync_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = SYNC,
+ .size = CMD_SIZE(sync_cmd),
+ .checksum = 0
+ },
+ .sync_sequence = {
+ 0x07, 0x07, 0x12, 0x20,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ }
+ };
+
+ return send_cmd(&sync_cmd, sizeof(sync_cmd), NULL);
+}
+
+
+esp_loader_error_t loader_write_reg_cmd(uint32_t address, uint32_t value,
+ uint32_t mask, uint32_t delay_us)
+{
+ write_reg_command_t write_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = WRITE_REG,
+ .size = CMD_SIZE(write_cmd),
+ .checksum = 0
+ },
+ .address = address,
+ .value = value,
+ .mask = mask,
+ .delay_us = delay_us
+ };
+
+ return send_cmd(&write_cmd, sizeof(write_cmd), NULL);
+}
+
+
+esp_loader_error_t loader_read_reg_cmd(uint32_t address, uint32_t *reg)
+{
+ read_reg_command_t read_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = READ_REG,
+ .size = CMD_SIZE(read_cmd),
+ .checksum = 0
+ },
+ .address = address,
+ };
+
+ return send_cmd(&read_cmd, sizeof(read_cmd), reg);
+}
+
+
+esp_loader_error_t loader_spi_attach_cmd(uint32_t config)
+{
+ spi_attach_command_t attach_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = SPI_ATTACH,
+ .size = CMD_SIZE(attach_cmd),
+ .checksum = 0
+ },
+ .configuration = config,
+ .zero = 0
+ };
+
+ return send_cmd(&attach_cmd, sizeof(attach_cmd), NULL);
+}
+
+esp_loader_error_t loader_change_baudrate_cmd(uint32_t baudrate)
+{
+ change_baudrate_command_t baudrate_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = CHANGE_BAUDRATE,
+ .size = CMD_SIZE(baudrate_cmd),
+ .checksum = 0
+ },
+ .new_baudrate = baudrate,
+ .old_baudrate = 0 // ESP32 ROM only
+ };
+
+ return send_cmd(&baudrate_cmd, sizeof(baudrate_cmd), NULL);
+}
+
+esp_loader_error_t loader_md5_cmd(uint32_t address, uint32_t size, uint8_t *md5_out)
+{
+ spi_flash_md5_command_t md5_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = SPI_FLASH_MD5,
+ .size = CMD_SIZE(md5_cmd),
+ .checksum = 0
+ },
+ .address = address,
+ .size = size,
+ .reserved_0 = 0,
+ .reserved_1 = 0
+ };
+
+ return send_cmd_md5(&md5_cmd, sizeof(md5_cmd), md5_out);
+}
+
+esp_loader_error_t loader_spi_parameters(uint32_t total_size)
+{
+ write_spi_command_t spi_cmd = {
+ .common = {
+ .direction = WRITE_DIRECTION,
+ .command = SPI_SET_PARAMS,
+ .size = 24,
+ .checksum = 0
+ },
+ .id = 0,
+ .total_size = total_size,
+ .block_size = 64 * 1024,
+ .sector_size = 4 * 1024,
+ .page_size = 0x100,
+ .status_mask = 0xFFFF,
+ };
+
+ return send_cmd(&spi_cmd, sizeof(spi_cmd), NULL);
+}
+
+__attribute__ ((weak)) void loader_port_debug_print(const char *str)
+{
+ (void)(str);
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/src/protocol_spi.c b/applications/external/esp_flasher/lib/esp-serial-flasher/src/protocol_spi.c
new file mode 100644
index 000000000..bd04fe79f
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/src/protocol_spi.c
@@ -0,0 +1,312 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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 "protocol.h"
+#include "protocol_prv.h"
+#include "esp_loader_io.h"
+#include
+#include
+
+typedef struct __attribute__((packed)) {
+ uint8_t cmd;
+ uint8_t addr;
+ uint8_t dummy;
+} transaction_preamble_t;
+
+typedef enum {
+ TRANS_CMD_WRBUF = 0x01,
+ TRANS_CMD_RDBUF = 0x02,
+ TRANS_CMD_WRDMA = 0x03,
+ TRANS_CMD_RDDMA = 0x04,
+ TRANS_CMD_SEG_DONE = 0x05,
+ TRANS_CMD_ENQPI = 0x06,
+ TRANS_CMD_WR_DONE = 0x07,
+ TRANS_CMD_CMD8 = 0x08,
+ TRANS_CMD_CMD9 = 0x09,
+ TRANS_CMD_CMDA = 0x0A,
+ TRANS_CMD_EXQPI = 0xDD,
+} transaction_cmd_t;
+
+/* Slave protocol registers */
+typedef enum {
+ SLAVE_REGISTER_VER = 0,
+ SLAVE_REGISTER_RXSTA = 4,
+ SLAVE_REGISTER_TXSTA = 8,
+ SLAVE_REGISTER_CMD = 12,
+} slave_register_addr_t;
+
+#define SLAVE_STA_TOGGLE_BIT (0x01U << 0)
+#define SLAVE_STA_INIT_BIT (0x01U << 1)
+#define SLAVE_STA_BUF_LENGTH_POS 2U
+
+typedef enum {
+ SLAVE_STATE_INIT = SLAVE_STA_TOGGLE_BIT | SLAVE_STA_INIT_BIT,
+ SLAVE_STATE_FIRST_PACKET = SLAVE_STA_INIT_BIT,
+} slave_state_t;
+
+typedef enum {
+ /* Target to host */
+ SLAVE_CMD_IDLE = 0xAA,
+ SLAVE_CMD_READY = 0xA5,
+ /* Host to target */
+ SLAVE_CMD_REBOOT = 0xFE,
+ SLAVE_CMD_COMM_REINIT = 0x5A,
+ SLAVE_CMD_DONE = 0x55,
+} slave_cmd_t;
+
+static uint8_t s_slave_seq_tx;
+static uint8_t s_slave_seq_rx;
+
+static esp_loader_error_t write_slave_reg(const uint8_t *data, const uint32_t addr,
+ const uint8_t size);
+static esp_loader_error_t read_slave_reg(uint8_t *out_data, const uint32_t addr,
+ const uint8_t size);
+static esp_loader_error_t handle_slave_state(const uint32_t status_reg_addr, uint8_t *seq_state,
+ bool *slave_ready, uint32_t *buf_size);
+static esp_loader_error_t check_response(command_t cmd, uint32_t *reg_value);
+
+esp_loader_error_t loader_initialize_conn(esp_loader_connect_args_t *connect_args)
+{
+ for (uint8_t trial = 0; trial < connect_args->trials; trial++) {
+ uint8_t slave_ready_flag;
+ RETURN_ON_ERROR(read_slave_reg(&slave_ready_flag, SLAVE_REGISTER_CMD,
+ sizeof(slave_ready_flag)));
+
+ if (slave_ready_flag != SLAVE_CMD_IDLE) {
+ loader_port_debug_print("Waiting for Slave to be idle...\n");
+ loader_port_delay_ms(100);
+ } else {
+ break;
+ }
+ }
+
+ const uint8_t reg_val = SLAVE_CMD_READY;
+ RETURN_ON_ERROR(write_slave_reg(®_val, SLAVE_REGISTER_CMD, sizeof(reg_val)));
+
+ for (uint8_t trial = 0; trial < connect_args->trials; trial++) {
+ uint8_t slave_ready_flag;
+ RETURN_ON_ERROR(read_slave_reg(&slave_ready_flag, SLAVE_REGISTER_CMD,
+ sizeof(slave_ready_flag)));
+
+ if (slave_ready_flag != SLAVE_CMD_READY) {
+ loader_port_debug_print("Waiting for Slave to be ready...\n");
+ loader_port_delay_ms(100);
+ } else {
+ break;
+ }
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+esp_loader_error_t send_cmd(const void *cmd_data, uint32_t size, uint32_t *reg_value)
+{
+ command_t command = ((const command_common_t *)cmd_data)->command;
+
+ uint32_t buf_size;
+ bool slave_ready = false;
+ while (!slave_ready) {
+ RETURN_ON_ERROR(handle_slave_state(SLAVE_REGISTER_RXSTA, &s_slave_seq_rx, &slave_ready,
+ &buf_size));
+ }
+
+ if (size > buf_size) {
+ return ESP_LOADER_ERROR_INVALID_PARAM;
+ }
+
+ /* Start and write the command */
+ transaction_preamble_t preamble = {.cmd = TRANS_CMD_WRDMA};
+
+ loader_port_spi_set_cs(0);
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)&preamble, sizeof(preamble),
+ loader_port_remaining_time()));
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)cmd_data, size,
+ loader_port_remaining_time()));
+ loader_port_spi_set_cs(1);
+
+ /* Terminate the write */
+ loader_port_spi_set_cs(0);
+ preamble.cmd = TRANS_CMD_WR_DONE;
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)&preamble, sizeof(preamble),
+ loader_port_remaining_time()));
+ loader_port_spi_set_cs(1);
+
+ return check_response(command, reg_value);
+}
+
+
+esp_loader_error_t send_cmd_with_data(const void *cmd_data, size_t cmd_size,
+ const void *data, size_t data_size)
+{
+ uint32_t buf_size;
+ bool slave_ready = false;
+ while (!slave_ready) {
+ RETURN_ON_ERROR(handle_slave_state(SLAVE_REGISTER_RXSTA, &s_slave_seq_rx, &slave_ready,
+ &buf_size));
+ }
+
+ if (cmd_size + data_size > buf_size) {
+ return ESP_LOADER_ERROR_INVALID_PARAM;
+ }
+
+ /* Start and write the command and the data */
+ transaction_preamble_t preamble = {.cmd = TRANS_CMD_WRDMA};
+
+ loader_port_spi_set_cs(0);
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)&preamble, sizeof(preamble),
+ loader_port_remaining_time()));
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)cmd_data, cmd_size,
+ loader_port_remaining_time()));
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)data, data_size,
+ loader_port_remaining_time()));
+ loader_port_spi_set_cs(1);
+
+ /* Terminate the write */
+ loader_port_spi_set_cs(0);
+ preamble.cmd = TRANS_CMD_WR_DONE;
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)&preamble, sizeof(preamble),
+ loader_port_remaining_time()));
+ loader_port_spi_set_cs(1);
+
+ command_t command = ((const command_common_t *)cmd_data)->command;
+ return check_response(command, NULL);
+}
+
+
+static esp_loader_error_t read_slave_reg(uint8_t *out_data, const uint32_t addr,
+ const uint8_t size)
+{
+ transaction_preamble_t preamble = {
+ .cmd = TRANS_CMD_RDBUF,
+ .addr = addr,
+ };
+
+ loader_port_spi_set_cs(0);
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)&preamble, sizeof(preamble),
+ loader_port_remaining_time()));
+ RETURN_ON_ERROR(loader_port_read(out_data, size, loader_port_remaining_time()));
+ loader_port_spi_set_cs(1);
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+static esp_loader_error_t write_slave_reg(const uint8_t *data, const uint32_t addr,
+ const uint8_t size)
+{
+ transaction_preamble_t preamble = {
+ .cmd = TRANS_CMD_WRBUF,
+ .addr = addr,
+ };
+
+ loader_port_spi_set_cs(0);
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)&preamble, sizeof(preamble),
+ loader_port_remaining_time()));
+ RETURN_ON_ERROR(loader_port_write(data, size, loader_port_remaining_time()));
+ loader_port_spi_set_cs(1);
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+static esp_loader_error_t handle_slave_state(const uint32_t status_reg_addr, uint8_t *seq_state,
+ bool *slave_ready, uint32_t *buf_size)
+{
+ uint32_t status_reg;
+ RETURN_ON_ERROR(read_slave_reg((uint8_t *)&status_reg, status_reg_addr,
+ sizeof(status_reg)));
+ const slave_state_t state = status_reg & (SLAVE_STA_TOGGLE_BIT | SLAVE_STA_INIT_BIT);
+
+ switch(state) {
+ case SLAVE_STATE_INIT: {
+ const uint32_t initial = 0U;
+ RETURN_ON_ERROR(write_slave_reg((uint8_t *)&initial, status_reg_addr, sizeof(initial)));
+ break;
+ }
+
+ case SLAVE_STATE_FIRST_PACKET: {
+ *seq_state = state & SLAVE_STA_TOGGLE_BIT;
+ *buf_size = status_reg >> SLAVE_STA_BUF_LENGTH_POS;
+ *slave_ready = true;
+ break;
+ }
+
+ default: {
+ const uint8_t new_seq = state & SLAVE_STA_TOGGLE_BIT;
+ if (new_seq != *seq_state) {
+ *seq_state = new_seq;
+ *buf_size = status_reg >> SLAVE_STA_BUF_LENGTH_POS;
+ *slave_ready = true;
+ }
+ break;
+ }
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+static esp_loader_error_t check_response(command_t cmd, uint32_t *reg_value)
+{
+ response_t resp;
+
+ uint32_t buf_size;
+ bool slave_ready = false;
+ while (!slave_ready) {
+ RETURN_ON_ERROR(handle_slave_state(SLAVE_REGISTER_TXSTA, &s_slave_seq_tx, &slave_ready,
+ &buf_size));
+ }
+
+ if (sizeof(resp) > buf_size) {
+ return ESP_LOADER_ERROR_INVALID_PARAM;
+ }
+
+ transaction_preamble_t preamble = {
+ .cmd = TRANS_CMD_RDDMA,
+ };
+
+ loader_port_spi_set_cs(0);
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)&preamble, sizeof(preamble),
+ loader_port_remaining_time()));
+ RETURN_ON_ERROR(loader_port_read((uint8_t *)&resp, sizeof(resp),
+ loader_port_remaining_time()));
+ loader_port_spi_set_cs(1);
+
+ /* Terminate the read */
+ loader_port_spi_set_cs(0);
+ preamble.cmd = TRANS_CMD_CMD8;
+ RETURN_ON_ERROR(loader_port_write((const uint8_t *)&preamble, sizeof(preamble),
+ loader_port_remaining_time()));
+ loader_port_spi_set_cs(1);
+
+ common_response_t *common = (common_response_t *)&resp;
+ if ((common->direction != READ_DIRECTION) || (common->command != cmd)) {
+ return ESP_LOADER_ERROR_INVALID_RESPONSE;
+ }
+
+ response_status_t *status =
+ (response_status_t *)((uint8_t *)&resp + sizeof(resp) - sizeof(response_status_t));
+ if (status->failed) {
+ log_loader_internal_error(status->error);
+ return ESP_LOADER_ERROR_INVALID_RESPONSE;
+ }
+
+ if (reg_value != NULL) {
+ *reg_value = common->value;
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/src/protocol_uart.c b/applications/external/esp_flasher/lib/esp-serial-flasher/src/protocol_uart.c
new file mode 100644
index 000000000..c5a51cec6
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/src/protocol_uart.c
@@ -0,0 +1,114 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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 "protocol.h"
+#include "protocol_prv.h"
+#include "esp_loader_io.h"
+#include "slip.h"
+#include
+#include
+
+static esp_loader_error_t check_response(command_t cmd, uint32_t *reg_value, void* resp, uint32_t resp_size);
+
+esp_loader_error_t loader_initialize_conn(esp_loader_connect_args_t *connect_args) {
+ esp_loader_error_t err;
+ int32_t trials = connect_args->trials;
+
+ do {
+ loader_port_start_timer(connect_args->sync_timeout);
+ err = loader_sync_cmd();
+ if (err == ESP_LOADER_ERROR_TIMEOUT) {
+ if (--trials == 0) {
+ return ESP_LOADER_ERROR_TIMEOUT;
+ }
+ loader_port_delay_ms(100);
+ } else if (err != ESP_LOADER_SUCCESS) {
+ return err;
+ }
+ } while (err != ESP_LOADER_SUCCESS);
+
+ return err;
+}
+
+esp_loader_error_t send_cmd(const void *cmd_data, uint32_t size, uint32_t *reg_value)
+{
+ response_t response;
+ command_t command = ((const command_common_t *)cmd_data)->command;
+
+ RETURN_ON_ERROR( SLIP_send_delimiter() );
+ RETURN_ON_ERROR( SLIP_send((const uint8_t *)cmd_data, size) );
+ RETURN_ON_ERROR( SLIP_send_delimiter() );
+
+ return check_response(command, reg_value, &response, sizeof(response));
+}
+
+
+esp_loader_error_t send_cmd_with_data(const void *cmd_data, size_t cmd_size,
+ const void *data, size_t data_size)
+{
+ response_t response;
+ command_t command = ((const command_common_t *)cmd_data)->command;
+
+ RETURN_ON_ERROR( SLIP_send_delimiter() );
+ RETURN_ON_ERROR( SLIP_send((const uint8_t *)cmd_data, cmd_size) );
+ RETURN_ON_ERROR( SLIP_send(data, data_size) );
+ RETURN_ON_ERROR( SLIP_send_delimiter() );
+
+ return check_response(command, NULL, &response, sizeof(response));
+}
+
+
+esp_loader_error_t send_cmd_md5(const void *cmd_data, size_t cmd_size, uint8_t md5_out[MD5_SIZE])
+{
+ rom_md5_response_t response;
+ command_t command = ((const command_common_t *)cmd_data)->command;
+
+ RETURN_ON_ERROR( SLIP_send_delimiter() );
+ RETURN_ON_ERROR( SLIP_send((const uint8_t *)cmd_data, cmd_size) );
+ RETURN_ON_ERROR( SLIP_send_delimiter() );
+
+ RETURN_ON_ERROR( check_response(command, NULL, &response, sizeof(response)) );
+
+ memcpy(md5_out, response.md5, MD5_SIZE);
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+static esp_loader_error_t check_response(command_t cmd, uint32_t *reg_value, void* resp, uint32_t resp_size)
+{
+ esp_loader_error_t err;
+ common_response_t *response = (common_response_t *)resp;
+
+ do {
+ err = SLIP_receive_packet(resp, resp_size);
+ if (err != ESP_LOADER_SUCCESS) {
+ return err;
+ }
+ } while ((response->direction != READ_DIRECTION) || (response->command != cmd));
+
+ response_status_t *status = (response_status_t *)((uint8_t *)resp + resp_size - sizeof(response_status_t));
+
+ if (status->failed) {
+ log_loader_internal_error(status->error);
+ return ESP_LOADER_ERROR_INVALID_RESPONSE;
+ }
+
+ if (reg_value != NULL) {
+ *reg_value = response->value;
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/src/slip.c b/applications/external/esp_flasher/lib/esp-serial-flasher/src/slip.c
new file mode 100644
index 000000000..ba926169c
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/src/slip.c
@@ -0,0 +1,125 @@
+/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * 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 "slip.h"
+#include "esp_loader_io.h"
+
+static const uint8_t DELIMITER = 0xC0;
+static const uint8_t C0_REPLACEMENT[2] = {0xDB, 0xDC};
+static const uint8_t DB_REPLACEMENT[2] = {0xDB, 0xDD};
+
+static inline esp_loader_error_t peripheral_read(uint8_t *buff, const size_t size)
+{
+ return loader_port_read(buff, size, loader_port_remaining_time());
+}
+
+static inline esp_loader_error_t peripheral_write(const uint8_t *buff, const size_t size)
+{
+ return loader_port_write(buff, size, loader_port_remaining_time());
+}
+
+esp_loader_error_t SLIP_receive_data(uint8_t *buff, const size_t size)
+{
+ uint8_t ch;
+
+ for (uint32_t i = 0; i < size; i++) {
+ RETURN_ON_ERROR( peripheral_read(&ch, 1) );
+
+ if (ch == 0xDB) {
+ RETURN_ON_ERROR( peripheral_read(&ch, 1) );
+ if (ch == 0xDC) {
+ buff[i] = 0xC0;
+ } else if (ch == 0xDD) {
+ buff[i] = 0xDB;
+ } else {
+ return ESP_LOADER_ERROR_INVALID_RESPONSE;
+ }
+ } else {
+ buff[i] = ch;
+ }
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+esp_loader_error_t SLIP_receive_packet(uint8_t *buff, const size_t size)
+{
+ uint8_t ch;
+
+ // Wait for delimiter
+ do {
+ RETURN_ON_ERROR( peripheral_read(&ch, 1) );
+ } while (ch != DELIMITER);
+
+ // Workaround: bootloader sends two dummy(0xC0) bytes after response when baud rate is changed.
+ do {
+ RETURN_ON_ERROR( peripheral_read(&ch, 1) );
+ } while (ch == DELIMITER);
+
+ buff[0] = ch;
+
+ RETURN_ON_ERROR( SLIP_receive_data(&buff[1], size - 1) );
+
+ // Wait for delimiter
+ do {
+ RETURN_ON_ERROR( peripheral_read(&ch, 1) );
+ } while (ch != DELIMITER);
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+esp_loader_error_t SLIP_send(const uint8_t *data, const size_t size)
+{
+ uint32_t to_write = 0; // Bytes ready to write as they are
+ uint32_t written = 0; // Bytes already written
+
+ for (uint32_t i = 0; i < size; i++) {
+ if (data[i] != 0xC0 && data[i] != 0xDB) {
+ to_write++; // Queue this byte for writing
+ continue;
+ }
+
+ // We have a byte that needs encoding, write the queue first
+ if (to_write > 0) {
+ RETURN_ON_ERROR( peripheral_write(&data[written], to_write) );
+ }
+
+ // Write the encoded byte
+ if (data[i] == 0xC0) {
+ RETURN_ON_ERROR( peripheral_write(C0_REPLACEMENT, 2) );
+ } else {
+ RETURN_ON_ERROR( peripheral_write(DB_REPLACEMENT, 2) );
+ }
+
+ // Update to start again after the encoded byte
+ written = i + 1;
+ to_write = 0;
+ }
+
+ // Write the rest of the bytes that didn't need encoding
+ if (to_write > 0) {
+ RETURN_ON_ERROR( peripheral_write(&data[written], to_write) );
+ }
+
+ return ESP_LOADER_SUCCESS;
+}
+
+
+esp_loader_error_t SLIP_send_delimiter(void)
+{
+ return peripheral_write(&DELIMITER, 1);
+}
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/submodules/CMakeLists.txt b/applications/external/esp_flasher/lib/esp-serial-flasher/submodules/CMakeLists.txt
new file mode 100644
index 000000000..59e665ac2
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/submodules/CMakeLists.txt
@@ -0,0 +1,20 @@
+
+cmake_minimum_required(VERSION 3.13)
+
+set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/stm32-cmake/cmake/gcc_stm32.cmake)
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/stm32-cmake/cmake)
+
+find_package(CMSIS REQUIRED)
+find_package(STM32HAL COMPONENTS gpio tim uart REQUIRED)
+
+add_library(stm_cube_impl ${CMSIS_SOURCES} ${STM32HAL_SOURCES})
+target_include_directories(stm_cube_impl PUBLIC ${CMSIS_INCLUDE_DIRS} ${STM32HAL_INCLUDE_DIR})
+stm32_set_target_properties(stm_cube_impl)
+
+# stm_cube target is made to propagate properties of stm_cube_impl, as stm32_set_target_properties
+# sets properties privately for given target. This eliminates need to call stm32_set_target_properties
+# on every target that links against STM32HAL.
+add_library(stm_cube INTERFACE)
+target_link_libraries(stm_cube INTERFACE stm_cube_impl)
+target_compile_definitions(stm_cube INTERFACE $)
+target_link_options(stm_cube INTERFACE -T${CMAKE_CURRENT_BINARY_DIR}/stm_cube_impl_flash.ld)
\ No newline at end of file
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/zephyr/CMakeLists.txt b/applications/external/esp_flasher/lib/esp-serial-flasher/zephyr/CMakeLists.txt
new file mode 100644
index 000000000..97da4eaae
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/zephyr/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 3.5)
+
+if (CONFIG_ESP_SERIAL_FLASHER)
+ zephyr_include_directories(
+ "${ZEPHYR_CURRENT_MODULE_DIR}/include"
+ "${ZEPHYR_CURRENT_MODULE_DIR}/port"
+ "${ZEPHYR_CURRENT_MODULE_DIR}/private_include"
+ )
+
+ zephyr_interface_library_named(esp_flasher)
+
+ zephyr_library()
+
+ zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/src/esp_loader.c
+ ${ZEPHYR_CURRENT_MODULE_DIR}/src/esp_targets.c
+ ${ZEPHYR_CURRENT_MODULE_DIR}/src/protocol_common.c
+ ${ZEPHYR_CURRENT_MODULE_DIR}/src/protocol_uart.c
+ ${ZEPHYR_CURRENT_MODULE_DIR}/src/slip.c
+ ${ZEPHYR_CURRENT_MODULE_DIR}/src/md5_hash.c
+ ${ZEPHYR_CURRENT_MODULE_DIR}/port/zephyr_port.c
+ )
+
+ target_compile_definitions(esp_flasher INTERFACE SERIAL_FLASHER_INTERFACE_UART)
+
+ zephyr_library_link_libraries(esp_flasher)
+
+ if(DEFINED MD5_ENABLED OR CONFIG_SERIAL_FLASHER_MD5_ENABLED)
+ target_compile_definitions(esp_flasher INTERFACE -DMD5_ENABLED=1)
+ endif()
+endif()
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/zephyr/Kconfig b/applications/external/esp_flasher/lib/esp-serial-flasher/zephyr/Kconfig
new file mode 100644
index 000000000..ebb524c86
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/zephyr/Kconfig
@@ -0,0 +1,16 @@
+config ESP_SERIAL_FLASHER
+ bool "Enable ESP serial flasher library"
+ default y
+ select CONSOLE_SUBSYS
+ help
+ Select this option to enable the ESP serial flasher library.
+
+config ESP_SERIAL_FLASHER_UART_BUFSIZE
+ int "ESP Serial Flasher UART buffer size"
+ default 512
+ help
+ Buffer size for UART TX and RX packets
+
+if ESP_SERIAL_FLASHER
+ rsource "../Kconfig"
+endif
diff --git a/applications/external/esp_flasher/lib/esp-serial-flasher/zephyr/module.yml b/applications/external/esp_flasher/lib/esp-serial-flasher/zephyr/module.yml
new file mode 100644
index 000000000..01d484fcb
--- /dev/null
+++ b/applications/external/esp_flasher/lib/esp-serial-flasher/zephyr/module.yml
@@ -0,0 +1,5 @@
+name: esp-flasher
+
+build:
+ cmake: zephyr
+ kconfig: zephyr/Kconfig
diff --git a/applications/external/esp_flasher/scenes/esp_flasher_scene.c b/applications/external/esp_flasher/scenes/esp_flasher_scene.c
new file mode 100644
index 000000000..c3fc13ade
--- /dev/null
+++ b/applications/external/esp_flasher/scenes/esp_flasher_scene.c
@@ -0,0 +1,30 @@
+#include "esp_flasher_scene.h"
+
+// Generate scene on_enter handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
+void (*const esp_flasher_scene_on_enter_handlers[])(void*) = {
+#include "esp_flasher_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 esp_flasher_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
+#include "esp_flasher_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 esp_flasher_scene_on_exit_handlers[])(void* context) = {
+#include "esp_flasher_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Initialize scene handlers configuration structure
+const SceneManagerHandlers esp_flasher_scene_handlers = {
+ .on_enter_handlers = esp_flasher_scene_on_enter_handlers,
+ .on_event_handlers = esp_flasher_scene_on_event_handlers,
+ .on_exit_handlers = esp_flasher_scene_on_exit_handlers,
+ .scene_num = EspFlasherSceneNum,
+};
diff --git a/applications/external/esp_flasher/scenes/esp_flasher_scene.h b/applications/external/esp_flasher/scenes/esp_flasher_scene.h
new file mode 100644
index 000000000..f1fc0916f
--- /dev/null
+++ b/applications/external/esp_flasher/scenes/esp_flasher_scene.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include
+
+// Generate scene id and total number
+#define ADD_SCENE(prefix, name, id) EspFlasherScene##id,
+typedef enum {
+#include "esp_flasher_scene_config.h"
+ EspFlasherSceneNum,
+} EspFlasherScene;
+#undef ADD_SCENE
+
+extern const SceneManagerHandlers esp_flasher_scene_handlers;
+
+// Generate scene on_enter handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
+#include "esp_flasher_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 "esp_flasher_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 "esp_flasher_scene_config.h"
+#undef ADD_SCENE
diff --git a/applications/external/esp_flasher/scenes/esp_flasher_scene_about.c b/applications/external/esp_flasher/scenes/esp_flasher_scene_about.c
new file mode 100644
index 000000000..e778b2bf7
--- /dev/null
+++ b/applications/external/esp_flasher/scenes/esp_flasher_scene_about.c
@@ -0,0 +1,56 @@
+#include "../esp_flasher_app_i.h"
+
+void esp_flasher_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) {
+ EspFlasherApp* app = context;
+ if(type == InputTypeShort) {
+ view_dispatcher_send_custom_event(app->view_dispatcher, result);
+ }
+}
+
+#define ESP_FLASHER_APP_DESCRIPTION \
+ "\e#Information\nVersion: " ESP_FLASHER_APP_VERSION \
+ "\nDeveloped by: 0xchocolate\n(@cococode on discord) using espressif's esp-serial-flasher library\nGithub: https://github.com/0xchocolate/flipperzero-esp-flasher\n\n\e#Description\nApp to flash ESP chips from\nthe flipper (over UART) using\nbin files on the sd card.\nReset the chip into bootloader\nmode before flashing.\n\n Supported targets:\n- ESP32\n- ESP8266\n- ESP32-S2\n- ESP32-S3\n- ESP32-C3\n- ESP32-C2\n- ESP32-H2"
+
+void esp_flasher_scene_about_on_enter(void* context) {
+ EspFlasherApp* app = context;
+
+ 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! ESP Flasher \e!\n",
+ false);
+ widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, ESP_FLASHER_APP_DESCRIPTION);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, EspFlasherAppViewWidget);
+}
+
+bool esp_flasher_scene_about_on_event(void* context, SceneManagerEvent event) {
+ EspFlasherApp* app = context;
+ bool consumed = false;
+ UNUSED(app);
+ UNUSED(event);
+
+ return consumed;
+}
+
+void esp_flasher_scene_about_on_exit(void* context) {
+ EspFlasherApp* app = context;
+
+ // Clear views
+ widget_reset(app->widget);
+}
\ No newline at end of file
diff --git a/applications/external/esp_flasher/scenes/esp_flasher_scene_browse.c b/applications/external/esp_flasher/scenes/esp_flasher_scene_browse.c
new file mode 100644
index 000000000..88a9b25e4
--- /dev/null
+++ b/applications/external/esp_flasher/scenes/esp_flasher_scene_browse.c
@@ -0,0 +1,266 @@
+#include "../esp_flasher_app_i.h"
+#include "../esp_flasher_worker.h"
+
+enum SubmenuIndex {
+ SubmenuIndexS3Mode,
+ SubmenuIndexBoot,
+ SubmenuIndexPart,
+ SubmenuIndexNvs,
+ SubmenuIndexBootApp0,
+ SubmenuIndexApp,
+ SubmenuIndexCustom,
+ SubmenuIndexFlash,
+};
+
+static void esp_flasher_scene_browse_callback(void* context, uint32_t index) {
+ EspFlasherApp* app = context;
+
+ scene_manager_set_scene_state(app->scene_manager, EspFlasherSceneBrowse, index);
+
+ // browse for files
+ FuriString* predefined_filepath = furi_string_alloc_set_str(ESP_APP_FOLDER);
+ FuriString* selected_filepath = furi_string_alloc();
+ DialogsFileBrowserOptions browser_options;
+ dialog_file_browser_set_basic_options(&browser_options, ".bin", &I_Text_10x10);
+
+ // TODO refactor
+ switch(index) {
+ case SubmenuIndexS3Mode:
+ // toggle S3 mode
+ app->selected_flash_options[SelectedFlashS3Mode] =
+ !app->selected_flash_options[SelectedFlashS3Mode];
+ view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
+ break;
+ case SubmenuIndexBoot:
+ app->selected_flash_options[SelectedFlashBoot] =
+ !app->selected_flash_options[SelectedFlashBoot];
+ if(app->selected_flash_options[SelectedFlashBoot]) {
+ if(dialog_file_browser_show(
+ app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
+ strncpy(
+ app->bin_file_path_boot,
+ furi_string_get_cstr(selected_filepath),
+ sizeof(app->bin_file_path_boot));
+ }
+ }
+ if(app->bin_file_path_boot[0] == '\0') {
+ // if user didn't select a file, leave unselected
+ app->selected_flash_options[SelectedFlashBoot] = false;
+ }
+ view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
+ break;
+ case SubmenuIndexPart:
+ app->selected_flash_options[SelectedFlashPart] =
+ !app->selected_flash_options[SelectedFlashPart];
+ if(dialog_file_browser_show(
+ app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
+ strncpy(
+ app->bin_file_path_part,
+ furi_string_get_cstr(selected_filepath),
+ sizeof(app->bin_file_path_part));
+ }
+ if(app->bin_file_path_part[0] == '\0') {
+ // if user didn't select a file, leave unselected
+ app->selected_flash_options[SelectedFlashPart] = false;
+ }
+ view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
+ break;
+ case SubmenuIndexNvs:
+ app->selected_flash_options[SelectedFlashNvs] =
+ !app->selected_flash_options[SelectedFlashNvs];
+ if(dialog_file_browser_show(
+ app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
+ strncpy(
+ app->bin_file_path_nvs,
+ furi_string_get_cstr(selected_filepath),
+ sizeof(app->bin_file_path_nvs));
+ }
+ if(app->bin_file_path_nvs[0] == '\0') {
+ // if user didn't select a file, leave unselected
+ app->selected_flash_options[SelectedFlashNvs] = false;
+ }
+ view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
+ break;
+ case SubmenuIndexBootApp0:
+ app->selected_flash_options[SelectedFlashBootApp0] =
+ !app->selected_flash_options[SelectedFlashBootApp0];
+ if(dialog_file_browser_show(
+ app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
+ strncpy(
+ app->bin_file_path_boot_app0,
+ furi_string_get_cstr(selected_filepath),
+ sizeof(app->bin_file_path_boot_app0));
+ }
+ if(app->bin_file_path_boot_app0[0] == '\0') {
+ // if user didn't select a file, leave unselected
+ app->selected_flash_options[SelectedFlashBootApp0] = false;
+ }
+ view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
+ break;
+ case SubmenuIndexApp:
+ app->selected_flash_options[SelectedFlashApp] =
+ !app->selected_flash_options[SelectedFlashApp];
+ if(dialog_file_browser_show(
+ app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
+ strncpy(
+ app->bin_file_path_app,
+ furi_string_get_cstr(selected_filepath),
+ sizeof(app->bin_file_path_app));
+ }
+ if(app->bin_file_path_app[0] == '\0') {
+ // if user didn't select a file, leave unselected
+ app->selected_flash_options[SelectedFlashApp] = false;
+ }
+ view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
+ break;
+ case SubmenuIndexCustom:
+ app->selected_flash_options[SelectedFlashCustom] =
+ !app->selected_flash_options[SelectedFlashCustom];
+ if(dialog_file_browser_show(
+ app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
+ strncpy(
+ app->bin_file_path_custom,
+ furi_string_get_cstr(selected_filepath),
+ sizeof(app->bin_file_path_custom));
+ }
+ if(app->bin_file_path_custom[0] == '\0') {
+ // if user didn't select a file, leave unselected
+ app->selected_flash_options[SelectedFlashCustom] = false;
+ }
+ view_dispatcher_send_custom_event(app->view_dispatcher, EspFlasherEventRefreshSubmenu);
+ break;
+ case SubmenuIndexFlash:
+ // count how many options are selected
+ app->num_selected_flash_options = 0;
+ for(bool* option = &app->selected_flash_options[SelectedFlashBoot];
+ option < &app->selected_flash_options[NUM_FLASH_OPTIONS];
+ ++option) {
+ if(*option) {
+ ++app->num_selected_flash_options;
+ }
+ }
+ if(app->num_selected_flash_options) {
+ // only start next scene if at least one option is selected
+ scene_manager_next_scene(app->scene_manager, EspFlasherSceneConsoleOutput);
+ }
+ break;
+ }
+
+ furi_string_free(selected_filepath);
+ furi_string_free(predefined_filepath);
+}
+
+#define STR_SELECT "[x]"
+#define STR_UNSELECT "[ ]"
+#define STR_BOOT "Bootloader (" TOSTRING(ESP_ADDR_BOOT) ")"
+#define STR_BOOT_S3 "Bootloader (" TOSTRING(ESP_ADDR_BOOT_S3) ")"
+#define STR_PART "Part Table (" TOSTRING(ESP_ADDR_PART) ")"
+#define STR_NVS "NVS (" TOSTRING(ESP_ADDR_NVS) ")"
+#define STR_BOOT_APP0 "boot_app0 (" TOSTRING(ESP_ADDR_BOOT_APP0) ")"
+#define STR_APP "Firmware (" TOSTRING(ESP_ADDR_APP) ")"
+#define STR_CUSTOM "Custom"
+#define STR_FLASH_S3 "[>] FLASH (ESP32-S3)"
+#define STR_FLASH "[>] FLASH"
+static void _refresh_submenu(EspFlasherApp* app) {
+ Submenu* submenu = app->submenu;
+
+ submenu_reset(app->submenu);
+
+ submenu_set_header(submenu, "Browse for files to flash");
+ submenu_add_item(
+ submenu,
+ app->selected_flash_options[SelectedFlashS3Mode] ? "[x] Using ESP32-S3" :
+ "[ ] Select if using S3",
+ SubmenuIndexS3Mode,
+ esp_flasher_scene_browse_callback,
+ app);
+ const char* strSelectBootloader = STR_UNSELECT " " STR_BOOT;
+ if(app->selected_flash_options[SelectedFlashS3Mode]) {
+ if(app->selected_flash_options[SelectedFlashBoot]) {
+ strSelectBootloader = STR_SELECT " " STR_BOOT_S3;
+ } else {
+ strSelectBootloader = STR_UNSELECT " " STR_BOOT_S3;
+ }
+ } else {
+ if(app->selected_flash_options[SelectedFlashBoot]) {
+ strSelectBootloader = STR_SELECT " " STR_BOOT;
+ } else {
+ strSelectBootloader = STR_UNSELECT " " STR_BOOT;
+ }
+ }
+ submenu_add_item(
+ submenu, strSelectBootloader, SubmenuIndexBoot, esp_flasher_scene_browse_callback, app);
+ submenu_add_item(
+ submenu,
+ app->selected_flash_options[SelectedFlashPart] ? STR_SELECT " " STR_PART :
+ STR_UNSELECT " " STR_PART,
+ SubmenuIndexPart,
+ esp_flasher_scene_browse_callback,
+ app);
+ submenu_add_item(
+ submenu,
+ app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS :
+ STR_UNSELECT " " STR_NVS,
+ SubmenuIndexNvs,
+ esp_flasher_scene_browse_callback,
+ app);
+ submenu_add_item(
+ submenu,
+ app->selected_flash_options[SelectedFlashBootApp0] ? STR_SELECT " " STR_BOOT_APP0 :
+ STR_UNSELECT " " STR_BOOT_APP0,
+ SubmenuIndexBootApp0,
+ esp_flasher_scene_browse_callback,
+ app);
+ submenu_add_item(
+ submenu,
+ app->selected_flash_options[SelectedFlashApp] ? STR_SELECT " " STR_APP :
+ STR_UNSELECT " " STR_APP,
+ SubmenuIndexApp,
+ esp_flasher_scene_browse_callback,
+ app);
+ // TODO: custom addr
+ //submenu_add_item(
+ // submenu, app->selected_flash_options[SelectedFlashCustom] ? STR_SELECT " " STR_CUSTOM : STR_UNSELECT " " STR_CUSTOM, SubmenuIndexCustom, esp_flasher_scene_browse_callback, app);
+ submenu_add_item(
+ submenu,
+ app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH,
+ SubmenuIndexFlash,
+ esp_flasher_scene_browse_callback,
+ app);
+
+ submenu_set_selected_item(
+ submenu, scene_manager_get_scene_state(app->scene_manager, EspFlasherSceneBrowse));
+ view_dispatcher_switch_to_view(app->view_dispatcher, EspFlasherAppViewSubmenu);
+}
+
+void esp_flasher_scene_browse_on_enter(void* context) {
+ EspFlasherApp* app = context;
+
+ memset(app->selected_flash_options, 0, sizeof(app->selected_flash_options));
+ app->bin_file_path_boot[0] = '\0';
+ app->bin_file_path_part[0] = '\0';
+ app->bin_file_path_nvs[0] = '\0';
+ app->bin_file_path_boot_app0[0] = '\0';
+ app->bin_file_path_app[0] = '\0';
+ app->bin_file_path_custom[0] = '\0';
+
+ _refresh_submenu(app);
+}
+
+bool esp_flasher_scene_browse_on_event(void* context, SceneManagerEvent event) {
+ EspFlasherApp* app = context;
+ bool consumed = false;
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == EspFlasherEventRefreshSubmenu) {
+ _refresh_submenu(app);
+ consumed = true;
+ }
+ }
+
+ return consumed;
+}
+
+void esp_flasher_scene_browse_on_exit(void* context) {
+ EspFlasherApp* app = context;
+ submenu_reset(app->submenu);
+}
diff --git a/applications/external/esp_flasher/scenes/esp_flasher_scene_config.h b/applications/external/esp_flasher/scenes/esp_flasher_scene_config.h
new file mode 100644
index 000000000..bf9c6e7b1
--- /dev/null
+++ b/applications/external/esp_flasher/scenes/esp_flasher_scene_config.h
@@ -0,0 +1,5 @@
+ADD_SCENE(esp_flasher, start, Start)
+ADD_SCENE(esp_flasher, devboard, Devboard)
+ADD_SCENE(esp_flasher, console_output, ConsoleOutput)
+ADD_SCENE(esp_flasher, about, About)
+ADD_SCENE(esp_flasher, browse, Browse)
diff --git a/applications/external/esp_flasher/scenes/esp_flasher_scene_console_output.c b/applications/external/esp_flasher/scenes/esp_flasher_scene_console_output.c
new file mode 100644
index 000000000..1e6d7654f
--- /dev/null
+++ b/applications/external/esp_flasher/scenes/esp_flasher_scene_console_output.c
@@ -0,0 +1,77 @@
+#include "../esp_flasher_app_i.h"
+
+#include "../esp_flasher_worker.h"
+
+void esp_flasher_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
+ furi_assert(context);
+ EspFlasherApp* app = context;
+
+ // If text box store gets too big, then truncate it
+ app->text_box_store_strlen += len;
+ if(app->text_box_store_strlen >= ESP_FLASHER_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, EspFlasherEventRefreshConsoleOutput);
+}
+
+void esp_flasher_scene_console_output_on_enter(void* context) {
+ EspFlasherApp* 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 end
+ text_box_set_focus(text_box, TextBoxFocusEnd);
+
+ // 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, EspFlasherSceneConsoleOutput, 0);
+ view_dispatcher_switch_to_view(app->view_dispatcher, EspFlasherAppViewConsoleOutput);
+
+ // Register callbacks to receive data
+ // setup callback for general log rx thread
+ esp_flasher_uart_set_handle_rx_data_cb(
+ app->uart,
+ esp_flasher_worker_handle_rx_data_cb); // setup callback for general log rx thread
+
+ // Start flash worker
+ esp_flasher_worker_start_thread(app);
+}
+
+bool esp_flasher_scene_console_output_on_event(void* context, SceneManagerEvent event) {
+ EspFlasherApp* 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;
+ } else {
+ if(app->flash_worker_busy) {
+ // ignore button presses while flashing
+ consumed = true;
+ }
+ }
+
+ return consumed;
+}
+
+void esp_flasher_scene_console_output_on_exit(void* context) {
+ EspFlasherApp* app = context;
+
+ esp_flasher_worker_stop_thread(app);
+
+ // Unregister rx callback
+ esp_flasher_uart_set_handle_rx_data_cb(app->uart, NULL);
+}
diff --git a/applications/external/esp_flasher/scenes/esp_flasher_scene_devboard.c b/applications/external/esp_flasher/scenes/esp_flasher_scene_devboard.c
new file mode 100644
index 000000000..ccb8f527c
--- /dev/null
+++ b/applications/external/esp_flasher/scenes/esp_flasher_scene_devboard.c
@@ -0,0 +1,86 @@
+#include "../esp_flasher_app_i.h"
+
+enum SubmenuIndex {
+ SubmenuIndexBlackMagic,
+ SubmenuIndexEvilPortal,
+ SubmenuIndexMarauder,
+};
+
+void esp_flasher_scene_devboard_submenu_callback(void* context, uint32_t index) {
+ furi_assert(context);
+ EspFlasherApp* app = context;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void esp_flasher_scene_devboard_on_enter(void* context) {
+ furi_assert(context);
+
+ EspFlasherApp* app = context;
+ Submenu* submenu = app->submenu;
+ submenu_set_header(submenu, "Select Firmware to flash");
+ submenu_add_item(
+ submenu,
+ "Black Magic",
+ SubmenuIndexBlackMagic,
+ esp_flasher_scene_devboard_submenu_callback,
+ app);
+ submenu_add_item(
+ submenu,
+ "Evil Portal",
+ SubmenuIndexEvilPortal,
+ esp_flasher_scene_devboard_submenu_callback,
+ app);
+ submenu_add_item(
+ submenu,
+ "Marauder",
+ SubmenuIndexMarauder,
+ esp_flasher_scene_devboard_submenu_callback,
+ app);
+
+ submenu_set_selected_item(
+ submenu, scene_manager_get_scene_state(app->scene_manager, EspFlasherSceneDevboard));
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, EspFlasherAppViewSubmenu);
+}
+
+bool esp_flasher_scene_devboard_on_event(void* context, SceneManagerEvent event) {
+ furi_assert(context);
+
+ EspFlasherApp* app = context;
+ bool consumed = false;
+ if(event.type == SceneManagerEventTypeCustom) {
+ const char* path = NULL;
+ consumed = true;
+ switch(event.event) {
+ case SubmenuIndexBlackMagic:
+ path = APP_DATA_PATH("Black_Magic.bin");
+ break;
+ case SubmenuIndexEvilPortal:
+ path = APP_DATA_PATH("Evil_Portal.bin");
+ break;
+ case SubmenuIndexMarauder:
+ path = APP_DATA_PATH("Marauder.bin");
+ break;
+ default:
+ consumed = false;
+ break;
+ }
+
+ if(consumed) {
+ app->selected_flash_options[SelectedFlashBoot] = true;
+ strncpy(app->bin_file_path_boot, path, sizeof(app->bin_file_path_boot));
+ scene_manager_next_scene(app->scene_manager, EspFlasherSceneConsoleOutput);
+ }
+ scene_manager_set_scene_state(app->scene_manager, EspFlasherSceneDevboard, event.event);
+ }
+
+ return consumed;
+}
+
+void esp_flasher_scene_devboard_on_exit(void* context) {
+ furi_assert(context);
+
+ EspFlasherApp* app = context;
+ submenu_reset(app->submenu);
+}
\ No newline at end of file
diff --git a/applications/external/esp_flasher/scenes/esp_flasher_scene_start.c b/applications/external/esp_flasher/scenes/esp_flasher_scene_start.c
new file mode 100644
index 000000000..0ae9eca30
--- /dev/null
+++ b/applications/external/esp_flasher/scenes/esp_flasher_scene_start.c
@@ -0,0 +1,73 @@
+#include "../esp_flasher_app_i.h"
+
+enum SubmenuIndex {
+ SubmenuIndexEspFlasherDevboardFlash,
+ SubmenuIndexEspFlasherFlash,
+ SubmenuIndexEspFlasherAbout,
+};
+
+void esp_flasher_scene_start_submenu_callback(void* context, uint32_t index) {
+ furi_assert(context);
+ EspFlasherApp* app = context;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void esp_flasher_scene_start_on_enter(void* context) {
+ furi_assert(context);
+
+ EspFlasherApp* app = context;
+ Submenu* submenu = app->submenu;
+ submenu_add_item(
+ submenu,
+ "Flash Wifi Devboard",
+ SubmenuIndexEspFlasherDevboardFlash,
+ esp_flasher_scene_start_submenu_callback,
+ app);
+ submenu_add_item(
+ submenu,
+ "Flash Generic ESP",
+ SubmenuIndexEspFlasherFlash,
+ esp_flasher_scene_start_submenu_callback,
+ app);
+ submenu_add_item(
+ submenu,
+ "About",
+ SubmenuIndexEspFlasherAbout,
+ esp_flasher_scene_start_submenu_callback,
+ app);
+
+ submenu_set_selected_item(
+ submenu, scene_manager_get_scene_state(app->scene_manager, EspFlasherSceneStart));
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, EspFlasherAppViewSubmenu);
+}
+
+bool esp_flasher_scene_start_on_event(void* context, SceneManagerEvent event) {
+ furi_assert(context);
+
+ EspFlasherApp* app = context;
+ bool consumed = false;
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == SubmenuIndexEspFlasherDevboardFlash) {
+ scene_manager_next_scene(app->scene_manager, EspFlasherSceneDevboard);
+ consumed = true;
+ } else if(event.event == SubmenuIndexEspFlasherFlash) {
+ scene_manager_next_scene(app->scene_manager, EspFlasherSceneBrowse);
+ consumed = true;
+ } else if(event.event == SubmenuIndexEspFlasherAbout) {
+ scene_manager_next_scene(app->scene_manager, EspFlasherSceneAbout);
+ consumed = true;
+ }
+ scene_manager_set_scene_state(app->scene_manager, EspFlasherSceneStart, event.event);
+ }
+
+ return consumed;
+}
+
+void esp_flasher_scene_start_on_exit(void* context) {
+ furi_assert(context);
+
+ EspFlasherApp* app = context;
+ submenu_reset(app->submenu);
+}
\ No newline at end of file
diff --git a/applications/external/esp_flasher/wifi_10px.png b/applications/external/esp_flasher/wifi_10px.png
new file mode 100644
index 000000000..c13534660
Binary files /dev/null and b/applications/external/esp_flasher/wifi_10px.png differ
diff --git a/applications/external/evil_portal/application.fam b/applications/external/evil_portal/application.fam
new file mode 100644
index 000000000..58c7d426c
--- /dev/null
+++ b/applications/external/evil_portal/application.fam
@@ -0,0 +1,12 @@
+App(
+ appid="evil_portal",
+ name="[ESP32] Evil Portal",
+ apptype=FlipperAppType.EXTERNAL,
+ entry_point="evil_portal_app",
+ cdefines=["APP_EVIL_PORTAL"],
+ requires=["gui"],
+ stack_size=1 * 1024,
+ order=90,
+ fap_icon="icons/evil_portal_10px.png",
+ fap_category="WiFi",
+)
diff --git a/applications/external/evil_portal/evil_portal_app.c b/applications/external/evil_portal/evil_portal_app.c
new file mode 100644
index 000000000..ee9b373d0
--- /dev/null
+++ b/applications/external/evil_portal/evil_portal_app.c
@@ -0,0 +1,117 @@
+#include "evil_portal_app_i.h"
+#include "helpers/evil_portal_storage.h"
+
+#include
+#include
+
+static bool evil_portal_app_custom_event_callback(void* context, uint32_t event) {
+ furi_assert(context);
+ Evil_PortalApp* app = context;
+ return scene_manager_handle_custom_event(app->scene_manager, event);
+}
+
+static bool evil_portal_app_back_event_callback(void* context) {
+ furi_assert(context);
+ Evil_PortalApp* app = context;
+ return scene_manager_handle_back_event(app->scene_manager);
+}
+
+static void evil_portal_app_tick_event_callback(void* context) {
+ furi_assert(context);
+ Evil_PortalApp* app = context;
+ scene_manager_handle_tick_event(app->scene_manager);
+}
+
+Evil_PortalApp* evil_portal_app_alloc() {
+ Evil_PortalApp* app = malloc(sizeof(Evil_PortalApp));
+
+ app->sent_html = false;
+ app->sent_ap = false;
+ app->sent_reset = false;
+ app->has_command_queue = false;
+ app->command_index = 0;
+ app->portal_logs = furi_string_alloc();
+
+ app->gui = furi_record_open(RECORD_GUI);
+ app->dialogs = furi_record_open(RECORD_DIALOGS);
+
+ app->view_dispatcher = view_dispatcher_alloc();
+ app->scene_manager = scene_manager_alloc(&evil_portal_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, evil_portal_app_custom_event_callback);
+ view_dispatcher_set_navigation_event_callback(
+ app->view_dispatcher, evil_portal_app_back_event_callback);
+ view_dispatcher_set_tick_event_callback(
+ app->view_dispatcher, evil_portal_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,
+ Evil_PortalAppViewVarItemList,
+ 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, Evil_PortalAppViewConsoleOutput, text_box_get_view(app->text_box));
+ app->text_box_store = furi_string_alloc();
+ furi_string_reserve(app->text_box_store, EVIL_PORTAL_TEXT_BOX_STORE_SIZE);
+
+ scene_manager_next_scene(app->scene_manager, Evil_PortalSceneStart);
+
+ return app;
+}
+
+void evil_portal_app_free(Evil_PortalApp* app) {
+ // save latest logs
+ if(furi_string_utf8_length(app->portal_logs) > 0) {
+ write_logs(app->portal_logs);
+ furi_string_free(app->portal_logs);
+ }
+
+ // Send reset event to dev board
+ evil_portal_uart_tx((uint8_t*)(RESET_CMD), strlen(RESET_CMD));
+ evil_portal_uart_tx((uint8_t*)("\n"), 1);
+
+ furi_assert(app);
+
+ // Views
+ view_dispatcher_remove_view(app->view_dispatcher, Evil_PortalAppViewVarItemList);
+ view_dispatcher_remove_view(app->view_dispatcher, Evil_PortalAppViewConsoleOutput);
+
+ text_box_free(app->text_box);
+ furi_string_free(app->text_box_store);
+
+ // View dispatcher
+ view_dispatcher_free(app->view_dispatcher);
+ scene_manager_free(app->scene_manager);
+
+ evil_portal_uart_free(app->uart);
+
+ // Close records
+ furi_record_close(RECORD_GUI);
+ furi_record_close(RECORD_DIALOGS);
+
+ free(app);
+}
+
+int32_t evil_portal_app(void* p) {
+ UNUSED(p);
+ Evil_PortalApp* evil_portal_app = evil_portal_app_alloc();
+
+ evil_portal_app->uart = evil_portal_uart_init(evil_portal_app);
+
+ view_dispatcher_run(evil_portal_app->view_dispatcher);
+
+ evil_portal_app_free(evil_portal_app);
+
+ return 0;
+}
diff --git a/applications/external/evil_portal/evil_portal_app.h b/applications/external/evil_portal/evil_portal_app.h
new file mode 100644
index 000000000..65c047ea5
--- /dev/null
+++ b/applications/external/evil_portal/evil_portal_app.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Evil_PortalApp Evil_PortalApp;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/applications/external/evil_portal/evil_portal_app_i.h b/applications/external/evil_portal/evil_portal_app_i.h
new file mode 100644
index 000000000..eeda72b70
--- /dev/null
+++ b/applications/external/evil_portal/evil_portal_app_i.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "evil_portal_app.h"
+#include "evil_portal_custom_event.h"
+#include "evil_portal_uart.h"
+#include "scenes/evil_portal_scene.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#define NUM_MENU_ITEMS (4)
+
+#define EVIL_PORTAL_TEXT_BOX_STORE_SIZE (4096)
+#define UART_CH (FuriHalUartIdUSART1)
+
+#define SET_HTML_CMD "sethtml"
+#define SET_AP_CMD "setap"
+#define RESET_CMD "reset"
+
+#define EVIL_PORTAL_INDEX_EXTENSION ".html"
+#define EVIL_PORTAL_BASE_FOLDER STORAGE_APP_DATA_PATH_PREFIX
+
+struct Evil_PortalApp {
+ Gui* gui;
+ ViewDispatcher* view_dispatcher;
+ SceneManager* scene_manager;
+ DialogsApp* dialogs;
+
+ FuriString* portal_logs;
+ const char* command_queue[1];
+ int command_index;
+ bool has_command_queue;
+
+ FuriString* text_box_store;
+ size_t text_box_store_strlen;
+ TextBox* text_box;
+
+ VariableItemList* var_item_list;
+ Evil_PortalUart* 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 sent_ap;
+ bool sent_html;
+ bool sent_reset;
+ int BAUDRATE;
+
+ uint8_t* index_html;
+ uint8_t* ap_name;
+};
+
+typedef enum {
+ Evil_PortalAppViewVarItemList,
+ Evil_PortalAppViewConsoleOutput,
+ Evil_PortalAppViewStartPortal,
+} Evil_PortalAppView;
diff --git a/applications/external/evil_portal/evil_portal_custom_event.h b/applications/external/evil_portal/evil_portal_custom_event.h
new file mode 100644
index 000000000..a566ca62e
--- /dev/null
+++ b/applications/external/evil_portal/evil_portal_custom_event.h
@@ -0,0 +1,8 @@
+#pragma once
+
+typedef enum {
+ Evil_PortalEventRefreshConsoleOutput = 0,
+ Evil_PortalEventStartConsole,
+ Evil_PortalEventStartKeyboard,
+ Evil_PortalEventStartPortal,
+} Evil_PortalCustomEvent;
diff --git a/applications/external/evil_portal/evil_portal_uart.c b/applications/external/evil_portal/evil_portal_uart.c
new file mode 100644
index 000000000..2698a4410
--- /dev/null
+++ b/applications/external/evil_portal/evil_portal_uart.c
@@ -0,0 +1,145 @@
+#include "evil_portal_app_i.h"
+#include "evil_portal_uart.h"
+#include "helpers/evil_portal_storage.h"
+
+struct Evil_PortalUart {
+ Evil_PortalApp* 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 evil_portal_uart_set_handle_rx_data_cb(
+ Evil_PortalUart* 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 evil_portal_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
+ Evil_PortalUart* uart = (Evil_PortalUart*)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) {
+ Evil_PortalUart* 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);
+
+ if(uart->app->has_command_queue) {
+ if(uart->app->command_index < 1) {
+ if(0 == strncmp(
+ SET_AP_CMD,
+ uart->app->command_queue[uart->app->command_index],
+ strlen(SET_AP_CMD))) {
+ FuriString* out_data = furi_string_alloc();
+
+ furi_string_cat(out_data, "setap=");
+ furi_string_cat(out_data, (char*)uart->app->ap_name);
+
+ evil_portal_uart_tx(
+ (uint8_t*)(furi_string_get_cstr(out_data)),
+ strlen(furi_string_get_cstr(out_data)));
+ evil_portal_uart_tx((uint8_t*)("\n"), 1);
+
+ uart->app->sent_ap = true;
+
+ free(out_data);
+ free(uart->app->ap_name);
+ }
+
+ uart->app->command_index = 0;
+ uart->app->has_command_queue = false;
+ uart->app->command_queue[0] = "";
+ }
+ }
+
+ if(uart->app->sent_reset == false) {
+ furi_string_cat(uart->app->portal_logs, (char*)uart->rx_buf);
+ }
+
+ if(furi_string_utf8_length(uart->app->portal_logs) > 4000) {
+ write_logs(uart->app->portal_logs);
+ furi_string_reset(uart->app->portal_logs);
+ }
+ } else {
+ uart->rx_buf[len] = '\0';
+ if(uart->app->sent_reset == false) {
+ furi_string_cat(uart->app->portal_logs, (char*)uart->rx_buf);
+ }
+
+ if(furi_string_utf8_length(uart->app->portal_logs) > 4000) {
+ write_logs(uart->app->portal_logs);
+ furi_string_reset(uart->app->portal_logs);
+ }
+ }
+ }
+ }
+ }
+
+ furi_stream_buffer_free(uart->rx_stream);
+
+ return 0;
+}
+
+void evil_portal_uart_tx(uint8_t* data, size_t len) {
+ furi_hal_uart_tx(UART_CH, data, len);
+}
+
+Evil_PortalUart* evil_portal_uart_init(Evil_PortalApp* app) {
+ Evil_PortalUart* uart = malloc(sizeof(Evil_PortalUart));
+ 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, "Evil_PortalUartRxThread");
+ 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, evil_portal_uart_on_irq_cb, uart);
+
+ return uart;
+}
+
+void evil_portal_uart_free(Evil_PortalUart* 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);
+}
diff --git a/applications/external/evil_portal/evil_portal_uart.h b/applications/external/evil_portal/evil_portal_uart.h
new file mode 100644
index 000000000..d7980a8e2
--- /dev/null
+++ b/applications/external/evil_portal/evil_portal_uart.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "furi_hal.h"
+
+#define RX_BUF_SIZE (320)
+
+typedef struct Evil_PortalUart Evil_PortalUart;
+
+void evil_portal_uart_set_handle_rx_data_cb(
+ Evil_PortalUart* uart,
+ void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
+void evil_portal_uart_tx(uint8_t* data, size_t len);
+Evil_PortalUart* evil_portal_uart_init(Evil_PortalApp* app);
+void evil_portal_uart_free(Evil_PortalUart* uart);
diff --git a/applications/external/evil_portal/helpers/evil_portal_storage.c b/applications/external/evil_portal/helpers/evil_portal_storage.c
new file mode 100644
index 000000000..aa9a50493
--- /dev/null
+++ b/applications/external/evil_portal/helpers/evil_portal_storage.c
@@ -0,0 +1,135 @@
+#include "evil_portal_storage.h"
+
+static Storage* evil_portal_open_storage() {
+ return furi_record_open(RECORD_STORAGE);
+}
+
+static void evil_portal_close_storage() {
+ furi_record_close(RECORD_STORAGE);
+}
+
+bool evil_portal_read_index_html(void* context) {
+ FuriString* file_path = furi_string_alloc_set(EVIL_PORTAL_BASE_FOLDER);
+
+ DialogsFileBrowserOptions browser_options;
+ dialog_file_browser_set_basic_options(
+ &browser_options,
+ EVIL_PORTAL_INDEX_EXTENSION,
+ NULL); // TODO configure icon
+ browser_options.base_path = EVIL_PORTAL_BASE_FOLDER;
+
+ Evil_PortalApp* app = context;
+ bool res = dialog_file_browser_show(app->dialogs, file_path, file_path, &browser_options);
+
+ if(!res) {
+ furi_string_free(file_path);
+ return false;
+ }
+
+ Storage* storage = evil_portal_open_storage();
+ FileInfo fi;
+
+ if(storage_common_stat(storage, furi_string_get_cstr(file_path), &fi) == FSE_OK) {
+ File* index_html = storage_file_alloc(storage);
+ if(storage_file_open(
+ index_html, furi_string_get_cstr(file_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
+ app->index_html = malloc((size_t)fi.size);
+ uint8_t* buf_ptr = app->index_html;
+ size_t read = 0;
+ while(read < fi.size) {
+ size_t to_read = fi.size - read;
+ if(to_read > UINT16_MAX) to_read = UINT16_MAX;
+ uint16_t now_read = storage_file_read(index_html, buf_ptr, (uint16_t)to_read);
+ read += now_read;
+ buf_ptr += now_read;
+ }
+ free(buf_ptr);
+ }
+ furi_string_free(file_path);
+ storage_file_close(index_html);
+ storage_file_free(index_html);
+ } else {
+ char* html_error = "Evil portal
Unable to read the html file.
"
+ "Is the SD Card set up correctly?
See instructions @ "
+ "github.com/bigbrodude6119/flipper-zero-evil-portal
"
+ "Under the 'Install pre-built app on the flipper' section.";
+ app->index_html = (uint8_t*)html_error;
+ }
+
+ evil_portal_close_storage();
+ return true;
+}
+
+void evil_portal_read_ap_name(void* context) {
+ Evil_PortalApp* app = context;
+ Storage* storage = evil_portal_open_storage();
+ FileInfo fi;
+
+ if(storage_common_stat(storage, EVIL_PORTAL_AP_SAVE_PATH, &fi) == FSE_OK) {
+ File* ap_name = storage_file_alloc(storage);
+ if(storage_file_open(ap_name, EVIL_PORTAL_AP_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
+ app->ap_name = malloc((size_t)fi.size);
+ uint8_t* buf_ptr = app->ap_name;
+ size_t read = 0;
+ while(read < fi.size) {
+ size_t to_read = fi.size - read;
+ if(to_read > UINT16_MAX) to_read = UINT16_MAX;
+ uint16_t now_read = storage_file_read(ap_name, buf_ptr, (uint16_t)to_read);
+ read += now_read;
+ buf_ptr += now_read;
+ }
+ free(buf_ptr);
+ }
+ storage_file_close(ap_name);
+ storage_file_free(ap_name);
+ } else {
+ char* app_default = "Evil Portal";
+ app->ap_name = (uint8_t*)app_default;
+ }
+ evil_portal_close_storage();
+}
+
+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);
+}
+
+void write_logs(FuriString* portal_logs) {
+ Storage* storage = evil_portal_open_storage();
+
+ if(!storage_file_exists(storage, EVIL_PORTAL_LOG_SAVE_PATH)) {
+ storage_simply_mkdir(storage, EVIL_PORTAL_LOG_SAVE_PATH);
+ }
+
+ char* seq_file_path =
+ sequential_file_resolve_path(storage, EVIL_PORTAL_LOG_SAVE_PATH, "log", "txt");
+
+ File* file = storage_file_alloc(storage);
+
+ if(storage_file_open(file, seq_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
+ storage_file_write(
+ file, furi_string_get_cstr(portal_logs), furi_string_utf8_length(portal_logs));
+ }
+ storage_file_close(file);
+ storage_file_free(file);
+ evil_portal_close_storage();
+}
diff --git a/applications/external/evil_portal/helpers/evil_portal_storage.h b/applications/external/evil_portal/helpers/evil_portal_storage.h
new file mode 100644
index 000000000..d4ad33e1d
--- /dev/null
+++ b/applications/external/evil_portal/helpers/evil_portal_storage.h
@@ -0,0 +1,21 @@
+#include "../evil_portal_app_i.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define PORTAL_FILE_DIRECTORY_PATH EXT_PATH("apps_data/evil_portal")
+#define EVIL_PORTAL_INDEX_SAVE_PATH PORTAL_FILE_DIRECTORY_PATH "/index.html"
+#define EVIL_PORTAL_AP_SAVE_PATH PORTAL_FILE_DIRECTORY_PATH "/ap.config.txt"
+#define EVIL_PORTAL_LOG_SAVE_PATH PORTAL_FILE_DIRECTORY_PATH "/logs"
+
+bool evil_portal_read_index_html(void* context);
+void evil_portal_read_ap_name(void* context);
+void write_logs(FuriString* portal_logs);
+char* sequential_file_resolve_path(
+ Storage* storage,
+ const char* dir,
+ const char* prefix,
+ const char* extension);
diff --git a/applications/external/evil_portal/icons/evil_portal_10px.png b/applications/external/evil_portal/icons/evil_portal_10px.png
new file mode 100644
index 000000000..c13534660
Binary files /dev/null and b/applications/external/evil_portal/icons/evil_portal_10px.png differ
diff --git a/applications/external/evil_portal/scenes/evil_portal_scene.c b/applications/external/evil_portal/scenes/evil_portal_scene.c
new file mode 100644
index 000000000..f6f06d8cc
--- /dev/null
+++ b/applications/external/evil_portal/scenes/evil_portal_scene.c
@@ -0,0 +1,30 @@
+#include "evil_portal_scene.h"
+
+// Generate scene on_enter handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
+void (*const evil_portal_scene_on_enter_handlers[])(void*) = {
+#include "evil_portal_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 evil_portal_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
+#include "evil_portal_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 evil_portal_scene_on_exit_handlers[])(void* context) = {
+#include "evil_portal_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Initialize scene handlers configuration structure
+const SceneManagerHandlers evil_portal_scene_handlers = {
+ .on_enter_handlers = evil_portal_scene_on_enter_handlers,
+ .on_event_handlers = evil_portal_scene_on_event_handlers,
+ .on_exit_handlers = evil_portal_scene_on_exit_handlers,
+ .scene_num = Evil_PortalSceneNum,
+};
diff --git a/applications/external/evil_portal/scenes/evil_portal_scene.h b/applications/external/evil_portal/scenes/evil_portal_scene.h
new file mode 100644
index 000000000..8468f9157
--- /dev/null
+++ b/applications/external/evil_portal/scenes/evil_portal_scene.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include
+
+// Generate scene id and total number
+#define ADD_SCENE(prefix, name, id) Evil_PortalScene##id,
+typedef enum {
+#include "evil_portal_scene_config.h"
+ Evil_PortalSceneNum,
+} Evil_PortalScene;
+#undef ADD_SCENE
+
+extern const SceneManagerHandlers evil_portal_scene_handlers;
+
+// Generate scene on_enter handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
+#include "evil_portal_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 "evil_portal_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 "evil_portal_scene_config.h"
+#undef ADD_SCENE
diff --git a/applications/external/evil_portal/scenes/evil_portal_scene_config.h b/applications/external/evil_portal/scenes/evil_portal_scene_config.h
new file mode 100644
index 000000000..94b09ae46
--- /dev/null
+++ b/applications/external/evil_portal/scenes/evil_portal_scene_config.h
@@ -0,0 +1,2 @@
+ADD_SCENE(evil_portal, start, Start)
+ADD_SCENE(evil_portal, console_output, ConsoleOutput)
diff --git a/applications/external/evil_portal/scenes/evil_portal_scene_console_output.c b/applications/external/evil_portal/scenes/evil_portal_scene_console_output.c
new file mode 100644
index 000000000..94f2cef4f
--- /dev/null
+++ b/applications/external/evil_portal/scenes/evil_portal_scene_console_output.c
@@ -0,0 +1,166 @@
+#include "../evil_portal_app_i.h"
+#include "../helpers/evil_portal_storage.h"
+
+void evil_portal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
+ furi_assert(context);
+ Evil_PortalApp* app = context;
+
+ // If text box store gets too big, then truncate it
+ app->text_box_store_strlen += len;
+ if(app->text_box_store_strlen >= EVIL_PORTAL_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, Evil_PortalEventRefreshConsoleOutput);
+}
+
+void evil_portal_scene_console_output_on_enter(void* context) {
+ Evil_PortalApp* app = context;
+
+ bool portal_file_set = false;
+
+ 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);
+ }
+
+ if(app->is_command) {
+ furi_string_reset(app->text_box_store);
+ app->text_box_store_strlen = 0;
+ app->sent_reset = false;
+
+ if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) {
+ const char* help_msg = "BLUE = Waiting\nGREEN = Good\nRED = Bad\n\nThis project is a "
+ "WIP.\ngithub.com/bigbrodude6119/flipper-zero-evil-portal\n\n"
+ "Version 0.0.2\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* msg = "Press BACK to return\n";
+ furi_string_cat_str(app->text_box_store, msg);
+ app->text_box_store_strlen += strlen(msg);
+ }
+ }
+
+ if(0 == strncmp("savelogs", app->selected_tx_string, strlen("savelogs"))) {
+ const char* help_msg = "Logs saved.\n\n";
+ furi_string_cat_str(app->text_box_store, help_msg);
+ app->text_box_store_strlen += strlen(help_msg);
+ write_logs(app->portal_logs);
+ furi_string_reset(app->portal_logs);
+ if(app->show_stopscan_tip) {
+ const char* msg = "Press BACK to return\n";
+ furi_string_cat_str(app->text_box_store, msg);
+ app->text_box_store_strlen += strlen(msg);
+ }
+ }
+
+ if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) {
+ portal_file_set = evil_portal_read_index_html(context);
+
+ if(portal_file_set) {
+ app->command_queue[0] = SET_AP_CMD;
+ app->has_command_queue = true;
+ app->command_index = 0;
+ if(app->show_stopscan_tip) {
+ const char* msg = "Starting portal\nIf no response press\nBACK to return\n";
+ furi_string_cat_str(app->text_box_store, msg);
+ app->text_box_store_strlen += strlen(msg);
+ }
+ } else {
+ if(app->show_stopscan_tip) {
+ const char* msg = "No portal selected\nShowing current logs\nPress "
+ "BACK to return\n";
+ furi_string_cat_str(app->text_box_store, msg);
+ app->text_box_store_strlen += strlen(msg);
+ }
+ }
+ }
+
+ if(0 == strncmp(RESET_CMD, app->selected_tx_string, strlen(RESET_CMD))) {
+ app->sent_reset = true;
+ if(app->show_stopscan_tip) {
+ const char* msg = "Reseting portal\nPress BACK to return\n\n\n\n";
+ furi_string_cat_str(app->text_box_store, msg);
+ app->text_box_store_strlen += strlen(msg);
+ }
+ }
+ }
+
+ text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
+
+ scene_manager_set_scene_state(app->scene_manager, Evil_PortalSceneConsoleOutput, 0);
+ view_dispatcher_switch_to_view(app->view_dispatcher, Evil_PortalAppViewConsoleOutput);
+
+ // Register callback to receive data
+ evil_portal_uart_set_handle_rx_data_cb(
+ app->uart, evil_portal_console_output_handle_rx_data_cb);
+
+ if(app->is_command && app->selected_tx_string) {
+ if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) {
+ if(!portal_file_set) {
+ scene_manager_set_scene_state(
+ app->scene_manager, Evil_PortalSceneConsoleOutput, 0);
+ view_dispatcher_switch_to_view(
+ app->view_dispatcher, Evil_PortalAppViewConsoleOutput);
+ return;
+ }
+
+ FuriString* data = furi_string_alloc();
+ furi_string_cat(data, "sethtml=");
+ furi_string_cat(data, (char*)app->index_html);
+
+ evil_portal_uart_tx(
+ (uint8_t*)(furi_string_get_cstr(data)), strlen(furi_string_get_cstr(data)));
+ evil_portal_uart_tx((uint8_t*)("\n"), 1);
+
+ app->sent_html = true;
+
+ free(data);
+ free(app->index_html);
+
+ evil_portal_read_ap_name(context);
+ } else if(0 == strncmp(RESET_CMD, app->selected_tx_string, strlen(RESET_CMD))) {
+ app->sent_html = false;
+ app->sent_ap = false;
+ evil_portal_uart_tx(
+ (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
+ evil_portal_uart_tx((uint8_t*)("\n"), 1);
+ } else if(1 == strncmp("help", app->selected_tx_string, strlen("help"))) {
+ evil_portal_uart_tx(
+ (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
+ evil_portal_uart_tx((uint8_t*)("\n"), 1);
+ }
+ }
+}
+
+bool evil_portal_scene_console_output_on_event(void* context, SceneManagerEvent event) {
+ Evil_PortalApp* 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 evil_portal_scene_console_output_on_exit(void* context) {
+ Evil_PortalApp* app = context;
+
+ // Unregister rx callback
+ evil_portal_uart_set_handle_rx_data_cb(app->uart, NULL);
+}
diff --git a/applications/external/evil_portal/scenes/evil_portal_scene_start.c b/applications/external/evil_portal/scenes/evil_portal_scene_start.c
new file mode 100644
index 000000000..7f7200fcb
--- /dev/null
+++ b/applications/external/evil_portal/scenes/evil_portal_scene_start.c
@@ -0,0 +1,130 @@
+#include "../evil_portal_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;
+} Evil_PortalItem;
+
+// NUM_MENU_ITEMS defined in evil_portal_app_i.h - if you add an entry here,
+// increment it!
+const Evil_PortalItem items[NUM_MENU_ITEMS] = {
+ // send command
+ {"Start portal", {""}, 1, {SET_HTML_CMD}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP},
+
+ // stop portal
+ {"Stop portal", {""}, 1, {RESET_CMD}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP},
+
+ // console
+ {"Save logs", {""}, 1, {"savelogs"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP},
+
+ // help
+ {"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP},
+};
+
+static void evil_portal_scene_start_var_list_enter_callback(void* context, uint32_t index) {
+ furi_assert(context);
+ Evil_PortalApp* app = context;
+
+ furi_assert(index < NUM_MENU_ITEMS);
+ const Evil_PortalItem* 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 = true;
+ 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;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, Evil_PortalEventStartConsole);
+}
+
+static void evil_portal_scene_start_var_list_change_callback(VariableItem* item) {
+ furi_assert(item);
+
+ Evil_PortalApp* app = variable_item_get_context(item);
+ furi_assert(app);
+
+ const Evil_PortalItem* 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 evil_portal_scene_start_on_enter(void* context) {
+ Evil_PortalApp* app = context;
+ VariableItemList* var_item_list = app->var_item_list;
+
+ variable_item_list_set_enter_callback(
+ var_item_list, evil_portal_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,
+ evil_portal_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, Evil_PortalSceneStart));
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, Evil_PortalAppViewVarItemList);
+}
+
+bool evil_portal_scene_start_on_event(void* context, SceneManagerEvent event) {
+ UNUSED(context);
+ Evil_PortalApp* app = context;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == Evil_PortalEventStartPortal) {
+ scene_manager_set_scene_state(
+ app->scene_manager, Evil_PortalSceneStart, app->selected_menu_index);
+ scene_manager_next_scene(app->scene_manager, Evil_PortalAppViewStartPortal);
+ } else if(event.event == Evil_PortalEventStartKeyboard) {
+ scene_manager_set_scene_state(
+ app->scene_manager, Evil_PortalSceneStart, app->selected_menu_index);
+ } else if(event.event == Evil_PortalEventStartConsole) {
+ scene_manager_set_scene_state(
+ app->scene_manager, Evil_PortalSceneStart, app->selected_menu_index);
+ scene_manager_next_scene(app->scene_manager, Evil_PortalAppViewConsoleOutput);
+ }
+ 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 evil_portal_scene_start_on_exit(void* context) {
+ Evil_PortalApp* app = context;
+ variable_item_list_reset(app->var_item_list);
+}
diff --git a/applications/external/hid_app/assets/KB_key_Alt_17x10.png b/applications/external/hid_app/assets/KB_key_Alt_17x10.png
new file mode 100644
index 000000000..26c4f7315
Binary files /dev/null and b/applications/external/hid_app/assets/KB_key_Alt_17x10.png 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
new file mode 100644
index 000000000..8d87ffde6
Binary files /dev/null and b/applications/external/hid_app/assets/KB_key_Cmd_17x10.png 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
new file mode 100644
index 000000000..01f3157c9
Binary files /dev/null and b/applications/external/hid_app/assets/KB_key_Ctl_17x10.png 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
new file mode 100644
index 000000000..62bad18b5
Binary files /dev/null and b/applications/external/hid_app/assets/KB_key_Del_17x10.png 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
new file mode 100644
index 000000000..7a9fdda22
Binary files /dev/null and b/applications/external/hid_app/assets/KB_key_Esc_17x10.png 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
new file mode 100644
index 000000000..d904dd418
Binary files /dev/null and b/applications/external/hid_app/assets/KB_key_Tab_17x10.png differ
diff --git a/applications/external/hid_app/assets/OutCircles.png b/applications/external/hid_app/assets/OutCircles_70x51.png
similarity index 100%
rename from applications/external/hid_app/assets/OutCircles.png
rename to applications/external/hid_app/assets/OutCircles_70x51.png
diff --git a/applications/external/hid_app/assets/S_DOWN.png b/applications/external/hid_app/assets/S_DOWN_31x15.png
similarity index 100%
rename from applications/external/hid_app/assets/S_DOWN.png
rename to applications/external/hid_app/assets/S_DOWN_31x15.png
diff --git a/applications/external/hid_app/assets/S_LEFT.png b/applications/external/hid_app/assets/S_LEFT_15x31.png
similarity index 100%
rename from applications/external/hid_app/assets/S_LEFT.png
rename to applications/external/hid_app/assets/S_LEFT_15x31.png
diff --git a/applications/external/hid_app/assets/S_RIGHT.png b/applications/external/hid_app/assets/S_RIGHT_15x31.png
similarity index 100%
rename from applications/external/hid_app/assets/S_RIGHT.png
rename to applications/external/hid_app/assets/S_RIGHT_15x31.png
diff --git a/applications/external/hid_app/assets/S_UP.png b/applications/external/hid_app/assets/S_UP_31x15.png
similarity index 100%
rename from applications/external/hid_app/assets/S_UP.png
rename to applications/external/hid_app/assets/S_UP_31x15.png
diff --git a/applications/external/hid_app/views/hid_keyboard.c b/applications/external/hid_app/views/hid_keyboard.c
index 9b8c87b13..1c1525ec9 100644
--- a/applications/external/hid_app/views/hid_keyboard.c
+++ b/applications/external/hid_app/views/hid_keyboard.c
@@ -139,17 +139,17 @@ const HidKeyboardKey hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = {
{.width = 1, .icon = &I_ButtonRight_4x7, .value = HID_KEYBOARD_RIGHT_ARROW},
},
{
- {.width = 2, .icon = NULL, .key = "Ctl", .value = HID_KEYBOARD_L_CTRL},
+ {.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 = NULL, .key = "Alt", .value = HID_KEYBOARD_L_ALT},
+ {.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 = NULL, .key = "Cmd", .value = HID_KEYBOARD_L_GUI},
+ {.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 = NULL, .key = "Tab", .value = HID_KEYBOARD_TAB},
+ {.width = 2, .icon = &I_KB_key_Tab_17x10, .value = HID_KEYBOARD_TAB},
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_TAB},
- {.width = 2, .icon = NULL, .key = "Esc", .value = HID_KEYBOARD_ESCAPE},
+ {.width = 2, .icon = &I_KB_key_Esc_17x10, .value = HID_KEYBOARD_ESCAPE},
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_ESCAPE},
- {.width = 2, .icon = NULL, .key = "Del", .value = HID_KEYBOARD_DELETE_FORWARD},
+ {.width = 2, .icon = &I_KB_key_Del_17x10, .value = HID_KEYBOARD_DELETE_FORWARD},
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_DELETE_FORWARD},
},
};
diff --git a/applications/external/hid_app/views/hid_media.c b/applications/external/hid_app/views/hid_media.c
index 98f88819f..caf854eb1 100644
--- a/applications/external/hid_app/views/hid_media.c
+++ b/applications/external/hid_app/views/hid_media.c
@@ -54,12 +54,12 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
canvas_set_font(canvas, FontSecondary);
// Keypad circles
- canvas_draw_icon(canvas, 58, 3, &I_OutCircles);
+ 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);
+ canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
@@ -69,7 +69,7 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
// Down
if(model->down_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 68, 36, &I_S_DOWN);
+ canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
@@ -79,7 +79,7 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
// Left
if(model->left_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 61, 13, &I_S_LEFT);
+ canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
@@ -90,7 +90,7 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
// Right
if(model->right_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT);
+ canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
diff --git a/applications/external/hid_app/views/hid_mouse.c b/applications/external/hid_app/views/hid_mouse.c
index e93ea3fc1..4c4737155 100644
--- a/applications/external/hid_app/views/hid_mouse.c
+++ b/applications/external/hid_app/views/hid_mouse.c
@@ -47,12 +47,12 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
}
// Keypad circles
- canvas_draw_icon(canvas, 58, 3, &I_OutCircles);
+ 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);
+ canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
@@ -62,7 +62,7 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
// Down
if(model->down_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 68, 36, &I_S_DOWN);
+ canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
@@ -72,7 +72,7 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
// Left
if(model->left_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 61, 13, &I_S_LEFT);
+ canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
@@ -82,7 +82,7 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
// Right
if(model->right_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT);
+ canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
diff --git a/applications/external/hid_app/views/hid_tikshorts.c b/applications/external/hid_app/views/hid_tikshorts.c
index b494245cf..78e7488f3 100644
--- a/applications/external/hid_app/views/hid_tikshorts.c
+++ b/applications/external/hid_app/views/hid_tikshorts.c
@@ -40,7 +40,7 @@ static void hid_tikshorts_draw_callback(Canvas* canvas, void* context) {
canvas_set_font(canvas, FontSecondary);
// Keypad circles
- canvas_draw_icon(canvas, 58, 3, &I_OutCircles);
+ canvas_draw_icon(canvas, 58, 3, &I_OutCircles_70x51);
// Pause
if(model->back_mouse_pressed) {
@@ -55,7 +55,7 @@ static void hid_tikshorts_draw_callback(Canvas* canvas, void* context) {
// Up
if(model->up_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 68, 6, &I_S_UP);
+ canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
@@ -65,7 +65,7 @@ static void hid_tikshorts_draw_callback(Canvas* canvas, void* context) {
// Down
if(model->down_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 68, 36, &I_S_DOWN);
+ canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
@@ -75,7 +75,7 @@ static void hid_tikshorts_draw_callback(Canvas* canvas, void* context) {
// Left
if(model->left_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 61, 13, &I_S_LEFT);
+ canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
@@ -85,7 +85,7 @@ static void hid_tikshorts_draw_callback(Canvas* canvas, void* context) {
// Right
if(model->right_pressed) {
canvas_set_bitmap_mode(canvas, 1);
- canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT);
+ canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31);
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
diff --git a/applications/external/jetpack_joyride/jetpack.c b/applications/external/jetpack_joyride/jetpack.c
index c12f094c9..7969300bd 100644
--- a/applications/external/jetpack_joyride/jetpack.c
+++ b/applications/external/jetpack_joyride/jetpack.c
@@ -18,8 +18,7 @@
#include "includes/game_state.h"
#define TAG "Jetpack Joyride"
-#define SAVING_DIRECTORY "/ext/apps/Games"
-#define SAVING_FILENAME SAVING_DIRECTORY "/jetpack.save"
+#define SAVING_FILENAME APP_DATA_PATH("jetpack.save")
static GameState* global_state;
typedef enum {
@@ -41,6 +40,7 @@ static SaveGame save_game;
static bool storage_game_state_load() {
Storage* storage = furi_record_open(RECORD_STORAGE);
+ storage_common_migrate(storage, EXT_PATH("apps/Games/jetpack.save"), SAVING_FILENAME);
File* file = storage_file_alloc(storage);
uint16_t bytes_readed = 0;
@@ -55,12 +55,6 @@ static bool storage_game_state_load() {
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));
@@ -376,4 +370,4 @@ free_and_exit:
furi_message_queue_free(event_queue);
return return_code;
-}
\ No newline at end of file
+}
diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c b/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c
index cc2ba138f..ac48a1008 100644
--- a/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c
+++ b/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c
@@ -49,8 +49,7 @@ int32_t mifare_fuzzer_worker_task(void* context) {
furi_hal_nfc_exit_sleep();
while(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) {
- furi_hal_nfc_listen(
- params.uid, params.uid_len, params.a_data.atqa, params.a_data.sak, false, 500);
+ furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 500);
furi_delay_ms(50);
}
furi_hal_nfc_sleep();
diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c
index 4e4be5dfd..d2e05b7e6 100644
--- a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c
+++ b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c
@@ -42,9 +42,9 @@ void mifare_fuzzer_scene_emulator_on_enter(void* context) {
app->emulator_view, emulator->ticks_between_cards);
// init default card data
FuriHalNfcDevData nfc_dev_data;
- nfc_dev_data.a_data.atqa[0] = 0x00;
- nfc_dev_data.a_data.atqa[1] = 0x00;
- nfc_dev_data.a_data.sak = 0x00;
+ nfc_dev_data.atqa[0] = 0x00;
+ nfc_dev_data.atqa[1] = 0x00;
+ nfc_dev_data.sak = 0x00;
if(app->card == MifareCardUltralight) {
nfc_dev_data.uid_len = 0x07;
} else {
@@ -84,19 +84,19 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
// Set card type
// TODO: Move somewhere else, I do not like this to be there
if(app->card == MifareCardClassic1k) {
- nfc_dev_data.a_data.atqa[0] = 0x04;
- nfc_dev_data.a_data.atqa[1] = 0x00;
- nfc_dev_data.a_data.sak = 0x08;
+ nfc_dev_data.atqa[0] = 0x04;
+ nfc_dev_data.atqa[1] = 0x00;
+ nfc_dev_data.sak = 0x08;
nfc_dev_data.uid_len = 0x04;
} else if(app->card == MifareCardClassic4k) {
- nfc_dev_data.a_data.atqa[0] = 0x02;
- nfc_dev_data.a_data.atqa[1] = 0x00;
- nfc_dev_data.a_data.sak = 0x18;
+ nfc_dev_data.atqa[0] = 0x02;
+ nfc_dev_data.atqa[1] = 0x00;
+ nfc_dev_data.sak = 0x18;
nfc_dev_data.uid_len = 0x04;
} else if(app->card == MifareCardUltralight) {
- nfc_dev_data.a_data.atqa[0] = 0x44;
- nfc_dev_data.a_data.atqa[1] = 0x00;
- nfc_dev_data.a_data.sak = 0x00;
+ nfc_dev_data.atqa[0] = 0x44;
+ nfc_dev_data.atqa[1] = 0x00;
+ nfc_dev_data.sak = 0x00;
nfc_dev_data.uid_len = 0x07;
}
diff --git a/applications/external/mifare_nested/mifare_nested_worker.c b/applications/external/mifare_nested/mifare_nested_worker.c
index 884dd1685..0b8097653 100644
--- a/applications/external/mifare_nested/mifare_nested_worker.c
+++ b/applications/external/mifare_nested/mifare_nested_worker.c
@@ -708,8 +708,7 @@ void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_neste
FuriString* folder_path = furi_string_alloc();
FuriHalNfcDevData data = {};
nested_get_data(&data);
- MfClassicType type = mifare_nested_worker_get_tag_type(
- data.a_data.atqa[0], data.a_data.atqa[1], data.a_data.sak);
+ 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;
@@ -872,8 +871,7 @@ void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_
FuriString* folder_path = furi_string_alloc();
FuriHalNfcDevData data = {};
nested_get_data(&data);
- MfClassicType type = mifare_nested_worker_get_tag_type(
- data.a_data.atqa[0], data.a_data.atqa[1], data.a_data.sak);
+ 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;
@@ -1122,8 +1120,7 @@ void mifare_nested_worker_collect_nonces(MifareNestedWorker* mifare_nested_worke
FuriString* folder_path = furi_string_alloc();
FuriHalNfcDevData data = {};
nested_get_data(&data);
- MfClassicType type = mifare_nested_worker_get_tag_type(
- data.a_data.atqa[0], data.a_data.atqa[1], data.a_data.sak);
+ 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;
@@ -1257,7 +1254,7 @@ void mifare_nested_worker_collect_nonces(MifareNestedWorker* mifare_nested_worke
MifareNestedWorkerEventNoTagDetected, mifare_nested_worker->context);
while(mifare_nested_worker->state == MifareNestedWorkerStateCollecting &&
- lost_tag_data.a_data.cuid != data.a_data.cuid) {
+ lost_tag_data.cuid != data.cuid) {
furi_delay_ms(250);
nested_get_data(&lost_tag_data);
}
@@ -1497,8 +1494,7 @@ void mifare_nested_worker_check_keys(MifareNestedWorker* mifare_nested_worker) {
FuriString* path = furi_string_alloc();
FuriHalNfcDevData data = {};
nested_get_data(&data);
- MfClassicType type = mifare_nested_worker_get_tag_type(
- data.a_data.atqa[0], data.a_data.atqa[1], data.a_data.sak);
+ 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;
@@ -1714,4 +1710,4 @@ void mifare_nested_worker_check_keys(MifareNestedWorker* mifare_nested_worker) {
MifareNestedWorkerEventKeysFound, mifare_nested_worker->context);
return;
-}
+}
\ No newline at end of file
diff --git a/applications/external/nfc_magic/nfc_magic_worker.c b/applications/external/nfc_magic/nfc_magic_worker.c
index 25af77049..86f521b2b 100644
--- a/applications/external/nfc_magic/nfc_magic_worker.c
+++ b/applications/external/nfc_magic/nfc_magic_worker.c
@@ -186,9 +186,9 @@ void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
}
gen4_config[7] = 0x00;
memset(gen4_config + 8, 0, 16);
- gen4_config[24] = dev_data->nfc_data.a_data.atqa[0];
- gen4_config[25] = dev_data->nfc_data.a_data.atqa[1];
- gen4_config[26] = dev_data->nfc_data.a_data.sak;
+ 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);
@@ -308,7 +308,7 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
}
if(furi_hal_nfc_detect(&nfc_data, 200)) {
- magic_dev->cuid = nfc_data.a_data.cuid;
+ magic_dev->cuid = nfc_data.cuid;
magic_dev->uid_len = nfc_data.uid_len;
} else {
// wrong BCC
@@ -320,7 +320,7 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
magic_deactivate();
magic_activate();
if(furi_hal_nfc_detect(&nfc_data, 200)) {
- magic_dev->cuid = nfc_data.a_data.cuid;
+ 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;
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
index 1d2f61d28..a194f83b4 100644
--- a/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_url.c
+++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_contact_url.c
@@ -28,6 +28,8 @@ void nfc_maker_scene_contact_url_on_enter(void* context) {
text_input_set_minimum_length(text_input, 0);
+ text_input_add_illegal_symbols(text_input);
+
view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput);
}
diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c
index a814f8e22..a7383c59b 100644
--- a/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c
+++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c
@@ -26,6 +26,8 @@ void nfc_maker_scene_https_on_enter(void* context) {
BIG_INPUT_LEN,
true);
+ text_input_add_illegal_symbols(text_input);
+
view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput);
}
diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c
index 4c86f3b52..2e53c3cf3 100644
--- a/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c
+++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c
@@ -26,6 +26,8 @@ void nfc_maker_scene_text_on_enter(void* context) {
BIG_INPUT_LEN,
true);
+ text_input_add_illegal_symbols(text_input);
+
view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput);
}
diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c
index f5d2eddaa..d2de8745e 100644
--- a/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c
+++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c
@@ -26,6 +26,8 @@ void nfc_maker_scene_url_on_enter(void* context) {
BIG_INPUT_LEN,
true);
+ text_input_add_illegal_symbols(text_input);
+
view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput);
}
diff --git a/applications/external/nrf24mousejacker/mousejacker.c b/applications/external/nrf24mousejacker/mousejacker.c
index 5b3cce336..03119e021 100644
--- a/applications/external/nrf24mousejacker/mousejacker.c
+++ b/applications/external/nrf24mousejacker/mousejacker.c
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include
#include "mousejacker_ducky.h"
#include
@@ -290,6 +291,8 @@ int32_t mousejacker_app(void* p) {
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);
@@ -308,10 +311,6 @@ int32_t mousejacker_app(void* p) {
furi_thread_set_context(plugin_state->mjthread, plugin_state);
furi_thread_set_callback(plugin_state->mjthread, mj_worker_thread);
- while(!furi_hal_speaker_acquire(100)) {
- furi_delay_ms(100);
- }
-
// spawn load file dialog to choose sniffed addresses file
if(load_addrs_file(plugin_state->file_stream)) {
addr_idx = 0;
@@ -356,9 +355,7 @@ int32_t mousejacker_app(void* p) {
if(!nrf24_check_connected(nrf24_HANDLE)) {
plugin_state->is_nrf24_connected = false;
view_port_update(view_port);
- furi_hal_speaker_start(100, 100);
- furi_delay_ms(100);
- furi_hal_speaker_stop();
+ notification_message(notification, &sequence_error);
} else if(!plugin_state->is_thread_running) {
furi_thread_start(plugin_state->mjthread);
view_port_update(view_port);
@@ -387,9 +384,9 @@ int32_t mousejacker_app(void* p) {
furi_thread_free(plugin_state->mjthread);
nrf24_deinit();
- furi_hal_speaker_release();
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
+ furi_record_close(RECORD_NOTIFICATION);
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_STORAGE);
view_port_free(view_port);
diff --git a/applications/external/nrf24sniff/nrfsniff.c b/applications/external/nrf24sniff/nrfsniff.c
index 18cbe6fb7..cad16f349 100644
--- a/applications/external/nrf24sniff/nrfsniff.c
+++ b/applications/external/nrf24sniff/nrfsniff.c
@@ -404,9 +404,7 @@ int32_t nrfsniff_app(void* p) {
wrap_up(storage, notification);
}
} else {
- furi_hal_speaker_start(100, 100);
- furi_delay_ms(100);
- furi_hal_speaker_stop();
+ notification_message(notification, &sequence_error);
}
break;
diff --git a/applications/external/spectrum_analyzer/spectrum_analyzer.c b/applications/external/spectrum_analyzer/spectrum_analyzer.c
index fd31a6935..bbecad642 100644
--- a/applications/external/spectrum_analyzer/spectrum_analyzer.c
+++ b/applications/external/spectrum_analyzer/spectrum_analyzer.c
@@ -11,7 +11,7 @@
#include "spectrum_analyzer_worker.h"
typedef struct {
- uint16_t center_freq;
+ uint32_t center_freq;
uint8_t width;
uint8_t band;
uint8_t vscroll;
@@ -53,39 +53,55 @@ void spectrum_analyzer_draw_scale(Canvas* canvas, const SpectrumAnalyzerModel* m
}
// Draw scale tags
- uint16_t tag_left;
- uint16_t tag_center;
- uint16_t tag_right;
+ 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 - 2;
- tag_right = model->center_freq + 2;
+ tag_left = model->center_freq - 2000;
+ tag_right = model->center_freq + 2000;
break;
case ULTRANARROW:
- tag_left = model->center_freq - 1;
- tag_right = model->center_freq + 1;
+ 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 - 40;
- tag_right = model->center_freq + 40;
+ tag_left = model->center_freq - 40000;
+ tag_right = model->center_freq + 40000;
break;
default:
- tag_left = model->center_freq - 10;
- tag_right = model->center_freq + 10;
+ tag_left = model->center_freq - 10000;
+ tag_right = model->center_freq + 10000;
}
canvas_set_font(canvas, FontSecondary);
- snprintf(temp_str, 18, "%u", tag_left);
- canvas_draw_str_aligned(canvas, FREQ_START_X, 63, AlignCenter, AlignBottom, temp_str);
- snprintf(temp_str, 18, "%u", tag_center);
- canvas_draw_str_aligned(canvas, 128 / 2, 63, AlignCenter, AlignBottom, temp_str);
- snprintf(temp_str, 18, "%u", tag_right);
- canvas_draw_str_aligned(
- canvas, FREQ_START_X + FREQ_LENGTH_X - 1, 63, AlignCenter, AlignBottom, temp_str);
+ switch(model->width) {
+ case PRECISE:
+ 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) {
@@ -115,6 +131,9 @@ static void spectrum_analyzer_render_callback(Canvas* const canvas, void* ctx) {
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;
@@ -207,12 +226,12 @@ void spectrum_analyzer_calculate_frequencies(SpectrumAnalyzerModel* model) {
uint8_t new_band;
uint32_t min_hz;
uint32_t max_hz;
- uint8_t margin;
- uint8_t step;
- uint16_t upper_limit;
- uint16_t lower_limit;
- uint16_t next_up;
- uint16_t next_down;
+ 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;
@@ -227,19 +246,24 @@ void spectrum_analyzer_calculate_frequencies(SpectrumAnalyzerModel* model) {
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 + 10) / 20) * 20;
+ 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 + 2) / 5) * 5;
+ model->center_freq = ((model->center_freq + 2000) / 5000) * 5000;
break;
}
@@ -288,21 +312,21 @@ void spectrum_analyzer_calculate_frequencies(SpectrumAnalyzerModel* model) {
/* doing everything in Hz from here on */
switch(model->band) {
case BAND_400:
- min_hz = MIN_400 * 1000000;
- max_hz = MAX_400 * 1000000;
+ min_hz = MIN_400 * 1000;
+ max_hz = MAX_400 * 1000;
break;
case BAND_300:
- min_hz = MIN_300 * 1000000;
- max_hz = MAX_300 * 1000000;
+ min_hz = MIN_300 * 1000;
+ max_hz = MAX_300 * 1000;
break;
default:
- min_hz = MIN_900 * 1000000;
- max_hz = MAX_900 * 1000000;
+ min_hz = MIN_900 * 1000;
+ max_hz = MAX_900 * 1000;
break;
}
model->channel0_frequency =
- model->center_freq * 1000000 - (model->spacing * ((NUM_CHANNELS / 2) + 1));
+ model->center_freq * 1000 - (model->spacing * ((NUM_CHANNELS / 2) + 1));
// /* calibrate upper channels */
// hz = model->center_freq * 1000000;
@@ -328,7 +352,7 @@ void spectrum_analyzer_calculate_frequencies(SpectrumAnalyzerModel* model) {
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: %u", model->center_freq);
+ FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
FURI_LOG_D(
"Spectrum",
"ch[0]: %lu - ch[%u]: %lu",
@@ -425,7 +449,7 @@ int32_t spectrum_analyzer_app(void* p) {
SpectrumAnalyzerModel* model = spectrum_analyzer->model;
uint8_t vstep = VERTICAL_SHORT_STEP;
- uint8_t hstep;
+ uint32_t hstep;
bool exit_loop = false;
@@ -455,7 +479,7 @@ int32_t spectrum_analyzer_app(void* p) {
break;
case InputKeyRight:
model->center_freq += hstep;
- FURI_LOG_D("Spectrum", "center_freq: %u", model->center_freq);
+ 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);
@@ -465,7 +489,7 @@ int32_t spectrum_analyzer_app(void* p) {
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: %u", model->center_freq);
+ FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
break;
case InputKeyOk: {
switch(model->width) {
@@ -476,6 +500,9 @@ int32_t spectrum_analyzer_app(void* p) {
model->width = ULTRANARROW;
break;
case ULTRANARROW:
+ model->width = PRECISE;
+ break;
+ case PRECISE:
model->width = ULTRAWIDE;
break;
case ULTRAWIDE:
diff --git a/applications/external/spectrum_analyzer/spectrum_analyzer.h b/applications/external/spectrum_analyzer/spectrum_analyzer.h
index b5cd6d8fe..7595f625c 100644
--- a/applications/external/spectrum_analyzer/spectrum_analyzer.h
+++ b/applications/external/spectrum_analyzer/spectrum_analyzer.h
@@ -15,17 +15,20 @@
* 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
+ * pricse 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
@@ -33,36 +36,40 @@
#define MIN_VSCROLL 0
#define DEFAULT_VSCROLL 48
-/* frequencies in MHz */
-#define DEFAULT_FREQ 440
-#define WIDE_STEP 5
-#define NARROW_STEP 1
-#define ULTRAWIDE_STEP 20
-#define ULTRANARROW_STEP 1
-#define WIDE_MARGIN 13
-#define NARROW_MARGIN 3
-#define ULTRAWIDE_MARGIN 42
-#define ULTRANARROW_MARGIN 1
+/* 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 MHz */
-#define MIN_300 281
-#define CEN_300 315
-#define MAX_300 361
-#define MIN_400 378
-#define CEN_400 435
-#define MAX_400 481
-#define MIN_900 749
-#define CEN_900 855
-#define MAX_900 962
+/* 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 MHz */
-#define EDGE_400 369
-#define EDGE_900 615
+/* band transition points in KHz */
+#define EDGE_400 369000
+#define EDGE_900 615000
/* VCO transition points in Hz */
#define MID_300 318000000
diff --git a/applications/main/application.fam b/applications/main/application.fam
index 0af6617d7..6f1be721b 100644
--- a/applications/main/application.fam
+++ b/applications/main/application.fam
@@ -13,7 +13,6 @@ App(
"u2f",
"xtreme_app",
"archive",
- "nightstand",
"main_apps_on_start",
],
)
diff --git a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c
index 587cb748c..b293af952 100644
--- a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c
+++ b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c
@@ -12,15 +12,15 @@ void ibutton_scene_delete_confirm_on_enter(void* context) {
widget_add_button_element(
widget, GuiButtonTypeRight, "Delete", ibutton_widget_callback, context);
- furi_string_printf(tmp, "Delete %s?", ibutton->key_name);
- widget_add_string_element(
- widget, 128 / 2, 0, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(tmp));
+ furi_string_printf(tmp, "\e#Delete %s?\e#", ibutton->key_name);
+ widget_add_text_box_element(
+ widget, 0, 0, 128, 23, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), false);
furi_string_reset(tmp);
ibutton_protocols_render_brief_data(ibutton->protocols, key, tmp);
widget_add_string_multiline_element(
- widget, 128 / 2, 16, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp));
+ widget, 128 / 2, 24, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp));
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
furi_string_free(tmp);
diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c
index aa3f74c36..0b7e75475 100644
--- a/applications/main/nfc/nfc_cli.c
+++ b/applications/main/nfc/nfc_cli.c
@@ -34,25 +34,13 @@ static void nfc_cli_detect(Cli* cli, FuriString* args) {
while(!cmd_exit) {
cmd_exit |= cli_cmd_interrupt_received(cli);
if(furi_hal_nfc_detect(&dev_data, 400)) {
- if(dev_data.type == FuriHalNfcTypeA) {
- printf("UID length: %d, UID:", dev_data.uid_len);
- for(size_t i = 0; i < dev_data.uid_len; i++) {
- printf("%02X", dev_data.uid[i]);
- }
- printf("\r\n");
- break;
- } else if(dev_data.type == FuriHalNfcTypeF) {
- printf("IDm:");
- for(size_t i = 0; i < 8; i++) {
- printf("%02X", dev_data.uid[i]);
- }
- printf(", PMm:");
- for(size_t i = 0; i < 8; i++) {
- printf("%02X", dev_data.f_data.pmm[i]);
- }
- printf("\r\n");
- break;
+ printf("Found: %s ", nfc_get_dev_type(dev_data.type));
+ printf("UID length: %d, UID:", dev_data.uid_len);
+ for(size_t i = 0; i < dev_data.uid_len; i++) {
+ printf("%02X", dev_data.uid[i]);
}
+ printf("\r\n");
+ break;
}
furi_hal_nfc_sleep();
furi_delay_ms(50);
@@ -75,17 +63,13 @@ static void nfc_cli_emulate(Cli* cli, FuriString* args) {
FuriHalNfcDevData params = {
.uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1, 0x34},
.uid_len = 7,
- .a_data =
- {
- .atqa = {0x44, 0x00},
- .sak = 0x00,
- },
+ .atqa = {0x44, 0x00},
+ .sak = 0x00,
.type = FuriHalNfcTypeA,
};
while(!cli_cmd_interrupt_received(cli)) {
- if(furi_hal_nfc_listen(
- params.uid, params.uid_len, params.a_data.atqa, params.a_data.sak, false, 100)) {
+ if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 100)) {
printf("Reader detected\r\n");
furi_hal_nfc_sleep();
}
diff --git a/applications/main/nfc/nfc_i.h b/applications/main/nfc/nfc_i.h
index 7331b9405..f7e489902 100644
--- a/applications/main/nfc/nfc_i.h
+++ b/applications/main/nfc/nfc_i.h
@@ -39,23 +39,13 @@
#include "rpc/rpc_app.h"
-#include
#include
-ARRAY_DEF(FelicaAreaPath, FelicaArea*, M_PTR_OPLIST)
-ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST)
+ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST);
#define NFC_TEXT_STORE_SIZE 128
#define NFC_APP_FOLDER ANY_PATH("nfc")
-typedef struct {
- FelicaSystem* selected_system;
-
- FelicaAreaPath_t selected_areas;
-
- FelicaService* selected_service;
-} FelicaSelectState;
-
typedef enum {
NfcRpcStateIdle,
NfcRpcStateEmulating,
@@ -75,7 +65,6 @@ struct Nfc {
FuriString* text_box_store;
uint8_t byte_input_store[6];
MfClassicUserKeys_t mfc_key_strs; // Used in MFC key listing
- FelicaSelectState felica_select;
void* rpc_ctx;
NfcRpcState rpc_state;
diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h
index 5414e11a2..f11d14798 100644
--- a/applications/main/nfc/scenes/nfc_scene_config.h
+++ b/applications/main/nfc/scenes/nfc_scene_config.h
@@ -21,8 +21,6 @@ ADD_SCENE(nfc, nfcv_unlock, NfcVUnlock)
ADD_SCENE(nfc, nfcv_emulate, NfcVEmulate)
ADD_SCENE(nfc, nfcv_sniff, NfcVSniff)
ADD_SCENE(nfc, nfcv_read_success, NfcVReadSuccess)
-ADD_SCENE(nfc, nfcf_read_success, NfcfReadSuccess)
-ADD_SCENE(nfc, nfcf_menu, NfcfMenu)
ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess)
ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData)
ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu)
@@ -55,10 +53,6 @@ ADD_SCENE(nfc, mf_classic_update_success, MfClassicUpdateSuccess)
ADD_SCENE(nfc, mf_classic_wrong_card, MfClassicWrongCard)
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
ADD_SCENE(nfc, emv_menu, EmvMenu)
-ADD_SCENE(nfc, felica_read_success, FelicaReadSuccess)
-ADD_SCENE(nfc, felica_menu, FelicaMenu)
-ADD_SCENE(nfc, felica_info_select, FelicaInfoSelect)
-ADD_SCENE(nfc, felica_service_data, FelicaServiceData)
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
ADD_SCENE(nfc, device_info, DeviceInfo)
ADD_SCENE(nfc, delete, Delete)
diff --git a/applications/main/nfc/scenes/nfc_scene_delete.c b/applications/main/nfc/scenes/nfc_scene_delete.c
index 8b712e948..0808db45a 100644
--- a/applications/main/nfc/scenes/nfc_scene_delete.c
+++ b/applications/main/nfc/scenes/nfc_scene_delete.c
@@ -44,8 +44,6 @@ void nfc_scene_delete_on_enter(void* context) {
} else if(protocol == NfcDeviceProtocolNfcV) {
furi_string_set(temp_str, "ISO15693 tag");
nfc_type = "NFC-V";
- } else if(protocol == NfcDeviceProtocolFelica) {
- furi_string_set(temp_str, "FeliCa");
} else {
furi_string_set(temp_str, "Unknown ISO tag");
}
diff --git a/applications/main/nfc/scenes/nfc_scene_felica_info_select.c b/applications/main/nfc/scenes/nfc_scene_felica_info_select.c
deleted file mode 100644
index 7a59521fa..000000000
--- a/applications/main/nfc/scenes/nfc_scene_felica_info_select.c
+++ /dev/null
@@ -1,152 +0,0 @@
-#include "../nfc_i.h"
-#include
-
-void nfc_scene_felica_info_select_submenu_callback(void* context, uint32_t index) {
- Nfc* nfc = context;
-
- view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
-}
-
-void nfc_scene_felica_info_select_on_enter(void* context) {
- Nfc* nfc = context;
- Submenu* submenu = nfc->submenu;
- FelicaData* data = &nfc->dev->dev_data.felica_data;
- FelicaSelectState* state = &nfc->felica_select;
-
- FelicaAreaPath_init(nfc->felica_select.selected_areas);
-
- submenu_add_item(submenu, "[Actions]", 0, nfc_scene_felica_info_select_submenu_callback, nfc);
- uint8_t i = 1;
- if(state->selected_system == NULL || state->selected_system->code == LITE_SYSTEM_CODE) {
- submenu_set_header(submenu, "Systems");
- for
- M_EACH(current_system, data->systems, FelicaSystemArray_t) {
- FuriString* system_name = felica_get_system_name(current_system);
- submenu_add_item(
- submenu,
- furi_string_get_cstr(system_name),
- i++,
- nfc_scene_felica_info_select_submenu_callback,
- nfc);
- furi_string_free(system_name);
- }
- } else {
- FelicaSystem* system = state->selected_system;
- FuriString* header = furi_string_alloc_printf("%04X/", system->code);
-
- FelicaNode* root = &system->root;
- furi_assert(root->type == FelicaNodeTypeArea);
- FelicaArea* area = root->area;
- if(FelicaAreaPath_size(state->selected_areas) > 0) {
- FelicaAreaPath_it_t it;
- for(FelicaAreaPath_it(it, state->selected_areas); !FelicaAreaPath_end_p(it);
- FelicaAreaPath_next(it)) {
- FelicaArea* ancestor = *FelicaAreaPath_ref(it);
- furi_string_cat_printf(header, "%d/", ancestor->number);
- }
- area = *FelicaAreaPath_back(state->selected_areas);
- }
- furi_string_cat(header, "Areas");
-
- submenu_set_header(submenu, furi_string_get_cstr(header));
- furi_string_free(header);
-
- for
- M_EACH(node, area->nodes, FelicaNodeArray_t) {
- FuriString* node_name = furi_string_alloc();
- if(node->type == FelicaNodeTypeArea) {
- furi_string_printf(node_name, "Area %d", node->area->number);
- submenu_add_item(
- submenu,
- furi_string_get_cstr(node_name),
- i++,
- nfc_scene_felica_info_select_submenu_callback,
- nfc);
- } else {
- uint16_t service_code = node->service->number << 6;
- furi_string_printf(node_name, "Service %04X", service_code);
- submenu_add_item(
- submenu,
- furi_string_get_cstr(node_name),
- i++,
- nfc_scene_felica_info_select_submenu_callback,
- nfc);
- }
-
- furi_string_free(node_name);
- }
- }
-
- state->selected_service = NULL;
- submenu_set_selected_item(
- nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneFelicaInfoSelect));
-
- view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
-}
-
-bool nfc_scene_felica_info_select_on_event(void* context, SceneManagerEvent event) {
- Nfc* nfc = context;
- FelicaData* data = &nfc->dev->dev_data.felica_data;
- FelicaSelectState* state = &nfc->felica_select;
- bool consumed = false;
-
- if(event.type == SceneManagerEventTypeCustom) {
- uint8_t index = event.event;
- scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu, index);
-
- if(index == 0) {
- return false;
- }
-
- index -= 1;
- if(state->selected_system == NULL) {
- state->selected_system = FelicaSystemArray_get(data->systems, index);
- if(state->selected_system->code == LITE_SYSTEM_CODE) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaServiceData);
- } else {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaInfoSelect);
- }
- consumed = true;
- } else {
- FelicaNode* selected_node = NULL;
-
- FelicaNode* root = &(state->selected_system->root);
- furi_assert(root->type == FelicaNodeTypeArea);
-
- if(FelicaAreaPath_size(state->selected_areas) == 0) {
- selected_node = FelicaNodeArray_get(root->area->nodes, index);
- } else {
- FelicaArea* current_area = *FelicaAreaPath_back(state->selected_areas);
- selected_node = FelicaNodeArray_get(current_area->nodes, index);
- }
-
- if(selected_node->type == FelicaNodeTypeArea) {
- FelicaAreaPath_push_back(state->selected_areas, selected_node->area);
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaInfoSelect);
- consumed = true;
- } else if(selected_node->type == FelicaNodeTypeService) {
- state->selected_service = selected_node->service;
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaServiceData);
- consumed = true;
- }
- }
- } else if(event.type == SceneManagerEventTypeBack) {
- if(FelicaAreaPath_size(state->selected_areas) <= 1) {
- FelicaAreaPath_clear(state->selected_areas);
- state->selected_system = NULL;
- } else {
- FelicaAreaPath_pop_back(NULL, state->selected_areas);
- }
- consumed = scene_manager_previous_scene(nfc->scene_manager);
- }
-
- return consumed;
-}
-
-void nfc_scene_felica_info_select_on_exit(void* context) {
- Nfc* nfc = context;
-
- // Clear view
- FelicaAreaPath_clear(nfc->felica_select.selected_areas);
- submenu_reset(nfc->submenu);
-}
diff --git a/applications/main/nfc/scenes/nfc_scene_felica_menu.c b/applications/main/nfc/scenes/nfc_scene_felica_menu.c
deleted file mode 100644
index b8e653e20..000000000
--- a/applications/main/nfc/scenes/nfc_scene_felica_menu.c
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "../nfc_i.h"
-#include
-
-enum SubmenuIndex {
- /*
- SubmenuIndexUnlock,
- */
- SubmenuIndexSave,
- /*
- SubmenuIndexEmulate,
- */
- SubmenuIndexInfo,
-};
-
-void nfc_scene_felica_menu_submenu_callback(void* context, uint32_t index) {
- Nfc* nfc = context;
-
- view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
-}
-
-void nfc_scene_felica_menu_on_enter(void* context) {
- Nfc* nfc = context;
- Submenu* submenu = nfc->submenu;
- // FelicaData* data = &nfc->dev->dev_data.felica_data;
-
- /*
- submenu_add_item(
- submenu, "Unlock", SubmenuIndexUnlock, nfc_scene_felica_menu_submenu_callback, nfc);
- */
- submenu_add_item(
- submenu, "Save", SubmenuIndexSave, nfc_scene_felica_menu_submenu_callback, nfc);
- /*
- submenu_add_item(
- submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_felica_menu_submenu_callback, nfc);
- */
- submenu_add_item(
- submenu, "Info", SubmenuIndexInfo, nfc_scene_felica_menu_submenu_callback, nfc);
-
- submenu_set_selected_item(
- nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneFelicaMenu));
-
- view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
-}
-
-bool nfc_scene_felica_menu_on_event(void* context, SceneManagerEvent event) {
- Nfc* nfc = context;
- bool consumed = false;
-
- if(event.type == SceneManagerEventTypeCustom) {
- if(event.event == SubmenuIndexSave) {
- nfc->dev->format = NfcDeviceSaveFormatFelica;
- // Clear device name
- nfc_device_set_name(nfc->dev, "");
- scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
- consumed = true;
- /*
- } else if(event.event == SubmenuIndexEmulate) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaEmulate);
- if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
- dolphin_deed(DolphinDeedNfcAddEmulate);
- } else {
- dolphin_deed(DolphinDeedNfcEmulate);
- }
- consumed = true;
- } else if(event.event == SubmenuIndexUnlock) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaUnlockMenu);
- consumed = true;
- */
- } else if(event.event == SubmenuIndexInfo) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaInfoSelect);
- consumed = true;
- }
- scene_manager_set_scene_state(nfc->scene_manager, NfcSceneFelicaMenu, event.event);
-
- } else if(event.type == SceneManagerEventTypeBack) {
- consumed = scene_manager_previous_scene(nfc->scene_manager);
- }
-
- return consumed;
-}
-
-void nfc_scene_felica_menu_on_exit(void* context) {
- Nfc* nfc = context;
-
- // Clear view
- submenu_reset(nfc->submenu);
-}
diff --git a/applications/main/nfc/scenes/nfc_scene_felica_read_success.c b/applications/main/nfc/scenes/nfc_scene_felica_read_success.c
deleted file mode 100644
index 79dd82297..000000000
--- a/applications/main/nfc/scenes/nfc_scene_felica_read_success.c
+++ /dev/null
@@ -1,81 +0,0 @@
-#include "../nfc_i.h"
-
-void nfc_scene_felica_read_success_widget_callback(
- GuiButtonType result,
- InputType type,
- void* context) {
- furi_assert(context);
- Nfc* nfc = context;
-
- if(type == InputTypeShort) {
- view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
- }
-}
-
-void nfc_scene_felica_read_success_on_enter(void* context) {
- Nfc* nfc = context;
- FelicaData* felica_data = &nfc->dev->dev_data.felica_data;
-
- // Setup view
- Widget* widget = nfc->widget;
- widget_add_button_element(
- widget, GuiButtonTypeLeft, "Retry", nfc_scene_felica_read_success_widget_callback, nfc);
- widget_add_button_element(
- widget, GuiButtonTypeRight, "More", nfc_scene_felica_read_success_widget_callback, nfc);
-
- FuriString* temp_str = NULL;
- if(furi_string_size(nfc->dev->dev_data.parsed_data)) {
- temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data);
- } else {
- temp_str = furi_string_alloc_printf("\e#%s", nfc_felica_type(felica_data->type));
-
- for
- M_EACH(current_system, felica_data->systems, FelicaSystemArray_t) {
- furi_string_cat_printf(
- temp_str, "\nSystem %04X (#%d):", current_system->code, current_system->number);
- furi_string_cat_printf(temp_str, "\nIDm:\n ");
- for(size_t i = 0; i < 8; i++) {
- furi_string_cat_printf(temp_str, "%02X", current_system->idm[i]);
- }
- furi_string_cat_printf(temp_str, "\nPMm:\n ");
- for(size_t i = 0; i < 8; i++) {
- furi_string_cat_printf(temp_str, "%02X", current_system->pmm[i]);
- }
- }
- }
-
- widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
- furi_string_free(temp_str);
-
- notification_message_block(nfc->notifications, &sequence_set_green_255);
-
- view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
-}
-
-bool nfc_scene_felica_read_success_on_event(void* context, SceneManagerEvent event) {
- Nfc* nfc = context;
- bool consumed = false;
-
- if(event.type == SceneManagerEventTypeCustom) {
- if(event.event == GuiButtonTypeLeft) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
- consumed = true;
- } else if(event.event == GuiButtonTypeRight) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaMenu);
- consumed = true;
- }
- } else if(event.type == SceneManagerEventTypeBack) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
- consumed = true;
- }
- return consumed;
-}
-
-void nfc_scene_felica_read_success_on_exit(void* context) {
- Nfc* nfc = context;
-
- notification_message_block(nfc->notifications, &sequence_reset_green);
-
- // Clear view
- widget_reset(nfc->widget);
-}
diff --git a/applications/main/nfc/scenes/nfc_scene_felica_service_data.c b/applications/main/nfc/scenes/nfc_scene_felica_service_data.c
deleted file mode 100644
index 5153d7d37..000000000
--- a/applications/main/nfc/scenes/nfc_scene_felica_service_data.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#include "../nfc_i.h"
-
-void nfc_scene_felica_service_data_on_enter(void* context) {
- Nfc* nfc = context;
- FelicaSelectState* select_state = &nfc->felica_select;
- FelicaSystem* system = select_state->selected_system;
- //FelicaService* service = select_state->selected_service;
- TextBox* text_box = nfc->text_box;
-
- if(system->code == LITE_SYSTEM_CODE) {
- FelicaLiteInfo* lite_info = &system->lite_info;
- uint8_t* data;
- text_box_set_font(text_box, TextBoxFontHex);
- furi_string_cat_str(nfc->text_box_store, "S_PAD:\n");
- for(int i = 0; i < REG_LITE_BLOCK; i++) {
- data = lite_info->S_PAD[i];
- for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
- if(!(i % 8) && i) {
- furi_string_push_back(nfc->text_box_store, '\n');
- }
- if(data != NULL) {
- furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
- } else {
- furi_string_cat_printf(nfc->text_box_store, "???? ");
- }
- }
- }
-
- furi_string_cat_str(nfc->text_box_store, "REG:\n");
- data = lite_info->REG;
- for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
- if(!(i % 8) && i) {
- furi_string_push_back(nfc->text_box_store, '\n');
- }
- if(data != NULL) {
- furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
- } else {
- furi_string_cat_printf(nfc->text_box_store, "???? ");
- }
- }
-
- furi_string_cat_str(nfc->text_box_store, "MAC:\n");
- data = lite_info->MAC;
- for(uint16_t i = 0; i < 8; i += 2) {
- if(!(i % 8) && i) {
- furi_string_push_back(nfc->text_box_store, '\n');
- }
- furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
- }
-
- furi_string_cat_printf(nfc->text_box_store, "DFC: %04X\n", lite_info->data_format_code);
-
- furi_string_cat_str(nfc->text_box_store, "ID data:\n");
- data = lite_info->ID_value;
- for(uint16_t i = 0; i < 6; i += 2) {
- furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
- }
- furi_string_cat_str(nfc->text_box_store, "\n");
-
- furi_string_cat_printf(nfc->text_box_store, "CKV: %04X\n", lite_info->card_key_version);
-
- furi_string_cat_str(nfc->text_box_store, "MC:\n");
- data = lite_info->memory_config;
- for(uint16_t i = 0; i < FELICA_BLOCK_SIZE; i += 2) {
- if(!(i % 8) && i) {
- furi_string_push_back(nfc->text_box_store, '\n');
- }
- furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
- }
-
- furi_string_cat_printf(nfc->text_box_store, "WCNT: %06lX\n", lite_info->write_count);
-
- furi_string_cat_str(nfc->text_box_store, "MAC_A:\n");
- data = lite_info->MAC_A;
- for(uint16_t i = 0; i < 8; i += 2) {
- if(!(i % 8) && i) {
- furi_string_push_back(nfc->text_box_store, '\n');
- }
- furi_string_cat_printf(nfc->text_box_store, "%02X%02X ", data[i], data[i + 1]);
- }
- }
- text_box_set_text(text_box, furi_string_get_cstr(nfc->text_box_store));
-
- view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
-}
-
-bool nfc_scene_felica_service_data_on_event(void* context, SceneManagerEvent event) {
- Nfc* nfc = context;
- bool consumed = false;
-
- if(event.type == SceneManagerEventTypeBack) {
- consumed = scene_manager_previous_scene(nfc->scene_manager);
- }
-
- return consumed;
-}
-
-void nfc_scene_felica_service_data_on_exit(void* context) {
- Nfc* nfc = context;
-
- // Clean view
- text_box_reset(nfc->text_box);
- furi_string_reset(nfc->text_box_store);
-}
\ No newline at end of file
diff --git a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c
index 4c2bfc678..bc64c65bf 100644
--- a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c
+++ b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c
@@ -1,5 +1,4 @@
#include "../nfc_i.h"
-#include
void nfc_scene_nfc_data_info_widget_callback(GuiButtonType result, InputType type, void* context) {
Nfc* nfc = context;
@@ -89,7 +88,6 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
Nfc* nfc = context;
Widget* widget = nfc->widget;
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data;
- FuriHalNfcType type = nfc_data->type;
NfcDeviceData* dev_data = &nfc->dev->dev_data;
NfcProtocol protocol = dev_data->protocol;
uint8_t text_scroll_height = 0;
@@ -141,8 +139,6 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n");
break;
}
- } else if(protocol == NfcDeviceProtocolFelica) {
- furi_string_cat_printf(temp_str, "\e#%s\n", nfc_felica_type(dev_data->felica_data.type));
} else {
furi_string_cat_printf(temp_str, "\e#Unknown ISO tag\n");
}
@@ -200,72 +196,16 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
furi_string_cat_printf(temp_str, " %s\n", status);
}
- } else if(type == FuriHalNfcTypeF) {
- // Set NFC-F data
- furi_string_cat_printf(temp_str, "ISO 18092 (NFC-F)\n");
- furi_string_cat_printf(temp_str, "CIN:");
- // NFC-F Card Identification Number (CIN) starts at "UID" byte 2.
- for(size_t i = 2; i < nfc_data->uid_len; i++) {
- furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
- }
- // The first 2 bytes of the "UID" are Manufacturer Code (MC)
- furi_string_cat_printf(
- temp_str,
- "\nMC: %02X %02X ROM: %02X IC: %02X\n\n",
- nfc_data->uid[0],
- nfc_data->uid[1],
- nfc_data->f_data.pmm[0],
- nfc_data->f_data.pmm[1]);
-
- furi_string_cat_printf(temp_str, "MRT (1 node/blk):\n");
- furi_string_cat_printf(
- temp_str,
- "- ReqSvc: %" PRIuLEAST32 "us\n",
- felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_VARIABLE_MRT], 1));
- furi_string_cat_printf(
- temp_str,
- "- Fixed: %" PRIuLEAST32 "us\n",
- felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_FIXED_MRT], 0));
- furi_string_cat_printf(
- temp_str,
- "- Auth1: %" PRIuLEAST32 "us\n",
- felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_MUTUAL_AUTH_MRT], 1));
- furi_string_cat_printf(
- temp_str,
- "- Auth2: %" PRIuLEAST32 "us\n",
- felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_MUTUAL_AUTH_MRT], 0));
- furi_string_cat_printf(
- temp_str,
- "- Read: %" PRIuLEAST32 "us\n",
- felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_READ_MRT], 1));
- furi_string_cat_printf(
- temp_str,
- "- Write: %" PRIuLEAST32 "us\n",
- felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_WRITE_MRT], 1));
- furi_string_cat_printf(
- temp_str,
- "- Other: %" PRIuLEAST32 "us\n\n",
- felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_OTHER_MRT], 0));
-
- furi_string_cat_printf(temp_str, "IDm:");
- for(size_t i = 0; i < nfc_data->uid_len; i++) {
- furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
- }
- furi_string_cat_printf(temp_str, "\nPMm:");
- for(size_t i = 0; i < sizeof(nfc_data->f_data.pmm); i++) {
- furi_string_cat_printf(temp_str, " %02X", nfc_data->f_data.pmm[i]);
- }
} else {
- // Set tag general data
- char iso_type = FURI_BIT(nfc_data->a_data.sak, 5) ? '4' : '3';
+ char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3';
furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type);
furi_string_cat_printf(temp_str, "UID:");
for(size_t i = 0; i < nfc_data->uid_len; i++) {
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
}
furi_string_cat_printf(
- temp_str, "\nATQA: %02X %02X ", nfc_data->a_data.atqa[1], nfc_data->a_data.atqa[0]);
- furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->a_data.sak);
+ temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]);
+ furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak);
}
// Set application specific data
diff --git a/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c b/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c
index 74fff367f..a38f31a98 100644
--- a/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c
+++ b/applications/main/nfc/scenes/nfc_scene_nfca_read_success.c
@@ -24,15 +24,14 @@ void nfc_scene_nfca_read_success_on_enter(void* context) {
notification_message_block(nfc->notifications, &sequence_set_green_255);
- char iso_type = FURI_BIT(data->a_data.sak, 5) ? '4' : '3';
+ char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3';
furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type);
furi_string_cat_printf(temp_str, "UID:");
for(size_t i = 0; i < data->uid_len; i++) {
furi_string_cat_printf(temp_str, " %02X", data->uid[i]);
}
- furi_string_cat_printf(
- temp_str, "\nATQA: %02X %02X ", data->a_data.atqa[1], data->a_data.atqa[0]);
- furi_string_cat_printf(temp_str, " SAK: %02X", data->a_data.sak);
+ furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]);
+ furi_string_cat_printf(temp_str, " SAK: %02X", data->sak);
widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
furi_string_free(temp_str);
diff --git a/applications/main/nfc/scenes/nfc_scene_nfcf_menu.c b/applications/main/nfc/scenes/nfc_scene_nfcf_menu.c
deleted file mode 100644
index 69815dab1..000000000
--- a/applications/main/nfc/scenes/nfc_scene_nfcf_menu.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "../nfc_i.h"
-#include
-
-enum SubmenuIndex {
- /*
- SubmenuIndexSave,
- SubmenuIndexEmulate,
- */
- SubmenuIndexInfo,
-};
-
-void nfc_scene_nfcf_menu_submenu_callback(void* context, uint32_t index) {
- Nfc* nfc = context;
-
- view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
-}
-
-void nfc_scene_nfcf_menu_on_enter(void* context) {
- Nfc* nfc = context;
- Submenu* submenu = nfc->submenu;
- // FelicaData* data = &nfc->dev->dev_data.felica_data;
-
- /*
- submenu_add_item(
- submenu, "Save IDm", SubmenuIndexSave, nfc_scene_felica_menu_submenu_callback, nfc);
- submenu_add_item(
- submenu, "Emulate IDm", SubmenuIndexEmulate, nfc_scene_felica_menu_submenu_callback, nfc);
- */
- submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_nfcf_menu_submenu_callback, nfc);
-
- submenu_set_selected_item(
- nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcfMenu));
-
- view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
-}
-
-bool nfc_scene_nfcf_menu_on_event(void* context, SceneManagerEvent event) {
- Nfc* nfc = context;
- bool consumed = false;
-
- if(event.type == SceneManagerEventTypeCustom) {
- /*
- if(event.event == SubmenuIndexSave) {
- nfc->dev->format = NfcDeviceSaveFormatFelica;
- // Clear device name
- nfc_device_set_name(nfc->dev, "");
- scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
- consumed = true;
- } else if(event.event == SubmenuIndexEmulate) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaEmulate);
- if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
- dolphin_deed(DolphinDeedNfcAddEmulate);
- } else {
- dolphin_deed(DolphinDeedNfcEmulate);
- }
- consumed = true;
- } else if(event.event == SubmenuIndexUnlock) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaUnlockMenu);
- consumed = true;
- } else
- */
- if(event.event == SubmenuIndexInfo) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
- consumed = true;
- }
- scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcfMenu, event.event);
-
- } else if(event.type == SceneManagerEventTypeBack) {
- consumed = scene_manager_previous_scene(nfc->scene_manager);
- }
-
- return consumed;
-}
-
-void nfc_scene_nfcf_menu_on_exit(void* context) {
- Nfc* nfc = context;
-
- // Clear view
- submenu_reset(nfc->submenu);
-}
diff --git a/applications/main/nfc/scenes/nfc_scene_nfcf_read_success.c b/applications/main/nfc/scenes/nfc_scene_nfcf_read_success.c
deleted file mode 100644
index da695ba83..000000000
--- a/applications/main/nfc/scenes/nfc_scene_nfcf_read_success.c
+++ /dev/null
@@ -1,88 +0,0 @@
-#include "../nfc_i.h"
-#include "nfc_device.h"
-
-void nfc_scene_nfcf_read_success_widget_callback(
- GuiButtonType result,
- InputType type,
- void* context) {
- furi_assert(context);
- Nfc* nfc = context;
-
- if(type == InputTypeShort) {
- view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
- }
-}
-
-void nfc_scene_nfcf_read_success_on_enter(void* context) {
- Nfc* nfc = context;
-
- FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data;
- NfcDeviceData* dev_data = &nfc->dev->dev_data;
-
- // Setup view
- Widget* widget = nfc->widget;
- widget_add_button_element(
- widget, GuiButtonTypeLeft, "Retry", nfc_scene_nfcf_read_success_widget_callback, nfc);
- widget_add_button_element(
- widget, GuiButtonTypeRight, "More", nfc_scene_nfcf_read_success_widget_callback, nfc);
-
- FuriString* temp_str = furi_string_alloc();
-
- if(dev_data->protocol == NfcDeviceProtocolFelica) {
- furi_string_cat_printf(temp_str, "\e#%s", nfc_felica_type(dev_data->felica_data.type));
- } else {
- furi_string_cat_printf(temp_str, "\e#Unknown ISO tag");
- }
-
- furi_string_cat_printf(temp_str, "\nISO 18092 (NFC-F)");
-
- furi_string_cat_printf(temp_str, "\nCIN:");
- // NFC-F Card Identification Number (CIN) starts at "UID" byte 2.
- for(size_t i = 2; i < data->uid_len; i++) {
- furi_string_cat_printf(temp_str, " %02X", data->uid[i]);
- }
-
- // The first 2 bytes of the "UID" are Manufacturer Code (MC)
- furi_string_cat_printf(
- temp_str,
- "\nMC: %02X %02X ROM: %02X IC: %02X",
- data->uid[0],
- data->uid[1],
- data->f_data.pmm[0],
- data->f_data.pmm[1]);
-
- widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
- furi_string_free(temp_str);
-
- notification_message_block(nfc->notifications, &sequence_set_green_255);
-
- view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
-}
-
-bool nfc_scene_nfcf_read_success_on_event(void* context, SceneManagerEvent event) {
- Nfc* nfc = context;
- bool consumed = false;
-
- if(event.type == SceneManagerEventTypeCustom) {
- if(event.event == GuiButtonTypeLeft) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
- consumed = true;
- } else if(event.event == GuiButtonTypeRight) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcfMenu);
- consumed = true;
- }
- } else if(event.type == SceneManagerEventTypeBack) {
- scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
- consumed = true;
- }
- return consumed;
-}
-
-void nfc_scene_nfcf_read_success_on_exit(void* context) {
- Nfc* nfc = context;
-
- notification_message_block(nfc->notifications, &sequence_reset_green);
-
- // Clear view
- widget_reset(nfc->widget);
-}
diff --git a/applications/main/nfc/scenes/nfc_scene_read.c b/applications/main/nfc/scenes/nfc_scene_read.c
index 45b0f4a7e..f254e08f8 100644
--- a/applications/main/nfc/scenes/nfc_scene_read.c
+++ b/applications/main/nfc/scenes/nfc_scene_read.c
@@ -57,6 +57,7 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if((event.event == NfcWorkerEventReadUidNfcB) ||
+ (event.event == NfcWorkerEventReadUidNfcF) ||
(event.event == NfcWorkerEventReadUidNfcV)) {
notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess);
@@ -101,16 +102,6 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
}
consumed = true;
- } else if(event.event == NfcWorkerEventReadUidNfcF) {
- notification_message(nfc->notifications, &sequence_success);
- scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcfReadSuccess);
- dolphin_deed(DolphinDeedNfcReadSuccess);
- consumed = true;
- } else if(event.event == NfcWorkerEventReadFelica) {
- notification_message(nfc->notifications, &sequence_success);
- scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaReadSuccess);
- dolphin_deed(DolphinDeedNfcReadSuccess);
- consumed = true;
} else if(event.event == NfcWorkerEventCardDetected) {
nfc_scene_read_set_state(nfc, NfcSceneReadStateReading);
nfc_blink_detect_start(nfc);
diff --git a/applications/main/nfc/scenes/nfc_scene_read_card_type.c b/applications/main/nfc/scenes/nfc_scene_read_card_type.c
index ed33515d4..94262aa1e 100644
--- a/applications/main/nfc/scenes/nfc_scene_read_card_type.c
+++ b/applications/main/nfc/scenes/nfc_scene_read_card_type.c
@@ -7,8 +7,6 @@ enum SubmenuIndex {
SubmenuIndexReadMfUltralight,
SubmenuIndexReadEMV,
SubmenuIndexReadNFCA,
- SubmenuIndexReadFelica,
- SubmenuIndexReadNFCF,
};
void nfc_scene_read_card_type_submenu_callback(void* context, uint32_t index) {
@@ -51,18 +49,6 @@ void nfc_scene_read_card_type_on_enter(void* context) {
SubmenuIndexReadNFCA,
nfc_scene_read_card_type_submenu_callback,
nfc);
- submenu_add_item(
- submenu,
- "Read FeliCa",
- SubmenuIndexReadFelica,
- nfc_scene_read_card_type_submenu_callback,
- nfc);
- submenu_add_item(
- submenu,
- "Read NFC-F data",
- SubmenuIndexReadNFCF,
- nfc_scene_read_card_type_submenu_callback,
- nfc);
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadCardType);
submenu_set_selected_item(submenu, state);
@@ -99,16 +85,6 @@ bool nfc_scene_read_card_type_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
consumed = true;
}
- if(event.event == SubmenuIndexReadFelica) {
- nfc->dev->dev_data.read_mode = NfcReadModeFelica;
- scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
- consumed = true;
- }
- if(event.event == SubmenuIndexReadNFCF) {
- nfc->dev->dev_data.read_mode = NfcReadModeNFCF;
- scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
- consumed = true;
- }
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, event.event);
}
return consumed;
diff --git a/applications/main/nfc/scenes/nfc_scene_set_atqa.c b/applications/main/nfc/scenes/nfc_scene_set_atqa.c
index f26ce8436..d079b3804 100644
--- a/applications/main/nfc/scenes/nfc_scene_set_atqa.c
+++ b/applications/main/nfc/scenes/nfc_scene_set_atqa.c
@@ -17,7 +17,7 @@ void nfc_scene_set_atqa_on_enter(void* context) {
nfc_scene_set_atqa_byte_input_callback,
NULL,
nfc,
- nfc->dev->dev_data.nfc_data.a_data.atqa,
+ nfc->dev->dev_data.nfc_data.atqa,
2);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
}
diff --git a/applications/main/nfc/scenes/nfc_scene_set_sak.c b/applications/main/nfc/scenes/nfc_scene_set_sak.c
index 98bd6441a..60a1e1494 100644
--- a/applications/main/nfc/scenes/nfc_scene_set_sak.c
+++ b/applications/main/nfc/scenes/nfc_scene_set_sak.c
@@ -17,7 +17,7 @@ void nfc_scene_set_sak_on_enter(void* context) {
nfc_scene_set_sak_byte_input_callback,
NULL,
nfc,
- &nfc->dev->dev_data.nfc_data.a_data.sak,
+ &nfc->dev->dev_data.nfc_data.sak,
1);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput);
}
diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam
index f4a181c1f..edc86b38d 100644
--- a/applications/main/subghz/application.fam
+++ b/applications/main/subghz/application.fam
@@ -1,8 +1,9 @@
App(
appid="subghz",
name="SubGHz",
- apptype=FlipperAppType.MENUEXTERNAL,
+ apptype=FlipperAppType.APP,
targets=["f7"],
+ cdefines=["APP_SUBGHZ"],
entry_point="subghz_app",
requires=[
"gui",
@@ -25,6 +26,7 @@ App(
targets=["f7"],
apptype=FlipperAppType.STARTUP,
entry_point="subghz_on_system_start",
+ requires=["subghz"],
order=40,
)
diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c
index bd17cbbdd..6abe0a99f 100644
--- a/applications/main/subghz/subghz.c
+++ b/applications/main/subghz/subghz.c
@@ -57,6 +57,7 @@ static void subghz_load_custom_presets(SubGhzSetting* setting) {
furi_assert(setting);
const char* presets[][2] = {
+ // FM95
{"FM95",
"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"},
@@ -71,6 +72,11 @@ static void subghz_load_custom_presets(SubGhzSetting* setting) {
// # HND - FM preset
{"HND_1",
"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 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"},
+
+ // AM_Q
+ {"AM_Q",
+ "02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 22 10 1C 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00"},
+
};
FlipperFormat* fff_temp = flipper_format_string_alloc();
diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_config.h b/applications/main/xtreme_app/scenes/xtreme_app_scene_config.h
index 77ba43991..b40191cff 100644
--- a/applications/main/xtreme_app/scenes/xtreme_app_scene_config.h
+++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_config.h
@@ -3,6 +3,8 @@ ADD_SCENE(xtreme_app, interface, Interface)
ADD_SCENE(xtreme_app, interface_graphics, InterfaceGraphics)
ADD_SCENE(xtreme_app, interface_mainmenu, InterfaceMainmenu)
ADD_SCENE(xtreme_app, interface_mainmenu_add, InterfaceMainmenuAdd)
+ADD_SCENE(xtreme_app, interface_mainmenu_add_main, InterfaceMainmenuAddMain)
+ADD_SCENE(xtreme_app, interface_mainmenu_reset, InterfaceMainmenuReset)
ADD_SCENE(xtreme_app, interface_lockscreen, InterfaceLockscreen)
ADD_SCENE(xtreme_app, interface_statusbar, InterfaceStatusbar)
ADD_SCENE(xtreme_app, interface_filebrowser, InterfaceFilebrowser)
diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu.c
index 4a5b5779d..86aa94544 100644
--- a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu.c
+++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu.c
@@ -2,9 +2,11 @@
enum VarItemListIndex {
VarItemListIndexMenuStyle,
+ VarItemListIndexResetMenu,
VarItemListIndexApp,
- VarItemListIndexRemoveApp,
VarItemListIndexAddApp,
+ VarItemListIndexMoveApp,
+ VarItemListIndexRemoveApp,
};
void xtreme_app_scene_interface_mainmenu_var_item_list_callback(void* context, uint32_t index) {
@@ -24,7 +26,33 @@ static void xtreme_app_scene_interface_mainmenu_app_changed(VariableItem* item)
XtremeApp* app = variable_item_get_context(item);
app->mainmenu_app_index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(
- item, *CharList_get(app->mainmenu_app_names, app->mainmenu_app_index));
+ item, *CharList_get(app->mainmenu_app_labels, app->mainmenu_app_index));
+ size_t count = CharList_size(app->mainmenu_app_labels);
+ char label[20];
+ snprintf(label, 20, "App %u/%u", 1 + app->mainmenu_app_index, count);
+ variable_item_set_item_label(item, label);
+}
+
+static void xtreme_app_scene_interface_mainmenu_move_app_changed(VariableItem* item) {
+ XtremeApp* app = variable_item_get_context(item);
+ uint8_t idx = app->mainmenu_app_index;
+ size_t size = CharList_size(app->mainmenu_app_labels);
+ uint8_t dir = variable_item_get_current_value_index(item);
+ if(size >= 2) {
+ if(dir == 2 && idx != size - 1) {
+ // Right
+ CharList_swap_at(app->mainmenu_app_labels, idx, idx + 1);
+ CharList_swap_at(app->mainmenu_app_exes, idx, idx + 1);
+ app->mainmenu_app_index++;
+ } else if(dir == 0 && idx != 0) {
+ // Left
+ CharList_swap_at(app->mainmenu_app_labels, idx, idx - 1);
+ CharList_swap_at(app->mainmenu_app_exes, idx, idx - 1);
+ app->mainmenu_app_index--;
+ }
+ view_dispatcher_send_custom_event(app->view_dispatcher, VarItemListIndexMoveApp);
+ }
+ variable_item_set_current_value_index(item, 1);
}
void xtreme_app_scene_interface_mainmenu_on_enter(void* context) {
@@ -39,25 +67,34 @@ void xtreme_app_scene_interface_mainmenu_on_enter(void* context) {
variable_item_set_current_value_text(
item, xtreme_settings->wii_menu ? "Wii Grid" : "App List");
+ variable_item_list_add(var_item_list, "Reset Menu", 0, NULL, app);
+
+ size_t count = CharList_size(app->mainmenu_app_labels);
item = variable_item_list_add(
- var_item_list,
- "App",
- CharList_size(app->mainmenu_app_names),
- xtreme_app_scene_interface_mainmenu_app_changed,
- app);
- app->mainmenu_app_index = 0;
- variable_item_set_current_value_index(item, app->mainmenu_app_index);
- if(CharList_size(app->mainmenu_app_names)) {
+ var_item_list, "App", count, xtreme_app_scene_interface_mainmenu_app_changed, app);
+ if(count) {
+ app->mainmenu_app_index = CLAMP(app->mainmenu_app_index, count - 1, 0U);
+ char label[20];
+ snprintf(label, 20, "App %u/%u", 1 + app->mainmenu_app_index, count);
+ variable_item_set_item_label(item, label);
variable_item_set_current_value_text(
- item, *CharList_get(app->mainmenu_app_names, app->mainmenu_app_index));
+ item, *CharList_get(app->mainmenu_app_labels, app->mainmenu_app_index));
} else {
+ app->mainmenu_app_index = 0;
variable_item_set_current_value_text(item, "None");
}
-
- variable_item_list_add(var_item_list, "Remove App", 0, NULL, app);
+ variable_item_set_current_value_index(item, app->mainmenu_app_index);
variable_item_list_add(var_item_list, "Add App", 0, NULL, app);
+ item = variable_item_list_add(
+ var_item_list, "Move App", 3, xtreme_app_scene_interface_mainmenu_move_app_changed, app);
+ variable_item_set_current_value_text(item, "");
+ variable_item_set_current_value_index(item, 1);
+ variable_item_set_locked(item, count < 2, "Can't move\nwith less\nthan 2 apps!");
+
+ variable_item_list_add(var_item_list, "Remove App", 0, NULL, app);
+
variable_item_list_set_enter_callback(
var_item_list, xtreme_app_scene_interface_mainmenu_var_item_list_callback, app);
@@ -77,13 +114,21 @@ bool xtreme_app_scene_interface_mainmenu_on_event(void* context, SceneManagerEve
app->scene_manager, XtremeAppSceneInterfaceMainmenu, event.event);
consumed = true;
switch(event.event) {
+ case VarItemListIndexResetMenu:
+ scene_manager_next_scene(app->scene_manager, XtremeAppSceneInterfaceMainmenuReset);
+ break;
case VarItemListIndexRemoveApp:
- if(!CharList_size(app->mainmenu_app_names)) break;
- if(!CharList_size(app->mainmenu_app_paths)) break;
+ if(!CharList_size(app->mainmenu_app_labels)) break;
+ if(!CharList_size(app->mainmenu_app_exes)) break;
+ free(*CharList_get(app->mainmenu_app_labels, app->mainmenu_app_index));
+ free(*CharList_get(app->mainmenu_app_exes, app->mainmenu_app_index));
CharList_remove_v(
- app->mainmenu_app_names, app->mainmenu_app_index, app->mainmenu_app_index + 1);
+ app->mainmenu_app_labels, app->mainmenu_app_index, app->mainmenu_app_index + 1);
CharList_remove_v(
- app->mainmenu_app_paths, app->mainmenu_app_index, app->mainmenu_app_index + 1);
+ app->mainmenu_app_exes, app->mainmenu_app_index, app->mainmenu_app_index + 1);
+ if(app->mainmenu_app_index) app->mainmenu_app_index--;
+ /* fall through */
+ case VarItemListIndexMoveApp:
app->save_mainmenu_apps = true;
app->require_reboot = true;
scene_manager_previous_scene(app->scene_manager);
diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_add.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_add.c
index dd9336022..5a81d5d77 100644
--- a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_add.c
+++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_add.c
@@ -1,10 +1,11 @@
#include "../xtreme_app.h"
-enum FileBrowserResult {
- FileBrowserResultOk,
+enum SubmenuIndex {
+ SubmenuIndexMainApp,
+ SubmenuIndexExternalApp,
};
-static bool xtreme_app_scene_interface_mainmenu_add_file_browser_callback(
+static bool fap_selector_item_callback(
FuriString* file_path,
void* context,
uint8_t** icon_ptr,
@@ -16,52 +17,87 @@ static bool xtreme_app_scene_interface_mainmenu_add_file_browser_callback(
return success;
}
+static void
+ xtreme_app_scene_interface_mainmenu_add_submenu_callback(void* context, uint32_t index) {
+ XtremeApp* app = context;
+ scene_manager_set_scene_state(app->scene_manager, XtremeAppSceneInterfaceMainmenuAdd, index);
+
+ switch(index) {
+ case SubmenuIndexMainApp:
+ scene_manager_next_scene(app->scene_manager, XtremeAppSceneInterfaceMainmenuAddMain);
+ break;
+ case SubmenuIndexExternalApp: {
+ const DialogsFileBrowserOptions browser_options = {
+ .extension = ".fap",
+ .icon = &I_unknown_10px,
+ .skip_assets = true,
+ .hide_ext = true,
+ .item_loader_callback = fap_selector_item_callback,
+ .item_loader_context = app,
+ .base_path = EXT_PATH("apps"),
+ };
+ FuriString* temp_path = furi_string_alloc_set_str(EXT_PATH("apps"));
+ if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) {
+ CharList_push_back(app->mainmenu_app_exes, strdup(furi_string_get_cstr(temp_path)));
+ Storage* storage = furi_record_open(RECORD_STORAGE);
+ flipper_application_load_name_and_icon(temp_path, storage, NULL, temp_path);
+ furi_record_close(RECORD_STORAGE);
+ if(furi_string_start_with_str(temp_path, "[")) {
+ size_t trim = furi_string_search_str(temp_path, "] ", 1);
+ if(trim != FURI_STRING_FAILURE) {
+ furi_string_right(temp_path, trim + 2);
+ }
+ }
+ CharList_push_back(app->mainmenu_app_labels, strdup(furi_string_get_cstr(temp_path)));
+ app->mainmenu_app_index = CharList_size(app->mainmenu_app_labels) - 1;
+ app->save_mainmenu_apps = true;
+ app->require_reboot = true;
+ scene_manager_search_and_switch_to_previous_scene(
+ app->scene_manager, XtremeAppSceneInterfaceMainmenu);
+ }
+ furi_string_free(temp_path);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
void xtreme_app_scene_interface_mainmenu_add_on_enter(void* context) {
XtremeApp* app = context;
- FuriString* string = furi_string_alloc_set_str(EXT_PATH("apps"));
+ Submenu* submenu = app->submenu;
- const DialogsFileBrowserOptions browser_options = {
- .extension = ".fap",
- .skip_assets = true,
- .hide_ext = true,
- .item_loader_callback = xtreme_app_scene_interface_mainmenu_add_file_browser_callback,
- .item_loader_context = app,
- .base_path = EXT_PATH("apps"),
- };
+ submenu_add_item(
+ submenu,
+ "Main App",
+ SubmenuIndexMainApp,
+ xtreme_app_scene_interface_mainmenu_add_submenu_callback,
+ app);
- if(dialog_file_browser_show(app->dialogs, string, string, &browser_options)) {
- CharList_push_back(app->mainmenu_app_paths, strdup(furi_string_get_cstr(string)));
- Storage* storage = furi_record_open(RECORD_STORAGE);
- flipper_application_load_name_and_icon(string, storage, NULL, string);
- furi_record_close(RECORD_STORAGE);
- CharList_push_back(app->mainmenu_app_names, strdup(furi_string_get_cstr(string)));
- app->save_mainmenu_apps = true;
- app->require_reboot = true;
- }
+ submenu_add_item(
+ submenu,
+ "External App",
+ SubmenuIndexExternalApp,
+ xtreme_app_scene_interface_mainmenu_add_submenu_callback,
+ app);
- furi_string_free(string);
+ submenu_set_header(submenu, "Add Menu App:");
- view_dispatcher_send_custom_event(app->view_dispatcher, FileBrowserResultOk);
+ view_dispatcher_switch_to_view(app->view_dispatcher, XtremeAppViewSubmenu);
}
bool xtreme_app_scene_interface_mainmenu_add_on_event(void* context, SceneManagerEvent event) {
- XtremeApp* app = context;
+ UNUSED(context);
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
consumed = true;
- switch(event.event) {
- case FileBrowserResultOk:
- scene_manager_previous_scene(app->scene_manager);
- break;
- default:
- break;
- }
}
return consumed;
}
void xtreme_app_scene_interface_mainmenu_add_on_exit(void* context) {
- UNUSED(context);
+ XtremeApp* app = context;
+ submenu_reset(app->submenu);
}
diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_add_main.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_add_main.c
new file mode 100644
index 000000000..93aa15ec5
--- /dev/null
+++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_add_main.c
@@ -0,0 +1,55 @@
+#include "../xtreme_app.h"
+
+static void
+ xtreme_app_scene_interface_mainmenu_add_main_submenu_callback(void* context, uint32_t index) {
+ XtremeApp* app = context;
+ const char* name = (const char*)index;
+
+ CharList_push_back(app->mainmenu_app_exes, strdup(name));
+ CharList_push_back(app->mainmenu_app_labels, strdup(name));
+ app->mainmenu_app_index = CharList_size(app->mainmenu_app_labels) - 1;
+ app->save_mainmenu_apps = true;
+ app->require_reboot = true;
+ scene_manager_search_and_switch_to_previous_scene(
+ app->scene_manager, XtremeAppSceneInterfaceMainmenu);
+}
+
+void xtreme_app_scene_interface_mainmenu_add_main_on_enter(void* context) {
+ XtremeApp* app = context;
+ Submenu* submenu = app->submenu;
+
+ for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
+ submenu_add_item(
+ submenu,
+ FLIPPER_APPS[i].name,
+ (uint32_t)FLIPPER_APPS[i].name,
+ xtreme_app_scene_interface_mainmenu_add_main_submenu_callback,
+ app);
+ }
+ for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT - 1; i++) {
+ submenu_add_item(
+ submenu,
+ FLIPPER_EXTERNAL_APPS[i].name,
+ (uint32_t)FLIPPER_EXTERNAL_APPS[i].name,
+ xtreme_app_scene_interface_mainmenu_add_main_submenu_callback,
+ app);
+ }
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, XtremeAppViewSubmenu);
+}
+
+bool xtreme_app_scene_interface_mainmenu_add_main_on_event(void* context, SceneManagerEvent event) {
+ UNUSED(context);
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ consumed = true;
+ }
+
+ return consumed;
+}
+
+void xtreme_app_scene_interface_mainmenu_add_main_on_exit(void* context) {
+ XtremeApp* app = context;
+ submenu_reset(app->submenu);
+}
diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_reset.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_reset.c
new file mode 100644
index 000000000..625cd1f88
--- /dev/null
+++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu_reset.c
@@ -0,0 +1,55 @@
+#include "../xtreme_app.h"
+
+static void xtreme_app_scene_interface_mainmenu_reset_dialog_callback(
+ DialogExResult result,
+ void* context) {
+ XtremeApp* app = context;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, result);
+}
+
+void xtreme_app_scene_interface_mainmenu_reset_on_enter(void* context) {
+ XtremeApp* app = context;
+ DialogEx* dialog_ex = app->dialog_ex;
+
+ dialog_ex_set_header(dialog_ex, "Reset Menu Apps?", 64, 10, AlignCenter, AlignCenter);
+ dialog_ex_set_text(dialog_ex, "Your edits will be lost!", 64, 32, AlignCenter, AlignCenter);
+ dialog_ex_set_left_button_text(dialog_ex, "Cancel");
+ dialog_ex_set_right_button_text(dialog_ex, "Reset");
+
+ dialog_ex_set_context(dialog_ex, app);
+ dialog_ex_set_result_callback(
+ dialog_ex, xtreme_app_scene_interface_mainmenu_reset_dialog_callback);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, XtremeAppViewDialogEx);
+}
+
+bool xtreme_app_scene_interface_mainmenu_reset_on_event(void* context, SceneManagerEvent event) {
+ XtremeApp* app = context;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ switch(event.event) {
+ case DialogExResultRight:
+ storage_common_remove(furi_record_open(RECORD_STORAGE), XTREME_MENU_PATH);
+ furi_record_close(RECORD_STORAGE);
+ app->save_mainmenu_apps = false;
+ app->require_reboot = true;
+ xtreme_app_apply(app);
+ break;
+ default:
+ break;
+ }
+ } else if(event.type == SceneManagerEventTypeBack) {
+ consumed = true;
+ }
+
+ return consumed;
+}
+
+void xtreme_app_scene_interface_mainmenu_reset_on_exit(void* context) {
+ XtremeApp* app = context;
+ DialogEx* dialog_ex = app->dialog_ex;
+
+ dialog_ex_reset(dialog_ex);
+}
diff --git a/applications/main/xtreme_app/xtreme_app.c b/applications/main/xtreme_app/xtreme_app.c
index 444341a87..3e62f7e27 100644
--- a/applications/main/xtreme_app/xtreme_app.c
+++ b/applications/main/xtreme_app/xtreme_app.c
@@ -16,11 +16,12 @@ bool xtreme_app_apply(XtremeApp* app) {
if(app->save_mainmenu_apps) {
Stream* stream = file_stream_alloc(storage);
- if(file_stream_open(stream, XTREME_APPS_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)) {
+ if(file_stream_open(stream, XTREME_MENU_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)) {
+ stream_write_format(stream, "MenuAppList Version %u\n", 0);
CharList_it_t it;
- CharList_it(it, app->mainmenu_app_paths);
- for(uint i = 0; i < CharList_size(app->mainmenu_app_paths); i++) {
- stream_write_format(stream, "%s\n", *CharList_get(app->mainmenu_app_paths, i));
+ CharList_it(it, app->mainmenu_app_exes);
+ for(size_t i = 0; i < CharList_size(app->mainmenu_app_exes); i++) {
+ stream_write_format(stream, "%s\n", *CharList_get(app->mainmenu_app_exes, i));
}
}
file_stream_close(stream);
@@ -184,6 +185,10 @@ XtremeApp* xtreme_app_alloc() {
XtremeAppViewVarItemList,
variable_item_list_get_view(app->var_item_list));
+ app->submenu = submenu_alloc();
+ view_dispatcher_add_view(
+ app->view_dispatcher, XtremeAppViewSubmenu, submenu_get_view(app->submenu));
+
app->text_input = text_input_alloc();
view_dispatcher_add_view(
app->view_dispatcher, XtremeAppViewTextInput, text_input_get_view(app->text_input));
@@ -191,6 +196,10 @@ XtremeApp* xtreme_app_alloc() {
app->popup = popup_alloc();
view_dispatcher_add_view(app->view_dispatcher, XtremeAppViewPopup, popup_get_view(app->popup));
+ app->dialog_ex = dialog_ex_alloc();
+ view_dispatcher_add_view(
+ app->view_dispatcher, XtremeAppViewDialogEx, dialog_ex_get_view(app->dialog_ex));
+
// Settings init
XtremeSettings* xtreme_settings = XTREME_SETTINGS();
@@ -204,9 +213,8 @@ XtremeApp* xtreme_app_alloc() {
if(storage_dir_open(folder, XTREME_ASSETS_PATH)) {
while(storage_dir_read(folder, &info, name, XTREME_ASSETS_PACK_NAME_LEN)) {
if(info.flags & FSF_DIRECTORY) {
- char* copy = malloc(XTREME_ASSETS_PACK_NAME_LEN);
- strlcpy(copy, name, XTREME_ASSETS_PACK_NAME_LEN);
- uint idx = 0;
+ char* copy = strdup(name);
+ size_t idx = 0;
if(strcmp(copy, "NSFW") != 0) {
for(; idx < CharList_size(app->asset_pack_names); idx++) {
char* comp = *CharList_get(app->asset_pack_names, idx);
@@ -228,17 +236,24 @@ XtremeApp* xtreme_app_alloc() {
free(name);
storage_file_free(folder);
- CharList_init(app->mainmenu_app_names);
- CharList_init(app->mainmenu_app_paths);
+ CharList_init(app->mainmenu_app_labels);
+ CharList_init(app->mainmenu_app_exes);
Stream* stream = file_stream_alloc(storage);
FuriString* line = furi_string_alloc();
- if(file_stream_open(stream, XTREME_APPS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
+ if(file_stream_open(stream, XTREME_MENU_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
+ stream_read_line(stream, line);
while(stream_read_line(stream, line)) {
furi_string_replace_all(line, "\r", "");
furi_string_replace_all(line, "\n", "");
- CharList_push_back(app->mainmenu_app_paths, strdup(furi_string_get_cstr(line)));
+ CharList_push_back(app->mainmenu_app_exes, strdup(furi_string_get_cstr(line)));
flipper_application_load_name_and_icon(line, storage, NULL, line);
- CharList_push_back(app->mainmenu_app_names, strdup(furi_string_get_cstr(line)));
+ if(furi_string_start_with_str(line, "[")) {
+ size_t trim = furi_string_search_str(line, "] ", 1);
+ if(trim != FURI_STRING_FAILURE) {
+ furi_string_right(line, trim + 2);
+ }
+ }
+ CharList_push_back(app->mainmenu_app_labels, strdup(furi_string_get_cstr(line)));
}
}
furi_string_free(line);
@@ -298,10 +313,14 @@ void xtreme_app_free(XtremeApp* app) {
// Gui modules
view_dispatcher_remove_view(app->view_dispatcher, XtremeAppViewVarItemList);
variable_item_list_free(app->var_item_list);
+ view_dispatcher_remove_view(app->view_dispatcher, XtremeAppViewSubmenu);
+ submenu_free(app->submenu);
view_dispatcher_remove_view(app->view_dispatcher, XtremeAppViewTextInput);
text_input_free(app->text_input);
view_dispatcher_remove_view(app->view_dispatcher, XtremeAppViewPopup);
popup_free(app->popup);
+ view_dispatcher_remove_view(app->view_dispatcher, XtremeAppViewDialogEx);
+ dialog_ex_free(app->dialog_ex);
// View Dispatcher and Scene Manager
view_dispatcher_free(app->view_dispatcher);
@@ -315,14 +334,14 @@ void xtreme_app_free(XtremeApp* app) {
}
CharList_clear(app->asset_pack_names);
- for(CharList_it(it, app->mainmenu_app_names); !CharList_end_p(it); CharList_next(it)) {
+ for(CharList_it(it, app->mainmenu_app_labels); !CharList_end_p(it); CharList_next(it)) {
free(*CharList_cref(it));
}
- CharList_clear(app->mainmenu_app_names);
- for(CharList_it(it, app->mainmenu_app_paths); !CharList_end_p(it); CharList_next(it)) {
+ CharList_clear(app->mainmenu_app_labels);
+ for(CharList_it(it, app->mainmenu_app_exes); !CharList_end_p(it); CharList_next(it)) {
free(*CharList_cref(it));
}
- CharList_clear(app->mainmenu_app_paths);
+ CharList_clear(app->mainmenu_app_exes);
FrequencyList_clear(app->subghz_static_freqs);
FrequencyList_clear(app->subghz_hopper_freqs);
diff --git a/applications/main/xtreme_app/xtreme_app.h b/applications/main/xtreme_app/xtreme_app.h
index 4089eb820..995b00310 100644
--- a/applications/main/xtreme_app/xtreme_app.h
+++ b/applications/main/xtreme_app/xtreme_app.h
@@ -6,8 +6,11 @@
#include
#include
#include
+#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -37,13 +40,15 @@ typedef struct {
SceneManager* scene_manager;
ViewDispatcher* view_dispatcher;
VariableItemList* var_item_list;
+ Submenu* submenu;
TextInput* text_input;
Popup* popup;
+ DialogEx* dialog_ex;
CharList_t asset_pack_names;
uint8_t asset_pack_index;
- CharList_t mainmenu_app_names;
- CharList_t mainmenu_app_paths;
+ CharList_t mainmenu_app_labels;
+ CharList_t mainmenu_app_exes;
uint8_t mainmenu_app_index;
bool subghz_use_defaults;
FrequencyList_t subghz_static_freqs;
@@ -72,8 +77,10 @@ typedef struct {
typedef enum {
XtremeAppViewVarItemList,
+ XtremeAppViewSubmenu,
XtremeAppViewTextInput,
XtremeAppViewPopup,
+ XtremeAppViewDialogEx,
} XtremeAppView;
bool xtreme_app_apply(XtremeApp* app);
diff --git a/applications/services/application.fam b/applications/services/application.fam
index aec49b231..ff4fc0bf1 100644
--- a/applications/services/application.fam
+++ b/applications/services/application.fam
@@ -10,4 +10,5 @@ App(
"loader",
"power",
],
+ sdk_headers=["applications.h"],
)
diff --git a/applications/services/cli/cli_commands.c b/applications/services/cli/cli_commands.c
index f11535cd3..b74f3c443 100644
--- a/applications/services/cli/cli_commands.c
+++ b/applications/services/cli/cli_commands.c
@@ -173,7 +173,7 @@ void cli_command_src(Cli* cli, FuriString* args, void* context) {
UNUSED(args);
UNUSED(context);
- printf("https://github.com/ClaraCrazy/Flipper-Xtreme");
+ printf("https://github.com/Flipper-XFW/Xtreme-Firmware");
}
#define CLI_COMMAND_LOG_RING_SIZE 2048
diff --git a/applications/services/gui/modules/menu.c b/applications/services/gui/modules/menu.c
index 29c5b4131..5dba503ca 100644
--- a/applications/services/gui/modules/menu.c
+++ b/applications/services/gui/modules/menu.c
@@ -50,12 +50,14 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
size_t shift_position;
if(XTREME_SETTINGS()->wii_menu) {
FuriString* name = furi_string_alloc();
- if(position < 2) {
- shift_position = 0;
- } else if(position >= items_count - 2 + (items_count % 2)) {
- shift_position = position - (position % 2) - 4;
+ if(items_count > 6 && position >= 4) {
+ if(position >= items_count - 2 + (items_count % 2)) {
+ shift_position = position - (position % 2) - 4;
+ } else {
+ shift_position = position - (position % 2) - 2;
+ }
} else {
- shift_position = position - (position % 2) - 2;
+ shift_position = 0;
}
canvas_set_font(canvas, FontSecondary);
size_t item_i;
diff --git a/applications/services/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c
index 4dc3eac48..126d647ae 100644
--- a/applications/services/gui/modules/text_input.c
+++ b/applications/services/gui/modules/text_input.c
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
struct TextInput {
View* view;
@@ -24,6 +25,7 @@ typedef struct {
char* text_buffer;
size_t text_buffer_size;
size_t minimum_length;
+ char extra_symbols[9];
bool clear_default_text;
bool cursor_select;
@@ -100,7 +102,7 @@ static const TextInputKey keyboard_keys_row_3[] = {
{'9', 120, 32},
};
-static const TextInputKey symbol_keyboard_keys_row_1[] = {
+static TextInputKey symbol_keyboard_keys_row_1[] = {
{'!', 2, 8},
{'@', 12, 8},
{'#', 22, 8},
@@ -116,7 +118,7 @@ static const TextInputKey symbol_keyboard_keys_row_1[] = {
{'3', 120, 8},
};
-static const TextInputKey symbol_keyboard_keys_row_2[] = {
+static TextInputKey symbol_keyboard_keys_row_2[] = {
{'~', 2, 20},
{'+', 12, 20},
{'-', 22, 20},
@@ -131,7 +133,7 @@ static const TextInputKey symbol_keyboard_keys_row_2[] = {
{'6', 120, 20},
};
-static const TextInputKey symbol_keyboard_keys_row_3[] = {
+static TextInputKey symbol_keyboard_keys_row_3[] = {
{SWITCH_KEYBOARD_KEY, 1, 23},
{'.', 15, 32},
{',', 29, 32},
@@ -339,7 +341,8 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) {
canvas_set_color(canvas, ColorWhite);
}
- if(model->clear_default_text || text_length == 0) {
+ if(model->selected_keyboard != symbol_keyboard.keyboard_index &&
+ (model->clear_default_text || text_length == 0)) {
canvas_draw_glyph(
canvas,
keyboard_origin_x + keys[column].x,
@@ -464,7 +467,8 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, I
text_length = 0;
}
if(text_length < (model->text_buffer_size - 1)) {
- if(shift != (text_length == 0)) {
+ if(shift != (text_length == 0) &&
+ model->selected_keyboard != symbol_keyboard.keyboard_index) {
selected = char_to_uppercase(selected);
}
if(model->clear_default_text) {
@@ -587,6 +591,33 @@ void text_input_timer_callback(void* context) {
true);
}
+static void reset_extra_symbols(TextInputModel* model) {
+ memset(model->extra_symbols, 0, sizeof(model->extra_symbols));
+ size_t symbol = 0;
+ for(size_t row = 0; row < 3; row++) {
+ size_t size = get_row_size(&symbol_keyboard, row) - 3;
+ for(size_t i = 0; i < 3; i++) {
+ FURI_CONST_ASSIGN_(
+ char, get_row(&symbol_keyboard, row)[size++].text, '1' + (symbol++));
+ }
+ }
+ FURI_CONST_ASSIGN_(
+ char, get_row(&symbol_keyboard, 0)[get_row_size(&symbol_keyboard, 0) - 4].text, '0');
+}
+
+static void apply_extra_symbols(TextInputModel* model) {
+ size_t symbol = 0;
+ for(size_t row = 0; row < 3; row++) {
+ size_t size = get_row_size(&symbol_keyboard, row) - 3;
+ for(size_t i = 0; i < 3; i++) {
+ FURI_CONST_ASSIGN_(
+ char, get_row(&symbol_keyboard, row)[size++].text, model->extra_symbols[symbol++]);
+ }
+ }
+ FURI_CONST_ASSIGN_(
+ char, get_row(&symbol_keyboard, 0)[get_row_size(&symbol_keyboard, 0) - 4].text, '_');
+}
+
TextInput* text_input_alloc() {
TextInput* text_input = malloc(sizeof(TextInput));
text_input->view = view_alloc();
@@ -603,6 +634,7 @@ TextInput* text_input_alloc() {
{
model->validator_text = furi_string_alloc();
model->minimum_length = 1;
+ reset_extra_symbols(model);
model->cursor_pos = 0;
model->cursor_select = false;
},
@@ -642,6 +674,7 @@ void text_input_reset(TextInput* text_input) {
model->selected_column = 0;
model->selected_keyboard = 0;
model->minimum_length = 1;
+ reset_extra_symbols(model);
model->clear_default_text = false;
model->cursor_pos = 0;
model->cursor_select = false;
@@ -700,6 +733,43 @@ void text_input_set_minimum_length(TextInput* text_input, size_t minimum_length)
true);
}
+void text_input_add_extra_symbol(TextInput* text_input, char symbol) {
+ if(!symbol) return;
+ with_view_model(
+ text_input->view,
+ TextInputModel * model,
+ {
+ for(size_t i = 0; i < sizeof(model->extra_symbols); i++) {
+ if(!model->extra_symbols[i]) {
+ model->extra_symbols[i] = symbol;
+ apply_extra_symbols(model);
+ break;
+ }
+ }
+ },
+ true);
+}
+
+void text_input_add_illegal_symbols(TextInput* text_input) {
+ with_view_model(
+ text_input->view,
+ TextInputModel * model,
+ {
+ size_t i = 0;
+ model->extra_symbols[i++] = '<';
+ model->extra_symbols[i++] = '>';
+ model->extra_symbols[i++] = ':';
+ model->extra_symbols[i++] = '"';
+ model->extra_symbols[i++] = '/';
+ model->extra_symbols[i++] = '\\';
+ model->extra_symbols[i++] = '|';
+ model->extra_symbols[i++] = '?';
+ model->extra_symbols[i++] = '*';
+ apply_extra_symbols(model);
+ },
+ true);
+}
+
void text_input_set_validator(
TextInput* text_input,
TextInputValidatorCallback callback,
diff --git a/applications/services/gui/modules/text_input.h b/applications/services/gui/modules/text_input.h
index 65207532e..1ba4f1cd4 100644
--- a/applications/services/gui/modules/text_input.h
+++ b/applications/services/gui/modules/text_input.h
@@ -72,6 +72,12 @@ void text_input_set_validator(
void text_input_set_minimum_length(TextInput* text_input, size_t minimum_length);
+// Add up to 9 extra characters for symbol keyboard
+void text_input_add_extra_symbol(TextInput* text_input, char symbol);
+
+// Add the 9 predefined illegal (windows) symbols <>:"/\|?*
+void text_input_add_illegal_symbols(TextInput* text_input);
+
TextInputValidatorCallback text_input_get_validator_callback(TextInput* text_input);
void* text_input_get_validator_callback_context(TextInput* text_input);
diff --git a/applications/services/gui/modules/variable_item_list.c b/applications/services/gui/modules/variable_item_list.c
index 423ab3179..9b22ac2f0 100644
--- a/applications/services/gui/modules/variable_item_list.c
+++ b/applications/services/gui/modules/variable_item_list.c
@@ -7,7 +7,7 @@
#include
struct VariableItem {
- const char* label;
+ FuriString* label;
uint8_t current_value_index;
FuriString* current_value_text;
uint8_t values_count;
@@ -81,9 +81,9 @@ static void variable_item_list_draw_callback(Canvas* canvas, void* _model) {
if(item->current_value_index == 0 && furi_string_empty(item->current_value_text)) {
// Only left text, no right text
- canvas_draw_str(canvas, 6, item_text_y, item->label);
+ canvas_draw_str(canvas, 6, item_text_y, furi_string_get_cstr(item->label));
} else {
- elements_scrollable_text_line_str(
+ elements_scrollable_text_line_centered(
canvas, 6, item_text_y, 66, item->label, scroll_counter, false, false);
}
@@ -420,6 +420,7 @@ void variable_item_list_free(VariableItemList* variable_item_list) {
VariableItemArray_it_t it;
for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it);
VariableItemArray_next(it)) {
+ furi_string_free(VariableItemArray_ref(it)->label);
furi_string_free(VariableItemArray_ref(it)->current_value_text);
furi_string_free(VariableItemArray_ref(it)->locked_message);
}
@@ -444,6 +445,7 @@ void variable_item_list_reset(VariableItemList* variable_item_list) {
VariableItemArray_it_t it;
for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it);
VariableItemArray_next(it)) {
+ furi_string_free(VariableItemArray_ref(it)->label);
furi_string_free(VariableItemArray_ref(it)->current_value_text);
furi_string_free(VariableItemArray_ref(it)->locked_message);
}
@@ -472,7 +474,7 @@ VariableItem* variable_item_list_add(
VariableItemListModel * model,
{
item = VariableItemArray_push_new(model->items);
- item->label = label;
+ item->label = furi_string_alloc_set(label);
item->values_count = values_count;
item->change_callback = change_callback;
item->context = context;
@@ -510,6 +512,10 @@ void variable_item_set_values_count(VariableItem* item, uint8_t values_count) {
item->values_count = values_count;
}
+void variable_item_set_item_label(VariableItem* item, const char* label) {
+ furi_string_set(item->label, label);
+}
+
void variable_item_set_current_value_text(VariableItem* item, const char* current_value_text) {
furi_string_set(item->current_value_text, current_value_text);
}
diff --git a/applications/services/gui/modules/variable_item_list.h b/applications/services/gui/modules/variable_item_list.h
index db8b1788f..b12fb856f 100644
--- a/applications/services/gui/modules/variable_item_list.h
+++ b/applications/services/gui/modules/variable_item_list.h
@@ -88,6 +88,13 @@ void variable_item_set_current_value_index(VariableItem* item, uint8_t current_v
*/
void variable_item_set_values_count(VariableItem* item, uint8_t values_count);
+/** Set number of values for item
+ *
+ * @param item VariableItem* instance
+ * @param label The new label text
+ */
+void variable_item_set_item_label(VariableItem* item, const char* label);
+
/** Set item current selected text
*
* @param item VariableItem* instance
diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c
index 6a7e7bb1d..81e25e499 100644
--- a/applications/services/loader/loader.c
+++ b/applications/services/loader/loader.c
@@ -134,9 +134,9 @@ FuriPubSub* loader_get_pubsub(Loader* loader) {
return loader->pubsub;
}
-ExtMainAppList_t* loader_get_ext_main_apps(Loader* loader) {
+MenuAppList_t* loader_get_menu_apps(Loader* loader) {
furi_assert(loader);
- return &loader->ext_main_apps;
+ return &loader->menu_apps;
}
// callbacks
@@ -195,6 +195,31 @@ bool loader_menu_load_fap_meta(
return true;
}
+static void loader_make_menu_file(Storage* storage) {
+ Stream* new = file_stream_alloc(storage);
+ if(!storage_file_exists(storage, XTREME_MENU_PATH)) {
+ if(file_stream_open(new, XTREME_MENU_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
+ stream_write_format(new, "MenuAppList Version %u\n", 0);
+ for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
+ stream_write_format(new, "%s\n", FLIPPER_APPS[i].name);
+ }
+ for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT - 1; i++) {
+ stream_write_format(new, "%s\n", FLIPPER_EXTERNAL_APPS[i].name);
+ }
+ Stream* old = file_stream_alloc(storage);
+ if(file_stream_open(old, XTREME_MENU_OLD_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
+ stream_copy(old, new, stream_size(old));
+ }
+ file_stream_close(old);
+ stream_free(old);
+ storage_common_remove(storage, XTREME_MENU_OLD_PATH);
+ }
+ file_stream_close(new);
+ }
+ file_stream_close(new);
+ stream_free(new);
+}
+
static Loader* loader_alloc() {
Loader* loader = malloc(sizeof(Loader));
loader->pubsub = furi_pubsub_alloc();
@@ -205,33 +230,75 @@ static Loader* loader_alloc() {
loader->app.thread = NULL;
loader->app.insomniac = false;
loader->app.fap = NULL;
- ExtMainAppList_init(loader->ext_main_apps);
+ MenuAppList_init(loader->menu_apps);
- if(furi_hal_is_normal_boot()) {
- Storage* storage = furi_record_open(RECORD_STORAGE);
- FuriString* path = furi_string_alloc();
- FuriString* name = furi_string_alloc();
- Stream* stream = file_stream_alloc(storage);
- if(file_stream_open(stream, XTREME_APPS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
- while(stream_read_line(stream, path)) {
- furi_string_replace_all(path, "\r", "");
- furi_string_replace_all(path, "\n", "");
- const Icon* icon;
- if(!loader_menu_load_fap_meta(storage, path, name, &icon)) continue;
- ExtMainAppList_push_back(
- loader->ext_main_apps,
- (ExtMainApp){
- .name = strdup(furi_string_get_cstr(name)),
- .path = strdup(furi_string_get_cstr(path)),
- .icon = icon});
+ if(!furi_hal_is_normal_boot()) return loader;
+ Storage* storage = furi_record_open(RECORD_STORAGE);
+ Stream* stream = file_stream_alloc(storage);
+ FuriString* line = furi_string_alloc();
+ FuriString* name = furi_string_alloc();
+ do {
+ if(!file_stream_open(stream, XTREME_MENU_PATH, FSAM_READ_WRITE, FSOM_OPEN_EXISTING)) {
+ file_stream_close(stream);
+ loader_make_menu_file(storage);
+ if(!file_stream_open(stream, XTREME_MENU_PATH, FSAM_READ_WRITE, FSOM_OPEN_EXISTING))
+ break;
+ }
+
+ uint32_t version;
+ if(!stream_read_line(stream, line) ||
+ sscanf(furi_string_get_cstr(line), "MenuAppList Version %lu", &version) != 1 ||
+ version > 0) {
+ file_stream_close(stream);
+ storage_common_remove(storage, XTREME_MENU_PATH);
+ loader_make_menu_file(storage);
+ if(!file_stream_open(stream, XTREME_MENU_PATH, FSAM_READ_WRITE, FSOM_OPEN_EXISTING))
+ break;
+ if(!stream_read_line(stream, line) ||
+ sscanf(furi_string_get_cstr(line), "MenuAppList Version %lu", &version) != 1 ||
+ version > 0)
+ break;
+ }
+
+ while(stream_read_line(stream, line)) {
+ furi_string_replace_all(line, "\r", "");
+ furi_string_replace_all(line, "\n", "");
+ const char* label = NULL;
+ const Icon* icon = NULL;
+ const char* exe = NULL;
+ if(storage_file_exists(storage, furi_string_get_cstr(line))) {
+ if(loader_menu_load_fap_meta(storage, line, name, &icon)) {
+ label = strdup(furi_string_get_cstr(name));
+ exe = strdup(furi_string_get_cstr(line));
+ }
+ } else {
+ for(size_t i = 0; !exe && i < FLIPPER_APPS_COUNT; i++) {
+ if(!strcmp(furi_string_get_cstr(line), FLIPPER_APPS[i].name)) {
+ label = FLIPPER_APPS[i].name;
+ icon = FLIPPER_APPS[i].icon;
+ exe = FLIPPER_APPS[i].name;
+ }
+ }
+ for(size_t i = 0; !exe && i < FLIPPER_EXTERNAL_APPS_COUNT; i++) {
+ if(!strcmp(furi_string_get_cstr(line), FLIPPER_EXTERNAL_APPS[i].name)) {
+ label = FLIPPER_EXTERNAL_APPS[i].name;
+ icon = FLIPPER_EXTERNAL_APPS[i].icon;
+ exe = FLIPPER_EXTERNAL_APPS[i].name;
+ }
+ }
+ }
+ if(label && exe && icon) {
+ MenuAppList_push_back(
+ loader->menu_apps, (MenuApp){.label = label, .icon = icon, .exe = exe});
}
}
- file_stream_close(stream);
- stream_free(stream);
- furi_string_free(name);
- furi_string_free(path);
- furi_record_close(RECORD_STORAGE);
- }
+
+ } while(false);
+ furi_string_free(name);
+ furi_string_free(line);
+ file_stream_close(stream);
+ stream_free(stream);
+ furi_record_close(RECORD_STORAGE);
return loader;
}
@@ -378,21 +445,33 @@ static LoaderStatus loader_start_external_app(
break;
} else if(api_mismatch) {
// Successful map, but found api mismatch -> warn user
+ const FlipperApplicationManifest* manifest =
+ flipper_application_get_manifest(loader->app.fap);
+
+ char buf[66];
+ snprintf(
+ buf,
+ 66,
+ "FAP: %i != FW: %i\nThis app might not work\nContinue anyways?",
+ manifest->base.api_version.major,
+ firmware_api_interface->api_version_major);
+
DialogMessage* message = dialog_message_alloc();
dialog_message_set_header(message, "API Mismatch", 64, 0, AlignCenter, AlignTop);
dialog_message_set_buttons(message, "Cancel", NULL, "Continue");
- dialog_message_set_text(
- message,
- "This app might not\nwork correctly\nContinue anyways?",
- 64,
- 32,
- AlignCenter,
- AlignCenter);
+ dialog_message_set_text(message, buf, 64, 32, AlignCenter, AlignCenter);
DialogMessageButton res =
dialog_message_show(furi_record_open(RECORD_DIALOGS), message);
dialog_message_free(message);
furi_record_close(RECORD_DIALOGS);
if(res != DialogMessageButtonRight) {
+ const char* err_msg = flipper_application_preload_status_to_string(preload_res);
+ status = loader_make_status_error(
+ LoaderStatusErrorAppStarted,
+ error_message,
+ "Preload failed, %s: %s",
+ path,
+ err_msg);
break;
}
}
diff --git a/applications/services/loader/loader_cli.c b/applications/services/loader/loader_cli.c
index af3ebf9e0..f5178f01e 100644
--- a/applications/services/loader/loader_cli.c
+++ b/applications/services/loader/loader_cli.c
@@ -18,6 +18,9 @@ static void loader_cli_list() {
for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
printf("\t%s\r\n", FLIPPER_APPS[i].name);
}
+ for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) {
+ printf("\t%s\r\n", FLIPPER_EXTERNAL_APPS[i].name);
+ }
printf("Settings:\r\n");
for(size_t i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) {
printf("\t%s\r\n", FLIPPER_SETTINGS_APPS[i].name);
@@ -104,4 +107,4 @@ void loader_on_system_start() {
#else
UNUSED(loader_cli);
#endif
-}
\ No newline at end of file
+}
diff --git a/applications/services/loader/loader_extmainapp.h b/applications/services/loader/loader_extmainapp.h
deleted file mode 100644
index 4eeb263c7..000000000
--- a/applications/services/loader/loader_extmainapp.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-
-#include
-#include
-
-typedef struct {
- const char* name;
- const char* path;
- const Icon* icon;
-} ExtMainApp;
-
-LIST_DEF(ExtMainAppList, ExtMainApp, M_POD_OPLIST)
-
-ExtMainAppList_t* loader_get_ext_main_apps(Loader* loader);
diff --git a/applications/services/loader/loader_i.h b/applications/services/loader/loader_i.h
index 5ed0441ba..c33e6d101 100644
--- a/applications/services/loader/loader_i.h
+++ b/applications/services/loader/loader_i.h
@@ -4,7 +4,7 @@
#include
#include "loader.h"
#include "loader_menu.h"
-#include "loader_extmainapp.h"
+#include "loader_menuapp.h"
#include "loader_applications.h"
typedef struct {
@@ -20,7 +20,7 @@ struct Loader {
LoaderMenu* loader_menu;
LoaderApplications* loader_applications;
LoaderAppData app;
- ExtMainAppList_t ext_main_apps;
+ MenuAppList_t menu_apps;
};
typedef enum {
diff --git a/applications/services/loader/loader_menu.c b/applications/services/loader/loader_menu.c
index d6b0bde09..ac88f7916 100644
--- a/applications/services/loader/loader_menu.c
+++ b/applications/services/loader/loader_menu.c
@@ -7,7 +7,7 @@
#include "loader.h"
#include "loader_menu.h"
-#include "loader_extmainapp.h"
+#include "loader_menuapp.h"
#define TAG "LoaderMenu"
@@ -56,23 +56,9 @@ static void loader_menu_start(const char* name) {
furi_record_close(RECORD_LOADER);
}
-static void loader_menu_apps_callback(void* context, uint32_t index) {
+static void loader_menu_callback(void* context, uint32_t index) {
UNUSED(context);
- const char* name_or_path = (const char*)index;
- loader_menu_start(name_or_path);
-}
-
-static void loader_menu_applications_callback(void* context, uint32_t index) {
- UNUSED(index);
- UNUSED(context);
- const char* name = LOADER_APPLICATIONS_NAME;
- loader_menu_start(name);
-}
-
-static void loader_menu_settings_menu_callback(void* context, uint32_t index) {
- UNUSED(context);
- const char* name = FLIPPER_SETTINGS_APPS[index].name;
- loader_menu_start(name);
+ loader_menu_start((const char*)index);
}
static void loader_menu_switch_to_settings(void* context, uint32_t index) {
@@ -96,43 +82,30 @@ static void loader_menu_build_menu(LoaderMenuApp* app, LoaderMenu* menu) {
app->primary_menu,
LOADER_APPLICATIONS_NAME,
&A_Plugins_14,
- 0,
- loader_menu_applications_callback,
+ (uint32_t)LOADER_APPLICATIONS_NAME,
+ loader_menu_callback,
(void*)menu);
- for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) {
- menu_add_item(
- app->primary_menu,
- FLIPPER_EXTERNAL_APPS[i].name,
- FLIPPER_EXTERNAL_APPS[i].icon,
- (uint32_t)FLIPPER_EXTERNAL_APPS[i].name,
- loader_menu_apps_callback,
- (void*)menu);
- }
- for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
- menu_add_item(
- app->primary_menu,
- FLIPPER_APPS[i].name,
- FLIPPER_APPS[i].icon,
- (uint32_t)FLIPPER_APPS[i].name,
- loader_menu_apps_callback,
- (void*)menu);
- }
- menu_add_item(
- app->primary_menu, "Settings", &A_Settings_14, 0, loader_menu_switch_to_settings, app);
Loader* loader = furi_record_open(RECORD_LOADER);
- ExtMainAppList_t* ext_main_apps = loader_get_ext_main_apps(loader);
- for(size_t i = 0; i < ExtMainAppList_size(*ext_main_apps); i++) {
- const ExtMainApp* ext_main_app = ExtMainAppList_get(*ext_main_apps, i);
+ MenuAppList_t* menu_apps = loader_get_menu_apps(loader);
+ for(size_t i = 0; i < MenuAppList_size(*menu_apps); i++) {
+ const MenuApp* menu_app = MenuAppList_get(*menu_apps, i);
menu_add_item(
app->primary_menu,
- ext_main_app->name,
- ext_main_app->icon,
- (uint32_t)ext_main_app->path,
- loader_menu_apps_callback,
+ menu_app->label,
+ menu_app->icon,
+ (uint32_t)menu_app->exe,
+ loader_menu_callback,
(void*)menu);
}
furi_record_close(RECORD_LOADER);
+
+ const FlipperExternalApplication* last =
+ &FLIPPER_EXTERNAL_APPS[FLIPPER_EXTERNAL_APPS_COUNT - 1];
+ menu_add_item(
+ app->primary_menu, last->name, last->icon, (uint32_t)last->path, loader_menu_callback, app);
+ menu_add_item(
+ app->primary_menu, "Settings", &A_Settings_14, 0, loader_menu_switch_to_settings, app);
};
static void loader_menu_build_submenu(LoaderMenuApp* app, LoaderMenu* loader_menu) {
@@ -140,8 +113,8 @@ static void loader_menu_build_submenu(LoaderMenuApp* app, LoaderMenu* loader_men
submenu_add_item(
app->settings_menu,
FLIPPER_SETTINGS_APPS[i].name,
- i,
- loader_menu_settings_menu_callback,
+ (uint32_t)FLIPPER_SETTINGS_APPS[i].name,
+ loader_menu_callback,
loader_menu);
}
}
diff --git a/applications/services/loader/loader_menuapp.h b/applications/services/loader/loader_menuapp.h
new file mode 100644
index 000000000..a2e0da4a5
--- /dev/null
+++ b/applications/services/loader/loader_menuapp.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include
+#include
+
+typedef struct {
+ const char* label;
+ const Icon* icon;
+ const char* exe;
+} MenuApp;
+
+LIST_DEF(MenuAppList, MenuApp, M_POD_OPLIST)
+
+MenuAppList_t* loader_get_menu_apps(Loader* loader);
diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c
index a42d700b5..480051d30 100644
--- a/applications/services/power/power_service/power.c
+++ b/applications/services/power/power_service/power.c
@@ -404,6 +404,7 @@ static bool power_update_info(Power* power) {
info.is_charging = furi_hal_power_is_charging();
info.gauge_is_ok = furi_hal_power_gauge_is_ok();
+ info.is_shutdown_requested = furi_hal_power_is_shutdown_requested();
info.charge = furi_hal_power_get_pct();
info.health = furi_hal_power_get_bat_health_pct();
info.capacity_remaining = furi_hal_power_get_battery_remaining_capacity();
@@ -432,7 +433,7 @@ static void power_check_low_battery(Power* power) {
}
// Check battery charge and vbus voltage
- if((power->info.charge == 0) && (power->info.voltage_vbus < 4.0f) &&
+ if((power->info.is_shutdown_requested) && (power->info.voltage_vbus < 4.0f) &&
power->show_low_bat_level_message) {
if(!power->battery_low) {
view_dispatcher_send_to_front(power->view_dispatcher);
diff --git a/applications/services/power/power_service/power.h b/applications/services/power/power_service/power.h
index ffe756f97..9cefd8d4c 100644
--- a/applications/services/power/power_service/power.h
+++ b/applications/services/power/power_service/power.h
@@ -37,6 +37,7 @@ typedef struct {
typedef struct {
bool gauge_is_ok;
bool is_charging;
+ bool is_shutdown_requested;
bool is_charge_capped;
float current_charger;
diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c
index 096060d82..447e76afc 100644
--- a/applications/services/storage/storage_cli.c
+++ b/applications/services/storage/storage_cli.c
@@ -29,6 +29,7 @@ static void storage_cli_print_usage() {
"\twrite_chunk\t - read data from cli and append it to file, should contain how many bytes you want to write\r\n");
printf("\tcopy\t - copy file to new file, must contain new path\r\n");
printf("\trename\t - move file to new file, must contain new path\r\n");
+ printf("\tmigrate\t - \r\n");
printf("\tmkdir\t - creates a new directory\r\n");
printf("\tmd5\t - md5 hash of the file\r\n");
printf("\tstat\t - info about file or dir\r\n");
@@ -466,6 +467,27 @@ static void storage_cli_rename(Cli* cli, FuriString* old_path, FuriString* args)
furi_record_close(RECORD_STORAGE);
}
+static void storage_cli_migrate(Cli* cli, FuriString* old_path, FuriString* args) {
+ UNUSED(cli);
+ Storage* api = furi_record_open(RECORD_STORAGE);
+ FuriString* new_path;
+ new_path = furi_string_alloc();
+
+ if(!args_read_probably_quoted_string_and_trim(args, new_path)) {
+ storage_cli_print_usage();
+ } else {
+ FS_Error error = storage_common_migrate(
+ api, furi_string_get_cstr(old_path), furi_string_get_cstr(new_path));
+
+ if(error != FSE_OK) {
+ storage_cli_print_error(error);
+ }
+ }
+
+ furi_string_free(new_path);
+ furi_record_close(RECORD_STORAGE);
+}
+
static void storage_cli_mkdir(Cli* cli, FuriString* path) {
UNUSED(cli);
Storage* api = furi_record_open(RECORD_STORAGE);
@@ -589,6 +611,11 @@ void storage_cli(Cli* cli, FuriString* args, void* context) {
break;
}
+ if(furi_string_cmp_str(cmd, "migrate") == 0) {
+ storage_cli_migrate(cli, path, args);
+ break;
+ }
+
if(furi_string_cmp_str(cmd, "mkdir") == 0) {
storage_cli_mkdir(cli, path);
break;
diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c
index f77fb4d03..1cfe06a52 100644
--- a/applications/services/storage/storage_external_api.c
+++ b/applications/services/storage/storage_external_api.c
@@ -593,8 +593,13 @@ FS_Error storage_common_copy(Storage* storage, const char* old_path, const char*
return error;
}
-static FS_Error
- storage_merge_recursive(Storage* storage, const char* old_path, const char* new_path) {
+static FS_Error _storage_common_merge(Storage*, const char*, const char*, bool);
+
+static FS_Error storage_merge_recursive(
+ Storage* storage,
+ const char* old_path,
+ const char* new_path,
+ bool copy) {
FS_Error error = FSE_OK;
DirWalk* dir_walk = dir_walk_alloc(storage);
FuriString *path, *file_basename, *tmp_new_path;
@@ -636,8 +641,8 @@ static FS_Error
}
}
}
- error = storage_common_merge(
- storage, furi_string_get_cstr(path), furi_string_get_cstr(tmp_new_path));
+ error = _storage_common_merge(
+ storage, furi_string_get_cstr(path), furi_string_get_cstr(tmp_new_path), copy);
if(error != FSE_OK) {
break;
@@ -654,7 +659,8 @@ static FS_Error
return error;
}
-FS_Error storage_common_merge(Storage* storage, const char* old_path, const char* new_path) {
+static FS_Error
+ _storage_common_merge(Storage* storage, const char* old_path, const char* new_path, bool copy) {
FS_Error error;
const char* new_path_tmp = NULL;
FuriString* new_path_next = NULL;
@@ -665,7 +671,12 @@ FS_Error storage_common_merge(Storage* storage, const char* old_path, const char
if(error == FSE_OK) {
if(file_info_is_dir(&fileinfo)) {
- error = storage_merge_recursive(storage, old_path, new_path);
+ if(!copy) {
+ error = storage_common_rename(storage, old_path, new_path);
+ }
+ if(copy || error != FSE_OK) {
+ error = storage_merge_recursive(storage, old_path, new_path, copy);
+ }
} else {
error = storage_common_stat(storage, new_path, &fileinfo);
if(error == FSE_OK) {
@@ -699,22 +710,28 @@ FS_Error storage_common_merge(Storage* storage, const char* old_path, const char
} else {
new_path_tmp = new_path;
}
- Stream* stream_from = file_stream_alloc(storage);
- Stream* stream_to = file_stream_alloc(storage);
+ if(copy) {
+ Stream* stream_from = file_stream_alloc(storage);
+ Stream* stream_to = file_stream_alloc(storage);
- do {
- if(!file_stream_open(stream_from, old_path, FSAM_READ, FSOM_OPEN_EXISTING)) break;
- if(!file_stream_open(stream_to, new_path_tmp, FSAM_WRITE, FSOM_CREATE_NEW)) break;
- stream_copy_full(stream_from, stream_to);
- } while(false);
+ do {
+ if(!file_stream_open(stream_from, old_path, FSAM_READ, FSOM_OPEN_EXISTING))
+ break;
+ if(!file_stream_open(stream_to, new_path_tmp, FSAM_WRITE, FSOM_CREATE_NEW))
+ break;
+ stream_copy_full(stream_from, stream_to);
+ } while(false);
- error = file_stream_get_error(stream_from);
- if(error == FSE_OK) {
- error = file_stream_get_error(stream_to);
+ error = file_stream_get_error(stream_from);
+ if(error == FSE_OK) {
+ error = file_stream_get_error(stream_to);
+ }
+
+ stream_free(stream_from);
+ stream_free(stream_to);
+ } else {
+ error = storage_common_rename(storage, old_path, new_path_tmp);
}
-
- stream_free(stream_from);
- stream_free(stream_to);
}
}
@@ -723,6 +740,10 @@ FS_Error storage_common_merge(Storage* storage, const char* old_path, const char
return error;
}
+FS_Error storage_common_merge(Storage* storage, const char* old_path, const char* new_path) {
+ return _storage_common_merge(storage, old_path, new_path, true);
+}
+
FS_Error storage_common_mkdir(Storage* storage, const char* path) {
S_API_PROLOGUE;
SAData data = {
@@ -774,14 +795,10 @@ FS_Error storage_common_migrate(Storage* storage, const char* source, const char
return FSE_OK;
}
- FS_Error error = storage_common_rename(storage, source, dest);
+ FS_Error error = _storage_common_merge(storage, source, dest, false);
- if(error != FSE_OK) {
- error = storage_common_merge(storage, source, dest);
-
- if(error == FSE_OK) {
- storage_simply_remove_recursive(storage, source);
- }
+ if(error == FSE_OK) {
+ storage_simply_remove_recursive(storage, source);
}
return error;
diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c
index 5e2fe6432..d8c50833a 100644
--- a/applications/settings/about/about.c
+++ b/applications/settings/about/about.c
@@ -87,6 +87,7 @@ static DialogMessageButton icon2_screen(DialogsApp* dialogs, DialogMessage* mess
message, furi_hal_version_get_mic_id(), 63, 27, AlignLeft, AlignCenter);
result = dialog_message_show(dialogs, message);
dialog_message_set_icon(message, NULL, 0, 0);
+ dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop);
return result;
}
diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c
index 1663246db..557956650 100644
--- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c
+++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c
@@ -25,19 +25,6 @@ void desktop_settings_scene_keybinds_action_on_enter(void* context) {
app->scene_manager, DesktopSettingsAppSceneKeybindsActionType);
if(action_type == DesktopSettingsAppKeybindActionTypeMainApp) {
- for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) {
- submenu_add_item(
- submenu,
- FLIPPER_EXTERNAL_APPS[i].name,
- (uint32_t)FLIPPER_EXTERNAL_APPS[i].name,
- desktop_settings_scene_keybinds_action_submenu_callback,
- app);
-
- // Select keybind item in submenu
- if(!strncmp(FLIPPER_EXTERNAL_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) {
- pre_select_item = (uint32_t)FLIPPER_EXTERNAL_APPS[i].name;
- }
- }
for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
submenu_add_item(
submenu,
@@ -51,6 +38,19 @@ void desktop_settings_scene_keybinds_action_on_enter(void* context) {
pre_select_item = (uint32_t)FLIPPER_APPS[i].name;
}
}
+ for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) {
+ submenu_add_item(
+ submenu,
+ FLIPPER_EXTERNAL_APPS[i].name,
+ (uint32_t)FLIPPER_EXTERNAL_APPS[i].name,
+ desktop_settings_scene_keybinds_action_submenu_callback,
+ app);
+
+ // Select keybind item in submenu
+ if(!strncmp(FLIPPER_EXTERNAL_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) {
+ pre_select_item = (uint32_t)FLIPPER_EXTERNAL_APPS[i].name;
+ }
+ }
} else if(action_type == DesktopSettingsAppKeybindActionTypeMoreActions) {
for(size_t i = 0; i < EXTRA_KEYBINDS_COUNT; i++) {
submenu_add_item(
@@ -67,7 +67,6 @@ void desktop_settings_scene_keybinds_action_on_enter(void* context) {
}
}
- // submenu_set_header(submenu, "Keybind action:");
submenu_set_selected_item(submenu, pre_select_item); // If set during loop, visual glitch.
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c
index 9fd078f7e..17791ecb3 100644
--- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c
+++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c
@@ -45,7 +45,6 @@ static void
}
furi_record_close(RECORD_STORAGE);
if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) {
- submenu_reset(app->submenu); // Prevent menu from being shown when we exiting scene
strncpy(keybind, furi_string_get_cstr(temp_path), MAX_KEYBIND_LENGTH);
DESKTOP_KEYBINDS_SAVE(&app->desktop->keybinds, sizeof(app->desktop->keybinds));
scene_manager_search_and_switch_to_previous_scene(
@@ -69,7 +68,6 @@ void desktop_settings_scene_keybinds_action_type_on_enter(void* context) {
DesktopSettingsApp* app = context;
Submenu* submenu = app->submenu;
char* keybind = desktop_settings_app_get_keybind(app);
- submenu_reset(submenu);
submenu_add_item(
submenu,
@@ -107,6 +105,11 @@ void desktop_settings_scene_keybinds_action_type_on_enter(void* context) {
selected = DesktopSettingsAppKeybindActionTypeMainApp;
}
}
+ for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) {
+ if(!strncmp(FLIPPER_EXTERNAL_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) {
+ selected = DesktopSettingsAppKeybindActionTypeMainApp;
+ }
+ }
if(storage_file_exists(furi_record_open(RECORD_STORAGE), keybind)) {
selected = DesktopSettingsAppKeybindActionTypeExternalApp;
diff --git a/applications/settings/power_settings_app/views/battery_info.c b/applications/settings/power_settings_app/views/battery_info.c
index e78e0e326..dd539bd6c 100644
--- a/applications/settings/power_settings_app/views/battery_info.c
+++ b/applications/settings/power_settings_app/views/battery_info.c
@@ -50,8 +50,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
(uint32_t)(data->vbus_voltage * 10) % 10,
current);
} else if(current < -5) {
- // Often gauge reports anything in the range 1~5ma as 5ma
- // That brings confusion, so we'll treat it as Napping
+ // 0-5ma deadband
snprintf(
emote,
sizeof(emote),
diff --git a/applications/system/updater/application.fam b/applications/system/updater/application.fam
index f53ee9b07..cdf98530b 100644
--- a/applications/system/updater/application.fam
+++ b/applications/system/updater/application.fam
@@ -6,7 +6,6 @@ App(
requires=[
"gui",
"storage",
- "archive",
],
conflicts=["desktop"],
entry_point="updater_srv",
@@ -23,7 +22,6 @@ App(
"gui",
"storage",
"bt",
- "archive",
],
conflicts=["updater"],
provides=["updater_start"],
diff --git a/applications/system/updater/updater.c b/applications/system/updater/updater.c
index 9d3a7bab8..248435b61 100644
--- a/applications/system/updater/updater.c
+++ b/applications/system/updater/updater.c
@@ -32,7 +32,7 @@ static void
updater_main_model_set_state(main_view, message, progress, failed);
}
-Updater* updater_alloc(char* arg) {
+Updater* updater_alloc(const char* arg) {
Updater* updater = malloc(sizeof(Updater));
if(arg && strlen(arg)) {
updater->startup_arg = furi_string_alloc_set(arg);
@@ -118,7 +118,7 @@ void updater_free(Updater* updater) {
free(updater);
}
-int32_t updater_srv(char* p) {
+int32_t updater_srv(const char* p) {
Updater* updater = updater_alloc(p);
view_dispatcher_run(updater->view_dispatcher);
updater_free(updater);
diff --git a/applications/system/updater/updater_i.h b/applications/system/updater/updater_i.h
index 4940eb60e..4e3c704d2 100644
--- a/applications/system/updater/updater_i.h
+++ b/applications/system/updater/updater_i.h
@@ -52,7 +52,7 @@ typedef struct {
int32_t idle_ticks;
} Updater;
-Updater* updater_alloc(char* arg);
+Updater* updater_alloc(const char* arg);
void updater_free(Updater* updater);
diff --git a/assets/resources/apps_data/esp_flasher/Black_Magic.bin b/assets/resources/apps_data/esp_flasher/Black_Magic.bin
new file mode 100644
index 000000000..337fbe603
Binary files /dev/null and b/assets/resources/apps_data/esp_flasher/Black_Magic.bin differ
diff --git a/assets/resources/apps_data/esp_flasher/Evil_Portal.bin b/assets/resources/apps_data/esp_flasher/Evil_Portal.bin
new file mode 100644
index 000000000..993755ee5
Binary files /dev/null and b/assets/resources/apps_data/esp_flasher/Evil_Portal.bin differ
diff --git a/assets/resources/apps_data/esp_flasher/Marauder.bin b/assets/resources/apps_data/esp_flasher/Marauder.bin
new file mode 100644
index 000000000..379d6c313
Binary files /dev/null and b/assets/resources/apps_data/esp_flasher/Marauder.bin differ
diff --git a/assets/resources/apps_data/evil_portal/ap.config.txt b/assets/resources/apps_data/evil_portal/ap.config.txt
new file mode 100644
index 000000000..a69f2a885
--- /dev/null
+++ b/assets/resources/apps_data/evil_portal/ap.config.txt
@@ -0,0 +1 @@
+Xtreme Demo
\ No newline at end of file
diff --git a/assets/resources/apps_data/evil_portal/xtreme.html b/assets/resources/apps_data/evil_portal/xtreme.html
new file mode 100644
index 000000000..0de50314c
--- /dev/null
+++ b/assets/resources/apps_data/evil_portal/xtreme.html
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/resources/badkb/demo_android.txt b/assets/resources/badkb/demo_android.txt
index 2e4820490..befb5737b 100644
--- a/assets/resources/badkb/demo_android.txt
+++ b/assets/resources/badkb/demo_android.txt
@@ -7,8 +7,8 @@ ENTER
DELAY 1000
CTRL l
DELAY 100
-STRING https://github.com/ClaraCrazy/Flipper-Xtreme
+STRING https://github.com/Flipper-XFW/Xtreme-Firmware
DELAY 100
ENTER
DELAY 500
-STRING f
\ No newline at end of file
+STRING f
diff --git a/assets/resources/badkb/demo_ios.txt b/assets/resources/badkb/demo_ios.txt
index eca294e47..e269704f6 100644
--- a/assets/resources/badkb/demo_ios.txt
+++ b/assets/resources/badkb/demo_ios.txt
@@ -2,12 +2,12 @@ REM Version 1.0
REM OS: iOS
REM Author: Peaakss | Optimized for older versions by WillyJL
REM Description: A simple payload that opens safari and inserts a link
-REM NOTICE CHANGE "STRING" to your desired link | EXAMPLE: STRING https://github.com/ClaraCrazy/Flipper-Xtreme |
+REM NOTICE CHANGE "STRING" to your desired link
GUI h
DELAY 420
GUI SPACE
DELAY 420
-STRING https://github.com/ClaraCrazy/Flipper-Xtreme
+STRING https://github.com/Flipper-XFW/Xtreme-Firmware
DELAY 69
ENTER
diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir
index 0e4ced07d..df312151d 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 13th Jul, 2023
-# Last Checked 13th Jul, 2023
+# Last Updated 14th Jul, 2023
+# Last Checked 14th Jul, 2023
#
# Model: Electrolux EACM-16 HP/N3
name: Off
@@ -152,6 +152,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
name: Dh
type: raw
frequency: 38000
@@ -337,7 +338,7 @@ frequency: 38000
duty_cycle: 0.330000
data: 503 365 500 364 501 366 499 365 500 364 502 25049 3535 1660 504 1228 503 390 474 391 473 393 471 1261 469 397 468 397 469 397 469 397 469 1264 468 398 468 1264 468 1264 468 398 468 1265 467 1265 467 1265 467 1265 467 1265 467 399 467 399 467 1266 466 399 467 400 466 400 466 400 466 423 443 423 443 401 465 423 442 424 442 424 442 1290 442 424 442 1290 442 424 442 424 441 424 442 1290 442 1291 441 425 441 424 442 425 441 425 441 1291 441 425 440 425 441 425 441 425 441 425 441 425 440 425 441 425 441 425 441 425 441 426 440 1292 440 1292 440 1292 440 426 440 426 440 1292 440 1293 439 1293 439 35480 3503 1696 467 1264 468 398 468 398 467 398 468 1265 467 398 467 399 467 399 466 399 467 1265 467 399 467 1266 466 1267 465 400 466 1290 442 1290 442 1290 442 1290 442 1290 442 424 442 424 442 1290 442 424 441 424 442 424 442 424 442 424 442 424 441 424 442 425 441 424 442 425 441 425 441 1291 441 425 441 425 441 425 441 425 440 1292 440 425 441 425 440 426 440 426 440 426 440 426 440 426 440 426 440 426 440 426 439 427 439 426 440 426 440 1293 439 427 439 427 439 427 438 427 439 428 438 1294 438 428 437 428 438 1295 437 1319 413 453 413 35480 3503 1696 468 1265 467 398 468 398 468 398 468 1265 467 398 468 399 466 399 467 399 467 1266 466 399 466 1267 465 1290 442 401 465 1290 442 1290 442 1290 442 1290 442 1290 442 424 442 424 441 1291 441 424 442 424 442 424 442 424 442 424 441 424 442 425 441 424 442 424 441 425 441 425 441 425 440 425 441 425 441 425 441 425 441 425 441 425 441 1292 440 426 440 426 440 1292 440 426 440 426 440 1293 439 426 440 426 440 1293 439 1293 439 1293 439 427 439 1294 438 427 438 427 439 427 438 428 438 428 438 428 438 428 438 453 413 429 437 453 413 1319 413 1320 412 1320 412 1320 412 454 412 1320 412 454 412 1321 411 1321 411 1321 411 1321 411 1321 411 455 410 455 411 455 411 455 410 456 410 456 410 456 410 481 384 481 385 482 383 482 383 483 358 507 359 1374 358 1374 358 508 358 508 358 508 358 509 357 509 357 535 331 535 331 535 330 535 330 536 330 1403 329 1403 329 563 302 564 301 564 302 564 301 565 301 591 274 619 246 593 273 620 245 620 245 621 245 673 189
#
-# Model: Mitsubishi SRK63HE.
+# Model: Mitsubishi Heavy Industries SRK63HE
name: Off
type: raw
frequency: 38000
@@ -585,44 +586,43 @@ frequency: 38000
duty_cycle: 0.330000
data: 8780 4015 578 1498 553 471 526 494 525 494 524 1520 525 495 523 498 522 499 521 502 522 497 522 499 522 500 521 1519 522 500 521 499 521 1520 546 1496 521 503 523 494 522 500 521 499 522 1520 521 499 522 499 522 502 522 1518 521 501 521 1522 522
#
-# Model: Shivaki General
+# Model: Shivaki SSA18002
name: Off
type: raw
frequency: 38000
duty_cycle: 0.330000
-data: 3163 1577 577 1009 579 1008 579 342 485 342 485 342 485 1033 579 339 462 342 485 1033 553 1034 552 342 485 1035 550 342 484 343 483 1039 547 1040 546 341 486 1041 546 1041 545 341 486 341 486 1041 545 341 486 340 487 1041 545 341 486 341 486 340 487 340 488 340 487 340 487 341 486 341 486 340 487 340 487 341 486 340 487 341 487 341 486 341 486 341 486 340 487 341 486 340 487 340 487 1041 545 341 486 341 486 1042 545 1041 545 341 486 340 487 340 487 340 487 340 487 341 486 1042 544 341 486 1042 544 341 486 341 486 341 486 341 486 341 486 341 486 341 486 341 486 1042 544 1042 544 1042 544 1042 544 340 488 341 486 341 486 341 486 341 486 341 486 341 486 341 486 341 486 340 487 340 487 341 487 341 486 341 486 341 487 341 486 341 486 341 486 341 486 341 486 341 486 341 486 341 486 341 486 340 487 341 486 341 487 341 486 341 487 341 486 341 486 340 487 1043 543 1043 544 341 486 1043 543 341 486 1043 543 1044 542 340 487 340 488
-#
+data: 3197 1545 581 1033 553 1006 606 338 463 342 485 339 488 1033 553 342 485 342 485 1034 551 1035 550 342 485 1037 548 342 485 340 487 1040 546 1040 546 340 487 1040 546 1040 546 340 487 340 488 1040 546 340 487 340 488 1040 546 340 487 340 487 340 487 342 485 340 487 340 487 340 487 342 485 342 485 342 485 340 487 342 485 340 487 340 487 342 485 342 485 342 485 342 485 340 488 342 485 1041 545 340 487 340 487 1041 545 1041 545 340 488 340 487 340 487 340 487 340 488 342 485 342 485 340 487 340 488 1041 545 340 487 340 487 342 486 342 485 340 487 340 487 340 487 340 487 342 485 341 486 1041 545 340 487 340 487 340 487 340 487 340 488 342 485 340 487 342 485 342 485 340 487 342 485 340 487 340 488 342 485 343 484 340 488 340 487 340 487 340 487 340 487 342 485 340 487 340 487 341 486 342 485 340 488 342 485 342 485 342 485 340 487 340 487 340 488 1042 544 340 487 340 487 340 487 340 487 340 487 340 487 340 488 342 485
name: Cool_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
-data: 3193 1549 579 1007 580 1007 579 342 485 342 485 342 511 1007 579 338 463 342 485 1034 552 1034 551 342 484 1035 550 342 484 340 487 1039 547 1040 546 341 487 1041 545 1041 545 340 487 341 487 1041 545 341 486 340 487 1041 545 341 486 341 486 340 487 340 487 341 486 340 487 341 486 341 486 340 487 341 486 340 487 340 488 341 486 340 487 340 487 340 487 341 487 1041 545 340 487 340 487 1041 545 340 488 341 486 1042 544 1042 544 341 487 341 486 341 486 340 487 341 487 341 486 1042 544 1042 544 1042 544 1042 545 341 486 341 487 341 486 341 486 1042 545 341 486 1042 544 1042 544 1042 544 1042 544 341 487 341 486 340 487 341 486 341 486 340 487 341 486 340 487 341 486 341 486 341 486 341 486 341 487 341 486 341 486 341 486 340 488 341 486 341 486 341 486 341 486 341 486 340 488 341 486 341 486 341 487 341 486 341 486 341 486 1043 544 341 486 341 486 341 487 1043 543 341 486 341 486 341 486 341 486 1044 542 340 487 341 486 341 486
+data: 3139 1604 522 1063 523 1063 523 340 487 342 485 340 487 1063 523 342 485 340 487 1063 523 1062 523 342 484 1063 522 342 485 342 509 1041 520 1066 520 342 485 1067 519 1067 519 342 485 342 485 1067 519 342 485 342 485 1067 519 342 485 342 485 342 485 342 485 342 485 342 485 342 485 342 485 343 484 342 485 343 484 342 485 342 485 342 485 342 485 342 485 342 485 1068 518 342 485 342 485 1068 518 342 485 342 485 1068 518 1068 518 342 485 342 485 342 485 342 485 342 485 342 485 1068 518 1069 517 1068 518 1069 517 342 485 342 485 342 485 342 485 343 484 343 484 343 484 342 485 343 484 343 484 343 484 342 485 342 485 342 485 342 485 343 484 342 485 343 484 342 485 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 342 485 343 484 342 485 343 484 343 484 342 485 342 485 343 484 342 485 343 484 342 485 342 485 342 485 342 485 343 484 1093 493 1093 493 1094 492 342 485 1093 493 342 485 342 485 1094 492 1093 493
#
name: Heat_hi
type: raw
frequency: 38000
duty_cycle: 0.330000
-data: 3169 1547 579 1006 580 1006 580 342 485 342 485 342 484 1033 553 342 485 342 485 1033 552 1034 551 342 484 1035 550 342 484 342 485 1039 546 1040 546 342 485 1040 546 1040 546 342 485 343 484 1040 546 342 485 342 485 1040 546 342 486 342 485 343 484 342 485 343 484 342 485 342 485 342 485 343 484 342 485 342 485 342 485 343 484 342 485 342 485 342 485 342 485 1041 545 342 485 343 484 1041 545 342 485 343 484 1041 545 342 485 343 484 342 485 342 485 342 485 342 485 342 485 1041 545 342 485 343 484 342 485 342 485 342 485 343 484 342 485 1041 545 342 485 1041 545 1041 545 1041 545 1041 545 342 485 342 485 343 484 342 485 343 484 342 485 342 485 342 485 342 485 342 485 342 485 342 485 343 484 342 485 342 485 342 485 342 485 342 485 342 485 342 485 342 485 343 484 342 485 342 485 342 485 342 485 342 485 343 484 342 485 1042 544 343 484 343 484 342 485 1042 544 341 486 342 485 342 485 343 484 342 485 342 485 342 485 340 487
+data: 3192 1547 579 1009 577 1008 578 338 489 338 488 338 489 1010 576 338 489 338 489 1035 550 1036 549 339 488 1038 547 339 488 339 488 1040 546 1040 546 339 488 1040 546 1040 546 339 488 339 489 1040 546 339 488 339 489 1040 546 339 488 339 488 339 489 339 488 339 489 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 1041 545 339 489 339 488 1041 545 339 488 339 488 1041 545 339 488 339 489 339 488 339 488 339 488 339 489 339 488 1041 545 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 489 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 489 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 489 339 488 339 488 339 488 339 488 340 487 339 488 339 488 339 489 339 488 339 488 339 488 1042 544 1042 545 1042 544 339 488 1042 544 1042 544 1042 544 339 488 1042 544
#
name: Heat_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
-data: 3162 1605 523 1064 522 1064 523 343 484 343 484 343 484 1063 523 343 484 343 484 1063 523 1063 523 343 484 1063 523 343 484 343 484 1065 521 1066 520 343 484 1068 518 1068 518 343 484 343 484 1068 518 343 484 343 484 1068 518 343 484 343 484 343 484 343 484 343 484 342 485 343 484 343 485 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 1068 518 343 484 343 484 1069 517 343 484 343 485 1069 517 343 484 343 484 343 485 343 484 343 484 343 484 343 485 343 484 343 484 343 484 1070 516 344 483 344 483 344 484 343 484 1070 517 344 483 1094 493 1070 517 1093 493 1094 492 344 483 343 484 343 484 343 484 343 484 343 484 343 485 343 484 343 484 343 484 344 483 343 484 344 483 343 484 344 483 343 484 344 483 343 484 343 484 344 483 344 483 343 484 343 484 344 483 343 484 343 484 343 484 344 483 343 484 1094 492 343 484 344 484 343 484 1094 492 1094 492 1094 492 1094 492 343 484 344 483 343 484 343 484 344 483
+data: 3194 1546 580 1006 580 1005 581 341 485 341 511 337 465 1032 554 341 486 339 488 1033 552 1033 552 341 485 1035 550 339 487 339 487 1039 546 1039 547 339 488 1040 546 1040 546 339 488 339 488 1040 546 339 488 339 488 1040 546 339 488 340 487 339 488 339 488 339 488 339 488 339 488 340 487 339 488 339 488 339 488 339 488 340 487 339 488 339 488 339 488 339 488 1040 546 339 488 339 488 1040 546 339 488 340 487 1040 546 339 488 340 487 339 488 339 488 340 487 339 488 340 487 340 487 340 487 339 488 1041 545 340 487 340 487 339 488 340 487 340 487 339 488 340 487 340 487 340 487 340 487 339 488 340 487 340 487 339 488 339 488 339 488 339 488 339 488 340 487 340 487 339 488 339 488 340 487 339 488 340 487 340 487 339 488 340 487 340 487 340 487 340 487 340 487 340 487 339 488 339 488 340 487 339 488 340 487 340 487 339 488 339 488 339 488 340 487 1042 544 340 487 1042 544 340 487 339 488 340 487 340 487 1042 544 1042 544
#
name: Cool_lo
type: raw
frequency: 38000
duty_cycle: 0.330000
-data: 3138 1604 523 1063 523 1063 523 343 484 343 484 343 484 1063 523 343 484 343 484 1062 523 1063 523 343 484 1063 522 343 484 343 484 1065 521 1066 519 343 484 1067 519 1067 519 343 484 343 484 1067 519 343 484 343 484 1067 519 343 484 343 484 343 484 343 484 343 484 343 484 343 484 342 485 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 1068 518 343 484 343 484 1068 518 343 484 343 484 1068 518 1068 518 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 1067 519 343 484 343 484 343 484 343 484 1067 519 343 484 1067 519 1067 519 1068 518 1067 519 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 343 484 1068 518 343 484 343 484 343 484 1068 518 1068 518 343 484 343 484 1068 518 343 484 343 484 343 484 343 484
+data: 3197 1547 580 1005 581 1033 553 341 512 338 463 341 486 1033 553 339 488 339 488 1033 552 1034 552 341 485 1036 549 339 488 339 488 1039 547 1040 547 340 487 1040 546 1040 546 340 487 340 487 1040 546 340 488 340 487 1040 546 340 487 340 487 340 487 340 487 340 487 340 487 339 488 339 488 340 487 340 488 339 488 340 487 340 487 339 489 340 487 340 487 339 488 1041 545 339 489 339 488 1040 546 339 488 339 488 1041 545 1041 546 340 487 340 487 340 487 340 488 340 487 340 487 340 487 340 487 340 487 1041 545 340 487 340 487 339 488 339 488 339 489 339 488 340 487 340 487 340 487 340 487 340 487 340 487 339 488 340 487 340 488 340 487 340 487 340 487 340 487 340 487 340 488 340 487 340 487 340 487 340 487 340 487 340 487 340 487 339 488 340 488 339 488 340 487 340 487 339 488 340 487 340 487 340 487 340 488 340 487 340 487 340 487 339 488 340 487 1042 544 340 487 340 488 1042 544 340 487 340 488 340 487 1043 543 1043 543
#
name: Dh
type: raw
frequency: 38000
duty_cycle: 0.330000
-data: 3165 1578 549 1037 549 1037 550 342 485 343 484 343 513 1034 551 340 487 340 487 1035 551 1035 550 340 486 1037 548 341 485 341 485 1041 545 1041 545 341 486 1042 544 1042 544 340 487 341 486 1042 544 341 486 340 488 1042 544 341 487 341 486 341 486 341 461 343 509 341 487 341 461 343 484 343 510 341 486 341 461 343 484 343 509 341 462 343 509 341 462 343 484 1068 518 343 510 341 461 1068 518 343 484 343 484 343 484 1068 518 343 484 343 484 343 484 343 484 342 485 343 485 1068 518 1068 518 1068 518 343 485 343 484 343 485 343 484 343 484 343 484 343 484 343 484 1068 518 1068 518 1068 518 343 484 343 484 343 485 343 484 343 484 343 484 343 484 343 484 343 484 342 485 343 485 343 484 343 484 343 484 343 484 343 484 343 484 343 485 343 484 343 484 343 484 343 484 343 484 343 485 343 484 343 484 343 484 343 484 343 484 1070 516 343 484 343 484 343 484 1071 515 343 484 1094 492 343 484 343 484 343 485 344 483 343 484 343 484
+data: 3196 1545 581 1005 580 1008 604 337 464 338 488 338 489 1033 553 339 488 338 489 1033 552 1034 551 339 487 1036 549 339 488 339 488 1039 547 1039 547 340 487 1040 546 1040 546 339 488 339 488 1040 546 340 487 339 488 1040 546 339 488 339 488 339 488 339 488 339 488 339 488 340 487 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 340 487 339 488 1040 546 339 488 339 488 1040 546 339 488 339 488 339 488 1040 546 339 488 339 488 339 488 339 488 339 488 339 488 1040 546 1041 545 1041 545 340 487 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 340 487 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 340 487 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 339 488 340 487 339 488 339 488 340 487 339 488 1042 544 339 488 1042 544 339 488 339 488 339 488 339 488 1042 544 1042 544
#
-# Model: Mitsubishi MSZ-AP25VGK
+# Model: Mitsubishi Electric MSZ-AP25VGK
name: Off
type: raw
frequency: 38000
diff --git a/fbt_options.py b/fbt_options.py
index efafce09d..f8e42f90d 100644
--- a/fbt_options.py
+++ b/fbt_options.py
@@ -1,6 +1,6 @@
from pathlib import Path
+import subprocess
import posixpath
-import datetime
# For more details on these options, run 'fbt -h'
@@ -19,7 +19,7 @@ DEBUG = 0
# If OS environment has DIST_SUFFIX set, it will be used instead
# How about we add the timestamp automatically. Solves some problems
-DIST_SUFFIX = f"XFW-0049_{datetime.datetime.today().strftime('%d%m%Y')}"
+DIST_SUFFIX = f"XFW-DEV_@{subprocess.check_output(['git', 'rev-parse', '--short=7', 'HEAD']).decode().strip().upper()}"
# Coprocessor firmware
COPRO_OB_DATA = "scripts/ob.data"
diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv
index 12229e5b8..8dd50b537 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.1,,
+Version,+,34.3,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -36,7 +36,6 @@ Header,+,applications/services/notification/notification_messages.h,,
Header,+,applications/services/power/power_service/power.h,,
Header,+,applications/services/rpc/rpc_app.h,,
Header,+,applications/services/storage/storage.h,,
-Header,-,firmware/targets/f18/furi_hal/furi_hal_power_calibration.h,,
Header,+,firmware/targets/f18/furi_hal/furi_hal_resources.h,,
Header,+,firmware/targets/f18/furi_hal/furi_hal_spi_config.h,,
Header,+,firmware/targets/f18/furi_hal/furi_hal_target_hw.h,,
@@ -82,6 +81,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,,
Header,+,lib/digital_signal/digital_signal.h,,
+Header,+,lib/drivers/cc1101_regs.h,,
Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,,
Header,+,lib/flipper_application/flipper_application.h,,
@@ -1147,6 +1147,7 @@ Function,-,furi_hal_power_insomnia_level,uint16_t,
Function,+,furi_hal_power_is_charging,_Bool,
Function,+,furi_hal_power_is_charging_done,_Bool,
Function,+,furi_hal_power_is_otg_enabled,_Bool,
+Function,+,furi_hal_power_is_shutdown_requested,_Bool,
Function,+,furi_hal_power_off,void,
Function,+,furi_hal_power_reset,void,
Function,+,furi_hal_power_set_battery_charge_voltage_limit,void,float
diff --git a/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h b/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h
deleted file mode 100644
index e97e1657d..000000000
--- a/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h
+++ /dev/null
@@ -1,37 +0,0 @@
-const ParamCEDV cedv = {
- .cedv_conf.gauge_conf =
- {
- .CCT = 1,
- .CSYNC = 0,
- .EDV_CMP = 0,
- .SC = 1,
- .FIXED_EDV0 = 1,
- .FCC_LIM = 1,
- .FC_FOR_VDQ = 1,
- .IGNORE_SD = 1,
- .SME0 = 0,
- },
- .full_charge_cap = 1300,
- .design_cap = 1300,
- .EDV0 = 3300,
- .EDV1 = 3321,
- .EDV2 = 3355,
- .EMF = 3679,
- .C0 = 430,
- .C1 = 0,
- .R1 = 408,
- .R0 = 334,
- .T0 = 4626,
- .TC = 11,
- .DOD0 = 4044,
- .DOD10 = 3905,
- .DOD20 = 3807,
- .DOD30 = 3718,
- .DOD40 = 3642,
- .DOD50 = 3585,
- .DOD60 = 3546,
- .DOD70 = 3514,
- .DOD80 = 3477,
- .DOD90 = 3411,
- .DOD100 = 3299,
-};
diff --git a/firmware/targets/f18/furi_hal/furi_hal_power_config.c b/firmware/targets/f18/furi_hal/furi_hal_power_config.c
new file mode 100644
index 000000000..50efceb7d
--- /dev/null
+++ b/firmware/targets/f18/furi_hal/furi_hal_power_config.c
@@ -0,0 +1,149 @@
+#include
+
+const BQ27220DMGaugingConfig furi_hal_power_gauge_data_memory_gauging_config = {
+ .CCT = 1,
+ .CSYNC = 0,
+ .EDV_CMP = 0,
+ .SC = 1,
+ .FIXED_EDV0 = 1,
+ .FCC_LIM = 1,
+ .FC_FOR_VDQ = 1,
+ .IGNORE_SD = 1,
+ .SME0 = 0,
+};
+
+const BQ27220DMData furi_hal_power_gauge_data_memory[] = {
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1GaugingConfig,
+ .type = BQ27220DMTypePtr16,
+ .value.u32 = (uint32_t)&furi_hal_power_gauge_data_memory_gauging_config,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1FullChargeCapacity,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 1300,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1DesignCapacity,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 1300,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1EMF,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3679,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1C0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 430,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1R0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 334,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1T0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 4626,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1R1,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 408,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1TC,
+ .type = BQ27220DMTypeU8,
+ .value.u8 = 11,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1C1,
+ .type = BQ27220DMTypeU8,
+ .value.u8 = 0,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 4044,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD10,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3905,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD20,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3807,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD30,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3718,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD40,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3642,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD50,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3585,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD60,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3546,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD70,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3514,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD80,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3477,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD90,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3411,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD100,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3299,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3300,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV1,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3321,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV2,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3355,
+ },
+ {
+ .address = BQ27220DMAddressCalibrationCurrentDeadband,
+ .type = BQ27220DMTypeU8,
+ .value.u8 = 1,
+ },
+ {
+ .address = BQ27220DMAddressConfigurationPowerSleepCurrent,
+ .type = BQ27220DMTypeI16,
+ .value.i16 = 1,
+ },
+ {
+ .type = BQ27220DMTypeEnd,
+ },
+};
diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv
index d0e8126ff..327d884f4 100644
--- a/firmware/targets/f7/api_symbols.csv
+++ b/firmware/targets/f7/api_symbols.csv
@@ -1,6 +1,8 @@
entry,status,name,type,params
-Version,+,34.1,,
+Version,+,34.3,,
+Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/main/archive/helpers/favorite_timeout.h,,
+Header,+,applications/services/applications.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -52,7 +54,6 @@ Header,+,firmware/targets/f7/furi_hal/furi_hal_idle_timer.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_interrupt.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_nfc.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_os.h,,
-Header,-,firmware/targets/f7/furi_hal/furi_hal_power_calibration.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_pwm.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_resources.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_rfid.h,,
@@ -90,6 +91,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,,
Header,+,lib/digital_signal/digital_signal.h,,
+Header,+,lib/drivers/cc1101_regs.h,,
Header,+,lib/drivers/rgb_backlight.h,,
Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,,
@@ -197,6 +199,7 @@ Header,+,lib/subghz/blocks/encoder.h,,
Header,+,lib/subghz/blocks/generic.h,,
Header,+,lib/subghz/blocks/math.h,,
Header,+,lib/subghz/devices/cc1101_configs.h,,
+Header,+,lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h,,
Header,+,lib/subghz/environment.h,,
Header,+,lib/subghz/protocols/raw.h,,
Header,+,lib/subghz/receiver.h,,
@@ -879,23 +882,6 @@ Function,-,fdim,double,"double, double"
Function,-,fdimf,float,"float, float"
Function,-,fdiml,long double,"long double, long double"
Function,-,fdopen,FILE*,"int, const char*"
-Function,-,felica_check_ic_type,_Bool,uint8_t*
-Function,-,felica_clear,void,FelicaData*
-Function,-,felica_define_normal_block,void,"FelicaService*, uint16_t, uint8_t*"
-Function,+,felica_estimate_timing_us,uint_least32_t,"uint_least8_t, uint_least8_t"
-Function,-,felica_get_ic_type,FelicaICType,uint8_t*
-Function,-,felica_get_service_name,FuriString*,FelicaService*
-Function,+,felica_get_system_name,FuriString*,FelicaSystem*
-Function,-,felica_lite_dump_data,_Bool,"FuriHalNfcTxRxContext*, FelicaReader*, FelicaData*, FelicaSystem*"
-Function,-,felica_lite_is_issued,_Bool,FelicaLiteInfo*
-Function,-,felica_lite_prepare_unencrypted_read,uint8_t,"uint8_t*, const FelicaReader*, _Bool, const uint8_t*, uint8_t"
-Function,-,felica_lite_prepare_unencrypted_write,uint8_t,"uint8_t*, const FelicaReader*, const uint8_t*, uint8_t, const uint8_t*"
-Function,-,felica_parse_unencrypted_read,uint16_t,"uint8_t*, uint8_t, FelicaReader*, uint8_t*, uint16_t"
-Function,-,felica_parse_unencrypted_write,_Bool,"uint8_t*, uint8_t, FelicaReader*"
-Function,-,felica_prepare_unencrypted_read,uint8_t,"uint8_t*, const FelicaReader*, const uint16_t*, uint8_t, const uint32_t*, uint8_t"
-Function,-,felica_prepare_unencrypted_write,uint8_t,"uint8_t*, FelicaReader*, const uint16_t*, uint8_t, const uint32_t*, uint8_t, const uint8_t*"
-Function,-,felica_push_normal_block,void,"FelicaService*, uint8_t*"
-Function,-,felica_read_card,_Bool,"FuriHalNfcTxRxContext*, FelicaData*, uint8_t*, uint8_t*"
Function,-,feof,int,FILE*
Function,-,feof_unlocked,int,FILE*
Function,-,ferror,int,FILE*
@@ -1346,6 +1332,7 @@ Function,-,furi_hal_power_insomnia_level,uint16_t,
Function,+,furi_hal_power_is_charging,_Bool,
Function,+,furi_hal_power_is_charging_done,_Bool,
Function,+,furi_hal_power_is_otg_enabled,_Bool,
+Function,+,furi_hal_power_is_shutdown_requested,_Bool,
Function,+,furi_hal_power_off,void,
Function,+,furi_hal_power_reset,void,
Function,+,furi_hal_power_set_battery_charge_voltage_limit,void,float
@@ -1683,6 +1670,7 @@ Function,+,furi_thread_suspend,void,FuriThreadId
Function,+,furi_thread_yield,void,
Function,+,furi_timer_alloc,FuriTimer*,"FuriTimerCallback, FuriTimerType, void*"
Function,+,furi_timer_free,void,FuriTimer*
+Function,-,furi_timer_get_current_name,const char*,
Function,+,furi_timer_is_running,uint32_t,FuriTimer*
Function,+,furi_timer_pending_callback,void,"FuriTimerPendigCallback, void*, uint32_t"
Function,+,furi_timer_start,FuriStatus,"FuriTimer*, uint32_t"
@@ -2033,7 +2021,7 @@ Function,-,mf_classic_auth_write_block,_Bool,"FuriHalNfcTxRxContext*, MfClassicB
Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey"
Function,-,mf_classic_authenticate_skip_activate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey, _Bool, uint32_t"
Function,-,mf_classic_block_to_value,_Bool,"const uint8_t*, int32_t*, uint8_t*"
-Function,-,mf_classic_check_card_type,_Bool,FuriHalNfcADevData*
+Function,-,mf_classic_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
Function,+,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*"
Function,-,mf_classic_dict_add_key_str,_Bool,"MfClassicDict*, FuriString*"
Function,+,mf_classic_dict_alloc,MfClassicDict*,MfClassicDictType
@@ -2051,7 +2039,7 @@ Function,+,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*"
Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*"
Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict*
Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*, _Bool"
-Function,-,mf_classic_get_classic_type,MfClassicType,FuriHalNfcADevData*
+Function,-,mf_classic_get_classic_type,MfClassicType,"uint8_t, uint8_t, uint8_t"
Function,+,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*"
Function,+,mf_classic_get_sector_by_block,uint8_t,uint8_t
Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t
@@ -2092,7 +2080,7 @@ Function,+,mf_df_cat_file,void,"MifareDesfireFile*, FuriString*"
Function,-,mf_df_cat_free_mem,void,"MifareDesfireFreeMemory*, FuriString*"
Function,-,mf_df_cat_key_settings,void,"MifareDesfireKeySettings*, FuriString*"
Function,-,mf_df_cat_version,void,"MifareDesfireVersion*, FuriString*"
-Function,-,mf_df_check_card_type,_Bool,FuriHalNfcADevData*
+Function,-,mf_df_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
Function,-,mf_df_clear,void,MifareDesfireData*
Function,-,mf_df_get_application,MifareDesfireApplication*,"MifareDesfireData*, const uint8_t[3]*"
Function,-,mf_df_get_file,MifareDesfireFile*,"MifareDesfireApplication*, uint8_t"
@@ -2117,7 +2105,7 @@ Function,-,mf_df_prepare_read_data,uint16_t,"uint8_t*, uint8_t, uint32_t, uint32
Function,-,mf_df_prepare_read_records,uint16_t,"uint8_t*, uint8_t, uint32_t, uint32_t"
Function,-,mf_df_prepare_select_application,uint16_t,"uint8_t*, uint8_t[3]"
Function,-,mf_df_read_card,_Bool,"FuriHalNfcTxRxContext*, MifareDesfireData*"
-Function,-,mf_ul_check_card_type,_Bool,FuriHalNfcADevData*
+Function,-,mf_ul_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
Function,+,mf_ul_emulation_supported,_Bool,MfUltralightData*
Function,+,mf_ul_is_full_capture,_Bool,MfUltralightData*
Function,-,mf_ul_prepare_emulation,void,"MfUltralightEmulator*, MfUltralightData*"
@@ -2188,7 +2176,6 @@ Function,+,nfc_device_save,_Bool,"NfcDevice*, const char*"
Function,+,nfc_device_save_shadow,_Bool,"NfcDevice*, const char*"
Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*"
Function,+,nfc_device_set_name,void,"NfcDevice*, const char*"
-Function,+,nfc_felica_type,const char*,FelicaICType
Function,+,nfc_file_select,_Bool,NfcDevice*
Function,-,nfc_generate_mf_classic,void,"NfcDeviceData*, uint8_t, MfClassicType"
Function,+,nfc_get_dev_type,const char*,FuriHalNfcType
@@ -2807,6 +2794,7 @@ Function,+,subghz_custom_btn_get_original,uint8_t,
Function,+,subghz_custom_btn_is_allowed,_Bool,
Function,+,subghz_custom_btn_set,_Bool,uint8_t
Function,+,subghz_custom_btns_reset,void,
+Function,-,subghz_device_cc1101_ext_ep,const FlipperAppPluginDescriptor*,
Function,+,subghz_devices_begin,_Bool,const SubGhzDevice*
Function,+,subghz_devices_deinit,void,
Function,+,subghz_devices_end,void,const SubGhzDevice*
@@ -3015,6 +3003,8 @@ Function,+,text_box_reset,void,TextBox*
Function,+,text_box_set_focus,void,"TextBox*, TextBoxFocus"
Function,+,text_box_set_font,void,"TextBox*, TextBoxFont"
Function,+,text_box_set_text,void,"TextBox*, const char*"
+Function,+,text_input_add_extra_symbol,void,"TextInput*, char"
+Function,+,text_input_add_illegal_symbols,void,TextInput*
Function,+,text_input_alloc,TextInput*,
Function,+,text_input_free,void,TextInput*
Function,+,text_input_get_validator_callback,TextInputValidatorCallback,TextInput*
@@ -3147,6 +3137,7 @@ Function,+,variable_item_list_set_enter_callback,void,"VariableItemList*, Variab
Function,+,variable_item_list_set_selected_item,void,"VariableItemList*, uint8_t"
Function,+,variable_item_set_current_value_index,void,"VariableItem*, uint8_t"
Function,+,variable_item_set_current_value_text,void,"VariableItem*, const char*"
+Function,+,variable_item_set_item_label,void,"VariableItem*, const char*"
Function,+,variable_item_set_locked,void,"VariableItem*, _Bool, const char*"
Function,+,variable_item_set_values_count,void,"VariableItem*, uint8_t"
Function,-,vasiprintf,int,"char**, const char*, __gnuc_va_list"
@@ -3303,6 +3294,20 @@ Variable,+,A_Sub1ghz_14,Icon,
Variable,+,A_U2F_14,Icon,
Variable,+,A_Xtreme_14,Icon,
Variable,+,A_iButton_14,Icon,
+Variable,+,FLIPPER_APPS,const FlipperInternalApplication[],
+Variable,+,FLIPPER_APPS_COUNT,const size_t,
+Variable,-,FLIPPER_ARCHIVE,const FlipperInternalApplication,
+Variable,-,FLIPPER_AUTORUN_APP_NAME,const char*,
+Variable,+,FLIPPER_EXTERNAL_APPS,const FlipperExternalApplication[],
+Variable,+,FLIPPER_EXTERNAL_APPS_COUNT,const size_t,
+Variable,-,FLIPPER_ON_SYSTEM_START,const FlipperInternalOnStartHook[],
+Variable,-,FLIPPER_ON_SYSTEM_START_COUNT,const size_t,
+Variable,-,FLIPPER_SERVICES,const FlipperInternalApplication[],
+Variable,-,FLIPPER_SERVICES_COUNT,const size_t,
+Variable,+,FLIPPER_SETTINGS_APPS,const FlipperInternalApplication[],
+Variable,+,FLIPPER_SETTINGS_APPS_COUNT,const size_t,
+Variable,-,FLIPPER_SYSTEM_APPS,const FlipperInternalApplication[],
+Variable,-,FLIPPER_SYSTEM_APPS_COUNT,const size_t,
Variable,+,ICON_PATHS,const IconPath[],
Variable,+,ICON_PATHS_COUNT,const size_t,
Variable,-,ITM_RxBuffer,volatile int32_t,
@@ -3774,6 +3779,7 @@ Variable,+,sequence_set_vibro_on,const NotificationSequence,
Variable,+,sequence_single_vibro,const NotificationSequence,
Variable,+,sequence_solid_yellow,const NotificationSequence,
Variable,+,sequence_success,const NotificationSequence,
+Variable,-,subghz_device_cc1101_int,const SubGhzDevice,
Variable,+,subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs,const uint8_t[],
Variable,+,subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs,const uint8_t[],
Variable,+,subghz_device_cc1101_preset_gfsk_9_99kb_async_regs,const uint8_t[],
diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c
index cdf31954f..b249c8658 100644
--- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c
+++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c
@@ -134,36 +134,21 @@ bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout) {
if(detected) {
if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA) {
nfc_data->type = FuriHalNfcTypeA;
- nfc_data->a_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo;
- nfc_data->a_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo;
- nfc_data->a_data.sak = dev_list[0].dev.nfca.selRes.sak;
+ nfc_data->atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo;
+ nfc_data->atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo;
+ nfc_data->sak = dev_list[0].dev.nfca.selRes.sak;
uint8_t* cuid_start = dev_list[0].nfcid;
if(dev_list[0].nfcidLen == 7) {
cuid_start = &dev_list[0].nfcid[3];
}
- nfc_data->a_data.cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) |
- (cuid_start[2] << 8) | (cuid_start[3]);
+ nfc_data->cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) |
+ (cuid_start[3]);
} else if(
dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCB ||
dev_list[0].type == RFAL_NFC_LISTEN_TYPE_ST25TB) {
nfc_data->type = FuriHalNfcTypeB;
} else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCF) {
nfc_data->type = FuriHalNfcTypeF;
- furi_assert(dev_list[0].nfcidLen == RFAL_NFCF_NFCID2_LEN);
- memcpy(
- &nfc_data->f_data.pmm[0],
- dev_list[0].dev.nfcf.sensfRes.PAD0,
- RFAL_NFCF_SENSF_RES_PAD0_LEN);
- memcpy(
- &nfc_data->f_data.pmm[RFAL_NFCF_SENSF_RES_PAD0_LEN],
- dev_list[0].dev.nfcf.sensfRes.PAD1,
- RFAL_NFCF_SENSF_RES_PAD1_LEN);
- nfc_data->f_data.pmm[RFAL_NFCF_SENSF_RES_PAD0_LEN + RFAL_NFCF_SENSF_RES_PAD1_LEN] =
- dev_list[0].dev.nfcf.sensfRes.MRTIcheck;
- nfc_data->f_data.pmm[RFAL_NFCF_SENSF_RES_PAD0_LEN + RFAL_NFCF_SENSF_RES_PAD1_LEN + 1] =
- dev_list[0].dev.nfcf.sensfRes.MRTIupdate;
- nfc_data->f_data.pmm[RFAL_NFCF_SENSF_RES_PAD0_LEN + RFAL_NFCF_SENSF_RES_PAD1_LEN + 2] =
- dev_list[0].dev.nfcf.sensfRes.PAD2;
} else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCV) {
nfc_data->type = FuriHalNfcTypeV;
}
@@ -386,15 +371,15 @@ void furi_hal_nfc_listen_start(FuriHalNfcDevData* nfc_data) {
// Write PT Memory
uint8_t pt_memory[15] = {};
memcpy(pt_memory, nfc_data->uid, nfc_data->uid_len);
- pt_memory[10] = nfc_data->a_data.atqa[0];
- pt_memory[11] = nfc_data->a_data.atqa[1];
+ pt_memory[10] = nfc_data->atqa[0];
+ pt_memory[11] = nfc_data->atqa[1];
if(nfc_data->uid_len == 4) {
- pt_memory[12] = nfc_data->a_data.sak & ~FURI_HAL_NFC_UID_INCOMPLETE;
+ pt_memory[12] = nfc_data->sak & ~FURI_HAL_NFC_UID_INCOMPLETE;
} else {
pt_memory[12] = FURI_HAL_NFC_UID_INCOMPLETE;
}
- pt_memory[13] = nfc_data->a_data.sak & ~FURI_HAL_NFC_UID_INCOMPLETE;
- pt_memory[14] = nfc_data->a_data.sak & ~FURI_HAL_NFC_UID_INCOMPLETE;
+ pt_memory[13] = nfc_data->sak & ~FURI_HAL_NFC_UID_INCOMPLETE;
+ pt_memory[14] = nfc_data->sak & ~FURI_HAL_NFC_UID_INCOMPLETE;
st25r3916WritePTMem(pt_memory, sizeof(pt_memory));
// Go to sense
diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.h b/firmware/targets/f7/furi_hal/furi_hal_nfc.h
index e970f345d..c87f04a9a 100644
--- a/firmware/targets/f7/furi_hal/furi_hal_nfc.h
+++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.h
@@ -69,25 +69,14 @@ typedef enum {
FuriHalNfcInterfaceNfcDep,
} FuriHalNfcInterface;
-typedef struct {
- uint32_t cuid;
- uint8_t atqa[2];
- uint8_t sak;
-} FuriHalNfcADevData;
-
-typedef struct {
- uint8_t pmm[8];
-} FuriHalNfcFDevData;
-
typedef struct {
FuriHalNfcType type;
FuriHalNfcInterface interface;
uint8_t uid_len;
uint8_t uid[10];
- union {
- FuriHalNfcADevData a_data;
- FuriHalNfcFDevData f_data;
- };
+ uint32_t cuid;
+ uint8_t atqa[2];
+ uint8_t sak;
} FuriHalNfcDevData;
typedef void (
diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c
index 5edde86e9..035919d78 100644
--- a/firmware/targets/f7/furi_hal/furi_hal_power.c
+++ b/firmware/targets/f7/furi_hal/furi_hal_power.c
@@ -15,6 +15,7 @@
#include
#include
+#include
#include
#include
@@ -37,16 +38,18 @@ typedef struct {
volatile uint8_t insomnia;
volatile uint8_t suppress_charge;
- uint8_t gauge_initialized;
- uint8_t charger_initialized;
+ bool gauge_ok;
+ bool charger_ok;
} FuriHalPower;
static volatile FuriHalPower furi_hal_power = {
.insomnia = 0,
.suppress_charge = 0,
+ .gauge_ok = false,
+ .charger_ok = false,
};
-#include
+extern const BQ27220DMData furi_hal_power_gauge_data_memory[];
void furi_hal_power_init() {
#ifdef FURI_HAL_POWER_DEBUG
@@ -63,8 +66,13 @@ void furi_hal_power_init() {
LL_C2_PWR_SetPowerMode(FURI_HAL_POWER_STOP_MODE);
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
- bq27220_init(&furi_hal_i2c_handle_power, &cedv);
- bq25896_init(&furi_hal_i2c_handle_power);
+ // Find and init gauge
+ if(bq27220_init(&furi_hal_i2c_handle_power)) {
+ furi_hal_power.gauge_ok = bq27220_apply_data_memory(
+ &furi_hal_i2c_handle_power, furi_hal_power_gauge_data_memory);
+ }
+ // Find and init charger
+ furi_hal_power.charger_ok = bq25896_init(&furi_hal_i2c_handle_power);
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
FURI_LOG_I(TAG, "Init OK");
@@ -78,14 +86,29 @@ bool furi_hal_power_gauge_is_ok() {
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
- if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) == BQ27220_ERROR ||
- bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status) ==
- BQ27220_ERROR) {
+ if(!bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) ||
+ !bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status)) {
ret = false;
} else {
ret &= battery_status.BATTPRES;
ret &= operation_status.INITCOMP;
- ret &= (cedv.design_cap == bq27220_get_design_capacity(&furi_hal_i2c_handle_power));
+ ret &= furi_hal_power.gauge_ok;
+ }
+
+ furi_hal_i2c_release(&furi_hal_i2c_handle_power);
+
+ return ret;
+}
+
+bool furi_hal_power_is_shutdown_requested() {
+ bool ret = false;
+
+ BatteryStatus battery_status;
+
+ furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
+
+ if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) != BQ27220_ERROR) {
+ ret = battery_status.SYSDWN;
}
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
@@ -576,9 +599,8 @@ void furi_hal_power_debug_get(PropertyValueCallback out, void* context) {
const uint32_t ntc_mpct = bq25896_get_ntc_mpct(&furi_hal_i2c_handle_power);
- if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) != BQ27220_ERROR &&
- bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status) !=
- BQ27220_ERROR) {
+ if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) &&
+ bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status)) {
property_value_out(&property_context, "%lu", 2, "charger", "ntc", ntc_mpct);
property_value_out(&property_context, "%d", 2, "gauge", "calmd", operation_status.CALMD);
property_value_out(&property_context, "%d", 2, "gauge", "sec", operation_status.SEC);
diff --git a/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h b/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h
deleted file mode 100644
index 5eb0f938b..000000000
--- a/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h
+++ /dev/null
@@ -1,37 +0,0 @@
-const ParamCEDV cedv = {
- .cedv_conf.gauge_conf =
- {
- .CCT = 1,
- .CSYNC = 0,
- .EDV_CMP = 0,
- .SC = 1,
- .FIXED_EDV0 = 1,
- .FCC_LIM = 1,
- .FC_FOR_VDQ = 1,
- .IGNORE_SD = 1,
- .SME0 = 0,
- },
- .full_charge_cap = 2101,
- .design_cap = 2101,
- .EDV0 = 3300,
- .EDV1 = 3321,
- .EDV2 = 3355,
- .EMF = 3679,
- .C0 = 430,
- .C1 = 0,
- .R1 = 408,
- .R0 = 334,
- .T0 = 4626,
- .TC = 11,
- .DOD0 = 4044,
- .DOD10 = 3905,
- .DOD20 = 3807,
- .DOD30 = 3718,
- .DOD40 = 3642,
- .DOD50 = 3585,
- .DOD60 = 3546,
- .DOD70 = 3514,
- .DOD80 = 3477,
- .DOD90 = 3411,
- .DOD100 = 3299,
-};
diff --git a/firmware/targets/f7/furi_hal/furi_hal_power_config.c b/firmware/targets/f7/furi_hal/furi_hal_power_config.c
new file mode 100644
index 000000000..488edce91
--- /dev/null
+++ b/firmware/targets/f7/furi_hal/furi_hal_power_config.c
@@ -0,0 +1,149 @@
+#include
+
+const BQ27220DMGaugingConfig furi_hal_power_gauge_data_memory_gauging_config = {
+ .CCT = 1,
+ .CSYNC = 0,
+ .EDV_CMP = 0,
+ .SC = 1,
+ .FIXED_EDV0 = 1,
+ .FCC_LIM = 1,
+ .FC_FOR_VDQ = 1,
+ .IGNORE_SD = 1,
+ .SME0 = 0,
+};
+
+const BQ27220DMData furi_hal_power_gauge_data_memory[] = {
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1GaugingConfig,
+ .type = BQ27220DMTypePtr16,
+ .value.u32 = (uint32_t)&furi_hal_power_gauge_data_memory_gauging_config,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1FullChargeCapacity,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 2100,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1DesignCapacity,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 2100,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1EMF,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3679,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1C0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 430,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1R0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 334,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1T0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 4626,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1R1,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 408,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1TC,
+ .type = BQ27220DMTypeU8,
+ .value.u8 = 11,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1C1,
+ .type = BQ27220DMTypeU8,
+ .value.u8 = 0,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 4044,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD10,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3905,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD20,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3807,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD30,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3718,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD40,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3642,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD50,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3585,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD60,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3546,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD70,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3514,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD80,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3477,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD90,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3411,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD100,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3299,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV0,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3300,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV1,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3321,
+ },
+ {
+ .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV2,
+ .type = BQ27220DMTypeU16,
+ .value.u16 = 3355,
+ },
+ {
+ .address = BQ27220DMAddressCalibrationCurrentDeadband,
+ .type = BQ27220DMTypeU8,
+ .value.u8 = 1,
+ },
+ {
+ .address = BQ27220DMAddressConfigurationPowerSleepCurrent,
+ .type = BQ27220DMTypeI16,
+ .value.i16 = 1,
+ },
+ {
+ .type = BQ27220DMTypeEnd,
+ },
+};
diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi.c b/firmware/targets/f7/furi_hal/furi_hal_spi.c
index 42b854799..17769832b 100644
--- a/firmware/targets/f7/furi_hal/furi_hal_spi.c
+++ b/firmware/targets/f7/furi_hal/furi_hal_spi.c
@@ -12,10 +12,10 @@
#define TAG "FuriHalSpi"
#define SPI_DMA DMA2
-#define SPI_DMA_RX_CHANNEL LL_DMA_CHANNEL_3
-#define SPI_DMA_TX_CHANNEL LL_DMA_CHANNEL_4
-#define SPI_DMA_RX_IRQ FuriHalInterruptIdDma2Ch3
-#define SPI_DMA_TX_IRQ FuriHalInterruptIdDma2Ch4
+#define SPI_DMA_RX_CHANNEL LL_DMA_CHANNEL_6
+#define SPI_DMA_TX_CHANNEL LL_DMA_CHANNEL_7
+#define SPI_DMA_RX_IRQ FuriHalInterruptIdDma2Ch6
+#define SPI_DMA_TX_IRQ FuriHalInterruptIdDma2Ch7
#define SPI_DMA_RX_DEF SPI_DMA, SPI_DMA_RX_CHANNEL
#define SPI_DMA_TX_DEF SPI_DMA, SPI_DMA_TX_CHANNEL
@@ -170,18 +170,18 @@ bool furi_hal_spi_bus_trx(
}
static void spi_dma_isr() {
-#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3
- if(LL_DMA_IsActiveFlag_TC3(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_RX_DEF)) {
- LL_DMA_ClearFlag_TC3(SPI_DMA);
+#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_6
+ if(LL_DMA_IsActiveFlag_TC6(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_RX_DEF)) {
+ LL_DMA_ClearFlag_TC6(SPI_DMA);
furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk);
}
#else
#error Update this code. Would you kindly?
#endif
-#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4
- if(LL_DMA_IsActiveFlag_TC4(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_TX_DEF)) {
- LL_DMA_ClearFlag_TC4(SPI_DMA);
+#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_7
+ if(LL_DMA_IsActiveFlag_TC7(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_TX_DEF)) {
+ LL_DMA_ClearFlag_TC7(SPI_DMA);
furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk);
}
#else
@@ -241,8 +241,8 @@ bool furi_hal_spi_bus_trx_dma(
dma_config.Priority = LL_DMA_PRIORITY_MEDIUM;
LL_DMA_Init(SPI_DMA_TX_DEF, &dma_config);
-#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4
- LL_DMA_ClearFlag_TC4(SPI_DMA);
+#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_7
+ LL_DMA_ClearFlag_TC7(SPI_DMA);
#else
#error Update this code. Would you kindly?
#endif
@@ -315,8 +315,8 @@ bool furi_hal_spi_bus_trx_dma(
dma_config.Priority = LL_DMA_PRIORITY_MEDIUM;
LL_DMA_Init(SPI_DMA_RX_DEF, &dma_config);
-#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3
- LL_DMA_ClearFlag_TC3(SPI_DMA);
+#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_6
+ LL_DMA_ClearFlag_TC6(SPI_DMA);
#else
#error Update this code. Would you kindly?
#endif
diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h
index 6b4b6cd89..5edda6ba1 100644
--- a/firmware/targets/furi_hal_include/furi_hal_power.h
+++ b/firmware/targets/furi_hal_include/furi_hal_power.h
@@ -34,6 +34,12 @@ void furi_hal_power_init();
*/
bool furi_hal_power_gauge_is_ok();
+/** Check if gauge requests system shutdown
+ *
+ * @return true if system shutdown requested
+ */
+bool furi_hal_power_is_shutdown_requested();
+
/** Get current insomnia level
*
* @return insomnia level: 0 - no insomnia, >0 - insomnia, bearer count.
diff --git a/furi/core/memmgr_heap.c b/furi/core/memmgr_heap.c
index ca206cd39..3b4fdafa0 100644
--- a/furi/core/memmgr_heap.c
+++ b/furi/core/memmgr_heap.c
@@ -481,7 +481,7 @@ void* pvPortMalloc(size_t xWantedSize) {
configASSERT((((size_t)pvReturn) & (size_t)portBYTE_ALIGNMENT_MASK) == 0);
- furi_check(pvReturn);
+ furi_check(pvReturn, "out of memory");
pvReturn = memset(pvReturn, 0, to_wipe);
return pvReturn;
}
diff --git a/furi/core/thread.c b/furi/core/thread.c
index 2b27a81f4..62ab6fec4 100644
--- a/furi/core/thread.c
+++ b/furi/core/thread.c
@@ -1,5 +1,6 @@
#include "thread.h"
#include "thread_i.h"
+#include "timer.h"
#include "kernel.h"
#include "memmgr.h"
#include "memmgr_heap.h"
@@ -9,6 +10,7 @@
#include "string.h"
#include
+#include
#include "log.h"
#include
#include
@@ -511,6 +513,11 @@ const char* furi_thread_get_appid(FuriThreadId thread_id) {
FuriThread* thread = (FuriThread*)pvTaskGetThreadLocalStoragePointer(hTask, 0);
if(thread) {
appid = thread->appid;
+ } else if(hTask == xTimerGetTimerDaemonTaskHandle()) {
+ const char* timer = furi_timer_get_current_name();
+ if(timer) {
+ appid = timer;
+ }
}
}
diff --git a/furi/core/timer.c b/furi/core/timer.c
index 7743ffe70..d1fdc4456 100644
--- a/furi/core/timer.c
+++ b/furi/core/timer.c
@@ -1,4 +1,5 @@
#include "timer.h"
+#include "thread.h"
#include "check.h"
#include "memmgr.h"
#include "kernel.h"
@@ -6,11 +7,17 @@
#include
#include
+const char* current_timer_name = NULL;
+
typedef struct {
FuriTimerCallback func;
void* context;
} TimerCallback_t;
+const char* furi_timer_get_current_name() {
+ return current_timer_name;
+}
+
static void TimerCallback(TimerHandle_t hTimer) {
TimerCallback_t* callb;
@@ -21,7 +28,9 @@ static void TimerCallback(TimerHandle_t hTimer) {
callb = (TimerCallback_t*)((uint32_t)callb & ~1U);
if(callb != NULL) {
+ current_timer_name = pcTimerGetName(hTimer);
callb->func(callb->context);
+ current_timer_name = NULL;
}
}
@@ -47,11 +56,14 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co
reload = pdTRUE;
}
+ // Timer name so thread appid works in timers, and so does APP_DATA_PATH()
+ const char* name = furi_thread_get_appid(furi_thread_get_current_id());
+
/* Store callback memory dynamic allocation flag */
callb = (TimerCallback_t*)((uint32_t)callb | 1U);
// TimerCallback function is always provided as a callback and is used to call application
// specified function with its context both stored in structure callb.
- hTimer = xTimerCreate(NULL, 1, reload, callb, TimerCallback);
+ hTimer = xTimerCreate(name, 1, reload, callb, TimerCallback);
furi_check(hTimer);
/* Return timer ID */
@@ -133,4 +145,4 @@ void furi_timer_pending_callback(FuriTimerPendigCallback callback, void* context
ret = xTimerPendFunctionCall(callback, context, arg, FuriWaitForever);
}
furi_check(ret == pdPASS);
-}
\ No newline at end of file
+}
diff --git a/furi/core/timer.h b/furi/core/timer.h
index 3f43de5fd..6c9c6fd2a 100644
--- a/furi/core/timer.h
+++ b/furi/core/timer.h
@@ -60,6 +60,12 @@ typedef void (*FuriTimerPendigCallback)(void* context, uint32_t arg);
void furi_timer_pending_callback(FuriTimerPendigCallback callback, void* context, uint32_t arg);
+/** Get currently executing timer name
+ *
+ * @return The pointer to the timer name, or NULL
+ */
+const char* furi_timer_get_current_name();
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/drivers/SConscript b/lib/drivers/SConscript
index 7cbd42b37..5040569b4 100644
--- a/lib/drivers/SConscript
+++ b/lib/drivers/SConscript
@@ -6,6 +6,7 @@ env.Append(
],
SDK_HEADERS=[
File("rgb_backlight.h"),
+ File("cc1101_regs.h"),
],
)
diff --git a/lib/drivers/bq25896.c b/lib/drivers/bq25896.c
index f675233bd..76aae5e82 100644
--- a/lib/drivers/bq25896.c
+++ b/lib/drivers/bq25896.c
@@ -35,13 +35,15 @@ typedef struct {
static bq25896_regs_t bq25896_regs;
-void bq25896_init(FuriHalI2cBusHandle* handle) {
+bool bq25896_init(FuriHalI2cBusHandle* handle) {
+ bool result = true;
+
bq25896_regs.r14.REG_RST = 1;
- furi_hal_i2c_write_reg_8(
+ result &= furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x14, *(uint8_t*)&bq25896_regs.r14, BQ25896_I2C_TIMEOUT);
// Readout all registers
- furi_hal_i2c_read_mem(
+ result &= furi_hal_i2c_read_mem(
handle,
BQ25896_ADDRESS,
0x00,
@@ -52,26 +54,28 @@ void bq25896_init(FuriHalI2cBusHandle* handle) {
// Poll ADC forever
bq25896_regs.r02.CONV_START = 1;
bq25896_regs.r02.CONV_RATE = 1;
- furi_hal_i2c_write_reg_8(
+ result &= furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x02, *(uint8_t*)&bq25896_regs.r02, BQ25896_I2C_TIMEOUT);
bq25896_regs.r07.WATCHDOG = WatchdogDisable;
- furi_hal_i2c_write_reg_8(
+ result &= furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x07, *(uint8_t*)&bq25896_regs.r07, BQ25896_I2C_TIMEOUT);
// OTG power configuration
bq25896_regs.r0A.BOOSTV = 0x8; // BOOST Voltage: 5.062V
bq25896_regs.r0A.BOOST_LIM = BoostLim_1400; // BOOST Current limit: 1.4A
- furi_hal_i2c_write_reg_8(
+ result &= furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x0A, *(uint8_t*)&bq25896_regs.r0A, BQ25896_I2C_TIMEOUT);
- furi_hal_i2c_read_mem(
+ result &= furi_hal_i2c_read_mem(
handle,
BQ25896_ADDRESS,
0x00,
(uint8_t*)&bq25896_regs,
sizeof(bq25896_regs),
BQ25896_I2C_TIMEOUT);
+
+ return result;
}
void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim) {
diff --git a/lib/drivers/bq25896.h b/lib/drivers/bq25896.h
index ce7293960..d35625ab3 100644
--- a/lib/drivers/bq25896.h
+++ b/lib/drivers/bq25896.h
@@ -7,7 +7,7 @@
#include
/** Initialize Driver */
-void bq25896_init(FuriHalI2cBusHandle* handle);
+bool bq25896_init(FuriHalI2cBusHandle* handle);
/** Set boost lim*/
void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim);
diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c
index f64120fa8..92dbfcd6a 100644
--- a/lib/drivers/bq27220.c
+++ b/lib/drivers/bq27220.c
@@ -1,12 +1,16 @@
+
#include "bq27220.h"
#include "bq27220_reg.h"
+#include "bq27220_data_memory.h"
+
+_Static_assert(sizeof(BQ27220DMGaugingConfig) == 2, "Incorrect structure size");
#include
#include
#define TAG "Gauge"
-uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) {
+static uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) {
uint16_t buf = 0;
furi_hal_i2c_read_mem(
@@ -15,14 +19,14 @@ uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) {
return buf;
}
-bool bq27220_control(FuriHalI2cBusHandle* handle, uint16_t control) {
+static bool bq27220_control(FuriHalI2cBusHandle* handle, uint16_t control) {
bool ret = furi_hal_i2c_write_mem(
handle, BQ27220_ADDRESS, CommandControl, (uint8_t*)&control, 2, BQ27220_I2C_TIMEOUT);
return ret;
}
-uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) {
+static uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) {
uint8_t ret = 0;
for(uint16_t i = 0; i < len; i++) {
ret += data[i];
@@ -30,80 +34,181 @@ uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) {
return 0xFF - ret;
}
-bool bq27220_set_parameter_u16(FuriHalI2cBusHandle* handle, uint16_t address, uint16_t value) {
- bool ret;
- uint8_t buffer[4];
+static bool bq27220_parameter_check(
+ FuriHalI2cBusHandle* handle,
+ uint16_t address,
+ uint32_t value,
+ size_t size,
+ bool update) {
+ furi_assert(size == 1 || size == 2 || size == 4);
+ bool ret = false;
+ uint8_t buffer[6] = {0};
+ uint8_t old_data[4] = {0};
- buffer[0] = address & 0xFF;
- buffer[1] = (address >> 8) & 0xFF;
- buffer[2] = (value >> 8) & 0xFF;
- buffer[3] = value & 0xFF;
- ret = furi_hal_i2c_write_mem(
- handle, BQ27220_ADDRESS, CommandSelectSubclass, buffer, 4, BQ27220_I2C_TIMEOUT);
+ do {
+ buffer[0] = address & 0xFF;
+ buffer[1] = (address >> 8) & 0xFF;
- furi_delay_us(10000);
+ for(size_t i = 0; i < size; i++) {
+ buffer[1 + size - i] = (value >> (i * 8)) & 0xFF;
+ }
- uint8_t checksum = bq27220_get_checksum(buffer, 4);
- buffer[0] = checksum;
- buffer[1] = 6;
- ret &= furi_hal_i2c_write_mem(
- handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT);
+ if(update) {
+ if(!furi_hal_i2c_write_mem(
+ handle,
+ BQ27220_ADDRESS,
+ CommandSelectSubclass,
+ buffer,
+ size + 2,
+ BQ27220_I2C_TIMEOUT)) {
+ FURI_LOG_I(TAG, "DM write failed");
+ break;
+ }
+
+ furi_delay_us(10000);
+
+ uint8_t checksum = bq27220_get_checksum(buffer, size + 2);
+ buffer[0] = checksum;
+ buffer[1] = 4 + size; // TODO: why 4?
+ if(!furi_hal_i2c_write_mem(
+ handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT)) {
+ FURI_LOG_I(TAG, "CRC write failed");
+ break;
+ }
+
+ furi_delay_us(10000);
+ ret = true;
+ } else {
+ if(!furi_hal_i2c_write_mem(
+ handle, BQ27220_ADDRESS, CommandSelectSubclass, buffer, 2, BQ27220_I2C_TIMEOUT)) {
+ FURI_LOG_I(TAG, "DM SelectSubclass for read failed");
+ break;
+ }
+
+ if(!furi_hal_i2c_rx(handle, BQ27220_ADDRESS, old_data, size, BQ27220_I2C_TIMEOUT)) {
+ FURI_LOG_I(TAG, "DM read failed");
+ break;
+ }
+
+ if(*(uint32_t*)&(old_data[0]) != *(uint32_t*)&(buffer[2])) {
+ FURI_LOG_W( //-V641
+ TAG,
+ "Data at 0x%04x(%zu): 0x%08lx!=0x%08lx",
+ address,
+ size,
+ *(uint32_t*)&(old_data[0]),
+ *(uint32_t*)&(buffer[2]));
+ } else {
+ ret = true;
+ }
+ }
+ } while(0);
- furi_delay_us(10000);
return ret;
}
-bool bq27220_init(FuriHalI2cBusHandle* handle, const ParamCEDV* cedv) {
- uint32_t timeout = 100;
- uint16_t design_cap = bq27220_get_design_capacity(handle);
- if(cedv->design_cap == design_cap) {
- FURI_LOG_I(TAG, "Skip battery profile update");
- return true;
+static bool bq27220_data_memory_check(
+ FuriHalI2cBusHandle* handle,
+ const BQ27220DMData* data_memory,
+ bool update) {
+ if(update) {
+ if(!bq27220_control(handle, Control_ENTER_CFG_UPDATE)) {
+ FURI_LOG_E(TAG, "ENTER_CFG_UPDATE command failed");
+ return false;
+ };
+
+ // Wait for enter CFG update mode
+ uint32_t timeout = 100;
+ OperationStatus status = {0};
+ while((status.CFGUPDATE != true) && (timeout-- > 0)) {
+ bq27220_get_operation_status(handle, &status);
+ }
+
+ if(timeout == 0) {
+ FURI_LOG_E(TAG, "CFGUPDATE mode failed");
+ return false;
+ }
}
- FURI_LOG_I(TAG, "Start updating battery profile");
- OperationStatus status = {0};
- if(!bq27220_control(handle, Control_ENTER_CFG_UPDATE)) {
- FURI_LOG_E(TAG, "Can't configure update");
+
+ // Process data memory records
+ bool result = true;
+ while(data_memory->type != BQ27220DMTypeEnd) {
+ if(data_memory->type == BQ27220DMTypeWait) {
+ furi_delay_us(data_memory->value.u32);
+ } else if(data_memory->type == BQ27220DMTypeU8) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, data_memory->value.u8, 1, update);
+ } else if(data_memory->type == BQ27220DMTypeU16) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, data_memory->value.u16, 2, update);
+ } else if(data_memory->type == BQ27220DMTypeU32) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, data_memory->value.u32, 4, update);
+ } else if(data_memory->type == BQ27220DMTypeI8) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, data_memory->value.i8, 1, update);
+ } else if(data_memory->type == BQ27220DMTypeI16) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, data_memory->value.i16, 2, update);
+ } else if(data_memory->type == BQ27220DMTypeI32) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, data_memory->value.i32, 4, update);
+ } else if(data_memory->type == BQ27220DMTypeF32) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, data_memory->value.u32, 4, update);
+ } else if(data_memory->type == BQ27220DMTypePtr8) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, *(uint8_t*)data_memory->value.u32, 1, update);
+ } else if(data_memory->type == BQ27220DMTypePtr16) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, *(uint16_t*)data_memory->value.u32, 2, update);
+ } else if(data_memory->type == BQ27220DMTypePtr32) {
+ result &= bq27220_parameter_check(
+ handle, data_memory->address, *(uint32_t*)data_memory->value.u32, 4, update);
+ } else {
+ furi_crash("Invalid DM Type");
+ }
+ data_memory++;
+ }
+
+ // Finalize configuration update
+ if(update) {
+ bq27220_control(handle, Control_EXIT_CFG_UPDATE_REINIT);
+ furi_delay_us(10000);
+ }
+
+ return result;
+}
+
+bool bq27220_init(FuriHalI2cBusHandle* handle) {
+ // Request device number(chip PN)
+ if(!bq27220_control(handle, Control_DEVICE_NUMBER)) {
+ FURI_LOG_E(TAG, "Device is not present");
+ return false;
+ };
+ // Check control response
+ uint16_t data = 0;
+ data = bq27220_read_word(handle, CommandControl);
+ if(data != 0xFF00) {
+ FURI_LOG_E(TAG, "Invalid control response: %x", data);
return false;
};
- while((status.CFGUPDATE != true) && (timeout-- > 0)) {
- bq27220_get_operation_status(handle, &status);
- }
- bq27220_set_parameter_u16(handle, AddressGaugingConfig, cedv->cedv_conf.gauge_conf_raw);
- bq27220_set_parameter_u16(handle, AddressFullChargeCapacity, cedv->full_charge_cap);
- bq27220_set_parameter_u16(handle, AddressDesignCapacity, cedv->design_cap);
- bq27220_set_parameter_u16(handle, AddressEMF, cedv->EMF);
- bq27220_set_parameter_u16(handle, AddressC0, cedv->C0);
- bq27220_set_parameter_u16(handle, AddressR0, cedv->R0);
- bq27220_set_parameter_u16(handle, AddressT0, cedv->T0);
- bq27220_set_parameter_u16(handle, AddressR1, cedv->R1);
- bq27220_set_parameter_u16(handle, AddressTC, (cedv->TC) << 8 | cedv->C1);
- bq27220_set_parameter_u16(handle, AddressStartDOD0, cedv->DOD0);
- bq27220_set_parameter_u16(handle, AddressStartDOD10, cedv->DOD10);
- bq27220_set_parameter_u16(handle, AddressStartDOD20, cedv->DOD20);
- bq27220_set_parameter_u16(handle, AddressStartDOD30, cedv->DOD30);
- bq27220_set_parameter_u16(handle, AddressStartDOD40, cedv->DOD40);
- bq27220_set_parameter_u16(handle, AddressStartDOD50, cedv->DOD40);
- bq27220_set_parameter_u16(handle, AddressStartDOD60, cedv->DOD60);
- bq27220_set_parameter_u16(handle, AddressStartDOD70, cedv->DOD70);
- bq27220_set_parameter_u16(handle, AddressStartDOD80, cedv->DOD80);
- bq27220_set_parameter_u16(handle, AddressStartDOD90, cedv->DOD90);
- bq27220_set_parameter_u16(handle, AddressStartDOD100, cedv->DOD100);
- bq27220_set_parameter_u16(handle, AddressEDV0, cedv->EDV0);
- bq27220_set_parameter_u16(handle, AddressEDV1, cedv->EDV1);
- bq27220_set_parameter_u16(handle, AddressEDV2, cedv->EDV2);
+ data = bq27220_read_word(handle, CommandMACData);
+ FURI_LOG_I(TAG, "Device Number %04x", data);
- bq27220_control(handle, Control_EXIT_CFG_UPDATE_REINIT);
- furi_delay_us(10000);
- design_cap = bq27220_get_design_capacity(handle);
- if(cedv->design_cap == design_cap) {
- FURI_LOG_I(TAG, "Battery profile update success");
- return true;
- } else {
- FURI_LOG_E(TAG, "Battery profile update failed");
- return false;
+ return data == 0x0220;
+}
+
+bool bq27220_apply_data_memory(FuriHalI2cBusHandle* handle, const BQ27220DMData* data_memory) {
+ FURI_LOG_I(TAG, "Verifying data memory");
+ if(!bq27220_data_memory_check(handle, data_memory, false)) {
+ FURI_LOG_I(TAG, "Updating data memory");
+ bq27220_data_memory_check(handle, data_memory, true);
}
+ FURI_LOG_I(TAG, "Data memory verification complete");
+
+ return true;
}
uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle) {
@@ -114,24 +219,23 @@ int16_t bq27220_get_current(FuriHalI2cBusHandle* handle) {
return bq27220_read_word(handle, CommandCurrent);
}
-uint8_t bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status) {
+bool bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status) {
uint16_t data = bq27220_read_word(handle, CommandBatteryStatus);
if(data == BQ27220_ERROR) {
- return BQ27220_ERROR;
+ return false;
} else {
*(uint16_t*)battery_status = data;
- return BQ27220_SUCCESS;
+ return true;
}
}
-uint8_t
- bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status) {
+bool bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status) {
uint16_t data = bq27220_read_word(handle, CommandOperationStatus);
if(data == BQ27220_ERROR) {
- return BQ27220_ERROR;
+ return false;
} else {
*(uint16_t*)operation_status = data;
- return BQ27220_SUCCESS;
+ return true;
}
}
diff --git a/lib/drivers/bq27220.h b/lib/drivers/bq27220.h
index c822301a4..ca9e0312e 100644
--- a/lib/drivers/bq27220.h
+++ b/lib/drivers/bq27220.h
@@ -47,60 +47,17 @@ typedef struct {
_Static_assert(sizeof(OperationStatus) == 2, "Incorrect structure size");
-typedef struct {
- // Low byte, Low bit first
- bool CCT : 1;
- bool CSYNC : 1;
- bool RSVD0 : 1;
- bool EDV_CMP : 1;
- bool SC : 1;
- bool FIXED_EDV0 : 1;
- uint8_t RSVD1 : 2;
- // High byte, Low bit first
- bool FCC_LIM : 1;
- bool RSVD2 : 1;
- bool FC_FOR_VDQ : 1;
- bool IGNORE_SD : 1;
- bool SME0 : 1;
- uint8_t RSVD3 : 3;
-} GaugingConfig;
-
-_Static_assert(sizeof(GaugingConfig) == 2, "Incorrect structure size");
-
-typedef struct {
- union {
- GaugingConfig gauge_conf;
- uint16_t gauge_conf_raw;
- } cedv_conf;
- uint16_t full_charge_cap;
- uint16_t design_cap;
- uint16_t EDV0;
- uint16_t EDV1;
- uint16_t EDV2;
- uint16_t EMF;
- uint16_t C0;
- uint16_t R0;
- uint16_t T0;
- uint16_t R1;
- uint8_t TC;
- uint8_t C1;
- uint16_t DOD0;
- uint16_t DOD10;
- uint16_t DOD20;
- uint16_t DOD30;
- uint16_t DOD40;
- uint16_t DOD50;
- uint16_t DOD60;
- uint16_t DOD70;
- uint16_t DOD80;
- uint16_t DOD90;
- uint16_t DOD100;
-} ParamCEDV;
+typedef struct BQ27220DMData BQ27220DMData;
/** Initialize Driver
* @return true on success, false otherwise
*/
-bool bq27220_init(FuriHalI2cBusHandle* handle, const ParamCEDV* cedv);
+bool bq27220_init(FuriHalI2cBusHandle* handle);
+
+/** Initialize Driver
+ * @return true on success, false otherwise
+ */
+bool bq27220_apply_data_memory(FuriHalI2cBusHandle* handle, const BQ27220DMData* data_memory);
/** Get battery voltage in mV or error */
uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle);
@@ -109,11 +66,10 @@ uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle);
int16_t bq27220_get_current(FuriHalI2cBusHandle* handle);
/** Get battery status */
-uint8_t bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status);
+bool bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status);
/** Get operation status */
-uint8_t
- bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status);
+bool bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status);
/** Get temperature in units of 0.1°K */
uint16_t bq27220_get_temperature(FuriHalI2cBusHandle* handle);
diff --git a/lib/drivers/bq27220_data_memory.h b/lib/drivers/bq27220_data_memory.h
new file mode 100644
index 000000000..ae00be883
--- /dev/null
+++ b/lib/drivers/bq27220_data_memory.h
@@ -0,0 +1,84 @@
+#pragma once
+
+#include
+#include
+
+typedef enum {
+ BQ27220DMTypeEnd,
+ BQ27220DMTypeWait,
+ BQ27220DMTypeU8,
+ BQ27220DMTypeU16,
+ BQ27220DMTypeU32,
+ BQ27220DMTypeI8,
+ BQ27220DMTypeI16,
+ BQ27220DMTypeI32,
+ BQ27220DMTypeF32,
+ BQ27220DMTypePtr8,
+ BQ27220DMTypePtr16,
+ BQ27220DMTypePtr32,
+} BQ27220DMType;
+
+typedef enum {
+ BQ27220DMAddressGasGaugingCEDVProfile1GaugingConfig = 0x929B,
+ BQ27220DMAddressGasGaugingCEDVProfile1FullChargeCapacity = 0x929D,
+ BQ27220DMAddressGasGaugingCEDVProfile1DesignCapacity = 0x929F,
+ BQ27220DMAddressGasGaugingCEDVProfile1EMF = 0x92A3,
+ BQ27220DMAddressGasGaugingCEDVProfile1C0 = 0x92A9,
+ BQ27220DMAddressGasGaugingCEDVProfile1R0 = 0x92AB,
+ BQ27220DMAddressGasGaugingCEDVProfile1T0 = 0x92AD,
+ BQ27220DMAddressGasGaugingCEDVProfile1R1 = 0x92AF,
+ BQ27220DMAddressGasGaugingCEDVProfile1TC = 0x92B1,
+ BQ27220DMAddressGasGaugingCEDVProfile1C1 = 0x92B2,
+ BQ27220DMAddressGasGaugingCEDVProfile1EDV0 = 0x92B4,
+ BQ27220DMAddressGasGaugingCEDVProfile1EDV1 = 0x92B7,
+ BQ27220DMAddressGasGaugingCEDVProfile1EDV2 = 0x92BA,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD0 = 0x92BD,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD10 = 0x92BF,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD20 = 0x92C1,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD30 = 0x92C3,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD40 = 0x92C5,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD50 = 0x92C7,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD60 = 0x92C9,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD70 = 0x92CB,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD80 = 0x92CD,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD90 = 0x92CF,
+ BQ27220DMAddressGasGaugingCEDVProfile1StartDOD100 = 0x92D1,
+ BQ27220DMAddressCalibrationCurrentDeadband = 0x91DE,
+ BQ27220DMAddressConfigurationPowerSleepCurrent = 0x9217,
+ BQ27220DMAddressConfigurationCurrentThresholdsDischargeDetectionThreshold = 0x9228,
+ BQ27220DMAddressConfigurationDataInitialStandby = 0x923C,
+} BQ27220DMAddress;
+
+typedef struct BQ27220DMData BQ27220DMData;
+
+struct BQ27220DMData {
+ uint16_t type;
+ uint16_t address;
+ union {
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ int8_t i8;
+ int16_t i16;
+ int32_t i32;
+ float f32;
+ } value;
+};
+
+typedef struct {
+ // Low byte, Low bit first
+ const bool CCT : 1;
+ const bool CSYNC : 1;
+ const bool RSVD0 : 1;
+ const bool EDV_CMP : 1;
+ const bool SC : 1;
+ const bool FIXED_EDV0 : 1;
+ const uint8_t RSVD1 : 2;
+ // High byte, Low bit first
+ const bool FCC_LIM : 1;
+ const bool RSVD2 : 1;
+ const bool FC_FOR_VDQ : 1;
+ const bool IGNORE_SD : 1;
+ const bool SME0 : 1;
+ const uint8_t RSVD3 : 3;
+} BQ27220DMGaugingConfig;
diff --git a/lib/drivers/bq27220_reg.h b/lib/drivers/bq27220_reg.h
index fa81b66eb..2e6e54aab 100644
--- a/lib/drivers/bq27220_reg.h
+++ b/lib/drivers/bq27220_reg.h
@@ -66,28 +66,3 @@
#define Control_EXIT_CFG_UPDATE_REINIT 0x0091
#define Control_EXIT_CFG_UPDATE 0x0092
#define Control_RETURN_TO_ROM 0x0F00
-
-#define AddressGaugingConfig 0x929B
-#define AddressFullChargeCapacity 0x929D
-#define AddressDesignCapacity 0x929F
-#define AddressEMF 0x92A3
-#define AddressC0 0x92A9
-#define AddressR0 0x92AB
-#define AddressT0 0x92AD
-#define AddressR1 0x92AF
-#define AddressTC 0x92B1
-#define AddressC1 0x92B2
-#define AddressEDV0 0x92B4
-#define AddressEDV1 0x92B7
-#define AddressEDV2 0x92BA
-#define AddressStartDOD0 0x92BD
-#define AddressStartDOD10 0x92BF
-#define AddressStartDOD20 0x92C1
-#define AddressStartDOD30 0x92C3
-#define AddressStartDOD40 0x92C5
-#define AddressStartDOD50 0x92C7
-#define AddressStartDOD60 0x92C9
-#define AddressStartDOD70 0x92CB
-#define AddressStartDOD80 0x92CD
-#define AddressStartDOD90 0x92CF
-#define AddressStartDOD100 0x92D1
diff --git a/lib/flipper_application/application_assets.c b/lib/flipper_application/application_assets.c
index 1262870d5..083c3ca19 100644
--- a/lib/flipper_application/application_assets.c
+++ b/lib/flipper_application/application_assets.c
@@ -157,14 +157,6 @@ static bool flipper_application_assets_process_dirs(
FuriString* full_path = flipper_application_assets_alloc_app_full_path(app_name);
do {
- if(!storage_simply_mkdir(storage, APPS_ASSETS_PATH)) {
- break;
- }
-
- if(!storage_simply_mkdir(storage, furi_string_get_cstr(full_path))) {
- break;
- }
-
FuriString* dir_path = furi_string_alloc();
char* path = NULL;
@@ -279,6 +271,8 @@ bool flipper_application_assets_load(File* file, const char* elf_path, size_t of
FURI_LOG_D(TAG, "Loading assets for %s", furi_string_get_cstr(app_name));
+ FuriString* full_path = flipper_application_assets_alloc_app_full_path(app_name);
+
do {
if(!storage_file_seek(file, offset, true)) {
break;
@@ -319,13 +313,23 @@ bool flipper_application_assets_load(File* file, const char* elf_path, size_t of
FURI_LOG_D(TAG, "Assets removed");
}
+ if(!storage_simply_mkdir(storage, APPS_ASSETS_PATH)) {
+ break;
+ }
+
+ if(!storage_simply_mkdir(storage, furi_string_get_cstr(full_path))) {
+ break;
+ }
+
// process directories
- if(!flipper_application_assets_process_dirs(storage, file, app_name, header.dirs_count)) {
+ if(header.dirs_count &&
+ !flipper_application_assets_process_dirs(storage, file, app_name, header.dirs_count)) {
break;
}
// process files
- if(!flipper_application_assets_process_files(storage, file, app_name, header.files_count)) {
+ if(header.files_count && !flipper_application_assets_process_files(
+ storage, file, app_name, header.files_count)) {
break;
}
@@ -353,6 +357,7 @@ bool flipper_application_assets_load(File* file, const char* elf_path, size_t of
}
furi_record_close(RECORD_STORAGE);
+ furi_string_free(full_path);
furi_string_free(app_name);
FURI_LOG_D(TAG, "Assets loading %s", result ? "success" : "failed");
diff --git a/lib/nfc/helpers/nfc_generators.c b/lib/nfc/helpers/nfc_generators.c
index 90bfbec9d..50c89aba8 100644
--- a/lib/nfc/helpers/nfc_generators.c
+++ b/lib/nfc/helpers/nfc_generators.c
@@ -83,9 +83,9 @@ static void nfc_generate_mf_ul_common(NfcDeviceData* data) {
data->nfc_data.interface = FuriHalNfcInterfaceRf;
data->nfc_data.uid_len = 7;
nfc_generate_mf_ul_uid(data->nfc_data.uid);
- data->nfc_data.a_data.atqa[0] = 0x44;
- data->nfc_data.a_data.atqa[1] = 0x00;
- data->nfc_data.a_data.sak = 0x00;
+ data->nfc_data.atqa[0] = 0x44;
+ data->nfc_data.atqa[1] = 0x00;
+ data->nfc_data.sak = 0x00;
data->protocol = NfcDeviceProtocolMifareUl;
}
@@ -94,15 +94,9 @@ static void
data->nfc_data.type = FuriHalNfcTypeA;
data->nfc_data.interface = FuriHalNfcInterfaceRf;
data->nfc_data.uid_len = uid_len;
- data->nfc_data.a_data.atqa[0] = 0x44;
- data->nfc_data.a_data.atqa[1] = 0x00;
- data->nfc_data.a_data.sak = 0x08;
- nfc_generate_mf_classic_block_0(
- data->mf_classic_data.block[0].value,
- uid_len,
- data->nfc_data.a_data.sak,
- data->nfc_data.a_data.atqa[0],
- data->nfc_data.a_data.atqa[1]);
+ data->nfc_data.atqa[0] = 0x44;
+ data->nfc_data.atqa[1] = 0x00;
+ data->nfc_data.sak = 0x08;
data->protocol = NfcDeviceProtocolMifareClassic;
data->mf_classic_data.type = type;
}
@@ -256,9 +250,9 @@ static void
mful->data_size = num_pages * 4;
mful->data_read = mful->data_size;
memcpy(mful->data, data->nfc_data.uid, data->nfc_data.uid_len);
- mful->data[7] = data->nfc_data.a_data.sak;
- mful->data[8] = data->nfc_data.a_data.atqa[0];
- mful->data[9] = data->nfc_data.a_data.atqa[1];
+ mful->data[7] = data->nfc_data.sak;
+ mful->data[8] = data->nfc_data.atqa[0];
+ mful->data[9] = data->nfc_data.atqa[1];
uint16_t config_register_page;
uint16_t session_register_page;
@@ -364,7 +358,7 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
}
// Set SAK to 18
- data->nfc_data.a_data.sak = 0x18;
+ data->nfc_data.sak = 0x18;
} else if(type == MfClassicType1k) {
// Set every block to 0xFF
for(uint16_t i = 1; i < MF_CLASSIC_1K_TOTAL_SECTORS_NUM * 4; i += 1) {
@@ -376,7 +370,7 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
}
// Set SAK to 08
- data->nfc_data.a_data.sak = 0x08;
+ data->nfc_data.sak = 0x08;
} else if(type == MfClassicTypeMini) {
// Set every block to 0xFF
for(uint16_t i = 1; i < MF_MINI_TOTAL_SECTORS_NUM * 4; i += 1) {
@@ -388,15 +382,15 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
}
// Set SAK to 09
- data->nfc_data.a_data.sak = 0x09;
+ data->nfc_data.sak = 0x09;
}
nfc_generate_mf_classic_block_0(
data->mf_classic_data.block[0].value,
uid_len,
- data->nfc_data.a_data.sak,
- data->nfc_data.a_data.atqa[0],
- data->nfc_data.a_data.atqa[1]);
+ data->nfc_data.sak,
+ data->nfc_data.atqa[0],
+ data->nfc_data.atqa[1]);
mfc->type = type;
}
diff --git a/lib/nfc/helpers/reader_analyzer.c b/lib/nfc/helpers/reader_analyzer.c
index c8f9c2c7e..e01e60d49 100644
--- a/lib/nfc/helpers/reader_analyzer.c
+++ b/lib/nfc/helpers/reader_analyzer.c
@@ -56,11 +56,13 @@ struct ReaderAnalyzer {
static FuriHalNfcDevData reader_analyzer_nfc_data[] = {
[ReaderAnalyzerNfcDataMfClassic] =
- {.interface = FuriHalNfcInterfaceRf,
+ {.sak = 0x08,
+ .atqa = {0x44, 0x00},
+ .interface = FuriHalNfcInterfaceRf,
.type = FuriHalNfcTypeA,
.uid_len = READER_ANALYZER_UID_SIZE,
.uid = {0x04, 0x77, 0x70, 0x2A, 0x23, 0x4F, 0x80},
- .a_data = {.sak = 0x08, .atqa = {0x44, 0x00}, .cuid = 0x2A234F80}},
+ .cuid = 0x2A234F80},
};
void reader_analyzer_parse(ReaderAnalyzer* instance, uint8_t* buffer, size_t size) {
@@ -122,7 +124,7 @@ ReaderAnalyzer* reader_analyzer_alloc() {
reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic].uid,
Uid.full_uid,
READER_ANALYZER_UID_SIZE);
- reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic].a_data.cuid =
+ reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic].cuid =
nfc_util_bytes2num(Uid.uid_converter.cuid, READER_ANALYZER_CUID_SIZE);
instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic];
@@ -156,7 +158,7 @@ void reader_analyzer_start(ReaderAnalyzer* instance, ReaderAnalyzerMode mode) {
instance->debug_log = nfc_debug_log_alloc();
}
if(mode & ReaderAnalyzerModeMfkey) {
- instance->mfkey32 = mfkey32_alloc(instance->nfc_data.a_data.cuid);
+ instance->mfkey32 = mfkey32_alloc(instance->nfc_data.cuid);
if(instance->mfkey32) {
mfkey32_set_callback(instance->mfkey32, reader_analyzer_mfkey_callback, instance);
}
diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c
index 38bb767cd..cd9eb336c 100644
--- a/lib/nfc/nfc_device.c
+++ b/lib/nfc/nfc_device.c
@@ -20,7 +20,6 @@ static const uint32_t nfc_keys_file_version = 1;
// Protocols format versions
static const uint32_t nfc_mifare_classic_data_format_version = 2;
static const uint32_t nfc_mifare_ultralight_data_format_version = 1;
-static const uint32_t nfc_felica_data_format_version = 1;
NfcDevice* nfc_device_alloc() {
NfcDevice* nfc_dev = malloc(sizeof(NfcDevice));
@@ -61,8 +60,6 @@ static void nfc_device_prepare_format_string(NfcDevice* dev, FuriString* format_
furi_string_set(format_string, "Mifare DESFire");
} else if(dev->format == NfcDeviceSaveFormatNfcV) {
furi_string_set(format_string, "ISO15693");
- } else if(dev->format == NfcDeviceSaveFormatFelica) {
- furi_string_set(format_string, "FeliCa");
} else {
furi_string_set(format_string, "Unknown");
}
@@ -1129,211 +1126,6 @@ static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice*
return saved;
}
-static bool nfc_device_save_felica_lite(FlipperFormat* file, FelicaLiteInfo* info) {
- bool saved = false;
- FuriString* key = furi_string_alloc();
- FuriString* temp = furi_string_alloc();
-
- do {
- flipper_format_write_comment_cstr(file, "Lite(-S) System");
- flipper_format_write_hex(
- file, "Data Format Code", (uint8_t*)&info->data_format_code, sizeof(uint16_t));
- flipper_format_write_hex(file, "ID Arbitrary Value", info->ID_value, 6);
- flipper_format_write_hex(file, "Memory Config", info->memory_config, FELICA_BLOCK_SIZE);
-
- for(uint8_t block_num = 0; block_num < 14; block_num++) {
- furi_string_reset(temp);
- for(size_t i = 0; i < FELICA_BLOCK_SIZE; i++) {
- if(info->S_PAD[block_num] != NULL) {
- furi_string_cat_printf(temp, "%02X ", info->S_PAD[block_num][i]);
- } else {
- furi_string_cat_printf(temp, "?? ");
- }
- }
-
- furi_string_printf(key, "S_PAD%d", block_num);
- flipper_format_write_string(file, furi_string_get_cstr(key), temp);
- }
-
- furi_string_reset(temp);
- for(size_t i = 0; i < FELICA_BLOCK_SIZE; i++) {
- if(info->REG != NULL) {
- furi_string_cat_printf(temp, "%02X ", info->REG[i]);
- } else {
- furi_string_cat_printf(temp, "?? ");
- }
- }
- flipper_format_write_string(file, "REG", temp);
-
- flipper_format_write_hex(
- file, "Card Key Version", (uint8_t*)&info->card_key_version, sizeof(uint16_t));
- furi_string_reset(temp);
- for(size_t i = 0; i < FELICA_BLOCK_SIZE; i++) {
- if(info->REG != NULL) {
- furi_string_cat_printf(temp, "%02X ", info->card_key_1[i]);
- } else {
- furi_string_cat_printf(temp, "?? ");
- }
- }
- flipper_format_write_string(file, "Card Key 1", temp);
-
- furi_string_reset(temp);
- for(size_t i = 0; i < FELICA_BLOCK_SIZE; i++) {
- if(info->REG != NULL) {
- furi_string_cat_printf(temp, "%02X ", info->card_key_2[i]);
- } else {
- furi_string_cat_printf(temp, "?? ");
- }
- }
- flipper_format_write_string(file, "Card Key 2", temp);
-
- flipper_format_write_hex(file, "Fixed Challenge MAC Response", info->MAC, 8);
-
- flipper_format_write_bool(file, "Is Lite-S", &info->is_lite_s, 1);
- if(info->is_lite_s) {
- flipper_format_write_hex(file, "Fixed Challenge MAC-A Response", info->MAC_A, 8);
- flipper_format_write_uint32(file, "Write Count", &info->write_count, 1);
- }
-
- } while(false);
-
- furi_string_free(temp);
- furi_string_free(key);
- return saved;
-}
-
-static bool nfc_device_save_felica_node(FlipperFormat* file, FelicaNode* node);
-
-static bool nfc_device_save_felica_area(FlipperFormat* file, FelicaArea* area) {
- bool saved = false;
- FuriString* prefix = furi_string_alloc_printf("Area %d", area->number);
- FuriString* key = furi_string_alloc();
-
- do {
- furi_string_printf(key, "%s Can Create Subareas", furi_string_get_cstr(prefix));
- flipper_format_write_bool(file, furi_string_get_cstr(key), &area->can_create_subareas, 1);
- furi_string_printf(key, "%s End Service Code", furi_string_get_cstr(prefix));
- flipper_format_write_hex(
- file, furi_string_get_cstr(key), (uint8_t*)&area->end_service_code, sizeof(uint16_t));
-
- bool node_saved = true;
- for
- M_EACH(node, area->nodes, FelicaNodeArray_t) {
- if(nfc_device_save_felica_node(file, node)) {
- node_saved = false;
- break;
- }
- }
-
- if(!node_saved) break;
- saved = true;
- } while(false);
-
- furi_string_free(prefix);
- furi_string_free(key);
- return saved;
-}
-
-static bool nfc_device_save_felica_service(FlipperFormat* file, FelicaService* service) {
- bool saved = false;
- FuriString* prefix = furi_string_alloc_printf("Service %d", service->number);
- FuriString* key = furi_string_alloc();
-
- do {
- furi_string_printf(key, "%s Is Extended Overlap", furi_string_get_cstr(prefix));
- flipper_format_write_bool(
- file, furi_string_get_cstr(key), &service->is_extended_overlap, 1);
- if(service->is_extended_overlap) {
- furi_string_printf(key, "%s Overlap Target", furi_string_get_cstr(prefix));
- flipper_format_write_hex(
- file,
- furi_string_get_cstr(key),
- (uint8_t*)&service->overlap_target,
- sizeof(uint16_t));
-
- furi_string_printf(key, "%s Block Start", furi_string_get_cstr(prefix));
- const uint32_t block_start = service->block_start;
- flipper_format_write_uint32(file, furi_string_get_cstr(key), &block_start, 1);
-
- furi_string_printf(key, "%s Block Count", furi_string_get_cstr(prefix));
- const uint32_t block_count = service->block_count;
- flipper_format_write_uint32(file, furi_string_get_cstr(key), &block_count, 1);
-
- uint32_t i = 0;
- for
- M_EACH(block, service->blocks, FelicaBlockArray_t) {
- furi_string_printf(key, "%s Block %ld", furi_string_get_cstr(prefix), i);
- flipper_format_write_hex(
- file, furi_string_get_cstr(key), block->data, FELICA_BLOCK_SIZE);
- }
- } else {
- furi_string_printf(key, "%s Block Count", furi_string_get_cstr(prefix));
- uint32_t block_count = FelicaBlockArray_size(service->blocks);
- flipper_format_write_uint32(file, furi_string_get_cstr(key), &block_count, 1);
- uint32_t i = 0;
- for
- M_EACH(block, service->blocks, FelicaBlockArray_t) {
- furi_string_printf(key, "%s Block %ld", furi_string_get_cstr(prefix), i);
- flipper_format_write_hex(
- file, furi_string_get_cstr(key), block->data, FELICA_BLOCK_SIZE);
- }
- }
-
- saved = true;
- } while(false);
-
- furi_string_free(prefix);
- furi_string_free(key);
- return saved;
-}
-
-static bool nfc_device_save_felica_node(FlipperFormat* file, FelicaNode* node) {
- bool saved = false;
-
- do {
- if(node->type == FelicaNodeTypeArea) {
- if(!nfc_device_save_felica_area(file, node->area)) {
- saved = false;
- break;
- }
- } else if(node->type == FelicaNodeTypeService) {
- if(!nfc_device_save_felica_service(file, node->service)) {
- saved = false;
- break;
- }
- }
-
- saved = true;
- } while(false);
-
- return saved;
-}
-
-static bool nfc_device_save_felica_data(FlipperFormat* file, NfcDevice* dev) {
- bool saved = false;
- FelicaData* data = &dev->dev_data.felica_data;
- // Save FeliCa specific data
- do {
- if(!flipper_format_write_comment_cstr(file, "FeliCa specific data")) break;
- if(!flipper_format_write_uint32(
- file, "Data format version", &nfc_felica_data_format_version, 1))
- break;
-
- for
- M_EACH(system, data->systems, FelicaSystemArray_t) {
- flipper_format_write_hex(file, "System", &system->number, sizeof(uint8_t));
- flipper_format_write_hex(file, "Code", (uint8_t*)&system->code, sizeof(uint16_t));
- if(system->code == LITE_SYSTEM_CODE) {
- nfc_device_save_felica_lite(file, &system->lite_info);
- } else {
- nfc_device_save_felica_node(file, &system->root);
- }
- }
- } while(false);
-
- return saved;
-}
-
static void nfc_device_load_mifare_classic_block(
FuriString* block_str,
MfClassicData* data,
@@ -1622,43 +1414,39 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break;
// Write nfc device type
if(!flipper_format_write_comment_cstr(
- file,
- "Nfc device type can be UID, Mifare Ultralight, Mifare Classic, FeliCa or ISO15693"))
+ file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic or ISO15693"))
break;
nfc_device_prepare_format_string(dev, temp_str);
if(!flipper_format_write_string(file, "Device type", temp_str)) break;
- if(data->type == FuriHalNfcTypeA) {
- if(!flipper_format_write_comment_cstr(file, "UID is common for all formats")) break;
- if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break;
+ // Write UID
+ if(!flipper_format_write_comment_cstr(file, "UID is common for all formats")) break;
+ if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break;
- if(dev->format != NfcDeviceSaveFormatNfcV) {
- // Write ATQA, SAK
- if(!flipper_format_write_comment_cstr(file, "ISO14443 specific fields")) break;
- // Save ATQA in MSB order for correct companion apps display
- uint8_t atqa[2] = {data->a_data.atqa[1], data->a_data.atqa[0]};
- if(!flipper_format_write_hex(file, "ATQA", atqa, 2)) break;
- if(!flipper_format_write_hex(file, "SAK", &data->a_data.sak, 1)) break;
- }
-
- // Save more data if necessary
- if(dev->format == NfcDeviceSaveFormatMifareUl) {
- if(!nfc_device_save_mifare_ul_data(file, dev)) break;
- } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
- if(!nfc_device_save_mifare_df_data(file, dev)) break;
- } else if(dev->format == NfcDeviceSaveFormatNfcV) {
- if(!nfc_device_save_nfcv_data(file, dev)) break;
- } else if(dev->format == NfcDeviceSaveFormatBankCard) {
- if(!nfc_device_save_bank_card_data(file, dev)) break;
- } else if(dev->format == NfcDeviceSaveFormatMifareClassic) {
- // Save data
- if(!nfc_device_save_mifare_classic_data(file, dev)) break;
- // Save keys cache
- if(!nfc_device_save_mifare_classic_keys(dev)) break;
- }
- saved = true;
- } else if(data->type == FuriHalNfcTypeF) {
- if(!nfc_device_save_felica_data(file, dev)) break;
+ if(dev->format != NfcDeviceSaveFormatNfcV) {
+ // Write ATQA, SAK
+ if(!flipper_format_write_comment_cstr(file, "ISO14443 specific fields")) break;
+ // Save ATQA in MSB order for correct companion apps display
+ uint8_t atqa[2] = {data->atqa[1], data->atqa[0]};
+ if(!flipper_format_write_hex(file, "ATQA", atqa, 2)) break;
+ if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break;
}
+
+ // Save more data if necessary
+ if(dev->format == NfcDeviceSaveFormatMifareUl) {
+ if(!nfc_device_save_mifare_ul_data(file, dev)) break;
+ } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
+ if(!nfc_device_save_mifare_df_data(file, dev)) break;
+ } else if(dev->format == NfcDeviceSaveFormatNfcV) {
+ if(!nfc_device_save_nfcv_data(file, dev)) break;
+ } else if(dev->format == NfcDeviceSaveFormatBankCard) {
+ if(!nfc_device_save_bank_card_data(file, dev)) break;
+ } else if(dev->format == NfcDeviceSaveFormatMifareClassic) {
+ // Save data
+ if(!nfc_device_save_mifare_classic_data(file, dev)) break;
+ // Save keys cache
+ if(!nfc_device_save_mifare_classic_keys(dev)) break;
+ }
+ saved = true;
} while(0);
if(!saved) { //-V547
@@ -1731,22 +1519,22 @@ static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dia
if(!flipper_format_read_hex(file, "UID", data->uid, data->uid_len)) break;
if(dev->format != NfcDeviceSaveFormatNfcV) {
if(version == version_with_lsb_atqa) {
- if(!flipper_format_read_hex(file, "ATQA", data->a_data.atqa, 2)) break;
+ if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break;
} else {
uint8_t atqa[2] = {};
if(!flipper_format_read_hex(file, "ATQA", atqa, 2)) break;
- data->a_data.atqa[0] = atqa[1];
- data->a_data.atqa[1] = atqa[0];
+ data->atqa[0] = atqa[1];
+ data->atqa[1] = atqa[0];
}
- if(!flipper_format_read_hex(file, "SAK", &data->a_data.sak, 1)) break;
+ if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break;
}
// Load CUID
uint8_t* cuid_start = data->uid;
if(data->uid_len == 7) {
cuid_start = &data->uid[3];
}
- data->a_data.cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) |
- (cuid_start[3]);
+ data->cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) |
+ (cuid_start[3]);
// Parse other data
if(dev->format == NfcDeviceSaveFormatMifareUl) {
if(!nfc_device_load_mifare_ul_data(file, dev)) break;
@@ -1842,8 +1630,6 @@ void nfc_device_data_clear(NfcDeviceData* dev_data) {
mf_ul_reset(&dev_data->mf_ul_data);
} else if(dev_data->protocol == NfcDeviceProtocolEMV) {
memset(&dev_data->emv_data, 0, sizeof(EmvData));
- } else if(dev_data->protocol == NfcDeviceProtocolFelica) {
- felica_clear(&dev_data->felica_data);
}
memset(&dev_data->nfc_data, 0, sizeof(FuriHalNfcDevData));
dev_data->protocol = NfcDeviceProtocolUnknown;
diff --git a/lib/nfc/nfc_device.h b/lib/nfc/nfc_device.h
index 793f733e4..6617171e7 100644
--- a/lib/nfc/nfc_device.h
+++ b/lib/nfc/nfc_device.h
@@ -12,8 +12,6 @@
#include
#include
#include
-#include
-#include
#ifdef __cplusplus
extern "C" {
@@ -35,7 +33,6 @@ typedef enum {
NfcDeviceProtocolMifareClassic,
NfcDeviceProtocolMifareDesfire,
NfcDeviceProtocolNfcV,
- NfcDeviceProtocolFelica,
} NfcProtocol;
typedef enum {
@@ -45,7 +42,6 @@ typedef enum {
NfcDeviceSaveFormatMifareClassic,
NfcDeviceSaveFormatMifareDesfire,
NfcDeviceSaveFormatNfcV,
- NfcDeviceSaveFormatFelica,
} NfcDeviceSaveFormat;
typedef struct {
@@ -65,8 +61,6 @@ typedef enum {
NfcReadModeMfDesfire,
NfcReadModeEMV,
NfcReadModeNFCA,
- NfcReadModeFelica,
- NfcReadModeNFCF,
} NfcReadMode;
typedef struct {
@@ -84,7 +78,6 @@ typedef struct {
MfClassicData mf_classic_data;
MifareDesfireData mf_df_data;
NfcVData nfcv_data;
- FelicaData felica_data;
};
FuriString* parsed_data;
} NfcDeviceData;
diff --git a/lib/nfc/nfc_types.c b/lib/nfc/nfc_types.c
index de44f4703..96b92640f 100644
--- a/lib/nfc/nfc_types.c
+++ b/lib/nfc/nfc_types.c
@@ -67,63 +67,3 @@ const char* nfc_mf_classic_type(MfClassicType type) {
return "Mifare Classic";
}
}
-
-const char* nfc_felica_type(FelicaICType type) {
- if(type == FelicaICType576B) {
- return "FeliCa Classic 576B";
- } else if(type == FelicaICType2K) {
- return "FeliCa Classic 2K";
- } else if(type == FelicaICType4K) {
- return "FeliCa Classic 4K";
- } else if(type == FelicaICTypeFRAM_4K) {
- return "FeliCa Classic 4K (FRAM)";
- } else if(type == FelicaICTypeFRAM_9K) {
- return "FeliCa Classic 9K";
- } else if(type == FelicaICTypeEMV_16K) {
- return "FeliCa Classic EMV 16K";
- } else if(type == FelicaICTypeEMV_32K) {
- return "FeliCa Classic EMV 32K";
- } else if(type == FelicaICTypeEMV_36K) {
- return "FeliCa Classic EMV 36K";
- } else if(type == FelicaICTypeEMV_36K) {
- return "FeliCa Classic EMV 36K";
- } else if(type == FelicaICTypeSD1WithDES) {
- return "FeliCa SD1 (DES compatible)";
- } else if(type == FelicaICTypeSD1) {
- return "FeliCa SD1";
- } else if(type == FelicaICTypeRC_SA08) {
- return "FeliCa RC-SA08";
- } else if(type == FelicaICTypeSD2WithDES) {
- return "FeliCa SD2 (DES compatible)";
- } else if(type == FelicaICTypeSD2_4K) {
- return "FeliCa SD2 4K";
- } else if(type == FelicaICTypeSD2_6K) {
- return "FeliCa SD2 6K";
- } else if(type == FelicaICTypeRC_SA24_6K) {
- return "FeliCa RC-SA24 6K";
- } else if(type == FelicaICTypeRC_SA24_10K) {
- return "FeliCa RC-SA24 6K";
- } else if(type == FelicaICTypeMobileIC_V1) {
- return "Mobile FeliCa v1";
- } else if(type == FelicaICTypeMobileIC_V2) {
- return "Mobile FeliCa v2";
- } else if(type == FelicaICTypeMobileIC_V3) {
- return "Mobile FeliCa v3";
- } else if(type == FelicaICTypeMobileIC_V4) {
- return "Mobile FeliCa v4";
- } else if(type == FelicaICTypeMobileIC_V4_1) {
- return "Mobile FeliCa v4.1";
- } else if(type == FelicaICTypeLite) {
- return "FeliCa Lite";
- } else if(type == FelicaICTypeLiteS) {
- return "FeliCa Lite-S";
- } else if(type == FelicaICTypeLink) {
- return "FeliCa Link";
- } else if(type == FelicaICTypePlug) {
- return "FeliCa Plug";
- } else if(type == FelicaICTypeSuica) {
- return "FeliCa (SuiCa)";
- } else {
- return "FeliCa";
- }
-}
diff --git a/lib/nfc/nfc_types.h b/lib/nfc/nfc_types.h
index 206d99fde..19dc15759 100644
--- a/lib/nfc/nfc_types.h
+++ b/lib/nfc/nfc_types.h
@@ -14,7 +14,6 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name);
const char* nfc_mf_classic_type(MfClassicType type);
-const char* nfc_felica_type(FelicaICType type);
#ifdef __cplusplus
}
#endif
diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c
index bc97d743d..77be3fb0d 100644
--- a/lib/nfc/nfc_worker.c
+++ b/lib/nfc/nfc_worker.c
@@ -545,20 +545,20 @@ static bool nfc_worker_read_bank_card(NfcWorker* nfc_worker, FuriHalNfcTxRxConte
static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
- FuriHalNfcADevData* a_data = &nfc_data->a_data;
bool card_read = false;
furi_hal_nfc_sleep();
- if(mf_ul_check_card_type(a_data)) {
+ if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
FURI_LOG_I(TAG, "Mifare Ultralight / NTAG detected");
nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl;
card_read = nfc_worker_read_mf_ultralight(nfc_worker, tx_rx);
- } else if(mf_classic_check_card_type(a_data)) {
+ } else if(mf_classic_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
FURI_LOG_I(TAG, "Mifare Classic detected");
nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic;
- nfc_worker->dev_data->mf_classic_data.type = mf_classic_get_classic_type(a_data);
+ nfc_worker->dev_data->mf_classic_data.type =
+ mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
card_read = nfc_worker_read_mf_classic(nfc_worker, tx_rx);
- } else if(mf_df_check_card_type(a_data)) {
+ } else if(mf_df_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
FURI_LOG_I(TAG, "Mifare DESFire detected");
nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareDesfire;
if(!nfc_worker_read_mf_desfire(nfc_worker, tx_rx)) {
@@ -582,46 +582,6 @@ static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* t
return card_read;
}
-static bool nfc_worker_read_felica(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
- bool read_success = false;
- FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
- FelicaData* data = &nfc_worker->dev_data->felica_data;
-
- if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
- reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, tx_rx, false);
- reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog);
- }
-
- do {
- if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 300)) break;
- if(!felica_read_card(tx_rx, data, nfc_data->uid, nfc_data->f_data.pmm)) break;
- read_success = true;
- } while(false);
-
- if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
- reader_analyzer_stop(nfc_worker->reader_analyzer);
- }
-
- return read_success;
-}
-
-static bool nfc_worker_read_nfcf(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
- FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
- FuriHalNfcFDevData* f_data = &nfc_data->f_data;
-
- bool card_read = false;
- furi_hal_nfc_sleep();
- if(felica_check_ic_type(f_data->pmm)) {
- FURI_LOG_I(TAG, "FeliCa detected");
- nfc_worker->dev_data->protocol = NfcDeviceProtocolFelica;
- nfc_worker->dev_data->felica_data.type = felica_get_ic_type(f_data->pmm);
- card_read = nfc_worker_read_felica(nfc_worker, tx_rx);
- } else {
- nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
- }
- return card_read;
-}
-
void nfc_worker_read(NfcWorker* nfc_worker) {
furi_assert(nfc_worker);
furi_assert(nfc_worker->callback);
@@ -666,11 +626,6 @@ void nfc_worker_read(NfcWorker* nfc_worker) {
event = NfcWorkerEventReadUidNfcB;
break;
} else if(nfc_data->type == FuriHalNfcTypeF) {
- nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
- if(nfc_worker_read_nfcf(nfc_worker, &tx_rx)) {
- event = NfcWorkerEventReadFelica;
- break;
- }
event = NfcWorkerEventReadUidNfcF;
break;
} else if(nfc_data->type == FuriHalNfcTypeV) {
@@ -719,8 +674,8 @@ void nfc_worker_read_type(NfcWorker* nfc_worker) {
if(nfc_data->type == FuriHalNfcTypeA) {
if(read_mode == NfcReadModeMfClassic) {
nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic;
- nfc_worker->dev_data->mf_classic_data.type =
- mf_classic_get_classic_type(&nfc_data->a_data);
+ nfc_worker->dev_data->mf_classic_data.type = mf_classic_get_classic_type(
+ nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
if(nfc_worker_read_mf_classic(nfc_worker, &tx_rx)) {
FURI_LOG_D(TAG, "Card read");
dev_data->protocol = NfcDeviceProtocolMifareClassic;
@@ -756,21 +711,6 @@ void nfc_worker_read_type(NfcWorker* nfc_worker) {
event = NfcWorkerEventReadUidNfcA;
break;
}
- } else if(nfc_data->type == FuriHalNfcTypeF) {
- if(read_mode == NfcReadModeFelica) {
- nfc_worker->dev_data->protocol = NfcDeviceProtocolFelica;
- if(nfc_worker_read_felica(nfc_worker, &tx_rx)) {
- nfc_worker->dev_data->protocol = NfcDeviceProtocolFelica;
- if(nfc_worker_read_felica(nfc_worker, &tx_rx)) {
- event = NfcWorkerEventReadFelica;
- break;
- }
- }
- } else if(read_mode == NfcReadModeNFCF) {
- nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
- event = NfcWorkerEventReadUidNfcF;
- break;
- }
}
} else {
if(!card_not_detected_notified) {
@@ -796,8 +736,7 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) {
// Need to save ATS to support ISO-14443A-4 emulation
while(nfc_worker->state == NfcWorkerStateUidEmulate) {
- if(furi_hal_nfc_listen(
- data->uid, data->uid_len, data->a_data.atqa, data->a_data.sak, false, 100)) {
+ if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) {
if(furi_hal_nfc_tx_rx(&tx_rx, 100)) {
reader_data->size = tx_rx.rx_bits / 8;
if(reader_data->size > 0) {
@@ -818,11 +757,8 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) {
FuriHalNfcDevData params = {
.uid = {0xCF, 0x72, 0xd4, 0x40},
.uid_len = 4,
- .a_data =
- {
- .atqa = {0x00, 0x04},
- .sak = 0x20,
- },
+ .atqa = {0x00, 0x04},
+ .sak = 0x20,
.type = FuriHalNfcTypeA,
};
@@ -832,8 +768,7 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) {
}
while(nfc_worker->state == NfcWorkerStateEmulateApdu) { //-V1044
- if(furi_hal_nfc_listen(
- params.uid, params.uid_len, params.a_data.atqa, params.a_data.sak, false, 300)) {
+ if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 300)) {
FURI_LOG_D(TAG, "POS terminal detected");
if(emv_card_emulation(&tx_rx)) {
FURI_LOG_D(TAG, "EMV card emulated");
@@ -876,8 +811,8 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) {
furi_hal_nfc_emulate_nfca(
nfc_data->uid,
nfc_data->uid_len,
- nfc_data->a_data.atqa,
- nfc_data->a_data.sak,
+ nfc_data->atqa,
+ nfc_data->sak,
mf_ul_prepare_emulation_response,
&emulator,
5000);
@@ -1209,7 +1144,8 @@ void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) {
}
FURI_LOG_I(TAG, "Check mf classic type");
- MfClassicType type = mf_classic_get_classic_type(&nfc_data.a_data);
+ MfClassicType type =
+ mf_classic_get_classic_type(nfc_data.atqa[0], nfc_data.atqa[1], nfc_data.sak);
if(type != nfc_worker->dev_data->mf_classic_data.type) {
FURI_LOG_E(TAG, "Wrong mf classic type");
nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context);
@@ -1281,7 +1217,8 @@ void nfc_worker_update_mf_classic(NfcWorker* nfc_worker) {
}
FURI_LOG_I(TAG, "Check MF classic type");
- MfClassicType type = mf_classic_get_classic_type(&nfc_data.a_data);
+ MfClassicType type =
+ mf_classic_get_classic_type(nfc_data.atqa[0], nfc_data.atqa[1], nfc_data.sak);
if(type != nfc_worker->dev_data->mf_classic_data.type) {
FURI_LOG_E(TAG, "MF classic type mismatch");
nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context);
@@ -1343,7 +1280,7 @@ void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker) {
while(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) {
furi_hal_nfc_sleep();
if(furi_hal_nfc_detect(nfc_data, 300) && nfc_data->type == FuriHalNfcTypeA) {
- if(mf_ul_check_card_type(&nfc_data->a_data)) {
+ if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
if(data->auth_method == MfUltralightAuthMethodManual ||
data->auth_method == MfUltralightAuthMethodAuto) {
diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h
index 3407a2d7c..ec740d15d 100644
--- a/lib/nfc/nfc_worker.h
+++ b/lib/nfc/nfc_worker.h
@@ -42,7 +42,6 @@ typedef enum {
NfcWorkerEventReadUidNfcV,
NfcWorkerEventReadUidNfcF,
NfcWorkerEventReadUidNfcA,
- NfcWorkerEventReadFelica,
NfcWorkerEventReadMfUltralight,
NfcWorkerEventReadMfDesfire,
NfcWorkerEventReadMfClassicDone,
diff --git a/lib/nfc/nfc_worker_i.h b/lib/nfc/nfc_worker_i.h
index eda42c313..d13d3c5c8 100644
--- a/lib/nfc/nfc_worker_i.h
+++ b/lib/nfc/nfc_worker_i.h
@@ -11,7 +11,6 @@
#include
#include
#include
-#include
#include
#include
#include
diff --git a/lib/nfc/parsers/plantain_4k_parser.c b/lib/nfc/parsers/plantain_4k_parser.c
index 3990461fc..19da0b5eb 100644
--- a/lib/nfc/parsers/plantain_4k_parser.c
+++ b/lib/nfc/parsers/plantain_4k_parser.c
@@ -70,8 +70,8 @@ bool plantain_4k_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx
furi_assert(nfc_worker);
MfClassicReader reader = {};
- FuriHalNfcADevData* nfc_a_data = &nfc_worker->dev_data->nfc_data.a_data;
- reader.type = mf_classic_get_classic_type(nfc_a_data);
+ FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
+ reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
for(size_t i = 0; i < COUNT_OF(plantain_keys_4k); i++) {
mf_classic_reader_add_sector(
&reader,
diff --git a/lib/nfc/parsers/plantain_parser.c b/lib/nfc/parsers/plantain_parser.c
index 758b038e8..2e4091dda 100644
--- a/lib/nfc/parsers/plantain_parser.c
+++ b/lib/nfc/parsers/plantain_parser.c
@@ -45,8 +45,8 @@ bool plantain_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
furi_assert(nfc_worker);
MfClassicReader reader = {};
- FuriHalNfcADevData* nfc_a_data = &nfc_worker->dev_data->nfc_data.a_data;
- reader.type = mf_classic_get_classic_type(nfc_a_data);
+ FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
+ reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
for(size_t i = 0; i < COUNT_OF(plantain_keys); i++) {
mf_classic_reader_add_sector(
&reader, plantain_keys[i].sector, plantain_keys[i].key_a, plantain_keys[i].key_b);
diff --git a/lib/nfc/parsers/troika_4k_parser.c b/lib/nfc/parsers/troika_4k_parser.c
index af4b4b3d1..d248feb17 100644
--- a/lib/nfc/parsers/troika_4k_parser.c
+++ b/lib/nfc/parsers/troika_4k_parser.c
@@ -67,8 +67,8 @@ bool troika_4k_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx)
furi_assert(nfc_worker);
MfClassicReader reader = {};
- FuriHalNfcADevData* nfc_a_data = &nfc_worker->dev_data->nfc_data.a_data;
- reader.type = mf_classic_get_classic_type(nfc_a_data);
+ FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
+ reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
for(size_t i = 0; i < COUNT_OF(troika_4k_keys); i++) {
mf_classic_reader_add_sector(
&reader, troika_4k_keys[i].sector, troika_4k_keys[i].key_a, troika_4k_keys[i].key_b);
diff --git a/lib/nfc/parsers/troika_parser.c b/lib/nfc/parsers/troika_parser.c
index 17de0d8a5..6d8ae98f3 100644
--- a/lib/nfc/parsers/troika_parser.c
+++ b/lib/nfc/parsers/troika_parser.c
@@ -43,8 +43,8 @@ bool troika_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
furi_assert(nfc_worker);
MfClassicReader reader = {};
- FuriHalNfcADevData* nfc_a_data = &nfc_worker->dev_data->nfc_data.a_data;
- reader.type = mf_classic_get_classic_type(nfc_a_data);
+ FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
+ reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
for(size_t i = 0; i < COUNT_OF(troika_keys); i++) {
mf_classic_reader_add_sector(
diff --git a/lib/nfc/parsers/two_cities.c b/lib/nfc/parsers/two_cities.c
index b6a8bc552..d6d4279dd 100644
--- a/lib/nfc/parsers/two_cities.c
+++ b/lib/nfc/parsers/two_cities.c
@@ -71,8 +71,8 @@ bool two_cities_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx)
furi_assert(nfc_worker);
MfClassicReader reader = {};
- FuriHalNfcADevData* nfc_a_data = &nfc_worker->dev_data->nfc_data.a_data;
- reader.type = mf_classic_get_classic_type(nfc_a_data);
+ FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
+ reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
for(size_t i = 0; i < COUNT_OF(two_cities_keys_4k); i++) {
mf_classic_reader_add_sector(
&reader,
diff --git a/lib/nfc/protocols/felica.c b/lib/nfc/protocols/felica.c
deleted file mode 100644
index 182893527..000000000
--- a/lib/nfc/protocols/felica.c
+++ /dev/null
@@ -1,943 +0,0 @@
-#include
-#include
-#include
-#include "felica.h"
-#include "nfc_util.h"
-#include
-#include "furi_hal_nfc.h"
-
-#define TAG "FeliCa"
-
-bool felica_check_ic_type(uint8_t* PMm) {
- uint8_t rom_type = PMm[0];
- uint8_t ic_type = PMm[1];
-
- bool is_valid_ic = false;
- if(ic_type == 0xff) { // RC-S967 in nfc-dep
- is_valid_ic = true;
- } else if(ic_type == 0xf2) { // RC-S732?
- is_valid_ic = true;
- } else if(ic_type == 0xf0 || ic_type == 0xf1) { // Lite(S)
- is_valid_ic = true;
- } else if(ic_type == 0xe1) { // RC-S967 in plug mode
- is_valid_ic = true;
- } else if(ic_type == 0xe0) { // RC-S926
- is_valid_ic = true;
- } else if(ic_type >= 0x44 && ic_type <= 0x48) { // SD2
- is_valid_ic = true;
- } else if(ic_type == 0x3e && rom_type == 0x03) { // RC-SA08
- return true;
- } else if(ic_type == 0x35) { // RC-SA01
- is_valid_ic = true;
- } else if(ic_type == 0x32) { // RC-SA00
- is_valid_ic = true;
- } else if(ic_type == 0x31) { // Suica/PASMO
- is_valid_ic = true;
- } else if(ic_type == 0x20) { // RC-S962
- is_valid_ic = true;
- } else if(ic_type >= 0x10 && ic_type <= 0x1f) { // Mobile IC version 2/3
- is_valid_ic = true;
- } else if(ic_type == 0x0d) { // RC-S960
- is_valid_ic = true;
- } else if(ic_type == 0x0c) { // RC-S954
- is_valid_ic = true;
- } else if(ic_type == 0x0b) { // Old Suica?
- is_valid_ic = true;
- } else if(ic_type == 0x09) { // RC-S953
- is_valid_ic = true;
- } else if(ic_type == 0x08) { // RC-S952
- is_valid_ic = true;
- } else if(ic_type == 0x06 || ic_type == 0x07) { // Mobile IC version 1
- is_valid_ic = true;
- } else if(ic_type == 0x02) { // RC-S919
- is_valid_ic = true;
- } else if(ic_type == 0x01) { // RC-S915
- is_valid_ic = true;
- } else if(ic_type == 0x00) { // RC-S830
- is_valid_ic = true;
- }
-
- if(!is_valid_ic) {
- return false;
- }
-
- // need more samples to confirm below
- /*
- if (rom_type != 0x01) {
- return false;
- }
- */
-
- return true;
-}
-
-FelicaICType felica_get_ic_type(uint8_t* PMm) {
- uint8_t rom_type = PMm[0];
- uint8_t ic_type = PMm[1];
-
- UNUSED(rom_type);
- switch(ic_type) {
- case 0xff:
- return FelicaICTypeLink;
- case 0xf2:
- return FelicaICTypeLink;
- case 0xf1:
- return FelicaICTypeLiteS;
- case 0xf0:
- return FelicaICTypeLite;
- case 0xe1:
- return FelicaICTypeLink;
- case 0xe0:
- return FelicaICTypePlug;
- case 0x48:
- return FelicaICTypeSD2_6K;
- case 0x47:
- return FelicaICTypeRC_SA24_6K;
- case 0x46:
- return FelicaICTypeSD2_4K;
- case 0x45:
- case 0x44:
- return FelicaICTypeSD2WithDES;
- case 0x3e:
- return FelicaICTypeRC_SA08;
- case 0x35:
- return FelicaICTypeSD1;
- case 0x32:
- return FelicaICTypeSD1WithDES;
- case 0x31:
- return FelicaICTypeSuica;
- case 0x20:
- return FelicaICTypeFRAM_4K;
- case 0x1f:
- case 0x1e:
- case 0x1d:
- case 0x1c:
- case 0x1b:
- case 0x1a:
- case 0x19:
- case 0x18:
- return FelicaICTypeMobileIC_V4_1;
- case 0x17:
- return FelicaICTypeMobileIC_V4;
- case 0x16:
- case 0x15:
- case 0x14:
- return FelicaICTypeMobileIC_V3;
- case 0x13:
- case 0x12:
- case 0x11:
- case 0x10:
- return FelicaICTypeMobileIC_V2;
- case 0x0d:
- return FelicaICTypeFRAM_9K;
- case 0x0c:
- return FelicaICTypeEMV_36K;
- case 0x0b: // Old Suica?
- return FelicaICTypeSuica;
- case 0x09:
- return FelicaICTypeEMV_16K;
- case 0x08:
- return FelicaICTypeEMV_32K;
- case 0x07:
- case 0x06:
- return FelicaICTypeMobileIC_V1;
- case 0x02:
- return FelicaICType576B;
- case 0x01:
- return FelicaICType4K;
- case 0x00:
- return FelicaICType2K;
- }
-
- return FelicaICType2K;
-}
-
-// static void felica_lite_diversify_key(uint8_t* id_block, uint8_t* master_key, uint8_t* card_key) {
-// uint8_t ZERO[8] = {0};
-// uint8_t L[8];
-// mbedtls_des3_context ctx;
-// mbedtls_des3_init(&ctx);
-// mbedtls_des3_set3key_enc(&ctx, master_key);
-// mbedtls_des3_crypt_ecb(&ctx, ZERO, L);
-// mbedtls_des3_free(&ctx);
-
-// uint8_t K1[8];
-// for(int i = 0; i < 8; i++) {
-// K1[i] = L[i] << 1;
-// if(i < 7) {
-// K1[i] |= (L[i + 1] >> 7);
-// }
-// }
-
-// if((L[0] ^ 0x80) == 0) {
-// K1[7] ^= 0x1B;
-// }
-
-// uint8_t M1[8];
-// uint8_t M2[8];
-// memcpy(M1, id_block, 8);
-// memcpy(M2, id_block + 8, 8);
-// for(int i = 0; i < 8; i++) {
-// M2[i] ^= K1[i];
-// }
-
-// uint8_t C1[8];
-// mbedtls_des3_init(&ctx);
-// mbedtls_des3_set3key_enc(&ctx, master_key);
-// mbedtls_des3_crypt_ecb(&ctx, M1, C1);
-// for(int i = 0; i < 8; i++) {
-// C1[i] ^= M2[i];
-// }
-
-// mbedtls_des3_crypt_ecb(&ctx, C1, card_key); // T
-
-// M1[0] ^= 0x80; // M'1
-// mbedtls_des3_crypt_ecb(&ctx, M1, C1); // C'1
-// for(int i = 0; i < 8; i++) {
-// C1[i] ^= M2[i];
-// }
-
-// mbedtls_des3_crypt_ecb(&ctx, C1, card_key + 8); // T'
-// mbedtls_des3_free(&ctx);
-// }
-
-// static void felica_lite_generate_session_key(
-// uint8_t* random_challenge,
-// uint8_t* card_key,
-// uint8_t* session_key) {
-// uint8_t RC1[8];
-// uint8_t RC2[8];
-// uint8_t CK[16];
-
-// for(int i = 0; i < 8; i++) {
-// RC1[i] = random_challenge[7 - i];
-// RC2[i] = random_challenge[i];
-// CK[i] = card_key[7 - i];
-// CK[i + 8] = card_key[15 - i];
-// }
-
-// mbedtls_des3_context ctx;
-
-// uint8_t SK1[8];
-// mbedtls_des3_init(&ctx);
-// mbedtls_des3_set2key_enc(&ctx, CK);
-// mbedtls_des3_crypt_ecb(&ctx, RC1, SK1);
-
-// uint8_t SK2[8];
-// for(int i = 0; i < 8; i++) {
-// RC2[i] ^= SK1[i];
-// }
-// mbedtls_des3_crypt_ecb(&ctx, RC2, SK2);
-// mbedtls_des3_free(&ctx);
-
-// for(int i = 0; i < 8; i++) {
-// session_key[i] = SK1[7 - i];
-// session_key[i + 8] = SK2[7 - i];
-// }
-// }
-
-// static void felica_lite_calculate_mac(
-// uint8_t* random_challenge,
-// uint8_t* session_key,
-// uint8_t* block_data,
-// size_t block_count,
-// uint8_t* MAC) {
-// uint8_t SK[16];
-
-// for(int i = 0; i < 8; i++) {
-// MAC[i] = random_challenge[7 - i];
-// SK[i] = session_key[7 - i];
-// SK[i + 8] = session_key[15 - i];
-// }
-
-// mbedtls_des3_context ctx;
-// mbedtls_des3_init(&ctx);
-// mbedtls_des3_set3key_enc(&ctx, SK);
-
-// for(size_t block_num = 0; block_num < block_count; block_num++) {
-// for(int i = 0; i < 8; i++) {
-// MAC[i] ^= block_data[block_num * FELICA_BLOCK_SIZE + 7 - i];
-// }
-
-// uint8_t intermediate[8];
-// mbedtls_des3_crypt_ecb(&ctx, MAC, intermediate);
-// for(int i = 0; i < 8; i++) {
-// intermediate[i] ^= block_data[block_num * FELICA_BLOCK_SIZE + 15 - i];
-// }
-
-// mbedtls_des3_crypt_ecb(&ctx, intermediate, MAC);
-// }
-
-// mbedtls_des3_free(&ctx);
-// }
-
-// static void felica_lite_calculate_mac_a(
-// uint8_t* random_challenge,
-// uint8_t* session_key,
-// uint8_t* iv,
-// uint8_t* block_data,
-// size_t block_count,
-// uint8_t* MAC_A) {
-// uint8_t SK[16];
-// uint8_t intermediate_a[8];
-// uint8_t intermediate_b[8];
-
-// for(int i = 0; i < 8; i++) {
-// intermediate_a[i] = iv[7 - 1] ^ random_challenge[7 - i];
-// SK[i] = session_key[7 - i];
-// SK[i + 8] = session_key[15 - i];
-// }
-
-// mbedtls_des3_context ctx;
-// mbedtls_des3_init(&ctx);
-// mbedtls_des3_set3key_enc(&ctx, SK);
-// mbedtls_des3_crypt_ecb(&ctx, intermediate_a, intermediate_b);
-
-// for(size_t block_num = 0; block_num < block_count; block_num++) {
-// for(int i = 0; i < 8; i++) {
-// intermediate_b[i] ^= block_data[block_num * FELICA_BLOCK_SIZE + 7 - i];
-// }
-
-// mbedtls_des3_crypt_ecb(&ctx, intermediate_b, intermediate_a);
-// for(int i = 0; i < 8; i++) {
-// intermediate_a[i] ^= block_data[block_num * FELICA_BLOCK_SIZE + 7 - i];
-// }
-
-// mbedtls_des3_crypt_ecb(&ctx, intermediate_a, intermediate_b);
-// }
-
-// for(int i = 0; i < 8; i++) {
-// MAC_A[i] = intermediate_b[7 - 1];
-// }
-// }
-
-// static void felica_lite_calculate_mac_a_for_write(
-// uint8_t* random_challenge,
-// uint8_t* session_key,
-// uint32_t write_count,
-// uint8_t block_number,
-// uint8_t* block_data,
-// uint8_t* MAC_A) {
-// uint8_t iv[8];
-// nfc_util_num2bytes(write_count, 3, iv);
-// iv[3] = 0x00;
-// iv[4] = block_number;
-// iv[5] = 0x00;
-// iv[6] = 0x91;
-// iv[7] = 0x00;
-
-// uint8_t SK[16];
-// for(int i = 0; i < 8; i++) {
-// SK[i] = session_key[i + 8];
-// SK[i + 8] = session_key[i];
-// }
-
-// felica_lite_calculate_mac_a(random_challenge, SK, iv, block_data, 1, MAC_A);
-// }
-
-// static void felica_lite_calculate_mac_a_for_read(
-// uint8_t* random_challenge,
-// uint8_t* session_key,
-// uint8_t* block_list,
-// uint8_t block_list_count,
-// uint8_t* block_data,
-// uint8_t block_count,
-// uint8_t* MAC_A) {
-// uint8_t iv[8] = {0};
-
-// uint8_t block_list_to_write = MIN(block_list_count, 4);
-// for(int i = 0; i < block_list_to_write; i++) {
-// iv[i * 2] = block_list[i];
-// }
-// if(block_list_to_write < 4) {
-// iv[6] = 0xFF;
-// iv[7] = 0xFF;
-// }
-// if(block_list_to_write < 3) {
-// iv[4] = 0xFF;
-// iv[5] = 0xFF;
-// }
-
-// felica_lite_calculate_mac_a(random_challenge, session_key, iv, block_data, block_count, MAC_A);
-// }
-
-/** Parse common FeliCa response headers.
- *
- * This parses and validates the most commonly occurring response header types.
- *
- * The header needs to match the (length, res, idm) format, and also (sf1, sf2) when always_succeed
- * is set to false.
- *
- * @param buf RX buffer.
- * @param len RX buffer length.
- * @param reader The FeliCa reader context.
- * @param expected_resp Expected response code. Must be an odd number.
- * @param always_succeed When set to true, skip status flags (sf1 and sf2) parsing.
- * @return The number of bytes parsed, or 0 when response is invalid or status flags are set.
- */
-static uint8_t felica_consume_unencrypted_header(
- uint8_t* buf,
- uint8_t len,
- FelicaReader* reader,
- uint8_t expected_resp,
- bool always_succeed) {
- furi_assert(expected_resp & 1);
- furi_assert(buf != NULL);
- furi_assert(reader != NULL);
-
- uint8_t header_size = always_succeed ? 10 : 12;
- if(len < header_size) {
- FURI_LOG_E(TAG, "Malformed header: too short.");
- return 0;
- }
- if(buf[1] != expected_resp) {
- FURI_LOG_E(TAG, "Expecting %u, got %u.", expected_resp, buf[1]);
- return 0;
- }
- if(memcmp(&buf[2], reader->current_idm, 8) != 0) {
- FURI_LOG_E(TAG, "IDm mismatch.");
- return 0;
- }
- if(always_succeed) {
- reader->status_flags[0] = buf[10];
- reader->status_flags[1] = buf[11];
- if(reader->status_flags[0] != 0 || reader->status_flags[1] != 0) {
- FURI_LOG_W(
- TAG, "SF1: %02X SF2: %02X", reader->status_flags[0], reader->status_flags[1]);
- return 0;
- }
- }
- return header_size;
-}
-
-uint8_t felica_prepare_unencrypted_read(
- uint8_t* dest,
- const FelicaReader* reader,
- const uint16_t* service_code_list,
- uint8_t service_count,
- const uint32_t* block_list,
- uint8_t block_count) {
- dest[0] = FELICA_UNENCRYPTED_READ_CMD;
- memcpy(&dest[1], reader->current_idm, 8);
-
- dest[9] = service_count;
- uint8_t msg_len = 10;
- for(int i = 0; i < service_count; i++) {
- uint16_t service_code = service_code_list[i];
- dest[msg_len++] = service_code & 0xFF;
- dest[msg_len++] = service_code >> 8;
- }
-
- dest[msg_len++] = block_count;
- for(int i = 0; i < block_count; i++) {
- uint16_t block_num = block_list[i];
- dest[msg_len++] = block_num & 0xFF;
- dest[msg_len++] = block_num >> 8;
- }
-
- return msg_len;
-}
-
-uint8_t felica_lite_prepare_unencrypted_read(
- uint8_t* dest,
- const FelicaReader* reader,
- bool is_read_only,
- const uint8_t* block_list,
- uint8_t block_count) {
- dest[0] = FELICA_UNENCRYPTED_READ_CMD;
- memcpy(&dest[1], reader->current_idm, 8);
-
- dest[9] = 1;
- uint8_t msg_len = 10;
- uint8_t service_code =
- FelicaServiceTypeRandom |
- ((is_read_only) ? FelicaServiceAttributeUnauthRO : FelicaServiceAttributeUnauthRO);
-
- dest[msg_len++] = service_code & 0xFF;
- dest[msg_len++] = service_code >> 8;
-
- dest[msg_len++] = block_count;
- for(int i = 0; i < block_count; i++) {
- dest[msg_len++] = IS_2_BYTE_BLOCK_LIST_ELEMENT;
- dest[msg_len++] = block_list[i];
- }
-
- return msg_len;
-}
-
-uint16_t felica_parse_unencrypted_read(
- uint8_t* buf,
- uint8_t len,
- FelicaReader* reader,
- uint8_t* out,
- uint16_t out_len) {
- uint8_t consumed =
- felica_consume_unencrypted_header(buf, len, reader, FELICA_UNENCRYPTED_READ_RES, false);
- if(!consumed) {
- return 0;
- }
- len -= consumed;
- buf += consumed;
-
- if(len < 1) {
- return 0;
- }
- uint16_t data_length = *buf * FELICA_BLOCK_SIZE;
- len--;
- buf++;
-
- if(len < data_length || out_len < data_length) {
- return 0;
- }
-
- memcpy(out, buf, data_length);
-
- return data_length;
-}
-
-uint8_t felica_prepare_unencrypted_write(
- uint8_t* dest,
- FelicaReader* reader,
- const uint16_t* service_code_list,
- uint8_t service_count,
- const uint32_t* block_list,
- uint8_t block_count,
- const uint8_t* block_data) {
- dest[0] = FELICA_UNENCRYPTED_WRITE_CMD;
- memcpy(&dest[1], reader->current_idm, 8);
-
- dest[9] = service_count;
- uint8_t msg_len = 10;
- for(int i = 0; i < service_count; i++) {
- uint16_t service_code = service_code_list[i];
- dest[msg_len++] = service_code & 0xFF;
- dest[msg_len++] = service_code >> 8;
- }
-
- dest[msg_len++] = block_count;
- for(int i = 0; i < block_count; i++) {
- uint16_t block_num = block_list[i];
- dest[msg_len++] = block_num & 0xFF;
- dest[msg_len++] = block_num >> 8;
- }
-
- uint16_t data_length = block_count * FELICA_BLOCK_SIZE;
- memcpy(dest + msg_len, block_data, data_length);
- msg_len += data_length;
- return msg_len;
-}
-
-uint8_t felica_lite_prepare_unencrypted_write(
- uint8_t* dest,
- const FelicaReader* reader,
- const uint8_t* block_list,
- uint8_t block_count,
- const uint8_t* block_data) {
- dest[0] = FELICA_UNENCRYPTED_WRITE_CMD;
- memcpy(&dest[1], reader->current_idm, 8);
-
- dest[9] = 1;
- uint8_t msg_len = 10;
- uint8_t service_code = FelicaServiceTypeRandom | FelicaServiceAttributeUnauthRW;
- dest[msg_len++] = service_code & 0xFF;
- dest[msg_len++] = service_code >> 8;
-
- dest[msg_len++] = block_count;
- for(int i = 0; i < block_count; i++) {
- dest[msg_len++] = block_list[i];
- dest[msg_len++] = IS_2_BYTE_BLOCK_LIST_ELEMENT;
- }
-
- uint16_t data_length = block_count * FELICA_BLOCK_SIZE;
- memcpy(dest + msg_len, block_data, data_length);
- msg_len += data_length;
- return msg_len;
-}
-
-bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* reader) {
- uint8_t consumed =
- felica_consume_unencrypted_header(buf, len, reader, FELICA_UNENCRYPTED_WRITE_RES, false);
- if(!consumed) {
- return false;
- }
- return true;
-}
-
-uint8_t felica_prepare_request_system_code(uint8_t* dest, FelicaReader* reader) {
- dest[0] = FELICA_REQUEST_SYSTEM_CODE_CMD;
- memcpy(&dest[1], reader->current_idm, 8);
- return 9;
-}
-
-bool felica_parse_request_system_code(
- uint8_t* buf,
- uint8_t len,
- FelicaReader* reader,
- FelicaSystemArray_t* systems) {
- uint8_t consumed =
- felica_consume_unencrypted_header(buf, len, reader, FELICA_REQUEST_SYSTEM_CODE_RES, true);
- if(consumed == 0) {
- return false;
- }
- len -= consumed;
- buf += consumed;
-
- uint8_t entries = *buf;
- len--;
- buf++;
-
- if(len < 2 * entries) {
- FURI_LOG_E(TAG, "FELICA_REQUEST_SYSTEM_CODE_RES: Response too short");
- return false;
- }
-
- for(uint8_t idx = 0; idx < entries; idx++) {
- FelicaSystem* system = FelicaSystemArray_push_new(*systems);
- furi_assert(system != NULL);
-
- // Set system code
- system->number = idx;
- system->code = buf[2 * idx] | (buf[2 * idx + 1] << 8);
-
- FURI_LOG_D(TAG, "Found system code %04X", system->code);
-
- // Fill in IDm and PMm
- memcpy(system->idm, reader->current_idm, 8);
- memcpy(system->pmm, reader->current_pmm, 8);
-
- // Set system index field in IDm
- system->idm[0] &= 0x0f;
- system->idm[0] |= ((idx & 0xf) << 4);
- }
-
- return true;
-}
-
-static FelicaSystem* felica_gen_monolithic_system_code(
- FelicaReader* reader,
- FelicaSystemArray_t* systems,
- uint16_t system_code) {
- FelicaSystem* system = FelicaSystemArray_push_new(*systems);
- furi_assert(reader != NULL);
- furi_assert(system != NULL);
-
- memcpy(system->idm, reader->current_idm, 8);
- memcpy(system->pmm, reader->current_pmm, 8);
- system->code = system_code;
-
- return system;
-}
-
-bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number) {
- if(block_number > REG_LITE_BLOCK) {
- return true;
- }
- uint8_t byte = mc_r_restr[block_number < 8 ? 0 : 1];
- return ((byte >> (block_number % 8)) & 1) == 0;
-}
-
-void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data) {
- FelicaBlock* block = FelicaBlockArray_safe_get(service->blocks, number);
- memcpy(block->data, data, FELICA_BLOCK_SIZE);
-}
-
-void felica_push_normal_block(FelicaService* service, uint8_t* data) {
- FelicaBlock* block = FelicaBlockArray_push_new(service->blocks);
- memcpy(block->data, data, FELICA_BLOCK_SIZE);
-}
-
-bool felica_lite_dump_data(
- FuriHalNfcTxRxContext* tx_rx,
- FelicaReader* reader,
- FelicaData* data,
- FelicaSystem* system) {
- const uint8_t fixed_blocks[] = {
- SYS_CODE_LITE_BLOCK,
- DEVICE_ID_LITE_BLOCK,
- ID_LITE_BLOCK,
- RC_LITE_BLOCK,
- CARD_KEY_LITE_BLOCK,
- MAC_LITE_BLOCK,
- CARD_KEY_VER_LITE_BLOCK,
- MEM_CONFIG_LITE_BLOCK,
- };
-
- uint8_t block_data[FELICA_BLOCK_SIZE * 4];
-
- tx_rx->tx_bits =
- 8 * felica_lite_prepare_unencrypted_read(tx_rx->tx_data, reader, true, fixed_blocks, 1);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_W(TAG, "Bad exchange verifying Lite system code");
- return false;
- }
- if(felica_parse_unencrypted_read(
- tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
- FELICA_BLOCK_SIZE) {
- FURI_LOG_W(TAG, "Bad response to Read without Encryption (SYS_C)");
- return false;
- }
- if(nfc_util_bytes2num(block_data, 2) != LITE_SYSTEM_CODE) {
- FURI_LOG_W(TAG, "Unexpected SYS_C value");
- return false;
- }
-
- tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
- tx_rx->tx_data, reader, true, &fixed_blocks[1], 1);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_W(TAG, "Bad exchange reading D_ID");
- return false;
- }
- if(felica_parse_unencrypted_read(
- tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
- FELICA_BLOCK_SIZE) {
- FURI_LOG_W(TAG, "Bad response to Read without Encryption (D_ID)");
- return false;
- }
- if(memcmp(system->idm, block_data, 8) != 0 || memcmp(system->pmm, block_data + 8, 8) != 0) {
- FURI_LOG_W(TAG, "Mismatching values for D_ID");
- return false;
- }
-
- FelicaLiteInfo* lite_info = &system->lite_info;
- lite_info->card_key_1 = NULL;
- lite_info->card_key_2 = NULL;
-
- tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
- tx_rx->tx_data, reader, true, &fixed_blocks[2], 1);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_W(TAG, "Bad exchange reading ID");
- return false;
- }
- if(felica_parse_unencrypted_read(
- tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
- FELICA_BLOCK_SIZE) {
- FURI_LOG_W(TAG, "Bad response to Read without Encryption (ID)");
- return false;
- }
- lite_info->data_format_code = nfc_util_bytes2num(block_data + 8, 2);
- memcpy(lite_info->ID_value, block_data + 10, 6);
- FURI_LOG_I(TAG, "ID:");
- for(int i = 0; i < FELICA_BLOCK_SIZE; i++) {
- FURI_LOG_I(TAG, "%02X", block_data[i]);
- }
-
- memset(block_data, 0, FELICA_BLOCK_SIZE);
- tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_write(
- tx_rx->tx_data, reader, &fixed_blocks[3], 1, block_data);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_W(TAG, "Bad exchange writing random challenge");
- return false;
- }
- if(!felica_parse_unencrypted_write(tx_rx->rx_data, tx_rx->rx_bits / 8, reader)) {
- FURI_LOG_W(TAG, "Bad response to Write without Encryption (RC)");
- return false;
- }
-
- tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
- tx_rx->tx_data, reader, true, &fixed_blocks[4], 2);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_W(TAG, "Bad exchange reading CK and MAC");
- return false;
- }
- if(felica_parse_unencrypted_read(
- tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
- FELICA_BLOCK_SIZE * 2) {
- FURI_LOG_W(TAG, "Bad response to Read without Encryption (CK, MAC)");
- return false;
- }
- memcpy(lite_info->MAC, block_data + FELICA_BLOCK_SIZE, 8);
- FURI_LOG_I(TAG, "MAC:");
- for(int i = 0; i < FELICA_BLOCK_SIZE; i++) {
- FURI_LOG_I(TAG, "%02X", block_data[i + FELICA_BLOCK_SIZE]);
- }
-
- tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
- tx_rx->tx_data, reader, true, &fixed_blocks[6], 2);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_W(TAG, "Bad exchange reading CKV and MC");
- return false;
- }
- if(felica_parse_unencrypted_read(
- tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
- FELICA_BLOCK_SIZE * 2) {
- FURI_LOG_W(TAG, "Bad response to Read without Encryption (CKV, MC)");
- return false;
- }
- lite_info->card_key_version = nfc_util_bytes2num(block_data, 2);
- memcpy(lite_info->memory_config, block_data + FELICA_BLOCK_SIZE, FELICA_BLOCK_SIZE);
-
- // Read SPAD and REG accordingly to MC
- uint8_t* mc_data = lite_info->memory_config;
- for(uint8_t block_number = 0; block_number <= REG_LITE_BLOCK; block_number++) {
- if(!felica_lite_can_read_without_mac(mc_data + 6, block_number)) {
- if(block_number < REG_LITE_BLOCK) {
- lite_info->S_PAD[block_number] = NULL;
- } else {
- lite_info->REG = NULL;
- }
- continue;
- }
-
- tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
- tx_rx->tx_data, reader, true, &block_number, 1);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_W(TAG, "Bad exchange reading blocks");
- return false;
- }
- if(felica_parse_unencrypted_read(
- tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
- FELICA_BLOCK_SIZE) {
- FURI_LOG_W(TAG, "Bad response to Read without Encryption (block %d)", block_number);
- return false;
- }
- uint8_t* block = malloc(FELICA_BLOCK_SIZE);
- memcpy(block, block_data, FELICA_BLOCK_SIZE);
- if(block_number < REG_LITE_BLOCK) {
- lite_info->S_PAD[block_number] = block;
- } else {
- lite_info->REG = block;
- }
- }
- if(data->type == FelicaICTypeLiteS) {
- lite_info->is_lite_s = true;
- const uint8_t fixed_s_blocks[] = {
- CARD_KEY_LITE_BLOCK,
- MAC_A_LITE_BLOCK,
- WRITE_COUNT_LITE_BLOCK,
- CRC_CHECK_LITE_BLOCK,
- };
-
- tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
- tx_rx->tx_data, reader, true, fixed_s_blocks, 2);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_W(TAG, "Bad exchange reading ID with MAC_A");
- return false;
- }
- if(felica_parse_unencrypted_read(
- tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
- FELICA_BLOCK_SIZE * 2) {
- FURI_LOG_W(TAG, "Bad response to Read without Encryption (CK, MAC_A)");
- return false;
- }
- memcpy(lite_info->MAC_A, block_data + FELICA_BLOCK_SIZE, FELICA_BLOCK_SIZE);
-
- tx_rx->tx_bits = 8 * felica_lite_prepare_unencrypted_read(
- tx_rx->tx_data, reader, true, &fixed_s_blocks[2], 2);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_W(TAG, "Bad exchange reading ID with MAC_A");
- return false;
- }
- if(felica_parse_unencrypted_read(
- tx_rx->rx_data, tx_rx->rx_bits / 8, reader, block_data, sizeof(block_data)) !=
- FELICA_BLOCK_SIZE * 2) {
- FURI_LOG_W(TAG, "Bad response to Read without Encryption (WC, CRC_CHECK)");
- return false;
- }
- lite_info->write_count = nfc_util_bytes2num(block_data, 3);
- lite_info->crc_valid = block_data[FELICA_BLOCK_SIZE] == 0x00;
- }
-
- return true;
-}
-
-bool felica_std_request_system_code(
- FuriHalNfcTxRxContext* tx_rx,
- FelicaReader* reader,
- FelicaSystemArray_t* systems) {
- tx_rx->tx_bits = 8 * felica_prepare_request_system_code(tx_rx->tx_data, reader);
- if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
- FURI_LOG_E(TAG, "Bad exchange requesting system code");
- return false;
- }
- if(!felica_parse_request_system_code(tx_rx->rx_data, tx_rx->rx_bits / 8, reader, systems)) {
- FURI_LOG_E(TAG, "Bad response to Request System Code command");
- return false;
- }
- return true;
-}
-
-bool felica_read_card(
- FuriHalNfcTxRxContext* tx_rx,
- FelicaData* data,
- uint8_t* polled_idm,
- uint8_t* polled_pmm) {
- furi_assert(tx_rx);
- furi_assert(polled_idm);
- furi_assert(polled_pmm);
-
- bool card_read = false;
- do {
- FelicaReader reader;
- memcpy(reader.current_idm, polled_idm, 8);
- memcpy(reader.current_pmm, polled_pmm, 8);
-
- FelicaSystemArray_init(data->systems);
-
- if(data->type == FelicaICTypeLite || data->type == FelicaICTypeLiteS) {
- FURI_LOG_I(TAG, "Reading Felica Lite system");
- FelicaSystem* lite_system =
- felica_gen_monolithic_system_code(&reader, &(data->systems), LITE_SYSTEM_CODE);
- felica_lite_dump_data(tx_rx, &reader, data, lite_system);
- card_read = true;
- break;
- }
- FURI_LOG_I(TAG, "Reading Felica Standard system");
- } while(false);
-
- return card_read;
-}
-
-void felica_service_clear(FelicaService* service) {
- FelicaBlockArray_clear(service->blocks);
-}
-
-void felica_lite_clear(FelicaLiteInfo* lite_info) {
- for(int i = 0; i < REG_LITE_BLOCK; i++) {
- uint8_t* block = lite_info->S_PAD[i];
- if(block != NULL) {
- free(block);
- }
- }
-
- if(lite_info->REG != NULL) {
- free(lite_info->REG);
- }
-
- if(lite_info->card_key_1 != NULL) {
- free(lite_info->card_key_1);
- }
- if(lite_info->card_key_2 != NULL) {
- free(lite_info->card_key_2);
- }
-}
-
-void felica_node_clear(FelicaNode* node);
-
-void felica_area_clear(FelicaArea* area) {
- for
- M_EACH(node, area->nodes, FelicaNodeArray_t) {
- felica_node_clear(node);
- }
- FelicaNodeArray_clear(area->nodes);
-}
-
-void felica_node_clear(FelicaNode* node) {
- if(node->type == FelicaNodeTypeArea) {
- felica_area_clear(node->area);
- } else if(node->type == FelicaNodeTypeService) {
- felica_service_clear(node->service);
- }
-}
-
-void felica_clear(FelicaData* data) {
- for
- M_EACH(system, data->systems, FelicaSystemArray_t) {
- if(system->code == LITE_SYSTEM_CODE) {
- felica_lite_clear(&system->lite_info);
- } else {
- felica_node_clear(&system->root);
- FelicaPublicServiceDict_clear(system->public_services);
- }
- }
- FelicaSystemArray_clear(data->systems);
-}
diff --git a/lib/nfc/protocols/felica.h b/lib/nfc/protocols/felica.h
deleted file mode 100644
index 876596bb5..000000000
--- a/lib/nfc/protocols/felica.h
+++ /dev/null
@@ -1,320 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-
-#define NFCF_F_SIG (13560000.0)
-#define MRT_T_SIG 302064.89 //ns, 256 * 16 / NFC_F_SIG * 1e9
-#define MRT_T_SIG_x4 1208259.56 //ns, MRT_T_SIG * (4 ** 1)
-#define MRT_T_SIG_x16 4833038.24 //ns, MRT_T_SIG * (4 ** 2)
-#define MRT_T_SIG_x64 19332152.96 //ns, MRT_T_SIG * (4 ** 2)
-
-#define FELICA_PMM_MRT_BASE 2
-
-#define FELICA_VARIABLE_MRT 0
-#define FELICA_FIXED_MRT 1
-#define FELICA_MUTUAL_AUTH_MRT 2
-#define FELICA_READ_MRT 3
-#define FELICA_WRITE_MRT 4
-#define FELICA_OTHER_MRT 5
-
-#define FELICA_PMM_VARIABLE_MRT (FELICA_PMM_MRT_BASE + FELICA_VARIABLE_MRT)
-#define FELICA_PMM_FIXED_MRT (FELICA_PMM_MRT_BASE + FELICA_FIXED_MRT)
-#define FELICA_PMM_MUTUAL_AUTH_MRT (FELICA_PMM_MRT_BASE + FELICA_MUTUAL_AUTH_MRT)
-#define FELICA_PMM_READ_MRT (FELICA_PMM_MRT_BASE + FELICA_READ_MRT)
-#define FELICA_PMM_WRITE_MRT (FELICA_PMM_MRT_BASE + FELICA_WRITE_MRT)
-#define FELICA_PMM_OTHER_MRT (FELICA_PMM_MRT_BASE + FELICA_OTHER_MRT)
-
-#define FELICA_BLOCK_SIZE 16
-
-#define CYBERNET_SYSTEM_CODE 0x0003
-#define NDEF_SYSTEM_CODE 0x12fc
-#define HCE_F_SYSTEM_CODE 0x4000
-#define OCTOPUS_SYSTEM_CODE 0x8008
-#define IRUCA_SYSTEM_CODE 0x80de
-#define EDY_SYSTEM_CODE 0x811d
-#define PASPY_SYSTEM_CODE 0x8592
-#define BLACKBOARD_SYSTEM_CODE 0x8620
-#define SAPICA_SYSTEM_CODE 0x865e
-#define SUICA_SYSTEM_CODE 0x86a7
-#define LITE_SYSTEM_CODE 0x88b4
-#define RYUTO_SYSTEM_CODE 0x8b5d
-#define OKICA_SYSTEM_CODE 0x8fc1
-#define SECURE_ID_SYSTEM_CODE 0x957a
-#define COMMON_AREA_SYSTEM_CODE 0xfe00
-#define PLUG_SYSTEM_CODE 0xfee1
-
-#define REG_LITE_BLOCK 0x0e
-#define RC_LITE_BLOCK 0x80
-#define MAC_LITE_BLOCK 0x81
-#define ID_LITE_BLOCK 0x82
-#define DEVICE_ID_LITE_BLOCK 0x83
-#define SERVICE_CODE_LITE_BLOCK 0x84
-#define SYS_CODE_LITE_BLOCK 0x85
-#define CARD_KEY_VER_LITE_BLOCK 0x86
-#define CARD_KEY_LITE_BLOCK 0x87
-#define MEM_CONFIG_LITE_BLOCK 0x88
-#define WRITE_COUNT_LITE_BLOCK 0x90
-#define MAC_A_LITE_BLOCK 0x91
-#define STATE_LITE_BLOCK 0x92
-#define CRC_CHECK_LITE_BLOCK 0xA0
-
-#define IS_2_BYTE_BLOCK_LIST_ELEMENT 0x80
-
-#define FELICA_UNENCRYPTED_READ_CMD 0x06
-#define FELICA_UNENCRYPTED_WRITE_CMD 0x08
-#define FELICA_SEARCH_SERVICE_CODE_CMD 0x0a
-#define FELICA_REQUEST_SYSTEM_CODE_CMD 0x0c
-
-#define FELICA_UNENCRYPTED_READ_RES 0x07
-#define FELICA_UNENCRYPTED_WRITE_RES 0x09
-#define FELICA_SEARCH_SERVICE_CODE_RES 0x0b
-#define FELICA_REQUEST_SYSTEM_CODE_RES 0x0d
-
-typedef enum {
- FelicaICTypeRC_SA24_10K, // RC-SA24/1x
- FelicaICTypeRC_SA24_6K, // RC-SA24/1x1
- FelicaICTypeSD2_6K, // RC-SA21/2x1
- FelicaICTypeSD2_4K, // RC-SA21/2
- FelicaICTypeSD2WithDES, // RC-SA20/1, RC-SA20/2
- FelicaICTypeRC_SA08, // Certifications exist, prototype?
- FelicaICTypeSD1, // RC-SA01
- FelicaICTypeSD1WithDES, // RC-SA00
- FelicaICTypeFRAM_4K, // RC-S962
- FelicaICTypeFRAM_9K, // RC-S960
- FelicaICTypeEMV_36K, // RC-S954
- FelicaICTypeEMV_16K, // RC-S953
- FelicaICTypeEMV_32K, // RC-S952
- FelicaICType576B, // RC-S919
- FelicaICType4K, // RC-S915
- FelicaICType2K, // RC-S830 series cards, chip name unknown,
- FelicaICTypeMobileIC_V4_1,
- FelicaICTypeMobileIC_V4,
- FelicaICTypeMobileIC_V3,
- FelicaICTypeMobileIC_V2,
- FelicaICTypeMobileIC_V1,
- FelicaICTypeLite, // RC-S965
- FelicaICTypeLiteS, // RC-S966
- FelicaICTypeLink, // RC-S967,
- FelicaICTypePlug, // RC-S926
- FelicaICTypeSuica, // https://www.tuv-nederland.nl/assets/files/cerfiticaten/2019/07/cr-nscib-cc-10-30076-cr.pdf
-} FelicaICType;
-
-typedef enum {
- FelicaServiceTypeRandom = (0b0010 << 2),
- FelicaServiceTypeCyclic = (0b0011 << 2),
- FelicaServiceTypePurse = (0b010 << 3),
-} FelicaServiceType;
-typedef enum {
- FelicaServiceAttributeAuthRW = 0b00,
- FelicaServiceAttributeUnauthRW = 0b01,
- FelicaServiceAttributeAuthRO = 0b10,
- FelicaServiceAttributeUnauthRO = 0b11,
-
- FelicaServiceAttributeAuthDirectAccess = 0b000,
- FelicaServiceAttributeUnauthDirectAccess = 0b001,
- FelicaServiceAttributeAuthCashbackDecrement = 0b010,
- FelicaServiceAttributeUnauthCashbackDecrement = 0b011,
- FelicaServiceAttributeAuthDecrement = 0b100,
- FelicaServiceAttributeUnauthDecrement = 0b101,
- FelicaServiceAttributeAuthPurseRO = 0b110,
- FelicaServiceAttributeUnauthPurseRO = 0b111,
-} FelicaServiceAttribute;
-
-DICT_SET_DEF(
- FelicaServiceAttributeList,
- FelicaServiceAttribute,
- M_ENUM_OPLIST(FelicaServiceAttribute, FelicaServiceAttributeAuthRW))
-
-typedef struct {
- uint8_t data[FELICA_BLOCK_SIZE];
-} FelicaBlock;
-
-ARRAY_DEF(FelicaBlockArray, FelicaBlock, M_POD_OPLIST)
-#define M_OPL_FelicaBlockArray_t() ARRAY_OPLIST(FelicaBlockArray, M_POD_OPLIST)
-
-typedef struct {
- uint16_t number;
- FelicaServiceAttributeList_t access_control_list; // accounts for overlap services
- bool is_extended_overlap; // We don't know much about this currently. will always be false
- union {
- // TODO change this to use FelicaBlockArray_t
- FelicaBlockArray_t blocks;
- struct {
- uint16_t overlap_target;
- uint8_t block_start;
- uint8_t block_count;
- };
- };
-} FelicaService;
-
-typedef enum {
- FelicaNodeTypeArea,
- FelicaNodeTypeService,
-} FelicaNodeType;
-
-struct _FelicaArea_t;
-typedef struct _FelicaArea_t FelicaArea;
-
-struct _FelicaNode_s;
-typedef struct _FelicaNode_s FelicaNode;
-
-struct _FelicaNode_s {
- /** Node type. */
- FelicaNodeType type;
- /** Borrowed pointer to its parent node. */
- FelicaNode* parent;
- union {
- /** (Area/dir type only) The area struct. */
- FelicaArea* area;
- /** (Service/file type only) The service struct. */
- FelicaService* service;
- };
-};
-
-// TODO properly remove this
-//ARRAY_DEF(FelicaNodeList, FelicaNode*, M_PTR_OPLIST)
-ARRAY_DEF(FelicaNodeArray, FelicaNode, M_POD_OPLIST)
-#define M_OPL_FelicaNodeArray_t() ARRAY_OPLIST(FelicaNodeArray, M_POD_OPLIST)
-
-ARRAY_DEF(FelicaNodeRefArray, FelicaNode*, M_PTR_OPLIST)
-#define M_OPL_FelicaNodeRefArray_t() ARRAY_OPLIST(FelicaNodeRefArray, M_PTR_OPLIST)
-
-// { service_number: service_ptr_in_tree }
-DICT_DEF2(FelicaPublicServiceDict, uint16_t, M_DEFAULT_OPLIST, FelicaService*, M_PTR_OPLIST)
-#define M_OPL_FelicaPublicServiceDict_t() \
- DICT_OPLIST(FelicaPublicServiceDict, M_DEFAULT_OPLIST, M_PTR_OPLIST)
-
-struct _FelicaArea_t {
- uint16_t number;
- bool can_create_subareas;
- uint16_t end_service_code;
-
- FelicaNodeArray_t nodes;
-};
-
-typedef struct {
- uint8_t* S_PAD[14];
- uint8_t* REG;
- // MACs of all zero bytes (read from CK)
- uint8_t MAC[8];
- uint16_t data_format_code;
- uint8_t ID_value[6];
- uint8_t* card_key_1;
- uint8_t* card_key_2;
- uint16_t card_key_version;
- uint8_t memory_config[FELICA_BLOCK_SIZE];
-
- bool is_lite_s;
- // Lite-S only
- uint8_t MAC_A[8];
- uint32_t write_count;
- bool crc_valid;
-} FelicaLiteInfo;
-
-typedef struct _FelicaSystem_t {
- /** FeliCa system index. */
- uint8_t number;
- /** If the system belongs to a FeliCa Lite (and be its only system). */
- bool is_lite;
- /** FeliCa system code. */
- uint16_t code;
- /** System IDm with system index bitfield properly set. */
- uint8_t idm[8];
- /** Cached card PMm. */
- uint8_t pmm[8];
-
- union {
- /** (For FeliCa Lite only) Card content. */
- FelicaLiteInfo lite_info;
- struct {
- /** (For FeliCa Standard only) The root of the raw filesystem tree. */
- FelicaNode root;
- /** (For FeliCa Standard only) Shortcut for all publicly accessible services for quick
- * access by card parsers. */
- FelicaPublicServiceDict_t public_services;
- };
- };
-} FelicaSystem;
-
-// TODO properly remove this
-//ARRAY_DEF(FelicaSystemList, FelicaSystem*, M_PTR_OPLIST)
-ARRAY_DEF(FelicaSystemArray, FelicaSystem, M_POD_OPLIST)
-#define M_OPL_FelicaSystemArray_t() ARRAY_OPLIST(FelicaSystemArray, M_POD_OPLIST)
-
-typedef struct {
- FelicaICType type;
- uint8_t subtype;
- FelicaSystemArray_t systems;
-} FelicaData;
-
-typedef struct {
- uint8_t current_idm[8];
- uint8_t current_pmm[8];
-
- uint8_t status_flags[2];
-} FelicaReader;
-
-bool felica_check_ic_type(uint8_t* PMm);
-FelicaICType felica_get_ic_type(uint8_t* PMm);
-
-uint8_t felica_prepare_unencrypted_read(
- uint8_t* dest,
- const FelicaReader* reader,
- const uint16_t* service_code_list,
- uint8_t service_count,
- const uint32_t* block_list,
- uint8_t block_count);
-uint8_t felica_lite_prepare_unencrypted_read(
- uint8_t* dest,
- const FelicaReader* reader,
- bool is_read_only,
- const uint8_t* block_list,
- uint8_t block_count);
-uint16_t felica_parse_unencrypted_read(
- uint8_t* buf,
- uint8_t len,
- FelicaReader* reader,
- uint8_t* out,
- uint16_t out_len);
-
-uint8_t felica_prepare_unencrypted_write(
- uint8_t* dest,
- FelicaReader* reader,
- const uint16_t* service_code_list,
- uint8_t service_count,
- const uint32_t* block_list,
- uint8_t block_count,
- const uint8_t* block_data);
-uint8_t felica_lite_prepare_unencrypted_write(
- uint8_t* dest,
- const FelicaReader* reader,
- const uint8_t* block_list,
- uint8_t block_count,
- const uint8_t* block_data);
-bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* reader);
-
-void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data);
-void felica_push_normal_block(FelicaService* service, uint8_t* data);
-
-/** Dump a FeliCa Lite or Lite-S tag.
- *
- * @param tx_rx NFC context.
- * @param reader FeliCa reader context.
- * @param data Output data object.
- * @param system FeliCa system description.
- * @return true if successful.
- */
-bool felica_lite_dump_data(
- FuriHalNfcTxRxContext* tx_rx,
- FelicaReader* reader,
- FelicaData* data,
- FelicaSystem* system);
-
-bool felica_read_card(
- FuriHalNfcTxRxContext* tx_rx,
- FelicaData* data,
- uint8_t* polled_idm,
- uint8_t* polled_pmm);
-void felica_clear(FelicaData* data);
\ No newline at end of file
diff --git a/lib/nfc/protocols/felica_util.c b/lib/nfc/protocols/felica_util.c
deleted file mode 100644
index 47f66fcc5..000000000
--- a/lib/nfc/protocols/felica_util.c
+++ /dev/null
@@ -1,67 +0,0 @@
-#include "./felica.h"
-#include
-
-static const uint32_t TIME_CONSTANT_US = 302;
-
-// TODO move this to felica.c
-uint_least32_t felica_estimate_timing_us(uint_least8_t timing, uint_least8_t units) {
- uint_least32_t base_cost_factor = 1 + (timing & 0x7);
- uint_least32_t unit_cost_factor = 1 + ((timing >> 3) & 0x7);
- uint_least32_t scale = 1 << ((timing >> 6) * 2);
- return TIME_CONSTANT_US * scale * (base_cost_factor + unit_cost_factor * units);
-}
-
-bool felica_lite_is_issued(FelicaLiteInfo* lite_info) {
- // System blocks aren't writable?
- if(lite_info->memory_config[2] == 0x00) {
- return false;
- }
-
- // MC is not writable?
- if(lite_info->memory_config[1] & 0x80) {
- return false;
- }
-
- return true;
-}
-
-FuriString* felica_get_system_name(FelicaSystem* system) {
- uint16_t code = system->code;
-
- const char* prefix;
- if(code == SUICA_SYSTEM_CODE) {
- prefix = "SuiCa";
- } else if(code == NDEF_SYSTEM_CODE) {
- prefix = "NDEF";
- } else if(code == HCE_F_SYSTEM_CODE) {
- prefix = "HCE-F";
- } else if(code == OCTOPUS_SYSTEM_CODE) {
- prefix = "Octopus";
- } else if(code == EDY_SYSTEM_CODE) {
- prefix = "Edy";
- } else if(code == PASPY_SYSTEM_CODE) {
- prefix = "PASPY";
- } else if(code == BLACKBOARD_SYSTEM_CODE) {
- prefix = "Blackboard";
- } else if(code == SAPICA_SYSTEM_CODE) {
- prefix = "SAPICA";
- } else if(code == LITE_SYSTEM_CODE) {
- prefix = "FeliCa Lite";
- } else if(code == RYUTO_SYSTEM_CODE) {
- prefix = "Ryuto";
- } else if(code == OKICA_SYSTEM_CODE) {
- prefix = "OKICA";
- } else if(code == SECURE_ID_SYSTEM_CODE) {
- prefix = "FeliCa Secure ID";
- } else if(code == IRUCA_SYSTEM_CODE) {
- prefix = "IruCa";
- } else if(code == COMMON_AREA_SYSTEM_CODE) {
- prefix = "Common Area";
- } else if(code == PLUG_SYSTEM_CODE) {
- prefix = "FeliCa Plug";
- } else {
- return furi_string_alloc_printf("System %04X", code);
- }
-
- return furi_string_alloc_printf("%s (%04X)", prefix, code);
-}
\ No newline at end of file
diff --git a/lib/nfc/protocols/felica_util.h b/lib/nfc/protocols/felica_util.h
deleted file mode 100644
index 653ba4501..000000000
--- a/lib/nfc/protocols/felica_util.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "./felica.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-uint_least32_t felica_estimate_timing_us(uint_least8_t timing, uint_least8_t units);
-bool felica_lite_is_issued(FelicaLiteInfo* lite_info);
-FuriString* felica_get_system_name(FelicaSystem* system);
-FuriString* felica_get_service_name(FelicaService* service);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c
index 8fd396cff..e8683d6c0 100644
--- a/lib/nfc/protocols/mifare_classic.c
+++ b/lib/nfc/protocols/mifare_classic.c
@@ -374,10 +374,7 @@ bool mf_classic_is_value_block(MfClassicData* data, uint8_t block_num) {
data, block_num, MfClassicKeyB, MfClassicActionDataDec));
}
-bool mf_classic_check_card_type(FuriHalNfcADevData* data) {
- uint8_t ATQA0 = data->atqa[0];
- uint8_t ATQA1 = data->atqa[1];
- uint8_t SAK = data->sak;
+bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
if((ATQA0 == 0x44 || ATQA0 == 0x04) &&
(SAK == 0x08 || SAK == 0x88 || SAK == 0x09 || SAK == 0x89)) {
return true;
@@ -391,10 +388,7 @@ bool mf_classic_check_card_type(FuriHalNfcADevData* data) {
}
}
-MfClassicType mf_classic_get_classic_type(FuriHalNfcADevData* data) {
- uint8_t ATQA0 = data->atqa[0];
- uint8_t ATQA1 = data->atqa[1];
- uint8_t SAK = data->sak;
+MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
if((ATQA0 == 0x44 || ATQA0 == 0x04)) {
if((SAK == 0x08 || SAK == 0x88)) {
return MfClassicType1k;
diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h
index 60d9ab743..7efe81b8c 100644
--- a/lib/nfc/protocols/mifare_classic.h
+++ b/lib/nfc/protocols/mifare_classic.h
@@ -98,9 +98,9 @@ typedef struct {
const char* mf_classic_get_type_str(MfClassicType type);
-bool mf_classic_check_card_type(FuriHalNfcADevData* data);
+bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
-MfClassicType mf_classic_get_classic_type(FuriHalNfcADevData* data);
+MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
uint8_t mf_classic_get_total_sectors_num(MfClassicType type);
diff --git a/lib/nfc/protocols/mifare_common.c b/lib/nfc/protocols/mifare_common.c
index 1f336cb51..5277cc8cd 100644
--- a/lib/nfc/protocols/mifare_common.c
+++ b/lib/nfc/protocols/mifare_common.c
@@ -1,10 +1,6 @@
#include "mifare_common.h"
-#include "furi_hal_nfc.h"
-MifareType mifare_common_get_type(FuriHalNfcADevData* data) {
- uint8_t ATQA0 = data->atqa[0];
- uint8_t ATQA1 = data->atqa[1];
- uint8_t SAK = data->sak;
+MifareType mifare_common_get_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
MifareType type = MifareTypeUnknown;
if((ATQA0 == 0x44) && (ATQA1 == 0x00) && (SAK == 0x00)) {
diff --git a/lib/nfc/protocols/mifare_common.h b/lib/nfc/protocols/mifare_common.h
index e60a97bd0..2b694d906 100644
--- a/lib/nfc/protocols/mifare_common.h
+++ b/lib/nfc/protocols/mifare_common.h
@@ -1,7 +1,6 @@
#pragma once
#include
-#include "furi_hal_nfc.h"
typedef enum {
MifareTypeUnknown,
@@ -10,4 +9,4 @@ typedef enum {
MifareTypeDesfire,
} MifareType;
-MifareType mifare_common_get_type(FuriHalNfcADevData* data);
+MifareType mifare_common_get_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
diff --git a/lib/nfc/protocols/mifare_desfire.c b/lib/nfc/protocols/mifare_desfire.c
index 0c43169a9..e0ead737f 100644
--- a/lib/nfc/protocols/mifare_desfire.c
+++ b/lib/nfc/protocols/mifare_desfire.c
@@ -258,11 +258,7 @@ void mf_df_cat_file(MifareDesfireFile* file, FuriString* out) {
}
}
-bool mf_df_check_card_type(FuriHalNfcADevData* data) {
- uint8_t ATQA0 = data->atqa[0];
- uint8_t ATQA1 = data->atqa[1];
- uint8_t SAK = data->sak;
-
+bool mf_df_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
return ATQA0 == 0x44 && ATQA1 == 0x03 && SAK == 0x20;
}
diff --git a/lib/nfc/protocols/mifare_desfire.h b/lib/nfc/protocols/mifare_desfire.h
index 7d5915b76..8faa98ec2 100644
--- a/lib/nfc/protocols/mifare_desfire.h
+++ b/lib/nfc/protocols/mifare_desfire.h
@@ -132,7 +132,7 @@ void mf_df_cat_application_info(MifareDesfireApplication* app, FuriString* out);
void mf_df_cat_application(MifareDesfireApplication* app, FuriString* out);
void mf_df_cat_file(MifareDesfireFile* file, FuriString* out);
-bool mf_df_check_card_type(FuriHalNfcADevData* data);
+bool mf_df_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
MifareDesfireApplication* mf_df_get_application(MifareDesfireData* data, const uint8_t (*aid)[3]);
MifareDesfireFile* mf_df_get_file(MifareDesfireApplication* app, uint8_t id);
diff --git a/lib/nfc/protocols/mifare_ultralight.c b/lib/nfc/protocols/mifare_ultralight.c
index 750ede8d7..266b6e2e2 100644
--- a/lib/nfc/protocols/mifare_ultralight.c
+++ b/lib/nfc/protocols/mifare_ultralight.c
@@ -33,12 +33,11 @@ uint32_t mf_ul_pwdgen_amiibo(FuriHalNfcDevData* data) {
return pwd;
}
-bool mf_ul_check_card_type(FuriHalNfcADevData* data) {
- uint8_t ATQA0 = data->atqa[0];
- uint8_t ATQA1 = data->atqa[1];
- uint8_t SAK = data->sak;
-
- return ((ATQA0 == 0x44) && (ATQA1 == 0x00) && (SAK == 0x00));
+bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
+ if((ATQA0 == 0x44) && (ATQA1 == 0x00) && (SAK == 0x00)) {
+ return true;
+ }
+ return false;
}
void mf_ul_reset(MfUltralightData* data) {
diff --git a/lib/nfc/protocols/mifare_ultralight.h b/lib/nfc/protocols/mifare_ultralight.h
index 64d61da56..9cb7ca535 100644
--- a/lib/nfc/protocols/mifare_ultralight.h
+++ b/lib/nfc/protocols/mifare_ultralight.h
@@ -207,7 +207,7 @@ typedef struct {
void mf_ul_reset(MfUltralightData* data);
-bool mf_ul_check_card_type(FuriHalNfcADevData* data);
+bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
bool mf_ultralight_read_version(
FuriHalNfcTxRxContext* tx_rx,
diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript
index 575d27b2a..96a87f665 100644
--- a/lib/subghz/SConscript
+++ b/lib/subghz/SConscript
@@ -22,6 +22,7 @@ env.Append(
File("subghz_setting.h"),
File("subghz_protocol_registry.h"),
File("devices/cc1101_configs.h"),
+ File("devices/cc1101_int/cc1101_int_interconnect.h"),
],
)
diff --git a/lib/xtreme/xtreme.h b/lib/xtreme/xtreme.h
index cfef8173a..29a76bc52 100644
--- a/lib/xtreme/xtreme.h
+++ b/lib/xtreme/xtreme.h
@@ -9,7 +9,8 @@ extern "C" {
#define XTREME_SETTINGS_PATH CFG_PATH("xtreme_settings.txt")
#define XTREME_ASSETS_PATH EXT_PATH("dolphin_custom")
-#define XTREME_APPS_PATH CFG_PATH("xtreme_apps.txt")
+#define XTREME_MENU_OLD_PATH CFG_PATH("xtreme_apps.txt")
+#define XTREME_MENU_PATH CFG_PATH("xtreme_menu.txt")
#define XTREME_ASSETS_PACK_NAME_LEN 32
typedef enum {
diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py
index 5ed8c260b..2d0d602c5 100644
--- a/scripts/fbt/appmanifest.py
+++ b/scripts/fbt/appmanifest.py
@@ -321,7 +321,13 @@ class AppBuildset:
def get_sdk_headers(self):
sdk_headers = []
for app in self.apps:
- sdk_headers.extend([app._appdir.File(header) for header in app.sdk_headers])
+ sdk_headers.extend(
+ [
+ src._appdir.File(header)
+ for src in [app, *app._plugins]
+ for header in src.sdk_headers
+ ]
+ )
return sdk_headers
def get_apps_of_type(self, apptype: FlipperAppType, all_known: bool = False):
diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py
index 7619c3263..51965681c 100644
--- a/scripts/fbt_tools/fbt_extapps.py
+++ b/scripts/fbt_tools/fbt_extapps.py
@@ -3,7 +3,7 @@ import os
import pathlib
import shutil
from dataclasses import dataclass, field
-from typing import Optional
+from typing import Optional, Dict, List
import SCons.Warnings
from ansi.color import fg
@@ -406,22 +406,26 @@ def generate_embed_app_metadata_actions(source, target, env, for_signature):
return Action(actions)
-def AddAppLaunchTarget(env, appname, launch_target_name):
- deploy_sources, flipp_dist_paths, validators = [], [], []
- run_script_extra_ars = ""
+@dataclass
+class AppDeploymentComponents:
+ deploy_sources: Dict[str, object] = field(default_factory=dict)
+ validators: List[object] = field(default_factory=list)
+ extra_launch_args: str = ""
- def _add_dist_targets(app_artifacts):
- validators.append(app_artifacts.validator)
+ def add_app(self, app_artifacts):
for _, ext_path in app_artifacts.dist_entries:
- deploy_sources.append(app_artifacts.compact)
- flipp_dist_paths.append(f"/ext/{ext_path}")
- return app_artifacts
+ self.deploy_sources[f"/ext/{ext_path}"] = app_artifacts.compact
+ self.validators.append(app_artifacts.validator)
+
+
+def _gather_app_components(env, appname) -> AppDeploymentComponents:
+ components = AppDeploymentComponents()
def _add_host_app_to_targets(host_app):
artifacts_app_to_run = env["EXT_APPS"].get(host_app.appid, None)
- _add_dist_targets(artifacts_app_to_run)
+ components.add_app(artifacts_app_to_run)
for plugin in host_app._plugins:
- _add_dist_targets(env["EXT_APPS"].get(plugin.appid, None))
+ components.add_app(env["EXT_APPS"].get(plugin.appid, None))
artifacts_app_to_run = env.GetExtAppByIdOrPath(appname)
if artifacts_app_to_run.app.apptype == FlipperAppType.PLUGIN:
@@ -433,25 +437,35 @@ def AddAppLaunchTarget(env, appname, launch_target_name):
FlipperAppType.EXTERNAL,
FlipperAppType.MENUEXTERNAL,
]:
- _add_host_app_to_targets(host_app)
+ components.add_app(host_app)
else:
# host app is a built-in app
- run_script_extra_ars = f"-a {host_app.name}"
- _add_dist_targets(artifacts_app_to_run)
+ components.add_app(artifacts_app_to_run)
+ components.extra_launch_args = f"-a {host_app.name}"
else:
raise UserError("Host app is unknown")
else:
_add_host_app_to_targets(artifacts_app_to_run.app)
+ return components
- # print(deploy_sources, flipp_dist_paths)
- env.PhonyTarget(
+
+def AddAppLaunchTarget(env, appname, launch_target_name):
+ components = _gather_app_components(env, appname)
+ target = env.PhonyTarget(
launch_target_name,
'${PYTHON3} "${APP_RUN_SCRIPT}" -p ${FLIP_PORT} ${EXTRA_ARGS} -s ${SOURCES} -t ${FLIPPER_FILE_TARGETS}',
- source=deploy_sources,
- FLIPPER_FILE_TARGETS=flipp_dist_paths,
- EXTRA_ARGS=run_script_extra_ars,
+ source=components.deploy_sources.values(),
+ FLIPPER_FILE_TARGETS=components.deploy_sources.keys(),
+ EXTRA_ARGS=components.extra_launch_args,
)
- env.Alias(launch_target_name, validators)
+ env.Alias(launch_target_name, components.validators)
+ return target
+
+
+def AddAppBuildTarget(env, appname, build_target_name):
+ components = _gather_app_components(env, appname)
+ env.Alias(build_target_name, components.validators)
+ env.Alias(build_target_name, components.deploy_sources.values())
def generate(env, **kw):
@@ -480,6 +494,7 @@ def generate(env, **kw):
env.AddMethod(BuildAppElf)
env.AddMethod(GetExtAppByIdOrPath)
env.AddMethod(AddAppLaunchTarget)
+ env.AddMethod(AddAppBuildTarget)
env.Append(
BUILDERS={
diff --git a/scripts/fbt_tools/fbt_help.py b/scripts/fbt_tools/fbt_help.py
index d971cfda5..e9364a42b 100644
--- a/scripts/fbt_tools/fbt_help.py
+++ b/scripts/fbt_tools/fbt_help.py
@@ -4,15 +4,16 @@ targets_help = """Configuration variables:
tail_help = """
TASKS:
-Building:
+Firmware & apps:
firmware_all, fw_dist:
Build firmware; create distribution package
faps, fap_dist:
Build all FAP apps
- fap_{APPID}, launch_app APPSRC={APPID}:
+ fap_{APPID}, build APPSRC={APPID}; launch APPSRC={APPID}:
Build FAP app with appid={APPID}; upload & start it over USB
fap_deploy:
Build and upload all FAP apps over USB
+
Flashing & debugging:
flash, flash_blackmagic, jflash:
diff --git a/scripts/fbt_tools/fbt_version.py b/scripts/fbt_tools/fbt_version.py
index aead13b29..1bd86f1f1 100644
--- a/scripts/fbt_tools/fbt_version.py
+++ b/scripts/fbt_tools/fbt_version.py
@@ -21,7 +21,7 @@ def generate(env):
action=Action(
'${PYTHON3} "${VERSION_SCRIPT}" generate '
"-t ${TARGET_HW} -fw-origin ${FIRMWARE_ORIGIN} "
- '-o ${TARGET.dir.posix} --dir "${ROOT_DIR}"',
+ '-o ${TARGET.dir.posix} --dir "${ROOT_DIR}" --suffix "${DIST_SUFFIX}"',
"${VERSIONCOMSTR}",
),
emitter=version_emitter,
diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct
index 703a9187a..9a9e0938c 100644
--- a/scripts/ufbt/SConstruct
+++ b/scripts/ufbt/SConstruct
@@ -336,8 +336,10 @@ def ambiguous_app_call(**kw):
if app_to_launch:
appenv.AddAppLaunchTarget(app_to_launch, "launch")
+ appenv.AddAppBuildTarget(app_to_launch, "build")
else:
dist_env.PhonyTarget("launch", Action(ambiguous_app_call, None))
+ dist_env.PhonyTarget("build", Action(ambiguous_app_call, None))
# cli handler
diff --git a/scripts/version.py b/scripts/version.py
index 987fd9b96..f33c5e6e9 100755
--- a/scripts/version.py
+++ b/scripts/version.py
@@ -1,6 +1,4 @@
#!/usb/bin/env python3
-VERSION = "XFW-0049"
-
import json
import os
import subprocess
@@ -12,8 +10,9 @@ from flipper.app import App
class GitVersion:
REVISION_SUFFIX_LENGTH = 8
- def __init__(self, source_dir):
+ def __init__(self, source_dir, suffix):
self.source_dir = source_dir
+ self.suffix = suffix
def get_version_info(self):
commit = (
@@ -32,14 +31,15 @@ class GitVersion:
# (set by CI)
branch = (
os.environ.get("WORKFLOW_BRANCH_OR_TAG", None)
- or VERSION
or self._exec_git("rev-parse --abbrev-ref HEAD")
or "unknown"
)
- branch_num = self._exec_git("rev-list --count HEAD") or "n/a"
-
- version = os.environ.get("DIST_SUFFIX", None) or VERSION or "unknown"
+ version = (
+ self.suffix.split("_")[0]
+ or os.environ.get("DIST_SUFFIX", None)
+ or "unknown"
+ )
force_no_dirty = os.environ.get("FORCE_NO_DIRTY", None) or ""
if force_no_dirty != "":
@@ -108,10 +108,13 @@ class Main(App):
required=True,
)
self.parser_generate.add_argument("--dir", dest="sourcedir", required=True)
+ self.parser_generate.add_argument("--suffix", dest="suffix", required=True)
self.parser_generate.set_defaults(func=self.generate)
def generate(self):
- current_info = GitVersion(self.args.sourcedir).get_version_info()
+ current_info = GitVersion(
+ self.args.sourcedir, self.args.suffix
+ ).get_version_info()
build_date = (
date.today()
diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons
index 0893c4556..5c6f18d68 100644
--- a/site_scons/extapps.scons
+++ b/site_scons/extapps.scons
@@ -114,8 +114,20 @@ extapps.resources_dist = appenv.FapDist(appenv["RESOURCES_ROOT"], [])
if appsrc := appenv.subst("$APPSRC"):
- appenv.AddAppLaunchTarget(appsrc, "launch_app")
+ launch_target = appenv.AddAppLaunchTarget(appsrc, "launch")
+ Alias("launch_app", launch_target)
+ appenv.PhonyTarget(
+ "launch_app",
+ Action(
+ lambda **kw: warn(
+ WarningOnByDefault,
+ "The 'launch_app' target is deprecated. Use 'launch' instead.",
+ ),
+ None,
+ ),
+ )
+ appenv.AddAppBuildTarget(appsrc, "build")
# SDK management
diff --git a/sonar-project.properties b/sonar-project.properties
index 30fc27a96..72add4236 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -1,8 +1,8 @@
-sonar.projectKey=ClaraCrazy_Flipper-Xtreme
-sonar.organization=claracrazy
+sonar.projectKey=Flipper-XFW_Xtreme-Firmware
+sonar.organization=Flipper-XFW
# This is the name and version displayed in the SonarCloud UI.
-#sonar.projectName=Flipper-Xtreme
+#sonar.projectName=Xtreme-Firmware
#sonar.projectVersion=1.0
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.