Merge remote-tracking branch 'upstream/420' into 420

This commit is contained in:
TalkingSasquach
2022-11-24 14:09:57 -05:00
4196 changed files with 99271 additions and 12709 deletions

128
.ci_files/anims_ofw.txt Normal file
View 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

View File

@@ -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
View File

@@ -55,3 +55,5 @@ openocd.log
# PVS Studio temporary files
.PVS-Studio/
PVS-Studio.log
.gdbinit

6
.gitmodules vendored
View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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",

View File

@@ -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,

View File

@@ -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",

View File

@@ -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`

Binary file not shown.

Binary file not shown.

256
ReadMe.md
View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -8,4 +8,5 @@ App(
stack_size=2 * 1024,
order=150,
fap_category="Debug",
fap_icon_assets="icons",
)

View File

@@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();

View 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`.

View File

@@ -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",
],
)

View File

@@ -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,
)

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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) {

View 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);
}

View File

@@ -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) {

View File

@@ -40,6 +40,7 @@ typedef enum {
ArchiveBrowserEventFileMenuRename,
ArchiveBrowserEventFileMenuDelete,
ArchiveBrowserEventFileMenuInfo,
ArchiveBrowserEventFileMenuShow,
ArchiveBrowserEventFileMenuClose,
ArchiveBrowserEventEnterDir,

View File

@@ -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"],
)

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -12,6 +12,7 @@ typedef enum {
BadUsbStateInit,
BadUsbStateNotConnected,
BadUsbStateIdle,
BadUsbStateWillRun,
BadUsbStateRunning,
BadUsbStateDelay,
BadUsbStateDone,

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

View File

@@ -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);

View 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",
)

View 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;
}

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View 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",
)

View File

@@ -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) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -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,
)

View File

@@ -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);

View File

@@ -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"],
)

View File

@@ -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);

View File

@@ -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;

View File

@@ -5,6 +5,8 @@ typedef enum {
GpioStartEventOtgOn,
GpioStartEventManualControl,
GpioStartEventUsbUart,
GpioStartEventI2CScanner,
GpioStartEventI2CSfp,
GpioCustomEventErrorBack,

View 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);
}

View 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);

View 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);
}

View 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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -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)

View 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);
}

View 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);
}

View File

@@ -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);

View File

@@ -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));

View File

@@ -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;

View 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);
}

View 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);

View 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);
}

View 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);

View 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",
)

View 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;
}

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