Merge branch 'flipperdevices:dev' into dev

This commit is contained in:
jaroslavmraz
2022-08-04 14:56:17 +02:00
committed by GitHub
285 changed files with 4030 additions and 1324 deletions
+46 -69
View File
@@ -15,11 +15,8 @@ env:
jobs:
main:
runs-on: [self-hosted,FlipperZero]
runs-on: [self-hosted,FlipperZeroShell]
steps:
- name: 'Cleanup workspace'
uses: AutoModality/action-clean@v1
- name: 'Decontaminate previous build leftovers'
run: |
if [ -d .git ]
@@ -32,12 +29,8 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 0
submodules: true
ref: ${{ github.event.pull_request.head.sha }}
- name: 'Build docker image'
uses: ./.github/actions/docker
- name: 'Make artifacts directory'
run: |
test -d artifacts && rm -rf artifacts || true
@@ -71,40 +64,38 @@ jobs:
run: |
tar czpf artifacts/flipper-z-any-scripts-${{steps.names.outputs.suffix}}.tgz scripts
- name: 'Build the firmware in docker'
uses: ./.github/actions/docker
with:
run: |
set -e
for TARGET in ${TARGETS}
do
./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }}
done
- name: 'Build the firmware'
run: |
set -e
for TARGET in ${TARGETS}
do
FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }}
done
- name: 'Move upload files'
if: ${{ !github.event.pull_request.head.repo.fork }}
uses: ./.github/actions/docker
with:
run: |
set -e
for TARGET in ${TARGETS}
do
mv dist/${TARGET}-*/* artifacts/
done
run: |
set -e
for TARGET in ${TARGETS}
do
mv dist/${TARGET}-*/* artifacts/
done
- name: 'Bundle self-update package'
if: ${{ !github.event.pull_request.head.repo.fork }}
uses: ./.github/actions/docker
with:
run: |
set -e
for UPDATEBUNDLE in artifacts/*/
do
BUNDLE_NAME=`echo $UPDATEBUNDLE | cut -d'/' -f2`
echo Packaging ${BUNDLE_NAME}
tar czpf artifacts/flipper-z-${BUNDLE_NAME}.tgz -C artifacts ${BUNDLE_NAME}
rm -rf artifacts/${BUNDLE_NAME}
done
run: |
set -e
for UPDATEBUNDLE in artifacts/*/
do
BUNDLE_NAME=`echo $UPDATEBUNDLE | cut -d'/' -f2`
echo Packaging ${BUNDLE_NAME}
tar czpf artifacts/flipper-z-${BUNDLE_NAME}.tgz -C artifacts ${BUNDLE_NAME}
rm -rf artifacts/${BUNDLE_NAME}
done
- name: "Check for uncommited changes"
run: |
git diff --exit-code
- name: 'Bundle resources'
if: ${{ !github.event.pull_request.head.repo.fork }}
@@ -113,29 +104,23 @@ jobs:
- name: 'Bundle core2 firmware'
if: ${{ !github.event.pull_request.head.repo.fork }}
uses: ./.github/actions/docker
with:
run: |
./fbt copro_dist
tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz -C assets core2_firmware
run: |
FBT_TOOLCHAIN_PATH=/opt ./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'
if: ${{ !github.event.pull_request.head.repo.fork }}
uses: burnett01/rsync-deployments@5.1
with:
switches: -avzP --delete --mkpath
path: artifacts/
remote_path: "${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/"
remote_host: ${{ secrets.RSYNC_DEPLOY_HOST }}
remote_port: ${{ secrets.RSYNC_DEPLOY_PORT }}
remote_user: ${{ secrets.RSYNC_DEPLOY_USER }}
remote_key: ${{ secrets.RSYNC_DEPLOY_KEY }}
run: |
echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key;
chmod 600 ./deploy_key;
rsync -avzP --delete --mkpath \
-e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \
artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/";
rm ./deploy_key;
- name: 'Trigger update server reindex'
if: ${{ !github.event.pull_request.head.repo.fork }}
uses: wei/curl@master
with:
args: -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
run: curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
- name: 'Find Previous Comment'
if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }}
@@ -161,11 +146,8 @@ jobs:
compact:
if: ${{ !startsWith(github.ref, 'refs/tags') }}
runs-on: [self-hosted,FlipperZero]
runs-on: [self-hosted,FlipperZeroShell]
steps:
- name: 'Cleanup workspace'
uses: AutoModality/action-clean@v1
- name: 'Decontaminate previous build leftovers'
run: |
if [ -d .git ]
@@ -181,9 +163,6 @@ jobs:
submodules: true
ref: ${{ github.event.pull_request.head.sha }}
- name: 'Build docker image'
uses: ./.github/actions/docker
- name: 'Generate suffix and folder name'
id: names
run: |
@@ -203,12 +182,10 @@ jobs:
echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV
echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV
- name: 'Build the firmware in docker'
uses: ./.github/actions/docker
with:
run: |
set -e
for TARGET in ${TARGETS}
do
./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package DEBUG=0 COMPACT=1
done
- name: 'Build the firmware'
run: |
set -e
for TARGET in ${TARGETS}
do
FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package DEBUG=0 COMPACT=1
done
-46
View File
@@ -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
+41 -11
View File
@@ -1,17 +1,47 @@
name: 'Check submodules'
name: 'Check submodules branch'
on:
push:
branches:
- dev
- "release*"
tags:
- '*'
pull_request:
jobs:
protobuf:
runs-on: ubuntu-latest
check_protobuf:
runs-on: [self-hosted, FlipperZeroShell]
steps:
- name: 'Checkout code'
uses: actions/checkout@v2
- name: 'Check submodule commit branch'
uses: jtmullen/submodule-branch-check-action@v1
with:
path: assets/protobuf
branch: dev
fetch_depth: 50
- name: 'Decontaminate previous build leftovers'
run: |
if [ -d .git ]
then
git submodule status \
|| git checkout `git rev-list --max-parents=0 HEAD | tail -n 1`
fi
- name: 'Checkout code'
uses: actions/checkout@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
+4 -20
View File
@@ -1,6 +1,6 @@
name: 'Lint C/C++ with clang-format'
on:
on:
push:
branches:
- dev
@@ -14,11 +14,8 @@ env:
jobs:
lint_c_cpp:
runs-on: [self-hosted,FlipperZero]
runs-on: [self-hosted,FlipperZeroShell]
steps:
- name: 'Cleanup workspace'
uses: AutoModality/action-clean@v1
- name: 'Decontaminate previous build leftovers'
run: |
if [ -d .git ]
@@ -31,23 +28,10 @@ jobs:
uses: actions/checkout@v2
with:
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'
id: syntax_check
uses: ./.github/actions/docker
with:
run: SET_GH_OUTPUT=1 ./fbt lint
run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/opt ./fbt lint
- name: Report code formatting errors
if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request
@@ -59,4 +43,4 @@ jobs:
```
${{ 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.
+4 -10
View File
@@ -1,6 +1,6 @@
name: 'Python Lint'
on:
on:
push:
branches:
- dev
@@ -11,11 +11,8 @@ on:
jobs:
lint_python:
runs-on: ubuntu-latest
runs-on: [self-hosted,FlipperZeroShell]
steps:
- name: 'Cleanup workspace'
uses: AutoModality/action-clean@v1
- name: 'Decontaminate previous build leftovers'
run: |
if [ -d .git ]
@@ -29,8 +26,5 @@ jobs:
with:
fetch-depth: 0
- name: 'Setup python'
uses: actions/setup-python@v2
- name: 'Check python code with black'
uses: psf/black@20.8b1
- name: 'Check code formatting'
run: SET_GH_OUTPUT=1 FBT_TOOLCHAIN_PATH=/opt ./fbt lint_py
+3 -4
View File
@@ -7,9 +7,8 @@ on:
jobs:
reindex:
name: 'Reindex updates'
runs-on: [self-hosted,FlipperZero]
runs-on: [self-hosted,FlipperZeroShell]
steps:
- name: Trigger reindex
uses: wei/curl@master
with:
args: -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
run: |
curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
+4
View File
@@ -0,0 +1,4 @@
./c_cpp_properties.json
./launch.json
./settings.json
./tasks.json
+32
View File
@@ -0,0 +1,32 @@
{
"configurations": [
{
"name": "Win32",
"compilerPath": "${workspaceFolder}/toolchain/i686-windows/bin/arm-none-eabi-gcc.exe",
"intelliSenseMode": "gcc-arm",
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
"configurationProvider": "ms-vscode.cpptools",
"cStandard": "gnu17",
"cppStandard": "c++17"
},
{
"name": "Linux",
"compilerPath": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gcc",
"intelliSenseMode": "gcc-arm",
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
"configurationProvider": "ms-vscode.cpptools",
"cStandard": "gnu17",
"cppStandard": "c++17"
},
{
"name": "Mac",
"compilerPath": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gcc",
"intelliSenseMode": "gcc-arm",
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
"configurationProvider": "ms-vscode.cpptools",
"cStandard": "gnu17",
"cppStandard": "c++17"
}
],
"version": 4
}
+87
View File
@@ -0,0 +1,87 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"inputs": [
{
"id": "BLACKMAGIC",
"type": "command",
"command": "shellCommand.execute",
"args": {
"command": "./fbt get_blackmagic",
"description": "Get Blackmagic device",
}
}
],
"configurations": [
{
"name": "Attach FW (ST-Link)",
"cwd": "${workspaceFolder}",
"executable": "./build/latest/firmware.elf",
"request": "attach",
"type": "cortex-debug",
"servertype": "openocd",
"device": "stlink",
"svdFile": "./debug/STM32WB55_CM4.svd",
"rtos": "FreeRTOS",
"configFiles": [
"interface/stlink.cfg",
"./debug/stm32wbx.cfg",
],
"postAttachCommands": [
// "attach 1",
"compare-sections",
]
// "showDevDebugOutput": "raw",
},
{
"name": "Attach FW (blackmagic)",
"cwd": "${workspaceFolder}",
"executable": "./build/latest/firmware.elf",
"request": "attach",
"type": "cortex-debug",
"servertype": "external",
"gdbTarget": "${input:BLACKMAGIC}",
"svdFile": "./debug/STM32WB55_CM4.svd",
"rtos": "FreeRTOS",
"postAttachCommands": [
"monitor swdp_scan",
"attach 1",
"set confirm off",
"set mem inaccessible-by-default off",
"compare-sections",
]
// "showDevDebugOutput": "raw",
},
{
"name": "Attach FW (JLink)",
"cwd": "${workspaceFolder}",
"executable": "./build/latest/firmware.elf",
"request": "attach",
"type": "cortex-debug",
"servertype": "jlink",
"interface": "swd",
"device": "STM32WB55RG",
"svdFile": "./debug/STM32WB55_CM4.svd",
"rtos": "FreeRTOS",
// "showDevDebugOutput": "raw",
},
{
"name": "fbt debug",
"type": "python",
"request": "launch",
"program": "./lib/scons/scripts/scons.py",
"args": [
"sdk"
]
},
{
"name": "python debug",
"type": "python",
"request": "launch",
"program": "${file}",
"args": []
}
]
}
+22
View File
@@ -0,0 +1,22 @@
{
"C_Cpp.default.cStandard": "gnu17",
"C_Cpp.default.cppStandard": "c++17",
"python.formatting.provider": "black",
"workbench.tree.indent": 12,
"cortex-debug.enableTelemetry": false,
"cortex-debug.variableUseNaturalFormat": true,
"cortex-debug.showRTOS": true,
"cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/i686-windows/bin",
"cortex-debug.armToolchainPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin",
"cortex-debug.armToolchainPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin",
"cortex-debug.openocdPath.windows": "${workspaceFolder}/toolchain/i686-windows/openocd/bin/openocd.exe",
"cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd",
"cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd",
"editor.formatOnSave": true,
"files.associations": {
"*.scons": "python",
"SConscript": "python",
"SConstruct": "python",
"*.fam": "python",
}
}
+103
View File
@@ -0,0 +1,103 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "[Release] Build",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0"
},
{
"label": "[Debug] Build",
"group": "build",
"type": "shell",
"command": "./fbt"
},
{
"label": "[Release] Flash (ST-Link)",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash"
},
{
"label": "[Debug] Flash (ST-Link)",
"group": "build",
"type": "shell",
"command": "./fbt FORCE=1 flash"
},
{
"label": "[Release] Flash (blackmagic)",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_blackmagic"
},
{
"label": "[Debug] Flash (blackmagic)",
"group": "build",
"type": "shell",
"command": "./fbt FORCE=1 flash_blackmagic"
},
{
"label": "[Release] Flash (JLink)",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 jflash"
},
{
"label": "[Debug] Flash (JLink)",
"group": "build",
"type": "shell",
"command": "./fbt FORCE=1 jflash"
},
{
"label": "[Release] Build update bundle",
"group": "build",
"type": "shell",
"command": "./fbt update_package COMPACT=1 DEBUG=0"
},
{
"label": "[Debug] Build update bundle",
"group": "build",
"type": "shell",
"command": "./fbt update_package"
},
{
"label": "[Release] Build updater",
"group": "build",
"type": "shell",
"command": "./fbt updater_all COMPACT=1 DEBUG=0"
},
{
"label": "[Debug] Build updater",
"group": "build",
"type": "shell",
"command": "./fbt updater_all"
},
{
"label": "[Debug] Flash (USB, w/o resources)",
"group": "build",
"type": "shell",
"command": "./fbt FORCE=1 flash_usb"
},
{
"label": "[Release] Flash (USB, w/o resources)",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb"
},
{
"label": "[Debug:unit_tests] Flash (USB)",
"group": "build",
"type": "shell",
"command": "./fbt FIRMWARE_APP_SET=unit_tests FORCE=1 flash_usb"
},
{
"label": "[Release] Flash (USB, with resources)",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full"
},
]
}
+15
View File
@@ -0,0 +1,15 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
// List of extensions which should be recommended for users of this workspace.
"recommendations": [
"ms-python.black-formatter",
"ms-vscode.cpptools",
"amiralizadeh9480.cpp-helper",
"marus25.cortex-debug",
"zxh404.vscode-proto3",
"augustocdias.tasks-shell-input"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": []
}
+2 -2
View File
@@ -29,11 +29,11 @@ They both must be flashed in the order described.
With Flipper attached over USB:
`./fbt --with-updater flash_usb`
`./fbt flash_usb`
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.
+91 -23
View File
@@ -7,6 +7,7 @@
# construction of certain targets behind command-line options.
import os
import subprocess
EnsurePythonVersion(3, 8)
@@ -33,8 +34,10 @@ coreenv["ROOT_DIR"] = Dir(".")
# Create a separate "dist" environment and add construction envs to it
distenv = coreenv.Clone(
tools=["fbt_dist", "openocd", "blackmagic"],
OPENOCD_GDB_PIPE=["|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"],
tools=["fbt_dist", "openocd", "blackmagic", "jflash"],
OPENOCD_GDB_PIPE=[
"|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"
],
GDBOPTS_BASE=[
"-ex",
"target extended-remote ${GDBREMOTE}",
@@ -61,6 +64,7 @@ distenv = coreenv.Clone(
"-ex",
"compare-sections",
],
JFLASHPROJECT="${ROOT_DIR.abspath}/debug/fw.jflash",
ENV=os.environ,
)
@@ -71,7 +75,9 @@ firmware_env = distenv.AddFwProject(
)
# 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(
base_env=coreenv,
fw_type="updater",
@@ -79,11 +85,11 @@ if GetOption("fullenv"):
)
# Target for self-update package
dist_arguments = [
"-r",
'"${ROOT_DIR.abspath}/assets/resources"',
dist_basic_arguments = [
"--bundlever",
'"${UPDATE_VERSION_STRING}"',
]
dist_radio_arguments = [
"--radio",
'"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"',
"--radiotype",
@@ -92,16 +98,34 @@ if GetOption("fullenv"):
"--obdata",
'"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"',
]
if distenv["UPDATE_SPLASH"]:
dist_arguments += [
dist_resource_arguments = [
"-r",
'"${ROOT_DIR.abspath}/assets/resources"',
]
dist_splash_arguments = (
[
"--splash",
distenv.subst("assets/slideshow/$UPDATE_SPLASH"),
]
if distenv["UPDATE_SPLASH"]
else []
)
selfupdate_dist = distenv.DistCommand(
"updater_package",
(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
@@ -121,18 +145,16 @@ if GetOption("fullenv"):
)
# Installation over USB & CLI
usb_update_package = distenv.UsbInstall(
"#build/usbinstall.flag",
(
distenv["DIST_DEPENDS"],
firmware_env["FW_RESOURCES"],
selfupdate_dist,
),
usb_update_package = distenv.AddUsbFlashTarget(
"#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist)
)
if distenv["FORCE"]:
distenv.AlwaysBuild(usb_update_package)
distenv.Depends(usb_update_package, selfupdate_dist)
distenv.Alias("flash_usb", usb_update_package)
distenv.Alias("flash_usb_full", usb_update_package)
usb_minupdate_package = distenv.AddUsbFlashTarget(
"#build/minusbinstall.flag", (selfupdate_min_dist,)
)
distenv.Alias("flash_usb", usb_minupdate_package)
# Target for copying & renaming binaries to dist folder
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)
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(
"flash_blackmagic",
@@ -209,10 +232,55 @@ distenv.PhonyTarget(
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
distenv.PhonyTarget(
"get_blackmagic",
"@echo $( ${BLACKMAGIC_ADDR} $)",
)
# Prepare vscode environment
vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*"))
distenv.Precious(vscode_dist)
distenv.NoClean(vscode_dist)
distenv.Alias("vscode_dist", vscode_dist)
+4 -4
View File
@@ -45,7 +45,7 @@ static DialogMessageButton compliance_screen(DialogsApp* dialogs, DialogMessage*
DialogMessageButton result;
const char* screen_text = "For all compliance\n"
"certificates please visit\n"
"certificates please visit:\n"
"www.flipp.dev/compliance";
dialog_message_set_text(message, screen_text, 0, 0, AlignLeft, AlignTop);
@@ -91,13 +91,13 @@ static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage*
furi_hal_version_get_hw_region_name(),
my_name ? my_name : "Unknown");
string_cat_printf(buffer, "Serial number:\n");
string_cat_printf(buffer, "Serial Number:\n");
const uint8_t* uid = furi_hal_version_uid();
for(size_t i = 0; i < furi_hal_version_uid_size(); i++) {
string_cat_printf(buffer, "%02X", uid[i]);
}
dialog_message_set_header(message, "HW Version info:", 0, 0, AlignLeft, AlignTop);
dialog_message_set_header(message, "HW Version Info:", 0, 0, AlignLeft, AlignTop);
dialog_message_set_text(message, string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop);
result = dialog_message_show(dialogs, message);
dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop);
@@ -133,7 +133,7 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage*
version_get_gitbranch(ver));
}
dialog_message_set_header(message, "FW Version info:", 0, 0, AlignLeft, AlignTop);
dialog_message_set_header(message, "FW Version Info:", 0, 0, AlignLeft, AlignTop);
dialog_message_set_text(message, string_get_cstr(buffer), 0, 13, AlignLeft, AlignTop);
result = dialog_message_show(dialogs, message);
dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop);
@@ -92,8 +92,6 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
ArchiveBrowserView* browser = archive->browser;
ArchiveFile_t* selected = archive_get_current_file(browser);
const char* name = archive_get_name(browser);
bool known_app = archive_is_known_app(selected->type);
bool favorites = archive_get_tab(browser) == ArchiveTabFavorites;
bool consumed = false;
@@ -108,18 +106,19 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
consumed = true;
break;
case ArchiveBrowserEventFileMenuRun:
if(known_app) {
if(archive_is_known_app(selected->type)) {
archive_run_in_app(browser, selected);
archive_show_file_menu(browser, false);
}
consumed = true;
break;
case ArchiveBrowserEventFileMenuPin:
case ArchiveBrowserEventFileMenuPin: {
const char* name = archive_get_name(browser);
if(favorites) {
archive_favorites_delete(name);
archive_file_array_rm_selected(browser);
archive_show_file_menu(browser, false);
} else if(known_app) {
} else if(archive_is_known_app(selected->type)) {
if(archive_is_favorite("%s", name)) {
archive_favorites_delete("%s", name);
} else {
@@ -128,12 +127,12 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
archive_show_file_menu(browser, false);
}
consumed = true;
break;
} break;
case ArchiveBrowserEventFileMenuRename:
if(favorites) {
browser->callback(ArchiveBrowserEventEnterFavMove, browser->context);
} else if((known_app) && (selected->is_app == false)) {
} else if((archive_is_known_app(selected->type)) && (selected->is_app == false)) {
archive_show_file_menu(browser, false);
scene_manager_set_scene_state(
archive->scene_manager, ArchiveAppSceneBrowser, SCENE_STATE_NEED_REFRESH);
@@ -37,7 +37,7 @@ void archive_scene_rename_on_enter(void* context) {
false);
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(archive->browser->path), archive->file_extension, NULL);
string_get_cstr(archive->browser->path), archive->file_extension, "");
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
string_clear(filename);
+1 -2
View File
@@ -28,7 +28,7 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
string_init(app->file_path);
if(arg != NULL) {
if(arg && strlen(arg)) {
string_set_str(app->file_path, arg);
}
@@ -79,7 +79,6 @@ void bad_usb_app_free(BadUsbApp* app) {
furi_assert(app);
// Views
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewFileSelect);
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork);
bad_usb_free(app->bad_usb_view);
-1
View File
@@ -38,6 +38,5 @@ struct BadUsbApp {
typedef enum {
BadUsbAppViewError,
BadUsbAppViewFileSelect,
BadUsbAppViewWork,
} BadUsbAppView;
+2 -2
View File
@@ -90,7 +90,7 @@ BtHid* bt_hid_app_alloc() {
submenu_add_item(
app->submenu, "Keyboard", BtHidSubmenuIndexKeyboard, bt_hid_submenu_callback, app);
submenu_add_item(
app->submenu, "Media player", BtHidSubmenuIndexMedia, bt_hid_submenu_callback, app);
app->submenu, "Media Player", BtHidSubmenuIndexMedia, bt_hid_submenu_callback, app);
submenu_add_item(app->submenu, "Mouse", BtHidSubmenuIndexMouse, bt_hid_submenu_callback, app);
view_set_previous_callback(submenu_get_view(app->submenu), bt_hid_exit);
view_dispatcher_add_view(
@@ -103,7 +103,7 @@ BtHid* bt_hid_app_alloc() {
dialog_ex_set_left_button_text(app->dialog, "Exit");
dialog_ex_set_right_button_text(app->dialog, "Stay");
dialog_ex_set_center_button_text(app->dialog, "Menu");
dialog_ex_set_header(app->dialog, "Close current app?", 16, 12, AlignLeft, AlignTop);
dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop);
view_dispatcher_add_view(
app->view_dispatcher, BtHidViewExitConfirm, dialog_ex_get_view(app->dialog));
+2 -1
View File
@@ -347,7 +347,8 @@ static void bt_close_connection(Bt* bt) {
furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT);
}
int32_t bt_srv() {
int32_t bt_srv(void* p) {
UNUSED(p);
Bt* bt = bt_alloc();
if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
@@ -10,9 +10,9 @@ void bt_settings_scene_forget_dev_confirm_dialog_callback(DialogExResult result,
void bt_settings_scene_forget_dev_confirm_on_enter(void* context) {
BtSettingsApp* app = context;
DialogEx* dialog = app->dialog;
dialog_ex_set_header(dialog, "Unpair all devices?", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_header(dialog, "Unpair All Devices?", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_text(
dialog, "All previous pairings\nwill be lost.", 64, 22, AlignCenter, AlignTop);
dialog, "All previous pairings\nwill be lost!", 64, 22, AlignCenter, AlignTop);
dialog_ex_set_left_button_text(dialog, "Back");
dialog_ex_set_right_button_text(dialog, "Unpair");
dialog_ex_set_context(dialog, app);
+5 -5
View File
@@ -439,9 +439,9 @@ void cli_session_open(Cli* cli, void* session) {
cli->session = session;
if(cli->session != NULL) {
cli->session->init();
furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout);
furi_thread_set_stdout_callback(cli->session->tx_stdout);
} else {
furi_stdglue_set_thread_stdout_callback(NULL);
furi_thread_set_stdout_callback(NULL);
}
furi_semaphore_release(cli->idle_sem);
furi_check(furi_mutex_release(cli->mutex) == FuriStatusOk);
@@ -455,7 +455,7 @@ void cli_session_close(Cli* cli) {
cli->session->deinit();
}
cli->session = NULL;
furi_stdglue_set_thread_stdout_callback(NULL);
furi_thread_set_stdout_callback(NULL);
furi_check(furi_mutex_release(cli->mutex) == FuriStatusOk);
}
@@ -469,9 +469,9 @@ int32_t cli_srv(void* p) {
furi_record_create(RECORD_CLI, cli);
if(cli->session != NULL) {
furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout);
furi_thread_set_stdout_callback(cli->session->tx_stdout);
} else {
furi_stdglue_set_thread_stdout_callback(NULL);
furi_thread_set_stdout_callback(NULL);
}
if(furi_hal_rtc_get_boot_mode() == FuriHalRtcBootModeNormal) {
+1 -1
View File
@@ -25,7 +25,7 @@ struct CliSession {
void (*deinit)(void);
size_t (*rx)(uint8_t* buffer, size_t size, uint32_t timeout);
void (*tx)(const uint8_t* buffer, size_t size);
void (*tx_stdout)(void* _cookie, const char* data, size_t size);
void (*tx_stdout)(const char* data, size_t size);
bool (*is_connected)(void);
};
+1 -2
View File
@@ -277,8 +277,7 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) {
#endif
}
static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) {
UNUSED(_cookie);
static void cli_vcp_tx_stdout(const char* data, size_t size) {
cli_vcp_tx((const uint8_t*)data, size);
}
+5 -5
View File
@@ -26,11 +26,11 @@ static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
canvas_clear(canvas);
char strings[5][20];
sprintf(strings[0], "Ok: %d", state->ok);
sprintf(strings[1], "L: %d", state->left);
sprintf(strings[2], "R: %d", state->right);
sprintf(strings[3], "U: %d", state->up);
sprintf(strings[4], "D: %d", state->down);
snprintf(strings[0], 20, "Ok: %d", state->ok);
snprintf(strings[1], 20, "L: %d", state->left);
snprintf(strings[2], 20, "R: %d", state->right);
snprintf(strings[3], 20, "U: %d", state->up);
snprintf(strings[4], 20, "D: %d", state->down);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 0, 10, "Keypad test");
@@ -143,7 +143,7 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) {
furi_assert(view);
bool activate = true;
BubbleAnimationViewModel* model = view_get_model(view->view);
if(!model->current) {
if(model->current == NULL) {
activate = false;
} else if(model->freeze_frame) {
activate = false;
@@ -151,14 +151,16 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) {
activate = false;
}
if(!force) {
if((model->active_ended_at + model->current->active_cooldown * 1000) >
xTaskGetTickCount()) {
activate = false;
} else if(model->active_shift) {
activate = false;
} else if(model->current_frame >= model->current->passive_frames) {
activate = false;
if(model->current != NULL) {
if(!force) {
if((model->active_ended_at + model->current->active_cooldown * 1000) >
xTaskGetTickCount()) {
activate = false;
} else if(model->active_shift) {
activate = false;
} else if(model->current_frame >= model->current->passive_frames) {
activate = false;
}
}
}
view_commit_model(view->view, false);
@@ -288,7 +290,10 @@ static void bubble_animation_enter(void* context) {
bubble_animation_activate(view, false);
BubbleAnimationViewModel* model = view_get_model(view->view);
uint8_t frame_rate = model->current->icon_animation.frame_rate;
uint8_t frame_rate = 0;
if(model->current != NULL) {
frame_rate = model->current->icon_animation.frame_rate;
}
view_commit_model(view->view, false);
if(frame_rate) {
@@ -90,7 +90,7 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
extern int32_t desktop_settings_app(void* p) {
DesktopSettingsApp* app = desktop_settings_app_alloc();
LOAD_DESKTOP_SETTINGS(&app->settings);
if(!strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG)) {
if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) {
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto);
} else {
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart);
@@ -23,7 +23,7 @@ void desktop_debug_render(Canvas* canvas, void* model) {
const Version* ver;
char buffer[64];
static const char* headers[] = {"FW Version info:", "Dolphin info:"};
static const char* headers[] = {"FW Version Info:", "Dolphin Info:"};
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
@@ -78,7 +78,6 @@ void desktop_debug_render(Canvas* canvas, void* model) {
canvas_draw_str(canvas, 5, 50 + STATUS_BAR_Y_SHIFT, buffer);
} else {
char buffer[64];
Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN);
DolphinStats stats = dolphin_stats(dolphin);
furi_record_close(RECORD_DOLPHIN);
@@ -87,18 +86,20 @@ void desktop_debug_render(Canvas* canvas, void* model) {
uint32_t remaining = dolphin_state_xp_to_levelup(m->icounter);
canvas_set_font(canvas, FontSecondary);
snprintf(buffer, 64, "Icounter: %ld Butthurt %ld", m->icounter, m->butthurt);
snprintf(buffer, sizeof(buffer), "Icounter: %ld Butthurt %ld", m->icounter, m->butthurt);
canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer);
snprintf(
buffer,
64,
sizeof(buffer),
"Level: %ld To level up: %ld",
current_lvl,
(remaining == (uint32_t)(-1) ? remaining : 0));
canvas_draw_str(canvas, 5, 29 + STATUS_BAR_Y_SHIFT, buffer);
snprintf(buffer, 64, "%s", asctime(localtime((const time_t*)&m->timestamp)));
// even if timestamp is uint64_t, it's safe to cast it to uint32_t, because furi_hal_rtc_datetime_to_timestamp only returns uint32_t
snprintf(buffer, sizeof(buffer), "%ld", (uint32_t)m->timestamp);
canvas_draw_str(canvas, 5, 39 + STATUS_BAR_Y_SHIFT, buffer);
canvas_draw_str(canvas, 0, 49 + STATUS_BAR_Y_SHIFT, "[< >] icounter value [ok] save");
}
@@ -67,7 +67,7 @@ void desktop_lock_menu_render(Canvas* canvas, void* model) {
const char* str = Lockmenu_Items[i];
if(i == 1 && !m->pin_set) str = "Set PIN";
if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not implemented";
if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not Implemented";
if(str != NULL)
canvas_draw_str_aligned(
+2
View File
@@ -38,6 +38,8 @@ appenv.AppendUnique(
"-Wl,--no-export-dynamic",
"-fvisibility=hidden",
"-Wl,-e${APP_ENTRY}",
"-Xlinker",
"-Map=${TARGET}.map",
],
)
+1 -1
View File
@@ -20,7 +20,7 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event);
static void gpio_test_draw_callback(Canvas* canvas, void* _model) {
GpioTestModel* model = _model;
canvas_set_font(canvas, FontPrimary);
elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Gpio Output mode test");
elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "GPIO Output Mode Test");
canvas_set_font(canvas, FontSecondary);
elements_multiline_text_aligned(
canvas, 64, 16, AlignCenter, AlignTop, "Press < or > to change pin");
+11 -9
View File
@@ -185,17 +185,19 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) {
return false;
});
if(item->type == ButtonMenuItemTypeControl) {
if(type == InputTypeShort) {
if(item && item->callback) {
item->callback(item->callback_context, item->index, type);
if(item) {
if(item->type == ButtonMenuItemTypeControl) {
if(type == InputTypeShort) {
if(item && item->callback) {
item->callback(item->callback_context, item->index, type);
}
}
}
}
if(item->type == ButtonMenuItemTypeCommon) {
if((type == InputTypePress) || (type == InputTypeRelease)) {
if(item && item->callback) {
item->callback(item->callback_context, item->index, type);
if(item->type == ButtonMenuItemTypeCommon) {
if((type == InputTypePress) || (type == InputTypeRelease)) {
if(item && item->callback) {
item->callback(item->callback_context, item->index, type);
}
}
}
}
+1 -1
View File
@@ -147,7 +147,7 @@ static void text_input_backspace_cb(TextInputModel* model) {
static void text_input_view_draw_callback(Canvas* canvas, void* _model) {
TextInputModel* model = _model;
uint8_t text_length = strlen(model->text_buffer);
uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
uint8_t needed_string_width = canvas_width(canvas) - 8;
uint8_t start_pos = 4;
+1 -1
View File
@@ -1,7 +1,7 @@
#pragma once
// #include <gui/view.h>
#include <m-string.h>
#include <core/common_defines.h>
#ifdef __cplusplus
extern "C" {
+9 -41
View File
@@ -5,24 +5,10 @@
#include "m-string.h"
#include <toolbox/path.h>
#include <flipper_format/flipper_format.h>
#include "rpc/rpc_app.h"
#include <rpc/rpc_app.h>
#define TAG "iButtonApp"
static const NotificationSequence sequence_blink_start_cyan = {
&message_blink_start_10,
&message_blink_set_color_cyan,
&message_do_not_reset,
NULL,
};
static const NotificationSequence sequence_blink_start_magenta = {
&message_blink_start_10,
&message_blink_set_color_magenta,
&message_do_not_reset,
NULL,
};
static const NotificationSequence sequence_blink_set_yellow = {
&message_blink_set_color_yellow,
NULL,
@@ -33,11 +19,6 @@ static const NotificationSequence sequence_blink_set_magenta = {
NULL,
};
static const NotificationSequence sequence_blink_stop = {
&message_blink_stop,
NULL,
};
static const NotificationSequence* ibutton_notification_sequences[] = {
&sequence_error,
&sequence_success,
@@ -58,7 +39,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);
bool result = false;
string_t data;
@@ -99,33 +80,20 @@ static bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show
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);
iButton* ibutton = context;
bool result = false;
if(event == RpcAppEventSessionClose) {
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
ibutton->rpc_ctx = NULL;
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
result = true;
view_dispatcher_send_custom_event(
ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose);
} else if(event == RpcAppEventAppExit) {
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
result = true;
} else if(event == RpcAppEventLoadFile) {
if(arg) {
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);
view_dispatcher_send_custom_event(
ibutton->view_dispatcher, iButtonCustomEventRpcLoad);
result = true;
}
}
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoad);
} else {
rpc_system_app_confirm(ibutton->rpc_ctx, event, false);
}
return result;
}
bool ibutton_custom_event_callback(void* context, uint32_t event) {
@@ -366,7 +334,7 @@ int32_t ibutton_app(void* p) {
bool key_loaded = false;
bool rpc_mode = false;
if(p) {
if(p && strlen(p)) {
uint32_t rpc_ctx = 0;
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
FURI_LOG_D(TAG, "Running in RPC mode");
@@ -12,4 +12,5 @@ enum iButtonCustomEvent {
iButtonCustomEventRpcLoad,
iButtonCustomEventRpcExit,
iButtonCustomEventRpcSessionClose,
};
+1
View File
@@ -78,6 +78,7 @@ typedef enum {
} iButtonNotificationMessage;
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_delete_key(iButton* ibutton);
void ibutton_text_store_set(iButton* ibutton, const char* text, ...);
@@ -21,7 +21,7 @@ void ibutton_scene_exit_confirm_on_enter(void* context) {
widget_add_string_element(
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to iButton menu?");
widget_add_string_element(
widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost.");
widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
}
@@ -14,7 +14,7 @@ void ibutton_scene_read_on_enter(void* context) {
DOLPHIN_DEED(DolphinDeedIbuttonRead);
popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom);
popup_set_text(popup, "waiting\nfor key ...", 95, 30, AlignCenter, AlignTop);
popup_set_text(popup, "Waiting\nfor key ...", 95, 30, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
@@ -21,7 +21,7 @@ void ibutton_scene_retry_confirm_on_enter(void* context) {
widget_add_string_element(
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?");
widget_add_string_element(
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost.");
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
}
+33 -15
View File
@@ -1,5 +1,6 @@
#include "../ibutton_i.h"
#include <toolbox/path.h>
#include <rpc/rpc_app.h>
void ibutton_scene_rpc_on_enter(void* context) {
iButton* ibutton = context;
@@ -26,23 +27,40 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
consumed = true;
if(event.event == iButtonCustomEventRpcLoad) {
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);
const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx);
bool result = false;
if(arg) {
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;
}
}
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);
rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result);
} 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);
view_dispatcher_stop(ibutton->view_dispatcher);
}
+22 -45
View File
@@ -7,10 +7,12 @@ static const NotificationSequence* infrared_notification_sequences[] = {
&sequence_success,
&sequence_set_only_green_255,
&sequence_reset_green,
&sequence_blink_cyan_10,
&sequence_blink_magenta_10,
&sequence_solid_yellow,
&sequence_reset_rgb};
&sequence_reset_rgb,
&sequence_blink_start_cyan,
&sequence_blink_start_magenta,
&sequence_blink_stop,
};
static void infrared_make_app_folder(Infrared* infrared) {
if(!storage_simply_mkdir(infrared->storage, INFRARED_APP_FOLDER)) {
@@ -36,52 +38,29 @@ static void infrared_tick_event_callback(void* context) {
scene_manager_handle_tick_event(infrared->scene_manager);
}
static bool
infrared_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context) {
furi_assert(context);
Infrared* infrared = context;
if(!infrared->rpc_ctx) {
return false;
}
bool result = false;
furi_assert(infrared->rpc_ctx);
if(event == RpcAppEventSessionClose) {
rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
infrared->rpc_ctx = NULL;
view_dispatcher_send_custom_event(
infrared->view_dispatcher, InfraredCustomEventTypeBackPressed);
result = true;
infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose);
} else if(event == RpcAppEventAppExit) {
view_dispatcher_send_custom_event(
infrared->view_dispatcher, InfraredCustomEventTypeBackPressed);
result = true;
infrared->view_dispatcher, InfraredCustomEventTypeRpcExit);
} else if(event == RpcAppEventLoadFile) {
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);
view_dispatcher_send_custom_event(
infrared->view_dispatcher, InfraredCustomEventTypeRpcLoaded);
}
view_dispatcher_send_custom_event(
infrared->view_dispatcher, InfraredCustomEventTypeRpcLoad);
} else if(event == RpcAppEventButtonPress) {
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;
}
}
view_dispatcher_send_custom_event(
infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPress);
} else if(event == RpcAppEventButtonRelease) {
infrared_tx_stop(infrared);
result = true;
view_dispatcher_send_custom_event(
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) {
@@ -324,6 +303,7 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {
DOLPHIN_DEED(DolphinDeedIrSend);
infrared_worker_tx_start(infrared->worker);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
}
void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) {
@@ -333,14 +313,17 @@ void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) {
InfraredSignal* signal = infrared_remote_button_get_signal(button);
infrared_tx_start_signal(infrared, signal);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
}
void infrared_tx_start_received(Infrared* infrared) {
infrared_tx_start_signal(infrared, infrared->received_signal);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
}
void infrared_tx_stop(Infrared* infrared) {
infrared_worker_tx_stop(infrared->worker);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
}
void infrared_text_store_set(Infrared* infrared, uint32_t bank, const char* text, ...) {
@@ -377,12 +360,6 @@ void infrared_show_loading_popup(Infrared* infrared, bool show) {
}
}
void infrared_signal_sent_callback(void* context) {
furi_assert(context);
Infrared* infrared = context;
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkSend);
}
void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal) {
furi_assert(context);
Infrared* infrared = context;
@@ -428,7 +405,7 @@ int32_t infrared_app(void* p) {
bool is_remote_loaded = false;
bool is_rpc_mode = false;
if(p) {
if(p && strlen(p)) {
uint32_t rpc_ctx = 0;
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
infrared->rpc_ctx = (void*)rpc_ctx;
+4 -4
View File
@@ -27,7 +27,7 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv
if(infrared_worker_signal_is_decoded(received_signal)) {
const InfraredMessage* message = infrared_worker_get_decoded_signal(received_signal);
buf_cnt = sniprintf(
buf_cnt = snprintf(
buf,
sizeof(buf),
"%s, A:0x%0*lX, C:0x%0*lX%s\r\n",
@@ -43,13 +43,13 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv
size_t timings_cnt;
infrared_worker_get_raw_signal(received_signal, &timings, &timings_cnt);
buf_cnt = sniprintf(buf, sizeof(buf), "RAW, %d samples:\r\n", timings_cnt);
buf_cnt = snprintf(buf, sizeof(buf), "RAW, %d samples:\r\n", timings_cnt);
cli_write(cli, (uint8_t*)buf, buf_cnt);
for(size_t i = 0; i < timings_cnt; ++i) {
buf_cnt = sniprintf(buf, sizeof(buf), "%lu ", timings[i]);
buf_cnt = snprintf(buf, sizeof(buf), "%lu ", timings[i]);
cli_write(cli, (uint8_t*)buf, buf_cnt);
}
buf_cnt = sniprintf(buf, sizeof(buf), "\r\n");
buf_cnt = snprintf(buf, sizeof(buf), "\r\n");
cli_write(cli, (uint8_t*)buf, buf_cnt);
}
}
@@ -14,7 +14,12 @@ enum InfraredCustomEventType {
InfraredCustomEventTypePopupClosed,
InfraredCustomEventTypeButtonSelected,
InfraredCustomEventTypeBackPressed,
InfraredCustomEventTypeRpcLoaded,
InfraredCustomEventTypeRpcLoad,
InfraredCustomEventTypeRpcExit,
InfraredCustomEventTypeRpcButtonPress,
InfraredCustomEventTypeRpcButtonRelease,
InfraredCustomEventTypeRpcSessionClose,
};
#pragma pack(push, 1)
+3 -3
View File
@@ -115,10 +115,11 @@ typedef enum {
InfraredNotificationMessageSuccess,
InfraredNotificationMessageGreenOn,
InfraredNotificationMessageGreenOff,
InfraredNotificationMessageBlinkRead,
InfraredNotificationMessageBlinkSend,
InfraredNotificationMessageYellowOn,
InfraredNotificationMessageYellowOff,
InfraredNotificationMessageBlinkStartRead,
InfraredNotificationMessageBlinkStartSend,
InfraredNotificationMessageBlinkStop,
} InfraredNotificationMessage;
bool infrared_add_remote_with_button(Infrared* infrared, const char* name, InfraredSignal* signal);
@@ -132,7 +133,6 @@ void infrared_text_store_clear(Infrared* infrared, uint32_t bank);
void infrared_play_notification_message(Infrared* infrared, uint32_t message);
void infrared_show_loading_popup(Infrared* infrared, bool show);
void infrared_signal_sent_callback(void* context);
void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal);
void infrared_text_input_callback(void* context);
void infrared_popup_closed_callback(void* context);
@@ -21,12 +21,14 @@ static void infrared_scene_universal_common_show_popup(Infrared* infrared, uint3
infrared_progress_view_set_back_callback(
progress, infrared_scene_universal_common_progress_back_callback, infrared);
view_stack_add_view(view_stack, infrared_progress_view_get_view(progress));
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
}
static void infrared_scene_universal_common_hide_popup(Infrared* infrared) {
ViewStack* view_stack = infrared->view_stack;
InfraredProgressView* progress = infrared->progress;
view_stack_remove_view(view_stack, infrared_progress_view_get_view(progress));
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
}
void infrared_scene_universal_common_on_enter(void* context) {
@@ -42,7 +44,6 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e
if(infrared_brute_force_is_started(brute_force)) {
if(event.type == SceneManagerEventTypeTick) {
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkSend);
bool success = infrared_brute_force_send_next(brute_force);
if(success) {
success = infrared_progress_view_increase_progress(infrared->progress);
@@ -71,8 +72,6 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e
brute_force, infrared_custom_event_get_value(event.event), &record_count)) {
DOLPHIN_DEED(DolphinDeedIrBruteForce);
infrared_scene_universal_common_show_popup(infrared, record_count);
infrared_play_notification_message(
infrared, InfraredNotificationMessageBlinkSend);
} else {
scene_manager_next_scene(scene_manager, InfraredSceneErrorDatabases);
}
@@ -10,13 +10,13 @@ void infrared_scene_ask_back_on_enter(void* context) {
DialogEx* dialog_ex = infrared->dialog_ex;
if(infrared->app_state.is_learning_new_remote) {
dialog_ex_set_header(dialog_ex, "Exit to Infrared menu?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "Exit to Infrared Menu?", 64, 0, AlignCenter, AlignTop);
} else {
dialog_ex_set_header(dialog_ex, "Exit to remote menu?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "Exit to Remote Menu?", 64, 0, AlignCenter, AlignTop);
}
dialog_ex_set_text(
dialog_ex, "All unsaved data\nwill be lost.", 64, 31, AlignCenter, AlignCenter);
dialog_ex, "All unsaved data\nwill be lost!", 64, 31, AlignCenter, AlignCenter);
dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
dialog_ex_set_left_button_text(dialog_ex, "Exit");
dialog_ex_set_center_button_text(dialog_ex, NULL);
@@ -9,9 +9,9 @@ void infrared_scene_ask_retry_on_enter(void* context) {
Infrared* infrared = context;
DialogEx* dialog_ex = infrared->dialog_ex;
dialog_ex_set_header(dialog_ex, "Return to reading?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "Return to Reading?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_text(
dialog_ex, "All unsaved data\nwill be lost.", 64, 31, AlignCenter, AlignCenter);
dialog_ex, "All unsaved data\nwill be lost!", 64, 31, AlignCenter, AlignCenter);
dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
dialog_ex_set_left_button_text(dialog_ex, "Exit");
dialog_ex_set_center_button_text(dialog_ex, NULL);
@@ -65,4 +65,5 @@ void infrared_scene_debug_on_exit(void* context) {
InfraredWorker* worker = infrared->worker;
infrared_worker_rx_stop(worker);
infrared_worker_rx_enable_blink_on_receiving(worker, false);
infrared_worker_rx_set_received_signal_callback(worker, NULL, NULL);
}
@@ -16,7 +16,7 @@ void infrared_scene_edit_delete_on_enter(void* context) {
int32_t current_button_index = infrared->app_state.current_button_index;
furi_assert(current_button_index != InfraredButtonIndexNone);
dialog_ex_set_header(dialog_ex, "Delete button?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "Delete Button?", 64, 0, AlignCenter, AlignTop);
InfraredRemoteButton* current_button =
infrared_remote_get_button(remote, current_button_index);
InfraredSignal* signal = infrared_remote_button_get_signal(current_button);
@@ -45,7 +45,7 @@ void infrared_scene_edit_delete_on_enter(void* context) {
}
} else if(edit_target == InfraredEditTargetRemote) {
dialog_ex_set_header(dialog_ex, "Delete remote?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "Delete Remote?", 64, 0, AlignCenter, AlignTop);
infrared_text_store_set(
infrared,
0,
@@ -8,6 +8,7 @@ void infrared_scene_learn_on_enter(void* context) {
infrared_worker_rx_set_received_signal_callback(
worker, infrared_signal_received_callback, context);
infrared_worker_rx_start(worker);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartRead);
popup_set_icon(popup, 0, 32, &I_InfraredLearnShort_128x31);
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignCenter);
@@ -22,10 +23,7 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) {
Infrared* infrared = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeTick) {
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkRead);
consumed = true;
} else if(event.type == SceneManagerEventTypeCustom) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == InfraredCustomEventTypeSignalReceived) {
infrared_worker_rx_set_received_signal_callback(infrared->worker, NULL, NULL);
infrared_play_notification_message(infrared, InfraredNotificationMessageSuccess);
@@ -41,6 +39,7 @@ void infrared_scene_learn_on_exit(void* context) {
Infrared* infrared = context;
Popup* popup = infrared->popup;
infrared_worker_rx_stop(infrared->worker);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
popup_set_icon(popup, 0, 0, NULL);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignCenter);
}
@@ -23,8 +23,6 @@ void infrared_scene_learn_success_on_enter(void* context) {
infrared_worker_tx_set_get_signal_callback(
infrared->worker, infrared_worker_tx_get_signal_steady_callback, context);
infrared_worker_tx_set_signal_sent_callback(
infrared->worker, infrared_signal_sent_callback, context);
if(infrared_signal_is_raw(signal)) {
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
@@ -104,6 +102,8 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even
InfraredSceneLearnSuccess,
InfraredSceneLearnSuccessStateSending);
infrared_tx_start_received(infrared);
infrared_play_notification_message(
infrared, InfraredNotificationMessageBlinkStartSend);
}
consumed = true;
} else if(event.event == DialogExReleaseCenter) {
@@ -111,6 +111,7 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even
scene_manager_set_scene_state(
scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle);
infrared_tx_stop(infrared);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
}
consumed = true;
@@ -124,7 +125,7 @@ void infrared_scene_learn_success_on_exit(void* context) {
Infrared* infrared = context;
InfraredWorker* worker = infrared->worker;
dialog_ex_reset(infrared->dialog_ex);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
infrared_worker_tx_set_get_signal_callback(worker, NULL, NULL);
infrared_worker_tx_set_signal_sent_callback(worker, NULL, NULL);
}
@@ -33,8 +33,6 @@ void infrared_scene_remote_on_enter(void* context) {
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);
size_t button_count = infrared_remote_get_button_count(remote);
for(size_t i = 0; i < button_count; ++i) {
@@ -112,7 +110,7 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
void infrared_scene_remote_on_exit(void* context) {
Infrared* infrared = context;
infrared_tx_stop(infrared);
infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL);
infrared_worker_tx_set_signal_sent_callback(infrared->worker, NULL, NULL);
button_menu_reset(infrared->button_menu);
}
@@ -28,12 +28,43 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
view_dispatcher_stop(infrared->view_dispatcher);
} else if(event.event == InfraredCustomEventTypePopupClosed) {
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);
}
const char* remote_name = infrared_remote_get_name(infrared->remote);
infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name);
popup_set_text(
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;
@@ -41,5 +72,6 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
void infrared_scene_rpc_on_exit(void* context) {
Infrared* infrared = context;
infrared_tx_stop(infrared);
popup_reset(infrared->popup);
}
+2 -1
View File
@@ -64,7 +64,8 @@ const char* input_get_type_name(InputType type) {
return "Unknown";
}
int32_t input_srv() {
int32_t input_srv(void* p) {
UNUSED(p);
input = malloc(sizeof(Input));
input->thread_id = furi_thread_get_current_id();
input->event_pubsub = furi_pubsub_alloc();
+12 -25
View File
@@ -25,7 +25,7 @@
#include <toolbox/path.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_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);
LfRfidApp* app = static_cast<LfRfidApp*>(context);
bool result = false;
if(event == RpcAppEventSessionClose) {
rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
app->rpc_ctx = NULL;
if(rpc_event == RpcAppEventSessionClose) {
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::RpcSessionClose;
app->view_controller.send_event(&event);
} else if(rpc_event == RpcAppEventAppExit) {
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Exit;
app->view_controller.send_event(&event);
result = true;
} else if(event == RpcAppEventAppExit) {
} else if(rpc_event == RpcAppEventLoadFile) {
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Exit;
event.type = LfRfidApp::EventType::RpcLoadFile;
app->view_controller.send_event(&event);
result = true;
} else if(event == RpcAppEventLoadFile) {
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;
}
}
} else {
rpc_system_app_confirm(app->rpc_ctx, rpc_event, false);
}
return result;
}
void LfRfidApp::run(void* _args) {
@@ -87,7 +74,7 @@ void LfRfidApp::run(void* _args) {
make_app_folder();
if(strlen(args)) {
if(args && strlen(args)) {
uint32_t rpc_ctx_ptr = 0;
if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) {
rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
+2
View File
@@ -33,6 +33,8 @@ public:
Retry,
Exit,
EmulateStart,
RpcLoadFile,
RpcSessionClose,
};
enum class SceneType : uint8_t {
+1 -1
View File
@@ -107,7 +107,7 @@ static void lfrfid_cli_write(Cli* cli, string_t args) {
UNUSED(cli);
UNUSED(args);
// TODO implement rfid write
printf("Not implemented :(\r\n");
printf("Not Implemented :(\r\n");
}
static void lfrfid_cli_emulate(Cli* cli, string_t args) {
@@ -2,18 +2,6 @@
#include <core/common_defines.h>
#include <dolphin/dolphin.h>
static const NotificationSequence sequence_blink_start_magenta = {
&message_blink_start_10,
&message_blink_set_color_magenta,
&message_do_not_reset,
NULL,
};
static const NotificationSequence sequence_blink_stop = {
&message_blink_stop,
NULL,
};
void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool /* need_restore */) {
string_init(data_string);
@@ -17,9 +17,9 @@ void LfRfidAppSceneExitConfirm::on_enter(LfRfidApp* app, bool /* need_restore */
auto line_1 = container->add<StringElement>();
auto line_2 = container->add<StringElement>();
line_1->set_text("Exit to RFID menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
line_1->set_text("Exit to RFID Menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
line_2->set_text(
"All unsaved data will be lost.", 64, 31, 0, AlignCenter, AlignBottom, FontSecondary);
"All unsaved data will be lost!", 64, 31, 0, AlignCenter, AlignBottom, FontSecondary);
app->view_controller.switch_to<ContainerVM>();
}
@@ -17,9 +17,9 @@ void LfRfidAppSceneRetryConfirm::on_enter(LfRfidApp* app, bool /* need_restore *
auto line_1 = container->add<StringElement>();
auto line_2 = container->add<StringElement>();
line_1->set_text("Return to reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
line_1->set_text("Return to Reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
line_2->set_text(
"All unsaved data will be lost.", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
"All unsaved data will be lost!", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
app->view_controller.switch_to<ContainerVM>();
}
@@ -1,18 +1,7 @@
#include "lfrfid_app_scene_rpc.h"
#include <core/common_defines.h>
#include <dolphin/dolphin.h>
static const NotificationSequence sequence_blink_start_magenta = {
&message_blink_start_10,
&message_blink_set_color_magenta,
&message_do_not_reset,
NULL,
};
static const NotificationSequence sequence_blink_stop = {
&message_blink_stop,
NULL,
};
#include <rpc/rpc_app.h>
void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) {
auto popup = app->view_controller.get<PopupVM>();
@@ -36,6 +25,16 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
LfRfidApp::Event view_event;
view_event.type = LfRfidApp::EventType::Back;
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) {
auto popup = app->view_controller.get<PopupVM>();
consumed = true;
@@ -45,7 +44,22 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
popup->set_text(app->text_store.text, 89, 43, AlignCenter, AlignTop);
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;
}
+1 -1
View File
@@ -300,7 +300,7 @@ int32_t music_player_app(void* p) {
string_init(file_path);
do {
if(p) {
if(p && strlen(p)) {
string_cat_str(file_path, p);
} else {
string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER);
@@ -11,4 +11,5 @@ enum NfcCustomEvent {
NfcCustomEventDictAttackDone,
NfcCustomEventDictAttackSkip,
NfcCustomEventRpcLoad,
NfcCustomEventRpcSessionClose,
};
+22 -76
View File
@@ -13,78 +13,21 @@ bool nfc_back_event_callback(void* context) {
return scene_manager_handle_back_event(nfc->scene_manager);
}
void nfc_rpc_exit_callback(Nfc* 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_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) {
static void nfc_rpc_command_callback(RpcAppSystemEvent event, void* context) {
furi_assert(context);
Nfc* nfc = context;
if(!nfc->rpc_ctx) {
return false;
}
bool result = false;
furi_assert(nfc->rpc_ctx);
if(event == RpcAppEventSessionClose) {
rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
nfc->rpc_ctx = NULL;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
result = true;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcSessionClose);
} else if(event == RpcAppEventAppExit) {
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
result = true;
} else if(event == RpcAppEventLoadFile) {
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_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;
}
}
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad);
} else {
rpc_system_app_confirm(nfc->rpc_ctx, event, false);
}
return result;
}
Nfc* nfc_alloc() {
@@ -163,6 +106,21 @@ Nfc* nfc_alloc() {
void nfc_free(Nfc* 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_free(nfc->dev);
@@ -241,18 +199,6 @@ void nfc_text_store_clear(Nfc* nfc) {
memset(nfc->text_store, 0, sizeof(nfc->text_store));
}
static const NotificationSequence sequence_blink_start_blue = {
&message_blink_start_10,
&message_blink_set_color_blue,
&message_do_not_reset,
NULL,
};
static const NotificationSequence sequence_blink_stop = {
&message_blink_stop,
NULL,
};
void nfc_blink_start(Nfc* nfc) {
notification_message(nfc->notifications, &sequence_blink_start_blue);
}
@@ -280,7 +226,7 @@ int32_t nfc_app(void* p) {
char* args = p;
// Check argument and run corresponding scene
if((*args != '\0')) {
if(args && strlen(args)) {
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
uint32_t rpc_ctx = 0;
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
-2
View File
@@ -102,5 +102,3 @@ void nfc_blink_start(Nfc* nfc);
void nfc_blink_stop(Nfc* nfc);
void nfc_show_loading_popup(void* context, bool show);
void nfc_rpc_exit_callback(Nfc* nfc);
@@ -37,7 +37,7 @@ static void nfc_scene_detect_reader_widget_config(Nfc* nfc, bool data_received)
widget_add_icon_element(widget, 0, 14, &I_Reader_detect);
widget_add_string_element(
widget, 64, 3, AlignCenter, AlignTop, FontSecondary, "Hold near reader");
widget, 64, 3, AlignCenter, AlignTop, FontSecondary, "Hold Near Reader");
widget_add_string_element(widget, 55, 22, AlignLeft, AlignTop, FontPrimary, "Emulating...");
if(data_received) {
@@ -12,9 +12,9 @@ void nfc_scene_exit_confirm_on_enter(void* context) {
dialog_ex_set_left_button_text(dialog_ex, "Exit");
dialog_ex_set_right_button_text(dialog_ex, "Stay");
dialog_ex_set_header(dialog_ex, "Exit to NFC menu?", 64, 11, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "Exit to NFC Menu?", 64, 11, AlignCenter, AlignTop);
dialog_ex_set_text(
dialog_ex, "All unsaved data\nwill be lost.", 64, 25, AlignCenter, AlignTop);
dialog_ex, "All unsaved data\nwill be lost!", 64, 25, AlignCenter, AlignTop);
dialog_ex_set_context(dialog_ex, nfc);
dialog_ex_set_result_callback(dialog_ex, nfc_scene_exit_confirm_dialog_callback);
@@ -1,5 +1,7 @@
#include "../nfc_i.h"
#define TAG "NfcMfClassicDictAttack"
typedef enum {
DictAttackStateIdle,
DictAttackStateUserDictInProgress,
@@ -32,7 +34,9 @@ static void nfc_scene_mf_classic_dict_attack_update_view(Nfc* nfc) {
static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackState state) {
MfClassicData* data = &nfc->dev->dev_data.mf_classic_data;
NfcMfClassicDictAttackData* dict_attack_data = &nfc->dev->dev_data.mf_classic_dict_attack_data;
NfcWorkerState worker_state = NfcWorkerStateReady;
MfClassicDict* dict = NULL;
// Identify scene state
if(state == DictAttackStateIdle) {
@@ -47,16 +51,36 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt
// Setup view
if(state == DictAttackStateUserDictInProgress) {
worker_state = NfcWorkerStateMfClassicUserDictAttack;
worker_state = NfcWorkerStateMfClassicDictAttack;
dict_attack_set_header(nfc->dict_attack, "Mf Classic User Dict.");
} else if(state == DictAttackStateFlipperDictInProgress) {
worker_state = NfcWorkerStateMfClassicFlipperDictAttack;
dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict.");
dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
// If failed to load user dictionary - try flipper dictionary
if(!dict) {
FURI_LOG_E(TAG, "User dictionary not found");
state = DictAttackStateFlipperDictInProgress;
}
}
if(state == DictAttackStateFlipperDictInProgress) {
worker_state = NfcWorkerStateMfClassicDictAttack;
dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict.");
dict = mf_classic_dict_alloc(MfClassicDictTypeFlipper);
if(!dict) {
FURI_LOG_E(TAG, "Flipper dictionary not found");
// Pass through to let worker handle the failure
}
}
// Free previous dictionary
if(dict_attack_data->dict) {
mf_classic_dict_free(dict_attack_data->dict);
}
dict_attack_data->dict = dict;
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfClassicDictAttack, state);
dict_attack_set_callback(nfc->dict_attack, nfc_dict_attack_dict_attack_result_callback, nfc);
dict_attack_set_current_sector(nfc->dict_attack, 0);
dict_attack_set_card_detected(nfc->dict_attack, data->type);
dict_attack_set_total_dict_keys(
nfc->dict_attack, dict ? mf_classic_dict_get_total_keys(dict) : 0);
nfc_scene_mf_classic_dict_attack_update_view(nfc);
nfc_worker_start(
nfc->worker, worker_state, &nfc->dev->dev_data, nfc_dict_attack_worker_callback, nfc);
@@ -112,6 +136,10 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
nfc_scene_mf_classic_dict_attack_update_view(nfc);
dict_attack_inc_current_sector(nfc->dict_attack);
consumed = true;
} else if(event.event == NfcWorkerEventNewDictKeyBatch) {
nfc_scene_mf_classic_dict_attack_update_view(nfc);
dict_attack_inc_current_dict_key(nfc->dict_attack, NFC_DICT_KEY_BATCH_SIZE);
consumed = true;
} else if(event.event == NfcCustomEventDictAttackSkip) {
if(state == DictAttackStateUserDictInProgress) {
nfc_worker_stop(nfc->worker);
@@ -130,8 +158,13 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
void nfc_scene_mf_classic_dict_attack_on_exit(void* context) {
Nfc* nfc = context;
NfcMfClassicDictAttackData* dict_attack_data = &nfc->dev->dev_data.mf_classic_dict_attack_data;
// Stop worker
nfc_worker_stop(nfc->worker);
if(dict_attack_data->dict) {
mf_classic_dict_free(dict_attack_data->dict);
dict_attack_data->dict = NULL;
}
dict_attack_reset(nfc->dict_attack);
nfc_blink_stop(nfc);
}
@@ -10,7 +10,7 @@ void nfc_scene_restore_original_confirm_on_enter(void* context) {
Nfc* nfc = context;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_header(dialog_ex, "Restore card data?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "Restore Card Data?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring);
dialog_ex_set_text(
dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop);
@@ -12,9 +12,9 @@ void nfc_scene_retry_confirm_on_enter(void* context) {
dialog_ex_set_left_button_text(dialog_ex, "Retry");
dialog_ex_set_right_button_text(dialog_ex, "Stay");
dialog_ex_set_header(dialog_ex, "Retry reading?", 64, 11, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "Retry Reading?", 64, 11, AlignCenter, AlignTop);
dialog_ex_set_text(
dialog_ex, "All unsaved data will be\nlost.", 64, 25, AlignCenter, AlignTop);
dialog_ex, "All unsaved data will be\nlost!", 64, 25, AlignCenter, AlignTop);
dialog_ex_set_context(dialog_ex, nfc);
dialog_ex_set_result_callback(dialog_ex, nfc_scene_retry_confirm_dialog_callback);
+45 -4
View File
@@ -14,6 +14,14 @@ void nfc_scene_rpc_on_enter(void* context) {
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) {
Nfc* nfc = context;
Popup* popup = nfc->popup;
@@ -22,13 +30,47 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
consumed = true;
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);
nfc_blink_stop(nfc);
} 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);
popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop);
nfc_blink_start(nfc);
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;
@@ -38,7 +80,6 @@ void nfc_scene_rpc_on_exit(void* context) {
Nfc* nfc = context;
Popup* popup = nfc->popup;
nfc_rpc_exit_callback(nfc);
nfc_blink_stop(nfc);
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
@@ -2,6 +2,7 @@
enum SubmenuIndex {
SubmenuIndexEmulate,
SubmenuIndexEditUid,
SubmenuIndexRename,
SubmenuIndexDelete,
SubmenuIndexInfo,
@@ -27,6 +28,14 @@ void nfc_scene_saved_menu_on_enter(void* context) {
SubmenuIndexEmulate,
nfc_scene_saved_menu_submenu_callback,
nfc);
if(nfc->dev->dev_data.protocol == NfcDeviceProtocolUnknown) {
submenu_add_item(
submenu,
"Edit UID",
SubmenuIndexEditUid,
nfc_scene_saved_menu_submenu_callback,
nfc);
}
} else if(
nfc->dev->format == NfcDeviceSaveFormatMifareUl ||
nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
@@ -71,6 +80,9 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
} else if(event.event == SubmenuIndexRename) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
consumed = true;
} else if(event.event == SubmenuIndexEditUid) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid);
consumed = true;
} else if(event.event == SubmenuIndexDelete) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete);
consumed = true;
+10 -2
View File
@@ -31,8 +31,16 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventByteInputDone) {
DOLPHIN_DEED(DolphinDeedNfcAdd);
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
consumed = true;
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
if(nfc_device_save(nfc->dev, nfc->dev->dev_name)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
consumed = true;
}
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
consumed = true;
}
}
}
return consumed;
+35 -2
View File
@@ -23,6 +23,8 @@ typedef struct {
uint8_t sector_current;
uint8_t keys_total;
uint8_t keys_found;
uint16_t dict_keys_total;
uint16_t dict_keys_current;
} DictAttackViewModel;
static void dict_attack_draw_callback(Canvas* canvas, void* model) {
@@ -38,8 +40,15 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, string_get_cstr(m->header));
canvas_set_font(canvas, FontSecondary);
float progress =
m->sectors_total == 0 ? 0 : (float)(m->sector_current) / (float)(m->sectors_total);
float dict_progress = m->dict_keys_total == 0 ?
0 :
(float)(m->dict_keys_current) / (float)(m->dict_keys_total);
float progress = m->sectors_total == 0 ? 0 :
((float)(m->sector_current) + dict_progress) /
(float)(m->sectors_total);
if(progress > 1.0) {
progress = 1.0;
}
elements_progress_bar(canvas, 5, 15, 120, progress);
canvas_set_font(canvas, FontSecondary);
snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total);
@@ -100,6 +109,8 @@ void dict_attack_reset(DictAttack* dict_attack) {
model->sector_current = 0;
model->keys_total = 0;
model->keys_found = 0;
model->dict_keys_total = 0;
model->dict_keys_current = 0;
string_reset(model->header);
return false;
});
@@ -171,6 +182,7 @@ void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec) {
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
model->sector_current = curr_sec;
model->dict_keys_current = 0;
return true;
});
}
@@ -181,6 +193,7 @@ void dict_attack_inc_current_sector(DictAttack* dict_attack) {
dict_attack->view, (DictAttackViewModel * model) {
if(model->sector_current < model->sectors_total) {
model->sector_current++;
model->dict_keys_current = 0;
}
return true;
});
@@ -196,3 +209,23 @@ void dict_attack_inc_keys_found(DictAttack* dict_attack) {
return true;
});
}
void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total) {
furi_assert(dict_attack);
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
model->dict_keys_total = dict_keys_total;
return true;
});
}
void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried) {
furi_assert(dict_attack);
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
if(model->dict_keys_current + keys_tried < model->dict_keys_total) {
model->dict_keys_current += keys_tried;
}
return true;
});
}
+4
View File
@@ -34,3 +34,7 @@ void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec);
void dict_attack_inc_current_sector(DictAttack* dict_attack);
void dict_attack_inc_keys_found(DictAttack* dict_attack);
void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total);
void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried);
@@ -431,6 +431,54 @@ const NotificationSequence sequence_blink_white_100 = {
NULL,
};
// Hardware blink
const NotificationSequence sequence_blink_start_blue = {
&message_blink_start_10,
&message_blink_set_color_blue,
&message_do_not_reset,
NULL,
};
const NotificationSequence sequence_blink_start_red = {
&message_blink_start_10,
&message_blink_set_color_red,
&message_do_not_reset,
NULL,
};
const NotificationSequence sequence_blink_start_green = {
&message_blink_start_10,
&message_blink_set_color_green,
&message_do_not_reset,
NULL,
};
const NotificationSequence sequence_blink_start_yellow = {
&message_blink_start_10,
&message_blink_set_color_yellow,
&message_do_not_reset,
NULL,
};
const NotificationSequence sequence_blink_start_cyan = {
&message_blink_start_10,
&message_blink_set_color_cyan,
&message_do_not_reset,
NULL,
};
const NotificationSequence sequence_blink_start_magenta = {
&message_blink_start_10,
&message_blink_set_color_magenta,
&message_do_not_reset,
NULL,
};
const NotificationSequence sequence_blink_stop = {
&message_blink_stop,
NULL,
};
//General
const NotificationSequence sequence_single_vibro = {
&message_vibro_on,
@@ -122,6 +122,15 @@ extern const NotificationSequence sequence_blink_cyan_100;
extern const NotificationSequence sequence_blink_magenta_100;
extern const NotificationSequence sequence_blink_white_100;
// Hardware blink
extern const NotificationSequence sequence_blink_start_blue;
extern const NotificationSequence sequence_blink_start_red;
extern const NotificationSequence sequence_blink_start_green;
extern const NotificationSequence sequence_blink_start_yellow;
extern const NotificationSequence sequence_blink_start_cyan;
extern const NotificationSequence sequence_blink_start_magenta;
extern const NotificationSequence sequence_blink_stop;
// General
extern const NotificationSequence sequence_single_vibro;
extern const NotificationSequence sequence_double_vibro;
@@ -13,7 +13,7 @@ void picopass_scene_read_card_on_enter(void* context) {
// Setup view
Popup* popup = picopass->popup;
popup_set_header(popup, "Detecting\npicopass card", 70, 34, AlignLeft, AlignTop);
popup_set_header(popup, "Detecting\npicopass\ncard", 68, 30, AlignLeft, AlignTop);
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
// Start worker
@@ -57,7 +57,7 @@ BatteryTestApp* battery_test_alloc() {
battery_info_get_view(app->batery_info));
app->dialog = dialog_ex_alloc();
dialog_ex_set_header(app->dialog, "Close battery test?", 64, 12, AlignCenter, AlignTop);
dialog_ex_set_header(app->dialog, "Close Battery Test?", 64, 12, AlignCenter, AlignTop);
dialog_ex_set_left_button_text(app->dialog, "Exit");
dialog_ex_set_right_button_text(app->dialog, "Stay");
dialog_ex_set_result_callback(app->dialog, battery_test_dialog_callback);
+1 -1
View File
@@ -200,7 +200,7 @@ static void power_check_battery_level_change(Power* power) {
}
int32_t power_srv(void* p) {
(void)p;
UNUSED(p);
Power* power = power_alloc();
power_update_info(power);
furi_record_create(RECORD_POWER, power);
@@ -76,7 +76,7 @@ void power_settings_app_free(PowerSettingsApp* app) {
int32_t power_settings_app(void* p) {
uint32_t first_scene = PowerSettingsAppSceneStart;
if(p && !strcmp(p, "off")) {
if(p && strlen(p) && !strcmp(p, "off")) {
first_scene = PowerSettingsAppScenePowerOff;
}
PowerSettingsApp* app = power_settings_app_alloc(first_scene);
@@ -10,7 +10,7 @@ void power_settings_scene_power_off_on_enter(void* context) {
PowerSettingsApp* app = context;
DialogEx* dialog = app->dialog;
dialog_ex_set_header(dialog, "Turn off Device?", 64, 2, AlignCenter, AlignTop);
dialog_ex_set_header(dialog, "Turn Off Device?", 64, 2, AlignCenter, AlignTop);
dialog_ex_set_text(
dialog, " I will be\nwaiting for\n you here...", 78, 16, AlignLeft, AlignTop);
dialog_ex_set_icon(dialog, 21, 13, &I_Cry_dolph_55x52);
+94 -53
View File
@@ -6,24 +6,18 @@
#include "rpc_app.h"
#define TAG "RpcSystemApp"
#define APP_BUTTON_TIMEOUT 1000
struct RpcAppSystem {
RpcSession* session;
RpcAppSystemCallback app_callback;
void* app_context;
PB_Main* state_msg;
FuriTimer* timer;
uint32_t last_id;
char* last_data;
};
static void rpc_system_app_timer_callback(void* context) {
furi_assert(context);
RpcAppSystem* rpc_app = context;
if(rpc_app->app_callback) {
rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context);
}
}
#define RPC_SYSTEM_APP_TEMP_ARGS_SIZE 16
static void rpc_system_app_start_process(const PB_Main* request, void* context) {
furi_assert(request);
@@ -33,9 +27,12 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
RpcAppSystem* rpc_app = context;
RpcSession* session = rpc_app->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;
@@ -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;
if(app_name) {
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
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;
}
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) {
result = PB_CommandStatus_OK;
} else {
furi_assert(0);
furi_crash("Programming Error");
}
} else {
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_LOG_D(TAG, "StartProcess: response id %d, result %d", 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_LOG_D(TAG, "LockStatus: response");
rpc_send_and_release(session, &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;
if(rpc_app->app_callback) {
if(rpc_app->app_callback(RpcAppEventAppExit, NULL, rpc_app->app_context)) {
status = PB_CommandStatus_OK;
furi_timer_stop(rpc_app->timer);
} else {
status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
}
FURI_LOG_D(TAG, "ExitRequest: id %d", request->command_id);
furi_assert(!rpc_app->last_id);
furi_assert(!rpc_app->last_data);
rpc_app->last_id = request->command_id;
rpc_app->app_callback(RpcAppEventAppExit, rpc_app->app_context);
} else {
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) {
@@ -133,17 +132,18 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) {
PB_CommandStatus status;
if(rpc_app->app_callback) {
const char* file_path = request->content.app_load_file_request.path;
if(rpc_app->app_callback(RpcAppEventLoadFile, file_path, rpc_app->app_context)) {
status = PB_CommandStatus_OK;
} else {
status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
}
FURI_LOG_D(TAG, "LoadFile: id %d", request->command_id);
furi_assert(!rpc_app->last_id);
furi_assert(!rpc_app->last_data);
rpc_app->last_id = request->command_id;
rpc_app->last_data = strdup(request->content.app_load_file_request.path);
rpc_app->app_callback(RpcAppEventLoadFile, rpc_app->app_context);
} else {
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) {
@@ -157,18 +157,18 @@ static void rpc_system_app_button_press(const PB_Main* request, void* context) {
PB_CommandStatus status;
if(rpc_app->app_callback) {
const char* args = request->content.app_button_press_request.args;
if(rpc_app->app_callback(RpcAppEventButtonPress, args, rpc_app->app_context)) {
status = PB_CommandStatus_OK;
furi_timer_start(rpc_app->timer, APP_BUTTON_TIMEOUT);
} else {
status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
}
FURI_LOG_D(TAG, "ButtonPress");
furi_assert(!rpc_app->last_id);
furi_assert(!rpc_app->last_data);
rpc_app->last_id = request->command_id;
rpc_app->last_data = strdup(request->content.app_button_press_request.args);
rpc_app->app_callback(RpcAppEventButtonPress, rpc_app->app_context);
} else {
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) {
@@ -182,17 +182,17 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context)
PB_CommandStatus status;
if(rpc_app->app_callback) {
if(rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context)) {
status = PB_CommandStatus_OK;
furi_timer_stop(rpc_app->timer);
} else {
status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
}
FURI_LOG_D(TAG, "ButtonRelease");
furi_assert(!rpc_app->last_id);
furi_assert(!rpc_app->last_data);
rpc_app->last_id = request->command_id;
rpc_app->app_callback(RpcAppEventButtonRelease, rpc_app->app_context);
} else {
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) {
@@ -201,6 +201,8 @@ void rpc_system_app_send_started(RpcAppSystem* rpc_app) {
furi_assert(session);
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);
}
@@ -210,9 +212,46 @@ void rpc_system_app_send_exited(RpcAppSystem* rpc_app) {
furi_assert(session);
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);
}
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) {
furi_assert(rpc_app);
@@ -226,8 +265,6 @@ void* rpc_system_app_alloc(RpcSession* session) {
RpcAppSystem* rpc_app = malloc(sizeof(RpcAppSystem));
rpc_app->session = session;
rpc_app->timer = furi_timer_alloc(rpc_system_app_timer_callback, FuriTimerTypeOnce, rpc_app);
// App exit message
rpc_app->state_msg = malloc(sizeof(PB_Main));
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;
furi_assert(session);
furi_timer_free(rpc_app->timer);
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);
}
+5 -1
View File
@@ -13,7 +13,7 @@ typedef enum {
RpcAppEventButtonRelease,
} RpcAppSystemEvent;
typedef bool (*RpcAppSystemCallback)(RpcAppSystemEvent event, const char* arg, void* context);
typedef void (*RpcAppSystemCallback)(RpcAppSystemEvent event, void* context);
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);
const char* rpc_system_app_get_data(RpcAppSystem* rpc_app);
void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result);
#ifdef __cplusplus
}
#endif
+9 -18
View File
@@ -541,7 +541,7 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
(void)md5sum_size;
furi_assert(hash_size <= ((md5sum_size - 1) / 2));
for(uint8_t i = 0; i < hash_size; i++) {
md5sum += sprintf(md5sum, "%02x", hash[i]);
md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]);
}
free(hash);
@@ -594,23 +594,19 @@ static void rpc_system_storage_backup_create_process(const PB_Main* request, voi
FURI_LOG_D(TAG, "BackupCreate");
RpcSession* session = (RpcSession*)context;
RpcStorageSystem* rpc_storage = context;
RpcSession* session = rpc_storage->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);
bool backup_ok =
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);
rpc_send_and_release(session, response);
free(response);
rpc_send_and_release_empty(
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) {
@@ -619,24 +615,19 @@ static void rpc_system_storage_backup_restore_process(const PB_Main* request, vo
FURI_LOG_D(TAG, "BackupRestore");
RpcSession* session = (RpcSession*)context;
RpcStorageSystem* rpc_storage = context;
RpcSession* session = rpc_storage->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);
bool backup_ok =
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);
rpc_send_and_release(session, response);
free(response);
rpc_send_and_release_empty(
session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR);
}
void* rpc_system_storage_alloc(RpcSession* session) {
+4
View File
@@ -78,6 +78,8 @@ static void rpc_system_system_device_info_callback(
furi_assert(value);
RpcSystemContext* ctx = context;
furi_assert(key);
furi_assert(value);
char* str_key = strdup(key);
char* str_value = strdup(value);
@@ -232,6 +234,8 @@ static void rpc_system_system_power_info_callback(
furi_assert(value);
RpcSystemContext* ctx = context;
furi_assert(key);
furi_assert(value);
char* str_key = strdup(key);
char* str_value = strdup(value);
+2 -2
View File
@@ -82,7 +82,7 @@ static void storage_cli_format(Cli* cli, string_t path) {
if(string_cmp_str(path, STORAGE_INT_PATH_PREFIX) == 0) {
storage_cli_print_error(FSE_NOT_IMPLEMENTED);
} else if(string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) {
printf("Formatting SD card, all data will be lost. Are you sure (y/n)?\r\n");
printf("Formatting SD card, All data will be lost! Are you sure (y/n)?\r\n");
char answer = cli_getc(cli);
if(answer == 'y' || answer == 'Y') {
Storage* api = furi_record_open(RECORD_STORAGE);
@@ -581,7 +581,7 @@ void storage_cli(Cli* cli, string_t args, void* context) {
static void storage_cli_factory_reset(Cli* cli, string_t args, void* context) {
UNUSED(args);
UNUSED(context);
printf("All data will be lost. Are you sure (y/n)?\r\n");
printf("All data will be lost! Are you sure (y/n)?\r\n");
char c = cli_getc(cli);
if(c == 'y' || c == 'Y') {
printf("Data will be wiped after reboot.\r\n");
+1 -2
View File
@@ -26,8 +26,7 @@ static FS_Error storage_ext_parse_error(SDError error);
static bool sd_mount_card(StorageData* storage, bool notify) {
bool result = false;
const uint8_t max_init_counts = 10;
uint8_t counter = max_init_counts;
uint8_t counter = BSP_SD_MaxMountRetryCount();
uint8_t bsp_result;
SDData* sd_data = storage->data;
@@ -75,7 +75,7 @@ static bool
static void storage_settings_scene_benchmark(StorageSettings* app) {
DialogEx* dialog_ex = app->dialog_ex;
uint8_t* bench_data;
dialog_ex_set_header(dialog_ex, "Preparing data...", 64, 32, AlignCenter, AlignCenter);
dialog_ex_set_header(dialog_ex, "Preparing Data...", 64, 32, AlignCenter, AlignCenter);
bench_data = malloc(BENCH_DATA_SIZE);
for(size_t i = 0; i < BENCH_DATA_SIZE; i++) {
@@ -123,7 +123,7 @@ void storage_settings_scene_benchmark_on_enter(void* context) {
if(sd_status != FSE_OK) {
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
dialog_ex_set_header(dialog_ex, "SD card not mounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_text(
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
dialog_ex_set_center_button_text(dialog_ex, "Ok");
@@ -24,7 +24,7 @@ void storage_settings_scene_factory_reset_on_enter(void* context) {
dialog_ex_set_header(dialog_ex, "Confirm Factory Reset", 64, 10, AlignCenter, AlignCenter);
dialog_ex_set_text(
dialog_ex,
"Internal storage will be erased\r\nData and setting will be lost",
"Internal storage will be erased\r\nData and setting will be lost!",
64,
32,
AlignCenter,
@@ -15,13 +15,13 @@ void storage_settings_scene_format_confirm_on_enter(void* context) {
if(sd_status == FSE_NOT_READY) {
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
dialog_ex_set_header(dialog_ex, "SD card not mounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_text(
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
dialog_ex_set_center_button_text(dialog_ex, "Ok");
} else {
dialog_ex_set_header(dialog_ex, "Format SD card?", 64, 10, AlignCenter, AlignCenter);
dialog_ex_set_text(dialog_ex, "All data will be lost", 64, 32, AlignCenter, AlignCenter);
dialog_ex_set_header(dialog_ex, "Format SD Card?", 64, 10, AlignCenter, AlignCenter);
dialog_ex_set_text(dialog_ex, "All data will be lost!", 64, 32, AlignCenter, AlignCenter);
dialog_ex_set_left_button_text(dialog_ex, "Cancel");
dialog_ex_set_right_button_text(dialog_ex, "Format");
}
@@ -43,7 +43,7 @@ void storage_settings_scene_formatting_on_enter(void* context) {
dialog_ex_set_result_callback(dialog_ex, storage_settings_scene_formatting_dialog_callback);
if(error != FSE_OK) {
dialog_ex_set_header(dialog_ex, "Cannot format SD Card", 64, 10, AlignCenter, AlignCenter);
dialog_ex_set_header(dialog_ex, "Cannot Format SD Card", 64, 10, AlignCenter, AlignCenter);
dialog_ex_set_text(
dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter);
} else {
@@ -21,7 +21,7 @@ void storage_settings_scene_internal_info_on_enter(void* context) {
if(error != FSE_OK) {
dialog_ex_set_header(
dialog_ex, "Internal storage error", 64, 10, AlignCenter, AlignCenter);
dialog_ex, "Internal Storage Error", 64, 10, AlignCenter, AlignCenter);
dialog_ex_set_text(
dialog_ex, storage_error_get_desc(error), 64, 32, AlignCenter, AlignCenter);
} else {
@@ -19,7 +19,7 @@ void storage_settings_scene_sd_info_on_enter(void* context) {
if(sd_status != FSE_OK) {
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
dialog_ex_set_header(dialog_ex, "SD card not mounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_text(
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
dialog_ex_set_center_button_text(dialog_ex, "Ok");
@@ -15,12 +15,12 @@ void storage_settings_scene_unmount_confirm_on_enter(void* context) {
if(sd_status == FSE_NOT_READY) {
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
dialog_ex_set_header(dialog_ex, "SD card not mounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "SD Card Not Mounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_text(
dialog_ex, "Try to reinsert\nor format SD\ncard.", 3, 19, AlignLeft, AlignTop);
dialog_ex_set_center_button_text(dialog_ex, "Ok");
} else {
dialog_ex_set_header(dialog_ex, "Unmount SD card?", 64, 10, AlignCenter, AlignCenter);
dialog_ex_set_header(dialog_ex, "Unmount SD Card?", 64, 10, AlignCenter, AlignCenter);
dialog_ex_set_text(
dialog_ex, "SD card will be\nunavailable", 64, 32, AlignCenter, AlignCenter);
dialog_ex_set_left_button_text(dialog_ex, "Cancel");
@@ -16,11 +16,11 @@ void storage_settings_scene_unmounted_on_enter(void* context) {
dialog_ex_set_icon(dialog_ex, 72, 14, &I_DolphinFirstStart8_56x51);
if(error == FSE_OK) {
dialog_ex_set_header(dialog_ex, "SD card unmounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "SD Card Unmounted", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_text(dialog_ex, "You can remove\nSD card now.", 3, 22, AlignLeft, AlignTop);
notification_message(app->notification, &sequence_blink_green_100);
} else {
dialog_ex_set_header(dialog_ex, "Cannot unmount SD Card", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_header(dialog_ex, "Cannot Unmount SD Card", 64, 3, AlignCenter, AlignTop);
dialog_ex_set_text(dialog_ex, storage_error_get_desc(error), 3, 22, AlignLeft, AlignTop);
notification_message(app->notification, &sequence_blink_red_100);
}
@@ -47,6 +47,9 @@ typedef enum {
SubGhzCustomEventSceneStay,
SubGhzCustomEventSceneRpcLoad,
SubGhzCustomEventSceneRpcButtonPress,
SubGhzCustomEventSceneRpcButtonRelease,
SubGhzCustomEventSceneRpcSessionClose,
SubGhzCustomEventViewReceiverOK,
SubGhzCustomEventViewReceiverConfig,
+2 -2
View File
@@ -72,11 +72,11 @@ typedef enum {
SubGhzViewIdTestPacket,
} SubGhzViewId;
struct SubGhzPesetDefinition {
struct SubGhzPresetDefinition {
string_t name;
uint32_t frequency;
uint8_t* data;
size_t data_size;
};
typedef struct SubGhzPesetDefinition SubGhzPesetDefinition;
typedef struct SubGhzPresetDefinition SubGhzPresetDefinition;

Some files were not shown because too many files have changed in this diff Show More