Merge remote-tracking branch 'upstream/420' into 420
128
.ci_files/anims_ofw.txt
Normal file
@@ -0,0 +1,128 @@
|
||||
Filetype: Flipper Animation Manifest
|
||||
Version: 1
|
||||
|
||||
Name: L1_Waves_128x50
|
||||
Min butthurt: 0
|
||||
Max butthurt: 5
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Laptop_128x51
|
||||
Min butthurt: 0
|
||||
Max butthurt: 7
|
||||
Min level: 1
|
||||
Max level: 1
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Sleep_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 10
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Recording_128x51
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 1
|
||||
Max level: 1
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Furippa1_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 6
|
||||
Min level: 1
|
||||
Max level: 1
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Furippa2_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 6
|
||||
Min level: 2
|
||||
Max level: 2
|
||||
Weight: 3
|
||||
|
||||
Name: L3_Furippa3_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 6
|
||||
Min level: 3
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Read_books_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 1
|
||||
Max level: 1
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Hacking_pc_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 2
|
||||
Max level: 2
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Cry_128x64
|
||||
Min butthurt: 8
|
||||
Max butthurt: 13
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Boxing_128x64
|
||||
Min butthurt: 10
|
||||
Max butthurt: 13
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Mad_fist_128x64
|
||||
Min butthurt: 9
|
||||
Max butthurt: 13
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Mods_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 9
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 5
|
||||
|
||||
Name: L1_Painting_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 7
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 4
|
||||
|
||||
Name: L3_Hijack_radio_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 3
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L3_Lab_research_128x54
|
||||
Min butthurt: 0
|
||||
Max butthurt: 10
|
||||
Min level: 3
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Soldering_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 10
|
||||
Min level: 2
|
||||
Max level: 2
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Leaving_sad_128x64
|
||||
Min butthurt: 14
|
||||
Max butthurt: 14
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
219
.drone.yml
@@ -1,6 +1,6 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: "Build firmware"
|
||||
name: "Release firmware"
|
||||
|
||||
steps:
|
||||
- name: "Update submodules"
|
||||
@@ -11,19 +11,38 @@ steps:
|
||||
- git submodule foreach git config --local gc.auto 0
|
||||
- git log -1 --format='%H'
|
||||
|
||||
- name: "Build default fw"
|
||||
- name: "Build firmware"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_TAG}
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-default
|
||||
- mv dist/f7-C/* artifacts-default/
|
||||
- ls -laS artifacts-default
|
||||
- ls -laS artifacts-default/f7-update-${DRONE_TAG}
|
||||
- sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md
|
||||
- echo '# [Install via Web Updater](https://my.flipp.dev/?url=https://unleashedflip.com/builds/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=dev-cfw&version='${DRONE_TAG}')' >> CHANGELOG.md
|
||||
- echo '# [Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')' >> CHANGELOG.md
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Build no anims FW"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- rm -f assets/dolphin/external/manifest.txt
|
||||
- cp .ci_files/anims_ofw.txt assets/dolphin/external/manifest.txt
|
||||
- export DIST_SUFFIX=${DRONE_TAG}n
|
||||
- export WORKFLOW_BRANCH_OR_TAG=no-custom-anims
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-ofw-anims
|
||||
- mv dist/f7-C/* artifacts-ofw-anims/
|
||||
- ls -laS artifacts-ofw-anims
|
||||
- ls -laS artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [Version without custom animations - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)' >> CHANGELOG.md
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
@@ -31,12 +50,19 @@ steps:
|
||||
- name: "Bundle self-update packages"
|
||||
image: kramos/alpine-zip
|
||||
commands:
|
||||
- cp artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.tgz .
|
||||
- cp artifacts-default/flipper-z-f7-update-${DRONE_TAG}.tgz .
|
||||
- zip -r artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.zip artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
||||
- zip -r artifacts-default/flipper-z-f7-update-${DRONE_TAG}.zip artifacts-default/f7-update-${DRONE_TAG}
|
||||
- tar czpf artifacts-default/flipper-z-any-scripts-${DRONE_TAG}.tgz scripts debug
|
||||
- rm -rf artifacts-ofw-anims/f7-update-${DRONE_TAG}
|
||||
- rm -rf artifacts-default/f7-update-${DRONE_TAG}
|
||||
- ls -laS artifacts-ofw-anims
|
||||
- ls -laS artifacts-default
|
||||
- mv artifacts-default/ ${DRONE_TAG}
|
||||
- ls -laS ${DRONE_TAG}
|
||||
|
||||
- name: "Upload to updates server"
|
||||
- name: "Upload default to updates srv"
|
||||
image: appleboy/drone-scp
|
||||
settings:
|
||||
host:
|
||||
@@ -48,8 +74,29 @@ steps:
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target
|
||||
source: flipper-z-f7-update-${DRONE_TAG}.tgz
|
||||
from_secret: dep_target_new
|
||||
source:
|
||||
- ${DRONE_TAG}/*.tgz
|
||||
- ${DRONE_TAG}/*.zip
|
||||
- ${DRONE_TAG}/*.json
|
||||
- ${DRONE_TAG}/*.elf
|
||||
- ${DRONE_TAG}/*.dfu
|
||||
- ${DRONE_TAG}/*.bin
|
||||
|
||||
- name: "Upload no-anims to updates srv"
|
||||
image: appleboy/drone-scp
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_noanim
|
||||
source: flipper-z-f7-update-${DRONE_TAG}n.tgz
|
||||
|
||||
- name: "Do Github release"
|
||||
image: ddplugins/github-release
|
||||
@@ -61,8 +108,9 @@ steps:
|
||||
api_key:
|
||||
from_secret: github_apikey
|
||||
files:
|
||||
- artifacts-default/*.tgz
|
||||
- artifacts-default/*.zip
|
||||
- ${DRONE_TAG}/*.tgz
|
||||
- ${DRONE_TAG}/*.zip
|
||||
- artifacts-ofw-anims/*.tgz
|
||||
title: ${DRONE_TAG}
|
||||
note: CHANGELOG.md
|
||||
checksum:
|
||||
@@ -70,6 +118,17 @@ steps:
|
||||
- sha1
|
||||
- crc32
|
||||
|
||||
- name: "Trigger update server reindex"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
environment:
|
||||
UPD_KEY:
|
||||
from_secret: git_update_serv_token
|
||||
UPD_URL:
|
||||
from_secret: git_update_server_url
|
||||
commands:
|
||||
- curl -X POST -F 'key='$UPD_KEY'' $UPD_URL
|
||||
|
||||
- name: "Send files to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
@@ -87,9 +146,18 @@ steps:
|
||||
[-Github-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
|
||||
|
||||
|
||||
[-Install via Web Updater-](https://my.flipp.dev/?url=https://unleashedflip.com/builds/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=dev-cfw&version=${DRONE_TAG})"
|
||||
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
|
||||
[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
||||
|
||||
|
||||
[-Version without custom animations - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-${DRONE_TAG}n.tgz&channel=release-cfw&version=${DRONE_TAG}n)
|
||||
|
||||
|
||||
[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=release-cfw&version=${DRONE_TAG})"
|
||||
document:
|
||||
- artifacts-default/flipper-z-f7-update-${DRONE_TAG}.tgz
|
||||
- ${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz
|
||||
|
||||
- name: "Send discord notification"
|
||||
image: appleboy/drone-discord
|
||||
@@ -107,7 +175,16 @@ steps:
|
||||
[[Github]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
|
||||
|
||||
|
||||
[-Install via Web Updater-](https://my.flipp.dev/?url=https://unleashedflip.com/builds/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=dev-cfw&version=${DRONE_TAG})"
|
||||
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
|
||||
[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
||||
|
||||
|
||||
[-Version without custom animations - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-${DRONE_TAG}n.tgz&channel=release-cfw&version=${DRONE_TAG}n)
|
||||
|
||||
|
||||
[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=release-cfw&version=${DRONE_TAG})"
|
||||
|
||||
trigger:
|
||||
event:
|
||||
@@ -115,3 +192,121 @@ trigger:
|
||||
|
||||
node:
|
||||
typ: haupt
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: "Dev build"
|
||||
|
||||
steps:
|
||||
- name: "Update submodules"
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git submodule sync
|
||||
- git -c protocol.version=2 submodule update --init --force --recursive
|
||||
- git submodule foreach git config --local gc.auto 0
|
||||
- git log -1 --format='%H'
|
||||
|
||||
- name: "Build dev FW"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-default
|
||||
- mv dist/f7-C/* artifacts-default/
|
||||
- ls -laS artifacts-default
|
||||
- ls -laS artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Bundle self-update packages"
|
||||
image: kramos/alpine-zip
|
||||
commands:
|
||||
- cp artifacts-default/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz .
|
||||
- rm -rf artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
|
||||
- ls -laS artifacts-default
|
||||
- mv artifacts-default/ dev
|
||||
- ls -laS dev
|
||||
|
||||
- name: "Clean dev folder"
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
command_timeout: 30s
|
||||
script:
|
||||
- cd web/unleashedflip.com/public_html/fw/dev
|
||||
- rm -f ./*
|
||||
|
||||
- name: "Upload default to updates srv"
|
||||
image: appleboy/drone-scp
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_new
|
||||
source:
|
||||
- dev/*.tgz
|
||||
- dev/*.zip
|
||||
- dev/*.json
|
||||
- dev/*.elf
|
||||
- dev/*.dfu
|
||||
- dev/*.bin
|
||||
|
||||
- name: "Trigger update server reindex"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
environment:
|
||||
UPD_KEY:
|
||||
from_secret: git_update_serv_token
|
||||
UPD_URL:
|
||||
from_secret: git_update_server_url
|
||||
commands:
|
||||
- curl -X POST -F 'key='$UPD_KEY'' $UPD_URL
|
||||
|
||||
- name: "Send files to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid_dev
|
||||
format: markdown
|
||||
message: "Unleashed firmware dev build successful!
|
||||
|
||||
|
||||
Build: {{build.number}}
|
||||
|
||||
SHA: {{commit.sha}}
|
||||
|
||||
|
||||
Commit: {{commit.message}}
|
||||
|
||||
|
||||
[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER})"
|
||||
document:
|
||||
- dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- dev
|
||||
event:
|
||||
- push
|
||||
|
||||
node:
|
||||
typ: haupt
|
||||
|
||||
2
.gitignore
vendored
@@ -55,3 +55,5 @@ openocd.log
|
||||
# PVS Studio temporary files
|
||||
.PVS-Studio/
|
||||
PVS-Studio.log
|
||||
|
||||
.gdbinit
|
||||
|
||||
6
.gitmodules
vendored
@@ -22,12 +22,12 @@
|
||||
[submodule "lib/microtar"]
|
||||
path = lib/microtar
|
||||
url = https://github.com/amachronic/microtar.git
|
||||
[submodule "lib/scons"]
|
||||
path = lib/scons
|
||||
url = https://github.com/SCons/scons.git
|
||||
[submodule "lib/mbedtls"]
|
||||
path = lib/mbedtls
|
||||
url = https://github.com/Mbed-TLS/mbedtls.git
|
||||
[submodule "lib/cxxheaderparser"]
|
||||
path = lib/cxxheaderparser
|
||||
url = https://github.com/robotpy/cxxheaderparser.git
|
||||
[submodule "applications/plugins/dap_link/lib/free-dap"]
|
||||
path = applications/plugins/dap_link/lib/free-dap
|
||||
url = https://github.com/ataradov/free-dap.git
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//-V:BPTREE_DEF2:779,1086,557,773,512
|
||||
//-V:DICT_DEF2:779,524,776,760,1044,1001,729,590,568,747,685
|
||||
//-V:ALGO_DEF:1048,747,1044
|
||||
//-V:TUPLE_DEF2:524,590,1001,760
|
||||
|
||||
# Non-severe malloc/null pointer deref warnings
|
||||
//-V::522:2,3
|
||||
|
||||
2
.vscode/example/c_cpp_properties.json
vendored
@@ -2,7 +2,7 @@
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/i686-windows/bin/arm-none-eabi-gcc.exe",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gcc.exe",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
|
||||
23
.vscode/example/launch.json
vendored
@@ -38,6 +38,7 @@
|
||||
"postAttachCommands": [
|
||||
// "compare-sections",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
// "source debug/FreeRTOS/FreeRTOS.py",
|
||||
// "svd_load debug/STM32WB55_CM4.svd"
|
||||
]
|
||||
@@ -59,6 +60,7 @@
|
||||
"set confirm off",
|
||||
"set mem inaccessible-by-default off",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
// "compare-sections",
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
@@ -76,9 +78,30 @@
|
||||
"rtos": "FreeRTOS",
|
||||
"postAttachCommands": [
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
{
|
||||
"name": "Attach FW (DAP)",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"executable": "./build/latest/firmware.elf",
|
||||
"request": "attach",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"device": "cmsis-dap",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"configFiles": [
|
||||
"interface/cmsis-dap.cfg",
|
||||
"./debug/stm32wbx.cfg",
|
||||
],
|
||||
"postAttachCommands": [
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
],
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
{
|
||||
"name": "fbt debug",
|
||||
"type": "python",
|
||||
|
||||
6
.vscode/example/settings.json
vendored
@@ -6,13 +6,13 @@
|
||||
"cortex-debug.enableTelemetry": false,
|
||||
"cortex-debug.variableUseNaturalFormat": true,
|
||||
"cortex-debug.showRTOS": true,
|
||||
"cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/i686-windows/bin",
|
||||
"cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/x86_64-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.windows": "${workspaceFolder}/toolchain/x86_64-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",
|
||||
"cortex-debug.gdbPath.windows": "${workspaceFolder}/toolchain/i686-windows/bin/arm-none-eabi-gdb-py.bat",
|
||||
"cortex-debug.gdbPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gdb-py.bat",
|
||||
"cortex-debug.gdbPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gdb-py",
|
||||
"cortex-debug.gdbPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gdb-py",
|
||||
"editor.formatOnSave": true,
|
||||
|
||||
4
.vscode/example/tasks.json
vendored
@@ -109,13 +109,13 @@
|
||||
"label": "[Debug] Build FAPs",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt plugin_dist"
|
||||
"command": "./fbt fap_dist"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Build FAPs",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 plugin_dist"
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Launch App on Flipper",
|
||||
|
||||
45
CHANGELOG.md
@@ -1,18 +1,42 @@
|
||||
### New changes
|
||||
* Add 433Mhz Security+ 1.0/2.0 in add manually in subghz
|
||||
* Update Minesweeper (https://github.com/panki27/minesweeper)
|
||||
-----
|
||||
* SubGHz: Fix DTM Neo (keeloq) encoder
|
||||
* fbt: fix flash usb without resources
|
||||
* OFW: DesktopSettings: reset submenu before running dialog
|
||||
* Plugins: SubGHz Bruteforcer -> Add support for Ansonic 12bit protocol (FM238)
|
||||
* Plugins: Fix DTMF Dolphin -> Add forgotten scene and menu item
|
||||
* Plugins: Update DTMF Dolphin [(by litui)](https://github.com/litui/dtmf_dolphin)
|
||||
* Plugins: Update TOTP [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
||||
* Plugins: iButton Fuzzer and RFID Fuzzer improvements
|
||||
* Plugins: i2c tools fix name display
|
||||
* Plugins: Add 3 new plugins BlackJack, Solitaire [(by teeebor)](https://github.com/teeebor/flipper_games) and HEX Viewer [(by QtRoS)](https://github.com/QtRoS/flipperzero-firmware)
|
||||
* Plugins -> PR: Wifi marauder BT menus option (by @rf-bandit | PR #164)
|
||||
* Plugins -> PR: Update i2c tools (New UI) (by @NaejEL | PR #171)
|
||||
* Plugins -> PR: Fix htu21d falsely reading temp as humidity (by @GottZ | PR #175)
|
||||
* SubGHz -> PR: GUI Fix - Allow setting RSSI trigger to beggining (by @TQMatvey | PR #180)
|
||||
* SubGHz: Remove not widely used frequency from hopper
|
||||
* SubGHz: Fix starline encoder
|
||||
* SubGHz: Frequency Analyzer -> Save last trigger level
|
||||
* SubGHz: Speedup subghz launch from favourites
|
||||
* SubGHz: Add new freqs and modulation to user config
|
||||
* Infrared: Update universal remote assets (by @Amec0e)
|
||||
* CI/CD: Improvements, dev builds (can be found in this telegram channel -> https://t.me/kotnehleb)
|
||||
* Power -> PR: Show battery percentile while charging (by @TQMatvey | PR #178)
|
||||
* Docs -> PR: Some updates (by @lucemans | PR #169 and #170)
|
||||
* CLI -> PR: Update cli_commands.c To add `src` / `source` command for people exploring cli (by @PharoahCoder | PR #176)
|
||||
* OFW: Fix U2F HID vulnerability
|
||||
* OFW: Core: thread allocation shortcut
|
||||
* OFW: WS: add protocol GT-WT02
|
||||
* OFW: SubGhz: add protocol "Ansonic"
|
||||
* OFW: SubGhz: add protocol Nice_Flo 20bit
|
||||
|
||||
#### [🎲 Download extra apps pack](https://download-directory.github.io/?url=https://github.com/UberGuidoZ/Flipper/tree/main/Applications/Unleashed)
|
||||
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
||||
|
||||
[-> How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
[-> Download qFlipper 1.2.1 (allows .tgz installation) (official link)](https://update.flipperzero.one/builds/qFlipper/1.2.1/)
|
||||
|
||||
## Please support development of the project
|
||||
* Boosty: https://boosty.to/mmxdev
|
||||
* destream (100 EUR min): https://destream.net/live/MMX/donate
|
||||
* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`
|
||||
* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`
|
||||
* ETH/BSC/ERC20-Tokens: `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`
|
||||
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
||||
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
||||
@@ -23,10 +47,3 @@
|
||||
Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or download `.tgz` for iOS mobile app / qFlipper
|
||||
|
||||
Update using qFlipper (1.2.0+) is now possible with `.tgz` update package! Also you can use Web Updater or self-update package.
|
||||
|
||||
|
||||
## Support unleashed (Not RM) so unleashed team can develop new features
|
||||
* ETH/BSC/ERC20-Tokens: `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`
|
||||
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
||||
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
||||
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
|
||||
|
||||
BIN
RM11240405-0.71.2-f50f05b.tgz
Normal file
BIN
RM11240405-0.71.2-f50f05b.zip
Normal file
256
ReadMe.md
@@ -1,51 +1,52 @@
|
||||
<h2>
|
||||
# Flipper Zero FW [ROGUEMASTER]
|
||||
This firmware is a fork of [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware) and the main Flipper Devices FW! I will try to keep active development and updates from both in this build along with any other projects that can be found to be useful to the community. I try to keep this FW build the most cutting edge with updates from both and updates from active community projects.
|
||||
|
||||
[Join THE Flipper Uncensored Discord](https://discord.gg/gF2bBUzAFe) & [support us if you like what you see](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/SUPPORT.md)! 😄🚀💸</h2>
|
||||
<table><tr><td width="75%">
|
||||
This software is for experimental purposes only and is not meant for any illegal activity/purposes. We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law.
|
||||
|
||||
#### Thank you to all the supporters; this firmware is a fork of [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware) & the main Flipper Devices FW! I will try to keep active development and updates from both in this build along with any other projects that can be found to be useful to the community. I try to keep this FW build the most cutting edge with updates from both and updates from active community projects. All features and projects pulled are listed in expandable sections below. Please do [support us](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/SUPPORT.md) and/or [xMasterX](https://github.com/DarkFlippers/unleashed-firmware)! Everyone gives much of their uncompensated free time to ensure the success of the Flipper Zero!
|
||||
## [Support Us!](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/SUPPORT.md)
|
||||
Everyone gives much of their uncompensated free time to ensure the success of the Flipper Zero!
|
||||
Thank you to all the supporters!
|
||||
|
||||
</td><td><center><a href="https://github.com/DarkFlippers/unleashed-firmware" target="_blank"><img src="https://user-images.githubusercontent.com/10697207/186202043-26947e28-b1cc-459a-8f20-ffcc7fc0c71c.png" align="center" alt="fzCUSTOM" border="0" width="95%" height="95%"></a></center></td></tr></table>
|
||||
- [Support us if you like what you see](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/SUPPORT.md)! 😄🚀💸
|
||||
- Donations: BTC: `3MPQbKmGRCstg4FjnadfHa3woCT94JkR2a`
|
||||
- Donations: ETH: `0xC32Ea488DBeCF95992A5C81BD411e56Bd418BC5f`
|
||||
- [Join THE Flipper Uncensored Discord](https://discord.gg/gF2bBUzAFe)
|
||||
|
||||
<b>Latest Updates:</b>
|
||||
## Latest Updates
|
||||
|
||||
- To avoid Application errors and duplicates, delete /ext/apps before doing the RM firmware update
|
||||
- Known Issues: `Chess`
|
||||
- Last Synced/Checked [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware), changes in [changelog](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/CHANGELOG.md): `2022-10-13 17:56 GMT`
|
||||
- Last Synced/Checked [OFW](https://github.com/flipperdevices/flipperzero-firmware), changes in [commits](https://github.com/flipperdevices/flipperzero-firmware/commits/dev): `2022-10-13 17:56 GMT`
|
||||
- Updated [TOTP (By akopachov)](https://github.com/akopachov/flipperzero-firmware/tree/totp_plugin)
|
||||
- Assets: Includes New Dolphin Animations: [Blaster (By Sasquach)]
|
||||
- Assets: Includes New Dolphin Animations: [Flipper City (By Svaarich)]
|
||||
- Updated Random Deed Function To Include New Options from OFW
|
||||
- Updated Assets: Dolphin Animations: [Rogue Master Custom Firmware (By Sasquach)] & [Narut0 (By Sasquach)]
|
||||
- OFW: Dolphin score points update **(WARNING!!! Dolphin Level will be reset after installing of this release!!!!)**
|
||||
- Updated view for desktop to exclude icons on the left and show minimal battery [By Talking-Sasquach](https://github.com/skizzophrenic/Talking-Sasquach/tree/main/Battery%20Only%20Top%20Status%20Bar)
|
||||
- Added: [Black Jack (By teeebor)](https://github.com/teeebor/flipper_games) (Thank you Haseo for PR)
|
||||
- Added: [Music Beeper (By OFW)](With Changes By qqMajiKpp/Haseo)
|
||||
- Chip 8 Removed, Tama Fix and Tanks Fixed [By Haseo](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/362)
|
||||
- Last Synced/Checked [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware), changes in [changelog](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/CHANGELOG.md): `2022-11-23 21:01 EST`
|
||||
- Last Synced/Checked [OFW](https://github.com/flipperdevices/flipperzero-firmware), changes in [commits](https://github.com/flipperdevices/flipperzero-firmware/commits/dev): `2022-11-23 21:01 EST`
|
||||
- Added: [Zero Tracker (By DrZZlo13)](https://github.com/DrZlo13/flipper-zero-music-tracker)
|
||||
- Updated: [DHT Temp Monitor (By quen0n)](https://github.com/quen0n/FipperZero-DHT-Monitor) `Req: DHT11/DHT22(AM2302)/AM2301`
|
||||
- Updated: [Sub-GHz Bruteforcer (By Ganapati & xMasterX)](https://github.com/derskythe/flipperzero-subbrute/tree/master)
|
||||
- Updated: [Wii EC Analyser (By csBlueChip)](https://github.com/csBlueChip/FlipperZero_WiiEC)
|
||||
- Updated: [Authenticator/TOTP (By akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
||||
- Updated: [Temperature Sensor (By Mywk)](https://github.com/Mywk/FlipperTemperatureSensor) `Req: HTU2XD, SHT2X, SI702X, SI700X, SI701X or AM2320`
|
||||
- Updated: [Zero Tracker (By DrZZlo13)](https://github.com/DrZlo13/flipper-zero-music-tracker)
|
||||
- Added: [Password Generator (By anakod)](https://github.com/anakod/flipper_passgen)
|
||||
- Updated: [Timelapse (By theageoflove)](https://github.com/theageoflove/flipperzero-zeitraffer)
|
||||
- Added: [NRF24 Scanner (By vad7)](https://github.com/vad7/nrf24scan)
|
||||
|
||||
<details>
|
||||
<summary><B>TO DO / REMOVED</b></summary><br/>
|
||||
## Install from Release
|
||||
FLASH STOCK FIRST BEFORE UPDATING TO CUSTOM FIRMWARE!
|
||||
- To avoid Application errors, delete /ext/apps before doing the RM firmware update
|
||||
- To install new FW, extract the [latest release zip file](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/releases) to a folder, put the folder in the update folder on your SD card, and run the update file inside the folder using the Archive app (down from flipper desktop). If you were previously unleashed, you need to update your extend_range.txt file.`UPDATE IGNORE FLAG TO TRUE TO UNLEASH YOUR FLIPPER!!` On any update, you may need to update this file and your unirf map file, so keep backups. 😄
|
||||
|
||||
- [Keynote BT plugin: long press on OK to switch between Space and Retur… #1729 (By coded-with-claws)]
|
||||
- GPIO: Feature to read EEPROM of SFP Modules using I2C [(By marcusju)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/198)
|
||||
- Settings: Rename from App [(Thanks to E_Surge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/259)
|
||||
- Lost To Faps: Settings: Favorite Game by holding UP on Desktop [Thanks to gotnull](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/57)
|
||||
- Lost To Faps: Settings: Hold Down for Games Menu [(Thanks to ESurge)](https://github.com/ESurge/flipperzero-firmware-wPlugins)
|
||||
- Moved SubGHz Remote to FAP App (Not Working, So Reverted To Internal)
|
||||
- Moved GPIO to FAP App (Not Working, So Reverted To Internal)
|
||||
- Moved Infrared to FAP App (Not Working, So Reverted To Internal)
|
||||
- [I²C-Scanner #1431 (By GitChris3004)](https://github.com/flipperdevices/flipperzero-firmware/pull/1431)
|
||||
## Build
|
||||
```bash
|
||||
$ git clone --recursive https://github.com/RogueMaster/flipperzero-firmware-wPlugins.git
|
||||
$ cd flipperzero-firmware-wPlugins/
|
||||
$ ./fbt updater_package
|
||||
|
||||
</details>
|
||||
# If building FAPS:
|
||||
$ ./fbt fap_dist
|
||||
|
||||
<table width="100%" border="0" cellspacing="0">
|
||||
<tr> <td colspan=2> <h3>This software is for experimental purposes only and is not meant for any illegal activity/purposes. We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law.</h3> </td> </tr>
|
||||
<tr> <td>
|
||||
<br><b>FLASH STOCK FIRST BEFORE UPDATING TO CUSTOM FIRMWARE<b>
|
||||
# If building image assets:
|
||||
$ ./fbt resources icons dolphin_ext
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><B>HOW TOs</b></summary><br/>
|
||||
## How To
|
||||
|
||||
- [HERE IS A GUIDE FOR INSTALL (BY PINGYWON)](https://flipper.pingywon.com/)
|
||||
- [HERE IS A NOOB GUIDE TO FLASH AND UNLOCK (BY interestingsoup)](https://interestingsoup.com/n00b-guide-flashing-flipper-zero-to-rougemaster/)
|
||||
@@ -59,62 +60,43 @@
|
||||
- [How to add extra SubGHz frequencies](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/documentation/SubGHzSettings.md)
|
||||
- [💎 Extra plugins precompiled for Unleashed](https://github.com/UberGuidoZ/Flipper/tree/main/Applications/Unleashed)
|
||||
- [Configure Sub-GHz Remote App](https://github.com/RogueMaster/flipperzero-firmware/blob/420/documentation/SubGHzRemotePlugin.md)
|
||||
</details>
|
||||
- [GAMES ONLY MODE PASSWORD: UP UP DOWN DOWN LEFT RIGHT LEFT RIGHT IN CLOCK](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/GAMES_ONLY.md)
|
||||
- [FLIPPER PROJECT WISH LIST](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/RoadMap.md)
|
||||
- [SAMPLE EDUCATIONAL PROJECTS 😄](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/RoadMap.md)
|
||||
- Contact me on [Discord](https://discord.gg/gF2bBUzAFe) if you want a renamed Flipper DFU. I can do custom names too!
|
||||
- [`FUN Links HERE` Collection for your Flipper SD](https://github.com/RogueMaster/awesome-flipperzero-withModules)
|
||||
|
||||
- To avoid Application errors, delete /ext/apps before doing the RM firmware update
|
||||
- To install new FW, extract the [latest release zip file](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/releases) to a folder, put the folder in the update folder on your SD card, and run the update file inside the folder using the Archive app (down from flipper desktop). If you were previously unleashed, you need to update your extend_range.txt file. **UPDATE IGNORE FLAG TO TRUE TO UNLEASH YOUR FLIPPER!!** On any update, you may need to update this file and your unirf map file, so keep backups. 😄
|
||||
- [<h2>GAMES ONLY MODE PASSWORD: UP UP DOWN DOWN LEFT RIGHT LEFT RIGHT IN CLOCK</h2>](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/GAMES_ONLY.md)
|
||||
<br>[FLIPPER PROJECT WISH LIST](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/RoadMap.md) - [SAMPLE EDUCATIONAL PROJECTS 😄](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/RoadMap.md)
|
||||
<br>[`FUN Links HERE` Collection for your Flipper SD](https://github.com/RogueMaster/awesome-flipperzero-withModules)
|
||||
</td> <td>
|
||||
|
||||
<h2>DONATIONS ACCEPTED 😄🚀💸</h2>
|
||||
BTC: <B>3MPQbKmGRCstg4FjnadfHa3woCT94JkR2a</B><br>
|
||||
ETH: <B>0xC32Ea488DBeCF95992A5C81BD411e56Bd418BC5f</B>
|
||||
<br> <br>
|
||||
|
||||
Contact me on [Discord](https://discord.gg/gF2bBUzAFe) if you want a renamed Flipper DFU. I can do custom names too!
|
||||
<br><h2>[Join my Flipper Uncensored Discord](https://discord.gg/gF2bBUzAFe)</h2>
|
||||
<details>
|
||||
<summary><B>You should clone with</B></summary></br>
|
||||
## All Changes/Features
|
||||
|
||||
```shell
|
||||
$ git clone --recursive https://github.com/RogueMaster/flipperzero-firmware-wPlugins.git
|
||||
$ cd flipperzero-firmware-wPlugins/
|
||||
$ ./fbt resources icons
|
||||
$ ./fbt updater_package
|
||||
|
||||
# If building FAPS:
|
||||
$ ./fbt plugin_dist
|
||||
```
|
||||
</details>
|
||||
</td> </tr>
|
||||
<tr> <td>
|
||||
|
||||
<details>
|
||||
<summary><B>All Changes/Features</b></summary><br/>
|
||||
|
||||
- Animations: File `/ext/dolphin/manifest.txt` no longer will get overwritten. Any automatic building of animations is disabled [here](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/commit/fbe9175e0c828a54e651ee11f64f10f21e36a907).
|
||||
- Animations: Hold Center to change Flipper idle animation. [Thanks to Zycenios](https://github.com/flipperdevices/flipperzero-firmware/commit/111786ef40e50a40d2e510595672b569d9b97bba) With changes by RogueMaster.
|
||||
- Animations: iButton and RFID P0kem0n images [Thanks to Panzer00Z](https://github.com/Panzer00Z/flipperzero-firmware/)
|
||||
- Animations: Idle animations will show all animations regardless of level and butthurt [Thanks to qqMajiKpp]
|
||||
- Animations: Painting speech bubbles updated from FalsePhilosopher
|
||||
- Animations: RM FW Update image [(Thanks to E_Surge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/257)
|
||||
- Animations: SubGHZ Scanning image with Pikachu [Thanks to Panzer00Z](https://github.com/Panzer00Z/flipperzero-firmware/blob/3a548ea9bb181c9348d8afb427890c411456134e/assets/icons/SubGhz/Scanning_123x52.png)
|
||||
- Animations: Trimmed out the Flipper animations. `/ext/dolphin` folder on your Flipper should now be managed by you! [Copy this folder (RM Select)](https://github.com/RogueMaster/awesome-flipperzero-withModules/tree/rogue_main/dolphin-RMselect) or [this folder (RM minimal)](https://github.com/RogueMaster/awesome-flipperzero-withModules/tree/rogue_main/dolphin-minimal) if you don't want to do the work but want more animations.
|
||||
- [Archive: File Browser Ordering (By Dig03)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/389)
|
||||
- [Archive: Browser: Context menu to show file content (By askoriy)](https://github.com/DarkFlippers/unleashed-firmware/pull/139)
|
||||
- Archive: FAPs are now launchable from Archive [By RogueMaster], thanks xMasterX for the suggestion
|
||||
- Assets: Includes a NFC Level 50 Gan0n Amiibo
|
||||
- Assets: Includes a NFC Level 50 Z3lda Amiibo
|
||||
- Assets: Includes a NFC Rick Roll link
|
||||
- Assets: Includes New Dolphin Animations: [Listed Here](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/tree/420/assets/resources/dolphin)
|
||||
- Assets: Includes sample Music Player tunes
|
||||
- Assets: Includes sample SubGHz assets for Crosswalk, Handicap Doors, Sextoys, Tesla Charge Port, and Unitree Go1 Robot Dog
|
||||
- Assets: Includes Sonic Screw Driver sound for the Wav Player
|
||||
- Assets: Running DolphinRestorer.fap on new install will auto-level to Level 7.
|
||||
- [BadUSB: BadUSB as FAP #396 (By ESurge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/396)
|
||||
- BadUSB: Added ignore DUCKY_LANG cmd to retain compatibility with existing scripts [(Thanks to v1nc)](https://github.com/v1nc/flipperzero-firmware)
|
||||
- BadUSB: Assets for Kiosk Evasion and Wifi Stealer
|
||||
- BadUSB: Assets for Kiosk Evasion (By nocomp) and Wifi Stealer (By 7h30th3r0n3)
|
||||
- BadUSB: [Dummy decoy/bad usb keyboard layout #1525 (By dummy-decoy)](https://github.com/flipperdevices/flipperzero-firmware/pull/1525)
|
||||
- BadUSB: nb-NO Added norwegian keyboard layout [(By jd-raymaker)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/357)
|
||||
- BadUSB: show script errors on screen [(By CromFr)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/200)
|
||||
- BadUSB: sk-SK maping keybord for BadUsb [(By jaroslavmraz)](https://github.com/flipperdevices/flipperzero-firmware/pull/1619)
|
||||
- Clock.fap, iButton.fap and U2F.fap loader apps and available as Favorites [Thanks to ESurge](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/336)
|
||||
- Clock: Clock.fap loader apps and available as Favorites [Thanks to ESurge](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/336)
|
||||
- Desktop: Hidden top bar [Thanks to ESurge](https://github.com/ESurge/)
|
||||
- Desktop: Exclude icons on the left and show minimal battery [Thanks to skizzophrenic/Talking-Sasquach](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/360)
|
||||
- Development free space thanks to removal of unused debug tools and [thanks to ESurge](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/46/files) for removal of first start assets.
|
||||
- Dolphin: Assigned profile pic for levels 1-10 (Happy Lvl 1 Dolphin), 11-15 (Happy Lvl 2 Dolphin), 16-18 (Happy Lvl 3 Dolphin), 19-21 (Kid G0ku), 22-24 (Adult G0ku), 25-27 (SSJ G0ku) and 28-30 (SSJ3 G0ku)
|
||||
- Dolphin: Expanded max level from 3 to 30 using [Roll20](https://roll20.net/compendium/dnd5e/Monsters#h-Experience%20Points), Increased max deed XP per action type from 15 to 45 exp daily & updated animation manifest for max level 30 for all animations (By RogueMaster)
|
||||
@@ -125,29 +107,37 @@ $ ./fbt plugin_dist
|
||||
- Dolphin: Passport: Show EXP [(By Dabolus)](https://github.com/Dabolus/flipperzero-firmware-rpg/)
|
||||
- Dolphin: Changed daily MAX to 198 on all 7 Deed Types. Random Deed Selection used for MAX +3 EXP daily gain.
|
||||
- Dolphin: Plugin Achivement +3 EXP for a total of up to 700 EXP daily. Plugin Achivements are:
|
||||
- - Dice First Roll for d20+ = sides on dice (i.e. Nat 20 on d20)
|
||||
- - Dice First Roll for d20+ = sides on dice - 1 (+1 EXP) (i.e. 19 on d20)
|
||||
- - Games Only Mode from Lock Menu
|
||||
- - Getting 2048 in 2048
|
||||
- - Mouse Jacker Ducky Run
|
||||
- - NRFSniffer Found Address
|
||||
- - Stopwatch @ Alert
|
||||
- - Tetris, Snake, or Flappy Bird Score For EXP
|
||||
- - Zombiez for every 20 Zombie kills
|
||||
- Dice First Roll for d20+ = sides on dice (i.e. Nat 20 on d20)
|
||||
- Dice First Roll for d20+ = sides on dice - 1 (+1 EXP) (i.e. 19 on d20)
|
||||
- Games Only Mode from Lock Menu
|
||||
- Getting 2048 in 2048
|
||||
- Mouse Jacker Ducky Run
|
||||
- NRFSniffer Found Address
|
||||
- Stopwatch @ Alert
|
||||
- Tetris, Snake, or Flappy Bird Score For EXP
|
||||
- Zombiez for every 20 Zombie kills
|
||||
- Dolphin: SD dolphin manifest updated to weight animations differently
|
||||
- GPIO: Feature to read EEPROM of SFP Modules using I2C [(By marcusju)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/198)
|
||||
- GPIO: [I²C-Scanner #1431 (By GitChris3004)](https://github.com/flipperdevices/flipperzero-firmware/pull/1431)
|
||||
- iButton: [Fixed issue when loading iButton keys or U2F token from Archive app #382 (By ESurge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/382)
|
||||
- iButton: iButton.fap loader apps and available as Favorites [Thanks to ESurge](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/336)
|
||||
- Icon Decode/Encode [(Thanks to PixlEmly)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/55/files)
|
||||
- IR: Universal AC, Audio, Fans & Projectors from [Unleashed/Eng1n33r](https://github.com/DarkFlippers/unleashed-firmware)
|
||||
- [Infrared: Infrared AS FAP #398 (By RogueMaster)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/398) (With Thanks to ESurge) [Restored Infrared and RFID CLI #405 (By ESurge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/405)
|
||||
- Infrared: Universal AC, Audio, Fans & Projectors from [Unleashed/Eng1n33r](https://github.com/DarkFlippers/unleashed-firmware)
|
||||
- Plugins: 2048, Arkanoid, Snake, and Tetris show score. Thanks to [whoamins](https://github.com/flipperdevices/flipperzero-firmware/commit/7feda832ede1ba8468eff2ca055fef3ddbdc16ac) and [DevMilanIan](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/188) With position changes by RogueMaster. Also all + Tic Tac Toe updated by [Unleashed/Eng1n33r](https://github.com/DarkFlippers/unleashed-firmware) for stability.
|
||||
- Plugins: Icon for Clock [Thanks to Redlink](https://github.com/redlink2/flipperzero-firmware/tree/menuChanges)
|
||||
- [RFID: LFRFID AS FAP #397 (By ROgueMaster)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/397) (With Thanks to ESurge) [Restored Infrared and RFID CLI #405 (By ESurge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/405)
|
||||
- Settings: "Lock W PIN + Off" add to UP menu [(By RogueMaster)]
|
||||
- Settings: Actual PIN Lock [(By RogueMaster)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/applications/desktop/desktop.c)
|
||||
- Settings: Auto-Lock Options Added: 10s+15s+90s [(By RogueMaster)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c)
|
||||
- Settings: Battery Meter on Desktop [Thanks to McAzzaMan](https://github.com/McAzzaMan/flipperzero-firmware/tree/BatteryPercentageView)
|
||||
- Settings: Custom name with this compile: CUSTOM_FLIPPER_NAME=name ./fbt updater_package [By Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware)
|
||||
- Settings: Desktop => [Games Only Mode (By RogueMaster)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/GAMES_ONLY.md)
|
||||
- - [UP UP DOWN DOWN LEFT RIGHT LEFT RIGHT FROM CLOCK](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/GAMES_ONLY.md)<== FULL LIST OF GAMES ONLY CONTROLS
|
||||
- - [UP UP DOWN DOWN LEFT RIGHT LEFT RIGHT FROM CLOCK](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/GAMES_ONLY.md) (FULL LIST OF GAMES ONLY CONTROLS)
|
||||
- Settings: LCD Timeout Options Added: 10s+90s+2min+5min+10min [(By RogueMaster)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/applications/notification/notification_settings_app.c)
|
||||
- Settings: Rename from App [(Thanks to E_Surge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/409)
|
||||
- Settings: Rename from SD `dolphin/name.txt` [(Thanks to E_Surge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/259)
|
||||
- Settings: Power: Fix for settings reload every second [(By lokiuox)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/364)
|
||||
- Settings: Scan names will have timestamp instead of random name assigned for [NFC](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/lib/toolbox/random_name.c) and [SubGHz](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/applications/subghz/scenes/subghz_scene_read_raw.c) (By RogueMaster)
|
||||
- Settings: Storage Info: [SD info: Add dynamic units and free % #1634 (By non-bin)](https://github.com/flipperdevices/flipperzero-firmware/pull/1634)
|
||||
- Settings: Updated Dummy Mode mode to have access to 2048, Dice, Snake, Tetris & Zombiez [(By RogueMaster)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/commit/bf964fffdd2c1d730623673987a6de32a3f7c92f)
|
||||
@@ -160,83 +150,105 @@ $ ./fbt plugin_dist
|
||||
- SubGHz: [Add settings to subghz read functionality to allow setting RSSI threshold (raw only) (By PolymerPrints)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/184)
|
||||
- SubGHz: Extended ranges enabled through flag in /ext/subghz/assets/extend_range.txt [from tkerrby](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/116)
|
||||
- SubGHz: Moved setting_user file to setting_user.txt! This makes it changable from IOS app. (By RogueMaster)
|
||||
- SubGHz: New frequency analyzer [(By ClusterM)](https://github.com/flipperdevices/flipperzero-firmware/pull/1501) [feedback mode (by darmiel)](https://github.com/darmiel/flipper-playlist/tree/feat/stealth-frequency-analyzer) [Quiet Mode (by Himura2la)](https://github.com/ClusterM/flipperzero-firmware/pull/1)
|
||||
- SubGHz: New frequency analyzer [(By ClusterM)](https://github.com/flipperdevices/flipperzero-firmware/pull/1501) [feedback mode (by darmiel)](https://github.com/darmiel/flipper-playlist/tree/feat/stealth-frequency-analyzer) [Quiet Mode (by Himura2la)](https://github.com/ClusterM/flipperzero-firmware/pull/1) [New frequency analyzer #1557 (By ClusterM)](https://github.com/flipperdevices/flipperzero-firmware/pull/1557)
|
||||
- SubGHz: Protocols An-Motors, BFT Mitto, Came Atomo, FAAC SLH (Spa), HCS101, Keeloq, Keeloq Common, Nice Flor S, SecPlus v1+v2 and Star Line updates from [Eng1n33r](https://github.com/DarkFlippers/unleashed-firmware)
|
||||
- SubGHz: Unlock from SD flag from [(cloudbreakdaniel)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/commit/97db0dc91ee3dff812b4dec0618e3f198de14405). Update `subghz/assets/extend_range.txt` with [this file](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/assets/resources/subghz/assets/extend_range.txt) on SD. **UPDATE IGNORE FLAG TO TRUE TO UNLEASH YOUR FLIPPER!!**
|
||||
- U2F: U2F.fap loader apps and available as Favorites [Thanks to ESurge](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/336)
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary><B>Open PRs Checked Out & Not Merged In Main</b></summary><br/>
|
||||
|
||||
- [NFC: Display UL PWD_AUTH payload / ntag-pwd-capture #1471 (Thanks to GMMan)](https://github.com/flipperdevices/flipperzero-firmware/pull/1471)
|
||||
- [New frequency analyzer #1557 (By ClusterM)](https://github.com/flipperdevices/flipperzero-firmware/pull/1557)
|
||||
- [Automatic shutdown on idle #1647 (By SHxKenzuto)](https://github.com/flipperdevices/flipperzero-firmware/pull/1647)
|
||||
- [Decode RAW recordings #1667 (By qistoph)](https://github.com/flipperdevices/flipperzero-firmware/pull/1667)
|
||||
|
||||
</details>
|
||||
|
||||
</td><td>
|
||||
|
||||
<details>
|
||||
<summary><B>GAMES</b></summary><br/>
|
||||
## Games
|
||||
|
||||
- [15 (By x27)](https://github.com/x27/flipperzero-game15)
|
||||
- [2048 (By OlegSchwann)](https://github.com/OlegSchwann/flipperzero-firmware/tree/hackaton/game_2048/applications/game-2048) [(Score By DevMilanIan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/186)
|
||||
- [Arkanoid (By gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins) [(Score By DevMilanIan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/188)
|
||||
- [Black Jack (By teeebor)](https://github.com/teeebor/flipper_games)
|
||||
- [BlackJack (By teeebor)](https://github.com/teeebor/flipper_games)
|
||||
- [Chess (By Okalachev)](https://github.com/okalachev/flipperzero-firmware/tree/chess) Crashes 1st load if FW <~750KB or every load on larger FW `Broken?`
|
||||
- [Chip8 Emulator (By mega8bit)](https://github.com/mega8bit/flipperzero-firmware) Updated by ESurge. Add SD folder `chip8`, [Get GAMES HERE](https://johnearnest.github.io/chip8Archive/) (Needs Controls Programmed) `HIDDEN because its broken`
|
||||
- [Doom (By p4nic4ttack)](https://github.com/p4nic4ttack/doom-flipper-zero/)
|
||||
- [Dice Roller Including SEX/WAR/8BALL/WEED DICE (By RogueMaster)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/applications/dice/dice.c)
|
||||
- [Flappy Bird (By DroomOne)](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird)
|
||||
- [Doom (By p4nic4ttack)](https://github.com/p4nic4ttack/doom-flipper-zero/)
|
||||
- [Flappy Bird (By DroomOne)](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird) [Flappy: Border hitboxes, bigger Pilars (By TQMatvey)](https://github.com/DarkFlippers/unleashed-firmware/pull/114) [Increase pilars line width to improve visibility (By ahumeniy)](https://github.com/DarkFlippers/unleashed-firmware/pull/140)
|
||||
- [Game of Life (Updated to work by tgxn) (By itsyourbedtime)](https://github.com/tgxn/flipperzero-firmware/blob/dev/applications/game_of_life/game_of_life.c)
|
||||
- [Heap Defence (By xMasterX)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/commit/fc776446de9fdd553b221c02668b925b689378d8) [(original by wquinoa & Vedmein)](https://github.com/Vedmein/flipperzero-firmware/tree/hd/svisto-perdelki)
|
||||
- [Mandelbrot Set (By Possibly-Matt)](https://github.com/Possibly-Matt/flipperzero-firmware-wPlugins)
|
||||
- [Minesweeper (By panki27)](https://github.com/panki27/minesweeper)
|
||||
- [Monty Hall (By DevMilanIan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/203)
|
||||
- Snake [OFW]
|
||||
- [Scorched Tanks (By jasniec)](https://github.com/jasniec/flipper-scorched-tanks-game)
|
||||
- [Snake (By OlegSchwann)-OFW](https://github.com/flipperdevices/flipperzero-firmware/pull/829)(With updates from DrZlo13, xMasterX, QtRoS and RogueMaster) [Snake Score Saving (By JuanJakobo)](https://github.com/flipperdevices/flipperzero-firmware/pull/1922) [Turns anywhere (By TQMatvey)](https://github.com/DarkFlippers/unleashed-firmware/pull/125) [Food Spawns Anywwhere (By TQMatvey)](https://github.com/DarkFlippers/unleashed-firmware/pull/130)
|
||||
- [Solitaire (By teeebor)](https://github.com/teeebor/flipper_games)
|
||||
- [T-Rex (By gelin)](https://github.com/gelin/t-rex-runner) WIP
|
||||
- [TAMA P1 (By GMMan)](https://github.com/GMMan/flipperzero-firmware/tree/tama-p1) requires [this rom](https://tinyurl.com/tamap1) IN `tama_p1` on SD as `rom.bin` to make it work.
|
||||
- [Tanks (By Alexgr13)](https://github.com/alexgr13/flipperzero-firmware/tree/fork/dev/applications/tanks-game)
|
||||
- [Tetris (By jeffplang)](https://github.com/jeffplang/flipperzero-firmware/tree/tetris_game/applications/tetris_game)
|
||||
- [Tic Tac Toe (By gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins)
|
||||
- [Video Poker (By PixlEmly)](https://github.com/PixlEmly/flipperzero-firmware-testing/blob/420/applications/VideoPoker/poker.c)
|
||||
- [Zombiez (Reworked By DevMilanIan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/240) [(Original By Dooskington)](https://github.com/Dooskington/flipperzero-zombiez)
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><B>PLUGINS</b></summary><br/>
|
||||
## Plugins
|
||||
|
||||
- [Bluetooth Remote (By Cutch)[OFW]](https://github.com/flipperdevices/flipperzero-firmware/pull/1330)
|
||||
- [Air Mouse (By ginkage)](https://github.com/ginkage/FlippAirMouse/)
|
||||
- [Authenticator/TOTP (By akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
||||
- [Bad Apple (By GMMan)](https://github.com/GMMan/flipperzero-badapple) `video.bin NEEDED, Please LMK if you have it`
|
||||
- [Barcode Generator (By McAzzaMan)](https://github.com/McAzzaMan/flipperzero-firmware/tree/UPC-A_Barcode_Generator/applications/barcode_generator)
|
||||
- [Bluetooth Remote (By Cutch)-OFW](https://github.com/flipperdevices/flipperzero-firmware/pull/1330)
|
||||
- [BPM Tapper (By panki27)](https://github.com/panki27/bpm-tapper)
|
||||
- [Calculator (By n-o-T-I-n-s-a-n-e)](https://github.com/n-o-T-I-n-s-a-n-e)
|
||||
- [Ceasar Cipher (By panki27)](https://github.com/panki27/caesar-cipher)
|
||||
- [Clock/Stopwatch (By CompaqDisc, Stopwatch & Sound Alert By RogueMaster)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61) [12/24HR (By non-bin)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/254) [Refactoring (By GMMan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/256)
|
||||
- [DSTIKE Deauther (By SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module/tree/FlipperZero-Module-v2/FlipperZeroModule/FlipperZero-ESP8266-Deauth-App)) `Req: ESP8266`
|
||||
- [Dolphin Backup (By nminaylov)](https://github.com/flipperdevices/flipperzero-firmware/pull/1384) Modified by RogueMaster
|
||||
- [Counter (By Krulknul)](https://github.com/Krulknul/dolphin-counter)
|
||||
- [DAP Link (By DrZlo13)-OFW](https://github.com/flipperdevices/flipperzero-firmware/pull/1897)
|
||||
- [Deauther PWNDTOOLS V2.6.0 (By HEX0DAYS)](https://github.com/HEX0DAYS/FlipperZero-PWNDTOOLS) `Req: ESP8266` [Original](https://github.com/SpacehuhnTech/esp8266_deauther)
|
||||
- [DHT Temp Monitor (By quen0n)](https://github.com/quen0n/FipperZero-DHT-Monitor) `Req: DHT11/DHT22(AM2302)/AM2301`
|
||||
- [Distance Sensor (By Sanqui)](https://github.com/Sanqui/flipperzero-firmware/tree/hc_sr04)) `Req: HC-SR04` Ported/Modified by xMasterX
|
||||
- [Dolphin Backup (By nminaylov)-OFW](https://github.com/flipperdevices/flipperzero-firmware/pull/1384) Modified by RogueMaster
|
||||
- [Dolphin Restorer (By nminaylov)](https://github.com/flipperdevices/flipperzero-firmware/pull/1384) Cloned by RogueMaster
|
||||
- [DSTIKE Deauther (By SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module/tree/FlipperZero-Module-v2/FlipperZeroModule/FlipperZero-ESP8266-Deauth-App) `Req: ESP8266`
|
||||
- [DTMF Dolphin (By litui)](https://github.com/litui/dtmf_dolphin)
|
||||
- [Flashlight (By xMasterX)](https://github.com/xMasterX/flipper-flashlight)
|
||||
- [GPS (By ezod)](https://github.com/ezod/flipperzero-gps) `Req: NMEA 0183`
|
||||
- [HEX Viewer (By QtRoS)](https://github.com/QtRoS/flipperzero-firmware)
|
||||
- [iButton Fuzzer (By xMasterX)](https://github.com/DarkFlippers/unleashed-firmware)
|
||||
- [i2c Tools (By NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools)
|
||||
- [Lightmeter (By oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter) `Req: BH1750`
|
||||
- [IFTTT Virtual Button (By Ferrazzi)](https://github.com/Ferrazzi/FlipperZero_IFTTT_Virtual_Button) `Req: ESP8266 w/ IFTTT FW Flashed`
|
||||
- [Metronome (By panki27)](https://github.com/panki27/Metronome)
|
||||
- [Morse Code (By wh00hw)](https://github.com/DarkFlippers/unleashed-firmware/pull/144)
|
||||
- [Mouse Jacker (By mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker) ([Pin Out](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/tree/420/applications/mousejacker) from nocomp/Frog/UberGuidoZ) `Req: NRF24`
|
||||
- [Mouse Jiggler (By Jacob-Tate)](https://github.com/Jacob-Tate/flipperzero-firmware/blob/dev/applications/mouse_jiggler/mouse_jiggler.c) (Original By MuddleBox)
|
||||
- [Multi Converter (By theisolinearchip)](https://github.com/theisolinearchip)
|
||||
- Music Beeper [OFW] (Music Player With Changes By qqMajiKpp/Haseo)
|
||||
- Music Player [OFW]
|
||||
- [Music Beeper (By DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/pull/1189) (With Changes By qqMajiKpp/Haseo)
|
||||
- [Music Player (By DrZlo13)-OFW](https://github.com/flipperdevices/flipperzero-firmware/pull/1189)
|
||||
- [NFC Magic (By gornekich)](https://github.com/flipperdevices/flipperzero-firmware/pull/1966)
|
||||
- [NRF Sniff (By mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/nrfsniff) ([Pin Out](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/tree/420/applications/nrfsniff) from nocomp/Frog/UberGuidoZ) `Req: NRF24`
|
||||
- [NRF24 Scanner (By vad7)](https://github.com/vad7/nrf24scan)
|
||||
- [Ocarina (By invalidna-me)](https://github.com/invalidna-me/flipperzero-ocarina) [Here are the LOTZ Songs](https://www.zeldadungeon.net/wiki/Ocarina_of_Time_Songs)
|
||||
- [Paint (By n-o-T-I-n-s-a-n-e)](https://github.com/n-o-T-I-n-s-a-n-e)
|
||||
- [Password Generator (By anakod)](https://github.com/anakod/flipper_passgen)
|
||||
- [PicoPass Reader (By Bettse)](https://github.com/flipperdevices/flipperzero-firmware/pull/1366)
|
||||
- [Pomodoro Timer (By sbrin)](https://github.com/sbrin/flipperzero_pomodoro)
|
||||
- [RFID Fuzzer (By Ganapati)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/245) [Changes by Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware)
|
||||
- [RF Remix (By ESurge)](https://github.com/ESurge/flipperzero-firmware-unirfremix) [(Original By jimilinuxguy)](https://github.com/jimilinuxguy/flipperzero-universal-rf-remote/tree/028d615c83f059bb2c905530ddb3d4efbd3cbcae/applications/jukebox) [(More protocols thanks to darmiel & xMasterX)](https://github.com/darmiel/flipper-playlist/blob/feat/unirf-protocols/applications/unirfremix/unirfremix_app.c)
|
||||
- [SAM (By Unknown)][Original?](https://github.com/ctoth/SAM)
|
||||
- [Sentry Safe (By H4ckd4ddy)](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin) ([Pin Out](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/tree/420/applications/sentry_safe) from [UberGuidoZ](https://github.com/UberGuidoZ/))
|
||||
- [Signal Generator (By nminaylov)-OFW](https://github.com/flipperdevices/flipperzero-firmware/pull/1793)
|
||||
- [Spectrum Analyzer (By jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) [Updates (for testing) Thanks to theY4Kman](https://github.com/theY4Kman/flipperzero-firmware)
|
||||
- [Sub-GHz Bruteforcer (By Ganapati & xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/57)
|
||||
- [Sub-GHz Bruteforcer (By Ganapati & xMasterX)](https://github.com/derskythe/flipperzero-subbrute/tree/master)
|
||||
- [Sub-GHz Playlist (By darmiel)](https://github.com/darmiel/flipper-playlist)
|
||||
- [TOTP (By akopachov)](https://github.com/akopachov/flipperzero-firmware/tree/totp_plugin)
|
||||
- [UPC-A Generator (By McAzzaMan)](https://github.com/McAzzaMan/flipperzero-firmware/tree/UPC-A_Barcode_Generator/applications/barcode_generator)
|
||||
- [Temperature Sensor (By Mywk)](https://github.com/Mywk/FlipperTemperatureSensor) `Req: HTU2XD, SHT2X, SI702X, SI700X, SI701X or AM2320`
|
||||
- [Temperature Sensor (By xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/commit/9c4612e571db42f5e6123a3f159e01337453a6af) `Req: AM2320`
|
||||
- [Timelapse (By theageoflove)](https://github.com/theageoflove/flipperzero-zeitraffer)
|
||||
- [Tuning Fork (By besya)](https://github.com/besya/flipperzero-tuning-fork)
|
||||
- [UART Echo (By DrZlo13)-OFW](https://github.com/flipperdevices/flipperzero-firmware/pull/831)
|
||||
- [USB HID Autofire (By pbek)](https://github.com/pbek/usb_hid_autofire)
|
||||
- [USB Keyboard (By huuck)](https://github.com/huuck/FlipperZeroUSBKeyboard)
|
||||
- [WAV Player (By Zlo)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) Updated by Atmanos & RogueMaster To Work
|
||||
- [WiFi (Deauther) (By Timmotools)](https://github.com/Timmotools/flipperzero_esp8266_deautherv2)
|
||||
- [WiFi (Marauder) (By 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) `REQUIRES ESP32 WITH MARAUDER FLASHED`
|
||||
- [WAV Player (By DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) Updated by Atmanos & RogueMaster To Work
|
||||
- [WiFi (Deauther) V2 (By Timmotools)](https://github.com/Timmotools/flipperzero_esp8266_deautherv2) `Req: ESP8266`
|
||||
- [WiFi (Marauder) (By 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) `Req: ESP32 WITH MARAUDER FLASHED`
|
||||
- [WiFi Scanner v.0.4 (By SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module-ESP8266) `Req: ESP8266 or ESP32`
|
||||
</details>
|
||||
- [Wii EC Analyser (By csBlueChip)](https://github.com/csBlueChip/FlipperZero_WiiEC)
|
||||
- [Zero Tracker (By DrZZlo13)](https://github.com/DrZlo13/flipper-zero-music-tracker)
|
||||
|
||||
</td></tr></table>
|
||||
## Open PRs Checked Out & Not Merged In Main
|
||||
|
||||
- [Automatic shutdown on idle #1647 (By SHxKenzuto)](https://github.com/flipperdevices/flipperzero-firmware/pull/1647)
|
||||
- [Decode RAW recordings #1667 (By qistoph)](https://github.com/flipperdevices/flipperzero-firmware/pull/1667)
|
||||
- [NFC - Machine Readable Travel Documents #1866 (By qistoph)](https://github.com/flipperdevices/flipperzero-firmware/pull/1866)
|
||||
- [nfc: NTAG password auto capture (and other password-related changes) #1843 (By GMMan)](https://github.com/flipperdevices/flipperzero-firmware/pull/1843)
|
||||
- [Snake Plugin: Store game state on close and restore it on restart, show highscore #1922 (By JuanJakobo)](https://github.com/flipperdevices/flipperzero-firmware/pull/1922)
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
- I tried to organize them in terms of difficulty.
|
||||
|
||||
## WISH LIST ITEMS:
|
||||
- Battery Type moved to Power Settings
|
||||
- `Notepad` APP to allow taking quick notes and saving to SD.
|
||||
- - Also can possibly open/edit .md,.txt,.fmf and other text friendly formats
|
||||
- `UART` Move UART Echo app from Debug to GPIO section.
|
||||
- `Write URL to NFC` APP to allow creating URL NFC tags from only the flipper
|
||||
- - Also can possibly support larger URLs than the ones in samples (due to length limits on NFC types)
|
||||
- - Also can possibly create other types of tags, like WIFI configurations
|
||||
|
||||
57
SConstruct
@@ -7,6 +7,7 @@
|
||||
# construction of certain targets behind command-line options.
|
||||
|
||||
import os
|
||||
from fbt.util import path_as_posix
|
||||
|
||||
DefaultEnvironment(tools=[])
|
||||
|
||||
@@ -33,10 +34,6 @@ coreenv = SConscript(
|
||||
)
|
||||
SConscript("site_scons/cc.scons", exports={"ENV": coreenv})
|
||||
|
||||
# Store root dir in environment for certain tools
|
||||
coreenv["ROOT_DIR"] = Dir(".")
|
||||
|
||||
|
||||
# Create a separate "dist" environment and add construction envs to it
|
||||
distenv = coreenv.Clone(
|
||||
tools=[
|
||||
@@ -47,6 +44,7 @@ distenv = coreenv.Clone(
|
||||
"jflash",
|
||||
],
|
||||
ENV=os.environ,
|
||||
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
||||
)
|
||||
|
||||
firmware_env = distenv.AddFwProject(
|
||||
@@ -144,23 +142,28 @@ distenv.Default(basic_dist)
|
||||
dist_dir = distenv.GetProjetDirName()
|
||||
fap_dist = [
|
||||
distenv.Install(
|
||||
f"#/dist/{dist_dir}/apps/debug_elf",
|
||||
firmware_env["FW_EXTAPPS"]["debug"].values(),
|
||||
distenv.Dir(f"#/dist/{dist_dir}/apps/debug_elf"),
|
||||
list(
|
||||
app_artifact.debug
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
),
|
||||
*(
|
||||
distenv.Install(f"#/dist/{dist_dir}/apps/{dist_entry[0]}", dist_entry[1])
|
||||
for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values()
|
||||
distenv.Install(
|
||||
f"#/dist/{dist_dir}/apps",
|
||||
"#/assets/resources/apps",
|
||||
),
|
||||
]
|
||||
Depends(fap_dist, firmware_env["FW_EXTAPPS"]["validators"].values())
|
||||
Depends(
|
||||
fap_dist,
|
||||
list(
|
||||
app_artifact.validator
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
)
|
||||
Alias("fap_dist", fap_dist)
|
||||
# distenv.Default(fap_dist)
|
||||
|
||||
plugin_resources_dist = list(
|
||||
distenv.Install(f"#/assets/resources/apps/{dist_entry[0]}", dist_entry[1])
|
||||
for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values()
|
||||
)
|
||||
distenv.Depends(firmware_env["FW_RESOURCES"], plugin_resources_dist)
|
||||
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
|
||||
|
||||
|
||||
# Target for bundling core2 package for qFlipper
|
||||
@@ -198,6 +201,7 @@ firmware_debug = distenv.PhonyTarget(
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
||||
)
|
||||
distenv.Depends(firmware_debug, firmware_flash)
|
||||
|
||||
@@ -207,6 +211,7 @@ distenv.PhonyTarget(
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
||||
)
|
||||
|
||||
# Debug alien elf
|
||||
@@ -215,7 +220,7 @@ distenv.PhonyTarget(
|
||||
"${GDBPYCOM}",
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ',
|
||||
GDBPYOPTS='-ex "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py" ',
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
@@ -235,14 +240,14 @@ distenv.PhonyTarget(
|
||||
# Linter
|
||||
distenv.PhonyTarget(
|
||||
"lint",
|
||||
"${PYTHON3} scripts/lint.py check ${LINT_SOURCES}",
|
||||
LINT_SOURCES=firmware_env["LINT_SOURCES"],
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py check ${LINT_SOURCES}",
|
||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"format",
|
||||
"${PYTHON3} scripts/lint.py format ${LINT_SOURCES}",
|
||||
LINT_SOURCES=firmware_env["LINT_SOURCES"],
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py format ${LINT_SOURCES}",
|
||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||
)
|
||||
|
||||
# PY_LINT_SOURCES contains recursively-built modules' SConscript files + application manifests
|
||||
@@ -282,7 +287,7 @@ distenv.PhonyTarget(
|
||||
)
|
||||
|
||||
# Start Flipper CLI via PySerial's miniterm
|
||||
distenv.PhonyTarget("cli", "${PYTHON3} scripts/serial_cli.py")
|
||||
distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py")
|
||||
|
||||
|
||||
# Find blackmagic probe
|
||||
@@ -291,6 +296,16 @@ distenv.PhonyTarget(
|
||||
"@echo $( ${BLACKMAGIC_ADDR} $)",
|
||||
)
|
||||
|
||||
|
||||
# Find STLink probe ids
|
||||
distenv.PhonyTarget(
|
||||
"get_stlink",
|
||||
distenv.Action(
|
||||
lambda **kw: distenv.GetDevices(),
|
||||
None,
|
||||
),
|
||||
)
|
||||
|
||||
# Prepare vscode environment
|
||||
vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*"))
|
||||
distenv.Precious(vscode_dist)
|
||||
|
||||
@@ -8,4 +8,5 @@ App(
|
||||
stack_size=2 * 1024,
|
||||
order=150,
|
||||
fap_category="Debug",
|
||||
fap_icon_assets="icons",
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "assets_icons.h"
|
||||
#include <file_browser_test_icons.h>
|
||||
#include "file_browser_app_i.h"
|
||||
#include "gui/modules/file_browser.h"
|
||||
#include <furi.h>
|
||||
|
||||
BIN
applications/debug/file_browser_test/icons/badusb_10px.png
Normal file
|
After Width: | Height: | Size: 576 B |
@@ -220,11 +220,7 @@ static UartEchoApp* uart_echo_app_alloc() {
|
||||
furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200);
|
||||
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
|
||||
|
||||
app->worker_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(app->worker_thread, "UsbUartWorker");
|
||||
furi_thread_set_stack_size(app->worker_thread, 1024);
|
||||
furi_thread_set_context(app->worker_thread, app);
|
||||
furi_thread_set_callback(app->worker_thread, uart_echo_worker);
|
||||
app->worker_thread = furi_thread_alloc_ex("UsbUartWorker", 1024, uart_echo_worker, app);
|
||||
furi_thread_start(app->worker_thread);
|
||||
|
||||
return app;
|
||||
|
||||
@@ -424,6 +424,7 @@ MU_TEST(infrared_test_decoder_mixed) {
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 5);
|
||||
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_nec) {
|
||||
@@ -489,6 +490,15 @@ MU_TEST(infrared_test_encoder_rc6) {
|
||||
infrared_test_run_encoder(InfraredProtocolRC6, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_kaseikyo) {
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 4);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 5);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 6);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_decoder_all) {
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolNEC, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolNECext, 1);
|
||||
@@ -498,6 +508,7 @@ MU_TEST(infrared_test_encoder_decoder_all) {
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolRC6, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolRC5, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolSIRC, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolKaseikyo, 1);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(infrared_test) {
|
||||
@@ -515,6 +526,7 @@ MU_TEST_SUITE(infrared_test) {
|
||||
MU_RUN_TEST(infrared_test_decoder_nec);
|
||||
MU_RUN_TEST(infrared_test_decoder_samsung32);
|
||||
MU_RUN_TEST(infrared_test_decoder_necext1);
|
||||
MU_RUN_TEST(infrared_test_decoder_kaseikyo);
|
||||
MU_RUN_TEST(infrared_test_decoder_mixed);
|
||||
MU_RUN_TEST(infrared_test_encoder_decoder_all);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <lib/nfc/protocols/nfca.h>
|
||||
#include <lib/nfc/helpers/mf_classic_dict.h>
|
||||
#include <lib/digital_signal/digital_signal.h>
|
||||
#include <lib/nfc/nfc_device.h>
|
||||
#include <applications/main/nfc/helpers/nfc_generators.h>
|
||||
|
||||
#include <lib/flipper_format/flipper_format_i.h>
|
||||
#include <lib/toolbox/stream/file_stream.h>
|
||||
@@ -16,6 +18,8 @@
|
||||
#define NFC_TEST_RESOURCES_DIR EXT_PATH("unit_tests/nfc/")
|
||||
#define NFC_TEST_SIGNAL_SHORT_FILE "nfc_nfca_signal_short.nfc"
|
||||
#define NFC_TEST_SIGNAL_LONG_FILE "nfc_nfca_signal_long.nfc"
|
||||
#define NFC_TEST_DICT_PATH EXT_PATH("unit_tests/mf_classic_dict.nfc")
|
||||
#define NFC_TEST_NFC_DEV_PATH EXT_PATH("unit_tests/nfc/nfc_dev_test.nfc")
|
||||
|
||||
static const char* nfc_test_file_type = "Flipper NFC test";
|
||||
static const uint32_t nfc_test_file_version = 1;
|
||||
@@ -220,11 +224,272 @@ MU_TEST(mf_classic_dict_test) {
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_dict_load_test) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
mu_assert(storage != NULL, "storage != NULL assert failed\r\n");
|
||||
|
||||
// Delete unit test dict file if exists
|
||||
if(storage_file_exists(storage, NFC_TEST_DICT_PATH)) {
|
||||
mu_assert(
|
||||
storage_simply_remove(storage, NFC_TEST_DICT_PATH),
|
||||
"remove == true assert failed\r\n");
|
||||
}
|
||||
|
||||
// Create unit test dict file
|
||||
Stream* file_stream = file_stream_alloc(storage);
|
||||
mu_assert(file_stream != NULL, "file_stream != NULL assert failed\r\n");
|
||||
mu_assert(
|
||||
file_stream_open(file_stream, NFC_TEST_DICT_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS),
|
||||
"file_stream_open == true assert failed\r\n");
|
||||
|
||||
// Write unit test dict file
|
||||
char key_str[] = "a0a1a2a3a4a5";
|
||||
mu_assert(
|
||||
stream_write_cstring(file_stream, key_str) == strlen(key_str),
|
||||
"write == true assert failed\r\n");
|
||||
// Close unit test dict file
|
||||
mu_assert(file_stream_close(file_stream), "file_stream_close == true assert failed\r\n");
|
||||
|
||||
// Load unit test dict file
|
||||
MfClassicDict* instance = NULL;
|
||||
instance = mf_classic_dict_alloc(MfClassicDictTypeUnitTest);
|
||||
mu_assert(instance != NULL, "mf_classic_dict_alloc\r\n");
|
||||
uint32_t total_keys = mf_classic_dict_get_total_keys(instance);
|
||||
mu_assert(total_keys == 1, "total_keys == 1 assert failed\r\n");
|
||||
|
||||
// Read key
|
||||
uint64_t key_ref = 0xa0a1a2a3a4a5;
|
||||
uint64_t key_dut = 0;
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
mu_assert(
|
||||
mf_classic_dict_get_next_key_str(instance, temp_str),
|
||||
"get_next_key_str == true assert failed\r\n");
|
||||
mu_assert(furi_string_cmp_str(temp_str, key_str) == 0, "invalid key loaded\r\n");
|
||||
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
|
||||
mu_assert(
|
||||
mf_classic_dict_get_next_key(instance, &key_dut),
|
||||
"get_next_key == true assert failed\r\n");
|
||||
mu_assert(key_dut == key_ref, "invalid key loaded\r\n");
|
||||
furi_string_free(temp_str);
|
||||
mf_classic_dict_free(instance);
|
||||
|
||||
// Check that MfClassicDict added new line to the end of the file
|
||||
mu_assert(
|
||||
file_stream_open(file_stream, NFC_TEST_DICT_PATH, FSAM_READ, FSOM_OPEN_EXISTING),
|
||||
"file_stream_open == true assert failed\r\n");
|
||||
mu_assert(stream_seek(file_stream, -1, StreamOffsetFromEnd), "seek == true assert failed\r\n");
|
||||
uint8_t last_char = 0;
|
||||
mu_assert(stream_read(file_stream, &last_char, 1) == 1, "read == true assert failed\r\n");
|
||||
mu_assert(last_char == '\n', "last_char == '\\n' assert failed\r\n");
|
||||
mu_assert(file_stream_close(file_stream), "file_stream_close == true assert failed\r\n");
|
||||
|
||||
// Delete unit test dict file
|
||||
mu_assert(
|
||||
storage_simply_remove(storage, NFC_TEST_DICT_PATH), "remove == true assert failed\r\n");
|
||||
stream_free(file_stream);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST(nfca_file_test) {
|
||||
NfcDevice* nfc = nfc_device_alloc();
|
||||
mu_assert(nfc != NULL, "nfc_device_data != NULL assert failed\r\n");
|
||||
nfc->format = NfcDeviceSaveFormatUid;
|
||||
|
||||
// Fill the UID, sak, ATQA and type
|
||||
uint8_t uid[7] = {0x04, 0x01, 0x23, 0x45, 0x67, 0x89, 0x00};
|
||||
memcpy(nfc->dev_data.nfc_data.uid, uid, 7);
|
||||
nfc->dev_data.nfc_data.uid_len = 7;
|
||||
|
||||
nfc->dev_data.nfc_data.sak = 0x08;
|
||||
nfc->dev_data.nfc_data.atqa[0] = 0x00;
|
||||
nfc->dev_data.nfc_data.atqa[1] = 0x04;
|
||||
nfc->dev_data.nfc_data.type = FuriHalNfcTypeA;
|
||||
|
||||
// Save the NFC device data to the file
|
||||
mu_assert(
|
||||
nfc_device_save(nfc, NFC_TEST_NFC_DEV_PATH), "nfc_device_save == true assert failed\r\n");
|
||||
nfc_device_free(nfc);
|
||||
|
||||
// Load the NFC device data from the file
|
||||
NfcDevice* nfc_validate = nfc_device_alloc();
|
||||
mu_assert(
|
||||
nfc_device_load(nfc_validate, NFC_TEST_NFC_DEV_PATH, true),
|
||||
"nfc_device_load == true assert failed\r\n");
|
||||
|
||||
// Check the UID, sak, ATQA and type
|
||||
mu_assert(memcmp(nfc_validate->dev_data.nfc_data.uid, uid, 7) == 0, "uid assert failed\r\n");
|
||||
mu_assert(nfc_validate->dev_data.nfc_data.sak == 0x08, "sak == 0x08 assert failed\r\n");
|
||||
mu_assert(
|
||||
nfc_validate->dev_data.nfc_data.atqa[0] == 0x00, "atqa[0] == 0x00 assert failed\r\n");
|
||||
mu_assert(
|
||||
nfc_validate->dev_data.nfc_data.atqa[1] == 0x04, "atqa[1] == 0x04 assert failed\r\n");
|
||||
mu_assert(
|
||||
nfc_validate->dev_data.nfc_data.type == FuriHalNfcTypeA,
|
||||
"type == FuriHalNfcTypeA assert failed\r\n");
|
||||
nfc_device_free(nfc_validate);
|
||||
}
|
||||
|
||||
static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) {
|
||||
NfcDevice* nfc_dev = nfc_device_alloc();
|
||||
mu_assert(nfc_dev != NULL, "nfc_device_data != NULL assert failed\r\n");
|
||||
nfc_dev->format = NfcDeviceSaveFormatMifareClassic;
|
||||
|
||||
// Create a test file
|
||||
nfc_generate_mf_classic(&nfc_dev->dev_data, uid_len, type);
|
||||
|
||||
// Get the uid from generated MFC
|
||||
uint8_t uid[7] = {0};
|
||||
memcpy(uid, nfc_dev->dev_data.nfc_data.uid, uid_len);
|
||||
uint8_t sak = nfc_dev->dev_data.nfc_data.sak;
|
||||
uint8_t atqa[2] = {};
|
||||
memcpy(atqa, nfc_dev->dev_data.nfc_data.atqa, 2);
|
||||
|
||||
MfClassicData* mf_data = &nfc_dev->dev_data.mf_classic_data;
|
||||
// Check the manufacturer block (should be uid[uid_len] + 0xFF[rest])
|
||||
uint8_t manufacturer_block[16] = {0};
|
||||
memcpy(manufacturer_block, nfc_dev->dev_data.mf_classic_data.block[0].value, 16);
|
||||
mu_assert(
|
||||
memcmp(manufacturer_block, uid, uid_len) == 0,
|
||||
"manufacturer_block uid doesn't match the file\r\n");
|
||||
for(uint8_t i = uid_len; i < 16; i++) {
|
||||
mu_assert(
|
||||
manufacturer_block[i] == 0xFF, "manufacturer_block[i] == 0xFF assert failed\r\n");
|
||||
}
|
||||
|
||||
// Reference sector trailers (should be 0xFF[6] + 0xFF + 0x07 + 0x80 + 0x69 + 0xFF[6])
|
||||
uint8_t sector_trailer[16] = {
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0x07,
|
||||
0x80,
|
||||
0x69,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0xFF};
|
||||
// Reference block data
|
||||
uint8_t block_data[16] = {};
|
||||
memset(block_data, 0xff, sizeof(block_data));
|
||||
uint16_t total_blocks = mf_classic_get_total_block_num(type);
|
||||
for(size_t i = 1; i < total_blocks; i++) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
mu_assert(
|
||||
memcmp(mf_data->block[i].value, sector_trailer, 16) == 0,
|
||||
"Failed sector trailer compare");
|
||||
} else {
|
||||
mu_assert(memcmp(mf_data->block[i].value, block_data, 16) == 0, "Failed data compare");
|
||||
}
|
||||
}
|
||||
// Save the NFC device data to the file
|
||||
mu_assert(
|
||||
nfc_device_save(nfc_dev, NFC_TEST_NFC_DEV_PATH),
|
||||
"nfc_device_save == true assert failed\r\n");
|
||||
// Verify that key cache is saved
|
||||
FuriString* key_cache_name = furi_string_alloc();
|
||||
furi_string_set_str(key_cache_name, "/ext/nfc/cache/");
|
||||
for(size_t i = 0; i < uid_len; i++) {
|
||||
furi_string_cat_printf(key_cache_name, "%02X", uid[i]);
|
||||
}
|
||||
furi_string_cat_printf(key_cache_name, ".keys");
|
||||
mu_assert(
|
||||
storage_common_stat(nfc_dev->storage, furi_string_get_cstr(key_cache_name), NULL) ==
|
||||
FSE_OK,
|
||||
"Key cache file save failed");
|
||||
nfc_device_free(nfc_dev);
|
||||
|
||||
// Load the NFC device data from the file
|
||||
NfcDevice* nfc_validate = nfc_device_alloc();
|
||||
mu_assert(nfc_validate, "Nfc device alloc assert");
|
||||
mu_assert(
|
||||
nfc_device_load(nfc_validate, NFC_TEST_NFC_DEV_PATH, false),
|
||||
"nfc_device_load == true assert failed\r\n");
|
||||
|
||||
// Check the UID, sak, ATQA and type
|
||||
mu_assert(
|
||||
memcmp(nfc_validate->dev_data.nfc_data.uid, uid, uid_len) == 0,
|
||||
"uid compare assert failed\r\n");
|
||||
mu_assert(nfc_validate->dev_data.nfc_data.sak == sak, "sak compare assert failed\r\n");
|
||||
mu_assert(
|
||||
memcmp(nfc_validate->dev_data.nfc_data.atqa, atqa, 2) == 0,
|
||||
"atqa compare assert failed\r\n");
|
||||
mu_assert(
|
||||
nfc_validate->dev_data.nfc_data.type == FuriHalNfcTypeA,
|
||||
"type == FuriHalNfcTypeA assert failed\r\n");
|
||||
|
||||
// Check the manufacturer block
|
||||
mu_assert(
|
||||
memcmp(nfc_validate->dev_data.mf_classic_data.block[0].value, manufacturer_block, 16) == 0,
|
||||
"manufacturer_block assert failed\r\n");
|
||||
// Check other blocks
|
||||
for(size_t i = 1; i < total_blocks; i++) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
mu_assert(
|
||||
memcmp(mf_data->block[i].value, sector_trailer, 16) == 0,
|
||||
"Failed sector trailer compare");
|
||||
} else {
|
||||
mu_assert(memcmp(mf_data->block[i].value, block_data, 16) == 0, "Failed data compare");
|
||||
}
|
||||
}
|
||||
nfc_device_free(nfc_validate);
|
||||
|
||||
// Check saved key cache
|
||||
NfcDevice* nfc_keys = nfc_device_alloc();
|
||||
mu_assert(nfc_validate, "Nfc device alloc assert");
|
||||
nfc_keys->dev_data.nfc_data.uid_len = uid_len;
|
||||
memcpy(nfc_keys->dev_data.nfc_data.uid, uid, uid_len);
|
||||
mu_assert(nfc_device_load_key_cache(nfc_keys), "Failed to load key cache");
|
||||
uint8_t total_sec = mf_classic_get_total_sectors_num(type);
|
||||
uint8_t default_key[6] = {};
|
||||
memset(default_key, 0xff, 6);
|
||||
for(size_t i = 0; i < total_sec; i++) {
|
||||
MfClassicSectorTrailer* sec_tr =
|
||||
mf_classic_get_sector_trailer_by_sector(&nfc_keys->dev_data.mf_classic_data, i);
|
||||
mu_assert(memcmp(sec_tr->key_a, default_key, 6) == 0, "Failed key compare");
|
||||
mu_assert(memcmp(sec_tr->key_b, default_key, 6) == 0, "Failed key compare");
|
||||
}
|
||||
|
||||
// Delete key cache file
|
||||
mu_assert(
|
||||
storage_common_remove(nfc_keys->storage, furi_string_get_cstr(key_cache_name)) == FSE_OK,
|
||||
"Failed to remove key cache file");
|
||||
furi_string_free(key_cache_name);
|
||||
nfc_device_free(nfc_keys);
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_1k_4b_file_test) {
|
||||
mf_classic_generator_test(4, MfClassicType1k);
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_4k_4b_file_test) {
|
||||
mf_classic_generator_test(4, MfClassicType4k);
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_1k_7b_file_test) {
|
||||
mf_classic_generator_test(7, MfClassicType1k);
|
||||
}
|
||||
|
||||
MU_TEST(mf_classic_4k_7b_file_test) {
|
||||
mf_classic_generator_test(7, MfClassicType4k);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(nfc) {
|
||||
nfc_test_alloc();
|
||||
|
||||
MU_RUN_TEST(nfca_file_test);
|
||||
MU_RUN_TEST(mf_classic_1k_4b_file_test);
|
||||
MU_RUN_TEST(mf_classic_4k_4b_file_test);
|
||||
MU_RUN_TEST(mf_classic_1k_7b_file_test);
|
||||
MU_RUN_TEST(mf_classic_4k_7b_file_test);
|
||||
MU_RUN_TEST(nfc_digital_signal_test);
|
||||
MU_RUN_TEST(mf_classic_dict_test);
|
||||
MU_RUN_TEST(mf_classic_dict_load_test);
|
||||
|
||||
nfc_test_free();
|
||||
}
|
||||
|
||||
@@ -43,11 +43,8 @@ MU_TEST(storage_file_open_lock) {
|
||||
File* file = storage_file_alloc(storage);
|
||||
|
||||
// file_locker thread start
|
||||
FuriThread* locker_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(locker_thread, "StorageFileLocker");
|
||||
furi_thread_set_stack_size(locker_thread, 2048);
|
||||
furi_thread_set_context(locker_thread, semaphore);
|
||||
furi_thread_set_callback(locker_thread, storage_file_locker);
|
||||
FuriThread* locker_thread =
|
||||
furi_thread_alloc_ex("StorageFileLocker", 2048, storage_file_locker, semaphore);
|
||||
furi_thread_start(locker_thread);
|
||||
|
||||
// wait for file lock
|
||||
@@ -133,11 +130,8 @@ MU_TEST(storage_dir_open_lock) {
|
||||
File* file = storage_file_alloc(storage);
|
||||
|
||||
// file_locker thread start
|
||||
FuriThread* locker_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(locker_thread, "StorageDirLocker");
|
||||
furi_thread_set_stack_size(locker_thread, 2048);
|
||||
furi_thread_set_context(locker_thread, semaphore);
|
||||
furi_thread_set_callback(locker_thread, storage_dir_locker);
|
||||
FuriThread* locker_thread =
|
||||
furi_thread_alloc_ex("StorageDirLocker", 2048, storage_dir_locker, semaphore);
|
||||
furi_thread_start(locker_thread);
|
||||
|
||||
// wait for dir lock
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <lib/subghz/transmitter.h>
|
||||
#include <lib/subghz/subghz_keystore.h>
|
||||
#include <lib/subghz/subghz_file_encoder_worker.h>
|
||||
#include <lib/subghz/protocols/registry.h>
|
||||
#include <lib/subghz/protocols/protocol_items.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
|
||||
#define TAG "SubGhz TEST"
|
||||
@@ -13,7 +13,7 @@
|
||||
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
||||
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
||||
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
|
||||
#define TEST_RANDOM_COUNT_PARSE 233
|
||||
#define TEST_RANDOM_COUNT_PARSE 244
|
||||
#define TEST_TIMEOUT 10000
|
||||
|
||||
static SubGhzEnvironment* environment_handler;
|
||||
@@ -43,6 +43,8 @@ static void subghz_test_init(void) {
|
||||
environment_handler, CAME_ATOMO_DIR_NAME);
|
||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||
environment_handler, NICE_FLOR_S_DIR_NAME);
|
||||
subghz_environment_set_protocol_registry(
|
||||
environment_handler, (void*)&subghz_protocol_registry);
|
||||
|
||||
receiver_handler = subghz_receiver_alloc_init(environment_handler);
|
||||
subghz_receiver_set_filter(receiver_handler, SubGhzProtocolFlag_Decodable);
|
||||
@@ -413,11 +415,11 @@ MU_TEST(subghz_decoder_honeywell_wdb_test) {
|
||||
"Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_magellen_test) {
|
||||
MU_TEST(subghz_decoder_magellan_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/magellen_raw.sub"), SUBGHZ_PROTOCOL_MAGELLEN_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n");
|
||||
EXT_PATH("unit_tests/subghz/magellan_raw.sub"), SUBGHZ_PROTOCOL_MAGELLAN_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_MAGELLAN_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_intertechno_v3_test) {
|
||||
@@ -435,11 +437,11 @@ MU_TEST(subghz_decoder_clemsa_test) {
|
||||
"Test decoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_oregon2_test) {
|
||||
MU_TEST(subghz_decoder_ansonic_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/oregon2_raw.sub"), SUBGHZ_PROTOCOL_OREGON2_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_OREGON2_NAME " error\r\n");
|
||||
EXT_PATH("unit_tests/subghz/ansonic_raw.sub"), SUBGHZ_PROTOCOL_ANSONIC_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_ANSONIC_NAME " error\r\n");
|
||||
}
|
||||
|
||||
//test encoders
|
||||
@@ -545,10 +547,10 @@ MU_TEST(subghz_encoder_honeywell_wdb_test) {
|
||||
"Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_magellen_test) {
|
||||
MU_TEST(subghz_encoder_magellan_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/magellen.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n");
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/magellan.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_MAGELLAN_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_intertechno_v3_test) {
|
||||
@@ -563,6 +565,12 @@ MU_TEST(subghz_encoder_clemsa_test) {
|
||||
"Test encoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_ansonic_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/ansonic.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_ANSONIC_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_random_test) {
|
||||
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
|
||||
}
|
||||
@@ -600,10 +608,10 @@ MU_TEST_SUITE(subghz) {
|
||||
MU_RUN_TEST(subghz_decoder_doitrand_test);
|
||||
MU_RUN_TEST(subghz_decoder_phoenix_v2_test);
|
||||
MU_RUN_TEST(subghz_decoder_honeywell_wdb_test);
|
||||
MU_RUN_TEST(subghz_decoder_magellen_test);
|
||||
MU_RUN_TEST(subghz_decoder_magellan_test);
|
||||
MU_RUN_TEST(subghz_decoder_intertechno_v3_test);
|
||||
MU_RUN_TEST(subghz_decoder_clemsa_test);
|
||||
MU_RUN_TEST(subghz_decoder_oregon2_test);
|
||||
MU_RUN_TEST(subghz_decoder_ansonic_test);
|
||||
|
||||
MU_RUN_TEST(subghz_encoder_princeton_test);
|
||||
MU_RUN_TEST(subghz_encoder_came_test);
|
||||
@@ -622,9 +630,10 @@ MU_TEST_SUITE(subghz) {
|
||||
MU_RUN_TEST(subghz_encoder_doitrand_test);
|
||||
MU_RUN_TEST(subghz_encoder_phoenix_v2_test);
|
||||
MU_RUN_TEST(subghz_encoder_honeywell_wdb_test);
|
||||
MU_RUN_TEST(subghz_encoder_magellen_test);
|
||||
MU_RUN_TEST(subghz_encoder_magellan_test);
|
||||
MU_RUN_TEST(subghz_encoder_intertechno_v3_test);
|
||||
MU_RUN_TEST(subghz_encoder_clemsa_test);
|
||||
MU_RUN_TEST(subghz_encoder_ansonic_test);
|
||||
|
||||
MU_RUN_TEST(subghz_random_test);
|
||||
subghz_test_deinit();
|
||||
|
||||
24
applications/examples/example_images/ReadMe.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Application icons
|
||||
To use icons, do the following:
|
||||
* add a line to the application manifest: `fap_icon_assets="folder"`, where `folder` points to the folder where your icons are located
|
||||
* add `#include "application_id_icons.h"` to the application code, where `application_id` is the appid from the manifest
|
||||
* every icon in the folder will be available as a `I_icon_name` variable, where `icon_name` is the name of the icon file without the extension
|
||||
|
||||
## Example
|
||||
We have an application with the following manifest:
|
||||
```
|
||||
App(
|
||||
appid="example_images",
|
||||
...
|
||||
fap_icon_assets="images",
|
||||
)
|
||||
```
|
||||
|
||||
So the icons are in the `images` folder and will be available in the generated `example_images_icons.h` file.
|
||||
|
||||
The example code is located in `example_images_main.c` and contains the following line:
|
||||
```
|
||||
#include "example_images_icons.h"
|
||||
```
|
||||
|
||||
Image `dolphin_71x25.png` is available as `I_dolphin_71x25`.
|
||||
@@ -4,20 +4,25 @@ App(
|
||||
apptype=FlipperAppType.METAPACKAGE,
|
||||
provides=[
|
||||
"clock_loader",
|
||||
"gpio",
|
||||
# "gpio",
|
||||
"gpio_loader",
|
||||
# "ibutton",
|
||||
"ibutton_loader",
|
||||
"infrared",
|
||||
# "infrared",
|
||||
"infrared_loader",
|
||||
"lfrfid",
|
||||
# "lfrfid_loader",
|
||||
"nfc",
|
||||
"subghz",
|
||||
"bad_usb",
|
||||
#"bad_usb",
|
||||
"bad_usb_loader",
|
||||
# "u2f",
|
||||
"u2f_loader",
|
||||
"fap_loader",
|
||||
"archive",
|
||||
# "Clock",
|
||||
"SubGHz_Remote",
|
||||
#"SubGHz_Remote",
|
||||
"SubGHz_Remote_loader",
|
||||
# "Spectrum_Analyzer",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ App(
|
||||
entry_point="archive_app",
|
||||
cdefines=["APP_ARCHIVE"],
|
||||
requires=["gui"],
|
||||
stack_size=4 * 1024,
|
||||
stack_size=6 * 1024,
|
||||
icon="A_FileManager_14",
|
||||
order=0,
|
||||
)
|
||||
|
||||
@@ -64,7 +64,13 @@ static void
|
||||
archive_add_file_item(browser, is_folder, furi_string_get_cstr(item_path));
|
||||
} else {
|
||||
with_view_model(
|
||||
browser->view, ArchiveBrowserViewModel * model, { model->list_loading = false; }, true);
|
||||
browser->view,
|
||||
ArchiveBrowserViewModel * model,
|
||||
{
|
||||
files_array_sort(model->files);
|
||||
model->list_loading = false;
|
||||
},
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder
|
||||
if(is_folder) {
|
||||
file->type = ArchiveFileTypeFolder;
|
||||
} else {
|
||||
char tmp_extension[MAX_EXT_LEN];
|
||||
path_extract_extension(file->path, tmp_extension, MAX_EXT_LEN);
|
||||
if((strcmp(tmp_extension, ".txt") == 0) || (strcmp(tmp_extension, ".md") == 0)) {
|
||||
file->is_text_file = true;
|
||||
}
|
||||
file->type = ArchiveFileTypeUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <m-array.h>
|
||||
#include <furi.h>
|
||||
#include <m-algo.h>
|
||||
#include <m-string.h>
|
||||
#include <storage/storage.h>
|
||||
#include "toolbox/path.h"
|
||||
|
||||
@@ -29,6 +31,7 @@ typedef struct {
|
||||
FuriString* custom_name;
|
||||
bool fav;
|
||||
bool is_app;
|
||||
bool is_text_file;
|
||||
} ArchiveFile_t;
|
||||
|
||||
static void ArchiveFile_t_init(ArchiveFile_t* obj) {
|
||||
@@ -38,6 +41,7 @@ static void ArchiveFile_t_init(ArchiveFile_t* obj) {
|
||||
obj->custom_name = furi_string_alloc();
|
||||
obj->fav = false;
|
||||
obj->is_app = false;
|
||||
obj->is_text_file = false;
|
||||
}
|
||||
|
||||
static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
|
||||
@@ -52,6 +56,7 @@ static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src)
|
||||
obj->custom_name = furi_string_alloc_set(src->custom_name);
|
||||
obj->fav = src->fav;
|
||||
obj->is_app = src->is_app;
|
||||
obj->is_text_file = src->is_text_file;
|
||||
}
|
||||
|
||||
static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
|
||||
@@ -66,6 +71,7 @@ static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
|
||||
furi_string_set(obj->custom_name, src->custom_name);
|
||||
obj->fav = src->fav;
|
||||
obj->is_app = src->is_app;
|
||||
obj->is_text_file = src->is_text_file;
|
||||
}
|
||||
|
||||
static void ArchiveFile_t_clear(ArchiveFile_t* obj) {
|
||||
@@ -77,13 +83,26 @@ static void ArchiveFile_t_clear(ArchiveFile_t* obj) {
|
||||
furi_string_free(obj->custom_name);
|
||||
}
|
||||
|
||||
ARRAY_DEF(
|
||||
files_array,
|
||||
ArchiveFile_t,
|
||||
(INIT(API_2(ArchiveFile_t_init)),
|
||||
SET(API_6(ArchiveFile_t_set)),
|
||||
INIT_SET(API_6(ArchiveFile_t_init_set)),
|
||||
CLEAR(API_2(ArchiveFile_t_clear))))
|
||||
static int ArchiveFile_t_cmp(const ArchiveFile_t* a, const ArchiveFile_t* b) {
|
||||
if(a->type == ArchiveFileTypeFolder && b->type != ArchiveFileTypeFolder) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return furi_string_cmp(a->path, b->path);
|
||||
}
|
||||
|
||||
#define M_OPL_ArchiveFile_t() \
|
||||
(INIT(API_2(ArchiveFile_t_init)), \
|
||||
SET(API_6(ArchiveFile_t_set)), \
|
||||
INIT_SET(API_6(ArchiveFile_t_init_set)), \
|
||||
CLEAR(API_2(ArchiveFile_t_clear)), \
|
||||
CMP(API_6(ArchiveFile_t_cmp)), \
|
||||
SWAP(M_SWAP_DEFAULT), \
|
||||
EQUAL(API_6(M_EQUAL_DEFAULT)))
|
||||
|
||||
ARRAY_DEF(files_array, ArchiveFile_t)
|
||||
|
||||
ALGO_DEF(files_array, ARRAY_OPLIST(files_array, M_OPL_ArchiveFile_t()))
|
||||
|
||||
void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder, bool is_app);
|
||||
bool archive_get_items(void* context, const char* path);
|
||||
|
||||
@@ -45,10 +45,55 @@ static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selec
|
||||
if(param != NULL) {
|
||||
param++;
|
||||
}
|
||||
status = loader_start(loader, flipper_app_name[selected->type], param);
|
||||
|
||||
if(strcmp(flipper_app_name[selected->type], "U2F") == 0) {
|
||||
char* tmpType = "/ext/apps/Main/U2F.fap¯";
|
||||
char* result =
|
||||
malloc(strlen(tmpType) + strlen(furi_string_get_cstr(selected->path)) + 1);
|
||||
|
||||
strcpy(result, tmpType);
|
||||
strcat(result, furi_string_get_cstr(selected->path));
|
||||
status = loader_start(loader, "Applications", result);
|
||||
} else {
|
||||
status = loader_start(loader, flipper_app_name[selected->type], param);
|
||||
}
|
||||
} else {
|
||||
status = loader_start(
|
||||
loader, flipper_app_name[selected->type], furi_string_get_cstr(selected->path));
|
||||
if(strcmp(flipper_app_name[selected->type], "iButton") == 0) {
|
||||
char* tmpType = "/ext/apps/Main/ibutton.fap¯";
|
||||
char* result =
|
||||
malloc(strlen(tmpType) + strlen(furi_string_get_cstr(selected->path)) + 1);
|
||||
|
||||
strcpy(result, tmpType);
|
||||
strcat(result, furi_string_get_cstr(selected->path));
|
||||
status = loader_start(loader, "Applications", result);
|
||||
} else if(strcmp(flipper_app_name[selected->type], "Bad USB") == 0) {
|
||||
char* tmpType = "/ext/apps/Main/bad_usb.fap¯";
|
||||
char* result =
|
||||
malloc(strlen(tmpType) + strlen(furi_string_get_cstr(selected->path)) + 1);
|
||||
|
||||
strcpy(result, tmpType);
|
||||
strcat(result, furi_string_get_cstr(selected->path));
|
||||
status = loader_start(loader, "Applications", result);
|
||||
// } else if(strcmp(flipper_app_name[selected->type], "125 kHz RFID") == 0) {
|
||||
// char* tmpType = "/ext/apps/Main/lfrfid.fap¯";
|
||||
// char* result =
|
||||
// malloc(strlen(tmpType) + strlen(furi_string_get_cstr(selected->path)) + 1);
|
||||
|
||||
// strcpy(result, tmpType);
|
||||
// strcat(result, furi_string_get_cstr(selected->path));
|
||||
// status = loader_start(loader, "Applications", result);
|
||||
} else if(strcmp(flipper_app_name[selected->type], "Infrared") == 0) {
|
||||
char* tmpType = "/ext/apps/Main/infrared.fap¯";
|
||||
char* result =
|
||||
malloc(strlen(tmpType) + strlen(furi_string_get_cstr(selected->path)) + 1);
|
||||
|
||||
strcpy(result, tmpType);
|
||||
strcat(result, furi_string_get_cstr(selected->path));
|
||||
status = loader_start(loader, "Applications", result);
|
||||
} else {
|
||||
status = loader_start(
|
||||
loader, flipper_app_name[selected->type], furi_string_get_cstr(selected->path));
|
||||
}
|
||||
}
|
||||
|
||||
if(status != LoaderStatusOk) {
|
||||
@@ -150,6 +195,13 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneInfo);
|
||||
consumed = true;
|
||||
break;
|
||||
case ArchiveBrowserEventFileMenuShow:
|
||||
archive_show_file_menu(browser, false);
|
||||
scene_manager_set_scene_state(
|
||||
archive->scene_manager, ArchiveAppSceneBrowser, SCENE_STATE_DEFAULT);
|
||||
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneShow);
|
||||
consumed = true;
|
||||
break;
|
||||
case ArchiveBrowserEventFileMenuDelete:
|
||||
if(archive_get_tab(browser) != ArchiveTabFavorites) {
|
||||
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneDelete);
|
||||
|
||||
@@ -2,3 +2,4 @@ ADD_SCENE(archive, browser, Browser)
|
||||
ADD_SCENE(archive, rename, Rename)
|
||||
ADD_SCENE(archive, delete, Delete)
|
||||
ADD_SCENE(archive, info, Info)
|
||||
ADD_SCENE(archive, show, Show)
|
||||
|
||||
@@ -48,11 +48,16 @@ bool archive_scene_delete_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeRight) {
|
||||
// Show loading popup on delete
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ArchiveViewStack);
|
||||
archive_show_loading_popup(app, true);
|
||||
|
||||
if(selected->is_app) {
|
||||
archive_app_delete_file(browser, name);
|
||||
} else {
|
||||
archive_delete_file(browser, "%s", name);
|
||||
}
|
||||
archive_show_loading_popup(app, false);
|
||||
archive_show_file_menu(browser, false);
|
||||
return scene_manager_previous_scene(app->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeLeft) {
|
||||
|
||||
@@ -64,6 +64,7 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) {
|
||||
ArchiveFile_t* file = archive_get_current_file(archive->browser);
|
||||
|
||||
FuriString* path_dst;
|
||||
|
||||
path_dst = furi_string_alloc();
|
||||
|
||||
if(file->type == ArchiveFileTypeFolder) {
|
||||
|
||||
147
applications/main/archive/scenes/archive_scene_show.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include "../archive_i.h"
|
||||
#include "../helpers/archive_browser.h"
|
||||
#include <storage/storage.h>
|
||||
|
||||
#define TAG "Archive"
|
||||
|
||||
#define SHOW_MAX_FILE_SIZE 5000
|
||||
|
||||
void archive_scene_show_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
ArchiveApp* app = (ArchiveApp*)context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
static bool text_show_read_lines(File* file, FuriString* str_result) {
|
||||
//furi_string_reset(str_result);
|
||||
uint8_t buffer[SHOW_MAX_FILE_SIZE];
|
||||
|
||||
uint16_t read_count = storage_file_read(file, buffer, SHOW_MAX_FILE_SIZE);
|
||||
if(storage_file_get_error(file) != FSE_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(uint16_t i = 0; i < read_count; i++) {
|
||||
furi_string_push_back(str_result, buffer[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void archive_scene_show_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
ArchiveApp* instance = context;
|
||||
|
||||
FuriString* filename;
|
||||
filename = furi_string_alloc();
|
||||
|
||||
FuriString* buffer;
|
||||
buffer = furi_string_alloc();
|
||||
|
||||
ArchiveFile_t* current = archive_get_current_file(instance->browser);
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(fs_api);
|
||||
|
||||
FileInfo fileinfo;
|
||||
FS_Error error = storage_common_stat(fs_api, furi_string_get_cstr(current->path), &fileinfo);
|
||||
if(error == FSE_OK) {
|
||||
if((fileinfo.size < SHOW_MAX_FILE_SIZE) && (fileinfo.size > 2)) {
|
||||
bool ok = storage_file_open(
|
||||
file, furi_string_get_cstr(current->path), FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
if(ok) {
|
||||
if(!text_show_read_lines(file, buffer)) {
|
||||
goto text_file_read_err;
|
||||
}
|
||||
if(!furi_string_size(buffer)) {
|
||||
goto text_file_read_err;
|
||||
}
|
||||
|
||||
storage_file_seek(file, 0, true);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(buffer));
|
||||
|
||||
} else {
|
||||
text_file_read_err:
|
||||
widget_add_text_box_element(
|
||||
instance->widget,
|
||||
0,
|
||||
0,
|
||||
128,
|
||||
64,
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
"\e#Error:\nStorage file open error\e#",
|
||||
false);
|
||||
}
|
||||
storage_file_close(file);
|
||||
} else if(fileinfo.size < 2) {
|
||||
widget_add_text_box_element(
|
||||
instance->widget,
|
||||
0,
|
||||
0,
|
||||
128,
|
||||
64,
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
"\e#Error:\nFile is too small\e#",
|
||||
false);
|
||||
} else {
|
||||
widget_add_text_box_element(
|
||||
instance->widget,
|
||||
0,
|
||||
0,
|
||||
128,
|
||||
64,
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
"\e#Error:\nFile is too large to show\e#",
|
||||
false);
|
||||
}
|
||||
} else {
|
||||
widget_add_text_box_element(
|
||||
instance->widget,
|
||||
0,
|
||||
0,
|
||||
128,
|
||||
64,
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
"\e#Error:\nFile system error\e#",
|
||||
false);
|
||||
}
|
||||
path_extract_filename(current->path, filename, false);
|
||||
|
||||
// This one to return and cursor select this file
|
||||
path_extract_filename_no_ext(furi_string_get_cstr(current->path), filename);
|
||||
strlcpy(instance->text_store, furi_string_get_cstr(filename), MAX_NAME_LEN);
|
||||
|
||||
furi_string_free(buffer);
|
||||
|
||||
storage_file_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
furi_string_free(filename);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, ArchiveViewWidget);
|
||||
}
|
||||
|
||||
bool archive_scene_show_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_assert(context);
|
||||
ArchiveApp* app = (ArchiveApp*)context;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_next_scene(app->scene_manager, ArchiveAppSceneBrowser);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void archive_scene_show_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
ArchiveApp* app = (ArchiveApp*)context;
|
||||
|
||||
widget_reset(app->widget);
|
||||
}
|
||||
@@ -51,6 +51,7 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
FuriString* item_run = furi_string_alloc_set("Run In App");
|
||||
FuriString* item_pin = furi_string_alloc_set("Pin");
|
||||
FuriString* item_info = furi_string_alloc_set("Info");
|
||||
FuriString* item_show = furi_string_alloc_set("Show");
|
||||
FuriString* item_rename = furi_string_alloc_set("Rename");
|
||||
FuriString* item_delete = furi_string_alloc_set("Delete");
|
||||
|
||||
@@ -79,6 +80,12 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_info,
|
||||
ArchiveBrowserEventFileMenuInfo);
|
||||
if(selected->is_text_file) {
|
||||
archive_menu_add_item(
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_show,
|
||||
ArchiveBrowserEventFileMenuShow);
|
||||
}
|
||||
archive_menu_add_item(
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_rename,
|
||||
@@ -100,6 +107,12 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_pin,
|
||||
ArchiveBrowserEventFileMenuPin);
|
||||
if(selected->type <= ArchiveFileTypeBadUsb) {
|
||||
archive_menu_add_item(
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_show,
|
||||
ArchiveBrowserEventFileMenuShow);
|
||||
}
|
||||
archive_menu_add_item(
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_rename,
|
||||
@@ -114,6 +127,12 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_info,
|
||||
ArchiveBrowserEventFileMenuInfo);
|
||||
if(selected->type <= ArchiveFileTypeBadUsb) {
|
||||
archive_menu_add_item(
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_show,
|
||||
ArchiveBrowserEventFileMenuShow);
|
||||
}
|
||||
archive_menu_add_item(
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_pin,
|
||||
@@ -136,6 +155,12 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_info,
|
||||
ArchiveBrowserEventFileMenuInfo);
|
||||
if(selected->type <= ArchiveFileTypeBadUsb) {
|
||||
archive_menu_add_item(
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_show,
|
||||
ArchiveBrowserEventFileMenuShow);
|
||||
}
|
||||
archive_menu_add_item(
|
||||
menu_array_push_raw(model->context_menu),
|
||||
item_rename,
|
||||
@@ -149,6 +174,7 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
furi_string_free(item_run);
|
||||
furi_string_free(item_pin);
|
||||
furi_string_free(item_info);
|
||||
furi_string_free(item_show);
|
||||
furi_string_free(item_rename);
|
||||
furi_string_free(item_delete);
|
||||
} /*else {
|
||||
@@ -160,9 +186,9 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
uint8_t calc_height = menu_height - ((MENU_ITEMS - size_menu) * line_height);
|
||||
canvas_draw_box(canvas, 71, 11, 57, calc_height + 4);
|
||||
canvas_draw_box(canvas, 71, 1, 57, calc_height + 4);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
elements_slightly_rounded_frame(canvas, 70, 12, 58, calc_height + 4);
|
||||
elements_slightly_rounded_frame(canvas, 70, 2, 58, calc_height + 4);
|
||||
|
||||
/*FURI_LOG_D(
|
||||
TAG,
|
||||
@@ -172,10 +198,10 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
model->menu_idx);*/
|
||||
for(size_t i = 0; i < size_menu; i++) {
|
||||
ArchiveContextMenuItem_t* current = menu_array_get(model->context_menu, i);
|
||||
canvas_draw_str(canvas, 82, 21 + i * line_height, furi_string_get_cstr(current->text));
|
||||
canvas_draw_str(canvas, 82, 11 + i * line_height, furi_string_get_cstr(current->text));
|
||||
}
|
||||
|
||||
canvas_draw_icon(canvas, 74, 14 + model->menu_idx * line_height, &I_ButtonRight_4x7);
|
||||
canvas_draw_icon(canvas, 74, 4 + model->menu_idx * line_height, &I_ButtonRight_4x7);
|
||||
}
|
||||
|
||||
static void archive_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar, bool moving) {
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef enum {
|
||||
ArchiveBrowserEventFileMenuRename,
|
||||
ArchiveBrowserEventFileMenuDelete,
|
||||
ArchiveBrowserEventFileMenuInfo,
|
||||
ArchiveBrowserEventFileMenuShow,
|
||||
ArchiveBrowserEventFileMenuClose,
|
||||
|
||||
ArchiveBrowserEventEnterDir,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
App(
|
||||
appid="bad_usb",
|
||||
name="Bad USB",
|
||||
apptype=FlipperAppType.APP,
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="bad_usb_app",
|
||||
cdefines=["APP_BAD_USB"],
|
||||
requires=[
|
||||
@@ -9,6 +9,10 @@ App(
|
||||
"dialogs",
|
||||
],
|
||||
stack_size=2 * 1024,
|
||||
icon="A_BadUsb_14",
|
||||
# icon="A_BadUsb_14",
|
||||
order=70,
|
||||
fap_category="Main",
|
||||
fap_icon="badusb_10px.png",
|
||||
fap_icon_assets="images",
|
||||
fap_libs=["assets"],
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "bad_usb_script.h"
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <bad_usb_icons.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
|
||||
@@ -86,7 +86,7 @@ static const DuckyKey ducky_keys[] = {
|
||||
{"PAGEUP", HID_KEYBOARD_PAGE_UP},
|
||||
{"PAGEDOWN", HID_KEYBOARD_PAGE_DOWN},
|
||||
{"PRINTSCREEN", HID_KEYBOARD_PRINT_SCREEN},
|
||||
{"SCROLLOCK", HID_KEYBOARD_SCROLL_LOCK},
|
||||
{"SCROLLLOCK", HID_KEYBOARD_SCROLL_LOCK},
|
||||
{"SPACE", HID_KEYBOARD_SPACEBAR},
|
||||
{"TAB", HID_KEYBOARD_TAB},
|
||||
{"MENU", HID_KEYBOARD_APPLICATION},
|
||||
@@ -243,12 +243,8 @@ static int32_t
|
||||
const char* line_tmp = furi_string_get_cstr(line);
|
||||
bool state = false;
|
||||
|
||||
for(uint32_t i = 0; i < line_len; i++) {
|
||||
if((line_tmp[i] != ' ') && (line_tmp[i] != '\t') && (line_tmp[i] != '\n')) {
|
||||
line_tmp = &line_tmp[i];
|
||||
break; // Skip spaces and tabs
|
||||
}
|
||||
if(i == line_len - 1) return SCRIPT_STATE_NEXT_LINE; // Skip empty lines
|
||||
if(line_len == 0) {
|
||||
return SCRIPT_STATE_NEXT_LINE; // Skip empty lines
|
||||
}
|
||||
|
||||
FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp);
|
||||
@@ -347,10 +343,6 @@ static int32_t
|
||||
furi_hal_hid_kb_release(key);
|
||||
return (0);
|
||||
}
|
||||
if(error != NULL) {
|
||||
strncpy(error, "Unknown error", error_len);
|
||||
}
|
||||
return SCRIPT_STATE_ERROR;
|
||||
}
|
||||
|
||||
static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) {
|
||||
@@ -463,19 +455,20 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
|
||||
bad_usb->st.line_cur++;
|
||||
bad_usb->buf_len = bad_usb->buf_len + bad_usb->buf_start - (i + 1);
|
||||
bad_usb->buf_start = i + 1;
|
||||
furi_string_trim(bad_usb->line);
|
||||
delay_val = ducky_parse_line(
|
||||
bad_usb, bad_usb->line, bad_usb->st.error, sizeof(bad_usb->st.error));
|
||||
|
||||
if(delay_val < 0) {
|
||||
if(delay_val == SCRIPT_STATE_NEXT_LINE) { // Empty line
|
||||
return 0;
|
||||
} else if(delay_val < 0) {
|
||||
bad_usb->st.error_line = bad_usb->st.line_cur;
|
||||
if(delay_val == SCRIPT_STATE_NEXT_LINE) {
|
||||
snprintf(
|
||||
bad_usb->st.error, sizeof(bad_usb->st.error), "Forbidden empty line");
|
||||
FURI_LOG_E(
|
||||
WORKER_TAG, "Forbidden empty line at line %lu", bad_usb->st.line_cur);
|
||||
WORKER_TAG, "Forbidden empty line at line %u", bad_usb->st.line_cur);
|
||||
} else {
|
||||
FURI_LOG_E(
|
||||
WORKER_TAG, "Unknown command at line %lu", bad_usb->st.line_cur);
|
||||
FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur);
|
||||
}
|
||||
return SCRIPT_STATE_ERROR;
|
||||
} else {
|
||||
@@ -541,12 +534,16 @@ static int32_t bad_usb_worker(void* context) {
|
||||
|
||||
} else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtConnect, FuriFlagWaitAny, FuriWaitForever);
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
|
||||
FuriFlagWaitAny,
|
||||
FuriWaitForever);
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtConnect) {
|
||||
worker_state = BadUsbStateIdle; // Ready to run
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
worker_state = BadUsbStateWillRun; // Will run when USB is connected
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
|
||||
@@ -573,6 +570,31 @@ static int32_t bad_usb_worker(void* context) {
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadUsbStateWillRun) { // State: start on connection
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
|
||||
FuriFlagWaitAny,
|
||||
FuriWaitForever);
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtConnect) { // Start executing script
|
||||
DOLPHIN_DEED(DolphinDeedBadUsbPlayScript);
|
||||
delay_val = 0;
|
||||
bad_usb->buf_len = 0;
|
||||
bad_usb->st.line_cur = 0;
|
||||
bad_usb->defdelay = 0;
|
||||
bad_usb->repeat_cnt = 0;
|
||||
bad_usb->file_end = false;
|
||||
storage_file_seek(script_file, 0, true);
|
||||
// extra time for PC to recognize Flipper as keyboard
|
||||
furi_thread_flags_wait(0, FuriFlagWaitAny, 1500);
|
||||
worker_state = BadUsbStateRunning;
|
||||
} else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
|
||||
worker_state = BadUsbStateNotConnected;
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadUsbStateRunning) { // State: running
|
||||
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
@@ -650,7 +672,7 @@ static void bad_usb_script_set_default_keyboard_layout(BadUsbScript* bad_usb) {
|
||||
BadUsbScript* bad_usb_script_open(FuriString* file_path) {
|
||||
furi_assert(file_path);
|
||||
|
||||
BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript));
|
||||
BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); //-V773
|
||||
bad_usb->file_path = furi_string_alloc();
|
||||
furi_string_set(bad_usb->file_path, file_path);
|
||||
bad_usb_script_set_default_keyboard_layout(bad_usb);
|
||||
@@ -658,12 +680,7 @@ BadUsbScript* bad_usb_script_open(FuriString* file_path) {
|
||||
bad_usb->st.state = BadUsbStateInit;
|
||||
bad_usb->st.error[0] = '\0';
|
||||
|
||||
bad_usb->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(bad_usb->thread, "BadUsbWorker");
|
||||
furi_thread_set_stack_size(bad_usb->thread, 2048);
|
||||
furi_thread_set_context(bad_usb->thread, bad_usb);
|
||||
furi_thread_set_callback(bad_usb->thread, bad_usb_worker);
|
||||
|
||||
bad_usb->thread = furi_thread_alloc_ex("BadUsbWorker", 2048, bad_usb_worker, bad_usb);
|
||||
furi_thread_start(bad_usb->thread);
|
||||
return bad_usb;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ typedef enum {
|
||||
BadUsbStateInit,
|
||||
BadUsbStateNotConnected,
|
||||
BadUsbStateIdle,
|
||||
BadUsbStateWillRun,
|
||||
BadUsbStateRunning,
|
||||
BadUsbStateDelay,
|
||||
BadUsbStateDone,
|
||||
|
||||
BIN
applications/main/bad_usb/badusb_10px.png
Normal file
|
After Width: | Height: | Size: 576 B |
BIN
applications/main/bad_usb/images/ActiveConnection_50x64.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
applications/main/bad_usb/images/Clock_18x18.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
applications/main/bad_usb/images/Error_18x18.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
applications/main/bad_usb/images/EviSmile1_18x21.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
applications/main/bad_usb/images/EviSmile2_18x21.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
applications/main/bad_usb/images/EviWaiting1_18x21.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
applications/main/bad_usb/images/EviWaiting2_18x21.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
applications/main/bad_usb/images/Percent_10x14.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
applications/main/bad_usb/images/SDQuestion_35x43.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
applications/main/bad_usb/images/Smile_18x18.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
applications/main/bad_usb/images/UsbTree_48x22.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
applications/main/bad_usb/images/badusb_10px.png
Normal file
|
After Width: | Height: | Size: 576 B |
BIN
applications/main/bad_usb/images/keyboard_10px.png
Normal file
|
After Width: | Height: | Size: 147 B |
@@ -2,6 +2,7 @@
|
||||
#include "../bad_usb_script.h"
|
||||
#include <toolbox/path.h>
|
||||
#include <gui/elements.h>
|
||||
#include <bad_usb_icons.h>
|
||||
|
||||
#define MAX_NAME_LEN 64
|
||||
|
||||
@@ -44,10 +45,13 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
||||
|
||||
canvas_draw_icon(canvas, 22, 24, &I_UsbTree_48x22);
|
||||
|
||||
if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone)) {
|
||||
if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone) ||
|
||||
(model->state.state == BadUsbStateNotConnected)) {
|
||||
elements_button_center(canvas, "Run");
|
||||
} else if((model->state.state == BadUsbStateRunning) || (model->state.state == BadUsbStateDelay)) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
} else if(model->state.state == BadUsbStateWillRun) {
|
||||
elements_button_center(canvas, "Cancel");
|
||||
}
|
||||
|
||||
if((model->state.state == BadUsbStateNotConnected) ||
|
||||
@@ -60,6 +64,11 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to USB");
|
||||
} else if(model->state.state == BadUsbStateWillRun) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect");
|
||||
} else if(model->state.state == BadUsbStateFileError) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Error_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
14
applications/main/bad_usb_loader/application.fam
Normal file
@@ -0,0 +1,14 @@
|
||||
App(
|
||||
appid="bad_usb_loader",
|
||||
name="Bad USB",
|
||||
apptype=FlipperAppType.APP,
|
||||
entry_point="bad_usb_loader_app",
|
||||
requires=[
|
||||
"gui",
|
||||
"dialogs",
|
||||
],
|
||||
stack_size=int(2 * 1024),
|
||||
icon="A_BadUsb_14",
|
||||
order=70,
|
||||
link="/ext/apps/Main/bad_usb.fap",
|
||||
)
|
||||
9
applications/main/bad_usb_loader/bad_usb_loader_app.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <applications/services/loader/loader_i.h>
|
||||
|
||||
#define TAG "bad_usb_loader_app"
|
||||
|
||||
int32_t bad_usb_loader_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
14
applications/main/clock/application.fam
Normal file
@@ -0,0 +1,14 @@
|
||||
App(
|
||||
appid="Clock",
|
||||
name="Clock",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="clock_app",
|
||||
cdefines=["APP_CLOCK"],
|
||||
requires=["gui"],
|
||||
# icon="A_Clock_14",
|
||||
stack_size=2 * 1024,
|
||||
order=9,
|
||||
fap_icon="ClockIcon.png",
|
||||
fap_category="Main",
|
||||
fap_icon_assets="icons",
|
||||
)
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include "applications/settings/desktop_settings/desktop_settings_app.h"
|
||||
#include "Clock_icons.h"
|
||||
|
||||
#define TAG "Clock"
|
||||
|
||||
@@ -200,6 +201,43 @@ const NotificationSequence clock_alert_startStop = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
const NotificationMessage message_red_127 = {
|
||||
.type = NotificationMessageTypeLedRed,
|
||||
.data.led.value = 0x7F,
|
||||
};
|
||||
|
||||
const NotificationMessage message_green_127 = {
|
||||
.type = NotificationMessageTypeLedGreen,
|
||||
.data.led.value = 0x7F,
|
||||
};
|
||||
|
||||
const NotificationMessage message_blue_127 = {
|
||||
.type = NotificationMessageTypeLedBlue,
|
||||
.data.led.value = 0x7F,
|
||||
};
|
||||
|
||||
const NotificationSequence sequence_rainbow = {
|
||||
&message_red_255, &message_green_0, &message_blue_0,
|
||||
&message_delay_250, &message_red_255, &message_green_127,
|
||||
&message_blue_0, &message_delay_250, &message_red_255,
|
||||
&message_green_255, &message_blue_0, &message_delay_250,
|
||||
&message_red_127, &message_green_255, &message_blue_0,
|
||||
&message_delay_250, &message_red_0, &message_green_255,
|
||||
&message_blue_0, &message_delay_250, &message_red_0,
|
||||
&message_green_255, &message_blue_127, &message_delay_250,
|
||||
&message_red_0, &message_green_255, &message_blue_255,
|
||||
&message_delay_250, &message_red_0, &message_green_127,
|
||||
&message_blue_255, &message_delay_250, &message_red_0,
|
||||
&message_green_0, &message_blue_255, &message_delay_250,
|
||||
&message_red_127, &message_green_0, &message_blue_255,
|
||||
&message_delay_250, &message_red_255, &message_green_0,
|
||||
&message_blue_255, &message_delay_250, &message_red_255,
|
||||
&message_green_0, &message_blue_127, &message_delay_250,
|
||||
&message_red_127, &message_green_127, &message_blue_127,
|
||||
&message_delay_250, &message_red_255, &message_green_255,
|
||||
&message_blue_255, &message_delay_250, NULL,
|
||||
};
|
||||
|
||||
static void desktop_view_main_dumbmode_changed(DesktopSettings* settings) {
|
||||
settings->is_dumbmode = !settings->is_dumbmode;
|
||||
DESKTOP_SETTINGS_SAVE(settings);
|
||||
@@ -260,8 +298,20 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
|
||||
int32_t elapsed_secs = timer_running ? (curr_ts - timer_start_timestamp) :
|
||||
timer_stopped_seconds;
|
||||
snprintf(strings[2], 20, "%.2ld:%.2ld", elapsed_secs / 60, elapsed_secs % 60);
|
||||
int32_t elapsed_secs_img = (elapsed_secs % 60) % 5;
|
||||
int32_t elapsed_secs_img2 = (elapsed_secs % 60) % 4;
|
||||
// int32_t elapsed_secs_img3 = (elapsed_secs % 60) % 4;
|
||||
static const Icon* const count_anim[5] = {
|
||||
&I_HappyFlipper_128x64, &I_G0ku, &I_g0ku_1, &I_g0ku_2, &I_g0ku_3};
|
||||
static const Icon* const count_anim2[4] = {
|
||||
&I_EviWaiting1_18x21, &I_EviWaiting2_18x21, &I_EviSmile1_18x21, &I_EviSmile2_18x21};
|
||||
static const Icon* const count_anim3[4] = {
|
||||
&I_frame_01, &I_frame_02, &I_frame_03, &I_frame_02};
|
||||
canvas_draw_icon(canvas, -5, 15, count_anim[elapsed_secs_img]);
|
||||
canvas_draw_icon(canvas, 90, 0, count_anim2[elapsed_secs_img2]);
|
||||
canvas_draw_icon(canvas, 110, 5, count_anim3[elapsed_secs_img2]);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 40, AlignCenter, AlignTop, strings[2]); // DRAW TIMER
|
||||
canvas, 64, 32, AlignCenter, AlignTop, strings[2]); // DRAW TIMER
|
||||
}
|
||||
canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignCenter, strings[1]); // DRAW TIME
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
@@ -294,7 +344,9 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
|
||||
elements_button_right(canvas, "S:ByMin");
|
||||
}
|
||||
}
|
||||
if(state->w_test) canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8);
|
||||
if(state->w_test && state->desktop_settings->is_dumbmode) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8);
|
||||
}
|
||||
}
|
||||
|
||||
static void clock_state_init(ClockState* const state) {
|
||||
@@ -393,6 +445,7 @@ int32_t clock_app(void* p) {
|
||||
plugin_state->codeSequence++;
|
||||
if(plugin_state->codeSequence == 8) {
|
||||
desktop_view_main_dumbmode_changed(plugin_state->desktop_settings);
|
||||
plugin_state->w_test = true; // OH HEY NOW LETS GAIN EXP & MORE FUN
|
||||
}
|
||||
} else {
|
||||
plugin_state->codeSequence = 0;
|
||||
@@ -472,6 +525,8 @@ int32_t clock_app(void* p) {
|
||||
if(plugin_state->codeSequence < (uint32_t)-1) processing = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(plugin_state->codeSequence == 10) {
|
||||
plugin_state->codeSequence = 0;
|
||||
@@ -481,9 +536,10 @@ int32_t clock_app(void* p) {
|
||||
if(plugin_state->songSelect == 1 || plugin_state->songSelect == 2 ||
|
||||
plugin_state->songSelect == 3) {
|
||||
notification_message(notification, &sequence_success);
|
||||
notification_message(notification, &sequence_rainbow);
|
||||
notification_message(notification, &sequence_rainbow);
|
||||
}
|
||||
plugin_state->militaryTime = true; // 24 HR TIME FOR THIS
|
||||
plugin_state->w_test = true; // OH HEY NOW LETS GAIN EXP & MORE FUN
|
||||
DOLPHIN_DEED(getRandomDeed());
|
||||
}
|
||||
} else if(event.input.type == InputTypeLong) {
|
||||
@@ -525,6 +581,8 @@ int32_t clock_app(void* p) {
|
||||
}
|
||||
if(plugin_state->timerSecs == plugin_state->alert_time + 2) {
|
||||
notification_message(notification, &clock_alert_pr3);
|
||||
notification_message(notification, &sequence_rainbow);
|
||||
notification_message(notification, &sequence_rainbow);
|
||||
}
|
||||
} else if(plugin_state->songSelect == 2) {
|
||||
if(plugin_state->timerSecs == plugin_state->alert_time) {
|
||||
@@ -543,6 +601,8 @@ int32_t clock_app(void* p) {
|
||||
}
|
||||
if(plugin_state->timerSecs == plugin_state->alert_time + 2) {
|
||||
notification_message(notification, &clock_alert_mario3);
|
||||
notification_message(notification, &sequence_rainbow);
|
||||
notification_message(notification, &sequence_rainbow);
|
||||
}
|
||||
} else {
|
||||
if(plugin_state->timerSecs == plugin_state->alert_time) {
|
||||
BIN
applications/main/clock/icons/EviSmile1_18x21.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
applications/main/clock/icons/EviSmile2_18x21.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
applications/main/clock/icons/EviWaiting1_18x21.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
applications/main/clock/icons/EviWaiting2_18x21.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
applications/main/clock/icons/G0ku.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
applications/main/clock/icons/GameMode_11x8.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
applications/main/clock/icons/HappyFlipper_128x64.png
Normal file
|
After Width: | Height: | Size: 633 B |
BIN
applications/main/clock/icons/frame_01.png
Normal file
|
After Width: | Height: | Size: 113 B |
BIN
applications/main/clock/icons/frame_02.png
Normal file
|
After Width: | Height: | Size: 116 B |
BIN
applications/main/clock/icons/frame_03.png
Normal file
|
After Width: | Height: | Size: 116 B |
BIN
applications/main/clock/icons/g0ku_1.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
applications/main/clock/icons/g0ku_2.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
applications/main/clock/icons/g0ku_3.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
@@ -3,11 +3,12 @@ App(
|
||||
name="Applications",
|
||||
apptype=FlipperAppType.APP,
|
||||
entry_point="fap_loader_app",
|
||||
cdefines=["APP_FAP_LOADER"],
|
||||
requires=[
|
||||
"gui",
|
||||
"storage",
|
||||
],
|
||||
stack_size=int(1.5 * 1024),
|
||||
icon="A_Plugins_14",
|
||||
order=90,
|
||||
order=9,
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <assets_icons.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <storage/storage.h>
|
||||
#include <gui/modules/loading.h>
|
||||
@@ -16,6 +17,7 @@ struct FapLoader {
|
||||
DialogsApp* dialogs;
|
||||
Gui* gui;
|
||||
FuriString* fap_path;
|
||||
FuriString* fap_args;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Loading* loading;
|
||||
};
|
||||
@@ -101,16 +103,28 @@ static bool fap_loader_run_selected_app(FapLoader* loader) {
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start));
|
||||
FURI_LOG_I(TAG, "FAP Loader is staring app");
|
||||
FURI_LOG_I(TAG, "FAP Loader is starting app");
|
||||
|
||||
FuriThread* thread = flipper_application_spawn(loader->app, NULL);
|
||||
furi_thread_start(thread);
|
||||
furi_thread_join(thread);
|
||||
if(strcmp(furi_string_get_cstr(loader->fap_args), "false") == 0) {
|
||||
FuriThread* thread = flipper_application_spawn(loader->app, NULL);
|
||||
furi_thread_start(thread);
|
||||
furi_thread_join(thread);
|
||||
|
||||
show_error = false;
|
||||
int ret = furi_thread_get_return_code(thread);
|
||||
show_error = false;
|
||||
int ret = furi_thread_get_return_code(thread);
|
||||
|
||||
FURI_LOG_I(TAG, "FAP app returned: %i", ret);
|
||||
FURI_LOG_I(TAG, "FAP app returned: %i", ret);
|
||||
} else {
|
||||
FuriThread* thread = flipper_application_spawn(
|
||||
loader->app, (void*)furi_string_get_cstr(loader->fap_args));
|
||||
furi_thread_start(thread);
|
||||
furi_thread_join(thread);
|
||||
|
||||
show_error = false;
|
||||
int ret = furi_thread_get_return_code(thread);
|
||||
|
||||
FURI_LOG_I(TAG, "FAP app returned: %i", ret);
|
||||
}
|
||||
} while(0);
|
||||
|
||||
if(show_error) {
|
||||
@@ -154,8 +168,28 @@ static bool fap_loader_select_app(FapLoader* loader) {
|
||||
}
|
||||
|
||||
static FapLoader* fap_loader_alloc(const char* path) {
|
||||
FapLoader* loader = malloc(sizeof(FapLoader));
|
||||
loader->fap_path = furi_string_alloc_set(path);
|
||||
FapLoader* loader = malloc(sizeof(FapLoader)); //-V773
|
||||
|
||||
char* tmp = malloc(strlen(path) + 1);
|
||||
strcpy(tmp, path);
|
||||
char* new_path;
|
||||
|
||||
new_path = strtok(tmp, "¯");
|
||||
|
||||
if(new_path) {
|
||||
loader->fap_path = furi_string_alloc_set(new_path);
|
||||
} else {
|
||||
loader->fap_path = furi_string_alloc_set(path);
|
||||
}
|
||||
|
||||
new_path = strtok(NULL, "¯");
|
||||
|
||||
if(new_path) {
|
||||
loader->fap_args = furi_string_alloc_set(new_path);
|
||||
} else {
|
||||
loader->fap_args = furi_string_alloc_set("false");
|
||||
}
|
||||
|
||||
loader->storage = furi_record_open(RECORD_STORAGE);
|
||||
loader->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
loader->gui = furi_record_open(RECORD_GUI);
|
||||
@@ -172,6 +206,7 @@ static void fap_loader_free(FapLoader* loader) {
|
||||
loading_free(loader->loading);
|
||||
view_dispatcher_free(loader->view_dispatcher);
|
||||
furi_string_free(loader->fap_path);
|
||||
furi_string_free(loader->fap_args);
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
App(
|
||||
appid="gpio",
|
||||
name="GPIO",
|
||||
apptype=FlipperAppType.APP,
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="gpio_app",
|
||||
cdefines=["APP_GPIO"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
icon="A_GPIO_14",
|
||||
# icon="A_GPIO_14",
|
||||
order=50,
|
||||
# fap_icon="gpioIcon.png",
|
||||
# fap_category="Main",
|
||||
fap_icon="gpioIcon.png",
|
||||
fap_category="Main",
|
||||
fap_icon_assets="images",
|
||||
fap_libs=["assets"],
|
||||
)
|
||||
|
||||
@@ -51,6 +51,16 @@ GpioApp* gpio_app_alloc() {
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, GpioAppViewGpioTest, gpio_test_get_view(app->gpio_test));
|
||||
|
||||
app->gpio_i2c_scanner = gpio_i2c_scanner_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
GpioAppViewI2CScanner,
|
||||
gpio_i2c_scanner_get_view(app->gpio_i2c_scanner));
|
||||
|
||||
app->gpio_i2c_sfp = gpio_i2c_sfp_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, GpioAppViewI2CSfp, gpio_i2c_sfp_get_view(app->gpio_i2c_sfp));
|
||||
|
||||
app->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, GpioAppViewUsbUartCloseRpc, widget_get_view(app->widget));
|
||||
@@ -75,6 +85,8 @@ void gpio_app_free(GpioApp* app) {
|
||||
// Views
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewVarItemList);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewGpioTest);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewI2CScanner);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewI2CSfp);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUart);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUartCfg);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUartCloseRpc);
|
||||
@@ -82,6 +94,8 @@ void gpio_app_free(GpioApp* app) {
|
||||
widget_free(app->widget);
|
||||
gpio_test_free(app->gpio_test);
|
||||
gpio_usb_uart_free(app->gpio_usb_uart);
|
||||
gpio_i2c_scanner_free(app->gpio_i2c_scanner);
|
||||
gpio_i2c_sfp_free(app->gpio_i2c_sfp);
|
||||
|
||||
// View dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include <gui/modules/widget.h>
|
||||
#include "views/gpio_test.h"
|
||||
#include "views/gpio_usb_uart.h"
|
||||
#include "views/gpio_i2c_scanner.h"
|
||||
#include "views/gpio_i2c_sfp.h"
|
||||
#include <gpio_icons.h>
|
||||
|
||||
struct GpioApp {
|
||||
Gui* gui;
|
||||
@@ -24,9 +27,12 @@ struct GpioApp {
|
||||
Widget* widget;
|
||||
|
||||
VariableItemList* var_item_list;
|
||||
VariableItem* var_item_flow;
|
||||
GpioTest* gpio_test;
|
||||
GpioUsbUart* gpio_usb_uart;
|
||||
UsbUartBridge* usb_uart_bridge;
|
||||
GpioI2CScanner* gpio_i2c_scanner;
|
||||
GpioI2CSfp* gpio_i2c_sfp;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -35,4 +41,6 @@ typedef enum {
|
||||
GpioAppViewUsbUart,
|
||||
GpioAppViewUsbUartCfg,
|
||||
GpioAppViewUsbUartCloseRpc,
|
||||
GpioAppViewI2CScanner,
|
||||
GpioAppViewI2CSfp
|
||||
} GpioAppView;
|
||||
|
||||
@@ -5,6 +5,8 @@ typedef enum {
|
||||
GpioStartEventOtgOn,
|
||||
GpioStartEventManualControl,
|
||||
GpioStartEventUsbUart,
|
||||
GpioStartEventI2CScanner,
|
||||
GpioStartEventI2CSfp,
|
||||
|
||||
GpioCustomEventErrorBack,
|
||||
|
||||
|
||||
23
applications/main/gpio/gpio_i2c_scanner_control.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "gpio_i2c_scanner_control.h"
|
||||
#include <furi.h>
|
||||
|
||||
void gpio_i2c_scanner_run_once(I2CScannerState* i2c_scanner_state) {
|
||||
//Reset the number of items for rewriting the array
|
||||
i2c_scanner_state->items = 0;
|
||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
|
||||
|
||||
uint32_t response_timeout_ticks = furi_ms_to_ticks(5.f);
|
||||
|
||||
//Addresses 0 to 7 are reserved and won't be scanned
|
||||
for(int i = FIRST_NON_RESERVED_I2C_ADDRESS; i <= HIGHEST_I2C_ADDRESS; i++) {
|
||||
if(furi_hal_i2c_is_device_ready(
|
||||
&furi_hal_i2c_handle_external,
|
||||
i << 1,
|
||||
response_timeout_ticks)) { //Bitshift of 1 bit to convert 7-Bit Address into 8-Bit Address
|
||||
i2c_scanner_state->responding_address[i2c_scanner_state->items] = i;
|
||||
i2c_scanner_state->items++;
|
||||
}
|
||||
}
|
||||
|
||||
furi_hal_i2c_release(&furi_hal_i2c_handle_external);
|
||||
}
|
||||
21
applications/main/gpio/gpio_i2c_scanner_control.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <furi_hal_i2c.h>
|
||||
|
||||
#define FIRST_NON_RESERVED_I2C_ADDRESS 8
|
||||
#define HIGHEST_I2C_ADDRESS 127
|
||||
#define AVAILABLE_NONRESVERED_I2C_ADDRESSES 120
|
||||
|
||||
typedef struct {
|
||||
uint8_t items;
|
||||
uint8_t responding_address[AVAILABLE_NONRESVERED_I2C_ADDRESSES];
|
||||
} I2CScannerState;
|
||||
|
||||
/** Scans the I2C-Bus (SDA: Pin 15, SCL: Pin 16) for available 7-Bit slave addresses. Saves the number of detected slaves and their addresses.
|
||||
*
|
||||
* @param i2c_scanner_state State including the detected addresses and the number of addresses saved.
|
||||
*/
|
||||
void gpio_i2c_scanner_run_once(I2CScannerState* st);
|
||||
334
applications/main/gpio/gpio_i2c_sfp_control.c
Normal file
@@ -0,0 +1,334 @@
|
||||
#include "gpio_i2c_sfp_control.h"
|
||||
#include <furi_hal.h>
|
||||
#include <string.h>
|
||||
|
||||
// This is map mapping the connector type to the appropriate name. (see SFF-8024 Rev. 4.9, Table 4-3)
|
||||
const char* sfp_connector_map[256] = {
|
||||
"Unknown or unspecified",
|
||||
"SC",
|
||||
"Fibre Channel Style 1",
|
||||
"Fibre Channel Style 2",
|
||||
"BNC/TNC",
|
||||
"Fibre Channel Coax",
|
||||
"Fiber Jack",
|
||||
"LC",
|
||||
"MT-RJ",
|
||||
"MU",
|
||||
"SG",
|
||||
"Optical Pigtail",
|
||||
"MP0 1x12",
|
||||
"MP 2x16",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"HSSDC II",
|
||||
"Copper pigtail",
|
||||
"RJ45",
|
||||
"No seperable connector",
|
||||
"MXC 2x16",
|
||||
"CS optical connector",
|
||||
"SN (prev. Mini CS)",
|
||||
"MPO 2x12",
|
||||
"MPO 1x16",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved"};
|
||||
|
||||
void str_part(uint8_t* data, char* buffer, int start, int len) {
|
||||
int i;
|
||||
for(i = start; i < start + len; i++) {
|
||||
buffer[i - start] = data[i];
|
||||
}
|
||||
buffer[i - start] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
void print_part(uint8_t *data, char *ptype, char *prefix, int start, int len){
|
||||
printf("%s: ", prefix);
|
||||
for (int i=start; i<start+len; i++){
|
||||
printf(ptype, data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
void gpio_i2c_sfp_run_once(I2CSfpState* i2c_sfp_state) {
|
||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
|
||||
// Allocate buffer for SFP Data
|
||||
uint8_t sfp_data[255];
|
||||
uint32_t response_timeout_ticks = furi_ms_to_ticks(5.f);
|
||||
|
||||
// Check for SFP Module on I2C Bus
|
||||
if(furi_hal_i2c_is_device_ready(
|
||||
&furi_hal_i2c_handle_external, SFP_I2C_ADDRESS << 1, response_timeout_ticks)) {
|
||||
for(uint8_t i = 0; i <= 254; i++) {
|
||||
uint8_t data = 0;
|
||||
// Read data from register
|
||||
furi_hal_i2c_read_reg_8(
|
||||
&furi_hal_i2c_handle_external,
|
||||
SFP_I2C_ADDRESS << 1,
|
||||
i,
|
||||
&data,
|
||||
response_timeout_ticks);
|
||||
// Save data
|
||||
sfp_data[i] = data;
|
||||
}
|
||||
|
||||
/*
|
||||
print_part(sfp_data, "%c", "Vendor", 20, 16);
|
||||
print_part(sfp_data, "%02X", "OUI", 37, 3);
|
||||
print_part(sfp_data, "%c", "Rev", 56, 4);
|
||||
print_part(sfp_data, "%c", "PN", 40, 16);
|
||||
print_part(sfp_data, "%c", "SN", 68, 16);
|
||||
print_part(sfp_data, "%c", "DC", 84, 6);
|
||||
|
||||
printf("Typ: 0x%02X\r\n", sfp_data[0]);
|
||||
printf("Connector: 0x%02X\r\n", sfp_data[2]);
|
||||
printf("Bitrate: %u MBd\r\n", sfp_data[12]*100);
|
||||
printf("Wavelength: %u nm\r\n", sfp_data[60] * 256 + sfp_data[61]);
|
||||
printf(" %-6s %-6s %-6s %-6s %-6s\r\n", "SM", "OM1", "OM2", "OM3", "OM4");
|
||||
printf("Max length: %3u km %4u m %4u m %4u m %4u m\r\n", sfp_data[14], sfp_data[17]*10, sfp_data[16]*10, sfp_data[19]*10, sfp_data[18]*10);
|
||||
*/
|
||||
|
||||
str_part(sfp_data, i2c_sfp_state->vendor, 20, 16);
|
||||
str_part(sfp_data, i2c_sfp_state->rev, 56, 4);
|
||||
str_part(sfp_data, i2c_sfp_state->pn, 40, 16);
|
||||
str_part(sfp_data, i2c_sfp_state->sn, 68, 16);
|
||||
str_part(sfp_data, i2c_sfp_state->dc, 84, 6);
|
||||
|
||||
//Look up connector in table and copy to struct.
|
||||
strcpy(i2c_sfp_state->connector, sfp_connector_map[sfp_data[2]]);
|
||||
i2c_sfp_state->bitrate = sfp_data[12] * 100;
|
||||
i2c_sfp_state->wavelength = sfp_data[60] * 256 + sfp_data[61];
|
||||
i2c_sfp_state->sm_reach = sfp_data[14];
|
||||
i2c_sfp_state->mm_reach_om3 = sfp_data[19] * 10;
|
||||
}
|
||||
furi_hal_i2c_release(&furi_hal_i2c_handle_external);
|
||||
}
|
||||
32
applications/main/gpio/gpio_i2c_sfp_control.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <furi_hal_i2c.h>
|
||||
|
||||
#define FIRST_NON_RESERVED_I2C_ADDRESS 8
|
||||
#define HIGHEST_I2C_ADDRESS 127
|
||||
#define AVAILABLE_NONRESVERED_I2C_ADDRESSES 120
|
||||
#define SFP_I2C_ADDRESS 0x50
|
||||
|
||||
typedef struct {
|
||||
char vendor[32];
|
||||
char oui[32];
|
||||
char rev[32];
|
||||
char pn[32];
|
||||
char sn[32];
|
||||
char dc[32];
|
||||
uint8_t type;
|
||||
char connector[32];
|
||||
int wavelength;
|
||||
int sm_reach;
|
||||
int mm_reach_om3;
|
||||
int bitrate;
|
||||
} I2CSfpState;
|
||||
|
||||
/** Reads data from a connected SFP on I2C-Bus (SDA: Pin 15, SCL: Pin 16). Saves data from SFP.
|
||||
*
|
||||
* @param i2c_sfp_state Data collected from SFP.
|
||||
*/
|
||||
void gpio_i2c_sfp_run_once(I2CSfpState* st);
|
||||
BIN
applications/main/gpio/images/ActiveConnection_50x64.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
applications/main/gpio/images/ArrowDownEmpty_14x15.png
Normal file
|
After Width: | Height: | Size: 654 B |
BIN
applications/main/gpio/images/ArrowDownFilled_14x15.png
Normal file
|
After Width: | Height: | Size: 669 B |
BIN
applications/main/gpio/images/ArrowUpEmpty_14x15.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
applications/main/gpio/images/ArrowUpFilled_14x15.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
@@ -3,3 +3,5 @@ ADD_SCENE(gpio, test, Test)
|
||||
ADD_SCENE(gpio, usb_uart, UsbUart)
|
||||
ADD_SCENE(gpio, usb_uart_cfg, UsbUartCfg)
|
||||
ADD_SCENE(gpio, usb_uart_close_rpc, UsbUartCloseRpc)
|
||||
ADD_SCENE(gpio, i2c_scanner, I2CScanner)
|
||||
ADD_SCENE(gpio, i2c_sfp, I2CSfp)
|
||||
|
||||
36
applications/main/gpio/scenes/gpio_scene_i2c_scanner.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "../gpio_app_i.h"
|
||||
#include <furi_hal_gpio.h>
|
||||
|
||||
static I2CScannerState* i2c_scanner_state;
|
||||
|
||||
void gpio_scene_i2c_scanner_ok_callback(InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
GpioApp* app = context;
|
||||
|
||||
if(type == InputTypeRelease) {
|
||||
notification_message(app->notifications, &sequence_set_green_255);
|
||||
gpio_i2c_scanner_run_once(i2c_scanner_state);
|
||||
notification_message(app->notifications, &sequence_reset_green);
|
||||
gpio_i2c_scanner_update_state(app->gpio_i2c_scanner, i2c_scanner_state);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_scene_i2c_scanner_on_enter(void* context) {
|
||||
GpioApp* app = context;
|
||||
i2c_scanner_state = malloc(sizeof(I2CScannerState));
|
||||
|
||||
gpio_i2c_scanner_set_ok_callback(
|
||||
app->gpio_i2c_scanner, gpio_scene_i2c_scanner_ok_callback, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewI2CScanner);
|
||||
}
|
||||
|
||||
bool gpio_scene_i2c_scanner_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void gpio_scene_i2c_scanner_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
free(i2c_scanner_state);
|
||||
}
|
||||
35
applications/main/gpio/scenes/gpio_scene_i2c_sfp.c
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "../gpio_app_i.h"
|
||||
#include <furi_hal_gpio.h>
|
||||
|
||||
static I2CSfpState* i2c_sfp_state;
|
||||
|
||||
void gpio_scene_i2c_sfp_ok_callback(InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
GpioApp* app = context;
|
||||
|
||||
if(type == InputTypeRelease) {
|
||||
notification_message(app->notifications, &sequence_set_green_255);
|
||||
gpio_i2c_sfp_run_once(i2c_sfp_state);
|
||||
notification_message(app->notifications, &sequence_reset_green);
|
||||
gpio_i2c_sfp_update_state(app->gpio_i2c_sfp, i2c_sfp_state);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_scene_i2c_sfp_on_enter(void* context) {
|
||||
GpioApp* app = context;
|
||||
i2c_sfp_state = malloc(sizeof(I2CSfpState));
|
||||
|
||||
gpio_i2c_sfp_set_ok_callback(app->gpio_i2c_sfp, gpio_scene_i2c_sfp_ok_callback, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewI2CSfp);
|
||||
}
|
||||
|
||||
bool gpio_scene_i2c_sfp_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void gpio_scene_i2c_sfp_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
free(i2c_sfp_state);
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
#include "../gpio_app_i.h"
|
||||
#include "furi_hal_power.h"
|
||||
#include "furi_hal_usb.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
enum GpioItem {
|
||||
GpioItemUsbUart,
|
||||
GpioItemTest,
|
||||
GpioItemOtg,
|
||||
GpioItemI2CScanner,
|
||||
GpioItemI2CSfp,
|
||||
};
|
||||
|
||||
enum GpioOtg {
|
||||
@@ -27,6 +28,10 @@ static void gpio_scene_start_var_list_enter_callback(void* context, uint32_t ind
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventManualControl);
|
||||
} else if(index == GpioItemUsbUart) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventUsbUart);
|
||||
} else if(index == GpioItemI2CScanner) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventI2CScanner);
|
||||
} else if(index == GpioItemI2CSfp) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventI2CSfp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +73,9 @@ void gpio_scene_start_on_enter(void* context) {
|
||||
variable_item_set_current_value_text(item, gpio_otg_text[GpioOtgOff]);
|
||||
}
|
||||
|
||||
variable_item_list_add(var_item_list, "I2C-Scanner", 0, NULL, NULL);
|
||||
variable_item_list_add(var_item_list, "I2C-SFP", 0, NULL, NULL);
|
||||
|
||||
variable_item_list_set_selected_item(
|
||||
var_item_list, scene_manager_get_scene_state(app->scene_manager, GpioSceneStart));
|
||||
|
||||
@@ -86,10 +94,15 @@ bool gpio_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
} else if(event.event == GpioStartEventManualControl) {
|
||||
scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemTest);
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneTest);
|
||||
} else if(event.event == GpioStartEventI2CScanner) {
|
||||
scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemI2CScanner);
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneI2CScanner);
|
||||
} else if(event.event == GpioStartEventI2CSfp) {
|
||||
scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemI2CSfp);
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneI2CSfp);
|
||||
} else if(event.event == GpioStartEventUsbUart) {
|
||||
scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemUsbUart);
|
||||
if(!furi_hal_usb_is_locked()) {
|
||||
DOLPHIN_DEED(DolphinDeedGpioUartBridge);
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneUsbUart);
|
||||
} else {
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneUsbUartCloseRpc);
|
||||
|
||||
@@ -13,7 +13,7 @@ static UsbUartConfig* cfg_set;
|
||||
|
||||
static const char* vcp_ch[] = {"0 (CLI)", "1"};
|
||||
static const char* uart_ch[] = {"13,14", "15,16"};
|
||||
static const char* flow_pins[] = {"None", "2,3", "6,7"};
|
||||
static const char* flow_pins[] = {"None", "2,3", "6,7", "16,15"};
|
||||
static const char* baudrate_mode[] = {"Host"};
|
||||
static const uint32_t baudrate_list[] = {
|
||||
2400,
|
||||
@@ -33,6 +33,24 @@ bool gpio_scene_usb_uart_cfg_on_event(void* context, SceneManagerEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void line_ensure_flow_invariant(GpioApp* app) {
|
||||
// GPIO pins PC0, PC1 (16,15) are unavailable for RTS/DTR when LPUART is
|
||||
// selected. This function enforces that invariant by resetting flow_pins
|
||||
// to None if it is configured to 16,15 when LPUART is selected.
|
||||
|
||||
uint8_t available_flow_pins = cfg_set->uart_ch == FuriHalUartIdLPUART1 ? 3 : 4;
|
||||
VariableItem* item = app->var_item_flow;
|
||||
variable_item_set_values_count(item, available_flow_pins);
|
||||
|
||||
if(cfg_set->flow_pins >= available_flow_pins) {
|
||||
cfg_set->flow_pins = 0;
|
||||
usb_uart_set_config(app->usb_uart_bridge, cfg_set);
|
||||
|
||||
variable_item_set_current_value_index(item, cfg_set->flow_pins);
|
||||
variable_item_set_current_value_text(item, flow_pins[cfg_set->flow_pins]);
|
||||
}
|
||||
}
|
||||
|
||||
static void line_vcp_cb(VariableItem* item) {
|
||||
GpioApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
@@ -54,6 +72,7 @@ static void line_port_cb(VariableItem* item) {
|
||||
else if(index == 1)
|
||||
cfg_set->uart_ch = FuriHalUartIdLPUART1;
|
||||
usb_uart_set_config(app->usb_uart_bridge, cfg_set);
|
||||
line_ensure_flow_invariant(app);
|
||||
}
|
||||
|
||||
static void line_flow_cb(VariableItem* item) {
|
||||
@@ -116,9 +135,12 @@ void gpio_scene_usb_uart_cfg_on_enter(void* context) {
|
||||
variable_item_set_current_value_index(item, cfg_set->uart_ch);
|
||||
variable_item_set_current_value_text(item, uart_ch[cfg_set->uart_ch]);
|
||||
|
||||
item = variable_item_list_add(var_item_list, "RTS/DTR Pins", 3, line_flow_cb, app);
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "RTS/DTR Pins", COUNT_OF(flow_pins), line_flow_cb, app);
|
||||
variable_item_set_current_value_index(item, cfg_set->flow_pins);
|
||||
variable_item_set_current_value_text(item, flow_pins[cfg_set->flow_pins]);
|
||||
app->var_item_flow = item;
|
||||
line_ensure_flow_invariant(app);
|
||||
|
||||
variable_item_list_set_selected_item(
|
||||
var_item_list, scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUartCfg));
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
static const GpioPin* flow_pins[][2] = {
|
||||
{&gpio_ext_pa7, &gpio_ext_pa6}, // 2, 3
|
||||
{&gpio_ext_pb2, &gpio_ext_pc3}, // 6, 7
|
||||
{&gpio_ext_pc0, &gpio_ext_pc1}, // 16, 15
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -158,11 +159,8 @@ static int32_t usb_uart_worker(void* context) {
|
||||
usb_uart->tx_sem = furi_semaphore_alloc(1, 1);
|
||||
usb_uart->usb_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
|
||||
usb_uart->tx_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(usb_uart->tx_thread, "UsbUartTxWorker");
|
||||
furi_thread_set_stack_size(usb_uart->tx_thread, 512);
|
||||
furi_thread_set_context(usb_uart->tx_thread, usb_uart);
|
||||
furi_thread_set_callback(usb_uart->tx_thread, usb_uart_tx_thread);
|
||||
usb_uart->tx_thread =
|
||||
furi_thread_alloc_ex("UsbUartTxWorker", 512, usb_uart_tx_thread, usb_uart);
|
||||
|
||||
usb_uart_vcp_init(usb_uart, usb_uart->cfg.vcp_ch);
|
||||
usb_uart_serial_init(usb_uart, usb_uart->cfg.uart_ch);
|
||||
@@ -183,7 +181,7 @@ static int32_t usb_uart_worker(void* context) {
|
||||
while(1) {
|
||||
uint32_t events =
|
||||
furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||
furi_check((events & FuriFlagError) == 0);
|
||||
furi_check(!(events & FuriFlagError));
|
||||
if(events & WorkerEvtStop) break;
|
||||
if(events & WorkerEvtRxDone) {
|
||||
size_t len = furi_stream_buffer_receive(
|
||||
@@ -287,7 +285,7 @@ static int32_t usb_uart_tx_thread(void* context) {
|
||||
while(1) {
|
||||
uint32_t events =
|
||||
furi_thread_flags_wait(WORKER_ALL_TX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||
furi_check((events & FuriFlagError) == 0);
|
||||
furi_check(!(events & FuriFlagError));
|
||||
if(events & WorkerEvtTxStop) break;
|
||||
if(events & WorkerEvtCdcRx) {
|
||||
furi_check(furi_mutex_acquire(usb_uart->usb_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
@@ -337,11 +335,7 @@ UsbUartBridge* usb_uart_enable(UsbUartConfig* cfg) {
|
||||
|
||||
memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig));
|
||||
|
||||
usb_uart->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(usb_uart->thread, "UsbUartWorker");
|
||||
furi_thread_set_stack_size(usb_uart->thread, 1024);
|
||||
furi_thread_set_context(usb_uart->thread, usb_uart);
|
||||
furi_thread_set_callback(usb_uart->thread, usb_uart_worker);
|
||||
usb_uart->thread = furi_thread_alloc_ex("UsbUartWorker", 1024, usb_uart_worker, usb_uart);
|
||||
|
||||
furi_thread_start(usb_uart->thread);
|
||||
return usb_uart;
|
||||
|
||||
139
applications/main/gpio/views/gpio_i2c_scanner.c
Normal file
@@ -0,0 +1,139 @@
|
||||
#include <gui/elements.h>
|
||||
#include "gpio_i2c_scanner.h"
|
||||
#include "../gpio_item.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct GpioI2CScanner {
|
||||
View* view;
|
||||
GpioI2CScannerOkCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t items;
|
||||
uint8_t responding_address[AVAILABLE_NONRESVERED_I2C_ADDRESSES];
|
||||
} GpioI2CScannerModel;
|
||||
|
||||
static bool gpio_i2c_scanner_process_ok(GpioI2CScanner* gpio_i2c_scanner, InputEvent* event);
|
||||
|
||||
static void gpio_i2c_scanner_draw_callback(Canvas* canvas, void* _model) {
|
||||
GpioI2CScannerModel* model = _model;
|
||||
|
||||
char temp_str[25];
|
||||
elements_button_center(canvas, "Start scan");
|
||||
canvas_draw_line(canvas, 2, 10, 125, 10);
|
||||
canvas_draw_line(canvas, 2, 52, 125, 52);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 2, 9, "I2C-Scanner");
|
||||
canvas_draw_str(canvas, 3, 25, "SDA:");
|
||||
canvas_draw_str(canvas, 3, 42, "SCL:");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
snprintf(temp_str, 25, "Slaves: %u", model->items);
|
||||
canvas_draw_str_aligned(canvas, 126, 8, AlignRight, AlignBottom, temp_str);
|
||||
|
||||
canvas_draw_str(canvas, 29, 25, "Pin 15");
|
||||
canvas_draw_str(canvas, 29, 42, "Pin 16");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
char temp_str2[6];
|
||||
if(model->items > 0) {
|
||||
snprintf(temp_str, 25, "Addr: ");
|
||||
for(int i = 0; i < model->items; i++) {
|
||||
snprintf(temp_str2, 6, "0x%x ", model->responding_address[i]);
|
||||
strcat(temp_str, temp_str2);
|
||||
|
||||
if(i == 1 || model->items == 1) { //Draw a maximum of two addresses in the first line
|
||||
canvas_draw_str_aligned(canvas, 127, 24, AlignRight, AlignBottom, temp_str);
|
||||
temp_str[0] = '\0';
|
||||
} else if(
|
||||
i == 4 || (model->items - 1 == i &&
|
||||
i < 6)) { //Draw a maximum of three addresses in the second line
|
||||
canvas_draw_str_aligned(canvas, 127, 36, AlignRight, AlignBottom, temp_str);
|
||||
temp_str[0] = '\0';
|
||||
} else if(i == 7 || model->items - 1 == i) { //Draw a maximum of three addresses in the third line
|
||||
canvas_draw_str_aligned(canvas, 127, 48, AlignRight, AlignBottom, temp_str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool gpio_i2c_scanner_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
GpioI2CScanner* gpio_i2c_scanner = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->key == InputKeyOk) {
|
||||
consumed = gpio_i2c_scanner_process_ok(gpio_i2c_scanner, event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static bool gpio_i2c_scanner_process_ok(GpioI2CScanner* gpio_i2c_scanner, InputEvent* event) {
|
||||
bool consumed = false;
|
||||
gpio_i2c_scanner->callback(event->type, gpio_i2c_scanner->context);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
GpioI2CScanner* gpio_i2c_scanner_alloc() {
|
||||
GpioI2CScanner* gpio_i2c_scanner = malloc(sizeof(GpioI2CScanner));
|
||||
|
||||
gpio_i2c_scanner->view = view_alloc();
|
||||
view_allocate_model(gpio_i2c_scanner->view, ViewModelTypeLocking, sizeof(GpioI2CScannerModel));
|
||||
view_set_context(gpio_i2c_scanner->view, gpio_i2c_scanner);
|
||||
view_set_draw_callback(gpio_i2c_scanner->view, gpio_i2c_scanner_draw_callback);
|
||||
view_set_input_callback(gpio_i2c_scanner->view, gpio_i2c_scanner_input_callback);
|
||||
|
||||
return gpio_i2c_scanner;
|
||||
}
|
||||
|
||||
void gpio_i2c_scanner_free(GpioI2CScanner* gpio_i2c_scanner) {
|
||||
furi_assert(gpio_i2c_scanner);
|
||||
view_free(gpio_i2c_scanner->view);
|
||||
free(gpio_i2c_scanner);
|
||||
}
|
||||
|
||||
View* gpio_i2c_scanner_get_view(GpioI2CScanner* gpio_i2c_scanner) {
|
||||
furi_assert(gpio_i2c_scanner);
|
||||
return gpio_i2c_scanner->view;
|
||||
}
|
||||
|
||||
void gpio_i2c_scanner_set_ok_callback(
|
||||
GpioI2CScanner* gpio_i2c_scanner,
|
||||
GpioI2CScannerOkCallback callback,
|
||||
void* context) {
|
||||
furi_assert(gpio_i2c_scanner);
|
||||
furi_assert(callback);
|
||||
with_view_model(
|
||||
gpio_i2c_scanner->view,
|
||||
GpioI2CScannerModel * model,
|
||||
{
|
||||
UNUSED(model);
|
||||
gpio_i2c_scanner->callback = callback;
|
||||
gpio_i2c_scanner->context = context;
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
void gpio_i2c_scanner_update_state(GpioI2CScanner* instance, I2CScannerState* st) {
|
||||
furi_assert(instance);
|
||||
furi_assert(st);
|
||||
|
||||
with_view_model(
|
||||
instance->view,
|
||||
GpioI2CScannerModel * model,
|
||||
{
|
||||
model->items = st->items;
|
||||
|
||||
for(int i = 0; i < model->items; i++) {
|
||||
model->responding_address[i] = st->responding_address[i];
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
20
applications/main/gpio/views/gpio_i2c_scanner.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../gpio_i2c_scanner_control.h"
|
||||
|
||||
typedef struct GpioI2CScanner GpioI2CScanner;
|
||||
typedef void (*GpioI2CScannerOkCallback)(InputType type, void* context);
|
||||
|
||||
GpioI2CScanner* gpio_i2c_scanner_alloc();
|
||||
|
||||
void gpio_i2c_scanner_free(GpioI2CScanner* gpio_i2c_scanner);
|
||||
|
||||
View* gpio_i2c_scanner_get_view(GpioI2CScanner* gpio_i2c_scanner);
|
||||
|
||||
void gpio_i2c_scanner_set_ok_callback(
|
||||
GpioI2CScanner* gpio_i2c_scanner,
|
||||
GpioI2CScannerOkCallback callback,
|
||||
void* context);
|
||||
|
||||
void gpio_i2c_scanner_update_state(GpioI2CScanner* instance, I2CScannerState* st);
|
||||
149
applications/main/gpio/views/gpio_i2c_sfp.c
Normal file
@@ -0,0 +1,149 @@
|
||||
#include <gui/elements.h>
|
||||
#include "gpio_i2c_sfp.h"
|
||||
#include "../gpio_item.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct GpioI2CSfp {
|
||||
View* view;
|
||||
GpioI2CSfpOkCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char vendor[32];
|
||||
char oui[32];
|
||||
char rev[32];
|
||||
char pn[32];
|
||||
char sn[32];
|
||||
char dc[32];
|
||||
uint8_t type;
|
||||
char connector[32];
|
||||
int wavelength;
|
||||
int sm_reach;
|
||||
int mm_reach_om3;
|
||||
int bitrate;
|
||||
} GpioI2CSfpModel;
|
||||
|
||||
static bool gpio_i2c_sfp_process_ok(GpioI2CSfp* gpio_i2c_sfp, InputEvent* event);
|
||||
|
||||
static void gpio_i2c_sfp_draw_callback(Canvas* canvas, void* _model) {
|
||||
GpioI2CSfpModel* model = _model;
|
||||
|
||||
// Temp String for formatting output
|
||||
char temp_str[280];
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_button_center(canvas, "Read");
|
||||
canvas_draw_str(canvas, 2, 63, "P15 SCL");
|
||||
canvas_draw_str(canvas, 92, 63, "P16 SDA");
|
||||
|
||||
snprintf(temp_str, 280, "Vendor: %s", model->vendor);
|
||||
canvas_draw_str(canvas, 2, 9, temp_str);
|
||||
|
||||
snprintf(temp_str, 280, "PN: %s", model->pn);
|
||||
canvas_draw_str(canvas, 2, 19, temp_str);
|
||||
|
||||
snprintf(temp_str, 280, "SN: %s", model->sn);
|
||||
canvas_draw_str(canvas, 2, 29, temp_str);
|
||||
|
||||
snprintf(temp_str, 280, "REV: %s", model->rev);
|
||||
canvas_draw_str(canvas, 2, 39, temp_str);
|
||||
|
||||
snprintf(temp_str, 280, "CON: %s", model->connector);
|
||||
canvas_draw_str(canvas, 50, 39, temp_str);
|
||||
|
||||
//Print Wavelength of Module
|
||||
snprintf(temp_str, 280, "%u nm", model->wavelength);
|
||||
canvas_draw_str(canvas, 2, 49, temp_str);
|
||||
|
||||
// These values will be zero if not applicable..
|
||||
if(model->sm_reach != 0) {
|
||||
snprintf(temp_str, 280, "%u km (SM)", model->sm_reach);
|
||||
canvas_draw_str(canvas, 50, 49, temp_str);
|
||||
}
|
||||
if(model->mm_reach_om3 != 0) {
|
||||
snprintf(temp_str, 280, "%u m (MM OM3)", model->mm_reach_om3);
|
||||
canvas_draw_str(canvas, 50, 49, temp_str);
|
||||
}
|
||||
}
|
||||
|
||||
static bool gpio_i2c_sfp_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
GpioI2CSfp* gpio_i2c_sfp = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->key == InputKeyOk) {
|
||||
consumed = gpio_i2c_sfp_process_ok(gpio_i2c_sfp, event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static bool gpio_i2c_sfp_process_ok(GpioI2CSfp* gpio_i2c_sfp, InputEvent* event) {
|
||||
bool consumed = false;
|
||||
gpio_i2c_sfp->callback(event->type, gpio_i2c_sfp->context);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
GpioI2CSfp* gpio_i2c_sfp_alloc() {
|
||||
GpioI2CSfp* gpio_i2c_sfp = malloc(sizeof(GpioI2CSfp));
|
||||
|
||||
gpio_i2c_sfp->view = view_alloc();
|
||||
view_allocate_model(gpio_i2c_sfp->view, ViewModelTypeLocking, sizeof(GpioI2CSfpModel));
|
||||
view_set_context(gpio_i2c_sfp->view, gpio_i2c_sfp);
|
||||
view_set_draw_callback(gpio_i2c_sfp->view, gpio_i2c_sfp_draw_callback);
|
||||
view_set_input_callback(gpio_i2c_sfp->view, gpio_i2c_sfp_input_callback);
|
||||
|
||||
return gpio_i2c_sfp;
|
||||
}
|
||||
|
||||
void gpio_i2c_sfp_free(GpioI2CSfp* gpio_i2c_sfp) {
|
||||
furi_assert(gpio_i2c_sfp);
|
||||
view_free(gpio_i2c_sfp->view);
|
||||
free(gpio_i2c_sfp);
|
||||
}
|
||||
|
||||
View* gpio_i2c_sfp_get_view(GpioI2CSfp* gpio_i2c_sfp) {
|
||||
furi_assert(gpio_i2c_sfp);
|
||||
return gpio_i2c_sfp->view;
|
||||
}
|
||||
|
||||
void gpio_i2c_sfp_set_ok_callback(
|
||||
GpioI2CSfp* gpio_i2c_sfp,
|
||||
GpioI2CSfpOkCallback callback,
|
||||
void* context) {
|
||||
furi_assert(gpio_i2c_sfp);
|
||||
furi_assert(callback);
|
||||
with_view_model(
|
||||
gpio_i2c_sfp->view,
|
||||
GpioI2CSfpModel * model,
|
||||
{
|
||||
UNUSED(model);
|
||||
gpio_i2c_sfp->callback = callback;
|
||||
gpio_i2c_sfp->context = context;
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
void gpio_i2c_sfp_update_state(GpioI2CSfp* instance, I2CSfpState* st) {
|
||||
furi_assert(instance);
|
||||
furi_assert(st);
|
||||
|
||||
with_view_model(
|
||||
instance->view,
|
||||
GpioI2CSfpModel * model,
|
||||
{
|
||||
// Insert values into model...
|
||||
strcpy(model->vendor, st->vendor);
|
||||
strcpy(model->pn, st->pn);
|
||||
strcpy(model->sn, st->sn);
|
||||
strcpy(model->rev, st->rev);
|
||||
strcpy(model->connector, st->connector);
|
||||
model->wavelength = st->wavelength;
|
||||
model->sm_reach = st->sm_reach;
|
||||
model->mm_reach_om3 = st->mm_reach_om3;
|
||||
},
|
||||
true);
|
||||
}
|
||||
20
applications/main/gpio/views/gpio_i2c_sfp.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../gpio_i2c_sfp_control.h"
|
||||
|
||||
typedef struct GpioI2CSfp GpioI2CSfp;
|
||||
typedef void (*GpioI2CSfpOkCallback)(InputType type, void* context);
|
||||
|
||||
GpioI2CSfp* gpio_i2c_sfp_alloc();
|
||||
|
||||
void gpio_i2c_sfp_free(GpioI2CSfp* gpio_i2c_sfp);
|
||||
|
||||
View* gpio_i2c_sfp_get_view(GpioI2CSfp* gpio_i2c_sfp);
|
||||
|
||||
void gpio_i2c_sfp_set_ok_callback(
|
||||
GpioI2CSfp* gpio_i2c_sfp,
|
||||
GpioI2CSfpOkCallback callback,
|
||||
void* context);
|
||||
|
||||
void gpio_i2c_sfp_update_state(GpioI2CSfp* instance, I2CSfpState* st);
|
||||
14
applications/main/gpio_loader/application.fam
Normal file
@@ -0,0 +1,14 @@
|
||||
App(
|
||||
appid="gpio_loader",
|
||||
name="GPIO",
|
||||
apptype=FlipperAppType.APP,
|
||||
entry_point="gpio_loader_app",
|
||||
requires=[
|
||||
"gui",
|
||||
"storage",
|
||||
],
|
||||
stack_size=int(1.5 * 1024),
|
||||
icon="A_GPIO_14",
|
||||
order=50,
|
||||
link="/ext/apps/Main/gpio.fap",
|
||||
)
|
||||
9
applications/main/gpio_loader/gpio_loader_app.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <applications/services/loader/loader_i.h>
|
||||
|
||||
#define TAG "gpio_loader_app"
|
||||
|
||||
int32_t gpio_loader_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||