Merge remote-tracking branch 'origin/dev' into release-candidate
115
.github/workflows/build.yml
vendored
@ -15,11 +15,8 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
main:
|
||||||
runs-on: [self-hosted,FlipperZero]
|
runs-on: [self-hosted,FlipperZeroShell]
|
||||||
steps:
|
steps:
|
||||||
- name: 'Cleanup workspace'
|
|
||||||
uses: AutoModality/action-clean@v1
|
|
||||||
|
|
||||||
- name: 'Decontaminate previous build leftovers'
|
- name: 'Decontaminate previous build leftovers'
|
||||||
run: |
|
run: |
|
||||||
if [ -d .git ]
|
if [ -d .git ]
|
||||||
@ -32,12 +29,8 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: true
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
- name: 'Build docker image'
|
|
||||||
uses: ./.github/actions/docker
|
|
||||||
|
|
||||||
- name: 'Make artifacts directory'
|
- name: 'Make artifacts directory'
|
||||||
run: |
|
run: |
|
||||||
test -d artifacts && rm -rf artifacts || true
|
test -d artifacts && rm -rf artifacts || true
|
||||||
@ -71,40 +64,38 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
tar czpf artifacts/flipper-z-any-scripts-${{steps.names.outputs.suffix}}.tgz scripts
|
tar czpf artifacts/flipper-z-any-scripts-${{steps.names.outputs.suffix}}.tgz scripts
|
||||||
|
|
||||||
- name: 'Build the firmware in docker'
|
- name: 'Build the firmware'
|
||||||
uses: ./.github/actions/docker
|
run: |
|
||||||
with:
|
set -e
|
||||||
run: |
|
for TARGET in ${TARGETS}
|
||||||
set -e
|
do
|
||||||
for TARGET in ${TARGETS}
|
FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }}
|
||||||
do
|
done
|
||||||
./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }}
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: 'Move upload files'
|
- name: 'Move upload files'
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
uses: ./.github/actions/docker
|
run: |
|
||||||
with:
|
set -e
|
||||||
run: |
|
for TARGET in ${TARGETS}
|
||||||
set -e
|
do
|
||||||
for TARGET in ${TARGETS}
|
mv dist/${TARGET}-*/* artifacts/
|
||||||
do
|
done
|
||||||
mv dist/${TARGET}-*/* artifacts/
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: 'Bundle self-update package'
|
- name: 'Bundle self-update package'
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
uses: ./.github/actions/docker
|
run: |
|
||||||
with:
|
set -e
|
||||||
run: |
|
for UPDATEBUNDLE in artifacts/*/
|
||||||
set -e
|
do
|
||||||
for UPDATEBUNDLE in artifacts/*/
|
BUNDLE_NAME=`echo $UPDATEBUNDLE | cut -d'/' -f2`
|
||||||
do
|
echo Packaging ${BUNDLE_NAME}
|
||||||
BUNDLE_NAME=`echo $UPDATEBUNDLE | cut -d'/' -f2`
|
tar czpf artifacts/flipper-z-${BUNDLE_NAME}.tgz -C artifacts ${BUNDLE_NAME}
|
||||||
echo Packaging ${BUNDLE_NAME}
|
rm -rf artifacts/${BUNDLE_NAME}
|
||||||
tar czpf artifacts/flipper-z-${BUNDLE_NAME}.tgz -C artifacts ${BUNDLE_NAME}
|
done
|
||||||
rm -rf artifacts/${BUNDLE_NAME}
|
|
||||||
done
|
- name: "Check for uncommited changes"
|
||||||
|
run: |
|
||||||
|
git diff --exit-code
|
||||||
|
|
||||||
- name: 'Bundle resources'
|
- name: 'Bundle resources'
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
@ -113,29 +104,23 @@ jobs:
|
|||||||
|
|
||||||
- name: 'Bundle core2 firmware'
|
- name: 'Bundle core2 firmware'
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
uses: ./.github/actions/docker
|
run: |
|
||||||
with:
|
FBT_TOOLCHAIN_PATH=/opt ./fbt copro_dist
|
||||||
run: |
|
tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz -C assets core2_firmware
|
||||||
./fbt copro_dist
|
|
||||||
tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz -C assets core2_firmware
|
|
||||||
|
|
||||||
- name: 'Upload artifacts to update server'
|
- name: 'Upload artifacts to update server'
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
uses: burnett01/rsync-deployments@5.1
|
run: |
|
||||||
with:
|
echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key;
|
||||||
switches: -avzP --delete --mkpath
|
chmod 600 ./deploy_key;
|
||||||
path: artifacts/
|
rsync -avzP --mkpath \
|
||||||
remote_path: "${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/"
|
-e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \
|
||||||
remote_host: ${{ secrets.RSYNC_DEPLOY_HOST }}
|
artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/";
|
||||||
remote_port: ${{ secrets.RSYNC_DEPLOY_PORT }}
|
rm ./deploy_key;
|
||||||
remote_user: ${{ secrets.RSYNC_DEPLOY_USER }}
|
|
||||||
remote_key: ${{ secrets.RSYNC_DEPLOY_KEY }}
|
|
||||||
|
|
||||||
- name: 'Trigger update server reindex'
|
- name: 'Trigger update server reindex'
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
uses: wei/curl@master
|
run: curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
|
||||||
with:
|
|
||||||
args: -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
|
|
||||||
|
|
||||||
- name: 'Find Previous Comment'
|
- name: 'Find Previous Comment'
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }}
|
if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }}
|
||||||
@ -161,11 +146,8 @@ jobs:
|
|||||||
|
|
||||||
compact:
|
compact:
|
||||||
if: ${{ !startsWith(github.ref, 'refs/tags') }}
|
if: ${{ !startsWith(github.ref, 'refs/tags') }}
|
||||||
runs-on: [self-hosted,FlipperZero]
|
runs-on: [self-hosted,FlipperZeroShell]
|
||||||
steps:
|
steps:
|
||||||
- name: 'Cleanup workspace'
|
|
||||||
uses: AutoModality/action-clean@v1
|
|
||||||
|
|
||||||
- name: 'Decontaminate previous build leftovers'
|
- name: 'Decontaminate previous build leftovers'
|
||||||
run: |
|
run: |
|
||||||
if [ -d .git ]
|
if [ -d .git ]
|
||||||
@ -181,9 +163,6 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
- name: 'Build docker image'
|
|
||||||
uses: ./.github/actions/docker
|
|
||||||
|
|
||||||
- name: 'Generate suffix and folder name'
|
- name: 'Generate suffix and folder name'
|
||||||
id: names
|
id: names
|
||||||
run: |
|
run: |
|
||||||
@ -203,12 +182,10 @@ jobs:
|
|||||||
echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV
|
echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV
|
||||||
echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV
|
echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: 'Build the firmware in docker'
|
- name: 'Build the firmware'
|
||||||
uses: ./.github/actions/docker
|
run: |
|
||||||
with:
|
set -e
|
||||||
run: |
|
for TARGET in ${TARGETS}
|
||||||
set -e
|
do
|
||||||
for TARGET in ${TARGETS}
|
FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package DEBUG=0 COMPACT=1
|
||||||
do
|
done
|
||||||
./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package DEBUG=0 COMPACT=1
|
|
||||||
done
|
|
||||||
|
|||||||
46
.github/workflows/build_toolchain.yml
vendored
@ -1,46 +0,0 @@
|
|||||||
name: 'Build toolchain Docker image'
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v3
|
|
||||||
with:
|
|
||||||
images: flipperdevices/flipperzero-toolchain
|
|
||||||
flavor: latest=${{ startsWith(github.ref, 'refs/tags/') && !endsWith(github.ref, 'rc')}}
|
|
||||||
tags: |
|
|
||||||
type=ref,event=branch
|
|
||||||
type=ref,event=tag
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v1
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v1
|
|
||||||
- name: Login to DockerHub
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: Build and push
|
|
||||||
id: docker_build
|
|
||||||
uses: docker/build-push-action@v2
|
|
||||||
with:
|
|
||||||
context: docker/
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
cache-from: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache
|
|
||||||
cache-to: type=registry,ref=flipperdevices/flipperzero-toolchain:buildcache,mode=max
|
|
||||||
52
.github/workflows/check_submodules.yml
vendored
@ -1,17 +1,47 @@
|
|||||||
name: 'Check submodules'
|
name: 'Check submodules branch'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
- "release*"
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
protobuf:
|
check_protobuf:
|
||||||
runs-on: ubuntu-latest
|
runs-on: [self-hosted, FlipperZeroShell]
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout code'
|
- name: 'Decontaminate previous build leftovers'
|
||||||
uses: actions/checkout@v2
|
run: |
|
||||||
- name: 'Check submodule commit branch'
|
if [ -d .git ]
|
||||||
uses: jtmullen/submodule-branch-check-action@v1
|
then
|
||||||
with:
|
git submodule status \
|
||||||
path: assets/protobuf
|
|| git checkout `git rev-list --max-parents=0 HEAD | tail -n 1`
|
||||||
branch: dev
|
fi
|
||||||
fetch_depth: 50
|
|
||||||
|
- name: 'Checkout code'
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: 'Check protobuf branch'
|
||||||
|
run: |
|
||||||
|
SUB_PATH="assets/protobuf";
|
||||||
|
SUB_BRANCH="dev";
|
||||||
|
SUB_COMMITS_MIN=40;
|
||||||
|
cd "$SUB_PATH";
|
||||||
|
SUBMODULE_HASH="$(git rev-parse HEAD)";
|
||||||
|
BRANCHES=$(git branch -r --contains "$SUBMODULE_HASH");
|
||||||
|
COMMITS_IN_BRANCH="$(git rev-list --count dev)";
|
||||||
|
if [ $COMMITS_IN_BRANCH -lt $SUB_COMMITS_MIN ]; then
|
||||||
|
echo "::set-output name=fails::error";
|
||||||
|
echo "::error::Error: Too low commits in $SUB_BRANCH of submodule $SUB_PATH: $COMMITS_IN_BRANCH(expected $SUB_COMMITS_MIN+)";
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
if ! grep -q "/$SUB_BRANCH" <<< "$BRANCHES"; then
|
||||||
|
echo "::set-output name=fails::error";
|
||||||
|
echo "::error::Error: Submodule $SUB_PATH is not on branch $SUB_BRANCH";
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|||||||
24
.github/workflows/lint_c.yml
vendored
@ -1,6 +1,6 @@
|
|||||||
name: 'Lint C/C++ with clang-format'
|
name: 'Lint C/C++ with clang-format'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- dev
|
- dev
|
||||||
@ -14,11 +14,8 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint_c_cpp:
|
lint_c_cpp:
|
||||||
runs-on: [self-hosted,FlipperZero]
|
runs-on: [self-hosted,FlipperZeroShell]
|
||||||
steps:
|
steps:
|
||||||
- name: 'Cleanup workspace'
|
|
||||||
uses: AutoModality/action-clean@v1
|
|
||||||
|
|
||||||
- name: 'Decontaminate previous build leftovers'
|
- name: 'Decontaminate previous build leftovers'
|
||||||
run: |
|
run: |
|
||||||
if [ -d .git ]
|
if [ -d .git ]
|
||||||
@ -31,23 +28,10 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: true
|
|
||||||
|
|
||||||
- name: 'Docker cache'
|
|
||||||
uses: satackey/action-docker-layer-caching@v0.0.11
|
|
||||||
continue-on-error: true
|
|
||||||
with:
|
|
||||||
key: docker-cache-${{ hashFiles('docker/**') }}-{hash}
|
|
||||||
restore-keys: docker-cache-${{ hashFiles('docker/**') }}-
|
|
||||||
|
|
||||||
- name: 'Build docker image'
|
|
||||||
uses: ./.github/actions/docker
|
|
||||||
|
|
||||||
- name: 'Check code formatting'
|
- name: 'Check code formatting'
|
||||||
id: syntax_check
|
id: syntax_check
|
||||||
uses: ./.github/actions/docker
|
run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/opt ./fbt lint
|
||||||
with:
|
|
||||||
run: SET_GH_OUTPUT=1 ./fbt lint
|
|
||||||
|
|
||||||
- name: Report code formatting errors
|
- name: Report code formatting errors
|
||||||
if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request
|
if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request
|
||||||
@ -59,4 +43,4 @@ jobs:
|
|||||||
```
|
```
|
||||||
${{ steps.syntax_check.outputs.errors }}
|
${{ steps.syntax_check.outputs.errors }}
|
||||||
```
|
```
|
||||||
You might want to run `docker compose exec dev make format` for an auto-fix.
|
You might want to run `./fbt format` for an auto-fix.
|
||||||
|
|||||||
14
.github/workflows/lint_python.yml
vendored
@ -1,6 +1,6 @@
|
|||||||
name: 'Python Lint'
|
name: 'Python Lint'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- dev
|
- dev
|
||||||
@ -11,11 +11,8 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint_python:
|
lint_python:
|
||||||
runs-on: ubuntu-latest
|
runs-on: [self-hosted,FlipperZeroShell]
|
||||||
steps:
|
steps:
|
||||||
- name: 'Cleanup workspace'
|
|
||||||
uses: AutoModality/action-clean@v1
|
|
||||||
|
|
||||||
- name: 'Decontaminate previous build leftovers'
|
- name: 'Decontaminate previous build leftovers'
|
||||||
run: |
|
run: |
|
||||||
if [ -d .git ]
|
if [ -d .git ]
|
||||||
@ -29,8 +26,5 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: 'Setup python'
|
- name: 'Check code formatting'
|
||||||
uses: actions/setup-python@v2
|
run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/opt ./fbt lint_py
|
||||||
|
|
||||||
- name: 'Check python code with black'
|
|
||||||
uses: psf/black@20.8b1
|
|
||||||
|
|||||||
7
.github/workflows/reindex.yml
vendored
@ -7,9 +7,8 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
reindex:
|
reindex:
|
||||||
name: 'Reindex updates'
|
name: 'Reindex updates'
|
||||||
runs-on: [self-hosted,FlipperZero]
|
runs-on: [self-hosted,FlipperZeroShell]
|
||||||
steps:
|
steps:
|
||||||
- name: Trigger reindex
|
- name: Trigger reindex
|
||||||
uses: wei/curl@master
|
run: |
|
||||||
with:
|
curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
|
||||||
args: -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
|
|
||||||
|
|||||||
@ -29,11 +29,11 @@ They both must be flashed in the order described.
|
|||||||
|
|
||||||
With Flipper attached over USB:
|
With Flipper attached over USB:
|
||||||
|
|
||||||
`./fbt --with-updater flash_usb`
|
`./fbt flash_usb`
|
||||||
|
|
||||||
Just building the package:
|
Just building the package:
|
||||||
|
|
||||||
`./fbt --with-updater updater_package`
|
`./fbt updater_package`
|
||||||
|
|
||||||
To update, copy the resulting directory to Flipper's SD card and navigate to `update.fuf` file in Archive app.
|
To update, copy the resulting directory to Flipper's SD card and navigate to `update.fuf` file in Archive app.
|
||||||
|
|
||||||
|
|||||||
107
SConstruct
@ -7,6 +7,7 @@
|
|||||||
# construction of certain targets behind command-line options.
|
# construction of certain targets behind command-line options.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
EnsurePythonVersion(3, 8)
|
EnsurePythonVersion(3, 8)
|
||||||
|
|
||||||
@ -33,8 +34,10 @@ coreenv["ROOT_DIR"] = Dir(".")
|
|||||||
|
|
||||||
# Create a separate "dist" environment and add construction envs to it
|
# Create a separate "dist" environment and add construction envs to it
|
||||||
distenv = coreenv.Clone(
|
distenv = coreenv.Clone(
|
||||||
tools=["fbt_dist", "openocd", "blackmagic"],
|
tools=["fbt_dist", "openocd", "blackmagic", "jflash"],
|
||||||
OPENOCD_GDB_PIPE=["|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"],
|
OPENOCD_GDB_PIPE=[
|
||||||
|
"|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"
|
||||||
|
],
|
||||||
GDBOPTS_BASE=[
|
GDBOPTS_BASE=[
|
||||||
"-ex",
|
"-ex",
|
||||||
"target extended-remote ${GDBREMOTE}",
|
"target extended-remote ${GDBREMOTE}",
|
||||||
@ -61,6 +64,7 @@ distenv = coreenv.Clone(
|
|||||||
"-ex",
|
"-ex",
|
||||||
"compare-sections",
|
"compare-sections",
|
||||||
],
|
],
|
||||||
|
JFLASHPROJECT="${ROOT_DIR.abspath}/debug/fw.jflash",
|
||||||
ENV=os.environ,
|
ENV=os.environ,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -71,7 +75,9 @@ firmware_env = distenv.AddFwProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# If enabled, initialize updater-related targets
|
# If enabled, initialize updater-related targets
|
||||||
if GetOption("fullenv"):
|
if GetOption("fullenv") or any(
|
||||||
|
filter(lambda target: "updater" in target or "flash_usb" in target, BUILD_TARGETS)
|
||||||
|
):
|
||||||
updater_env = distenv.AddFwProject(
|
updater_env = distenv.AddFwProject(
|
||||||
base_env=coreenv,
|
base_env=coreenv,
|
||||||
fw_type="updater",
|
fw_type="updater",
|
||||||
@ -79,11 +85,11 @@ if GetOption("fullenv"):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Target for self-update package
|
# Target for self-update package
|
||||||
dist_arguments = [
|
dist_basic_arguments = [
|
||||||
"-r",
|
|
||||||
'"${ROOT_DIR.abspath}/assets/resources"',
|
|
||||||
"--bundlever",
|
"--bundlever",
|
||||||
'"${UPDATE_VERSION_STRING}"',
|
'"${UPDATE_VERSION_STRING}"',
|
||||||
|
]
|
||||||
|
dist_radio_arguments = [
|
||||||
"--radio",
|
"--radio",
|
||||||
'"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"',
|
'"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"',
|
||||||
"--radiotype",
|
"--radiotype",
|
||||||
@ -92,16 +98,34 @@ if GetOption("fullenv"):
|
|||||||
"--obdata",
|
"--obdata",
|
||||||
'"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"',
|
'"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"',
|
||||||
]
|
]
|
||||||
if distenv["UPDATE_SPLASH"]:
|
dist_resource_arguments = [
|
||||||
dist_arguments += [
|
"-r",
|
||||||
|
'"${ROOT_DIR.abspath}/assets/resources"',
|
||||||
|
]
|
||||||
|
dist_splash_arguments = (
|
||||||
|
[
|
||||||
"--splash",
|
"--splash",
|
||||||
distenv.subst("assets/slideshow/$UPDATE_SPLASH"),
|
distenv.subst("assets/slideshow/$UPDATE_SPLASH"),
|
||||||
]
|
]
|
||||||
|
if distenv["UPDATE_SPLASH"]
|
||||||
|
else []
|
||||||
|
)
|
||||||
|
|
||||||
selfupdate_dist = distenv.DistCommand(
|
selfupdate_dist = distenv.DistCommand(
|
||||||
"updater_package",
|
"updater_package",
|
||||||
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]),
|
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]),
|
||||||
DIST_EXTRA=dist_arguments,
|
DIST_EXTRA=[
|
||||||
|
*dist_basic_arguments,
|
||||||
|
*dist_radio_arguments,
|
||||||
|
*dist_resource_arguments,
|
||||||
|
*dist_splash_arguments,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
selfupdate_min_dist = distenv.DistCommand(
|
||||||
|
"updater_minpackage",
|
||||||
|
distenv["DIST_DEPENDS"],
|
||||||
|
DIST_EXTRA=dist_basic_arguments,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Updater debug
|
# Updater debug
|
||||||
@ -121,18 +145,16 @@ if GetOption("fullenv"):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Installation over USB & CLI
|
# Installation over USB & CLI
|
||||||
usb_update_package = distenv.UsbInstall(
|
usb_update_package = distenv.AddUsbFlashTarget(
|
||||||
"#build/usbinstall.flag",
|
"#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist)
|
||||||
(
|
|
||||||
distenv["DIST_DEPENDS"],
|
|
||||||
firmware_env["FW_RESOURCES"],
|
|
||||||
selfupdate_dist,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
if distenv["FORCE"]:
|
distenv.Alias("flash_usb_full", usb_update_package)
|
||||||
distenv.AlwaysBuild(usb_update_package)
|
|
||||||
distenv.Depends(usb_update_package, selfupdate_dist)
|
usb_minupdate_package = distenv.AddUsbFlashTarget(
|
||||||
distenv.Alias("flash_usb", usb_update_package)
|
"#build/minusbinstall.flag", (selfupdate_min_dist,)
|
||||||
|
)
|
||||||
|
distenv.Alias("flash_usb", usb_minupdate_package)
|
||||||
|
|
||||||
|
|
||||||
# Target for copying & renaming binaries to dist folder
|
# Target for copying & renaming binaries to dist folder
|
||||||
basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
|
basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
|
||||||
@ -147,8 +169,9 @@ distenv.Alias("copro_dist", copro_dist)
|
|||||||
|
|
||||||
firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env)
|
firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env)
|
||||||
distenv.Alias("flash", firmware_flash)
|
distenv.Alias("flash", firmware_flash)
|
||||||
if distenv["FORCE"]:
|
|
||||||
distenv.AlwaysBuild(firmware_flash)
|
firmware_jflash = distenv.AddJFlashTarget(firmware_env)
|
||||||
|
distenv.Alias("jflash", firmware_jflash)
|
||||||
|
|
||||||
firmware_bm_flash = distenv.PhonyTarget(
|
firmware_bm_flash = distenv.PhonyTarget(
|
||||||
"flash_blackmagic",
|
"flash_blackmagic",
|
||||||
@ -209,6 +232,46 @@ distenv.PhonyTarget(
|
|||||||
LINT_SOURCES=firmware_env["LINT_SOURCES"],
|
LINT_SOURCES=firmware_env["LINT_SOURCES"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# PY_LINT_SOURCES contains recursively-built modules' SConscript files + application manifests
|
||||||
|
# Here we add additional Python files residing in repo root
|
||||||
|
firmware_env.Append(
|
||||||
|
PY_LINT_SOURCES=[
|
||||||
|
# Py code folders
|
||||||
|
"site_scons",
|
||||||
|
"scripts",
|
||||||
|
# Extra files
|
||||||
|
"applications/extapps.scons",
|
||||||
|
"SConstruct",
|
||||||
|
"firmware.scons",
|
||||||
|
"fbt_options.py",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
black_commandline = "@${PYTHON3} -m black ${PY_BLACK_ARGS} ${PY_LINT_SOURCES}"
|
||||||
|
black_base_args = ["--include", '"\\.scons|\\.py|SConscript|SConstruct"']
|
||||||
|
|
||||||
|
distenv.PhonyTarget(
|
||||||
|
"lint_py",
|
||||||
|
black_commandline,
|
||||||
|
PY_BLACK_ARGS=[
|
||||||
|
"--check",
|
||||||
|
"--diff",
|
||||||
|
*black_base_args,
|
||||||
|
],
|
||||||
|
PY_LINT_SOURCES=firmware_env["PY_LINT_SOURCES"],
|
||||||
|
)
|
||||||
|
|
||||||
|
distenv.PhonyTarget(
|
||||||
|
"format_py",
|
||||||
|
black_commandline,
|
||||||
|
PY_BLACK_ARGS=black_base_args,
|
||||||
|
PY_LINT_SOURCES=firmware_env["PY_LINT_SOURCES"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Start Flipper CLI via PySerial's miniterm
|
||||||
|
distenv.PhonyTarget("cli", "${PYTHON3} scripts/serial_cli.py")
|
||||||
|
|
||||||
|
|
||||||
# Find blackmagic probe
|
# Find blackmagic probe
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,8 @@ appenv.AppendUnique(
|
|||||||
"-Wl,--no-export-dynamic",
|
"-Wl,--no-export-dynamic",
|
||||||
"-fvisibility=hidden",
|
"-fvisibility=hidden",
|
||||||
"-Wl,-e${APP_ENTRY}",
|
"-Wl,-e${APP_ENTRY}",
|
||||||
|
"-Xlinker",
|
||||||
|
"-Map=${TARGET}.map",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
#include "m-string.h"
|
#include "m-string.h"
|
||||||
#include <toolbox/path.h>
|
#include <toolbox/path.h>
|
||||||
#include <flipper_format/flipper_format.h>
|
#include <flipper_format/flipper_format.h>
|
||||||
#include "rpc/rpc_app.h"
|
#include <rpc/rpc_app.h>
|
||||||
|
|
||||||
#define TAG "iButtonApp"
|
#define TAG "iButtonApp"
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ static void ibutton_make_app_folder(iButton* ibutton) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog) {
|
bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog) {
|
||||||
FlipperFormat* file = flipper_format_file_alloc(ibutton->storage);
|
FlipperFormat* file = flipper_format_file_alloc(ibutton->storage);
|
||||||
bool result = false;
|
bool result = false;
|
||||||
string_t data;
|
string_t data;
|
||||||
@ -99,33 +99,20 @@ static bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ibutton_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
|
static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if(event == RpcAppEventSessionClose) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
view_dispatcher_send_custom_event(
|
||||||
ibutton->rpc_ctx = NULL;
|
ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose);
|
||||||
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
|
|
||||||
result = true;
|
|
||||||
} else if(event == RpcAppEventAppExit) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
|
||||||
result = true;
|
|
||||||
} else if(event == RpcAppEventLoadFile) {
|
} else if(event == RpcAppEventLoadFile) {
|
||||||
if(arg) {
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoad);
|
||||||
string_set_str(ibutton->file_path, arg);
|
} else {
|
||||||
if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) {
|
rpc_system_app_confirm(ibutton->rpc_ctx, event, false);
|
||||||
ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key);
|
|
||||||
view_dispatcher_send_custom_event(
|
|
||||||
ibutton->view_dispatcher, iButtonCustomEventRpcLoad);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_custom_event_callback(void* context, uint32_t event) {
|
bool ibutton_custom_event_callback(void* context, uint32_t event) {
|
||||||
|
|||||||
@ -12,4 +12,5 @@ enum iButtonCustomEvent {
|
|||||||
|
|
||||||
iButtonCustomEventRpcLoad,
|
iButtonCustomEventRpcLoad,
|
||||||
iButtonCustomEventRpcExit,
|
iButtonCustomEventRpcExit,
|
||||||
|
iButtonCustomEventRpcSessionClose,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -78,6 +78,7 @@ typedef enum {
|
|||||||
} iButtonNotificationMessage;
|
} iButtonNotificationMessage;
|
||||||
|
|
||||||
bool ibutton_file_select(iButton* ibutton);
|
bool ibutton_file_select(iButton* ibutton);
|
||||||
|
bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog);
|
||||||
bool ibutton_save_key(iButton* ibutton, const char* key_name);
|
bool ibutton_save_key(iButton* ibutton, const char* key_name);
|
||||||
bool ibutton_delete_key(iButton* ibutton);
|
bool ibutton_delete_key(iButton* ibutton);
|
||||||
void ibutton_text_store_set(iButton* ibutton, const char* text, ...);
|
void ibutton_text_store_set(iButton* ibutton, const char* text, ...);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "../ibutton_i.h"
|
#include "../ibutton_i.h"
|
||||||
#include <toolbox/path.h>
|
#include <toolbox/path.h>
|
||||||
|
#include <rpc/rpc_app.h>
|
||||||
|
|
||||||
void ibutton_scene_rpc_on_enter(void* context) {
|
void ibutton_scene_rpc_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
@ -26,23 +27,40 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == iButtonCustomEventRpcLoad) {
|
if(event.event == iButtonCustomEventRpcLoad) {
|
||||||
string_t key_name;
|
const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx);
|
||||||
string_init(key_name);
|
bool result = false;
|
||||||
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
|
if(arg) {
|
||||||
path_extract_filename(ibutton->file_path, key_name, true);
|
string_set_str(ibutton->file_path, arg);
|
||||||
|
if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) {
|
||||||
|
ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key);
|
||||||
|
string_t key_name;
|
||||||
|
string_init(key_name);
|
||||||
|
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
|
||||||
|
path_extract_filename(ibutton->file_path, key_name, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!string_empty_p(key_name)) {
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton, "emulating\n%s", string_get_cstr(key_name));
|
||||||
|
} else {
|
||||||
|
ibutton_text_store_set(ibutton, "emulating");
|
||||||
|
}
|
||||||
|
popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop);
|
||||||
|
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
|
||||||
|
|
||||||
|
string_clear(key_name);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result);
|
||||||
if(!string_empty_p(key_name)) {
|
|
||||||
ibutton_text_store_set(ibutton, "emulating\n%s", string_get_cstr(key_name));
|
|
||||||
} else {
|
|
||||||
ibutton_text_store_set(ibutton, "emulating");
|
|
||||||
}
|
|
||||||
popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop);
|
|
||||||
|
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
|
|
||||||
|
|
||||||
string_clear(key_name);
|
|
||||||
} else if(event.event == iButtonCustomEventRpcExit) {
|
} else if(event.event == iButtonCustomEventRpcExit) {
|
||||||
|
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventAppExit, true);
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
||||||
|
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||||
|
} else if(event.event == iButtonCustomEventRpcSessionClose) {
|
||||||
|
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
||||||
|
ibutton->rpc_ctx = NULL;
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
||||||
view_dispatcher_stop(ibutton->view_dispatcher);
|
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,52 +36,29 @@ static void infrared_tick_event_callback(void* context) {
|
|||||||
scene_manager_handle_tick_event(infrared->scene_manager);
|
scene_manager_handle_tick_event(infrared->scene_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
||||||
infrared_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
Infrared* infrared = context;
|
Infrared* infrared = context;
|
||||||
|
furi_assert(infrared->rpc_ctx);
|
||||||
if(!infrared->rpc_ctx) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if(event == RpcAppEventSessionClose) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
|
|
||||||
infrared->rpc_ctx = NULL;
|
|
||||||
view_dispatcher_send_custom_event(
|
view_dispatcher_send_custom_event(
|
||||||
infrared->view_dispatcher, InfraredCustomEventTypeBackPressed);
|
infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose);
|
||||||
result = true;
|
|
||||||
} else if(event == RpcAppEventAppExit) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
view_dispatcher_send_custom_event(
|
view_dispatcher_send_custom_event(
|
||||||
infrared->view_dispatcher, InfraredCustomEventTypeBackPressed);
|
infrared->view_dispatcher, InfraredCustomEventTypeRpcExit);
|
||||||
result = true;
|
|
||||||
} else if(event == RpcAppEventLoadFile) {
|
} else if(event == RpcAppEventLoadFile) {
|
||||||
if(arg) {
|
view_dispatcher_send_custom_event(
|
||||||
string_set_str(infrared->file_path, arg);
|
infrared->view_dispatcher, InfraredCustomEventTypeRpcLoad);
|
||||||
result = infrared_remote_load(infrared->remote, infrared->file_path);
|
|
||||||
infrared_worker_tx_set_get_signal_callback(
|
|
||||||
infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
|
|
||||||
infrared_worker_tx_set_signal_sent_callback(
|
|
||||||
infrared->worker, infrared_signal_sent_callback, infrared);
|
|
||||||
view_dispatcher_send_custom_event(
|
|
||||||
infrared->view_dispatcher, InfraredCustomEventTypeRpcLoaded);
|
|
||||||
}
|
|
||||||
} else if(event == RpcAppEventButtonPress) {
|
} else if(event == RpcAppEventButtonPress) {
|
||||||
if(arg) {
|
view_dispatcher_send_custom_event(
|
||||||
size_t button_index = 0;
|
infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPress);
|
||||||
if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) {
|
|
||||||
infrared_tx_start_button_index(infrared, button_index);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(event == RpcAppEventButtonRelease) {
|
} else if(event == RpcAppEventButtonRelease) {
|
||||||
infrared_tx_stop(infrared);
|
view_dispatcher_send_custom_event(
|
||||||
result = true;
|
infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonRelease);
|
||||||
|
} else {
|
||||||
|
rpc_system_app_confirm(infrared->rpc_ctx, event, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void infrared_find_vacant_remote_name(string_t name, const char* path) {
|
static void infrared_find_vacant_remote_name(string_t name, const char* path) {
|
||||||
|
|||||||
@ -14,7 +14,12 @@ enum InfraredCustomEventType {
|
|||||||
InfraredCustomEventTypePopupClosed,
|
InfraredCustomEventTypePopupClosed,
|
||||||
InfraredCustomEventTypeButtonSelected,
|
InfraredCustomEventTypeButtonSelected,
|
||||||
InfraredCustomEventTypeBackPressed,
|
InfraredCustomEventTypeBackPressed,
|
||||||
InfraredCustomEventTypeRpcLoaded,
|
|
||||||
|
InfraredCustomEventTypeRpcLoad,
|
||||||
|
InfraredCustomEventTypeRpcExit,
|
||||||
|
InfraredCustomEventTypeRpcButtonPress,
|
||||||
|
InfraredCustomEventTypeRpcButtonRelease,
|
||||||
|
InfraredCustomEventTypeRpcSessionClose,
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|||||||
@ -28,12 +28,45 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
view_dispatcher_stop(infrared->view_dispatcher);
|
view_dispatcher_stop(infrared->view_dispatcher);
|
||||||
} else if(event.event == InfraredCustomEventTypePopupClosed) {
|
} else if(event.event == InfraredCustomEventTypePopupClosed) {
|
||||||
view_dispatcher_stop(infrared->view_dispatcher);
|
view_dispatcher_stop(infrared->view_dispatcher);
|
||||||
} else if(event.event == InfraredCustomEventTypeRpcLoaded) {
|
} else if(event.event == InfraredCustomEventTypeRpcLoad) {
|
||||||
|
bool result = false;
|
||||||
|
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
||||||
|
if(arg) {
|
||||||
|
string_set_str(infrared->file_path, arg);
|
||||||
|
result = infrared_remote_load(infrared->remote, infrared->file_path);
|
||||||
|
infrared_worker_tx_set_get_signal_callback(
|
||||||
|
infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
|
||||||
|
infrared_worker_tx_set_signal_sent_callback(
|
||||||
|
infrared->worker, infrared_signal_sent_callback, infrared);
|
||||||
|
}
|
||||||
const char* remote_name = infrared_remote_get_name(infrared->remote);
|
const char* remote_name = infrared_remote_get_name(infrared->remote);
|
||||||
|
|
||||||
infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name);
|
infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name);
|
||||||
popup_set_text(
|
popup_set_text(
|
||||||
infrared->popup, infrared->text_store[0], 82, 32, AlignCenter, AlignTop);
|
infrared->popup, infrared->text_store[0], 82, 32, AlignCenter, AlignTop);
|
||||||
|
|
||||||
|
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventLoadFile, result);
|
||||||
|
} else if(event.event == InfraredCustomEventTypeRpcButtonPress) {
|
||||||
|
bool result = false;
|
||||||
|
const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
|
||||||
|
if(arg) {
|
||||||
|
size_t button_index = 0;
|
||||||
|
if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) {
|
||||||
|
infrared_tx_start_button_index(infrared, button_index);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result);
|
||||||
|
} else if(event.event == InfraredCustomEventTypeRpcButtonRelease) {
|
||||||
|
infrared_tx_stop(infrared);
|
||||||
|
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, true);
|
||||||
|
} else if(event.event == InfraredCustomEventTypeRpcExit) {
|
||||||
|
view_dispatcher_stop(infrared->view_dispatcher);
|
||||||
|
rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventAppExit, true);
|
||||||
|
} else if(event.event == InfraredCustomEventTypeRpcSessionClose) {
|
||||||
|
rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
|
||||||
|
infrared->rpc_ctx = NULL;
|
||||||
|
view_dispatcher_stop(infrared->view_dispatcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
#include <toolbox/path.h>
|
#include <toolbox/path.h>
|
||||||
#include <flipper_format/flipper_format.h>
|
#include <flipper_format/flipper_format.h>
|
||||||
|
|
||||||
#include "rpc/rpc_app.h"
|
#include <rpc/rpc_app.h>
|
||||||
|
|
||||||
const char* LfRfidApp::app_folder = ANY_PATH("lfrfid");
|
const char* LfRfidApp::app_folder = ANY_PATH("lfrfid");
|
||||||
const char* LfRfidApp::app_extension = ".rfid";
|
const char* LfRfidApp::app_extension = ".rfid";
|
||||||
@ -48,38 +48,25 @@ LfRfidApp::~LfRfidApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
|
static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||||
|
|
||||||
bool result = false;
|
if(rpc_event == RpcAppEventSessionClose) {
|
||||||
|
LfRfidApp::Event event;
|
||||||
if(event == RpcAppEventSessionClose) {
|
event.type = LfRfidApp::EventType::RpcSessionClose;
|
||||||
rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
|
app->view_controller.send_event(&event);
|
||||||
app->rpc_ctx = NULL;
|
} else if(rpc_event == RpcAppEventAppExit) {
|
||||||
LfRfidApp::Event event;
|
LfRfidApp::Event event;
|
||||||
event.type = LfRfidApp::EventType::Exit;
|
event.type = LfRfidApp::EventType::Exit;
|
||||||
app->view_controller.send_event(&event);
|
app->view_controller.send_event(&event);
|
||||||
result = true;
|
} else if(rpc_event == RpcAppEventLoadFile) {
|
||||||
} else if(event == RpcAppEventAppExit) {
|
|
||||||
LfRfidApp::Event event;
|
LfRfidApp::Event event;
|
||||||
event.type = LfRfidApp::EventType::Exit;
|
event.type = LfRfidApp::EventType::RpcLoadFile;
|
||||||
app->view_controller.send_event(&event);
|
app->view_controller.send_event(&event);
|
||||||
result = true;
|
} else {
|
||||||
} else if(event == RpcAppEventLoadFile) {
|
rpc_system_app_confirm(app->rpc_ctx, rpc_event, false);
|
||||||
if(arg) {
|
|
||||||
string_set_str(app->file_path, arg);
|
|
||||||
if(app->load_key_data(app->file_path, &(app->worker.key), false)) {
|
|
||||||
LfRfidApp::Event event;
|
|
||||||
event.type = LfRfidApp::EventType::EmulateStart;
|
|
||||||
app->view_controller.send_event(&event);
|
|
||||||
app->worker.start_emulate();
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LfRfidApp::run(void* _args) {
|
void LfRfidApp::run(void* _args) {
|
||||||
|
|||||||
@ -33,6 +33,8 @@ public:
|
|||||||
Retry,
|
Retry,
|
||||||
Exit,
|
Exit,
|
||||||
EmulateStart,
|
EmulateStart,
|
||||||
|
RpcLoadFile,
|
||||||
|
RpcSessionClose,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SceneType : uint8_t {
|
enum class SceneType : uint8_t {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "lfrfid_app_scene_rpc.h"
|
#include "lfrfid_app_scene_rpc.h"
|
||||||
#include <core/common_defines.h>
|
#include <core/common_defines.h>
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
#include <rpc/rpc_app.h>
|
||||||
|
|
||||||
static const NotificationSequence sequence_blink_start_magenta = {
|
static const NotificationSequence sequence_blink_start_magenta = {
|
||||||
&message_blink_start_10,
|
&message_blink_start_10,
|
||||||
@ -36,6 +37,16 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
|||||||
LfRfidApp::Event view_event;
|
LfRfidApp::Event view_event;
|
||||||
view_event.type = LfRfidApp::EventType::Back;
|
view_event.type = LfRfidApp::EventType::Back;
|
||||||
app->view_controller.send_event(&view_event);
|
app->view_controller.send_event(&view_event);
|
||||||
|
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
|
||||||
|
} else if(event->type == LfRfidApp::EventType::RpcSessionClose) {
|
||||||
|
// Detach RPC
|
||||||
|
rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
|
||||||
|
app->rpc_ctx = NULL;
|
||||||
|
|
||||||
|
consumed = true;
|
||||||
|
LfRfidApp::Event view_event;
|
||||||
|
view_event.type = LfRfidApp::EventType::Back;
|
||||||
|
app->view_controller.send_event(&view_event);
|
||||||
} else if(event->type == LfRfidApp::EventType::EmulateStart) {
|
} else if(event->type == LfRfidApp::EventType::EmulateStart) {
|
||||||
auto popup = app->view_controller.get<PopupVM>();
|
auto popup = app->view_controller.get<PopupVM>();
|
||||||
consumed = true;
|
consumed = true;
|
||||||
@ -45,7 +56,22 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
|||||||
popup->set_text(app->text_store.text, 89, 43, AlignCenter, AlignTop);
|
popup->set_text(app->text_store.text, 89, 43, AlignCenter, AlignTop);
|
||||||
|
|
||||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||||
|
} else if(event->type == LfRfidApp::EventType::RpcLoadFile) {
|
||||||
|
const char* arg = rpc_system_app_get_data(app->rpc_ctx);
|
||||||
|
bool result = false;
|
||||||
|
if(arg) {
|
||||||
|
string_set_str(app->file_path, arg);
|
||||||
|
if(app->load_key_data(app->file_path, &(app->worker.key), false)) {
|
||||||
|
LfRfidApp::Event event;
|
||||||
|
event.type = LfRfidApp::EventType::EmulateStart;
|
||||||
|
app->view_controller.send_event(&event);
|
||||||
|
app->worker.start_emulate();
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,4 +11,5 @@ enum NfcCustomEvent {
|
|||||||
NfcCustomEventDictAttackDone,
|
NfcCustomEventDictAttackDone,
|
||||||
NfcCustomEventDictAttackSkip,
|
NfcCustomEventDictAttackSkip,
|
||||||
NfcCustomEventRpcLoad,
|
NfcCustomEventRpcLoad,
|
||||||
|
NfcCustomEventRpcSessionClose,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,78 +13,21 @@ bool nfc_back_event_callback(void* context) {
|
|||||||
return scene_manager_handle_back_event(nfc->scene_manager);
|
return scene_manager_handle_back_event(nfc->scene_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfc_rpc_exit_callback(Nfc* nfc) {
|
static void nfc_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
||||||
if(nfc->rpc_state == NfcRpcStateEmulating) {
|
|
||||||
// Stop worker
|
|
||||||
nfc_worker_stop(nfc->worker);
|
|
||||||
} else if(nfc->rpc_state == NfcRpcStateEmulated) {
|
|
||||||
// Stop worker
|
|
||||||
nfc_worker_stop(nfc->worker);
|
|
||||||
// Save data in shadow file
|
|
||||||
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
|
|
||||||
}
|
|
||||||
if(nfc->rpc_ctx) {
|
|
||||||
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
|
|
||||||
rpc_system_app_send_exited(nfc->rpc_ctx);
|
|
||||||
nfc->rpc_ctx = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool nfc_rpc_emulate_callback(NfcWorkerEvent event, void* context) {
|
|
||||||
UNUSED(event);
|
|
||||||
Nfc* nfc = context;
|
|
||||||
|
|
||||||
nfc->rpc_state = NfcRpcStateEmulated;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool nfc_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
|
|
||||||
if(!nfc->rpc_ctx) {
|
furi_assert(nfc->rpc_ctx);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if(event == RpcAppEventSessionClose) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcSessionClose);
|
||||||
nfc->rpc_ctx = NULL;
|
|
||||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
|
||||||
result = true;
|
|
||||||
} else if(event == RpcAppEventAppExit) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||||
result = true;
|
|
||||||
} else if(event == RpcAppEventLoadFile) {
|
} else if(event == RpcAppEventLoadFile) {
|
||||||
if((arg) && (nfc->rpc_state == NfcRpcStateIdle)) {
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad);
|
||||||
if(nfc_device_load(nfc->dev, arg, false)) {
|
} else {
|
||||||
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
rpc_system_app_confirm(nfc->rpc_ctx, event, false);
|
||||||
nfc_worker_start(
|
|
||||||
nfc->worker,
|
|
||||||
NfcWorkerStateMfUltralightEmulate,
|
|
||||||
&nfc->dev->dev_data,
|
|
||||||
nfc_rpc_emulate_callback,
|
|
||||||
nfc);
|
|
||||||
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
|
|
||||||
nfc_worker_start(
|
|
||||||
nfc->worker,
|
|
||||||
NfcWorkerStateMfClassicEmulate,
|
|
||||||
&nfc->dev->dev_data,
|
|
||||||
nfc_rpc_emulate_callback,
|
|
||||||
nfc);
|
|
||||||
} else {
|
|
||||||
nfc_worker_start(
|
|
||||||
nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc);
|
|
||||||
}
|
|
||||||
nfc->rpc_state = NfcRpcStateEmulating;
|
|
||||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Nfc* nfc_alloc() {
|
Nfc* nfc_alloc() {
|
||||||
@ -163,6 +106,21 @@ Nfc* nfc_alloc() {
|
|||||||
void nfc_free(Nfc* nfc) {
|
void nfc_free(Nfc* nfc) {
|
||||||
furi_assert(nfc);
|
furi_assert(nfc);
|
||||||
|
|
||||||
|
if(nfc->rpc_state == NfcRpcStateEmulating) {
|
||||||
|
// Stop worker
|
||||||
|
nfc_worker_stop(nfc->worker);
|
||||||
|
} else if(nfc->rpc_state == NfcRpcStateEmulated) {
|
||||||
|
// Stop worker
|
||||||
|
nfc_worker_stop(nfc->worker);
|
||||||
|
// Save data in shadow file
|
||||||
|
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
|
||||||
|
}
|
||||||
|
if(nfc->rpc_ctx) {
|
||||||
|
rpc_system_app_send_exited(nfc->rpc_ctx);
|
||||||
|
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
|
||||||
|
nfc->rpc_ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Nfc device
|
// Nfc device
|
||||||
nfc_device_free(nfc->dev);
|
nfc_device_free(nfc->dev);
|
||||||
|
|
||||||
|
|||||||
@ -102,5 +102,3 @@ void nfc_blink_start(Nfc* nfc);
|
|||||||
void nfc_blink_stop(Nfc* nfc);
|
void nfc_blink_stop(Nfc* nfc);
|
||||||
|
|
||||||
void nfc_show_loading_popup(void* context, bool show);
|
void nfc_show_loading_popup(void* context, bool show);
|
||||||
|
|
||||||
void nfc_rpc_exit_callback(Nfc* nfc);
|
|
||||||
|
|||||||
@ -14,6 +14,14 @@ void nfc_scene_rpc_on_enter(void* context) {
|
|||||||
notification_message(nfc->notifications, &sequence_display_backlight_on);
|
notification_message(nfc->notifications, &sequence_display_backlight_on);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool nfc_scene_rpc_emulate_callback(NfcWorkerEvent event, void* context) {
|
||||||
|
UNUSED(event);
|
||||||
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
nfc->rpc_state = NfcRpcStateEmulated;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
Popup* popup = nfc->popup;
|
Popup* popup = nfc->popup;
|
||||||
@ -22,13 +30,47 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == NfcCustomEventViewExit) {
|
if(event.event == NfcCustomEventViewExit) {
|
||||||
|
rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventAppExit, true);
|
||||||
|
view_dispatcher_stop(nfc->view_dispatcher);
|
||||||
|
nfc_blink_stop(nfc);
|
||||||
|
} else if(event.event == NfcCustomEventRpcSessionClose) {
|
||||||
|
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
|
||||||
|
nfc->rpc_ctx = NULL;
|
||||||
view_dispatcher_stop(nfc->view_dispatcher);
|
view_dispatcher_stop(nfc->view_dispatcher);
|
||||||
nfc_blink_stop(nfc);
|
nfc_blink_stop(nfc);
|
||||||
} else if(event.event == NfcCustomEventRpcLoad) {
|
} else if(event.event == NfcCustomEventRpcLoad) {
|
||||||
nfc_blink_start(nfc);
|
bool result = false;
|
||||||
|
const char* arg = rpc_system_app_get_data(nfc->rpc_ctx);
|
||||||
|
if((arg) && (nfc->rpc_state == NfcRpcStateIdle)) {
|
||||||
|
if(nfc_device_load(nfc->dev, arg, false)) {
|
||||||
|
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
|
||||||
|
nfc_worker_start(
|
||||||
|
nfc->worker,
|
||||||
|
NfcWorkerStateMfUltralightEmulate,
|
||||||
|
&nfc->dev->dev_data,
|
||||||
|
nfc_scene_rpc_emulate_callback,
|
||||||
|
nfc);
|
||||||
|
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||||
|
nfc_worker_start(
|
||||||
|
nfc->worker,
|
||||||
|
NfcWorkerStateMfClassicEmulate,
|
||||||
|
&nfc->dev->dev_data,
|
||||||
|
nfc_scene_rpc_emulate_callback,
|
||||||
|
nfc);
|
||||||
|
} else {
|
||||||
|
nfc_worker_start(
|
||||||
|
nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc);
|
||||||
|
}
|
||||||
|
nfc->rpc_state = NfcRpcStateEmulating;
|
||||||
|
result = true;
|
||||||
|
|
||||||
nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name);
|
nfc_blink_start(nfc);
|
||||||
popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop);
|
nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name);
|
||||||
|
popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventLoadFile, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
@ -38,7 +80,6 @@ void nfc_scene_rpc_on_exit(void* context) {
|
|||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
Popup* popup = nfc->popup;
|
Popup* popup = nfc->popup;
|
||||||
|
|
||||||
nfc_rpc_exit_callback(nfc);
|
|
||||||
nfc_blink_stop(nfc);
|
nfc_blink_stop(nfc);
|
||||||
|
|
||||||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
||||||
|
|||||||
@ -6,24 +6,18 @@
|
|||||||
#include "rpc_app.h"
|
#include "rpc_app.h"
|
||||||
|
|
||||||
#define TAG "RpcSystemApp"
|
#define TAG "RpcSystemApp"
|
||||||
#define APP_BUTTON_TIMEOUT 1000
|
|
||||||
|
|
||||||
struct RpcAppSystem {
|
struct RpcAppSystem {
|
||||||
RpcSession* session;
|
RpcSession* session;
|
||||||
RpcAppSystemCallback app_callback;
|
RpcAppSystemCallback app_callback;
|
||||||
void* app_context;
|
void* app_context;
|
||||||
PB_Main* state_msg;
|
PB_Main* state_msg;
|
||||||
FuriTimer* timer;
|
|
||||||
|
uint32_t last_id;
|
||||||
|
char* last_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void rpc_system_app_timer_callback(void* context) {
|
#define RPC_SYSTEM_APP_TEMP_ARGS_SIZE 16
|
||||||
furi_assert(context);
|
|
||||||
RpcAppSystem* rpc_app = context;
|
|
||||||
|
|
||||||
if(rpc_app->app_callback) {
|
|
||||||
rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rpc_system_app_start_process(const PB_Main* request, void* context) {
|
static void rpc_system_app_start_process(const PB_Main* request, void* context) {
|
||||||
furi_assert(request);
|
furi_assert(request);
|
||||||
@ -33,9 +27,12 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
|
|||||||
RpcAppSystem* rpc_app = context;
|
RpcAppSystem* rpc_app = context;
|
||||||
RpcSession* session = rpc_app->session;
|
RpcSession* session = rpc_app->session;
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
char args_temp[16];
|
char args_temp[RPC_SYSTEM_APP_TEMP_ARGS_SIZE];
|
||||||
|
|
||||||
FURI_LOG_D(TAG, "Start");
|
furi_assert(!rpc_app->last_id);
|
||||||
|
furi_assert(!rpc_app->last_data);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "StartProcess: id %d", request->command_id);
|
||||||
|
|
||||||
PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START;
|
PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START;
|
||||||
|
|
||||||
@ -43,9 +40,9 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
|
|||||||
const char* app_name = request->content.app_start_request.name;
|
const char* app_name = request->content.app_start_request.name;
|
||||||
if(app_name) {
|
if(app_name) {
|
||||||
const char* app_args = request->content.app_start_request.args;
|
const char* app_args = request->content.app_start_request.args;
|
||||||
if(strcmp(app_args, "RPC") == 0) {
|
if(app_args && strcmp(app_args, "RPC") == 0) {
|
||||||
// If app is being started in RPC mode - pass RPC context via args string
|
// If app is being started in RPC mode - pass RPC context via args string
|
||||||
snprintf(args_temp, 16, "RPC %08lX", (uint32_t)rpc_app);
|
snprintf(args_temp, RPC_SYSTEM_APP_TEMP_ARGS_SIZE, "RPC %08lX", (uint32_t)rpc_app);
|
||||||
app_args = args_temp;
|
app_args = args_temp;
|
||||||
}
|
}
|
||||||
LoaderStatus status = loader_start(loader, app_name, app_args);
|
LoaderStatus status = loader_start(loader, app_name, app_args);
|
||||||
@ -58,7 +55,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
|
|||||||
} else if(status == LoaderStatusOk) {
|
} else if(status == LoaderStatusOk) {
|
||||||
result = PB_CommandStatus_OK;
|
result = PB_CommandStatus_OK;
|
||||||
} else {
|
} else {
|
||||||
furi_assert(0);
|
furi_crash("Programming Error");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
result = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
||||||
@ -66,6 +63,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
|
|||||||
|
|
||||||
furi_record_close(RECORD_LOADER);
|
furi_record_close(RECORD_LOADER);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "StartProcess: response id %d, result %d", request->command_id, result);
|
||||||
rpc_send_and_release_empty(session, request->command_id, result);
|
rpc_send_and_release_empty(session, request->command_id, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +91,7 @@ static void rpc_system_app_lock_status_process(const PB_Main* request, void* con
|
|||||||
|
|
||||||
furi_record_close(RECORD_LOADER);
|
furi_record_close(RECORD_LOADER);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "LockStatus: response");
|
||||||
rpc_send_and_release(session, &response);
|
rpc_send_and_release(session, &response);
|
||||||
pb_release(&PB_Main_msg, &response);
|
pb_release(&PB_Main_msg, &response);
|
||||||
}
|
}
|
||||||
@ -109,17 +108,17 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) {
|
|||||||
PB_CommandStatus status;
|
PB_CommandStatus status;
|
||||||
|
|
||||||
if(rpc_app->app_callback) {
|
if(rpc_app->app_callback) {
|
||||||
if(rpc_app->app_callback(RpcAppEventAppExit, NULL, rpc_app->app_context)) {
|
FURI_LOG_D(TAG, "ExitRequest: id %d", request->command_id);
|
||||||
status = PB_CommandStatus_OK;
|
furi_assert(!rpc_app->last_id);
|
||||||
furi_timer_stop(rpc_app->timer);
|
furi_assert(!rpc_app->last_data);
|
||||||
} else {
|
rpc_app->last_id = request->command_id;
|
||||||
status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
|
rpc_app->app_callback(RpcAppEventAppExit, rpc_app->app_context);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
||||||
|
FURI_LOG_E(
|
||||||
|
TAG, "ExitRequest: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
|
||||||
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_app_load_file(const PB_Main* request, void* context) {
|
static void rpc_system_app_load_file(const PB_Main* request, void* context) {
|
||||||
@ -133,17 +132,18 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) {
|
|||||||
|
|
||||||
PB_CommandStatus status;
|
PB_CommandStatus status;
|
||||||
if(rpc_app->app_callback) {
|
if(rpc_app->app_callback) {
|
||||||
const char* file_path = request->content.app_load_file_request.path;
|
FURI_LOG_D(TAG, "LoadFile: id %d", request->command_id);
|
||||||
if(rpc_app->app_callback(RpcAppEventLoadFile, file_path, rpc_app->app_context)) {
|
furi_assert(!rpc_app->last_id);
|
||||||
status = PB_CommandStatus_OK;
|
furi_assert(!rpc_app->last_data);
|
||||||
} else {
|
rpc_app->last_id = request->command_id;
|
||||||
status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
|
rpc_app->last_data = strdup(request->content.app_load_file_request.path);
|
||||||
}
|
rpc_app->app_callback(RpcAppEventLoadFile, rpc_app->app_context);
|
||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
||||||
|
FURI_LOG_E(
|
||||||
|
TAG, "LoadFile: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
|
||||||
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_app_button_press(const PB_Main* request, void* context) {
|
static void rpc_system_app_button_press(const PB_Main* request, void* context) {
|
||||||
@ -157,18 +157,18 @@ static void rpc_system_app_button_press(const PB_Main* request, void* context) {
|
|||||||
|
|
||||||
PB_CommandStatus status;
|
PB_CommandStatus status;
|
||||||
if(rpc_app->app_callback) {
|
if(rpc_app->app_callback) {
|
||||||
const char* args = request->content.app_button_press_request.args;
|
FURI_LOG_D(TAG, "ButtonPress");
|
||||||
if(rpc_app->app_callback(RpcAppEventButtonPress, args, rpc_app->app_context)) {
|
furi_assert(!rpc_app->last_id);
|
||||||
status = PB_CommandStatus_OK;
|
furi_assert(!rpc_app->last_data);
|
||||||
furi_timer_start(rpc_app->timer, APP_BUTTON_TIMEOUT);
|
rpc_app->last_id = request->command_id;
|
||||||
} else {
|
rpc_app->last_data = strdup(request->content.app_button_press_request.args);
|
||||||
status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
|
rpc_app->app_callback(RpcAppEventButtonPress, rpc_app->app_context);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
||||||
|
FURI_LOG_E(
|
||||||
|
TAG, "ButtonPress: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
|
||||||
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_app_button_release(const PB_Main* request, void* context) {
|
static void rpc_system_app_button_release(const PB_Main* request, void* context) {
|
||||||
@ -182,17 +182,17 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context)
|
|||||||
|
|
||||||
PB_CommandStatus status;
|
PB_CommandStatus status;
|
||||||
if(rpc_app->app_callback) {
|
if(rpc_app->app_callback) {
|
||||||
if(rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context)) {
|
FURI_LOG_D(TAG, "ButtonRelease");
|
||||||
status = PB_CommandStatus_OK;
|
furi_assert(!rpc_app->last_id);
|
||||||
furi_timer_stop(rpc_app->timer);
|
furi_assert(!rpc_app->last_data);
|
||||||
} else {
|
rpc_app->last_id = request->command_id;
|
||||||
status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
|
rpc_app->app_callback(RpcAppEventButtonRelease, rpc_app->app_context);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
|
||||||
|
FURI_LOG_E(
|
||||||
|
TAG, "ButtonRelease: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
|
||||||
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpc_system_app_send_started(RpcAppSystem* rpc_app) {
|
void rpc_system_app_send_started(RpcAppSystem* rpc_app) {
|
||||||
@ -201,6 +201,8 @@ void rpc_system_app_send_started(RpcAppSystem* rpc_app) {
|
|||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_STARTED;
|
rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_STARTED;
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "SendStarted");
|
||||||
rpc_send(session, rpc_app->state_msg);
|
rpc_send(session, rpc_app->state_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,9 +212,46 @@ void rpc_system_app_send_exited(RpcAppSystem* rpc_app) {
|
|||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_CLOSED;
|
rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_CLOSED;
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "SendExit");
|
||||||
rpc_send(session, rpc_app->state_msg);
|
rpc_send(session, rpc_app->state_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* rpc_system_app_get_data(RpcAppSystem* rpc_app) {
|
||||||
|
furi_assert(rpc_app);
|
||||||
|
furi_assert(rpc_app->last_data);
|
||||||
|
return rpc_app->last_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result) {
|
||||||
|
furi_assert(rpc_app);
|
||||||
|
RpcSession* session = rpc_app->session;
|
||||||
|
furi_assert(session);
|
||||||
|
furi_assert(rpc_app->last_id);
|
||||||
|
|
||||||
|
PB_CommandStatus status = result ? PB_CommandStatus_OK : PB_CommandStatus_ERROR_APP_CMD_ERROR;
|
||||||
|
|
||||||
|
uint32_t last_id = 0;
|
||||||
|
switch(event) {
|
||||||
|
case RpcAppEventAppExit:
|
||||||
|
case RpcAppEventLoadFile:
|
||||||
|
case RpcAppEventButtonPress:
|
||||||
|
case RpcAppEventButtonRelease:
|
||||||
|
last_id = rpc_app->last_id;
|
||||||
|
rpc_app->last_id = 0;
|
||||||
|
if(rpc_app->last_data) {
|
||||||
|
free(rpc_app->last_data);
|
||||||
|
rpc_app->last_data = NULL;
|
||||||
|
}
|
||||||
|
FURI_LOG_D(TAG, "AppConfirm: event %d last_id %d status %d", event, last_id, status);
|
||||||
|
rpc_send_and_release_empty(session, last_id, status);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
furi_crash("RPC App state programming Error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void rpc_system_app_set_callback(RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* ctx) {
|
void rpc_system_app_set_callback(RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* ctx) {
|
||||||
furi_assert(rpc_app);
|
furi_assert(rpc_app);
|
||||||
|
|
||||||
@ -226,8 +265,6 @@ void* rpc_system_app_alloc(RpcSession* session) {
|
|||||||
RpcAppSystem* rpc_app = malloc(sizeof(RpcAppSystem));
|
RpcAppSystem* rpc_app = malloc(sizeof(RpcAppSystem));
|
||||||
rpc_app->session = session;
|
rpc_app->session = session;
|
||||||
|
|
||||||
rpc_app->timer = furi_timer_alloc(rpc_system_app_timer_callback, FuriTimerTypeOnce, rpc_app);
|
|
||||||
|
|
||||||
// App exit message
|
// App exit message
|
||||||
rpc_app->state_msg = malloc(sizeof(PB_Main));
|
rpc_app->state_msg = malloc(sizeof(PB_Main));
|
||||||
rpc_app->state_msg->which_content = PB_Main_app_state_response_tag;
|
rpc_app->state_msg->which_content = PB_Main_app_state_response_tag;
|
||||||
@ -265,12 +302,16 @@ void rpc_system_app_free(void* context) {
|
|||||||
RpcSession* session = rpc_app->session;
|
RpcSession* session = rpc_app->session;
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
furi_timer_free(rpc_app->timer);
|
|
||||||
|
|
||||||
if(rpc_app->app_callback) {
|
if(rpc_app->app_callback) {
|
||||||
rpc_app->app_callback(RpcAppEventSessionClose, NULL, rpc_app->app_context);
|
rpc_app->app_callback(RpcAppEventSessionClose, rpc_app->app_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while(rpc_app->app_callback) {
|
||||||
|
furi_delay_tick(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rpc_app->last_data) free(rpc_app->last_data);
|
||||||
|
|
||||||
free(rpc_app->state_msg);
|
free(rpc_app->state_msg);
|
||||||
free(rpc_app);
|
free(rpc_app);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ typedef enum {
|
|||||||
RpcAppEventButtonRelease,
|
RpcAppEventButtonRelease,
|
||||||
} RpcAppSystemEvent;
|
} RpcAppSystemEvent;
|
||||||
|
|
||||||
typedef bool (*RpcAppSystemCallback)(RpcAppSystemEvent event, const char* arg, void* context);
|
typedef void (*RpcAppSystemCallback)(RpcAppSystemEvent event, void* context);
|
||||||
|
|
||||||
typedef struct RpcAppSystem RpcAppSystem;
|
typedef struct RpcAppSystem RpcAppSystem;
|
||||||
|
|
||||||
@ -23,6 +23,10 @@ void rpc_system_app_send_started(RpcAppSystem* rpc_app);
|
|||||||
|
|
||||||
void rpc_system_app_send_exited(RpcAppSystem* rpc_app);
|
void rpc_system_app_send_exited(RpcAppSystem* rpc_app);
|
||||||
|
|
||||||
|
const char* rpc_system_app_get_data(RpcAppSystem* rpc_app);
|
||||||
|
|
||||||
|
void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -594,23 +594,19 @@ static void rpc_system_storage_backup_create_process(const PB_Main* request, voi
|
|||||||
|
|
||||||
FURI_LOG_D(TAG, "BackupCreate");
|
FURI_LOG_D(TAG, "BackupCreate");
|
||||||
|
|
||||||
RpcSession* session = (RpcSession*)context;
|
RpcStorageSystem* rpc_storage = context;
|
||||||
|
RpcSession* session = rpc_storage->session;
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
PB_Main* response = malloc(sizeof(PB_Main));
|
|
||||||
response->command_id = request->command_id;
|
|
||||||
response->has_next = false;
|
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||||
|
|
||||||
bool backup_ok =
|
bool backup_ok =
|
||||||
lfs_backup_create(fs_api, request->content.storage_backup_create_request.archive_path);
|
lfs_backup_create(fs_api, request->content.storage_backup_create_request.archive_path);
|
||||||
response->command_status = backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR;
|
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
rpc_send_and_release(session, response);
|
rpc_send_and_release_empty(
|
||||||
free(response);
|
session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_storage_backup_restore_process(const PB_Main* request, void* context) {
|
static void rpc_system_storage_backup_restore_process(const PB_Main* request, void* context) {
|
||||||
@ -619,24 +615,19 @@ static void rpc_system_storage_backup_restore_process(const PB_Main* request, vo
|
|||||||
|
|
||||||
FURI_LOG_D(TAG, "BackupRestore");
|
FURI_LOG_D(TAG, "BackupRestore");
|
||||||
|
|
||||||
RpcSession* session = (RpcSession*)context;
|
RpcStorageSystem* rpc_storage = context;
|
||||||
|
RpcSession* session = rpc_storage->session;
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
PB_Main* response = malloc(sizeof(PB_Main));
|
|
||||||
response->command_id = request->command_id;
|
|
||||||
response->has_next = false;
|
|
||||||
response->command_status = PB_CommandStatus_OK;
|
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||||
|
|
||||||
bool backup_ok =
|
bool backup_ok =
|
||||||
lfs_backup_unpack(fs_api, request->content.storage_backup_restore_request.archive_path);
|
lfs_backup_unpack(fs_api, request->content.storage_backup_restore_request.archive_path);
|
||||||
response->command_status = backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR;
|
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
rpc_send_and_release(session, response);
|
rpc_send_and_release_empty(
|
||||||
free(response);
|
session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* rpc_system_storage_alloc(RpcSession* session) {
|
void* rpc_system_storage_alloc(RpcSession* session) {
|
||||||
|
|||||||
@ -26,8 +26,7 @@ static FS_Error storage_ext_parse_error(SDError error);
|
|||||||
|
|
||||||
static bool sd_mount_card(StorageData* storage, bool notify) {
|
static bool sd_mount_card(StorageData* storage, bool notify) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
const uint8_t max_init_counts = 10;
|
uint8_t counter = BSP_SD_MaxMountRetryCount();
|
||||||
uint8_t counter = max_init_counts;
|
|
||||||
uint8_t bsp_result;
|
uint8_t bsp_result;
|
||||||
SDData* sd_data = storage->data;
|
SDData* sd_data = storage->data;
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,9 @@ typedef enum {
|
|||||||
SubGhzCustomEventSceneStay,
|
SubGhzCustomEventSceneStay,
|
||||||
|
|
||||||
SubGhzCustomEventSceneRpcLoad,
|
SubGhzCustomEventSceneRpcLoad,
|
||||||
|
SubGhzCustomEventSceneRpcButtonPress,
|
||||||
|
SubGhzCustomEventSceneRpcButtonRelease,
|
||||||
|
SubGhzCustomEventSceneRpcSessionClose,
|
||||||
|
|
||||||
SubGhzCustomEventViewReceiverOK,
|
SubGhzCustomEventViewReceiverOK,
|
||||||
SubGhzCustomEventViewReceiverConfig,
|
SubGhzCustomEventViewReceiverConfig,
|
||||||
|
|||||||
@ -72,11 +72,11 @@ typedef enum {
|
|||||||
SubGhzViewIdTestPacket,
|
SubGhzViewIdTestPacket,
|
||||||
} SubGhzViewId;
|
} SubGhzViewId;
|
||||||
|
|
||||||
struct SubGhzPesetDefinition {
|
struct SubGhzPresetDefinition {
|
||||||
string_t name;
|
string_t name;
|
||||||
uint32_t frequency;
|
uint32_t frequency;
|
||||||
uint8_t* data;
|
uint8_t* data;
|
||||||
size_t data_size;
|
size_t data_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct SubGhzPesetDefinition SubGhzPesetDefinition;
|
typedef struct SubGhzPresetDefinition SubGhzPresetDefinition;
|
||||||
|
|||||||
@ -28,8 +28,8 @@ static bool subghz_scene_receiver_info_update_parser(void* context) {
|
|||||||
subghz->txrx->decoder_result,
|
subghz->txrx->decoder_result,
|
||||||
subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen));
|
subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen));
|
||||||
|
|
||||||
SubGhzPesetDefinition* preset =
|
SubGhzPresetDefinition* preset =
|
||||||
subghz_history_get_presset(subghz->txrx->history, subghz->txrx->idx_menu_chosen);
|
subghz_history_get_preset_def(subghz->txrx->history, subghz->txrx->idx_menu_chosen);
|
||||||
subghz_preset_init(
|
subghz_preset_init(
|
||||||
subghz,
|
subghz,
|
||||||
string_get_cstr(preset->name),
|
string_get_cstr(preset->name),
|
||||||
|
|||||||
@ -22,20 +22,60 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == SubGhzCustomEventSceneExit) {
|
if(event.event == SubGhzCustomEventSceneExit) {
|
||||||
|
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||||
|
subghz_tx_stop(subghz);
|
||||||
|
subghz_sleep(subghz);
|
||||||
|
}
|
||||||
view_dispatcher_stop(subghz->view_dispatcher);
|
view_dispatcher_stop(subghz->view_dispatcher);
|
||||||
|
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventAppExit, true);
|
||||||
|
} else if(event.event == SubGhzCustomEventSceneRpcSessionClose) {
|
||||||
|
rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
|
||||||
|
subghz->rpc_ctx = NULL;
|
||||||
|
subghz_blink_stop(subghz);
|
||||||
|
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||||
|
subghz_tx_stop(subghz);
|
||||||
|
subghz_sleep(subghz);
|
||||||
|
}
|
||||||
|
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
|
||||||
|
} else if(event.event == SubGhzCustomEventSceneRpcButtonPress) {
|
||||||
|
bool result = false;
|
||||||
|
if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) {
|
||||||
|
subghz_blink_start(subghz);
|
||||||
|
result = subghz_tx_start(subghz, subghz->txrx->fff_data);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result);
|
||||||
|
} else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) {
|
||||||
|
bool result = false;
|
||||||
|
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||||
|
subghz_blink_stop(subghz);
|
||||||
|
subghz_tx_stop(subghz);
|
||||||
|
subghz_sleep(subghz);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonRelease, result);
|
||||||
} else if(event.event == SubGhzCustomEventSceneRpcLoad) {
|
} else if(event.event == SubGhzCustomEventSceneRpcLoad) {
|
||||||
string_t file_name;
|
bool result = false;
|
||||||
string_init(file_name);
|
const char* arg = rpc_system_app_get_data(subghz->rpc_ctx);
|
||||||
path_extract_filename(subghz->file_path, file_name, true);
|
if(arg) {
|
||||||
|
if(subghz_key_load(subghz, arg, false)) {
|
||||||
|
string_set_str(subghz->file_path, arg);
|
||||||
|
result = true;
|
||||||
|
string_t file_name;
|
||||||
|
string_init(file_name);
|
||||||
|
path_extract_filename(subghz->file_path, file_name, true);
|
||||||
|
|
||||||
snprintf(
|
snprintf(
|
||||||
subghz->file_name_tmp,
|
subghz->file_name_tmp,
|
||||||
SUBGHZ_MAX_LEN_NAME,
|
SUBGHZ_MAX_LEN_NAME,
|
||||||
"loaded\n%s",
|
"loaded\n%s",
|
||||||
string_get_cstr(file_name));
|
string_get_cstr(file_name));
|
||||||
popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop);
|
popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop);
|
||||||
|
|
||||||
string_clear(file_name);
|
string_clear(file_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventLoadFile, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@ -35,57 +35,38 @@ void subghz_tick_event_callback(void* context) {
|
|||||||
scene_manager_handle_tick_event(subghz->scene_manager);
|
scene_manager_handle_tick_event(subghz->scene_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool subghz_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
|
static void subghz_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
|
|
||||||
if(!subghz->rpc_ctx) {
|
furi_assert(subghz->rpc_ctx);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if(event == RpcAppEventSessionClose) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
|
view_dispatcher_send_custom_event(
|
||||||
subghz->rpc_ctx = NULL;
|
subghz->view_dispatcher, SubGhzCustomEventSceneRpcSessionClose);
|
||||||
notification_message(subghz->notifications, &sequence_blink_stop);
|
|
||||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
|
|
||||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
|
||||||
subghz_tx_stop(subghz);
|
|
||||||
subghz_sleep(subghz);
|
|
||||||
}
|
|
||||||
result = true;
|
|
||||||
} else if(event == RpcAppEventAppExit) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
|
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
|
||||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
|
||||||
subghz_tx_stop(subghz);
|
|
||||||
subghz_sleep(subghz);
|
|
||||||
}
|
|
||||||
result = true;
|
|
||||||
} else if(event == RpcAppEventLoadFile) {
|
} else if(event == RpcAppEventLoadFile) {
|
||||||
if(arg) {
|
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad);
|
||||||
if(subghz_key_load(subghz, arg, false)) {
|
|
||||||
string_set_str(subghz->file_path, arg);
|
|
||||||
view_dispatcher_send_custom_event(
|
|
||||||
subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad);
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(event == RpcAppEventButtonPress) {
|
} else if(event == RpcAppEventButtonPress) {
|
||||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) {
|
view_dispatcher_send_custom_event(
|
||||||
notification_message(subghz->notifications, &sequence_blink_start_magenta);
|
subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonPress);
|
||||||
result = subghz_tx_start(subghz, subghz->txrx->fff_data);
|
|
||||||
}
|
|
||||||
} else if(event == RpcAppEventButtonRelease) {
|
} else if(event == RpcAppEventButtonRelease) {
|
||||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
view_dispatcher_send_custom_event(
|
||||||
notification_message(subghz->notifications, &sequence_blink_stop);
|
subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonRelease);
|
||||||
subghz_tx_stop(subghz);
|
} else {
|
||||||
subghz_sleep(subghz);
|
rpc_system_app_confirm(subghz->rpc_ctx, event, false);
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
void subghz_blink_start(SubGhz* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
notification_message(instance->notifications, &sequence_blink_start_magenta);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_blink_stop(SubGhz* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
notification_message(instance->notifications, &sequence_blink_stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
SubGhz* subghz_alloc() {
|
SubGhz* subghz_alloc() {
|
||||||
@ -199,7 +180,7 @@ SubGhz* subghz_alloc() {
|
|||||||
//init Worker & Protocol & History & KeyBoard
|
//init Worker & Protocol & History & KeyBoard
|
||||||
subghz->lock = SubGhzLockOff;
|
subghz->lock = SubGhzLockOff;
|
||||||
subghz->txrx = malloc(sizeof(SubGhzTxRx));
|
subghz->txrx = malloc(sizeof(SubGhzTxRx));
|
||||||
subghz->txrx->preset = malloc(sizeof(SubGhzPesetDefinition));
|
subghz->txrx->preset = malloc(sizeof(SubGhzPresetDefinition));
|
||||||
string_init(subghz->txrx->preset->name);
|
string_init(subghz->txrx->preset->name);
|
||||||
subghz_preset_init(
|
subghz_preset_init(
|
||||||
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
|
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
|
||||||
@ -237,7 +218,7 @@ void subghz_free(SubGhz* subghz) {
|
|||||||
if(subghz->rpc_ctx) {
|
if(subghz->rpc_ctx) {
|
||||||
rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
|
rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
|
||||||
rpc_system_app_send_exited(subghz->rpc_ctx);
|
rpc_system_app_send_exited(subghz->rpc_ctx);
|
||||||
notification_message(subghz->notifications, &sequence_blink_stop);
|
subghz_blink_stop(subghz);
|
||||||
subghz->rpc_ctx = NULL;
|
subghz->rpc_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ typedef struct {
|
|||||||
string_t item_str;
|
string_t item_str;
|
||||||
FlipperFormat* flipper_string;
|
FlipperFormat* flipper_string;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
SubGhzPesetDefinition* preset;
|
SubGhzPresetDefinition* preset;
|
||||||
} SubGhzHistoryItem;
|
} SubGhzHistoryItem;
|
||||||
|
|
||||||
ARRAY_DEF(SubGhzHistoryItemArray, SubGhzHistoryItem, M_POD_OPLIST)
|
ARRAY_DEF(SubGhzHistoryItemArray, SubGhzHistoryItem, M_POD_OPLIST)
|
||||||
@ -61,7 +61,7 @@ uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx) {
|
|||||||
return item->preset->frequency;
|
return item->preset->frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
SubGhzPesetDefinition* subghz_history_get_presset(SubGhzHistory* instance, uint16_t idx) {
|
SubGhzPresetDefinition* subghz_history_get_preset_def(SubGhzHistory* instance, uint16_t idx) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
|
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
|
||||||
return item->preset;
|
return item->preset;
|
||||||
@ -139,7 +139,7 @@ void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output,
|
|||||||
bool subghz_history_add_to_history(
|
bool subghz_history_add_to_history(
|
||||||
SubGhzHistory* instance,
|
SubGhzHistory* instance,
|
||||||
void* context,
|
void* context,
|
||||||
SubGhzPesetDefinition* preset) {
|
SubGhzPresetDefinition* preset) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ bool subghz_history_add_to_history(
|
|||||||
string_t text;
|
string_t text;
|
||||||
string_init(text);
|
string_init(text);
|
||||||
SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data);
|
SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data);
|
||||||
item->preset = malloc(sizeof(SubGhzPesetDefinition));
|
item->preset = malloc(sizeof(SubGhzPresetDefinition));
|
||||||
item->type = decoder_base->protocol->type;
|
item->type = decoder_base->protocol->type;
|
||||||
item->preset->frequency = preset->frequency;
|
item->preset->frequency = preset->frequency;
|
||||||
string_init(item->preset->name);
|
string_init(item->preset->name);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ void subghz_history_reset(SubGhzHistory* instance);
|
|||||||
*/
|
*/
|
||||||
uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx);
|
uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx);
|
||||||
|
|
||||||
SubGhzPesetDefinition* subghz_history_get_presset(SubGhzHistory* instance, uint16_t idx);
|
SubGhzPresetDefinition* subghz_history_get_preset_def(SubGhzHistory* instance, uint16_t idx);
|
||||||
|
|
||||||
/** Get preset to history[idx]
|
/** Get preset to history[idx]
|
||||||
*
|
*
|
||||||
@ -88,13 +88,13 @@ bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output
|
|||||||
*
|
*
|
||||||
* @param instance - SubGhzHistory instance
|
* @param instance - SubGhzHistory instance
|
||||||
* @param context - SubGhzProtocolCommon context
|
* @param context - SubGhzProtocolCommon context
|
||||||
* @param preset - SubGhzPesetDefinition preset
|
* @param preset - SubGhzPresetDefinition preset
|
||||||
* @return bool;
|
* @return bool;
|
||||||
*/
|
*/
|
||||||
bool subghz_history_add_to_history(
|
bool subghz_history_add_to_history(
|
||||||
SubGhzHistory* instance,
|
SubGhzHistory* instance,
|
||||||
void* context,
|
void* context,
|
||||||
SubGhzPesetDefinition* preset);
|
SubGhzPresetDefinition* preset);
|
||||||
|
|
||||||
/** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data
|
/** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data
|
||||||
*
|
*
|
||||||
|
|||||||
@ -331,8 +331,10 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) {
|
|||||||
subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
||||||
subghz->txrx->receiver, string_get_cstr(temp_str));
|
subghz->txrx->receiver, string_get_cstr(temp_str));
|
||||||
if(subghz->txrx->decoder_result) {
|
if(subghz->txrx->decoder_result) {
|
||||||
subghz_protocol_decoder_base_deserialize(
|
if(!subghz_protocol_decoder_base_deserialize(
|
||||||
subghz->txrx->decoder_result, subghz->txrx->fff_data);
|
subghz->txrx->decoder_result, subghz->txrx->fff_data)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_E(TAG, "Protocol not found");
|
FURI_LOG_E(TAG, "Protocol not found");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -49,7 +49,7 @@ struct SubGhzTxRx {
|
|||||||
SubGhzProtocolDecoderBase* decoder_result;
|
SubGhzProtocolDecoderBase* decoder_result;
|
||||||
FlipperFormat* fff_data;
|
FlipperFormat* fff_data;
|
||||||
|
|
||||||
SubGhzPesetDefinition* preset;
|
SubGhzPresetDefinition* preset;
|
||||||
SubGhzHistory* history;
|
SubGhzHistory* history;
|
||||||
uint16_t idx_menu_chosen;
|
uint16_t idx_menu_chosen;
|
||||||
SubGhzTxRxState txrx_state;
|
SubGhzTxRxState txrx_state;
|
||||||
@ -108,6 +108,10 @@ void subghz_begin(SubGhz* subghz, uint8_t* preset_data);
|
|||||||
uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency);
|
uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency);
|
||||||
void subghz_rx_end(SubGhz* subghz);
|
void subghz_rx_end(SubGhz* subghz);
|
||||||
void subghz_sleep(SubGhz* subghz);
|
void subghz_sleep(SubGhz* subghz);
|
||||||
|
|
||||||
|
void subghz_blink_start(SubGhz* instance);
|
||||||
|
void subghz_blink_stop(SubGhz* instance);
|
||||||
|
|
||||||
bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format);
|
bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format);
|
||||||
void subghz_tx_stop(SubGhz* subghz);
|
void subghz_tx_stop(SubGhz* subghz);
|
||||||
void subghz_dialog_message_show_only_rx(SubGhz* subghz);
|
void subghz_dialog_message_show_only_rx(SubGhz* subghz);
|
||||||
|
|||||||
@ -216,8 +216,8 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) {
|
|||||||
uint8_t graphics_mode = 1;
|
uint8_t graphics_mode = 1;
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
canvas_draw_str(canvas, 5, 8, string_get_cstr(model->frequency_str));
|
canvas_draw_str(canvas, 5, 7, string_get_cstr(model->frequency_str));
|
||||||
canvas_draw_str(canvas, 40, 8, string_get_cstr(model->preset_str));
|
canvas_draw_str(canvas, 40, 7, string_get_cstr(model->preset_str));
|
||||||
canvas_draw_str_aligned(
|
canvas_draw_str_aligned(
|
||||||
canvas, 126, 0, AlignRight, AlignTop, string_get_cstr(model->sample_write));
|
canvas, 126, 0, AlignRight, AlignTop, string_get_cstr(model->sample_write));
|
||||||
|
|
||||||
|
|||||||
@ -387,6 +387,34 @@ MU_TEST(stream_split_test) {
|
|||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(stream_buffered_write_after_read_test) {
|
||||||
|
const char* prefix = "I write ";
|
||||||
|
const char* substr = "Hello there";
|
||||||
|
|
||||||
|
const size_t substr_len = strlen(substr);
|
||||||
|
const size_t prefix_len = strlen(prefix);
|
||||||
|
const size_t buf_size = substr_len + 1;
|
||||||
|
|
||||||
|
char buf[buf_size];
|
||||||
|
memset(buf, 0, buf_size);
|
||||||
|
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
Stream* stream = buffered_file_stream_alloc(storage);
|
||||||
|
mu_check(buffered_file_stream_open(
|
||||||
|
stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
|
||||||
|
mu_assert_int_eq(strlen(stream_test_data), stream_write_cstring(stream, stream_test_data));
|
||||||
|
mu_check(stream_rewind(stream));
|
||||||
|
mu_assert_int_eq(prefix_len, stream_read(stream, (uint8_t*)buf, prefix_len));
|
||||||
|
mu_assert_string_eq(prefix, buf);
|
||||||
|
mu_assert_int_eq(substr_len, stream_write(stream, (uint8_t*)substr, substr_len));
|
||||||
|
mu_check(stream_seek(stream, prefix_len, StreamOffsetFromStart));
|
||||||
|
mu_assert_int_eq(substr_len, stream_read(stream, (uint8_t*)buf, substr_len));
|
||||||
|
mu_assert_string_eq(substr, buf);
|
||||||
|
|
||||||
|
stream_free(stream);
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST(stream_buffered_large_file_test) {
|
MU_TEST(stream_buffered_large_file_test) {
|
||||||
string_t input_data;
|
string_t input_data;
|
||||||
string_t output_data;
|
string_t output_data;
|
||||||
@ -470,6 +498,7 @@ MU_TEST_SUITE(stream_suite) {
|
|||||||
MU_RUN_TEST(stream_write_read_save_load_test);
|
MU_RUN_TEST(stream_write_read_save_load_test);
|
||||||
MU_RUN_TEST(stream_composite_test);
|
MU_RUN_TEST(stream_composite_test);
|
||||||
MU_RUN_TEST(stream_split_test);
|
MU_RUN_TEST(stream_split_test);
|
||||||
|
MU_RUN_TEST(stream_buffered_write_after_read_test);
|
||||||
MU_RUN_TEST(stream_buffered_large_file_test);
|
MU_RUN_TEST(stream_buffered_large_file_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -103,8 +103,7 @@ if assetsenv["IS_BASE_FIRMWARE"]:
|
|||||||
)
|
)
|
||||||
assetsenv.Precious(resources)
|
assetsenv.Precious(resources)
|
||||||
assetsenv.NoClean(resources)
|
assetsenv.NoClean(resources)
|
||||||
if assetsenv["FORCE"]:
|
assetsenv.AlwaysBuild(resources)
|
||||||
assetsenv.AlwaysBuild(resources)
|
|
||||||
|
|
||||||
# Exporting resources node to external environment
|
# Exporting resources node to external environment
|
||||||
env["FW_RESOURCES"] = resources
|
env["FW_RESOURCES"] = resources
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 301 B |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 624 B |
|
Before Width: | Height: | Size: 558 B |
|
Before Width: | Height: | Size: 574 B |
|
Before Width: | Height: | Size: 527 B |
|
Before Width: | Height: | Size: 556 B |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 553 B |
|
Before Width: | Height: | Size: 423 B |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 372 B |
|
Before Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 298 B |
|
Before Width: | Height: | Size: 100 B |
|
Before Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 96 B |
|
Before Width: | Height: | Size: 97 B |
|
Before Width: | Height: | Size: 99 B |
@ -1 +0,0 @@
|
|||||||
3
|
|
||||||
|
Before Width: | Height: | Size: 96 B |
|
Before Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 105 B |
|
Before Width: | Height: | Size: 104 B |
|
Before Width: | Height: | Size: 105 B |
|
Before Width: | Height: | Size: 102 B |
|
Before Width: | Height: | Size: 101 B |
|
Before Width: | Height: | Size: 102 B |
|
Before Width: | Height: | Size: 100 B |
@ -1 +0,0 @@
|
|||||||
3
|
|
||||||
|
Before Width: | Height: | Size: 98 B |
|
Before Width: | Height: | Size: 81 B |
|
Before Width: | Height: | Size: 86 B |
|
Before Width: | Height: | Size: 89 B |
|
Before Width: | Height: | Size: 89 B |
|
Before Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 97 B |
|
Before Width: | Height: | Size: 97 B |
|
Before Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 98 B |
@ -1 +0,0 @@
|
|||||||
3
|
|
||||||
|
Before Width: | Height: | Size: 326 B |
@ -1 +0,0 @@
|
|||||||
3
|
|
||||||
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 106 B |
@ -1 +0,0 @@
|
|||||||
3
|
|
||||||
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 83 B |
|
Before Width: | Height: | Size: 81 B |
|
Before Width: | Height: | Size: 312 B |
|
Before Width: | Height: | Size: 318 B |
@ -1,5 +1,5 @@
|
|||||||
V:0
|
V:0
|
||||||
T:1655152832
|
T:1658906571
|
||||||
D:badusb
|
D:badusb
|
||||||
D:dolphin
|
D:dolphin
|
||||||
D:infrared
|
D:infrared
|
||||||
@ -232,10 +232,10 @@ F:41b4f08774249014cb8d3dffa5f5c07d:1757:nfc/assets/currency_code.nfc
|
|||||||
F:c60e862919731b0bd538a1001bbc1098:17453:nfc/assets/mf_classic_dict.nfc
|
F:c60e862919731b0bd538a1001bbc1098:17453:nfc/assets/mf_classic_dict.nfc
|
||||||
D:subghz/assets
|
D:subghz/assets
|
||||||
F:dda1ef895b8a25fde57c874feaaef997:650:subghz/assets/came_atomo
|
F:dda1ef895b8a25fde57c874feaaef997:650:subghz/assets/came_atomo
|
||||||
F:610a0ffa2479a874f2060eb2348104c5:2712:subghz/assets/keeloq_mfcodes
|
F:788eef2cc74e29f3388463d6607dab0d:3264:subghz/assets/keeloq_mfcodes
|
||||||
F:9214f9c10463b746a27e82ce0b96e040:465:subghz/assets/keeloq_mfcodes_user
|
F:9214f9c10463b746a27e82ce0b96e040:465:subghz/assets/keeloq_mfcodes_user
|
||||||
F:653bd8d349055a41e1152e557d4a52d3:202:subghz/assets/nice_flor_s
|
F:653bd8d349055a41e1152e557d4a52d3:202:subghz/assets/nice_flor_s
|
||||||
F:c6ec4374275cd20f482ecd46de9f53e3:528:subghz/assets/setting_user
|
F:c1c63fbd5f5aa3ea504027014652191f:1150:subghz/assets/setting_user
|
||||||
D:u2f/assets
|
D:u2f/assets
|
||||||
F:7e11e688e39034bbb9d88410044795e1:365:u2f/assets/cert.der
|
F:7e11e688e39034bbb9d88410044795e1:365:u2f/assets/cert.der
|
||||||
F:f60b88c20ed479ed9684e249f7134618:264:u2f/assets/cert_key.u2f
|
F:f60b88c20ed479ed9684e249f7134618:264:u2f/assets/cert_key.u2f
|
||||||
|
|||||||
90
debug/fw.jflash
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
AppVersion = 76803
|
||||||
|
FileVersion = 2
|
||||||
|
[GENERAL]
|
||||||
|
aATEModuleSel[24] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
ConnectMode = 0
|
||||||
|
CurrentFile = "..\build\latest\firmware.bin"
|
||||||
|
DataFileSAddr = 0x08000000
|
||||||
|
GUIMode = 0
|
||||||
|
HostName = ""
|
||||||
|
TargetIF = 1
|
||||||
|
USBPort = 0
|
||||||
|
USBSerialNo = 0x00000000
|
||||||
|
UseATEModuleSelection = 0
|
||||||
|
[JTAG]
|
||||||
|
IRLen = 0
|
||||||
|
MultipleTargets = 0
|
||||||
|
NumDevices = 0
|
||||||
|
Speed0 = 8000
|
||||||
|
Speed1 = 8000
|
||||||
|
TAP_Number = 0
|
||||||
|
UseAdaptive0 = 0
|
||||||
|
UseAdaptive1 = 0
|
||||||
|
UseMaxSpeed0 = 0
|
||||||
|
UseMaxSpeed1 = 0
|
||||||
|
[CPU]
|
||||||
|
NumInitSteps = 2
|
||||||
|
InitStep0_Action = "Reset"
|
||||||
|
InitStep0_Value0 = 0x00000000
|
||||||
|
InitStep0_Value1 = 0x00000000
|
||||||
|
InitStep0_Comment = ""
|
||||||
|
InitStep1_Action = "Halt"
|
||||||
|
InitStep1_Value0 = 0xFFFFFFFF
|
||||||
|
InitStep1_Value1 = 0xFFFFFFFF
|
||||||
|
InitStep1_Comment = ""
|
||||||
|
NumExitSteps = 1
|
||||||
|
ExitStep0_Action = "Reset"
|
||||||
|
ExitStep0_Value0 = 0x00000005
|
||||||
|
ExitStep0_Value1 = 0x00000032
|
||||||
|
ExitStep0_Comment = ""
|
||||||
|
UseScriptFile = 0
|
||||||
|
ScriptFile = ""
|
||||||
|
UseRAM = 1
|
||||||
|
RAMAddr = 0x20000000
|
||||||
|
RAMSize = 0x00030000
|
||||||
|
CheckCoreID = 1
|
||||||
|
CoreID = 0x6BA02477
|
||||||
|
CoreIDMask = 0x0F000FFF
|
||||||
|
UseAutoSpeed = 0x00000001
|
||||||
|
ClockSpeed = 0x00000000
|
||||||
|
EndianMode = 0
|
||||||
|
ChipName = "ST STM32WB55RG"
|
||||||
|
[FLASH]
|
||||||
|
aRangeSel[1] = 0-255
|
||||||
|
BankName = "Internal flash"
|
||||||
|
BankSelMode = 1
|
||||||
|
BaseAddr = 0x08000000
|
||||||
|
NumBanks = 1
|
||||||
|
[PRODUCTION]
|
||||||
|
AutoPerformsDisconnect = 0
|
||||||
|
AutoPerformsErase = 1
|
||||||
|
AutoPerformsProgram = 1
|
||||||
|
AutoPerformsSecure = 0
|
||||||
|
AutoPerformsStartApp = 1
|
||||||
|
AutoPerformsUnsecure = 0
|
||||||
|
AutoPerformsVerify = 0
|
||||||
|
EnableFixedVTref = 0
|
||||||
|
EnableTargetPower = 0
|
||||||
|
EraseType = 1
|
||||||
|
FixedVTref = 0x00000CE4
|
||||||
|
MonitorVTref = 0
|
||||||
|
MonitorVTrefMax = 0x0000157C
|
||||||
|
MonitorVTrefMin = 0x000003E8
|
||||||
|
OverrideTimeouts = 0
|
||||||
|
ProgramSN = 0
|
||||||
|
SerialFile = ""
|
||||||
|
SNAddr = 0x00000000
|
||||||
|
SNInc = 0x00000001
|
||||||
|
SNLen = 0x00000004
|
||||||
|
SNListFile = ""
|
||||||
|
SNValue = 0x00000001
|
||||||
|
StartAppType = 1
|
||||||
|
TargetPowerDelay = 0x00000014
|
||||||
|
TimeoutErase = 0x00003A98
|
||||||
|
TimeoutProgram = 0x00002710
|
||||||
|
TimeoutVerify = 0x00002710
|
||||||
|
VerifyType = 1
|
||||||
|
[PERFORMANCE]
|
||||||
|
DisableSkipBlankDataOnProgram = 0x00000000
|
||||||
|
PerfromBlankCheckPriorEraseChip = 0x00000001
|
||||||
|
PerfromBlankCheckPriorEraseSelectedSectors = 0x00000001
|
||||||