Compare commits
55 Commits
ARF-1.0.0
...
dev-d5b46f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5b46ffefb | ||
|
|
9d2298114c | ||
|
|
b93a970647 | ||
|
|
c6265ea29b | ||
|
|
8e0a81b89d | ||
|
|
6f39fd4803 | ||
|
|
41d10f9b3d | ||
|
|
1f97aa2e3c | ||
|
|
5b9038173b | ||
|
|
fde0a57595 | ||
|
|
3fb40944e6 | ||
|
|
e61cfa765a | ||
|
|
fd0dd6c324 | ||
|
|
8ff5e3c311 | ||
|
|
4974201851 | ||
|
|
b0b464e3fb | ||
|
|
57226fc902 | ||
|
|
cb9aee6422 | ||
|
|
b720fac88a | ||
|
|
22daa7cfc3 | ||
|
|
1c9fddf076 | ||
|
|
4380d9f156 | ||
|
|
a4da50c191 | ||
|
|
e881d69ab3 | ||
|
|
b041177398 | ||
|
|
f347d5a976 | ||
|
|
3a6da87288 | ||
|
|
5d94639d81 | ||
|
|
5dcfc48e10 | ||
|
|
20a95b2fec | ||
|
|
3605669cc5 | ||
|
|
fb1c28a0dd | ||
|
|
64a971e806 | ||
|
|
12db96a8ab | ||
|
|
4b50b8b70c | ||
|
|
0f24f8c105 | ||
|
|
238f39d0d8 | ||
|
|
4c3581735b | ||
|
|
689df5262d | ||
|
|
86c740d923 | ||
|
|
0aef017c15 | ||
|
|
cea3bc3b6a | ||
|
|
f3d08573a1 | ||
|
|
9e52a6eb6b | ||
|
|
faf669b457 | ||
|
|
e445b28d73 | ||
|
|
19e2eaa554 | ||
|
|
2571ad7f22 | ||
|
|
22a0870559 | ||
|
|
1c9d1f404a | ||
|
|
fabb1ccc2d | ||
|
|
6a432a93ad | ||
|
|
d2cca91ec8 | ||
|
|
6e483393e1 | ||
|
|
4dc688c25b |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
.arf_pictures/home.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
5
.github/CODEOWNERS
vendored
@@ -1,5 +1,2 @@
|
||||
# Default
|
||||
* @xMasterX
|
||||
|
||||
# Assets
|
||||
/assets/resources/infrared/assets/ @amec0e @Leptopt1los @xMasterX
|
||||
* ARF Crew
|
||||
|
||||
3
.github/workflows/build-dev.yml
vendored
@@ -17,6 +17,7 @@ jobs:
|
||||
|
||||
- name: Build firmware
|
||||
run: |
|
||||
export DIST_SUFFIX=Flipper-ARF
|
||||
chmod +x fbt
|
||||
./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
|
||||
@@ -28,7 +29,7 @@ jobs:
|
||||
id: firmware
|
||||
run: |
|
||||
DIR=$(ls -d dist/f7-* | head -n 1)
|
||||
FILE="$DIR/flipper-z-f7-update-local.tgz"
|
||||
FILE="$DIR/flipper-z-f7-update-Flipper-ARF.tgz"
|
||||
|
||||
if [ ! -f "$FILE" ]; then
|
||||
echo "Firmware file not found!"
|
||||
|
||||
66
CHANGELOG.md
@@ -1,66 +0,0 @@
|
||||
## Main changes
|
||||
- Current API: 87.6
|
||||
* SubGHz: Signal Settings Improvements (PR #968 | by @Dmitry422)
|
||||
* Apps: Build tag (**17feb2026**) - **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev)
|
||||
## Other changes
|
||||
* MFKey: Update to v4.1 (by @noproto & @dchristle)
|
||||
<br><br>
|
||||
#### Known NFC post-refactor regressions list:
|
||||
- Mifare Mini clones reading is broken (original mini working fine) (OFW)
|
||||
- While reading some EMV capable cards via NFC->Read flipper may crash due to Desfire poller issue, read those cards via Extra actions->Read specific card type->EMV
|
||||
|
||||
----
|
||||
|
||||
[-> How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
[-> Unleashed FW Web Installer](https://web.unleashedflip.com)
|
||||
|
||||
## Please support development of the project
|
||||
|
||||
| Service | Remark | QR Code | Link/Wallet |
|
||||
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
|
||||
| <img src="https://cdn.simpleicons.org/patreon/dark/white" alt="Patreon" width="14"/> **Patreon** | | <div align="center"><a href="https://github.com/user-attachments/assets/a88a90a5-28c3-40b4-864a-0c0b79494a42"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | [patreon.com/mmxdev](https://patreon.com/mmxdev) |
|
||||
| <img src="https://cdn.simpleicons.org/boosty" alt="Boosty" width="14"/> **Boosty** | patreon alternative | <div align="center"><a href="https://github.com/user-attachments/assets/893c0760-f738-42c1-acaa-916019a7bdf8"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | [boosty.to/mmxdev](https://boosty.to/mmxdev) |
|
||||
| <img src="https://gist.githubusercontent.com/m-xim/255a3ef36c886dec144a58864608084c/raw/71da807b4abbd1582e511c9ea30fad27f78d642a/cloudtips_icon.svg" alt="Cloudtips" width="14"/> CloudTips | only RU payments accepted | <div align="center"><a href="https://github.com/user-attachments/assets/5de31d6a-ef24-4d30-bd8e-c06af815332a"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | [pay.cloudtips.ru/p/7b3e9d65](https://pay.cloudtips.ru/p/7b3e9d65) |
|
||||
| <img src="https://raw.githubusercontent.com/gist/PonomareVlad/55c8708f11702b4df629ae61129a9895/raw/1657350724dab66f2ad68ea034c480a2df2a1dfd/YooMoney.svg" alt="YooMoney" width="14"/> YooMoney | only RU payments accepted | <div align="center"><a href="https://github.com/user-attachments/assets/33454f79-074b-4349-b453-f94fdadc3c68"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | [yoomoney.ru/fundraise/XA49mgQLPA0.221209](https://yoomoney.ru/fundraise/XA49mgQLPA0.221209) |
|
||||
| <img src="https://cdn.simpleicons.org/tether" alt="USDT" width="14"/> USDT | TRC20 | <div align="center"><a href="https://github.com/user-attachments/assets/0500498d-18ed-412d-a1a4-8a66d0b6f057"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs` |
|
||||
| <img src="https://cdn.simpleicons.org/ethereum" alt="ETH" width="14"/> ETH | BSC/ERC20-Tokens | <div align="center"><a href="https://github.com/user-attachments/assets/0f323e98-c524-4f41-abb2-f4f1cec83ab6"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a` |
|
||||
| <img src="https://cdn.simpleicons.org/bitcoin" alt="BTC" width="14"/> BTC | | <div align="center"><a href="https://github.com/user-attachments/assets/5a904d45-947e-4b92-9f0f-7fbaaa7b37f8"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9` |
|
||||
| <img src="https://cdn.simpleicons.org/solana" alt="SOL" width="13"/> SOL | Solana/Tokens | <div align="center"><a href="https://github.com/user-attachments/assets/ab33c5e0-dd59-497b-9c91-ceb89c36b34d"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | `DSgwouAEgu8iP5yr7EHHDqMNYWZxAqXWsTEeqCAXGLj8` |
|
||||
| <img src="https://cdn.simpleicons.org/dogecoin" alt="DOGE" width="14"/> DOGE | | <div align="center"><a href="https://github.com/user-attachments/assets/2937edd0-5c85-4465-a444-14d4edb481c0"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv` |
|
||||
| <img src="https://cdn.simpleicons.org/litecoin" alt="LTC" width="14"/> LTC | | <div align="center"><a href="https://github.com/user-attachments/assets/441985fe-f028-4400-83c1-c215760c1e74"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9` |
|
||||
| <img src="https://bitcoincash.org/img/green/bitcoin-cash-circle.svg" alt="BCH" width="14"/> BCH | | <div align="center"><a href="https://github.com/user-attachments/assets/7f365976-19a3-4777-b17e-4bfba5f69eff"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3` |
|
||||
| <img src="https://cdn.simpleicons.org/monero" alt="XMR" width="14"/> XMR | Monero | <div align="center"><a href="https://github.com/user-attachments/assets/96186c06-61e7-4b4d-b716-6eaf1779bfd8"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn` |
|
||||
| <img src="https://cdn.simpleicons.org/ton" alt="TON" width="14"/> TON | | <div align="center"><a href="https://github.com/user-attachments/assets/92a57e57-7462-42b7-a342-6f22c6e600c1"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div> | `UQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmsxa` |
|
||||
|
||||
|
||||
#### Thanks to our sponsors who supported project in the past and special thanks to sponsors who supports us on regular basis:
|
||||
@mishamyte, ClaraCrazy, Pathfinder [Count Zero cDc], callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
|
||||
and all other great people who supported our project and me (xMasterX), thanks to you all!
|
||||
|
||||
|
||||
## **Recommended update option - Web Updater**
|
||||
|
||||
### What `e`, ` `, `c` means? What I need to download if I don't want to use Web updater?
|
||||
What build I should download and what this name means - `flipper-z-f7-update-(version)(e / c).tgz` ? <br>
|
||||
`flipper-z` = for Flipper Zero device<br>
|
||||
`f7` = Hardware version - same for all flipper zero devices<br>
|
||||
`update` = Update package, contains updater, all assets (plugins, IR libs, etc.), and firmware itself<br>
|
||||
`(version)` = Firmware version<br>
|
||||
| Designation | [Base Apps](https://github.com/xMasterX/all-the-plugins#default-pack) | [Extra Apps](https://github.com/xMasterX/all-the-plugins#extra-pack) |
|
||||
|-----|:---:|:---:|
|
||||
| ` ` | ✅ | |
|
||||
| `c` | | |
|
||||
| `e` | ✅ | ✅ |
|
||||
|
||||
**To enable RGB Backlight support go into LCD & Notifications settings**
|
||||
|
||||
⚠️RGB backlight [hardware mod](https://github.com/quen0n/flipperzero-firmware-rgb#readme), works only on modded flippers! do not enable on non modded device!
|
||||
|
||||
|
||||
Firmware Self-update package (update from microSD) - `flipper-z-f7-update-(version).tgz` for mobile app / qFlipper / web<br>
|
||||
Archive of `scripts` folder (contains scripts for FW/plugins development) - `flipper-z-any-scripts-(version).tgz`<br>
|
||||
SDK files for plugins development and uFBT - `flipper-z-f7-sdk-(version).zip`
|
||||
|
||||
|
||||
|
||||
43
README.md
@@ -29,11 +29,11 @@ This project may incorporate, adapt, or build upon **other open-source projects*
|
||||
|
||||
| | |
|
||||
|:---:|:---:|
|
||||
|  |  |
|
||||
|  |  |
|
||||
| Home Screen | Sub-GHz Scanner |
|
||||
|  |  |
|
||||
|  |  |
|
||||
| Keeloq Key Manager | Mod Hopping Config |
|
||||
|  |  |
|
||||
|  |  |
|
||||
| PSA XTEA Decrypt | Counter BruteForce |
|
||||
|
||||
---
|
||||
@@ -45,19 +45,19 @@ This project may incorporate, adapt, or build upon **other open-source projects*
|
||||
| Manufacturer | Protocol | Frequency | Modulation | Encoder | Decoder | CRC |
|
||||
|:---|:---|:---:|:---:|:---:|:---:|:---:|
|
||||
| VAG (VW/Audi/Skoda/Seat) | VAG GROUP | 433 MHz | AM | Yes | Yes | No |
|
||||
| Porsche | Cayenne | 433/868 MHz | AM | Yes | Yes | No |
|
||||
| Porsche | Porsche AG | 433/868 MHz | AM | Yes | Yes | No |
|
||||
| PSA (Peugeot/Citroën/DS) | PSA GROUP | 433 MHz | AM/FM | Yes | Yes | Yes |
|
||||
| Ford | Ford V0 | 315/433 MHz | AM | Yes | Yes | Yes |
|
||||
| Fiat | Fiat SpA | 433 MHz | AM | Yes | Yes | Yes |
|
||||
| Fiat | Fiat Marelli | 433 MHz | AM | No | Yes | No |
|
||||
| Fiat | Marelli/Delphi | 433 MHz | AM | No | Yes | No |
|
||||
| Mazda | Siemens (5WK49365D) | 315/433 MHz | AM/FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | KIA/HYU V0 | 433 MHz | FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | KIA/HYU V1 | 315/433 MHz | AM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | KIA/HYU V2 | 315/433 MHz | AM/FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | KIA/HYU V3/V4 | 315/433 MHz | AM/FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | KIA/HYU V5 | 433 MHz | FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | KIA/HYU V6 | 433 MHz | FM | Yes | Yes | Yes |
|
||||
| Subaru | Subaru | 433 MHz | AM | Yes | Yes | No |
|
||||
| Mazda | Siemens (5WK49365D) | 315/433 MHz | FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | Kia V0 | 433 MHz | FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | Kia V1 | 315/433 MHz | AM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | Kia V2 | 315/433 MHz | FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | Kia V3/V4 | 315/433 MHz | AM/FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | Kia V5 | 433 MHz | FM | Yes | Yes | Yes |
|
||||
| Kia/Hyundai | Kia V6 | 433 MHz | FM | Yes | Yes | Yes |
|
||||
| Suzuki | Suzuki | 433 MHz | FM | Yes | Yes | Yes |
|
||||
| Mitsubishi | Mitsubishi V0 | 868 MHz | FM | Yes | Yes | No |
|
||||
|
||||
@@ -72,16 +72,19 @@ This project may incorporate, adapt, or build upon **other open-source projects*
|
||||
| CAME TWEE | 433 MHz | AM | Yes | Yes | No |
|
||||
| CAME Atomo | 433 MHz | AM | Yes | Yes | No |
|
||||
| Faac SLH | 433/868 MHz | AM | Yes | Yes | No |
|
||||
| Holtek | 433 MHz | AM | Yes | Yes | No |
|
||||
| Holtek-Ht12x | 433 MHz | AM | Yes | Yes | No |
|
||||
| Somfy Telis | 433 MHz | AM | Yes | Yes | Yes |
|
||||
| Somfy Keytis | 433 MHz | AM | Yes | Yes | Yes |
|
||||
| Alutech AT-4N | 433 MHz | AM | Yes | Yes | Yes |
|
||||
| Keyfinder | 433 MHz | AM | Yes | Yes | No |
|
||||
| KingGates Stylo4k | 433 MHz | AM | Yes | Yes | No |
|
||||
| Beninca ARC | 433 MHz | AM | Yes | Yes | No |
|
||||
| Hormann HSM | 433/868 MHz | AM | Yes | Yes | No |
|
||||
| Marantec | 433 MHz | AM | Yes | Yes | Yes |
|
||||
| Marantec24 | 433 MHz | AM | Yes | Yes | Yes |
|
||||
|
||||
### General Static Protocols
|
||||
### General Protocols
|
||||
|
||||
| Protocol | Frequency | Modulation | Encoder | Decoder | CRC |
|
||||
|:---|:---:|:---:|:---:|:---:|:---:|
|
||||
@@ -101,8 +104,6 @@ This project may incorporate, adapt, or build upon **other open-source projects*
|
||||
| Hay21 | 433 MHz | AM | Yes | Yes | No |
|
||||
| Revers RB2 | 433 MHz | AM | Yes | Yes | No |
|
||||
| Roger | 433 MHz | AM | Yes | Yes | No |
|
||||
| BinRAW | 433/315/868 MHz | AM/FM | Yes | Yes | No |
|
||||
| RAW | All | All | Yes | Yes | No |
|
||||
|
||||
---
|
||||
|
||||
@@ -110,9 +111,14 @@ This project may incorporate, adapt, or build upon **other open-source projects*
|
||||
|
||||
Compact release build:
|
||||
|
||||
To build:
|
||||
```
|
||||
./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
```
|
||||
To flash:
|
||||
```
|
||||
./fbt COMPACT=1 DEBUG=0 flash_usb_full
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -125,7 +131,7 @@ Flipper-ARF aims to achieve:
|
||||
- Stable encoder/decoder implementations
|
||||
- Modular protocol expansion
|
||||
|
||||
**Primary focus:** VAG, PSA, Fiat, Ford, Asian platforms, and aftermarket alarm systems.
|
||||
**Primary focus:** Automotives/Alarm's keyfob protocols, keeloq, and keyless systems.
|
||||
|
||||
> ⚠ This is a protocol-focused research firmware, not a general-purpose firmware.
|
||||
|
||||
@@ -133,10 +139,9 @@ Flipper-ARF aims to achieve:
|
||||
|
||||
## To Do / Planned Features
|
||||
|
||||
- [ ] Add Scher Khan & Starline protocols
|
||||
- [ ] Marelli BSI encoder and encryption
|
||||
- [ ] Improve RollJam app
|
||||
- [ ] Expand and refine Subaru, Kia, PSA, and other manufacturer protocols
|
||||
- [ ] Expand and refine as many manufacturer protocols as possible
|
||||
|
||||
---
|
||||
|
||||
@@ -177,7 +182,7 @@ Contributions are welcome if they:
|
||||
> Non-automotive features are considered out-of-scope for now.
|
||||
|
||||
### This code is a mess!
|
||||

|
||||

|
||||
---
|
||||
|
||||
## Citations & References
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
static bool otg_was_enabled = false;
|
||||
|
||||
static bool use_flux_capacitor = false;
|
||||
|
||||
void rolljam_ext_set_flux_capacitor(bool enabled) {
|
||||
use_flux_capacitor = enabled;
|
||||
}
|
||||
|
||||
static void rolljam_ext_power_on(void) {
|
||||
otg_was_enabled = furi_hal_power_is_otg_enabled();
|
||||
if(!otg_was_enabled) {
|
||||
@@ -423,7 +429,7 @@ static int32_t jam_thread_worker(void* context) {
|
||||
0xAA,0x55
|
||||
};
|
||||
|
||||
furi_hal_gpio_write(pin_amp, true);
|
||||
if(use_flux_capacitor) furi_hal_gpio_write(pin_amp, true);
|
||||
jam_start_tx(noise_pattern, 62);
|
||||
|
||||
uint8_t st = cc_state();
|
||||
@@ -432,7 +438,7 @@ static int32_t jam_thread_worker(void* context) {
|
||||
jam_start_tx(noise_pattern, 62);
|
||||
st = cc_state();
|
||||
if(st != MARC_TX) {
|
||||
furi_hal_gpio_write(pin_amp, false);
|
||||
if(use_flux_capacitor) furi_hal_gpio_write(pin_amp, false);
|
||||
FURI_LOG_E(TAG, "JAM: Cannot enter TX!");
|
||||
return -1;
|
||||
}
|
||||
@@ -492,7 +498,7 @@ static int32_t jam_thread_worker(void* context) {
|
||||
}
|
||||
|
||||
cc_idle();
|
||||
furi_hal_gpio_write(pin_amp, false);
|
||||
if(use_flux_capacitor) furi_hal_gpio_write(pin_amp, false);
|
||||
cc_write(CC_IOCFG2, 0x2E);
|
||||
FURI_LOG_I(TAG, "JAM: STOPPED (loops=%lu uf=%lu refills=%lu)", loops, underflows, refills);
|
||||
return 0;
|
||||
@@ -512,13 +518,17 @@ void rolljam_ext_gpio_init(void) {
|
||||
furi_hal_gpio_write(pin_mosi, false);
|
||||
furi_hal_gpio_init(pin_miso, GpioModeInput, GpioPullUp, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init(pin_gdo0, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init_simple(pin_amp, GpioModeOutputPushPull);
|
||||
furi_hal_gpio_write(pin_amp, false);
|
||||
if(use_flux_capacitor) {
|
||||
furi_hal_gpio_init_simple(pin_amp, GpioModeOutputPushPull);
|
||||
furi_hal_gpio_write(pin_amp, false);
|
||||
}
|
||||
}
|
||||
|
||||
void rolljam_ext_gpio_deinit(void) {
|
||||
furi_hal_gpio_write(pin_amp, false);
|
||||
furi_hal_gpio_init_simple(pin_amp, GpioModeAnalog);
|
||||
if(use_flux_capacitor) {
|
||||
furi_hal_gpio_write(pin_amp, false);
|
||||
furi_hal_gpio_init_simple(pin_amp, GpioModeAnalog);
|
||||
}
|
||||
furi_hal_gpio_init(pin_cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(pin_sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(pin_mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
void rolljam_ext_gpio_init(void);
|
||||
void rolljam_ext_set_flux_capacitor(bool enabled);
|
||||
void rolljam_ext_gpio_deinit(void);
|
||||
void rolljam_jammer_start(RollJamApp* app);
|
||||
void rolljam_jammer_stop(RollJamApp* app);
|
||||
|
||||
@@ -57,6 +57,11 @@ const char* jam_offset_names[] = {
|
||||
"1000 kHz",
|
||||
};
|
||||
|
||||
const char* hw_names[] = {
|
||||
"CC1101",
|
||||
"Flux Cap",
|
||||
};
|
||||
|
||||
// ============================================================
|
||||
// Scene handlers table (extern declarations in scene header)
|
||||
// ============================================================
|
||||
@@ -119,6 +124,7 @@ static RollJamApp* rolljam_app_alloc(void) {
|
||||
app->mod_index = ModIndex_AM650;
|
||||
app->jam_offset_index = JamOffIndex_700k;
|
||||
app->jam_offset_hz = jam_offset_values[JamOffIndex_700k];
|
||||
app->hw_index = HwIndex_CC1101;
|
||||
|
||||
// Services
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
@@ -69,6 +69,17 @@ typedef enum {
|
||||
extern const uint32_t jam_offset_values[];
|
||||
extern const char* jam_offset_names[];
|
||||
|
||||
// ============================================================
|
||||
// Hardware type
|
||||
// ============================================================
|
||||
typedef enum {
|
||||
HwIndex_CC1101 = 0,
|
||||
HwIndex_FluxCapacitor,
|
||||
HwIndex_COUNT,
|
||||
} HwIndex;
|
||||
|
||||
extern const char* hw_names[];
|
||||
|
||||
// ============================================================
|
||||
// Scenes
|
||||
// ============================================================
|
||||
@@ -133,6 +144,7 @@ typedef struct {
|
||||
FreqIndex freq_index;
|
||||
ModIndex mod_index;
|
||||
JamOffIndex jam_offset_index;
|
||||
HwIndex hw_index;
|
||||
uint32_t frequency;
|
||||
uint32_t jam_frequency;
|
||||
uint32_t jam_offset_hz;
|
||||
|
||||
@@ -41,6 +41,9 @@ void rolljam_scene_attack_phase1_on_enter(void* context) {
|
||||
view_dispatcher_switch_to_view(
|
||||
app->view_dispatcher, RollJamViewWidget);
|
||||
|
||||
// Configure hardware type
|
||||
rolljam_ext_set_flux_capacitor(app->hw_index == HwIndex_FluxCapacitor);
|
||||
|
||||
// Start jamming
|
||||
rolljam_jammer_start(app);
|
||||
|
||||
|
||||
@@ -30,10 +30,18 @@ static void menu_jam_offset_changed(VariableItem* item) {
|
||||
variable_item_set_current_value_text(item, jam_offset_names[index]);
|
||||
}
|
||||
|
||||
static void menu_hw_changed(VariableItem* item) {
|
||||
RollJamApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
app->hw_index = index;
|
||||
variable_item_set_current_value_text(item, hw_names[index]);
|
||||
}
|
||||
|
||||
static void menu_enter_callback(void* context, uint32_t index) {
|
||||
RollJamApp* app = context;
|
||||
|
||||
if(index == 3) {
|
||||
if(index == 4) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, RollJamEventStartAttack);
|
||||
}
|
||||
@@ -73,6 +81,16 @@ void rolljam_scene_menu_on_enter(void* context) {
|
||||
variable_item_set_current_value_index(offset_item, app->jam_offset_index);
|
||||
variable_item_set_current_value_text(offset_item, jam_offset_names[app->jam_offset_index]);
|
||||
|
||||
// --- Hardware ---
|
||||
VariableItem* hw_item = variable_item_list_add(
|
||||
app->var_item_list,
|
||||
"Hardware",
|
||||
HwIndex_COUNT,
|
||||
menu_hw_changed,
|
||||
app);
|
||||
variable_item_set_current_value_index(hw_item, app->hw_index);
|
||||
variable_item_set_current_value_text(hw_item, hw_names[app->hw_index]);
|
||||
|
||||
// --- Start button ---
|
||||
variable_item_list_add(
|
||||
app->var_item_list,
|
||||
|
||||
@@ -14,7 +14,9 @@ enum {
|
||||
SubmenuIndexUnlock = SubmenuIndexCommonMax,
|
||||
SubmenuIndexUnlockByReader,
|
||||
SubmenuIndexUnlockByPassword,
|
||||
SubmenuIndexDictAttack
|
||||
SubmenuIndexDictAttack,
|
||||
SubmenuIndexWriteKeepKey, // ULC: write data pages, keep target card's existing key
|
||||
SubmenuIndexWriteCopyKey, // ULC: write all pages including key from source card
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -214,8 +216,26 @@ static void nfc_scene_read_and_saved_menu_on_enter_mf_ultralight(NfcApp* instanc
|
||||
if(is_locked ||
|
||||
(data->type != MfUltralightTypeNTAG213 && data->type != MfUltralightTypeNTAG215 &&
|
||||
data->type != MfUltralightTypeNTAG216 && data->type != MfUltralightTypeUL11 &&
|
||||
data->type != MfUltralightTypeUL21 && data->type != MfUltralightTypeOrigin)) {
|
||||
data->type != MfUltralightTypeUL21 && data->type != MfUltralightTypeOrigin &&
|
||||
data->type != MfUltralightTypeMfulC)) {
|
||||
submenu_remove_item(submenu, SubmenuIndexCommonWrite);
|
||||
} else if(data->type == MfUltralightTypeMfulC) {
|
||||
// Replace the generic Write item with two ULC-specific options so the user
|
||||
// can choose whether to keep or overwrite the target card's 3DES key.
|
||||
// This avoids any mid-write dialog/view-switching complexity entirely.
|
||||
submenu_remove_item(submenu, SubmenuIndexCommonWrite);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write (Keep Key)",
|
||||
SubmenuIndexWriteKeepKey,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write (Copy Key)",
|
||||
SubmenuIndexWriteCopyKey,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
if(is_locked) {
|
||||
@@ -291,6 +311,14 @@ static bool nfc_scene_read_and_saved_menu_on_event_mf_ultralight(
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightCDictAttack);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWriteKeepKey) {
|
||||
instance->mf_ultralight_c_write_context.copy_key = false;
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneWrite);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWriteCopyKey) {
|
||||
instance->mf_ultralight_c_write_context.copy_key = true;
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneWrite);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
@@ -307,12 +335,139 @@ static NfcCommand
|
||||
if(mf_ultralight_event->type == MfUltralightPollerEventTypeRequestMode) {
|
||||
mf_ultralight_event->data->poller_mode = MfUltralightPollerModeWrite;
|
||||
furi_string_reset(instance->text_box_store);
|
||||
if(instance->mf_ultralight_c_dict_context.dict) {
|
||||
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
|
||||
}
|
||||
instance->mf_ultralight_c_dict_context.dict = NULL;
|
||||
instance->mf_ultralight_c_write_context.dict_state = NfcMfUltralightCWriteDictIdle;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthRequest) {
|
||||
// Skip auth during the read phase of write - we'll authenticate
|
||||
// against the target card in RequestWriteData using source key or dict attack
|
||||
mf_ultralight_event->data->auth_context.skip_auth = true;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeRequestKey) {
|
||||
// Dict attack key provider - user dict first, then system dict
|
||||
if(!instance->mf_ultralight_c_dict_context.dict &&
|
||||
instance->mf_ultralight_c_write_context.dict_state == NfcMfUltralightCWriteDictIdle) {
|
||||
if(keys_dict_check_presence(NFC_APP_MF_ULTRALIGHT_C_DICT_USER_PATH)) {
|
||||
instance->mf_ultralight_c_dict_context.dict = keys_dict_alloc(
|
||||
NFC_APP_MF_ULTRALIGHT_C_DICT_USER_PATH,
|
||||
KeysDictModeOpenExisting,
|
||||
sizeof(MfUltralightC3DesAuthKey));
|
||||
instance->mf_ultralight_c_write_context.dict_state = NfcMfUltralightCWriteDictUser;
|
||||
}
|
||||
if(!instance->mf_ultralight_c_dict_context.dict) {
|
||||
instance->mf_ultralight_c_dict_context.dict = keys_dict_alloc(
|
||||
NFC_APP_MF_ULTRALIGHT_C_DICT_SYSTEM_PATH,
|
||||
KeysDictModeOpenExisting,
|
||||
sizeof(MfUltralightC3DesAuthKey));
|
||||
instance->mf_ultralight_c_write_context.dict_state =
|
||||
NfcMfUltralightCWriteDictSystem;
|
||||
}
|
||||
}
|
||||
MfUltralightC3DesAuthKey key = {};
|
||||
bool got_key = false;
|
||||
if(instance->mf_ultralight_c_dict_context.dict) {
|
||||
got_key = keys_dict_get_next_key(
|
||||
instance->mf_ultralight_c_dict_context.dict,
|
||||
key.data,
|
||||
sizeof(MfUltralightC3DesAuthKey));
|
||||
}
|
||||
if(!got_key &&
|
||||
instance->mf_ultralight_c_write_context.dict_state == NfcMfUltralightCWriteDictUser) {
|
||||
// Exhausted user dict, switch to system dict
|
||||
if(instance->mf_ultralight_c_dict_context.dict) {
|
||||
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
|
||||
}
|
||||
instance->mf_ultralight_c_dict_context.dict = keys_dict_alloc(
|
||||
NFC_APP_MF_ULTRALIGHT_C_DICT_SYSTEM_PATH,
|
||||
KeysDictModeOpenExisting,
|
||||
sizeof(MfUltralightC3DesAuthKey));
|
||||
instance->mf_ultralight_c_write_context.dict_state = NfcMfUltralightCWriteDictSystem;
|
||||
if(instance->mf_ultralight_c_dict_context.dict) {
|
||||
got_key = keys_dict_get_next_key(
|
||||
instance->mf_ultralight_c_dict_context.dict,
|
||||
key.data,
|
||||
sizeof(MfUltralightC3DesAuthKey));
|
||||
}
|
||||
}
|
||||
if(got_key) {
|
||||
mf_ultralight_event->data->key_request_data.key = key;
|
||||
mf_ultralight_event->data->key_request_data.key_provided = true;
|
||||
FURI_LOG_D(
|
||||
"MfULC",
|
||||
"Trying dict key: "
|
||||
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
key.data[0],
|
||||
key.data[1],
|
||||
key.data[2],
|
||||
key.data[3],
|
||||
key.data[4],
|
||||
key.data[5],
|
||||
key.data[6],
|
||||
key.data[7],
|
||||
key.data[8],
|
||||
key.data[9],
|
||||
key.data[10],
|
||||
key.data[11],
|
||||
key.data[12],
|
||||
key.data[13],
|
||||
key.data[14],
|
||||
key.data[15]);
|
||||
} else {
|
||||
mf_ultralight_event->data->key_request_data.key_provided = false;
|
||||
FURI_LOG_D("MfULC", "Dict exhausted - no more keys");
|
||||
if(instance->mf_ultralight_c_dict_context.dict) {
|
||||
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
|
||||
instance->mf_ultralight_c_dict_context.dict = NULL;
|
||||
}
|
||||
instance->mf_ultralight_c_write_context.dict_state =
|
||||
NfcMfUltralightCWriteDictExhausted;
|
||||
}
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeRequestWriteData) {
|
||||
mf_ultralight_event->data->write_data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
|
||||
// Reset dict context so RequestKey starts fresh for the write-phase auth
|
||||
if(instance->mf_ultralight_c_dict_context.dict) {
|
||||
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
|
||||
instance->mf_ultralight_c_dict_context.dict = NULL;
|
||||
}
|
||||
instance->mf_ultralight_c_write_context.dict_state = NfcMfUltralightCWriteDictIdle;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeWriteKeyRequest) {
|
||||
// Apply the user's key choice - read from static, not scene state (scene manager
|
||||
// resets state to 0 on scene entry, wiping any value set before next_scene).
|
||||
bool keep_key = !instance->mf_ultralight_c_write_context.copy_key;
|
||||
mf_ultralight_event->data->write_key_skip = keep_key;
|
||||
|
||||
if(mf_ultralight_event->data->key_request_data.key_provided) {
|
||||
MfUltralightC3DesAuthKey found_key = mf_ultralight_event->data->key_request_data.key;
|
||||
FURI_LOG_D(
|
||||
"MfULC",
|
||||
"WriteKeyRequest: target key = "
|
||||
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
found_key.data[0],
|
||||
found_key.data[1],
|
||||
found_key.data[2],
|
||||
found_key.data[3],
|
||||
found_key.data[4],
|
||||
found_key.data[5],
|
||||
found_key.data[6],
|
||||
found_key.data[7],
|
||||
found_key.data[8],
|
||||
found_key.data[9],
|
||||
found_key.data[10],
|
||||
found_key.data[11],
|
||||
found_key.data[12],
|
||||
found_key.data[13],
|
||||
found_key.data[14],
|
||||
found_key.data[15]);
|
||||
}
|
||||
FURI_LOG_D(
|
||||
"MfULC",
|
||||
"WriteKeyRequest: decision = %s (copy_key=%d)",
|
||||
keep_key ? "KEEP target key (pages 44-47 NOT written)" :
|
||||
"OVERWRITE with source key (pages 44-47 WILL be written)",
|
||||
(int)instance->mf_ultralight_c_write_context.copy_key);
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeCardMismatch) {
|
||||
furi_string_set(instance->text_box_store, "Card of the same\ntype should be\n presented");
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventWrongCard);
|
||||
@@ -323,6 +478,7 @@ static NfcCommand
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
command = NfcCommandStop;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeWriteFail) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
command = NfcCommandStop;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeWriteSuccess) {
|
||||
furi_string_reset(instance->text_box_store);
|
||||
@@ -334,9 +490,18 @@ static NfcCommand
|
||||
}
|
||||
|
||||
static void nfc_scene_write_on_enter_mf_ultralight(NfcApp* instance) {
|
||||
// Free any dict the write callback opened (dict_state != Idle means we own it).
|
||||
// After a DictAttack scene, on_exit now NULLs the pointer so a simple NULL check
|
||||
// is safe here too — but the state enum is the authoritative ownership record.
|
||||
if(instance->mf_ultralight_c_write_context.dict_state != NfcMfUltralightCWriteDictIdle &&
|
||||
instance->mf_ultralight_c_dict_context.dict) {
|
||||
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
|
||||
}
|
||||
instance->mf_ultralight_c_dict_context.dict = NULL;
|
||||
instance->mf_ultralight_c_write_context.dict_state = NfcMfUltralightCWriteDictIdle;
|
||||
furi_string_set(instance->text_box_store, "\nApply the\ntarget\ncard now");
|
||||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfUltralight);
|
||||
nfc_poller_start(instance->poller, nfc_scene_write_poller_callback_mf_ultralight, instance);
|
||||
furi_string_set(instance->text_box_store, "Apply the initial\ncard only");
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight = {
|
||||
|
||||
@@ -126,6 +126,18 @@ typedef struct {
|
||||
size_t dict_keys_current;
|
||||
} NfcMfUltralightCDictContext;
|
||||
|
||||
typedef enum {
|
||||
NfcMfUltralightCWriteDictIdle, /**< No dict open; safe to open either dict. */
|
||||
NfcMfUltralightCWriteDictUser, /**< User dict currently open. */
|
||||
NfcMfUltralightCWriteDictSystem, /**< System dict currently open. */
|
||||
NfcMfUltralightCWriteDictExhausted, /**< All dicts tried; do not re-open. */
|
||||
} NfcMfUltralightCWriteDictState;
|
||||
|
||||
typedef struct {
|
||||
bool copy_key; /**< True = overwrite target 3DES key with source key pages. */
|
||||
NfcMfUltralightCWriteDictState dict_state; /**< Which dict is open for write-phase auth. */
|
||||
} NfcMfUltralightCWriteContext;
|
||||
|
||||
struct NfcApp {
|
||||
DialogsApp* dialogs;
|
||||
Storage* storage;
|
||||
@@ -165,6 +177,7 @@ struct NfcApp {
|
||||
SlixUnlock* slix_unlock;
|
||||
NfcMfClassicDictAttackContext nfc_dict_context;
|
||||
NfcMfUltralightCDictContext mf_ultralight_c_dict_context;
|
||||
NfcMfUltralightCWriteContext mf_ultralight_c_write_context;
|
||||
Mfkey32Logger* mfkey32_logger;
|
||||
MfUserDict* mf_user_dict;
|
||||
MfClassicKeyCache* mfc_key_cache;
|
||||
|
||||
@@ -77,6 +77,15 @@ void nfc_scene_mf_ultralight_c_dict_attack_prepare_view(NfcApp* instance) {
|
||||
// Set attack type to Ultralight C
|
||||
dict_attack_set_type(instance->dict_attack, DictAttackTypeMfUltralightC);
|
||||
|
||||
// Guard: if a previous write phase left a dict handle open, close it now.
|
||||
// Without this, navigating write->back->read->dict-attack would open the same
|
||||
// file twice, corrupting VFS state and causing a ViewPort lockup.
|
||||
if(instance->mf_ultralight_c_dict_context.dict) {
|
||||
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
|
||||
instance->mf_ultralight_c_dict_context.dict = NULL;
|
||||
instance->mf_ultralight_c_write_context.dict_state = NfcMfUltralightCWriteDictIdle;
|
||||
}
|
||||
|
||||
if(state == DictAttackStateUserDictInProgress) {
|
||||
do {
|
||||
if(!keys_dict_check_presence(NFC_APP_MF_ULTRALIGHT_C_DICT_USER_PATH)) {
|
||||
@@ -167,6 +176,7 @@ bool nfc_scene_mf_ultralight_c_dict_attack_on_event(void* context, SceneManagerE
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
|
||||
instance->mf_ultralight_c_dict_context.dict = NULL;
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager,
|
||||
NfcSceneMfUltralightCDictAttack,
|
||||
@@ -199,6 +209,7 @@ bool nfc_scene_mf_ultralight_c_dict_attack_on_event(void* context, SceneManagerE
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
|
||||
instance->mf_ultralight_c_dict_context.dict = NULL;
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager,
|
||||
NfcSceneMfUltralightCDictAttack,
|
||||
@@ -230,6 +241,7 @@ void nfc_scene_mf_ultralight_c_dict_attack_on_exit(void* context) {
|
||||
NfcSceneMfUltralightCDictAttack,
|
||||
DictAttackStateUserDictInProgress);
|
||||
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
|
||||
instance->mf_ultralight_c_dict_context.dict = NULL;
|
||||
instance->mf_ultralight_c_dict_context.dict_keys_total = 0;
|
||||
instance->mf_ultralight_c_dict_context.dict_keys_current = 0;
|
||||
instance->mf_ultralight_c_dict_context.auth_success = false;
|
||||
|
||||
@@ -93,6 +93,7 @@ typedef enum {
|
||||
SubGhzViewIdFrequencyAnalyzer,
|
||||
SubGhzViewIdReadRAW,
|
||||
SubGhzViewIdPsaDecrypt,
|
||||
SubGhzViewIdKeeloqDecrypt,
|
||||
|
||||
} SubGhzViewId;
|
||||
|
||||
|
||||
@@ -1,107 +1,108 @@
|
||||
Filetype: Flipper SubGhz Keystore File
|
||||
Version: 0
|
||||
Encryption: 0
|
||||
0000000000000000:1:Allgate_Simple
|
||||
0000000023304758:6:KGB/Subaru
|
||||
0000000033205748:7:Magic_2
|
||||
00000000C3644917:2:VAG_Custom_Seed
|
||||
0102030410203040:1:IronLogic
|
||||
0123456789ABCDEF:2:Stilmatic
|
||||
0132456789ABCDEF:1:Pandora_Test_Debug_2
|
||||
05AEDAABAA981903:1:Rosh
|
||||
08AEDAABAA981903:1:Dea_Mio
|
||||
1067DC33E7D88A46:0:Leopard
|
||||
12332594A9189478:1:Sheriff
|
||||
1234567812345678:2:NICE_Flor_S
|
||||
1234567890123456:1:Cenmax
|
||||
188B0544A9B1DF14:2:Centurion
|
||||
1961DAC2EB198847:2:Guard_RF-311A
|
||||
1B36977B281597AC:1:Pandora_PRO
|
||||
207DBBE59D386F44:2:Cardin_S449
|
||||
2156EB02D8E9B977:1:Pandora_DEA
|
||||
2255EA01DBEABA76:1:Pandora_GIBIDI
|
||||
2354E900DAEBBB75:1:Pandora_MCODE
|
||||
2453EE07DDECBC72:1:Pandora_Unknown_1
|
||||
2552EF06DCEDBD73:1:Pandora_SUZUKI
|
||||
2587010764070864:1:Harpoon
|
||||
2626991902991902:1:Gibidi
|
||||
2651EC05DFEEBE70:1:Pandora_Unknown_2
|
||||
27193A9B117C0835:11:Jarolift
|
||||
2739451414471820:2:Audii
|
||||
2750ED04DEEFBF71:2:Pandora_NISSAN
|
||||
30317B307D794471:1:KEY
|
||||
314C3865304E3961:1:Novoferm
|
||||
32130221685B9D8C:2:VAG_HELLA_VPM2
|
||||
3519B934A4227995:1:Pandora_SUBARU
|
||||
352BABACA5F4DFE0:1:Pecinin
|
||||
381D7D9A2A17AE99:1:Pandora_M101
|
||||
3E461AB4F76DA19B:2:Merlin
|
||||
4030201004030201:1:IL-100(Smart)
|
||||
4130850A82610A14:1:Pantera_CLK
|
||||
414C455831393830:1:Kingates_Stylo4k
|
||||
4292903083134583:2:Monarch
|
||||
434144494C4C4143:2:Cadillac_GM
|
||||
43485259534C4552:2:Chrysler
|
||||
444145574F4F0000:2:Daewoo
|
||||
4772736565734769:1:Aprimatic
|
||||
484D6C6D73545253:1:NICE_MHOUSE
|
||||
484F4E4441200000:2:Honda
|
||||
4859554E44414920:2:Hyundai_Asia
|
||||
4C6D4D7A55644F76:3:BFT
|
||||
4D41474E64796E65:1:Pantera
|
||||
4D49545355424953:2:Mitsubishi
|
||||
4E495353414E2000:2:Nissan
|
||||
535446524B453030:13:KIAV5
|
||||
53555A554B490000:2:Suzuki
|
||||
53696C7669618C14:5:FAAC_SLH
|
||||
54365CB7676284F9:1:Alligator_S-275
|
||||
544F594F54410000:2:Toyota
|
||||
54524D534543494E:1:NICE_Smilo
|
||||
5504045708301203:1:SL_A6-A9/Tomahawk_9010
|
||||
572768229476CAFF:2:Motorline
|
||||
638664A880AA23FC:11:KIAV6A
|
||||
6408076407018725:1:Tomahawk_TZ-9030
|
||||
66B446B980AC752B:1:Cenmax_St-7
|
||||
67732C5056334627:1:Pantera_XS/Jaguar
|
||||
685B9D8C5A130221:2:VAG_HELLA_VPM
|
||||
68732C5056334728:1:APS-1100_APS-2550
|
||||
6912FA557DC2418A:0:Reff
|
||||
6B8E6CA088A22BF4:12:KIAV6B
|
||||
6D69736572657265:2:BFT_Miserere
|
||||
6EB6AE4815C63ED2:9:Beninca_ARC
|
||||
6F5E4D3B2AABCDEF:1:Tomahawk_Z,X_3-5
|
||||
7BCBEED4376EDCBF:2:Sommer
|
||||
7EAF1E9A392B19B9:1:Pandora_PRO2
|
||||
8455F43584941223:1:DoorHan
|
||||
8607427861394E30:2:EcoStar
|
||||
8765432187654321:2:Sommer_FM_868
|
||||
89146E59537903B7:1:JCM_Tech
|
||||
8A326438B62287F5:0:Faraon
|
||||
8BC9E46704700800:1:Vag
|
||||
96638C36C99C2C9B:1:Came_Space
|
||||
9804655AA5000000:8:Magic_4
|
||||
9BF7F89BF8FE78DA:1:SL_A2-A4
|
||||
9C61FD3A47B8E25C:2:Elmes_Poland
|
||||
9DA08153CF312BA7:1:Normstahl
|
||||
A8F5DFFC8DAA5CDB:10:KIA
|
||||
A9748532B7655297:2:GSN
|
||||
AA38A7A32189B5A1:0:Mutanco_Mutancode
|
||||
AAFBFBA8F7CFEDFC:1:Cenmax_St-5
|
||||
AC35BB2759000000:8:Magic_3
|
||||
AD3C12A17028F11E:1:Partisan_RX
|
||||
B3E5625A8CCD7139:2:Steelmate
|
||||
B51526E8F126D1D7:0:Teco
|
||||
B51A7AAB27351596:0:ZX-730-750-1055
|
||||
BBEE9EDDAAF97ECC:1:Jolly_Motors
|
||||
CEB6AE48B5C63ED2:4:Beninca
|
||||
D5A5E7B2A7C1A0BA:2:Mongoose
|
||||
E5D2C83529C113E6:2:VAG_HELLA_PWM
|
||||
EEF3D4B2626C5578:1:Alligator
|
||||
F1A3E552C8647E55:2:Comunello
|
||||
F250006EF29E030E:2:Vauweh
|
||||
F6E5D4B32ABADCFE:1:SL_B6,B9_dop
|
||||
FAAC05600001FAAC:2:FAAC_RC,XT
|
||||
FAAC05600002FAAC:2:Genius_Bravo
|
||||
FADA12FADA34F0DA:1:Rossi
|
||||
FC4DE22CD5370320:1:DTM_Neo
|
||||
FEDCBA9876543210:2:Came_Tam
|
||||
Encryption: 1
|
||||
IV: 41 52 46 5F 54 68 65 5F 46 69 72 6D 77 61 72 65
|
||||
1F55E94BD99C5FCA4E8CD620CB2F014854B25B5A5AC7633F7B8C2CE3993328A7A275ED382F23319461EC7B2E2BC450AC
|
||||
71DF40F4D16CF30DC5223ED59B395704BC67271E3058CB09D7F5D9CEE1C04852
|
||||
250208FB825F12A07A8C3F295C3B5FA69F52F2C9CA80452FDD1AEFC5A25F24DC
|
||||
9D6D26F67532E91FE89476A9E754A60DF8ECE7B92CD1772A7AD3190FCABF06414C0A3762E0012D102798EE204A5549EC
|
||||
0DCC0382D81B9D3E291FDEDDC697E2841D88A326D2869BA29F248D5DA4C96110
|
||||
F84B5EB3BB882F76E0264A5A1791EDAC8A1CA35E7579EA4D247E473EB1F8F4C1
|
||||
F8A4AFFF527E13643AC511900CF1764408691F60ABD1373E6AFE477E9967FD7F57E3CE41AE4700722DFA383BC64E9669
|
||||
265C0060DE53B95EF07EE3E00045A6D03C89FE1D89F90EA3A2AFBFDB4A4636D6
|
||||
DA1EBA6372C50D2072AC38CAACA3B023DEFDAE50987E764BEDA1E9FE53390CBA
|
||||
1C0378D5294FC62DCD95A385B3AD2E6FACC13D9AAC37EF7BCE4341E33876BCE8
|
||||
68AA58FB1DCDC05E56E0685DC57661333F66D890C6377771327DFB5EBEDA6AE1
|
||||
E647CDE269D1DC5F404830C30B3CE38D8C0B6E928DB4E8863523799E51977B2B
|
||||
AB40C8B0815B04C84BA1B1ACFFC93F20FE7F60F64AAE6E6AD4562415E6EFC049
|
||||
DCD258016EB06D81DFC494261017E9DF36601076970EA09B008EEA43DA0E68EE
|
||||
321F568C032B4C8B0B392A868ECC0D87EC9969E328FA35BBE9656701C77C35A8
|
||||
E14A72B0B0689AA7E08A6081E56A00862A34808D77111DE804DDFA39FFCF6782
|
||||
FF2573046D35FAA029BF0871A2D3216029B66927CECF527C72F192E06E13C3DC
|
||||
FF890BCB54AD911EE78345FCC4F2DA65B653D68C7F6774C74DC998A2295F4916
|
||||
8D1D92B53C1DD31BE8E1759640471793EFA8E987A4EDEE64A6DF658F2F67C136F5EFC0E895493BC02DB11B783E04DF84
|
||||
20FD4B91D4169332B3CCCBDAB4FA5C730F37FF16A283ADBA6EA9D80F5D9C9F26
|
||||
7B710488CFE33CE2EDDD37A3E864A517F7309FB097F8959497A5AD42B0E5C8AC2BA7AC6CD6B0BFCDEF5C88F4A995F20C
|
||||
00D242BF328330A11124C423779CC73379BB80B8071CEFB8F413ED3C9A11BB1F7D4B3B22CA0AC10A74A68887E0994259
|
||||
5BA325DD503C710D0BC153C50A2CC4F621AB6AE87E9CBBCD2996ED1B2FA1A854
|
||||
731724428F104BB5697E7705B3E0834B41202A9F2D49C90C4889DDDB21F5AC3E
|
||||
A22BAAB3818146B7B099CD3D65634F7CEBAD36015E7A5A16206ADFBD51988E038F2F62D273CA65CC592AF7DEB805510A
|
||||
8DD12F73EF956047011A61C212986775D2A41F98E629DD78C6FA70C0E2634ECA
|
||||
25D57BF539C51295524A53E5EF633547C54CB3D9A8072D9CAD897CEBD2AED3B3
|
||||
C54BA9B2D4C6DFDC639E2964316D5311B2A039631880D5F4986E38D63976E28EABFF01B643EFC853DFB8E2E1622A7674
|
||||
7A4062817B4848748A66AB34F9A4DA942BB3FE82CE1E264A12297FB7C6CF68B4
|
||||
65DC6DC85C44CF8D04F7B786C16D30F9BB12C7AE80B68612464021CAAEB196AD
|
||||
DD1F98CF4AF384B2412A786614C16109ED8FF9E842DCFF8E859B1D27BF1E08AD4C31793D1A6E07F8BCC7E5E0BCD4DF3B
|
||||
C0FF96999B5AC49EDCDFF82A51968F2A985D240A2AC91178C02B34DDD5F2EE77DA0804D9E47470889DC8FC8BA01B2C11
|
||||
51BAEBB4763C7E2A57C638ED824D83C73FB5E3E128992BBAAB7690CED5B40310
|
||||
947F12090F89793CE465816679654F5E6397E3A15D726DF86A6023E6E8ABB065
|
||||
B70CC56D0AF6F8E04E63031BBCB02EED4DB59A80B81FD4F67B8B61DFA57A0D51
|
||||
C3DC0E9717759C36DFBDA6CCDD146B54C5F1A52A3C3802ADE9D2303BD179F5CE
|
||||
5728832CD50226018ADD6A4736866EE4E932616C1CE74D67E2CE00D1427CBD96
|
||||
222A41966802B8607EF496D898D5BCA41BD9D891552F53FD809C81C487EBB8C25DB6CA656AFF45D5911BE9B10BADBDF5
|
||||
E171BE8EEC7773BB6AC1EC6B8AD13696267770931E4D72ADEB6A519A085F4EAF
|
||||
29FA68F7BB01E55AA738A68866F674CF34873E6109C328D4654FF3CCAE7D3C73
|
||||
E6791ABDD092843AE7A9B3A936B1AA77B812FF16CEA352F7972F132480AA4561
|
||||
701A4DCFF6C7A56D9DAC77F071220F7C28B8206BB5F3213F5761C8ED6DABEDC6
|
||||
AA4678E9AF3FE65F9B8E90A5CC95034CF510F1BD2C26DC89200CDAF3E15A9990
|
||||
A13B1578F6A2241830208014AD3E864CB0AA442AFF02952F3C2FCCC4F33140B2
|
||||
7C08CEC7BD2CC73EC9C436D32BB692E9020B9E043CF5F428705097F0AB141DEF
|
||||
8F39C7668AD33A2F66E5451E07CDF87D4B44FC962DEDE7D68365EA8E729A058E
|
||||
67F6C50C2D1BDEF471913E405A182D91040D4F4160484ED8762037F7F2EE8EBA
|
||||
4DF3627B7F42226780EB3C247F18C1F37CD25AA22C120F69B732A1FAC9D02C8A
|
||||
2A277456C8BA44CDC5A44D4353B9FA04D3F45743DB04B1E659F7DB4A8219672E
|
||||
1E749351CBE258D2B8710B48FF9D3F4034244C7CAEA25C93FA4A2E04E2F4CB59
|
||||
AEEA5813C69800830540B6768FCD0EF35A43FA58F6A8315AE06545A6103112D1
|
||||
5A773FDCBABB5C9ADAD19B356D0300D5A5E905E6FEDED53D209A9BE2853C5BD8
|
||||
F7C5AA9B29EB56D16610B560F65E99E78DCFE9463E6347E9477F387AC5756B05
|
||||
59AF0DCF53E422B553B250F9131E365D9265ACA04C1763CEA379459D8E2D2026E4C6523DBEC8CFA9D2C287C7AB6F8719
|
||||
CC11C8105B3643EAF8F935EE3E5408181CD7A41011EDF11F37D8BE45A70CB5A2
|
||||
0B71155A1BFE1A61D1C6122EC9961CF97BF34C188AEEA1FCBDA8A56631180926
|
||||
C4EA8825FB1030BDFCAD7A991F3CC7D65CA4300E1ABA4C53EB7287CF33031286E699217258B9CECCF99412915C50A579
|
||||
A38F7B2D60ECD413609AF9A02924D50591FB07C2EF95B8512569E48D613855F0
|
||||
6EBF32A7D2070E13A7EB01CB3CB3C62A2173DD56AC3627320B54E3D3211BCBC2
|
||||
CCD92DEBB91582B72DC921F8675002399299C243C6AE9BADFE3EEB1BCC79512C3FEA1A83393F795AC6E0546B3FFAE364
|
||||
491AD804382AA360C866082778A8ABA358FF9586A955BD5A9FD28FDF0B05744B
|
||||
9D6D8647BC32B0A4EE08F2D361B13037BA596402E6BEB4ED9D3D582F5552C89B9D96CD6836DF15E55251ED39E5D0E8C4
|
||||
BE92434BC3F646A192146500D150462E8FDFADB93E0DC8C1BE1B2F9E4B3A762B
|
||||
7FA5E6D202BE57AA4DAFE94090FA8F84D483C3A6DEFD7EDF69D0F9972F55212EEBA83C847A8374059280AEDB24BA11BC
|
||||
B6CDA34C4E8DFE3E509A22DC89B67E9706A980198D3FC522362B59647D79DBEA
|
||||
BEED72A8B1DFBABF59D58D8EA98385BF706BDF403E3F84702D0BF5D87E0FAEBC
|
||||
B049623264E92A557F1F6B04546D0D73889BF732ACE3109583CD52E226D8C2BC
|
||||
91881B87503555F8A82E3E4314C1276F636BD5F2BB451FF1E131CB8CD0E089BF
|
||||
AEA6163792A3B2D587F9270752F9D744849621E8A4DF9B5B82DFF06297DA828D4A95DD8E71267E560BFEB6C2EDB06F2A
|
||||
98CEA896C163DBE5C9839CAE6E09DF46EE9AEC8A8978C5B018DB80E1081E01A3
|
||||
27759BD9760153C94F982ADD85DA3F7FDD51EF17B3791968417ACDEBEBE59F9C
|
||||
716574AB5E60E65600B86A66F6C8A6536FB97792D5B9A5EDE477D5B623F118B1
|
||||
740FD62AFEF9D781976A5C01D8041B00A0D69DE56F1FAE030CC680D0D81793CB
|
||||
9BFF7A62569BA492B586CA27B2A87F96861F5564696AD3F779A58C09955A6342
|
||||
9BBF2793C0326BD03BA66A59BE65977C68225E26A55AAA6B56AC4F1D21B795DB
|
||||
B8D4A1B5134B09C81B586A8ADDFA6292DE50CA84D0FAA9448D610C68129FD9CD
|
||||
46827F0D09BEBFF241B4615EF4F9E5ADDB559EB87F4FC15A2AC58816969E186A
|
||||
B090E1924CEF93ADC559E876CC71D174A43FE7ECB0FA2A7D748BD51E9B4D9780
|
||||
8E8BFD7D356C101EB4998068767D9C259BE6C86A3BCE682C7BC05A8E6B32E106
|
||||
8E57374694C5EB4A928B5BC25AD17ED2A0FF9563ADFEE22DA5C5CB15896C8C08
|
||||
F4DF5C45823C2F3C590D6D962D0B46CB7442CFE1CE9930159E03C6D1B99A728E
|
||||
72B3D5150BD2BFF2411DC4C85673D29B22649FA2F7CD4309C2C3BEB834D44CF8
|
||||
51E14868A82570D2736DB6BDA6ADF110ABABC3982A1CD3F3107C9A4774DA2C49
|
||||
7AFC1EA6CFAD93CBD16D7C6783E425378405F4E45A1F4757C5703513B693B069
|
||||
944DD7315336FF24EC1D08211FF22DE40669C2D3F5D1F8C6907E6E0DD0F3024B9C536D32C4D4D1B05C0DA2AF139156BC
|
||||
F78DB3774E964AF6EA61A0E6CB6FA311A63777DD6C82E83CF1508A4845AD995A
|
||||
ADE6563483B98ABBA28FCC0AC6A6D046EBA57C28C9274938E47D07F78B3256B9
|
||||
717C322142EAD4B0160D208CAB0EC6062A79D4CE917C805757A8812E7E1BE2B4
|
||||
C6647C1643449A8E0A99F42AF0467376318FECE96EB11297EA6EC979CD50335B
|
||||
CAFDBBCA3A8DCE026E6C131435656FA5B2FE2AB7340D227D37C7318C498B3F0C
|
||||
F546BFA436AC20207F604E7634B6B30BBA4AA8047E7E72041FF023E9BFCA8D48219740033478EE52FC2CA9ED69F6B1AF
|
||||
E54DE969B061414A725483E3455923112462408DD43D221E7651F245DD9AECAA
|
||||
5E8A5BB037F8F6FF326190B9A3E6D5D0ED268D2F6EA77DAAE3E6FC2FC60AE46E
|
||||
5E4457C2A8CD8A9EC4EB16F674775D2F27AD91E7D0ED4A58E42F0C8FB2195F52
|
||||
E802E4FD33685950082F2CC510B5BD5D394FAADF7B88107F8C6BD1B30EFA5951
|
||||
A8C339432E43C41206417FE5C5341B6063D011EC682914247939000741A4325E
|
||||
97A26AAA3AA268F2271563B10173228C9CE67DE0872E7D6088B40D2B43599AA0
|
||||
452F34AA2ACB42D23BF801CBC2B9956C3DFED71B34672BA0D09D20CBC5B6AE5E
|
||||
AD473E39707EFECEC634A84099CF8BB05B9307390EAABFDF54901936E265F9EC
|
||||
E946D1047A519101DB2B4FA48939049E869D43E54AD34A2E314E67BA86D4D577
|
||||
7FCE70BF03798364ECD144909FB344FFC3C66A34AE5CBC230D970423A5412ED0
|
||||
0BF57416D2600E332F14737333A7FB7D8327B96B98F217B620B3080F61F2DFEB
|
||||
8D77033A47064B6D304C29E61FD3497CECE0CB0BE1305A0A5C418479FA142CA7
|
||||
ACDA2BB920997BF6BAA1BFFD1300BCDCE0117C81DBFAA986A2DD9820287D853E
|
||||
|
||||
121
applications/main/subghz/resources/subghz/assets/setting_user
Normal file
@@ -0,0 +1,121 @@
|
||||
# to use manual settings and prevent them from being deleted on upgrade, rename *_user.example files to *_user
|
||||
Filetype: Flipper SubGhz Setting File
|
||||
Version: 1
|
||||
# Add Standard frequencies included with firmware and place user frequencies after them
|
||||
#Add_standard_frequencies: false
|
||||
|
||||
# Default Frequency: used as default for "Read" and "Read Raw"
|
||||
#Default_frequency: 433920000
|
||||
|
||||
# Frequencies used for "Read", "Read Raw" and "Frequency Analyzer"
|
||||
Frequency: 300000000
|
||||
Frequency: 302757000
|
||||
Frequency: 303000000
|
||||
Frequency: 303875000
|
||||
Frequency: 303900000
|
||||
Frequency: 304250000
|
||||
Frequency: 307000000
|
||||
Frequency: 307500000
|
||||
Frequency: 307800000
|
||||
Frequency: 309000000
|
||||
Frequency: 310000000
|
||||
Frequency: 312000000
|
||||
Frequency: 312100000
|
||||
Frequency: 312200000
|
||||
Frequency: 313000000
|
||||
Frequency: 313850000
|
||||
Frequency: 314000000
|
||||
Frequency: 314350000
|
||||
Frequency: 314980000
|
||||
Frequency: 315000000
|
||||
Frequency: 318000000
|
||||
Frequency: 320000000
|
||||
Frequency: 320150000
|
||||
Frequency: 330000000
|
||||
Frequency: 345000000
|
||||
Frequency: 348000000
|
||||
Frequency: 350000000
|
||||
Frequency: 387000000
|
||||
Frequency: 390000000
|
||||
Frequency: 418000000
|
||||
Frequency: 430000000
|
||||
Frequency: 430500000
|
||||
Frequency: 431000000
|
||||
Frequency: 431500000
|
||||
Frequency: 433075000
|
||||
Frequency: 433220000
|
||||
Frequency: 433420000
|
||||
Frequency: 433657070
|
||||
Frequency: 433880000
|
||||
Frequency: 433889000
|
||||
Frequency: 433900000
|
||||
Frequency: 433910000
|
||||
Frequency: 433920000
|
||||
Frequency: 433930000
|
||||
Frequency: 433940000
|
||||
Frequency: 433950000
|
||||
Frequency: 433960000
|
||||
Frequency: 434075000
|
||||
Frequency: 434176948
|
||||
Frequency: 434190000
|
||||
Frequency: 434390000
|
||||
Frequency: 434420000
|
||||
Frequency: 434620000
|
||||
Frequency: 434775000
|
||||
Frequency: 438900000
|
||||
Frequency: 440175000
|
||||
Frequency: 462750000
|
||||
Frequency: 464000000
|
||||
Frequency: 467750000
|
||||
Frequency: 779000000
|
||||
Frequency: 868350000
|
||||
Frequency: 868400000
|
||||
Frequency: 868460000
|
||||
Frequency: 868800000
|
||||
Frequency: 868950000
|
||||
Frequency: 906400000
|
||||
Frequency: 915000000
|
||||
Frequency: 925000000
|
||||
Frequency: 928000000
|
||||
|
||||
# Frequencies used for hopping mode (keep this list small or flipper will miss signal)
|
||||
Hopper_frequency: 315000000
|
||||
Hopper_frequency: 433920000
|
||||
Hopper_frequency: 434420000
|
||||
Hopper_frequency: 868350000
|
||||
|
||||
# Presets used for preset hopping mode (cycles through these modulations)
|
||||
Hopping_Preset: AM650
|
||||
Hopping_Preset: FM476
|
||||
Hopping_Preset: FM95
|
||||
|
||||
# Custom preset
|
||||
# format for CC1101 "Custom_preset_data:" XX YY XX YY .. 00 00 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ, where: XX-register, YY - register data, 00 00 - end load register, ZZ - 8 byte Pa table register
|
||||
|
||||
Custom_preset_name: OOK_LR
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 07 04 08 32 0B 06 10 F8 11 32 12 30 14 00 15 00 18 18 19 16 1B 07 1C 00 1D B1 20 FB 21 B6 22 11 00 00 00 C0 00 00 00 00 00 00
|
||||
|
||||
Custom_preset_name: OOK_U
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 07 04 08 32 0B 06 10 F8 11 32 12 30 14 00 15 00 17 0C 18 18 19 16 1B 07 1C 00 1D B1 20 FB 21 B6 22 11 2C 81 2D 35 2E 09 00 00 00 C0 00 00 00 00 00 00
|
||||
|
||||
Custom_preset_name: AM_1
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 07 04 08 32 0B 06 10 C9 11 F8 12 30 14 00 15 14 18 18 19 16 1B 07 1C 00 1D 91 20 FB 21 55 22 00 00 00 00 C0 00 00 00 00 00 00
|
||||
|
||||
Custom_preset_name: FSK_1
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 03 47 08 32 0B 0C 10 C7 11 93 12 00 13 22 14 F8 15 35 18 18 19 1D 1B 04 1C 00 1D 92 20 FB 21 B6 22 17 00 00 12 0E 1D 34 60 84 C8 C0
|
||||
|
||||
Custom_preset_name: F3
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 03 47 08 32 0B 06 0C 00 0D 10 0D 0D 10 C5 11 83 12 80 13 22 14 F8 15 42 16 07 17 30 18 18 19 1D 1A 1C 1B 43 1C 40 1D 91 20 FB 21 B6 22 00 23 E9 24 2A 25 00 26 1F 2C 81 2D 35 2E 09 00 00 12 0E 1D 34 60 84 C8 C0
|
||||
|
||||
Custom_preset_name: FM95
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 07 04 08 32 0B 06 10 67 11 83 12 04 13 02 15 24 18 18 19 16 1B 07 1C 00 1D 91 20 FB 21 56 22 10 00 00 C0 00 00 00 00 00 00 00
|
||||
|
||||
Custom_preset_name: FM15k
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 03 47 08 32 0B 06 10 A7 11 32 12 00 13 00 14 00 15 32 18 18 19 1D 1B 04 1C 00 1D 92 20 FB 21 B6 22 17 00 00 00 12 0E 34 60 C5 C1 C0
|
||||
@@ -1,47 +0,0 @@
|
||||
# to use manual settings and prevent them from being deleted on upgrade, rename *_user.example files to *_user
|
||||
Filetype: Flipper SubGhz Setting File
|
||||
Version: 1
|
||||
# Add Standard frequencies included with firmware and place user frequencies after them
|
||||
#Add_standard_frequencies: true
|
||||
|
||||
# Default Frequency: used as default for "Read" and "Read Raw"
|
||||
#Default_frequency: 433920000
|
||||
|
||||
# Frequencies used for "Read", "Read Raw" and "Frequency Analyzer"
|
||||
#Frequency: 300000000
|
||||
#Frequency: 310000000
|
||||
#Frequency: 320000000
|
||||
|
||||
# Frequencies used for hopping mode (keep this list small or flipper will miss signal)
|
||||
#Hopper_frequency: 300000000
|
||||
#Hopper_frequency: 310000000
|
||||
#Hopper_frequency: 310000000
|
||||
|
||||
# Custom preset
|
||||
# format for CC1101 "Custom_preset_data:" XX YY XX YY .. 00 00 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ, where: XX-register, YY - register data, 00 00 - end load register, ZZ - 8 byte Pa table register
|
||||
|
||||
#Custom_preset_name: FM95
|
||||
#Custom_preset_module: CC1101
|
||||
#Custom_preset_data: 02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 83 10 67 15 24 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00
|
||||
|
||||
#2-FSK 200khz BW / 135kHz Filter/ 15.86Khz Deviation + Ramping
|
||||
#Custom_preset_name: FM15k
|
||||
#Custom_preset_module: CC1101
|
||||
#Custom_preset_data: 02 0D 03 47 08 32 0B 06 15 32 14 00 13 00 12 00 11 32 10 A7 18 18 19 1D 1D 92 1C 00 1B 04 20 FB 22 17 21 B6 00 00 00 12 0E 34 60 C5 C1 C0
|
||||
|
||||
#Custom_preset_name: Pagers
|
||||
#Custom_preset_module: CC1101
|
||||
#Custom_preset_data: 02 0D 07 04 08 32 0B 06 10 64 11 93 12 0C 13 02 14 00 15 15 18 18 19 16 1B 07 1C 00 1D 91 20 FB 21 56 22 10 00 00 C0 00 00 00 00 00 00 00
|
||||
|
||||
#Custom_preset_name: AM_1
|
||||
#Custom_preset_module: CC1101
|
||||
#Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00
|
||||
|
||||
#Custom_preset_name: AM_2
|
||||
#Custom_preset_module: CC1101
|
||||
#Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00
|
||||
|
||||
# Presets used for preset hopping mode (cycles through these modulations)
|
||||
#Hopping_Preset: AM650
|
||||
#Hopping_Preset: FM238
|
||||
#Hopping_Preset: FM476
|
||||
@@ -30,4 +30,7 @@ ADD_SCENE(subghz, protocol_list, ProtocolList)
|
||||
ADD_SCENE(subghz, keeloq_keys, KeeloqKeys)
|
||||
ADD_SCENE(subghz, keeloq_key_edit, KeeloqKeyEdit)
|
||||
ADD_SCENE(subghz, psa_decrypt, PsaDecrypt)
|
||||
ADD_SCENE(subghz, keeloq_decrypt, KeeloqDecrypt)
|
||||
ADD_SCENE(subghz, keeloq_bf2, KeeloqBf2)
|
||||
ADD_SCENE(subghz, kl_bf_cleanup, KlBfCleanup)
|
||||
ADD_SCENE(subghz, counter_bf, CounterBf)
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
#define TAG "SubGhzCounterBf"
|
||||
|
||||
// How many ticks to wait between transmissions (1 tick ~100ms)
|
||||
#define COUNTER_BF_TX_INTERVAL_TICKS 3
|
||||
#define COUNTER_BF_TX_INTERVAL_TICKS 5
|
||||
|
||||
typedef enum {
|
||||
CounterBfStateWarning,
|
||||
CounterBfStateIdle,
|
||||
CounterBfStateRunning,
|
||||
CounterBfStateStopped,
|
||||
@@ -22,8 +23,16 @@ typedef struct {
|
||||
uint32_t tick_wait;
|
||||
} CounterBfContext;
|
||||
|
||||
#define CounterBfEventStart (0xC0)
|
||||
#define CounterBfEventStop (0xC1)
|
||||
#define CounterBfEventStart (0xC0)
|
||||
#define CounterBfEventStop (0xC1)
|
||||
#define CounterBfEventWarningOk (0xC2)
|
||||
|
||||
static void counter_bf_warning_callback(GuiButtonType result, InputType type, void* context) {
|
||||
SubGhz* subghz = context;
|
||||
if(result == GuiButtonTypeCenter && type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, CounterBfEventWarningOk);
|
||||
}
|
||||
}
|
||||
|
||||
static void counter_bf_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
SubGhz* subghz = context;
|
||||
@@ -32,18 +41,36 @@ static void counter_bf_widget_callback(GuiButtonType result, InputType type, voi
|
||||
}
|
||||
}
|
||||
|
||||
static void counter_bf_draw_warning(SubGhz* subghz) {
|
||||
widget_reset(subghz->widget);
|
||||
widget_add_string_multiline_element(
|
||||
subghz->widget,
|
||||
64,
|
||||
20,
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
FontSecondary,
|
||||
"WARNING:\nThis may desync\nyour fob!");
|
||||
widget_add_button_element(
|
||||
subghz->widget,
|
||||
GuiButtonTypeCenter,
|
||||
"OK",
|
||||
counter_bf_warning_callback,
|
||||
subghz);
|
||||
}
|
||||
|
||||
static void counter_bf_draw(SubGhz* subghz, CounterBfContext* ctx) {
|
||||
widget_reset(subghz->widget);
|
||||
FuriString* str = furi_string_alloc();
|
||||
furi_string_printf(
|
||||
str,
|
||||
"Counter BruteForce\n"
|
||||
"Cnt: 0x%08lX\n"
|
||||
"Sent: %lu pkts\n"
|
||||
"Start: 0x%08lX",
|
||||
ctx->current_cnt,
|
||||
ctx->packets_sent,
|
||||
ctx->start_cnt);
|
||||
"Cnt: 0x%06lX\n"
|
||||
"Start: 0x%06lX\n"
|
||||
"Sent: %lu",
|
||||
ctx->current_cnt & 0xFFFFFF,
|
||||
ctx->start_cnt & 0xFFFFFF,
|
||||
ctx->packets_sent);
|
||||
widget_add_string_multiline_element(
|
||||
subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(str));
|
||||
furi_string_free(str);
|
||||
@@ -57,14 +84,12 @@ static void counter_bf_draw(SubGhz* subghz, CounterBfContext* ctx) {
|
||||
}
|
||||
|
||||
static void counter_bf_save(SubGhz* subghz, CounterBfContext* ctx) {
|
||||
// Escribir el Cnt final directamente en el archivo .sub en disco.
|
||||
// No usar subghz_save_protocol_to_file() porque ese serializa el estado
|
||||
// actual del encoder (que puede tener el Cnt ya incrementado internamente).
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* file_fff = flipper_format_buffered_file_alloc(storage);
|
||||
if(flipper_format_buffered_file_open_existing(
|
||||
file_fff, furi_string_get_cstr(subghz->file_path))) {
|
||||
if(!flipper_format_update_uint32(file_fff, "Cnt", &ctx->current_cnt, 1)) {
|
||||
uint32_t cnt = ctx->current_cnt & 0xFFFFFF;
|
||||
if(!flipper_format_update_uint32(file_fff, "Cnt", &cnt, 1)) {
|
||||
FURI_LOG_E(TAG, "Failed to update Cnt in .sub file");
|
||||
}
|
||||
} else {
|
||||
@@ -77,16 +102,15 @@ static void counter_bf_save(SubGhz* subghz, CounterBfContext* ctx) {
|
||||
static void counter_bf_send(SubGhz* subghz, CounterBfContext* ctx) {
|
||||
subghz_txrx_stop(subghz->txrx);
|
||||
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
uint32_t delta = (ctx->current_cnt - ctx->start_cnt) & 0xFFFFFF;
|
||||
furi_hal_subghz_set_rolling_counter_mult((int32_t)delta);
|
||||
subghz_block_generic_global_counter_override_set(ctx->current_cnt & 0xFFFFFF);
|
||||
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
uint32_t repeat = 20;
|
||||
flipper_format_rewind(fff);
|
||||
flipper_format_update_uint32(fff, "Repeat", &repeat, 1);
|
||||
|
||||
// Actualizar Cnt DESPUES de Repeat (update es secuencial en el buffer)
|
||||
flipper_format_rewind(fff);
|
||||
flipper_format_update_uint32(fff, "Cnt", &ctx->current_cnt, 1);
|
||||
|
||||
subghz_tx_start(subghz, fff);
|
||||
|
||||
ctx->packets_sent++;
|
||||
@@ -98,42 +122,38 @@ void subghz_scene_counter_bf_on_enter(void* context) {
|
||||
|
||||
CounterBfContext* ctx = malloc(sizeof(CounterBfContext));
|
||||
memset(ctx, 0, sizeof(CounterBfContext));
|
||||
ctx->state = CounterBfStateIdle;
|
||||
ctx->state = CounterBfStateWarning;
|
||||
ctx->step = 1;
|
||||
furi_hal_subghz_set_rolling_counter_mult(0);
|
||||
subghz_key_load(subghz, furi_string_get_cstr(subghz->file_path), false);
|
||||
|
||||
// FIX: Leer el Cnt DIRECTAMENTE del archivo en disco con un FlipperFormat
|
||||
// propio, completamente separado del fff en memoria (que puede tener el Cnt
|
||||
// modificado por TXs previas y no refleja el estado real del .sub).
|
||||
{
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* file_fff = flipper_format_buffered_file_alloc(storage);
|
||||
if(flipper_format_buffered_file_open_existing(
|
||||
file_fff, furi_string_get_cstr(subghz->file_path))) {
|
||||
uint32_t cnt = 0;
|
||||
if(flipper_format_read_uint32(file_fff, "Cnt", &cnt, 1)) {
|
||||
ctx->current_cnt = cnt;
|
||||
ctx->start_cnt = cnt;
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Cnt field not found in file");
|
||||
}
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
flipper_format_rewind(fff);
|
||||
uint32_t cnt = 0;
|
||||
if(flipper_format_read_uint32(fff, "Cnt", &cnt, 1)) {
|
||||
ctx->current_cnt = cnt & 0xFFFFFF;
|
||||
ctx->start_cnt = cnt & 0xFFFFFF;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to open .sub file for Cnt read");
|
||||
FURI_LOG_W(TAG, "Cnt not in fff after key_load, reading from disk");
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* file_fff = flipper_format_buffered_file_alloc(storage);
|
||||
if(flipper_format_buffered_file_open_existing(
|
||||
file_fff, furi_string_get_cstr(subghz->file_path))) {
|
||||
if(flipper_format_read_uint32(file_fff, "Cnt", &cnt, 1)) {
|
||||
ctx->current_cnt = cnt & 0xFFFFFF;
|
||||
ctx->start_cnt = cnt & 0xFFFFFF;
|
||||
}
|
||||
}
|
||||
flipper_format_free(file_fff);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
flipper_format_free(file_fff);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneCounterBf, (uint32_t)(uintptr_t)ctx);
|
||||
|
||||
// Deshabilitar auto-increment del protocolo para controlar el Cnt manualmente
|
||||
furi_hal_subghz_set_rolling_counter_mult(0);
|
||||
|
||||
// Recargar el protocolo DESPUES de haber leído el Cnt del disco,
|
||||
// para preparar el fff para TX sin que pise nuestro valor leído.
|
||||
subghz_key_load(subghz, furi_string_get_cstr(subghz->file_path), false);
|
||||
|
||||
counter_bf_draw(subghz, ctx);
|
||||
counter_bf_draw_warning(subghz);
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget);
|
||||
}
|
||||
|
||||
@@ -144,15 +164,21 @@ bool subghz_scene_counter_bf_on_event(void* context, SceneManagerEvent event) {
|
||||
if(!ctx) return false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == CounterBfEventWarningOk) {
|
||||
ctx->state = CounterBfStateIdle;
|
||||
counter_bf_draw(subghz, ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(event.event == CounterBfEventStart) {
|
||||
if(ctx->state == CounterBfStateWarning) return true;
|
||||
|
||||
if(ctx->state != CounterBfStateRunning) {
|
||||
ctx->state = CounterBfStateRunning;
|
||||
ctx->tick_wait = 0;
|
||||
subghz->state_notifications = SubGhzNotificationStateTx;
|
||||
counter_bf_send(subghz, ctx);
|
||||
} else {
|
||||
// FIX 2: Al detener, guardar el contador actual en el .sub
|
||||
// para que al volver a emular manualmente continúe desde acá.
|
||||
ctx->state = CounterBfStateStopped;
|
||||
subghz_txrx_stop(subghz->txrx);
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
@@ -167,19 +193,24 @@ bool subghz_scene_counter_bf_on_event(void* context, SceneManagerEvent event) {
|
||||
if(ctx->tick_wait > 0) {
|
||||
ctx->tick_wait--;
|
||||
} else {
|
||||
ctx->current_cnt += ctx->step;
|
||||
ctx->current_cnt = (ctx->current_cnt + ctx->step) & 0xFFFFFF;
|
||||
counter_bf_send(subghz, ctx);
|
||||
counter_bf_save(subghz, ctx);
|
||||
counter_bf_draw(subghz, ctx);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
if(ctx->state == CounterBfStateWarning) {
|
||||
furi_hal_subghz_set_rolling_counter_mult(1);
|
||||
free(ctx);
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
return true;
|
||||
}
|
||||
|
||||
subghz_txrx_stop(subghz->txrx);
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
|
||||
// FIX 2 (también en Back): guardar siempre al salir
|
||||
counter_bf_save(subghz, ctx);
|
||||
|
||||
furi_hal_subghz_set_rolling_counter_mult(1);
|
||||
free(ctx);
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
|
||||
257
applications/main/subghz/scenes/subghz_scene_keeloq_bf2.c
Normal file
@@ -0,0 +1,257 @@
|
||||
#include "../subghz_i.h"
|
||||
#include <lib/subghz/protocols/keeloq.h>
|
||||
#include <lib/subghz/blocks/math.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
enum {
|
||||
KlBf2IndexLoadSig1,
|
||||
KlBf2IndexLoadSig2,
|
||||
KlBf2IndexType,
|
||||
KlBf2IndexStartBf,
|
||||
};
|
||||
|
||||
static const char* kl_bf2_type_labels[] = {
|
||||
"Type: Auto (6>7>8)",
|
||||
"Type: 6 (Serial 1)",
|
||||
"Type: 7 (Serial 2)",
|
||||
"Type: 8 (Serial 3)",
|
||||
};
|
||||
static const uint8_t kl_bf2_type_values[] = {0, 6, 7, 8};
|
||||
|
||||
static bool kl_bf2_extract_key(SubGhz* subghz, uint32_t* out_fix, uint32_t* out_hop) {
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
flipper_format_rewind(fff);
|
||||
uint8_t key_data[8] = {0};
|
||||
if(!flipper_format_read_hex(fff, "Key", key_data, 8)) return false;
|
||||
uint64_t raw = 0;
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
raw = (raw << 8) | key_data[i];
|
||||
}
|
||||
uint64_t reversed = subghz_protocol_blocks_reverse_key(raw, 64);
|
||||
*out_fix = (uint32_t)(reversed >> 32);
|
||||
*out_hop = (uint32_t)(reversed & 0xFFFFFFFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool kl_bf2_is_keeloq(SubGhz* subghz) {
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
flipper_format_rewind(fff);
|
||||
FuriString* proto = furi_string_alloc();
|
||||
bool ok = flipper_format_read_string(fff, "Protocol", proto) &&
|
||||
furi_string_equal_str(proto, "KeeLoq");
|
||||
furi_string_free(proto);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void kl_bf2_submenu_callback(void* context, uint32_t index) {
|
||||
SubGhz* subghz = context;
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, index);
|
||||
}
|
||||
|
||||
static bool kl_bf2_load_signal(SubGhz* subghz, FuriString* out_path) {
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(
|
||||
&browser_options, SUBGHZ_APP_FILENAME_EXTENSION, &I_sub1_10px);
|
||||
browser_options.base_path = SUBGHZ_APP_FOLDER;
|
||||
|
||||
FuriString* selected = furi_string_alloc();
|
||||
furi_string_set(selected, SUBGHZ_APP_FOLDER);
|
||||
|
||||
bool res = dialog_file_browser_show(subghz->dialogs, selected, selected, &browser_options);
|
||||
|
||||
if(res) {
|
||||
res = subghz_key_load(subghz, furi_string_get_cstr(selected), true);
|
||||
if(res) {
|
||||
furi_string_set(out_path, selected);
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_free(selected);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void kl_bf2_rebuild_menu(SubGhz* subghz) {
|
||||
submenu_reset(subghz->submenu);
|
||||
|
||||
char label1[64];
|
||||
char label2[64];
|
||||
|
||||
if(subghz->keeloq_bf2.sig1_loaded) {
|
||||
FuriString* name = furi_string_alloc();
|
||||
path_extract_filename(subghz->keeloq_bf2.sig1_path, name, true);
|
||||
snprintf(label1, sizeof(label1), "Sig 1: %s", furi_string_get_cstr(name));
|
||||
furi_string_free(name);
|
||||
} else {
|
||||
snprintf(label1, sizeof(label1), "Load Signal 1");
|
||||
}
|
||||
|
||||
if(subghz->keeloq_bf2.sig2_loaded) {
|
||||
FuriString* name = furi_string_alloc();
|
||||
path_extract_filename(subghz->keeloq_bf2.sig2_path, name, true);
|
||||
snprintf(label2, sizeof(label2), "Sig 2: %s", furi_string_get_cstr(name));
|
||||
furi_string_free(name);
|
||||
} else {
|
||||
snprintf(label2, sizeof(label2), "Load Signal 2");
|
||||
}
|
||||
|
||||
submenu_add_item(
|
||||
subghz->submenu, label1, KlBf2IndexLoadSig1,
|
||||
kl_bf2_submenu_callback, subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu, label2, KlBf2IndexLoadSig2,
|
||||
kl_bf2_submenu_callback, subghz);
|
||||
|
||||
int type_idx = 0;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(kl_bf2_type_values[i] == subghz->keeloq_bf2.learn_type) {
|
||||
type_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
submenu_add_item(
|
||||
subghz->submenu, kl_bf2_type_labels[type_idx], KlBf2IndexType,
|
||||
kl_bf2_submenu_callback, subghz);
|
||||
|
||||
if(subghz->keeloq_bf2.sig1_loaded && subghz->keeloq_bf2.sig2_loaded) {
|
||||
submenu_add_item(
|
||||
subghz->submenu, "Start BF", KlBf2IndexStartBf,
|
||||
kl_bf2_submenu_callback, subghz);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdMenu);
|
||||
}
|
||||
|
||||
void subghz_scene_keeloq_bf2_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
subghz->keeloq_bf2.sig1_loaded = false;
|
||||
subghz->keeloq_bf2.sig2_loaded = false;
|
||||
subghz->keeloq_bf2.learn_type = 0;
|
||||
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
}
|
||||
|
||||
bool subghz_scene_keeloq_bf2_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == KlBf2IndexLoadSig1) {
|
||||
FuriString* path = furi_string_alloc();
|
||||
if(kl_bf2_load_signal(subghz, path)) {
|
||||
if(!kl_bf2_is_keeloq(subghz)) {
|
||||
dialog_message_show_storage_error(
|
||||
subghz->dialogs, "Not a KeeLoq\nprotocol file");
|
||||
furi_string_free(path);
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t fix, hop;
|
||||
if(!kl_bf2_extract_key(subghz, &fix, &hop)) {
|
||||
dialog_message_show_storage_error(
|
||||
subghz->dialogs, "Cannot read Key\nfrom file");
|
||||
furi_string_free(path);
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
}
|
||||
|
||||
subghz->keeloq_bf2.fix = fix;
|
||||
subghz->keeloq_bf2.hop1 = hop;
|
||||
subghz->keeloq_bf2.serial = fix & 0x0FFFFFFF;
|
||||
subghz->keeloq_bf2.sig1_loaded = true;
|
||||
furi_string_set(subghz->keeloq_bf2.sig1_path, path);
|
||||
|
||||
subghz->keeloq_bf2.sig2_loaded = false;
|
||||
}
|
||||
furi_string_free(path);
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
|
||||
} else if(event.event == KlBf2IndexLoadSig2) {
|
||||
if(!subghz->keeloq_bf2.sig1_loaded) {
|
||||
dialog_message_show_storage_error(
|
||||
subghz->dialogs, "Load Signal 1 first");
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
}
|
||||
|
||||
FuriString* path = furi_string_alloc();
|
||||
if(kl_bf2_load_signal(subghz, path)) {
|
||||
if(!kl_bf2_is_keeloq(subghz)) {
|
||||
dialog_message_show_storage_error(
|
||||
subghz->dialogs, "Not a KeeLoq\nprotocol file");
|
||||
furi_string_free(path);
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t fix2, hop2;
|
||||
if(!kl_bf2_extract_key(subghz, &fix2, &hop2)) {
|
||||
dialog_message_show_storage_error(
|
||||
subghz->dialogs, "Cannot read Key\nfrom file");
|
||||
furi_string_free(path);
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t serial2 = fix2 & 0x0FFFFFFF;
|
||||
if(serial2 != subghz->keeloq_bf2.serial) {
|
||||
dialog_message_show_storage_error(
|
||||
subghz->dialogs, "Serial mismatch!\nMust be same remote");
|
||||
furi_string_free(path);
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(hop2 == subghz->keeloq_bf2.hop1) {
|
||||
dialog_message_show_storage_error(
|
||||
subghz->dialogs, "Same hop code!\nUse a different\ncapture");
|
||||
furi_string_free(path);
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
}
|
||||
|
||||
subghz->keeloq_bf2.hop2 = hop2;
|
||||
subghz->keeloq_bf2.sig2_loaded = true;
|
||||
furi_string_set(subghz->keeloq_bf2.sig2_path, path);
|
||||
}
|
||||
furi_string_free(path);
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
|
||||
} else if(event.event == KlBf2IndexType) {
|
||||
uint8_t cur = subghz->keeloq_bf2.learn_type;
|
||||
if(cur == 0) cur = 6;
|
||||
else if(cur == 6) cur = 7;
|
||||
else if(cur == 7) cur = 8;
|
||||
else cur = 0;
|
||||
subghz->keeloq_bf2.learn_type = cur;
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
|
||||
} else if(event.event == KlBf2IndexStartBf) {
|
||||
if(!subghz->keeloq_bf2.sig1_loaded || !subghz->keeloq_bf2.sig2_loaded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!subghz_key_load(
|
||||
subghz,
|
||||
furi_string_get_cstr(subghz->keeloq_bf2.sig1_path),
|
||||
true)) {
|
||||
dialog_message_show_storage_error(
|
||||
subghz->dialogs, "Cannot reload\nSignal 1");
|
||||
kl_bf2_rebuild_menu(subghz);
|
||||
return true;
|
||||
}
|
||||
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneKeeloqDecrypt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void subghz_scene_keeloq_bf2_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
submenu_reset(subghz->submenu);
|
||||
}
|
||||
299
applications/main/subghz/scenes/subghz_scene_keeloq_decrypt.c
Normal file
@@ -0,0 +1,299 @@
|
||||
#include "../subghz_i.h"
|
||||
#include "../helpers/subghz_txrx_i.h"
|
||||
#include <lib/subghz/protocols/keeloq.h>
|
||||
#include <lib/subghz/protocols/keeloq_common.h>
|
||||
#include <lib/subghz/blocks/math.h>
|
||||
#include <lib/subghz/environment.h>
|
||||
#include <lib/subghz/subghz_keystore.h>
|
||||
#include <furi.h>
|
||||
#include <bt/bt_service/bt.h>
|
||||
|
||||
#define KL_DECRYPT_EVENT_DONE (0xD2)
|
||||
#define KL_DECRYPT_EVENT_CANDIDATE (0xD3)
|
||||
#define KL_TOTAL_KEYS 0x100000000ULL
|
||||
|
||||
#define KL_MSG_BF_REQUEST 0x10
|
||||
#define KL_MSG_BF_PROGRESS 0x11
|
||||
#define KL_MSG_BF_RESULT 0x12
|
||||
#define KL_MSG_BF_CANCEL 0x13
|
||||
|
||||
typedef struct {
|
||||
SubGhz* subghz;
|
||||
volatile bool cancel;
|
||||
uint32_t start_tick;
|
||||
bool success;
|
||||
FuriString* result;
|
||||
|
||||
uint32_t fix;
|
||||
uint32_t hop;
|
||||
uint32_t serial;
|
||||
uint8_t btn;
|
||||
uint16_t disc;
|
||||
|
||||
uint32_t hop2;
|
||||
|
||||
uint32_t candidate_count;
|
||||
uint64_t recovered_mfkey;
|
||||
uint16_t recovered_type;
|
||||
uint32_t recovered_cnt;
|
||||
|
||||
bool ble_offload;
|
||||
} KlDecryptCtx;
|
||||
|
||||
static void kl_ble_data_received(uint8_t* data, uint16_t size, void* context) {
|
||||
KlDecryptCtx* ctx = context;
|
||||
if(size < 1 || ctx->cancel) return;
|
||||
|
||||
if(data[0] == KL_MSG_BF_PROGRESS && size >= 10) {
|
||||
uint32_t keys_tested, keys_per_sec;
|
||||
memcpy(&keys_tested, data + 2, 4);
|
||||
memcpy(&keys_per_sec, data + 6, 4);
|
||||
|
||||
uint32_t elapsed_sec = (furi_get_tick() - ctx->start_tick) / 1000;
|
||||
uint32_t remaining = (keys_tested > 0) ? (0xFFFFFFFFU - keys_tested) : 0xFFFFFFFFU;
|
||||
uint32_t eta_sec = (keys_per_sec > 0) ? (remaining / keys_per_sec) : 0;
|
||||
uint8_t pct = (uint8_t)((uint64_t)keys_tested * 100 / 0xFFFFFFFFULL);
|
||||
|
||||
subghz_view_keeloq_decrypt_update_stats(
|
||||
ctx->subghz->subghz_keeloq_decrypt, pct, keys_tested, keys_per_sec, elapsed_sec, eta_sec);
|
||||
|
||||
} else if(data[0] == KL_MSG_BF_RESULT && size >= 26) {
|
||||
uint8_t found = data[1];
|
||||
|
||||
if(found == 1) {
|
||||
uint64_t mfkey = 0;
|
||||
uint32_t cnt = 0;
|
||||
memcpy(&mfkey, data + 2, 8);
|
||||
memcpy(&cnt, data + 18, 4);
|
||||
uint16_t learn_type = (size >= 27) ? data[26] : 6;
|
||||
|
||||
ctx->candidate_count++;
|
||||
ctx->recovered_mfkey = mfkey;
|
||||
ctx->recovered_type = learn_type;
|
||||
ctx->recovered_cnt = cnt;
|
||||
|
||||
subghz_view_keeloq_decrypt_update_candidates(
|
||||
ctx->subghz->subghz_keeloq_decrypt, ctx->candidate_count);
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
ctx->subghz->view_dispatcher, KL_DECRYPT_EVENT_CANDIDATE);
|
||||
|
||||
} else if(found == 2) {
|
||||
ctx->success = (ctx->candidate_count > 0);
|
||||
view_dispatcher_send_custom_event(
|
||||
ctx->subghz->view_dispatcher, KL_DECRYPT_EVENT_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void kl_ble_cleanup(KlDecryptCtx* ctx) {
|
||||
if(!ctx->ble_offload) return;
|
||||
Bt* bt = furi_record_open(RECORD_BT);
|
||||
bt_set_custom_data_callback(bt, NULL, NULL);
|
||||
furi_record_close(RECORD_BT);
|
||||
ctx->ble_offload = false;
|
||||
}
|
||||
|
||||
static bool kl_ble_start_offload(KlDecryptCtx* ctx) {
|
||||
Bt* bt = furi_record_open(RECORD_BT);
|
||||
if(!bt_is_connected(bt)) {
|
||||
furi_record_close(RECORD_BT);
|
||||
return false;
|
||||
}
|
||||
|
||||
bt_set_custom_data_callback(bt, kl_ble_data_received, ctx);
|
||||
|
||||
uint8_t req[18];
|
||||
req[0] = KL_MSG_BF_REQUEST;
|
||||
req[1] = ctx->subghz->keeloq_bf2.learn_type;
|
||||
memcpy(req + 2, &ctx->fix, 4);
|
||||
memcpy(req + 6, &ctx->hop, 4);
|
||||
memcpy(req + 10, &ctx->hop2, 4);
|
||||
memcpy(req + 14, &ctx->serial, 4);
|
||||
bt_custom_data_tx(bt, req, sizeof(req));
|
||||
|
||||
furi_record_close(RECORD_BT);
|
||||
ctx->ble_offload = true;
|
||||
|
||||
subghz_view_keeloq_decrypt_set_status(
|
||||
ctx->subghz->subghz_keeloq_decrypt, "[BT] Offloading...");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void kl_decrypt_view_callback(SubGhzCustomEvent event, void* context) {
|
||||
SubGhz* subghz = context;
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void subghz_scene_keeloq_decrypt_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
KlDecryptCtx* ctx = malloc(sizeof(KlDecryptCtx));
|
||||
memset(ctx, 0, sizeof(KlDecryptCtx));
|
||||
ctx->subghz = subghz;
|
||||
ctx->result = furi_string_alloc_set("No result");
|
||||
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
flipper_format_rewind(fff);
|
||||
|
||||
uint8_t key_data[8] = {0};
|
||||
if(flipper_format_read_hex(fff, "Key", key_data, 8)) {
|
||||
uint64_t raw = 0;
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
raw = (raw << 8) | key_data[i];
|
||||
}
|
||||
uint64_t reversed = subghz_protocol_blocks_reverse_key(raw, 64);
|
||||
ctx->fix = (uint32_t)(reversed >> 32);
|
||||
ctx->hop = (uint32_t)(reversed & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
ctx->serial = ctx->fix & 0x0FFFFFFF;
|
||||
ctx->btn = ctx->fix >> 28;
|
||||
ctx->disc = ctx->serial & 0x3FF;
|
||||
ctx->hop2 = subghz->keeloq_bf2.sig2_loaded ? subghz->keeloq_bf2.hop2 : 0;
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneKeeloqDecrypt, (uint32_t)(uintptr_t)ctx);
|
||||
|
||||
subghz_view_keeloq_decrypt_reset(subghz->subghz_keeloq_decrypt);
|
||||
subghz_view_keeloq_decrypt_set_callback(
|
||||
subghz->subghz_keeloq_decrypt, kl_decrypt_view_callback, subghz);
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdKeeloqDecrypt);
|
||||
|
||||
ctx->start_tick = furi_get_tick();
|
||||
|
||||
if(!kl_ble_start_offload(ctx)) {
|
||||
char msg[128];
|
||||
snprintf(msg, sizeof(msg),
|
||||
"No BLE connection!\n"
|
||||
"Connect companion app\n"
|
||||
"and try again.\n\n"
|
||||
"Fix:0x%08lX\nHop:0x%08lX",
|
||||
ctx->fix, ctx->hop);
|
||||
subghz_view_keeloq_decrypt_set_result(
|
||||
subghz->subghz_keeloq_decrypt, false, msg);
|
||||
}
|
||||
}
|
||||
|
||||
bool subghz_scene_keeloq_decrypt_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
KlDecryptCtx* ctx = (KlDecryptCtx*)(uintptr_t)scene_manager_get_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneKeeloqDecrypt);
|
||||
if(!ctx) return false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == KL_DECRYPT_EVENT_CANDIDATE) {
|
||||
if(!subghz->keeloq_keys_manager) {
|
||||
subghz->keeloq_keys_manager = subghz_keeloq_keys_alloc();
|
||||
}
|
||||
char key_name[24];
|
||||
snprintf(key_name, sizeof(key_name), "BF_%07lX", ctx->serial);
|
||||
subghz_keeloq_keys_add(
|
||||
subghz->keeloq_keys_manager,
|
||||
ctx->recovered_mfkey,
|
||||
KEELOQ_LEARNING_SIMPLE,
|
||||
key_name);
|
||||
subghz_keeloq_keys_save(subghz->keeloq_keys_manager);
|
||||
|
||||
SubGhzKeystore* env_ks = subghz_environment_get_keystore(
|
||||
subghz->txrx->environment);
|
||||
SubGhzKeyArray_t* env_arr = subghz_keystore_get_data(env_ks);
|
||||
SubGhzKey* entry = SubGhzKeyArray_push_raw(*env_arr);
|
||||
entry->name = furi_string_alloc_set(key_name);
|
||||
entry->key = ctx->recovered_mfkey;
|
||||
entry->type = KEELOQ_LEARNING_SIMPLE;
|
||||
return true;
|
||||
|
||||
} else if(event.event == KL_DECRYPT_EVENT_DONE) {
|
||||
kl_ble_cleanup(ctx);
|
||||
subghz->keeloq_bf2.sig1_loaded = false;
|
||||
subghz->keeloq_bf2.sig2_loaded = false;
|
||||
|
||||
if(ctx->success) {
|
||||
furi_string_printf(
|
||||
ctx->result,
|
||||
"Found %lu candidate(s)\n"
|
||||
"Last: %08lX%08lX\n"
|
||||
"Type:%u Cnt:%04lX\n"
|
||||
"Saved to user keys",
|
||||
ctx->candidate_count,
|
||||
(uint32_t)(ctx->recovered_mfkey >> 32),
|
||||
(uint32_t)(ctx->recovered_mfkey & 0xFFFFFFFF),
|
||||
ctx->recovered_type,
|
||||
ctx->recovered_cnt);
|
||||
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
flipper_format_rewind(fff);
|
||||
|
||||
char mf_str[20];
|
||||
snprintf(mf_str, sizeof(mf_str), "BF_%07lX", ctx->serial);
|
||||
flipper_format_insert_or_update_string_cstr(fff, "Manufacture", mf_str);
|
||||
|
||||
uint32_t cnt_val = ctx->recovered_cnt;
|
||||
flipper_format_rewind(fff);
|
||||
flipper_format_insert_or_update_uint32(fff, "Cnt", &cnt_val, 1);
|
||||
|
||||
if(ctx->hop2 != 0) {
|
||||
flipper_format_rewind(fff);
|
||||
flipper_format_insert_or_update_uint32(fff, "Hop2", &ctx->hop2, 1);
|
||||
}
|
||||
|
||||
flipper_format_rewind(fff);
|
||||
subghz_protocol_decoder_base_deserialize(
|
||||
subghz_txrx_get_decoder(subghz->txrx), fff);
|
||||
|
||||
const char* save_path = NULL;
|
||||
if(subghz_path_is_file(subghz->file_path)) {
|
||||
save_path = furi_string_get_cstr(subghz->file_path);
|
||||
} else if(subghz_path_is_file(subghz->keeloq_bf2.sig1_path)) {
|
||||
save_path = furi_string_get_cstr(subghz->keeloq_bf2.sig1_path);
|
||||
}
|
||||
if(save_path) {
|
||||
subghz_save_protocol_to_file(
|
||||
subghz,
|
||||
subghz_txrx_get_fff_data(subghz->txrx),
|
||||
save_path);
|
||||
furi_string_set_str(subghz->file_path, save_path);
|
||||
}
|
||||
|
||||
subghz_view_keeloq_decrypt_set_result(
|
||||
subghz->subghz_keeloq_decrypt, true, furi_string_get_cstr(ctx->result));
|
||||
} else if(!ctx->cancel) {
|
||||
subghz_view_keeloq_decrypt_set_result(
|
||||
subghz->subghz_keeloq_decrypt, false,
|
||||
"Key NOT found.\nNo matching key in\n2^32 search space.");
|
||||
} else {
|
||||
subghz_view_keeloq_decrypt_set_result(
|
||||
subghz->subghz_keeloq_decrypt, false, "Cancelled.");
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if(event.event == SubGhzCustomEventViewTransmitterBack) {
|
||||
if(ctx->ble_offload) {
|
||||
Bt* bt = furi_record_open(RECORD_BT);
|
||||
uint8_t cancel_msg = KL_MSG_BF_CANCEL;
|
||||
bt_custom_data_tx(bt, &cancel_msg, 1);
|
||||
furi_record_close(RECORD_BT);
|
||||
}
|
||||
ctx->cancel = true;
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void subghz_scene_keeloq_decrypt_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
KlDecryptCtx* ctx = (KlDecryptCtx*)(uintptr_t)scene_manager_get_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneKeeloqDecrypt);
|
||||
|
||||
if(ctx) {
|
||||
kl_ble_cleanup(ctx);
|
||||
ctx->cancel = true;
|
||||
furi_string_free(ctx->result);
|
||||
free(ctx);
|
||||
scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneKeeloqDecrypt, 0);
|
||||
}
|
||||
}
|
||||
141
applications/main/subghz/scenes/subghz_scene_kl_bf_cleanup.c
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "../subghz_i.h"
|
||||
#include <lib/subghz/protocols/keeloq_common.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t serial;
|
||||
uint32_t fix;
|
||||
uint32_t hop;
|
||||
uint32_t hop2;
|
||||
uint8_t btn;
|
||||
uint16_t disc;
|
||||
size_t bf_indices[32];
|
||||
size_t bf_count;
|
||||
size_t valid_indices[32];
|
||||
size_t valid_count;
|
||||
} KlCleanupCtx;
|
||||
|
||||
static bool kl_cleanup_validate_hop(uint64_t key, uint32_t hop, uint8_t btn, uint16_t disc) {
|
||||
uint32_t dec = subghz_protocol_keeloq_common_decrypt(hop, key);
|
||||
if((dec >> 28) != btn) return false;
|
||||
uint16_t dec_disc = (dec >> 16) & 0x3FF;
|
||||
if(dec_disc == disc) return true;
|
||||
if((dec_disc & 0xFF) == (disc & 0xFF)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool kl_cleanup_validate_key(uint64_t key, uint32_t hop1, uint32_t hop2, uint8_t btn, uint16_t disc) {
|
||||
if(!kl_cleanup_validate_hop(key, hop1, btn, disc)) return false;
|
||||
if(hop2 == 0) return true;
|
||||
if(!kl_cleanup_validate_hop(key, hop2, btn, disc)) return false;
|
||||
uint32_t dec1 = subghz_protocol_keeloq_common_decrypt(hop1, key);
|
||||
uint32_t dec2 = subghz_protocol_keeloq_common_decrypt(hop2, key);
|
||||
uint16_t cnt1 = dec1 & 0xFFFF;
|
||||
uint16_t cnt2 = dec2 & 0xFFFF;
|
||||
int diff = (int)cnt2 - (int)cnt1;
|
||||
return (diff >= 1 && diff <= 256);
|
||||
}
|
||||
|
||||
void subghz_scene_kl_bf_cleanup_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
KlCleanupCtx* ctx = malloc(sizeof(KlCleanupCtx));
|
||||
memset(ctx, 0, sizeof(KlCleanupCtx));
|
||||
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
flipper_format_rewind(fff);
|
||||
|
||||
uint8_t key_data[8] = {0};
|
||||
if(flipper_format_read_hex(fff, "Key", key_data, 8)) {
|
||||
ctx->fix = ((uint32_t)key_data[0] << 24) | ((uint32_t)key_data[1] << 16) |
|
||||
((uint32_t)key_data[2] << 8) | key_data[3];
|
||||
ctx->hop = ((uint32_t)key_data[4] << 24) | ((uint32_t)key_data[5] << 16) |
|
||||
((uint32_t)key_data[6] << 8) | key_data[7];
|
||||
ctx->serial = ctx->fix & 0x0FFFFFFF;
|
||||
ctx->btn = ctx->fix >> 28;
|
||||
ctx->disc = ctx->serial & 0x3FF;
|
||||
}
|
||||
|
||||
ctx->hop2 = 0;
|
||||
flipper_format_rewind(fff);
|
||||
flipper_format_read_uint32(fff, "Hop2", &ctx->hop2, 1);
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneKlBfCleanup, (uint32_t)(uintptr_t)ctx);
|
||||
|
||||
if(!subghz->keeloq_keys_manager) {
|
||||
subghz->keeloq_keys_manager = subghz_keeloq_keys_alloc();
|
||||
}
|
||||
|
||||
char bf_name[24];
|
||||
snprintf(bf_name, sizeof(bf_name), "BF_%07lX", ctx->serial);
|
||||
|
||||
size_t user_count = subghz_keeloq_keys_user_count(subghz->keeloq_keys_manager);
|
||||
ctx->bf_count = 0;
|
||||
ctx->valid_count = 0;
|
||||
|
||||
for(size_t i = 0; i < user_count && ctx->bf_count < 32; i++) {
|
||||
SubGhzKey* k = subghz_keeloq_keys_get(subghz->keeloq_keys_manager, i);
|
||||
if(!k || !k->name) continue;
|
||||
const char* name = furi_string_get_cstr(k->name);
|
||||
if(strcmp(name, bf_name) == 0) {
|
||||
ctx->bf_indices[ctx->bf_count] = i;
|
||||
if(kl_cleanup_validate_key(k->key, ctx->hop, ctx->hop2, ctx->btn, ctx->disc)) {
|
||||
ctx->valid_indices[ctx->valid_count++] = i;
|
||||
}
|
||||
ctx->bf_count++;
|
||||
}
|
||||
}
|
||||
|
||||
FuriString* msg = furi_string_alloc();
|
||||
|
||||
if(ctx->bf_count == 0) {
|
||||
furi_string_set_str(msg, "No BF candidate keys\nfound for this serial.");
|
||||
} else if(ctx->bf_count == 1) {
|
||||
furi_string_set_str(msg, "Only 1 BF key exists.\nNothing to clean up.");
|
||||
} else if(ctx->valid_count == 1) {
|
||||
size_t deleted = 0;
|
||||
for(int i = (int)ctx->bf_count - 1; i >= 0; i--) {
|
||||
if(ctx->bf_indices[i] != ctx->valid_indices[0]) {
|
||||
subghz_keeloq_keys_delete(subghz->keeloq_keys_manager, ctx->bf_indices[i]);
|
||||
deleted++;
|
||||
}
|
||||
}
|
||||
subghz_keeloq_keys_save(subghz->keeloq_keys_manager);
|
||||
|
||||
furi_string_printf(msg,
|
||||
"Cleaned %u keys.\nKept valid key:\n%s",
|
||||
deleted, bf_name);
|
||||
} else if(ctx->valid_count == 0) {
|
||||
furi_string_printf(msg,
|
||||
"%u BF keys found\nbut none validates\nhop. Kept all.",
|
||||
ctx->bf_count);
|
||||
} else {
|
||||
furi_string_printf(msg,
|
||||
"%u BF keys, %u valid.\nCannot auto-select.\nKept all.",
|
||||
ctx->bf_count, ctx->valid_count);
|
||||
}
|
||||
|
||||
widget_add_text_scroll_element(subghz->widget, 0, 0, 128, 64, furi_string_get_cstr(msg));
|
||||
furi_string_free(msg);
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget);
|
||||
}
|
||||
|
||||
bool subghz_scene_kl_bf_cleanup_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void subghz_scene_kl_bf_cleanup_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
KlCleanupCtx* ctx = (KlCleanupCtx*)(uintptr_t)scene_manager_get_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneKlBfCleanup);
|
||||
if(ctx) {
|
||||
free(ctx);
|
||||
scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneKlBfCleanup, 0);
|
||||
}
|
||||
|
||||
widget_reset(subghz->widget);
|
||||
}
|
||||
@@ -45,25 +45,24 @@ bool subghz_scene_need_saving_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateBack);
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
return true;
|
||||
} else if(event.event == SubGhzCustomEventSceneExit) {
|
||||
} else if(event.event == SubGhzCustomEventSceneExit) {
|
||||
SubGhzRxKeyState state = subghz_rx_key_state_get(subghz);
|
||||
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE);
|
||||
|
||||
if(state == SubGhzRxKeyStateExit) {
|
||||
if(scene_manager_has_previous_scene(subghz->scene_manager, SubGhzSceneReadRAW)) {
|
||||
if(!furi_string_empty(subghz->file_path_tmp)) {
|
||||
subghz_delete_file(subghz);
|
||||
}
|
||||
}
|
||||
|
||||
subghz_txrx_set_preset(
|
||||
subghz->txrx, "AM650", subghz->last_settings->frequency, NULL, 0);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
if(!scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart)) {
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
}
|
||||
} else {
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,21 +133,21 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
}
|
||||
//CC1101 Stop RX -> Start TX
|
||||
subghz_txrx_hopper_pause(subghz->txrx);
|
||||
// key concept: we start endless TX until user release OK button, and after this we send last
|
||||
// protocols repeats - this guarantee that one press OK will
|
||||
// be guarantee send the required minimum protocol data packets
|
||||
// for all of this we use subghz_block_generic_global.endless_tx in protocols _yield function.
|
||||
subghz->state_notifications = SubGhzNotificationStateTx;
|
||||
subghz_block_generic_global.endless_tx = true;
|
||||
if(!subghz_tx_start(
|
||||
subghz,
|
||||
subghz_history_get_raw_data(subghz->history, subghz->idx_menu_chosen))) {
|
||||
subghz_txrx_rx_start(subghz->txrx);
|
||||
subghz_txrx_hopper_unpause(subghz->txrx);
|
||||
subghz->state_notifications = SubGhzNotificationStateRx;
|
||||
} else {
|
||||
// key concept: we start endless TX until user release OK button, and after this we send last
|
||||
// protocols repeats - this guarantee that one press OK will
|
||||
// be guarantee send the required minimum protocol data packets
|
||||
// for all of this we use subghz_block_generic_global.endless_tx in protocols _yield function.
|
||||
subghz->state_notifications = SubGhzNotificationStateTx;
|
||||
subghz_block_generic_global.endless_tx = true;
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubGhzCustomEventSceneReceiverInfoTxStop) {
|
||||
//CC1101 Stop Tx -> next tick event Start RX
|
||||
// user release OK
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexPsaDecrypt,
|
||||
SubmenuIndexEdit,
|
||||
SubmenuIndexDelete,
|
||||
SubmenuIndexSignalSettings,
|
||||
SubmenuIndexPsaDecrypt,
|
||||
SubmenuIndexCounterBf
|
||||
};
|
||||
|
||||
@@ -17,7 +17,6 @@ void subghz_scene_saved_menu_submenu_callback(void* context, uint32_t index) {
|
||||
void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
// Check protocol type for conditional menu items
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
bool is_psa_encrypted = false;
|
||||
bool has_counter = false;
|
||||
@@ -26,7 +25,6 @@ void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
flipper_format_rewind(fff);
|
||||
if(flipper_format_read_string(fff, "Protocol", proto)) {
|
||||
if(furi_string_equal_str(proto, "PSA GROUP")) {
|
||||
// Check if Type field is missing or zero (not yet decrypted)
|
||||
FuriString* type_str = furi_string_alloc();
|
||||
flipper_format_rewind(fff);
|
||||
if(!flipper_format_read_string(fff, "Type", type_str) ||
|
||||
@@ -39,7 +37,6 @@ void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
furi_string_free(proto);
|
||||
}
|
||||
|
||||
// Check if protocol has a Cnt field (supports counter bruteforce)
|
||||
if(fff) {
|
||||
uint32_t cnt_tmp = 0;
|
||||
flipper_format_rewind(fff);
|
||||
@@ -48,12 +45,23 @@ void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"Emulate",
|
||||
SubmenuIndexEmulate,
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
if(!is_psa_encrypted) {
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"Emulate",
|
||||
SubmenuIndexEmulate,
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
}
|
||||
|
||||
if(is_psa_encrypted) {
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"PSA Decrypt",
|
||||
SubmenuIndexPsaDecrypt,
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
}
|
||||
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
@@ -76,15 +84,8 @@ void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
SubmenuIndexSignalSettings,
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
};
|
||||
if(is_psa_encrypted) {
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"PSA Decrypt",
|
||||
SubmenuIndexPsaDecrypt,
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
}
|
||||
|
||||
if(has_counter) {
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
@@ -110,6 +111,11 @@ bool subghz_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz->scene_manager, SubGhzSceneSavedMenu, SubmenuIndexEmulate);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTransmitter);
|
||||
return true;
|
||||
} else if(event.event == SubmenuIndexPsaDecrypt) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneSavedMenu, SubmenuIndexPsaDecrypt);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzScenePsaDecrypt);
|
||||
return true;
|
||||
} else if(event.event == SubmenuIndexDelete) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneSavedMenu, SubmenuIndexDelete);
|
||||
@@ -125,11 +131,6 @@ bool subghz_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz->scene_manager, SubGhzSceneSavedMenu, SubmenuIndexSignalSettings);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSignalSettings);
|
||||
return true;
|
||||
} else if(event.event == SubmenuIndexPsaDecrypt) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneSavedMenu, SubmenuIndexPsaDecrypt);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzScenePsaDecrypt);
|
||||
return true;
|
||||
} else if(event.event == SubmenuIndexCounterBf) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneSavedMenu, SubmenuIndexCounterBf);
|
||||
|
||||
@@ -55,6 +55,12 @@ void subghz_scene_start_on_enter(void* context) {
|
||||
SubmenuIndexKeeloqKeys,
|
||||
subghz_scene_start_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"KeeLoq BF (2 Signals)",
|
||||
SubmenuIndexKeeloqBf2,
|
||||
subghz_scene_start_submenu_callback,
|
||||
subghz);
|
||||
submenu_set_selected_item(
|
||||
subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart));
|
||||
|
||||
@@ -112,6 +118,11 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexKeeloqKeys);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneKeeloqKeys);
|
||||
return true;
|
||||
} else if(event.event == SubmenuIndexKeeloqBf2) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexKeeloqBf2);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneKeeloqBf2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -10,4 +10,5 @@ enum SubmenuIndex {
|
||||
SubmenuIndexProtocolList,
|
||||
SubmenuIndexRadioSetting,
|
||||
SubmenuIndexKeeloqKeys,
|
||||
SubmenuIndexKeeloqBf2,
|
||||
};
|
||||
|
||||
@@ -95,6 +95,11 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
|
||||
|
||||
subghz->keeloq_keys_manager = NULL;
|
||||
|
||||
subghz->keeloq_bf2.sig1_loaded = false;
|
||||
subghz->keeloq_bf2.sig2_loaded = false;
|
||||
subghz->keeloq_bf2.sig1_path = furi_string_alloc();
|
||||
subghz->keeloq_bf2.sig2_path = furi_string_alloc();
|
||||
|
||||
subghz->file_path = furi_string_alloc();
|
||||
subghz->file_path_tmp = furi_string_alloc();
|
||||
|
||||
@@ -195,6 +200,12 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
|
||||
SubGhzViewIdPsaDecrypt,
|
||||
subghz_view_psa_decrypt_get_view(subghz->subghz_psa_decrypt));
|
||||
|
||||
subghz->subghz_keeloq_decrypt = subghz_view_keeloq_decrypt_alloc();
|
||||
view_dispatcher_add_view(
|
||||
subghz->view_dispatcher,
|
||||
SubGhzViewIdKeeloqDecrypt,
|
||||
subghz_view_keeloq_decrypt_get_view(subghz->subghz_keeloq_decrypt));
|
||||
|
||||
//init threshold rssi
|
||||
subghz->threshold_rssi = subghz_threshold_rssi_alloc();
|
||||
|
||||
@@ -306,6 +317,10 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) {
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdPsaDecrypt);
|
||||
subghz_view_psa_decrypt_free(subghz->subghz_psa_decrypt);
|
||||
|
||||
// KeeLoq Decrypt
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdKeeloqDecrypt);
|
||||
subghz_view_keeloq_decrypt_free(subghz->subghz_keeloq_decrypt);
|
||||
|
||||
// Read RAW
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdReadRAW);
|
||||
subghz_read_raw_free(subghz->subghz_read_raw);
|
||||
@@ -353,7 +368,9 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) {
|
||||
furi_string_free(subghz->file_path);
|
||||
furi_string_free(subghz->file_path_tmp);
|
||||
|
||||
// KeeLoq key manager (may still be live if app exited from within the edit scene)
|
||||
furi_string_free(subghz->keeloq_bf2.sig1_path);
|
||||
furi_string_free(subghz->keeloq_bf2.sig2_path);
|
||||
|
||||
if(subghz->keeloq_keys_manager) {
|
||||
subghz_keeloq_keys_free(subghz->keeloq_keys_manager);
|
||||
subghz->keeloq_keys_manager = NULL;
|
||||
@@ -386,6 +403,7 @@ int32_t subghz_app(void* p) {
|
||||
subghz->view_dispatcher, subghz->gui, ViewDispatcherTypeFullscreen);
|
||||
furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER);
|
||||
if(subghz_txrx_is_database_loaded(subghz->txrx)) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStart);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
|
||||
} else {
|
||||
scene_manager_set_scene_state(
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "views/subghz_frequency_analyzer.h"
|
||||
#include "views/subghz_read_raw.h"
|
||||
#include "views/subghz_psa_decrypt.h"
|
||||
#include "views/subghz_keeloq_decrypt.h"
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <assets_icons.h>
|
||||
@@ -74,6 +75,7 @@ struct SubGhz {
|
||||
SubGhzFrequencyAnalyzer* subghz_frequency_analyzer;
|
||||
SubGhzReadRAW* subghz_read_raw;
|
||||
SubGhzViewPsaDecrypt* subghz_psa_decrypt;
|
||||
SubGhzViewKeeloqDecrypt* subghz_keeloq_decrypt;
|
||||
bool raw_send_only;
|
||||
|
||||
bool save_datetime_set;
|
||||
@@ -102,13 +104,25 @@ struct SubGhz {
|
||||
// KeeLoq key management
|
||||
SubGhzKeeloqKeysManager* keeloq_keys_manager;
|
||||
struct {
|
||||
uint8_t key_bytes[8]; // ByteInput result
|
||||
char name[65]; // TextInput result
|
||||
uint16_t type; // selected learning type 1..8
|
||||
bool is_new; // true = add, false = edit
|
||||
size_t edit_index; // valid when is_new == false
|
||||
uint8_t edit_step; // 0 = key, 1 = name, 2 = type
|
||||
uint8_t key_bytes[8];
|
||||
char name[65];
|
||||
uint16_t type;
|
||||
bool is_new;
|
||||
size_t edit_index;
|
||||
uint8_t edit_step;
|
||||
} keeloq_edit;
|
||||
|
||||
struct {
|
||||
uint32_t fix;
|
||||
uint32_t hop1;
|
||||
uint32_t hop2;
|
||||
uint32_t serial;
|
||||
bool sig1_loaded;
|
||||
bool sig2_loaded;
|
||||
FuriString* sig1_path;
|
||||
FuriString* sig2_path;
|
||||
uint8_t learn_type;
|
||||
} keeloq_bf2;
|
||||
};
|
||||
|
||||
void subghz_blink_start(SubGhz* subghz);
|
||||
|
||||
246
applications/main/subghz/views/subghz_keeloq_decrypt.c
Normal file
@@ -0,0 +1,246 @@
|
||||
#include "subghz_keeloq_decrypt.h"
|
||||
|
||||
#include <gui/elements.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define KL_TOTAL_KEYS 0x100000000ULL
|
||||
|
||||
struct SubGhzViewKeeloqDecrypt {
|
||||
View* view;
|
||||
SubGhzViewKeeloqDecryptCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t progress;
|
||||
uint32_t keys_tested;
|
||||
uint32_t keys_per_sec;
|
||||
uint32_t elapsed_sec;
|
||||
uint32_t eta_sec;
|
||||
bool done;
|
||||
bool success;
|
||||
uint32_t candidates;
|
||||
FuriString* result_str;
|
||||
char status_line[40];
|
||||
} SubGhzKeeloqDecryptModel;
|
||||
|
||||
static void subghz_view_keeloq_decrypt_format_count(char* buf, size_t len, uint32_t count) {
|
||||
if(count >= 1000000) {
|
||||
snprintf(buf, len, "%lu.%luM", count / 1000000, (count % 1000000) / 100000);
|
||||
} else if(count >= 1000) {
|
||||
snprintf(buf, len, "%luK", count / 1000);
|
||||
} else {
|
||||
snprintf(buf, len, "%lu", count);
|
||||
}
|
||||
}
|
||||
|
||||
static void subghz_view_keeloq_decrypt_draw(Canvas* canvas, void* _model) {
|
||||
SubGhzKeeloqDecryptModel* model = (SubGhzKeeloqDecryptModel*)_model;
|
||||
|
||||
canvas_clear(canvas);
|
||||
|
||||
if(!model->done) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
if(model->status_line[0]) {
|
||||
canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, model->status_line);
|
||||
} else {
|
||||
canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "KeeLoq BF");
|
||||
}
|
||||
|
||||
canvas_draw_rframe(canvas, 3, 15, 122, 12, 2);
|
||||
uint8_t fill = (uint8_t)((uint16_t)model->progress * 116 / 100);
|
||||
if(fill > 0) {
|
||||
canvas_draw_rbox(canvas, 5, 17, fill, 8, 1);
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
char keys_str[32];
|
||||
char tested_buf[12];
|
||||
subghz_view_keeloq_decrypt_format_count(tested_buf, sizeof(tested_buf), model->keys_tested);
|
||||
snprintf(keys_str, sizeof(keys_str), "%d%% - %s / 4G keys", model->progress, tested_buf);
|
||||
canvas_draw_str(canvas, 2, 38, keys_str);
|
||||
|
||||
char speed_str[40];
|
||||
char speed_buf[12];
|
||||
subghz_view_keeloq_decrypt_format_count(speed_buf, sizeof(speed_buf), model->keys_per_sec);
|
||||
uint32_t eta_m = model->eta_sec / 60;
|
||||
uint32_t eta_s = model->eta_sec % 60;
|
||||
if(eta_m > 0) {
|
||||
snprintf(speed_str, sizeof(speed_str), "%s keys/sec ETA %lum %lus", speed_buf, eta_m, eta_s);
|
||||
} else {
|
||||
snprintf(speed_str, sizeof(speed_str), "%s keys/sec ETA %lus", speed_buf, eta_s);
|
||||
}
|
||||
canvas_draw_str(canvas, 2, 48, speed_str);
|
||||
|
||||
if(model->candidates > 0) {
|
||||
char cand_str[32];
|
||||
snprintf(cand_str, sizeof(cand_str), "Candidates: %lu", model->candidates);
|
||||
canvas_draw_str(canvas, 2, 58, cand_str);
|
||||
} else {
|
||||
char elapsed_str[24];
|
||||
uint32_t el_m = model->elapsed_sec / 60;
|
||||
uint32_t el_s = model->elapsed_sec % 60;
|
||||
if(el_m > 0) {
|
||||
snprintf(elapsed_str, sizeof(elapsed_str), "Elapsed: %lum %lus", el_m, el_s);
|
||||
} else {
|
||||
snprintf(elapsed_str, sizeof(elapsed_str), "Elapsed: %lus", el_s);
|
||||
}
|
||||
canvas_draw_str(canvas, 2, 58, elapsed_str);
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 126, 64, AlignRight, AlignBottom, "Hold BACK");
|
||||
} else {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
if(model->result_str) {
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->result_str));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool subghz_view_keeloq_decrypt_input(InputEvent* event, void* context) {
|
||||
SubGhzViewKeeloqDecrypt* instance = (SubGhzViewKeeloqDecrypt*)context;
|
||||
|
||||
if(event->key == InputKeyBack) {
|
||||
if(instance->callback) {
|
||||
instance->callback(SubGhzCustomEventViewTransmitterBack, instance->context);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SubGhzViewKeeloqDecrypt* subghz_view_keeloq_decrypt_alloc(void) {
|
||||
SubGhzViewKeeloqDecrypt* instance = malloc(sizeof(SubGhzViewKeeloqDecrypt));
|
||||
instance->view = view_alloc();
|
||||
view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubGhzKeeloqDecryptModel));
|
||||
view_set_context(instance->view, instance);
|
||||
view_set_draw_callback(instance->view, subghz_view_keeloq_decrypt_draw);
|
||||
view_set_input_callback(instance->view, subghz_view_keeloq_decrypt_input);
|
||||
|
||||
with_view_model(
|
||||
instance->view,
|
||||
SubGhzKeeloqDecryptModel * model,
|
||||
{
|
||||
model->result_str = furi_string_alloc();
|
||||
model->progress = 0;
|
||||
model->keys_tested = 0;
|
||||
model->keys_per_sec = 0;
|
||||
model->elapsed_sec = 0;
|
||||
model->eta_sec = 0;
|
||||
model->done = false;
|
||||
model->success = false;
|
||||
model->candidates = 0;
|
||||
},
|
||||
false);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_view_keeloq_decrypt_free(SubGhzViewKeeloqDecrypt* instance) {
|
||||
furi_check(instance);
|
||||
with_view_model(
|
||||
instance->view,
|
||||
SubGhzKeeloqDecryptModel * model,
|
||||
{ furi_string_free(model->result_str); },
|
||||
false);
|
||||
view_free(instance->view);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
View* subghz_view_keeloq_decrypt_get_view(SubGhzViewKeeloqDecrypt* instance) {
|
||||
furi_check(instance);
|
||||
return instance->view;
|
||||
}
|
||||
|
||||
void subghz_view_keeloq_decrypt_set_callback(
|
||||
SubGhzViewKeeloqDecrypt* instance,
|
||||
SubGhzViewKeeloqDecryptCallback callback,
|
||||
void* context) {
|
||||
furi_check(instance);
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
void subghz_view_keeloq_decrypt_update_stats(
|
||||
SubGhzViewKeeloqDecrypt* instance,
|
||||
uint8_t progress,
|
||||
uint32_t keys_tested,
|
||||
uint32_t keys_per_sec,
|
||||
uint32_t elapsed_sec,
|
||||
uint32_t eta_sec) {
|
||||
furi_check(instance);
|
||||
with_view_model(
|
||||
instance->view,
|
||||
SubGhzKeeloqDecryptModel * model,
|
||||
{
|
||||
model->progress = progress;
|
||||
model->keys_tested = keys_tested;
|
||||
model->keys_per_sec = keys_per_sec;
|
||||
model->elapsed_sec = elapsed_sec;
|
||||
model->eta_sec = eta_sec;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void subghz_view_keeloq_decrypt_set_result(
|
||||
SubGhzViewKeeloqDecrypt* instance,
|
||||
bool success,
|
||||
const char* result) {
|
||||
furi_check(instance);
|
||||
with_view_model(
|
||||
instance->view,
|
||||
SubGhzKeeloqDecryptModel * model,
|
||||
{
|
||||
model->done = true;
|
||||
model->success = success;
|
||||
furi_string_set_str(model->result_str, result);
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void subghz_view_keeloq_decrypt_reset(SubGhzViewKeeloqDecrypt* instance) {
|
||||
furi_check(instance);
|
||||
with_view_model(
|
||||
instance->view,
|
||||
SubGhzKeeloqDecryptModel * model,
|
||||
{
|
||||
model->progress = 0;
|
||||
model->keys_tested = 0;
|
||||
model->keys_per_sec = 0;
|
||||
model->elapsed_sec = 0;
|
||||
model->eta_sec = 0;
|
||||
model->done = false;
|
||||
model->success = false;
|
||||
model->candidates = 0;
|
||||
furi_string_reset(model->result_str);
|
||||
model->status_line[0] = '\0';
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
void subghz_view_keeloq_decrypt_set_status(SubGhzViewKeeloqDecrypt* instance, const char* status) {
|
||||
furi_check(instance);
|
||||
with_view_model(
|
||||
instance->view,
|
||||
SubGhzKeeloqDecryptModel * model,
|
||||
{
|
||||
if(status) {
|
||||
strlcpy(model->status_line, status, sizeof(model->status_line));
|
||||
} else {
|
||||
model->status_line[0] = '\0';
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void subghz_view_keeloq_decrypt_update_candidates(
|
||||
SubGhzViewKeeloqDecrypt* instance, uint32_t count) {
|
||||
furi_check(instance);
|
||||
with_view_model(
|
||||
instance->view,
|
||||
SubGhzKeeloqDecryptModel * model,
|
||||
{ model->candidates = count; },
|
||||
true);
|
||||
}
|
||||
37
applications/main/subghz/views/subghz_keeloq_decrypt.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../helpers/subghz_custom_event.h"
|
||||
|
||||
typedef struct SubGhzViewKeeloqDecrypt SubGhzViewKeeloqDecrypt;
|
||||
|
||||
typedef void (*SubGhzViewKeeloqDecryptCallback)(SubGhzCustomEvent event, void* context);
|
||||
|
||||
SubGhzViewKeeloqDecrypt* subghz_view_keeloq_decrypt_alloc(void);
|
||||
void subghz_view_keeloq_decrypt_free(SubGhzViewKeeloqDecrypt* instance);
|
||||
View* subghz_view_keeloq_decrypt_get_view(SubGhzViewKeeloqDecrypt* instance);
|
||||
|
||||
void subghz_view_keeloq_decrypt_set_callback(
|
||||
SubGhzViewKeeloqDecrypt* instance,
|
||||
SubGhzViewKeeloqDecryptCallback callback,
|
||||
void* context);
|
||||
|
||||
void subghz_view_keeloq_decrypt_update_stats(
|
||||
SubGhzViewKeeloqDecrypt* instance,
|
||||
uint8_t progress,
|
||||
uint32_t keys_tested,
|
||||
uint32_t keys_per_sec,
|
||||
uint32_t elapsed_sec,
|
||||
uint32_t eta_sec);
|
||||
|
||||
void subghz_view_keeloq_decrypt_set_result(
|
||||
SubGhzViewKeeloqDecrypt* instance,
|
||||
bool success,
|
||||
const char* result);
|
||||
|
||||
void subghz_view_keeloq_decrypt_reset(SubGhzViewKeeloqDecrypt* instance);
|
||||
|
||||
void subghz_view_keeloq_decrypt_set_status(SubGhzViewKeeloqDecrypt* instance, const char* status);
|
||||
|
||||
void subghz_view_keeloq_decrypt_update_candidates(
|
||||
SubGhzViewKeeloqDecrypt* instance, uint32_t count);
|
||||
@@ -50,8 +50,10 @@ static void subghz_view_psa_decrypt_draw(Canvas* canvas, void* _model) {
|
||||
// Progress bar outline + fill
|
||||
canvas_draw_rframe(canvas, 3, 15, 122, 12, 2);
|
||||
uint8_t fill = (uint8_t)((uint16_t)model->progress * 116 / 100);
|
||||
if(fill > 0) {
|
||||
if(fill > 2) {
|
||||
canvas_draw_rbox(canvas, 5, 17, fill, 8, 1);
|
||||
} else if(fill > 0) {
|
||||
canvas_draw_box(canvas, 5, 17, fill, 8);
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
@@ -90,19 +92,23 @@ static void subghz_view_psa_decrypt_draw(Canvas* canvas, void* _model) {
|
||||
// Cancel hint - bottom right
|
||||
canvas_draw_str_aligned(canvas, 126, 64, AlignRight, AlignBottom, "Hold BACK");
|
||||
} else {
|
||||
// Result screen
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
if(model->result_str) {
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->result_str));
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Decrypted!");
|
||||
|
||||
if(model->result_str) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text_aligned(canvas, 64, 20, AlignCenter, AlignTop,
|
||||
furi_string_get_cstr(model->result_str));
|
||||
}
|
||||
|
||||
elements_button_center(canvas, "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
static bool subghz_view_psa_decrypt_input(InputEvent* event, void* context) {
|
||||
SubGhzViewPsaDecrypt* instance = (SubGhzViewPsaDecrypt*)context;
|
||||
|
||||
if(event->key == InputKeyBack) {
|
||||
if(event->key == InputKeyBack || event->key == InputKeyOk) {
|
||||
if(instance->callback) {
|
||||
instance->callback(SubGhzCustomEventViewTransmitterBack, instance->context);
|
||||
}
|
||||
|
||||
1
applications_user/.gitignore
vendored
@@ -0,0 +1 @@
|
||||
*
|
||||
|
||||
2
applications_user/rf-jammer/.gitattributes
vendored
@@ -1,2 +0,0 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
7
applications_user/rf-jammer/.gitignore
vendored
@@ -1,7 +0,0 @@
|
||||
dist/*
|
||||
.vscode
|
||||
.clang-format
|
||||
.clangd
|
||||
.editorconfig
|
||||
.env
|
||||
.ufbt
|
||||
@@ -1,674 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
@@ -1,130 +0,0 @@
|
||||
# RF Jammer App by RocketGod ☠️📡
|
||||
|
||||
This **RF Jammer App** for the Flipper Zero, made by **RocketGod**, is a powerful tool for jamming across multiple radio frequencies and modulation schemes. Below is an in-depth look at each mode, from its technical details to the real-world impact of its jamming strategy.
|
||||
|
||||
## 🎥 Internal CC1101 Demonstration
|
||||
https://github.com/user-attachments/assets/4a34bc73-d419-480e-bb87-90216eb8a1e0
|
||||
## 🎥 External CC1101 Demonstration
|
||||
https://github.com/user-attachments/assets/1053ec27-a15f-4313-9257-2360135c5e96
|
||||
## 🎥 Modulation Modes
|
||||
https://github.com/user-attachments/assets/77970e50-d46f-4d59-bbb0-6e2624a98127
|
||||
|
||||
|
||||
## 🧪 Car Fob in Controlled Lab Test (-28dBm)
|
||||

|
||||
## 🧪 Community .sub files in Controlled Lab Test (-8dBm narrow)
|
||||

|
||||
## 🧪 RF Jammer App and Internal CC1101/Antenna in Controlled Lab Test (-8dBm wide)
|
||||

|
||||
## 🧪 RF Jammer App and External CC1101/Antenna Flux Capacitor by Rabbit Labs (10dBm) [TinySA Ultra hard wired w/25W attenuator]
|
||||

|
||||
|
||||
https://github.com/user-attachments/assets/53a3123e-b749-4af6-b542-e1784b131084
|
||||
|
||||
## 📡 External CC1101 Notes
|
||||
- **To use an external CC1101, attach it to the GPIO before starting the app.**
|
||||
- Tested with [Rabbit Labs - Flux Capacitor amplified external CC1101](https://rabbit-labs.com/product/rabbit-labs-flux-capacitor-amplified-cc1101/)
|
||||
|
||||
## 📡 Frequency Control
|
||||
|
||||
The app supports multiple frequency bands, ensuring compliance with the ranges handled by the Flipper's sub-GHz radio:
|
||||
- **Band 1**: 300 MHz – 348 MHz
|
||||
- **Band 2**: 387 MHz – 464 MHz
|
||||
- **Band 3**: 779 MHz – 928 MHz
|
||||
|
||||
You can adjust frequencies with **precision**:
|
||||
- **Left/Right** arrows move between digits to adjust.
|
||||
- **Up/Down** arrows increase or decrease the selected digit.
|
||||
|
||||
The app will automatically correct the frequency if it's outside the valid range for the selected band.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Jamming Modes Breakdown
|
||||
|
||||
Each jamming mode is implemented as a distinct modulation scheme and data pattern. The app generates these patterns and transmits them over the RF link to disrupt legitimate signals in the selected frequency range.
|
||||
|
||||
### 🦾 **OOK 650 kHz** (On-Off Keying):
|
||||
- **Pattern**: A continuous stream of `0xFF` (i.e., all bits set to `1`, equivalent to `11111111`).
|
||||
- **Mechanism**: In **OOK** (On-Off Keying), the presence or absence of a carrier wave represents binary data. In this case, the app transmits `11111111`, meaning the carrier is always "on."
|
||||
- **Impact**: This mode overwhelms receivers that use OOK modulation by constantly transmitting a high state (fully "on"). Because the signal never drops, devices expecting to detect short pulses (like garage doors, remotes, etc.) will be swamped and unable to distinguish real data from the noise.
|
||||
|
||||
### ⚡ **2FSK 2.38 kHz** (Frequency Shift Keying):
|
||||
- **Pattern**: Alternates between `0xAA` (`10101010`) and `0x55` (`01010101`), simulating binary `0`s and `1`s.
|
||||
- **Mechanism**: **2FSK** modulates the frequency by shifting between two discrete frequencies. A low deviation of **2.38 kHz** means that the frequency shifts only slightly between the two states, making this mode very precise.
|
||||
- **Impact**: Narrowband receivers expecting binary frequency-shifted data will receive rapid shifts between frequencies, confusing their demodulators. This small frequency shift can effectively jam simple devices, such as low-data-rate remotes, by creating ambiguity in the frequency state they expect.
|
||||
|
||||
### 🔥 **2FSK 47.6 kHz**:
|
||||
- **Pattern**: Alternates between `0xAA` and `0x55`, just like the 2.38 kHz mode.
|
||||
- **Mechanism**: Similar to the 2FSK 2.38 kHz mode, but with a much higher deviation of **47.6 kHz**. This makes the frequency shifts more pronounced, allowing the jammer to disrupt broader spectrum devices.
|
||||
- **Impact**: The wider frequency deviation affects a larger bandwidth, making it effective against systems that use wider channels or higher data rates. This mode can cause severe interference across a broader frequency spectrum, jamming systems with a higher tolerance for noise or frequency shifts.
|
||||
|
||||
### 💥 **MSK 99.97 Kb/s** (Minimum Shift Keying):
|
||||
- **Pattern**: A stream of **random data** (each byte is randomly generated, not a static pattern like the previous modes).
|
||||
- **Mechanism**: **MSK** is a highly efficient modulation technique where the frequency shifts are minimal, which makes it spectrally efficient (i.e., it occupies less bandwidth). The randomness of the data simulates high-speed communication, creating a noise-like signal.
|
||||
- **Impact**: By simulating a noisy digital communication channel, this mode is highly effective against digital systems that rely on MSK or similar modulation schemes. The continuous flow of random data saturates the receiver, making it impossible for legitimate data to be detected, especially in high-speed links like telemetry systems.
|
||||
|
||||
### 📶 **GFSK 9.99 Kb/s** (Gaussian Frequency Shift Keying):
|
||||
- **Pattern**: Like the MSK mode, this also uses **random data**.
|
||||
- **Mechanism**: **GFSK** is a variant of FSK where the frequency shifts are smoothed by a Gaussian filter. This reduces the bandwidth required for transmission, making it more efficient while still being robust against interference.
|
||||
- **Impact**: **GFSK** is widely used in Bluetooth and low-power RF systems. This mode simulates an authentic transmission with continuous random data, making it ideal for disrupting low-power communications without requiring significant bandwidth. Devices expecting real GFSK signals will be overloaded with random frequency shifts, making proper communication impossible.
|
||||
|
||||
### 🚀 **Bruteforce 0xFF**:
|
||||
- **Pattern**: A continuous stream of `0xFF` (equivalent to `11111111`).
|
||||
- **Mechanism**: This mode sends a constant, unmodulated signal of `1`s. In the digital domain, `0xFF` means every bit is a `1`, resulting in a strong, uninterrupted carrier wave being transmitted.
|
||||
- **Impact**: The **Bruteforce 0xFF** mode creates the most aggressive form of jamming. By transmitting non-stop high bits, it forces constant noise across the frequency, which jams nearly any communication within the affected band. Most RF systems rely on alternating data bits (`1`s and `0`s), so flooding the airwaves with pure `1`s causes receivers to lock up, unable to process real signals.
|
||||
|
||||
### 🎶 **Sine Wave**:
|
||||
- **Pattern**: Generates a continuous sine wave signal across the frequency.
|
||||
- **Mechanism**: Sine waves represent the most basic continuous wave (CW) modulation, commonly used in signal testing.
|
||||
- **Impact**: Affects devices using analog modulation schemes, causing them to interpret the signal as a valid, albeit meaningless, transmission, effectively drowning out real signals.
|
||||
|
||||
### 🟥 **Square Wave**:
|
||||
- **Pattern**: Alternates between high (`0xFF`) and low (`0x00`) states.
|
||||
- **Mechanism**: Square waves are simple digital pulses that are straightforward to generate and disruptive across various digital communication schemes.
|
||||
- **Impact**: Mimics basic digital signals, likely interfering with devices expecting digital pulse sequences like on-off signaling, potentially causing dropouts or erratic behavior.
|
||||
|
||||
### 📈 **Sawtooth Wave**:
|
||||
- **Pattern**: A gradually increasing signal followed by a sharp drop, repeated continuously.
|
||||
- **Mechanism**: The sawtooth pattern is similar to frequency sweeps used in testing, creating a continuously shifting interference.
|
||||
- **Impact**: Effective against frequency-sensitive systems by introducing an unpredictable, ramped noise, often disrupting RF links that lack sufficient error correction.
|
||||
|
||||
### 🎲 **White Noise**:
|
||||
- **Pattern**: Randomized data across the signal spectrum.
|
||||
- **Mechanism**: Emulates white noise, a common form of interference that introduces random amplitude values.
|
||||
- **Impact**: White noise can disrupt any frequency-based device, particularly analog devices, making it a universal jamming signal for both digital and analog targets.
|
||||
|
||||
### 🔺 **Triangle Wave**:
|
||||
- **Pattern**: Oscillates linearly between high and low values in a symmetric pattern.
|
||||
- **Mechanism**: The triangular waveform introduces a consistent frequency shift, resembling certain synthetic modulations.
|
||||
- **Impact**: Affects devices relying on predictable frequency patterns, making it harder for them to differentiate between legitimate and jammed signals.
|
||||
|
||||
### 📡 **Chirp Signal**:
|
||||
- **Pattern**: Frequency increases steadily within the waveform, known as a "chirp."
|
||||
- **Mechanism**: Common in radar and sonar, chirp signals create a rising frequency pattern over time.
|
||||
- **Impact**: Causes RF receivers to detect multiple frequencies simultaneously, often confusing or overloading their demodulators.
|
||||
|
||||
### 🎲 **Gaussian Noise**:
|
||||
- **Pattern**: Random values with a Gaussian (bell-curve) distribution.
|
||||
- **Mechanism**: Gaussian noise introduces random, statistically distributed values that mimic natural noise in RF environments.
|
||||
- **Impact**: Particularly effective for jamming digital signals relying on Gaussian-based frequency modulation, as it closely resembles natural interference, making the jamming less detectable.
|
||||
|
||||
### 💥 **Burst Mode**:
|
||||
- **Pattern**: Periodic bursts of high (`0xFF`) data with pauses in between.
|
||||
- **Mechanism**: Sends intense pulses followed by intervals, creating an effect similar to packetized data.
|
||||
- **Impact**: Effective against burst-based communication systems by mimicking valid data bursts, which can confuse or overload the receiver's data handling.
|
||||
|
||||
---
|
||||
|
||||
## 💣 Controls
|
||||
|
||||
- **Up/Down Buttons**: Modify the currently selected digit in the frequency.
|
||||
- **Left/Right Buttons**: Move between digits to adjust frequency values.
|
||||
- **OK Button**: Switch jamming modes in real-time.
|
||||
- **Back Button**: Stop the jamming and exit the app.
|
||||
|
||||
---
|
||||
|
||||
**Disclaimer**: This app is intended for educational and research purposes by experienced RF users. Ensure compliance with local regulations before using this tool.
|
||||
|
||||

|
||||
@@ -1,16 +0,0 @@
|
||||
App(
|
||||
appid="jammer_app",
|
||||
name="Jammer",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="jammer_app",
|
||||
requires=["gui", "subghz", "furi"],
|
||||
cdefines=["APP_JAMMER"],
|
||||
stack_size=2 * 1024,
|
||||
fap_category="Sub-GHz",
|
||||
fap_version="0.1",
|
||||
fap_icon_assets="assets",
|
||||
fap_author="@RocketGod-git",
|
||||
fap_description="Jammer for Flipper Zero",
|
||||
fap_icon="icons/jammer_icon.png",
|
||||
fap_weburl="https://github.com/RocketGod-Git/Flipper-Zero-Jammer",
|
||||
)
|
||||
@@ -1,2 +0,0 @@
|
||||
Thanks for the code @xMasterX
|
||||
https://github.com/flipperdevices/flipperzero-good-faps/pull/200
|
||||
@@ -1,80 +0,0 @@
|
||||
#include "radio_device_loader.h"
|
||||
|
||||
#include <applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h>
|
||||
#include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
|
||||
|
||||
static void radio_device_loader_power_on() {
|
||||
uint8_t attempts = 0;
|
||||
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
|
||||
furi_hal_power_enable_otg();
|
||||
//CC1101 power-up time
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
}
|
||||
|
||||
static void radio_device_loader_power_off() {
|
||||
if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg();
|
||||
}
|
||||
|
||||
bool radio_device_loader_is_connect_external(const char* name) {
|
||||
bool is_connect = false;
|
||||
bool is_otg_enabled = furi_hal_power_is_otg_enabled();
|
||||
|
||||
if(!is_otg_enabled) {
|
||||
radio_device_loader_power_on();
|
||||
}
|
||||
|
||||
const SubGhzDevice* device = subghz_devices_get_by_name(name);
|
||||
if(device) {
|
||||
is_connect = subghz_devices_is_connect(device);
|
||||
}
|
||||
|
||||
if(!is_otg_enabled) {
|
||||
radio_device_loader_power_off();
|
||||
}
|
||||
return is_connect;
|
||||
}
|
||||
|
||||
const SubGhzDevice* radio_device_loader_set(
|
||||
const SubGhzDevice* current_radio_device,
|
||||
SubGhzRadioDeviceType radio_device_type) {
|
||||
|
||||
const SubGhzDevice* radio_device = NULL;
|
||||
|
||||
if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 &&
|
||||
radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) {
|
||||
radio_device_loader_power_on();
|
||||
radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME);
|
||||
if (radio_device) {
|
||||
subghz_devices_begin(radio_device);
|
||||
FURI_LOG_D("radio_device_loader", "External CC1101 initialized.");
|
||||
} else {
|
||||
FURI_LOG_E("radio_device_loader", "Failed to initialize external CC1101.");
|
||||
}
|
||||
} else if (current_radio_device == NULL) {
|
||||
radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
|
||||
if (radio_device) {
|
||||
FURI_LOG_D("radio_device_loader", "Internal CC1101 selected.");
|
||||
} else {
|
||||
FURI_LOG_E("radio_device_loader", "Failed to load internal CC1101.");
|
||||
}
|
||||
} else {
|
||||
radio_device_loader_end(current_radio_device);
|
||||
radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
|
||||
}
|
||||
|
||||
return radio_device;
|
||||
}
|
||||
|
||||
bool radio_device_loader_is_external(const SubGhzDevice* radio_device) {
|
||||
furi_assert(radio_device);
|
||||
return (radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME));
|
||||
}
|
||||
|
||||
void radio_device_loader_end(const SubGhzDevice* radio_device) {
|
||||
furi_assert(radio_device);
|
||||
radio_device_loader_power_off();
|
||||
if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) {
|
||||
subghz_devices_end(radio_device);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/subghz/devices/devices.h>
|
||||
|
||||
#define SUBGHZ_DEVICE_CC1101_INT_NAME "cc1101_int"
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_NAME "cc1101_ext"
|
||||
|
||||
typedef enum {
|
||||
SubGhzRadioDeviceTypeInternal,
|
||||
SubGhzRadioDeviceTypeExternalCC1101,
|
||||
} SubGhzRadioDeviceType;
|
||||
|
||||
const SubGhzDevice* radio_device_loader_set(
|
||||
const SubGhzDevice* current_radio_device,
|
||||
SubGhzRadioDeviceType radio_device_type);
|
||||
|
||||
bool radio_device_loader_is_connect_external(const char* name);
|
||||
bool radio_device_loader_is_external(const SubGhzDevice* radio_device);
|
||||
void radio_device_loader_end(const SubGhzDevice* radio_device);
|
||||
|
Before Width: | Height: | Size: 4.0 KiB |
@@ -1,676 +0,0 @@
|
||||
#include "jammer_app.h"
|
||||
#include <furi_hal_region.h>
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <subghz/devices/devices.h>
|
||||
#include <furi/core/log.h>
|
||||
#include <furi_hal.h>
|
||||
#include <lib/subghz/subghz_tx_rx_worker.h>
|
||||
#include "helpers/radio_device_loader.h"
|
||||
|
||||
#define TAG "JammerApp"
|
||||
#define SUBGHZ_FREQUENCY_MIN 300000000
|
||||
#define SUBGHZ_FREQUENCY_MAX 928000000
|
||||
#define MESSAGE_MAX_LEN 1024
|
||||
|
||||
static FuriHalRegion unlockedRegion = {
|
||||
.country_code = "FTW",
|
||||
.bands_count = 3,
|
||||
.bands = {
|
||||
{.start = 299999755, .end = 348000000, .power_limit = 20, .duty_cycle = 50},
|
||||
{.start = 386999938, .end = 464000000, .power_limit = 20, .duty_cycle = 50},
|
||||
{.start = 778999847, .end = 928000000, .power_limit = 20, .duty_cycle = 50},
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
} FrequencyBand;
|
||||
|
||||
static const FrequencyBand valid_frequency_bands[] = {
|
||||
{300000000, 348000000},
|
||||
{387000000, 464000000},
|
||||
{779000000, 928000000},
|
||||
};
|
||||
|
||||
#define NUM_FREQUENCY_BANDS (sizeof(valid_frequency_bands) / sizeof(valid_frequency_bands[0]))
|
||||
|
||||
static const char* jamming_modes[] = {
|
||||
"OOK 650kHz",
|
||||
"2FSK 2.38kHz",
|
||||
"2FSK 47.6kHz",
|
||||
"MSK 99.97Kb/s",
|
||||
"GFSK 9.99Kb/s",
|
||||
"Bruteforce 0xFF",
|
||||
"Sine Wave",
|
||||
"Square Wave",
|
||||
"Sawtooth Wave",
|
||||
"White Noise",
|
||||
"Triangle Wave",
|
||||
"Chirp Signal",
|
||||
"Gaussian Noise",
|
||||
"Burst Mode"
|
||||
};
|
||||
|
||||
static void jammer_show_splash_screen(JammerApp* app);
|
||||
static bool jammer_init_subghz(JammerApp* app);
|
||||
static void jammer_start_tx(JammerApp* app);
|
||||
static void jammer_switch_mode(JammerApp* app);
|
||||
static void jammer_update_view(JammerApp* app);
|
||||
static void jammer_adjust_frequency(JammerApp* app, bool up);
|
||||
static uint32_t adjust_frequency_to_valid(uint32_t frequency, bool up);
|
||||
static bool is_frequency_valid(uint32_t frequency);
|
||||
static int32_t jammer_tx_thread(void* context);
|
||||
static void jammer_splash_screen_draw_callback(Canvas* canvas, void* context);
|
||||
static void jammer_draw_callback(Canvas* canvas, void* context);
|
||||
static void jammer_input_callback(InputEvent* input_event, void* context);
|
||||
|
||||
int32_t jammer_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
FURI_LOG_I(TAG, "Starting JammerApp");
|
||||
|
||||
JammerApp* app = jammer_app_alloc();
|
||||
if(!app) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate JammerApp");
|
||||
return -1;
|
||||
}
|
||||
|
||||
jammer_show_splash_screen(app);
|
||||
|
||||
if(!jammer_init_subghz(app)) {
|
||||
jammer_app_free(app);
|
||||
return -1;
|
||||
}
|
||||
|
||||
jammer_start_tx(app);
|
||||
|
||||
FURI_LOG_I(TAG, "Entering main loop");
|
||||
|
||||
InputEvent event;
|
||||
while(app->running) {
|
||||
if(furi_message_queue_get(app->event_queue, &event, 10) == FuriStatusOk) {
|
||||
if(event.type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyOk:
|
||||
FURI_LOG_I(TAG, "OK button pressed");
|
||||
jammer_switch_mode(app);
|
||||
jammer_update_view(app);
|
||||
break;
|
||||
case InputKeyBack:
|
||||
FURI_LOG_I(TAG, "Back button pressed");
|
||||
app->running = false;
|
||||
break;
|
||||
case InputKeyRight:
|
||||
FURI_LOG_I(TAG, "Right button pressed");
|
||||
if(app->cursor_position < 4) {
|
||||
app->cursor_position++;
|
||||
jammer_update_view(app);
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
FURI_LOG_I(TAG, "Left button pressed");
|
||||
if(app->cursor_position > 0) {
|
||||
app->cursor_position--;
|
||||
jammer_update_view(app);
|
||||
}
|
||||
break;
|
||||
case InputKeyUp:
|
||||
FURI_LOG_I(TAG, "Up button pressed");
|
||||
jammer_adjust_frequency(app, true);
|
||||
jammer_update_view(app);
|
||||
break;
|
||||
case InputKeyDown:
|
||||
FURI_LOG_I(TAG, "Down button pressed");
|
||||
jammer_adjust_frequency(app, false);
|
||||
jammer_update_view(app);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Exiting JammerApp main loop");
|
||||
|
||||
jammer_app_free(app);
|
||||
|
||||
FURI_LOG_I(TAG, "JammerApp exited");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
JammerApp* jammer_app_alloc(void) {
|
||||
JammerApp* app = malloc(sizeof(JammerApp));
|
||||
if(!app) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
app->view_port = view_port_alloc();
|
||||
app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
||||
app->frequency = 315000000;
|
||||
app->cursor_position = 0;
|
||||
app->running = true;
|
||||
app->tx_running = false;
|
||||
app->jamming_mode = JammerModeOok650Async;
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
furi_hal_region_set(&unlockedRegion);
|
||||
|
||||
view_port_draw_callback_set(app->view_port, jammer_draw_callback, app);
|
||||
view_port_input_callback_set(app->view_port, jammer_input_callback, app);
|
||||
gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
|
||||
|
||||
app->tx_thread = NULL;
|
||||
app->subghz_txrx = NULL;
|
||||
app->device = NULL;
|
||||
|
||||
subghz_devices_init();
|
||||
app->subghz_txrx = subghz_tx_rx_worker_alloc();
|
||||
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void jammer_app_free(JammerApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Enter jammer_app_free");
|
||||
#endif
|
||||
|
||||
if(app->tx_running) {
|
||||
app->tx_running = false;
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Set tx_running to false");
|
||||
#endif
|
||||
}
|
||||
|
||||
if(app->tx_thread) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Joining tx_thread");
|
||||
#endif
|
||||
furi_thread_join(app->tx_thread);
|
||||
furi_thread_free(app->tx_thread);
|
||||
app->tx_thread = NULL;
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "tx_thread joined and freed");
|
||||
#endif
|
||||
}
|
||||
|
||||
if(app->subghz_txrx) {
|
||||
if(subghz_tx_rx_worker_is_running(app->subghz_txrx)) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subghz_txrx worker is running, stopping");
|
||||
#endif
|
||||
subghz_tx_rx_worker_stop(app->subghz_txrx);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subghz_txrx worker stopped");
|
||||
#endif
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Freeing subghz_txrx worker");
|
||||
#endif
|
||||
subghz_tx_rx_worker_free(app->subghz_txrx);
|
||||
app->subghz_txrx = NULL;
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subghz_txrx worker freed");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Ending radio device");
|
||||
#endif
|
||||
if(app->device) {
|
||||
#ifdef FURI_DEBUG
|
||||
const char* device_name = app->device->name ? app->device->name : "Unknown";
|
||||
FURI_LOG_D(TAG, "Device name: %s", device_name);
|
||||
#endif
|
||||
|
||||
if(radio_device_loader_is_external(app->device)) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Device is external, performing manual cleanup");
|
||||
#endif
|
||||
if(furi_hal_power_is_otg_enabled()) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "OTG power is enabled, disabling");
|
||||
#endif
|
||||
furi_hal_power_disable_otg();
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "OTG power disabled");
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Device is internal, calling radio_device_loader_end");
|
||||
#endif
|
||||
radio_device_loader_end(app->device);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "radio_device_loader_end completed");
|
||||
#endif
|
||||
}
|
||||
|
||||
app->device = NULL;
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Radio device ended");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Calling subghz_devices_deinit");
|
||||
#endif
|
||||
subghz_devices_deinit();
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subghz_devices_deinit completed");
|
||||
#endif
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Exiting power suppression mode");
|
||||
#endif
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Removing view port from GUI");
|
||||
#endif
|
||||
gui_remove_view_port(app->gui, app->view_port);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "gui_remove_view_port completed");
|
||||
#endif
|
||||
|
||||
view_port_free(app->view_port);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "view_port freed");
|
||||
#endif
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Closing GUI record");
|
||||
#endif
|
||||
furi_record_close(RECORD_GUI);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "GUI record closed");
|
||||
#endif
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Freeing event queue");
|
||||
#endif
|
||||
furi_message_queue_free(app->event_queue);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Event queue freed");
|
||||
#endif
|
||||
|
||||
free(app);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Exit jammer_app_free");
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool jammer_init_subghz(JammerApp* app) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Enter jammer_init_subghz");
|
||||
#endif
|
||||
app->device = radio_device_loader_set(NULL, SubGhzRadioDeviceTypeExternalCC1101);
|
||||
|
||||
if(!app->device) {
|
||||
FURI_LOG_W(TAG, "External CC1101 not found, trying internal CC1101.");
|
||||
app->device = radio_device_loader_set(NULL, SubGhzRadioDeviceTypeInternal);
|
||||
if(!app->device) {
|
||||
FURI_LOG_E(TAG, "Failed to initialize internal CC1101.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
subghz_devices_reset(app->device);
|
||||
subghz_devices_idle(app->device);
|
||||
|
||||
FURI_LOG_I(TAG, "Initialized device %s", app->device->name);
|
||||
|
||||
subghz_devices_load_preset(app->device, FuriHalSubGhzPresetOok650Async, NULL);
|
||||
|
||||
if(subghz_tx_rx_worker_start(app->subghz_txrx, app->device, app->frequency)) {
|
||||
FURI_LOG_I(TAG, "Started SubGhz TX RX worker with device %s", app->device->name);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Exit jammer_init_subghz");
|
||||
#endif
|
||||
return true;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to start TX RX worker with device %s", app->device->name);
|
||||
subghz_tx_rx_worker_stop(app->subghz_txrx);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Exit jammer_init_subghz");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void jammer_show_splash_screen(JammerApp* app) {
|
||||
view_port_draw_callback_set(app->view_port, jammer_splash_screen_draw_callback, app);
|
||||
view_port_update(app->view_port);
|
||||
furi_delay_ms(2000);
|
||||
view_port_draw_callback_set(app->view_port, jammer_draw_callback, app);
|
||||
}
|
||||
|
||||
static void jammer_splash_screen_draw_callback(Canvas* canvas, void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
canvas_clear(canvas);
|
||||
|
||||
for(int x = 0; x < 128; x += 8) {
|
||||
for(int y = 0; y < 64; y += 8) {
|
||||
canvas_draw_dot(canvas, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 64, 15, AlignCenter, AlignTop, "RF Jammer");
|
||||
canvas_draw_str_aligned(canvas, 64, 35, AlignCenter, AlignTop, "by RocketGod");
|
||||
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
}
|
||||
|
||||
static void jammer_draw_callback(Canvas* canvas, void* context) {
|
||||
JammerApp* app = (JammerApp*)context;
|
||||
canvas_clear(canvas);
|
||||
|
||||
char freq_str[20];
|
||||
snprintf(freq_str, sizeof(freq_str), "%3lu.%02lu",
|
||||
app->frequency / 1000000,
|
||||
(app->frequency % 1000000) / 10000);
|
||||
|
||||
int total_width = strlen(freq_str) * 12;
|
||||
int start_x = (128 - total_width) / 2;
|
||||
int digit_position = 0;
|
||||
|
||||
for(size_t i = 0; i < strlen(freq_str); i++) {
|
||||
bool highlight = (digit_position == app->cursor_position);
|
||||
|
||||
if(freq_str[i] != '.') {
|
||||
canvas_set_font(canvas, highlight ? FontBigNumbers : FontPrimary);
|
||||
char temp[2] = {freq_str[i], '\0'};
|
||||
canvas_draw_str_aligned(canvas, start_x + (i * 12), 10, AlignCenter, AlignTop, temp);
|
||||
digit_position++;
|
||||
} else {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
char temp[2] = {freq_str[i], '\0'};
|
||||
canvas_draw_str_aligned(canvas, start_x + (i * 12), 10, AlignCenter, AlignTop, temp);
|
||||
}
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 64, 55, AlignCenter, AlignTop, jamming_modes[app->jamming_mode]);
|
||||
}
|
||||
|
||||
static void jammer_input_callback(InputEvent* input_event, void* context) {
|
||||
JammerApp* app = (JammerApp*)context;
|
||||
furi_message_queue_put(app->event_queue, input_event, FuriWaitForever);
|
||||
}
|
||||
|
||||
static void jammer_adjust_frequency(JammerApp* app, bool up) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Enter jammer_adjust_frequency");
|
||||
#endif
|
||||
uint32_t frequency = app->frequency;
|
||||
uint32_t step;
|
||||
|
||||
switch(app->cursor_position) {
|
||||
case 0: step = 100000000; break;
|
||||
case 1: step = 10000000; break;
|
||||
case 2: step = 1000000; break;
|
||||
case 3: step = 100000; break;
|
||||
case 4: step = 10000; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
frequency = up ? frequency + step : frequency - step;
|
||||
|
||||
if(frequency > SUBGHZ_FREQUENCY_MAX) {
|
||||
frequency = SUBGHZ_FREQUENCY_MIN;
|
||||
} else if(frequency < SUBGHZ_FREQUENCY_MIN) {
|
||||
frequency = SUBGHZ_FREQUENCY_MAX;
|
||||
}
|
||||
|
||||
frequency = adjust_frequency_to_valid(frequency, up);
|
||||
app->frequency = frequency;
|
||||
|
||||
FURI_LOG_I(TAG, "Frequency adjusted to %lu Hz", app->frequency);
|
||||
|
||||
if(app->tx_running) {
|
||||
if(app->subghz_txrx && app->device) {
|
||||
subghz_tx_rx_worker_stop(app->subghz_txrx);
|
||||
if(subghz_tx_rx_worker_start(app->subghz_txrx, app->device, app->frequency)) {
|
||||
FURI_LOG_I(TAG, "Restarted SubGhz TX RX worker with new frequency %lu Hz", app->frequency);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to restart SubGhz TX RX worker");
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Cannot adjust frequency, subghz_txrx or device is NULL");
|
||||
}
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Exit jammer_adjust_frequency");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void jammer_switch_mode(JammerApp* app) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Enter jammer_switch_mode");
|
||||
#endif
|
||||
if(app->tx_running) {
|
||||
app->tx_running = false;
|
||||
if(app->tx_thread) {
|
||||
furi_thread_join(app->tx_thread);
|
||||
furi_thread_free(app->tx_thread);
|
||||
app->tx_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(app->subghz_txrx) {
|
||||
if(subghz_tx_rx_worker_is_running(app->subghz_txrx)) {
|
||||
subghz_tx_rx_worker_stop(app->subghz_txrx);
|
||||
}
|
||||
}
|
||||
|
||||
if(!app->device) {
|
||||
app->device = radio_device_loader_set(NULL, SubGhzRadioDeviceTypeExternalCC1101);
|
||||
if(!app->device) {
|
||||
app->device = radio_device_loader_set(NULL, SubGhzRadioDeviceTypeInternal);
|
||||
if(!app->device) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subghz_devices_begin(app->device);
|
||||
subghz_devices_reset(app->device);
|
||||
subghz_devices_idle(app->device);
|
||||
|
||||
app->jamming_mode = (app->jamming_mode + 1) % 14;
|
||||
|
||||
switch(app->jamming_mode) {
|
||||
case JammerModeOok650Async:
|
||||
subghz_devices_load_preset(app->device, FuriHalSubGhzPresetOok650Async, NULL);
|
||||
break;
|
||||
case JammerMode2FSKDev238Async:
|
||||
subghz_devices_load_preset(app->device, FuriHalSubGhzPreset2FSKDev238Async, NULL);
|
||||
break;
|
||||
case JammerMode2FSKDev476Async:
|
||||
subghz_devices_load_preset(app->device, FuriHalSubGhzPreset2FSKDev476Async, NULL);
|
||||
break;
|
||||
case JammerModeMSK99_97KbAsync:
|
||||
subghz_devices_load_preset(app->device, FuriHalSubGhzPresetMSK99_97KbAsync, NULL);
|
||||
break;
|
||||
case JammerModeGFSK9_99KbAsync:
|
||||
subghz_devices_load_preset(app->device, FuriHalSubGhzPresetGFSK9_99KbAsync, NULL);
|
||||
break;
|
||||
case JammerModeBruteforce:
|
||||
subghz_devices_load_preset(app->device, FuriHalSubGhzPresetOok650Async, NULL);
|
||||
break;
|
||||
case JammerModeSineWave:
|
||||
case JammerModeSquareWave:
|
||||
case JammerModeSawtoothWave:
|
||||
case JammerModeWhiteNoise:
|
||||
case JammerModeTriangleWave:
|
||||
case JammerModeChirp:
|
||||
case JammerModeGaussianNoise:
|
||||
case JammerModeBurst:
|
||||
FURI_LOG_I(TAG, "Switched to waveform generation mode: %d", app->jamming_mode);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(app->subghz_txrx) {
|
||||
if(subghz_tx_rx_worker_start(app->subghz_txrx, app->device, app->frequency)) {
|
||||
jammer_start_tx(app);
|
||||
}
|
||||
} else {
|
||||
app->subghz_txrx = subghz_tx_rx_worker_alloc();
|
||||
if(app->subghz_txrx) {
|
||||
if(subghz_tx_rx_worker_start(app->subghz_txrx, app->device, app->frequency)) {
|
||||
jammer_start_tx(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Exit jammer_switch_mode");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void jammer_start_tx(JammerApp* app) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Enter jammer_start_tx");
|
||||
#endif
|
||||
app->tx_running = true;
|
||||
app->tx_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(app->tx_thread, "Jammer TX");
|
||||
furi_thread_set_stack_size(app->tx_thread, 2048);
|
||||
furi_thread_set_context(app->tx_thread, app);
|
||||
furi_thread_set_callback(app->tx_thread, jammer_tx_thread);
|
||||
furi_thread_start(app->tx_thread);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Exit jammer_start_tx");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int32_t jammer_tx_thread(void* context) {
|
||||
JammerApp* app = context;
|
||||
uint8_t jam_data[MESSAGE_MAX_LEN];
|
||||
|
||||
const char* device_name = (app->device && app->device->name) ? app->device->name : "Unknown";
|
||||
FURI_LOG_I(TAG, "TX Thread started with mode %d on device %s", app->jamming_mode, device_name);
|
||||
|
||||
switch(app->jamming_mode) {
|
||||
case JammerModeOok650Async:
|
||||
memset(jam_data, 0xFF, sizeof(jam_data));
|
||||
break;
|
||||
case JammerMode2FSKDev238Async:
|
||||
case JammerMode2FSKDev476Async:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
jam_data[i] = (i % 2 == 0) ? 0xAA : 0x55;
|
||||
}
|
||||
break;
|
||||
case JammerModeMSK99_97KbAsync:
|
||||
case JammerModeGFSK9_99KbAsync:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
jam_data[i] = rand() % 256;
|
||||
}
|
||||
break;
|
||||
case JammerModeBruteforce:
|
||||
memset(jam_data, 0xFF, sizeof(jam_data));
|
||||
break;
|
||||
case JammerModeSineWave:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
jam_data[i] = (uint8_t)(127 * sinf(2 * M_PI * i / sizeof(jam_data)) + 128);
|
||||
}
|
||||
break;
|
||||
case JammerModeSquareWave:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
jam_data[i] = (i % 2 == 0) ? 0xFF : 0x00;
|
||||
}
|
||||
break;
|
||||
case JammerModeSawtoothWave:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
jam_data[i] = (uint8_t)(255 * i / sizeof(jam_data));
|
||||
}
|
||||
break;
|
||||
case JammerModeWhiteNoise:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
jam_data[i] = rand() % 256;
|
||||
}
|
||||
break;
|
||||
case JammerModeTriangleWave:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
jam_data[i] = (i < sizeof(jam_data) / 2) ? (i * 255 / (sizeof(jam_data) / 2)) : (255 - (i * 255 / (sizeof(jam_data) / 2)));
|
||||
}
|
||||
break;
|
||||
case JammerModeChirp:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
jam_data[i] = (uint8_t)(127 * sinf(2 * M_PI * i * (1 + (float)i / sizeof(jam_data))));
|
||||
}
|
||||
break;
|
||||
case JammerModeGaussianNoise:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
float u1 = (float)rand() / RAND_MAX;
|
||||
float u2 = (float)rand() / RAND_MAX;
|
||||
float gaussian_noise = sqrtf(-2.0f * logf(u1)) * cosf(2 * M_PI * u2);
|
||||
jam_data[i] = (uint8_t)(127 * gaussian_noise + 128);
|
||||
}
|
||||
break;
|
||||
case JammerModeBurst:
|
||||
for(size_t i = 0; i < sizeof(jam_data); i++) {
|
||||
jam_data[i] = (i % 10 == 0) ? 0xFF : 0x00;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
while(app->tx_running) {
|
||||
if(app->subghz_txrx) {
|
||||
bool write_result = subghz_tx_rx_worker_write(app->subghz_txrx, jam_data, sizeof(jam_data));
|
||||
if(!write_result) {
|
||||
furi_delay_ms(20);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "TX Thread exiting");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jammer_update_view(JammerApp* app) {
|
||||
view_port_update(app->view_port);
|
||||
}
|
||||
|
||||
static uint32_t adjust_frequency_to_valid(uint32_t frequency, bool up) {
|
||||
if(is_frequency_valid(frequency)) {
|
||||
return frequency;
|
||||
} else {
|
||||
if(up) {
|
||||
for(size_t i = 0; i < NUM_FREQUENCY_BANDS; i++) {
|
||||
if(frequency < valid_frequency_bands[i].min) {
|
||||
return valid_frequency_bands[i].min;
|
||||
}
|
||||
}
|
||||
return valid_frequency_bands[0].min;
|
||||
} else {
|
||||
for(int i = NUM_FREQUENCY_BANDS - 1; i >= 0; i--) {
|
||||
if(frequency > valid_frequency_bands[i].max) {
|
||||
return valid_frequency_bands[i].max;
|
||||
}
|
||||
}
|
||||
return valid_frequency_bands[NUM_FREQUENCY_BANDS - 1].max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_frequency_valid(uint32_t frequency) {
|
||||
for(size_t i = 0; i < NUM_FREQUENCY_BANDS; i++) {
|
||||
if(frequency >= valid_frequency_bands[i].min && frequency <= valid_frequency_bands[i].max) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <lib/subghz/subghz_tx_rx_worker.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewPort* view_port;
|
||||
FuriMessageQueue* event_queue;
|
||||
uint32_t frequency;
|
||||
uint8_t cursor_position;
|
||||
bool running;
|
||||
const SubGhzDevice* device;
|
||||
SubGhzTxRxWorker* subghz_txrx;
|
||||
FuriThread* tx_thread;
|
||||
bool tx_running;
|
||||
int jamming_mode;
|
||||
} JammerApp;
|
||||
|
||||
typedef enum {
|
||||
JammerModeOok650Async,
|
||||
JammerMode2FSKDev238Async,
|
||||
JammerMode2FSKDev476Async,
|
||||
JammerModeMSK99_97KbAsync,
|
||||
JammerModeGFSK9_99KbAsync,
|
||||
JammerModeBruteforce,
|
||||
JammerModeSineWave,
|
||||
JammerModeSquareWave,
|
||||
JammerModeSawtoothWave,
|
||||
JammerModeWhiteNoise,
|
||||
JammerModeTriangleWave,
|
||||
JammerModeChirp,
|
||||
JammerModeGaussianNoise,
|
||||
JammerModeBurst,
|
||||
} JammerMode;
|
||||
|
||||
JammerApp* jammer_app_alloc(void);
|
||||
void jammer_app_free(JammerApp* app);
|
||||
int32_t jammer_app(void* p);
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 511 B After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 518 B After Width: | Height: | Size: 968 B |
|
Before Width: | Height: | Size: 483 B After Width: | Height: | Size: 1.2 KiB |
1
documentation/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/doxygen/build
|
||||
@@ -1,139 +0,0 @@
|
||||
# FAM (Flipper App Manifests) {#app_manifests}
|
||||
|
||||
All components of Flipper Zero firmware — services, user applications, and system settings — are developed independently. Each component has a build system manifest file named `application.fam`, which defines the basic properties of that component and its relations to other parts of the system.
|
||||
|
||||
When building firmware, `fbt` collects all app manifests and processes their dependencies. Then it builds only those components referenced in the current build configuration. See [FBT docs](fbt.md) for details on build configurations.
|
||||
|
||||
## App definition
|
||||
|
||||
A firmware component's properties are declared in a Python code snippet, forming a call to the `App()` function with various parameters.
|
||||
|
||||
Only two parameters are mandatory: **appid** and **apptype**. Others are optional and may only be meaningful for certain app types.
|
||||
|
||||
### Parameters
|
||||
|
||||
- **appid**: string, app ID within the build system. It is used to specify which app to include in the build configuration and resolve dependencies and conflicts.
|
||||
|
||||
- **apptype**: member of FlipperAppType.\* enumeration. Valid values are:
|
||||
|
||||
| Enum member | Firmware component type |
|
||||
| ----------- | ------------------------------------------------------------------------------------------- |
|
||||
| SERVICE | System service, created at early startup |
|
||||
| SYSTEM | App is not being shown in any menus. It can be started by other apps or from CLI |
|
||||
| APP | Regular app for the main menu |
|
||||
| PLUGIN | App to be built as a part of the firmware and to be placed in the Plugins menu |
|
||||
| DEBUG | App only visible in Debug menu with debug mode enabled |
|
||||
| ARCHIVE | One and only Archive app |
|
||||
| SETTINGS | App to be placed in the system settings menu |
|
||||
| STARTUP | Callback function to run at system startup. Does not define a separate app |
|
||||
| EXTERNAL | App to be built as `.fap` plugin |
|
||||
| METAPACKAGE | Does not define any code to be run, used for declaring dependencies and app bundles |
|
||||
|
||||
- **name**: name displayed in menus.
|
||||
- **entry_point**: C function to be used as the app's entry point. Note that C++ function names are mangled, so you need to wrap them in `extern "C"` to use them as entry points.
|
||||
- **flags**: internal flags for system apps. Do not use.
|
||||
- **cdefines**: C preprocessor definitions to declare globally for other apps when the current app is included in the active build configuration. **For external apps**: specified definitions are used when building the app itself.
|
||||
- **requires**: list of app IDs to include in the build configuration when the current app is referenced in the list of apps to build.
|
||||
- **conflicts**: list of app IDs with which the current app conflicts. If any of them is found in the constructed app list, `fbt` will abort the firmware build process.
|
||||
- **provides**: functionally identical to **_requires_** field.
|
||||
- **stack_size**: stack size in bytes to allocate for an app on its startup. Note that allocating a stack too small for an app to run will cause a system crash due to stack overflow, and allocating too much stack space will reduce usable heap memory size for apps to process data. _Note: you can use `top` and `free` CLI commands to profile your app's memory usage._
|
||||
- **icon**: animated icon name from built-in assets to be used when building the app as a part of the firmware.
|
||||
- **order**: order of an app within its group when sorting entries in it. The lower the order is, the closer to the start of the list the item is placed. _Used for ordering startup hooks and menu entries._
|
||||
- **sdk_headers**: list of C header files from this app's code to include in API definitions for external apps.
|
||||
- **targets**: list of strings and target names with which this app is compatible. If not specified, the app is built for all targets. The default value is `["all"]`.
|
||||
- **resources**: name of a folder within the app's source folder to be used for packacking SD card resources for this app. They will only be used if app is included in build configuration. The default value is `""`, meaning no resources are packaged.
|
||||
|
||||
#### Parameters for external apps
|
||||
|
||||
The following parameters are used only for [FAPs](./AppsOnSDCard.md):
|
||||
|
||||
- **sources**: list of strings, file name masks used for gathering sources within the app folder. The default value of `["*.c*"]` includes C and C++ source files. Apps cannot use the `"lib"` folder for their own source code, as it is reserved for **fap_private_libs**. Paths starting with `"!"` are excluded from the list of sources. They can also include wildcard characters and directory names. For example, a value of `["*.c*", "!plugins"]` will include all C and C++ source files in the app folder except those in the `plugins` (and `lib`) folders. Paths with no wildcards (`*, ?`) are treated as full literal paths for both inclusion and exclusion.
|
||||
- **fap_version**: string, app version. The default value is "0.1". You can also use a tuple of 2 numbers in the form of (x,y) to specify the version. It is also possible to add more dot-separated parts to the version, like patch number, but only major and minor version numbers are stored in the built .fap.
|
||||
- **fap_icon**: name of a `.png` file, 1-bit color depth, 10x10px, to be embedded within `.fap` file.
|
||||
- **fap_libs**: list of extra libraries to link the app against. Provides access to extra functions that are not exported as a part of main firmware at the expense of increased `.fap` file size and RAM consumption.
|
||||
- **fap_category**: string, may be empty. App subcategory, also determines the path of the FAP within the apps folder in the file system.
|
||||
- **fap_description**: string, may be empty. Short app description.
|
||||
- **fap_author**: string, may be empty. App's author.
|
||||
- **fap_weburl**: string, may be empty. App's homepage.
|
||||
- **fap_icon_assets**: string. If present, it defines a folder name to be used for gathering image assets for this app. These images will be preprocessed and built alongside the app. See [FAP assets](AppsOnSDCard.md) for details.
|
||||
- **fap_extbuild**: provides support for parts of app sources to be built by external tools. Contains a list of `ExtFile(path="file name", command="shell command")` definitions. `fbt` will run the specified command for each file in the list.
|
||||
- **fal_embedded**: boolean, default `False`. Applies only to PLUGIN type. If `True`, the plugin will be embedded into host app's .fap file as a resource and extracted to `apps_assets/APPID` folder on its start. This allows plugins to be distributed as a part of the host app.
|
||||
|
||||
Note that commands are executed at the firmware root folder, and all intermediate files must be placed in an app's temporary build folder. For that, you can use pattern expansion by `fbt`: `${FAP_WORK_DIR}` will be replaced with the path to the app's temporary build folder, and `${FAP_SRC_DIR}` will be replaced with the path to the app's source folder. You can also use other variables defined internally by `fbt`.
|
||||
|
||||
Example for building an app from Rust sources:
|
||||
|
||||
```python
|
||||
sources=["target/thumbv7em-none-eabihf/release/libhello_rust.a"],
|
||||
fap_extbuild=(
|
||||
ExtFile(
|
||||
path="${FAP_WORK_DIR}/target/thumbv7em-none-eabihf/release/libhello_rust.a",
|
||||
command="cargo build --release --verbose --target thumbv7em-none-eabihf --target-dir ${FAP_WORK_DIR}/target --manifest-path ${FAP_SRC_DIR}/Cargo.toml",
|
||||
),
|
||||
),
|
||||
```
|
||||
|
||||
- **fap_private_libs**: list of additional libraries distributed as sources alongside the app. These libraries will be built as a part of the app build process.
|
||||
Library sources must be placed in a subfolder of the `lib` folder within the app's source folder.
|
||||
Each library is defined as a call to the `Lib()` function, accepting the following parameters:
|
||||
|
||||
- **name**: name of the library's folder. Required.
|
||||
- **fap_include_paths**: list of the library's relative paths to add to the parent fap's include path list. The default value is `["."]`, meaning the library's source root.
|
||||
- **sources**: list of filename masks to be used for gathering include files for this library. Paths are relative to the library's source root. The default value is `["*.c*"]`.
|
||||
- **cflags**: list of additional compiler flags to be used for building this library. The default value is `[]`.
|
||||
- **cdefines**: list of additional preprocessor definitions to be used for building this library. The default value is `[]`.
|
||||
- **cincludes**: list of additional include paths to be used for building this library. Paths are relative to the app's root. This can be used for providing external search paths for this library's code — for configuration headers. The default value is `[]`.
|
||||
|
||||
Example for building an app with a private library:
|
||||
|
||||
```python
|
||||
fap_private_libs=[
|
||||
Lib(
|
||||
name="mbedtls",
|
||||
fap_include_paths=["include"],
|
||||
sources=[
|
||||
"library/des.c",
|
||||
"library/sha1.c",
|
||||
"library/platform_util.c",
|
||||
],
|
||||
cdefines=["MBEDTLS_ERROR_C"],
|
||||
),
|
||||
Lib(
|
||||
name="loclass",
|
||||
cflags=["-Wno-error"],
|
||||
),
|
||||
],
|
||||
```
|
||||
|
||||
For that snippet, `fbt` will build 2 libraries: one from sources in `lib/mbedtls` folder and another from sources in the `lib/loclass` folder. For the `mbedtls` library, `fbt` will add `lib/mbedtls/include` to the list of include paths for the app and compile only the files specified in the `sources` list. Additionally, `fbt` will enable `MBEDTLS_ERROR_C` preprocessor definition for `mbedtls` sources.
|
||||
For the `loclass` library, `fbt` will add `lib/loclass` to the list of the included paths for the app and build all sources in that folder. Also, `fbt` will disable treating compiler warnings as errors for the `loclass` library, which can be useful when compiling large 3rd-party codebases.
|
||||
|
||||
Both libraries will be linked with the app.
|
||||
|
||||
## .fam file contents
|
||||
|
||||
The `.fam` file contains one or more app definitions. For example, here's a part of `applications/service/bt/application.fam`:
|
||||
|
||||
```python
|
||||
App(
|
||||
appid="bt_start",
|
||||
apptype=FlipperAppType.STARTUP,
|
||||
entry_point="bt_on_system_start",
|
||||
order=70,
|
||||
)
|
||||
|
||||
App(
|
||||
appid="bt_settings",
|
||||
name="Bluetooth",
|
||||
apptype=FlipperAppType.SETTINGS,
|
||||
entry_point="bt_settings_app",
|
||||
stack_size=1 * 1024,
|
||||
requires=[
|
||||
"bt",
|
||||
"gui",
|
||||
],
|
||||
order=10,
|
||||
)
|
||||
```
|
||||
|
||||
For more examples, see `.fam` files from various firmware parts.
|
||||
@@ -1,83 +0,0 @@
|
||||
# FAP (Flipper App Package) {#apps_on_sd_card}
|
||||
|
||||
[fbt](./fbt.md) supports building apps as FAP files. FAPs are essentially `.elf` executables with extra metadata and resources bundled in.
|
||||
|
||||
FAPs are built with the `faps` target. They can also be deployed to the `dist` folder with the `fap_dist` target.
|
||||
|
||||
FAPs do not depend on being run on a specific firmware version. Compatibility is determined by the FAP's metadata, which includes the required [API version](#api-versioning).
|
||||
|
||||
## How to set up an app to be built as a FAP {#fap-howto}
|
||||
|
||||
FAPs are created and developed the same way as internal apps that are part of the firmware.
|
||||
|
||||
To build your app as a FAP, create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in app. Then configure its `application.fam` manifest, and set its `apptype` to `FlipperAppType.EXTERNAL`. See [Flipper App Manifests](AppManifests.md) for more details.
|
||||
|
||||
- To build your app, run `./fbt fap_{APPID}`, where APPID is your app's ID in its manifest.
|
||||
- To build your app and upload it over USB to run on Flipper, use `./fbt launch APPSRC=applications_user/path/to/app`. This command is configured in the default [VS Code profile](../.vscode/ReadMe.md) as a "Launch App on Flipper" build action (Ctrl+Shift+B menu).
|
||||
- To build an app without uploading it to Flipper, use `./fbt build APPSRC=applications_user/path/to/app`. This command is also available in VSCode configuration as "Build App".
|
||||
- To build all FAPs, run `./fbt faps` or `./fbt fap_dist`.
|
||||
|
||||
## FAP assets
|
||||
|
||||
FAPs can include static and animated images as private assets. They will be automatically compiled alongside app sources and can be referenced the same way as assets from the main firmware.
|
||||
|
||||
To use that feature, put your images in a subfolder inside your app's folder, then reference that folder in your app's manifest in the `fap_icon_assets` field. See [Flipper App Manifests](AppManifests.md) for more details.
|
||||
|
||||
To use these assets in your app, put `#include "{APPID}_icons.h"` in your app's source code, where `{APPID}` is the `appid` value field from your app's manifest. Then you can use all icons from your app's assets the same way as if they were a part of `assets_icons.h` of the main firmware.
|
||||
|
||||
Images and animated icons should follow the same [naming convention](../assets/ReadMe.md) as those from the main firmware.
|
||||
|
||||
## Debugging FAPs
|
||||
|
||||
`fbt` includes a script for gdb-py to provide debugging support for FAPs, `debug/flipperapps.py`. It is loaded in default debugging configurations by `fbt` and stock VS Code configurations.
|
||||
|
||||
With it, you can debug FAPs as if they were a part of the main firmware — inspect variables, set breakpoints, step through the code, etc.
|
||||
|
||||
If debugging session is active, firmware will trigger a breakpoint after loading a FAP into memory, but before running any code from it. This allows you to set breakpoints in the FAP's code. Note that any breakpoints set before the FAP is loaded may need re-setting after the FAP is actually loaded, since the debugger cannot know the exact address of the FAP's code before loading the FAP.
|
||||
|
||||
### Setting up debugging environment
|
||||
|
||||
The debugging support script looks up debugging information in the latest firmware build directory (`build/latest`). That directory is symlinked by `fbt` to the latest firmware configuration (Debug or Release) build directory when you run `./fbt` for the chosen configuration. See [fbt docs](fbt.md) for details.
|
||||
|
||||
To debug FAPs, do the following:
|
||||
|
||||
1. Build firmware with `./fbt`
|
||||
2. Flash it with `./fbt flash`
|
||||
3. [Build your FAP](#fap-howto) and run it on Flipper
|
||||
|
||||
After that, you can attach the debugger to the target MCU with `./fbt debug` or VS Code and use all debug features.
|
||||
|
||||
It is **important** that firmware and app build type (debug/release) match and that the matching firmware folder is linked as `build/latest`. Otherwise, debugging will not work.
|
||||
|
||||
## How Flipper runs an app from an SD card
|
||||
|
||||
Flipper's MCU cannot run code directly from external storage, so it needs to be copied to RAM first. That is done by the App Loader responsible for loading the FAP from the SD card, verifying its integrity and compatibility, copying it to RAM, and adjusting it for its new location.
|
||||
|
||||
Since the FAP has to be loaded to RAM to be executed, the amount of RAM available for allocations from heap is reduced compared to running the same app from flash, as a part of the firmware. Note that the amount of occupied RAM is less than the total FAP file size since only code and data sections are allocated, while the FAP file includes extra information only used at app load time.
|
||||
|
||||
Apps are built for a specific API version. It is a part of the hardware target's definition and contains a major and minor version number. The App Loader checks if the app's major API version matches the firmware's major API version.
|
||||
|
||||
The App Loader allocates memory for the app and copies it to RAM, processing relocations and providing concrete addresses for imported symbols using the [symbol table](#symbol-table). Then it starts the app.
|
||||
|
||||
## API versioning {#api-versioning}
|
||||
|
||||
Not all parts of firmware are available for external apps. A subset of available functions and variables is defined in the "api_symbols.csv" file, which is a part of the firmware target definition in the `targets/` directory.
|
||||
|
||||
`fbt` uses semantic versioning for the API. The major version is incremented when there are breaking changes in the API. The minor version is incremented when new features are added.
|
||||
|
||||
Breaking changes include:
|
||||
|
||||
- Removing a function or a global variable
|
||||
- Changing the signature of a function
|
||||
|
||||
API versioning is mostly automated by `fbt`. When rebuilding the firmware, `fbt` checks if there are any changes in the API exposed by headers gathered from `SDK_HEADERS`. If so, it stops the build, adjusts the API version, and asks the user to go through the changes in the `.csv` file. New entries are marked with a "`?`" mark, and the user is supposed to change the mark to "`+`" for the entry to be exposed for FAPs, or to "`-`" for it to be unavailable.
|
||||
|
||||
`fbt` will not allow building a firmware until all "`?`" entries are changed to "`+`" or "`-`".
|
||||
|
||||
**NB:** `fbt` automatically manages the API version. The only case where manually incrementing the major API version is allowed (and required) is when existing "`+`" entries are to be changed to "`-`".
|
||||
|
||||
### Symbol table {#symbol-table}
|
||||
|
||||
The symbol table is a list of symbols exported by firmware and available for external apps. It is generated by `fbt` from the API symbols file and is used by the App Loader to resolve addresses of imported symbols. It is build as a part of the `fap_loader` app.
|
||||
|
||||
`fbt` also checks if all imported symbols are present in the symbol table. If there are any missing symbols, it will issue a warning listing them. The app won't be able to run on the device until all required symbols are provided in the symbol table.
|
||||
@@ -1,16 +0,0 @@
|
||||
# This is a UPC-A Barcode Generator for the Flipper Zero hardware.
|
||||
|
||||
> Author: [McAzzaMan](https://github.com/McAzzaMan/flipperzero-firmware/tree/UPC-A_Barcode_Generator/applications/barcode_generator)
|
||||
|
||||
<img src="https://i.imgur.com/TDbo1tz.png" alt="" />
|
||||
|
||||
It will eventually be expanded into other barcode types. It currently only generates UPC-A type barcodes.
|
||||
|
||||
<img src="https://i.imgur.com/bxTdzuA.png" alt="" />
|
||||
|
||||
## Controls
|
||||
|
||||
Hitting the `centre` button on the Flipper toggles edit mode.
|
||||
When in edit mode, `Left` and `Right` will change the digit to be changed, and up and down will adjust the digit value.
|
||||
|
||||
<img src="https://i.imgur.com/lGbzdwH.png" alt="" />
|
||||
@@ -1,10 +0,0 @@
|
||||
# How to change Flipper name:
|
||||
|
||||
## Instruction
|
||||
1. Go to Settings -> Desktop -> Change Flipper Name
|
||||
2. Enter your new custom name for your flipper and click `Save`, **name will be saved on microSD card, and will stay same after firmware updates**
|
||||
3. You will see a message `Name is set!` and when you exit from settings -> flipper will automatically reboot!
|
||||
4. After reboot you will see your new custom name in device info and right screen `passport`
|
||||
5. Done!
|
||||
|
||||
**To reset device name to default - do same steps but do not enter any characters, leave it empty and click** `Save`
|
||||
@@ -1,12 +0,0 @@
|
||||
## How to extend SubGHz supported frequency range
|
||||
|
||||
#### CC1101 Frequency range specs: 300-348 MHz, 386-464 MHz, and 778-928 MHz (+ 350MHz and 467MHz was added to default range)
|
||||
#### This setting will extend to: 281-361 MHz, 378-481 MHz, and 749-962 MHz
|
||||
|
||||
1. Please do not do that unless you know what exactly you are doing
|
||||
2. You don't need extended range for almost all use cases
|
||||
3. Extending frequency range and transmitting on frequencies that outside of hardware specs can damage your hardware!
|
||||
4. Flipper Devices team and/or unleashed fw developers is not responsible of any damage that can be caused by using CFW or extending frequency ranges!!!
|
||||
|
||||
If you really sure you need that change, find `subghz/assets/dangerous_settings` file on your microSD, read comments on first lines
|
||||
and change `false` to `true`
|
||||
@@ -1,172 +0,0 @@
|
||||
# Expansion Module Protocol {#expansion_protocol}
|
||||
|
||||
## Terms and definitions
|
||||
|
||||
- Expansion Module: A third-party hardware unit meant for use with Flipper Zero by connecting it to its GPIO header.
|
||||
- Expansion Module Protocol: A serial-based, byte-oriented, synchronous communication protocol described in this document.
|
||||
- Host: Hardware unit tasked with serving requests. Used interchangeably with Flipper, Server, Host etc. throughout this document.
|
||||
- Device: Used interchangeably with Expansion Module, Module, Client, etc.
|
||||
- RPC: Remote Procedure Call, a protobuf-based communication protocol widely used by Flipper Zero companion applications.
|
||||
- Timeout Interval: Period of inactivity to be treated as a loss of connection, also denoted as Tto. Equals to 250 ms.
|
||||
- Baud Rate Switch Dead Time: Period of time after baud rate change during which no communication is allowed, also denoted Tdt. Equals to 25 ms.
|
||||
|
||||
## Features
|
||||
|
||||
- Automatic expansion module detection
|
||||
- Baud rate negotiation
|
||||
- Basic error detection
|
||||
- Request-response communication flow
|
||||
- Integration with Flipper RPC protocol
|
||||
|
||||
## Hardware
|
||||
|
||||
Depending on the UART selected for communication, the following pins area available for the expansion modules to connect to:
|
||||
|
||||
| UART | Tx pin | Rx pin |
|
||||
|--------|--------|--------|
|
||||
| USART | 13 | 14 |
|
||||
| LPUART | 15 | 16 |
|
||||
|
||||
## Frame structure
|
||||
|
||||
Each frame consists of a header (1 byte), contents (size depends on frame type) and checksum (1 byte) fields:
|
||||
|
||||
| Header (1 byte) | Contents (0 or more bytes) | Checksum (1 byte) |
|
||||
|-----------------|----------------------------|-------------------|
|
||||
| Frame type | Frame payload | XOR checksum |
|
||||
|
||||
### Heartbeat frame
|
||||
|
||||
HEARTBEAT frames are used to maintain an idle connection. In the event of not receiving any frames within Tto, either side must cease all communications and be ready to initiate the connection again.
|
||||
|
||||
| Header (1 byte) | Checksum (1 byte) |
|
||||
|-----------------|-------------------|
|
||||
| 0x01 | XOR checksum |
|
||||
|
||||
Note that the contents field is not present (0 bytes length).
|
||||
|
||||
### Status frame
|
||||
|
||||
STATUS frames are used to report the status of a transaction. Every received frame MUST be confirmed by a matching STATUS response.
|
||||
|
||||
| Header (1 byte) | Contents (1 byte) | Checksum (1 byte) |
|
||||
|-----------------|-------------------|-------------------|
|
||||
| 0x02 | Error code | XOR checksum |
|
||||
|
||||
The `Error code` field SHALL have one of the following values:
|
||||
|
||||
| Error code | Meaning |
|
||||
|------------|-------------------------|
|
||||
| 0x00 | OK (No error) |
|
||||
| 0x01 | Unknown error |
|
||||
| 0x02 | Baud rate not supported |
|
||||
|
||||
### Baud rate frame
|
||||
|
||||
BAUD RATE frames are used to negotiate communication speed. The initial connection SHALL always happen at 9600 baud. The first message sent by the module MUST be a BAUD RATE frame, even if a different speed is not required.
|
||||
|
||||
| Header (1 byte) | Contents (4 bytes) | Checksum (1 byte) |
|
||||
|-----------------|--------------------|-------------------|
|
||||
| 0x03 | Baud rate | XOR checksum |
|
||||
|
||||
If the requested baud rate is supported by the host, it SHALL respond with a STATUS frame with an OK error code, otherwise the error code SHALL be 0x02 (Baud rate not supported). Until the negotiation succeeds, the speed SHALL remain at 9600 baud. The module MAY send additional BAUD RATE frames with alternative speeds in case the initial request was refused. No other frames are allowed until the speed negotiation succeeds.
|
||||
|
||||
### Control frame
|
||||
|
||||
CONTROL frames are used to control various aspects of the communication and enable/disable various device features.
|
||||
|
||||
| Header (1 byte) | Contents (1 byte) | Checksum (1 byte) |
|
||||
|-----------------|-------------------|-------------------|
|
||||
| 0x04 | Command | XOR checksum |
|
||||
|
||||
The `Command` field SHALL have one of the following values:
|
||||
|
||||
| Command | Meaning | Note |
|
||||
|---------|--------------------------|:----:|
|
||||
| 0x00 | Start RPC session | 1 |
|
||||
| 0x01 | Stop RPC session | 2 |
|
||||
| 0x02 | Enable OTG (5V) on GPIO | 3 |
|
||||
| 0x03 | Disable OTG (5V) on GPIO | 3 |
|
||||
|
||||
Notes:
|
||||
|
||||
1. Must only be used while the RPC session NOT active.
|
||||
2. Must only be used while the RPC session IS active.
|
||||
3. See 1, otherwise OTG is to be controlled via RPC messages.
|
||||
|
||||
### Data frame
|
||||
|
||||
DATA frames are used to transmit arbitrary data in either direction. Each DATA frame can hold up to 64 bytes. If an RPC session is currently open, all received bytes are forwarded to it.
|
||||
|
||||
| Header (1 byte) | Contents (1 to 65 byte(s)) | Checksum (1 byte) |
|
||||
|-----------------|----------------------------|-------------------|
|
||||
| 0x05 | Data | XOR checksum |
|
||||
|
||||
The `Data` field SHALL have the following structure:
|
||||
|
||||
| Data size (1 byte) | Data (0 to 64 bytes) |
|
||||
|--------------------|----------------------|
|
||||
| 0x00 ... 0x40 | Arbitrary data |
|
||||
|
||||
## Communication flow
|
||||
|
||||
In order for the host to be able to detect the module, the respective feature must be enabled first. This can be done via the GUI by going to `Settings → Expansion Modules` and selecting the required `Listen UART` or programmatically by calling `expansion_enable()`. Likewise, disabling this feature via the same GUI or by calling `expansion_disable()` will result in ceasing all communications and not being able to detect any connected modules.
|
||||
|
||||
The communication is always initiated by the module by the means of shortly pulling the RX pin down. The host SHALL respond with a HEARTBEAT frame indicating that it is ready to receive requests. The module then MUST issue a BAUDRATE request within Tto. Failure to do so will result in the host dropping the connection and returning to its initial state.
|
||||
|
||||
```
|
||||
MODULE | FLIPPER
|
||||
-----------------------------+---------------------------
|
||||
| (Start)
|
||||
Pull down RX -->
|
||||
<-- Heartbeat
|
||||
Baud Rate -->
|
||||
<-- Status [OK | Error]
|
||||
|
|
||||
(Module changes baud rate | (Flipper changes
|
||||
and waits for Tdt) | baud rate)
|
||||
|
|
||||
Control [Start RPC] -->
|
||||
<-- Status [OK | Error]
|
||||
-----------------------------+--------------------------- (1)
|
||||
Data [RPC Request] -->
|
||||
<-- Status [OK | Error]
|
||||
<-- Data [RPC Response]
|
||||
Status [OK | Error] -->
|
||||
-----------------------------+--------------------------- (2)
|
||||
Data [RPC Request pt.1] -->
|
||||
<-- Status [OK | Error]
|
||||
Data [RPC Request pt.2] -->
|
||||
<-- Status [OK | Error]
|
||||
Data [RPC Request pt.3] -->
|
||||
<-- Status [OK | Error]
|
||||
<-- Data [RPC Response]
|
||||
Status [OK | Error] -->
|
||||
-----------------------------+--------------------------- (3)
|
||||
Heartbeat -->
|
||||
<-- Heartbeat
|
||||
Heartbeat -->
|
||||
<-- Heartbeat
|
||||
-----------------------------+---------------------------
|
||||
Control [Stop RPC] -->
|
||||
<-- Status [OK | Error]
|
||||
(Module disconnected) |
|
||||
| (No activity within Tto
|
||||
| return to start)
|
||||
|
||||
(1) The module MUST confirm all implicitly requested frames (e.g. DATA frames containing RPC responses) with a STATUS frame.
|
||||
(2) RPC requests larger than 64 bytes are split into multiple frames. Every DATA frame MUST be confirmed with a STATUS frame.
|
||||
(3) When the module has no data to send, it MUST send HEARTBEAT frames with a period < Tto in order to maintain the connection.
|
||||
The host SHALL respond with a HEARTBEAT frame each time.
|
||||
```
|
||||
|
||||
## Error detection
|
||||
|
||||
Error detection is implemented via adding an extra checksum byte to every frame (see above).
|
||||
|
||||
The checksum is calculated by bitwise XOR-ing every byte in the frame (excluding the checksum byte itself), with an initial value of 0.
|
||||
|
||||
### Error recovery behaviour
|
||||
|
||||
In the event of a detected error, the concerned side MUST cease all communications and reset to initial state. The other side will then experience
|
||||
a communication timeout and the connection will be re-established automatically.
|
||||
@@ -1,372 +0,0 @@
|
||||
# FAQ
|
||||
|
||||
## I bought Flipper Zero, and I don't know what I can do with it, please help!
|
||||
|
||||
- Start with reading [official main page](https://flipperzero.one/)
|
||||
- Then check out official docs where you can find answers to [most questions](https://docs.flipper.net/)
|
||||
|
||||
## How do I install Unleashed Firmware?
|
||||
|
||||
See [this](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
## What version should I install? What do the letters `e`, `c`... mean?
|
||||
|
||||
Follow this link for [details](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/CHANGELOG.md#recommended-update-option---web-updater).
|
||||
|
||||
## I installed Unleashed and now the backlight doesn't work
|
||||
|
||||
You’ve enabled RGB backlight mod in settings made for custom RGB modded flippers. <br />
|
||||
|
||||
Please, do not use that version if your flipper isn’t modded!
|
||||
Disable in Settings -> LCD & Notifications -> RGB mod settings
|
||||
|
||||
If you have RGB backlight mod do the same but enable the mod instead
|
||||
|
||||
## What apps (plugins) are included with Unleashed Firmware?
|
||||
|
||||
See default pack and extra pack (for `e` build) list [here](https://github.com/xMasterX/all-the-plugins/tree/dev).
|
||||
|
||||
## Where can I find differences between the original (official) firmware and Unleashed Firmware?
|
||||
|
||||
[Right here](https://github.com/DarkFlippers/unleashed-firmware#whats-changed)
|
||||
|
||||
## How to use the SubGHz Remote app?
|
||||
|
||||
1. Open the app, press the `Back` button, and select `New map file`
|
||||
2. Configure signal files and their names for every button (also you can only add one signal and make other buttons empty - just don't select any files for them in config)
|
||||
3. Save the new map file
|
||||
4. Open the map file and select your previously created file
|
||||
5. Use buttons to send the subghz signal files that you selected in map config at step 2
|
||||
|
||||
## Where can I find what SubGHz protocols (manufacturers) are supported and what frequency and modulation to use with them?
|
||||
|
||||
Here - [link](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSupportedSystems.md).
|
||||
|
||||
## I want to request or make new SubGHz protocol, my remote (is not car keyfob) and is not supported, how to record RAW signal properly?
|
||||
|
||||
1. Open SubGHz app, (if you know the frequency skip that step and go to Read) select Frequency analyzer, press and hold button on your remote and place it near IR window on flipper<br />
|
||||
You will find a approx. frequency that remote uses, release button on the remote and wait until frequency will be placed in history list<br />
|
||||
Hold OK on flipper to jump into Read mode, now try pressing your remote couple times holding it for at least 2 seconds<br />
|
||||
Try different modulations, AM650/FM238/FM476/FM12K - nothing works? Lets make RAW recording for analysis<br />
|
||||
2. Knowing the frequency open Read RAW and set it here in config page<br />
|
||||
Make sure RSSI Threshold is set to (----)<br />
|
||||
You need to make 1 RAW for each modulation AM650/FM238/FM476/FM12K<br />
|
||||
Press REC and on your remote press 1 button 5 times holding it for 1-2 seconds - then 5 times holding it for 5 seconds each time<br />
|
||||
If your remote has more than 1 button - record each button in similar way<br />
|
||||
Label each raw - what button you recorded
|
||||
3. Copy all that RAW files to PC and create issue in firmware repo, attach raw's in archive<br />
|
||||
Provide high quality photos of the remote, if possible - photos of disassembled remote too<br />
|
||||
Its model, manufacturer, any known information<br />
|
||||
If you have access to receiver board, add a photo too<br />
|
||||
Done! If your remote appears not to be encrypted and very unique, it might be added soon<br />
|
||||
In case if you want to help us or analyze that signals youself there's a great online tool - https://lab.flipper.net/pulse-plotter
|
||||
|
||||
## How to build (compile) the firmware?
|
||||
|
||||
Follow this [link](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToBuild.md#how-to-build-by-yourself).
|
||||
|
||||
## I installed Unleashed firmware, and now my mobile app doesn't connect to flipper ( OR I changed flipper device name, and my mobile app now doesn't connect to flipper )
|
||||
|
||||
1. Click Forget flipper in the mobile app
|
||||
2. Open `Phone Settings - Bluetooth`, find the flipper - if it present here - open its options and click forget device
|
||||
3. On the flipper itself open `Settings -> Bluetooth -> Forget all devices` and confirm
|
||||
4. Make sure your flipper has bluetooth `ON` then open the mobile app and pair it to the flipper
|
||||
|
||||
## My desktop (pin, favourites, etc..) (or other) settings were reset to default after an update, what do I do?
|
||||
|
||||
Just configure those settings again, and make sure you view the changelogs for the releases that came out after your previous version, when settings struct is changed, the settings file is reset after an update, this happens only when struct changes are required, so don't assume that settings will be reset in every release, this will only happen in specific ones
|
||||
|
||||
## Why is my flipper not connecting to Chrome?
|
||||
|
||||
The most common cause of the flipper not connecting to google chrome is having qFlipper open while trying to connect your flipper. <br />
|
||||
|
||||
Or having second flipper lab page open at same time.<br />
|
||||
|
||||
You must close qFlipper (or other flipper lab web pages) before attempting to connect your flipper to Chrome.
|
||||
|
||||
## Flipper doesn't work! How to restore firmware?
|
||||
|
||||
Follow this [guide](https://docs.flipper.net/basics/firmware-update/firmware-recovery)
|
||||
|
||||
## Useful links and files
|
||||
|
||||
Flipper Awesome - place where you can find almost all links that you might need:<br />
|
||||
* [Awesome-FlipperZero](https://github.com/djsime1/awesome-flipperzero)
|
||||
* Dict files for iButton Fuzzer and RFID Fuzzer:<br />
|
||||
* https://t.me/flipperzero_unofficial_ru/37058 <br />
|
||||
* https://t.me/flipperzero_unofficial_ru/37072
|
||||
* UL Releases in [Telegram](https://t.me/unleashed_fw)
|
||||
* UL Dev Builds in [Telegram](https://t.me/kotnehleb)
|
||||
* Our [Discord](https://discord.unleashedflip.com)
|
||||
|
||||
## How do I change my flipper's name?
|
||||
|
||||
It's easy:
|
||||
1. Open `Settings -> Desktop -> Change Flipper Name`
|
||||
2. Enter new name and click `Save`
|
||||
3. Exit from settings - flipper will automatically reboot
|
||||
4. Done, you now have a custom name which will stay until you reset it or replace it with a new one
|
||||
|
||||
## How to reset the name to default?
|
||||
|
||||
1. Open `Settings -> Desktop -> Change Flipper Name`
|
||||
2. Do not enter anything, just click `Save`
|
||||
3. Exit from settings - Flipper will automatically reboot
|
||||
4. Done, name is reset to its original form.
|
||||
|
||||
## How do I copy files from GitHub to my Flipper Zero?
|
||||
|
||||
Follow this detailed [guide](https://github.com/wrenchathome/flipperfiles/blob/main/_Guides/How2Flipper.pdf).
|
||||
|
||||
## Where can I find “This file” or “That file” for my flipper?
|
||||
|
||||
These 2 repos will cover (99.9%) of your needs:<br />
|
||||
* https://github.com/UberGuidoZ/Flipper/tree/main
|
||||
* https://github.com/UberGuidoZ/Flipper-IRDB/tree/main
|
||||
|
||||
## How can I support the Unleashed firmware project?
|
||||
|
||||
Please follow this [link](https://github.com/DarkFlippers/unleashed-firmware#please-support-development-of-the-project).
|
||||
|
||||
## What are the dev builds? Where I can get the latest build for dev branch?
|
||||
|
||||
This is an automatic assembly of the latest commits from this repository that have not yet been released. The previous build is deleted when a new one is uploaded, and the old one remains only as a file in the telegram channel
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Be wary - these are not release ready builds!
|
||||
>
|
||||
> They may have bugs and issues!
|
||||
> If you are using the dev build and find issues:
|
||||
> Report it! [GitHub issues](https://github.com/DarkFlippers/unleashed-firmware/issues)
|
||||
|
||||
Dev builds are available in Discord, in channel - `unleashed-development` <br />
|
||||
Builds can also be found [here](https://t.me/kotnehleb).<br />
|
||||
And [here](https://dev.unleashedflip.com/)<br />
|
||||
|
||||
## What is the update server?
|
||||
|
||||
We have our own update server https://up.unleashedflip.com/directory.json <br /><br />
|
||||
It is identical to the official one; it is impossible to change it in applications without rebuilding the application <br /><br />
|
||||
If you want to use it, you need to patch or build your own build of the application you are interested in <br />
|
||||
|
||||
Also you can use it with uFBT to build apps for UL SDK - uFBT will accept that link as one of args<br />
|
||||
|
||||
The server will remain active and will be automatically updated
|
||||
|
||||
## External Radio: How to connect the CC1101 module
|
||||
|
||||
[Guide](https://github.com/quen0n/flipperzero-ext-cc1101)
|
||||
|
||||
## How to add extra Sub-GHz frequencies
|
||||
|
||||
[Guide](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
||||
|
||||
## How to use Flipper as new SubGHz remote (Nice FlorS, BFT Mitto, Somfy Telis, Aprimatic, AN-Motors, etc..)
|
||||
|
||||
[Guide](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
|
||||
## How Can I Unlock / Remove SubGHz restriction?
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> If you are using Unleashed Firmware - **all region locks are removed by default**!
|
||||
|
||||
Also, there is a way to go outside of frequencies stated in `CC1101 datasheet`, but transmission on those frequencies may cause chip damage, make sure you know what you are doing!
|
||||
|
||||
Do not edit these settings to bypass region lock since there is no region locks in unleashed, all chip supported frequencies will work without any extra steps.<br /><br />
|
||||
|
||||
But, if you know that you need to bypass subghz chip safety restrictions - you can unlock the safety restriction which will allow you to go outside the chips supported frequency. <br /><br />
|
||||
This covers how to do it and information regarding the risks of damage to the flipper by doing so.
|
||||
|
||||
Please read [this](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md) before.
|
||||
|
||||
## Can I clone a car key fob for my own car to use my flipper as a key?
|
||||
|
||||
No, and trying to do so with Read RAW will lead to key desync or unpair with blacklist which means re-pair is very hard to do and requires service tools
|
||||
|
||||
## How to clean .DS_Store and other dot files left from macOS
|
||||
|
||||
`sudo dot_clean -mn /Volumes/Flipper\ SD` -> `Flipper\ SD` may be named differently for you, replace it with your microSD card name
|
||||
|
||||
## How to sort files on flipper microSD on macOS / Linux?
|
||||
|
||||
Will make sorting faster, and will work for OFW:
|
||||
1. `brew install fatsort` -> Install fatsort using `brew.sh` (only on macOS)
|
||||
2. `diskutil list` -> Find your disk name for flipper microSD
|
||||
3. `diskutil unmount /Volumes/Flipper\ SD`
|
||||
4. `sudo fatsort -n /dev/disk4s1` -> Replace `disk4s1` with your microSD id found on step 2
|
||||
|
||||
## My flipper feels slow and unresponsive?
|
||||
|
||||
1. Make sure you are using a good microSD card from a known brand. Flipper works with microSD via SPI meaning not all microSDs will work well even if they are compatible with other devices.
|
||||
2. Go into `Settings -> System` and make sure that you have
|
||||
```text
|
||||
Log Level = None
|
||||
Debug = OFF
|
||||
Heap Trace = None
|
||||
```
|
||||
3. If some settings are set to something different - change them to `None` / `OFF`
|
||||
4. Make sure your battery is charged, that can affect performance too
|
||||
|
||||
## Flipper crashed, stuck, frozen?
|
||||
|
||||
Reboot it by holding `Left` + `Back` buttons
|
||||
|
||||

|
||||
|
||||
## How to reset a forgotten Flipper pin code?
|
||||
|
||||
**Disconnect USB Cable if it was connected**
|
||||
1. Turn off the device - hold back button -> `Turn Off`
|
||||
**If you can't turn it off, try the next step but hold the buttons for 30-40 seconds)**
|
||||
2. Hold <kbd>Up</kbd> + <kbd>Back</kbd> for `~5 sec` -> You will see a reset screen -> Hold <kbd>Right</kbd> to reset (and <kbd>Down</kbd> arrow to exit if you don't want to reset your pin code)
|
||||
3. Done, user config (some settings, pin code) is erased to default factory setup, user files on microSD will stay
|
||||
|
||||
## What are the differences between x, y, and z firmware?
|
||||
|
||||
If you just got your flipper and not sure what will work better for you, start with original official firmware, if you think you need more features or want to remove subghz region locks then:<br />
|
||||
* Try installing **Unleashed firmware**, which is fork of official firmware with many new features and preinstalled apps (check out `e` build).<br />
|
||||
* In other case, If you want to experiment more with UI and other things look for existing forks of Unleashed Firmware.<br />
|
||||
* Or, create your own fork with your own customisations<br />
|
||||
* Also, before reporting any found issues, make sure you are in correct repo, if you are not using **Unleashed**, but a different fork or the original firmware, do not report issue in **Unleashed firmware** repo or UL communities (Telegram, Discord, etc..)
|
||||
|
||||
## Is there a correct way to capture Infrared signals?
|
||||
|
||||
There is indeed, especially with AC units - a new documentation has been released with some notes and steps on capturing infrared signals correctly along with some example data so you visually able to understand the difference between the two.
|
||||
|
||||
[More info](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/InfraredCaptures.md)
|
||||
|
||||
## NFC / RFID FAQ
|
||||
|
||||
From our good friends `@Equip` and `@np0` <br />
|
||||
|
||||
### MIFARE Ultralight
|
||||
|
||||
Scan the card, hold the Flipper Zero up to the reader to get the password to unlock the rest of the sectors, then scan the card again.
|
||||
|
||||
### MIFARE DESFire / MIFARE Ultralight C
|
||||
|
||||
The Flipper Zero has no available attacks for this card currently.
|
||||
|
||||
### Bank cards
|
||||
|
||||
- You cannot clone bank cards
|
||||
- The Flipper Zero cannot emulate bank cards
|
||||
- The Flipper Zero cannot pretend to be a point of sale machine
|
||||
|
||||
### Amiibos
|
||||
|
||||
- `NTAG215`. That's it. It's not going on a MIFARE Classic.
|
||||
- Currently, you cannot write Amiibos to new physical tags.
|
||||
|
||||
### HID / iClass
|
||||
|
||||
- `Picopass` iClass can be read using the `Picopass` reader plugin
|
||||
- 26bit Picopass can be downgraded to H10301 RFID credentials (note, it is not guaranteed to work if the reader is not configured to read low frequency)
|
||||
- Readers will need to be configured and have an LF RFID antenna in order to be read. Certain iClass readers are HF only, and do not have the ability to have LF configured.
|
||||
- **Emulation for Picopass** was added on July 26th, and the updated version can be found in latest releases of **Unleashed** Firmware with apps preinstalled, or in official Apps Hub via Flipper Mobile app
|
||||
- Write support for personalization mode cards is doable with the app
|
||||
- The Seader app and a [SAM expansion board](https://www.redteamtools.com/nard-sam-expansion-board-for-flipper-zero-with-hid-seos-iclass-sam/) will allow you to read more secure HID cards, which may be helpful in downgrade attacks
|
||||
|
||||
### LF-RFID
|
||||
|
||||
If you want to make clones of low frequency RFID chips you need to write to T5577's. `Blanks` do not exist. All of the chips the Flipper Zero can interact with are read-only and cannot be overwritten or purchased blank.
|
||||
|
||||
T5577s are multi-emulator chips that the Flipper Zero can program to be other tags
|
||||
|
||||
### Unknown Card / Fob
|
||||
|
||||
If you have exhausted all options of scanning via NFC / RFID / PICOPASS then take a photo of:
|
||||
|
||||
- The front and back of your credential
|
||||
- The reader you use with the credential
|
||||
- If your credential is a card, hold it up to a very bright light source e.g. a lightbulb and take a photo of the exposed antenna. This is useful for identification, post it for us to identify!
|
||||
|
||||
## How do I access the CLI / Logs?
|
||||
|
||||
To access the Serial CLI, click one of the following based on your platform.
|
||||
|
||||
<blockquote>
|
||||
<details>
|
||||
<summary>Desktop web browser*</summary>
|
||||
<em>*Chromium browsers only, such as: Google Chrome, Microsoft Edge, Opera / Opera GX, Brave, and Vivaldi.</em>
|
||||
<ul>
|
||||
<li>Connect your Flipper via USB.</li>
|
||||
<li>Ensure qFlipper and any other serial terminals are closed.</li>
|
||||
<li>Open <a href="https://lab.flipper.net/cli">lab.flipper.net/cli</a> in one of the aforementioned browsers.</li>
|
||||
<li>Click <kbd>CONNECT</kbd> and select <kbd>USB Serial Device</kbd> from the list.</li>
|
||||
<li>Wait until you can see your device details on screen.</li>
|
||||
<li>Select the 💻 CLI item from the left sidebar.</li>
|
||||
<li><strong>Done!</strong></li>
|
||||
</ul>
|
||||
</details>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<details>
|
||||
<summary>Windows</summary>
|
||||
<ul>
|
||||
<li>Install <a href="https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html">PuTTY</a> if it isn't already.</li>
|
||||
<li>Connect your Flipper via USB.</li>
|
||||
<li>Open qFlipper and look for the COM port next to the Flipper's name. <em> (Should say COM followed by a number, like <kbd>COM1</kbd>)</em></li>
|
||||
<li>Take note of the COM port number.</li>
|
||||
<li><strong>CLOSE qFlipper</strong>, otherwise the next steps won't work.</li>
|
||||
<li>Open PuTTY and ensure you're on the Session screen.</li>
|
||||
<li>Select <kbd>Serial</kbd> under connection type.</li>
|
||||
<li>Set serial line to the COM port. <em> (Just COM followed by the number, like <kbd>COM1</kbd>)</em></li>
|
||||
<li>Set speed to <code>115200</code></li>
|
||||
<li><em>Optional: Save the session settings for easy connection later.</em></li>
|
||||
<li>Finally, click <kbd>Open</kbd> to enter the CLI.</li>
|
||||
<li><strong>Done!</strong></li>
|
||||
<li>If you get an "Access Denied" error, make sure qFlipper isn't running!</li>
|
||||
</ul>
|
||||
</details>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<details>
|
||||
<summary>MacOS/Linux</summary>
|
||||
<em>Note: I'm a filthy Windows user without any way to verify this procedure. Let me know if it's wrong!</em>
|
||||
<ul>
|
||||
<li>Install <a href="https://www.gnu.org/software/screen/">GNU Screen</a> if it isn't already.</li>
|
||||
<li>Connect your Flipper via USB.</li>
|
||||
<li>Open qFlipper and look for the device path next to the Flipper's name. <em>(Starts with /dev/tty)</em></li>
|
||||
<li><em>Alternatively: Run <code>ls /dev/tty.*</code> in a terminal.</em></li>
|
||||
<li>Take note of the full device path.</li>
|
||||
<li><strong>CLOSE qFlipper</strong>, otherwise the next steps won't work.</li>
|
||||
<li>Open a terminal.</li>
|
||||
<li>Run <code>screen PATH 115200</code>, replacing PATH with the device path from earlier.</li>
|
||||
<li><strong>Done!</strong></li>
|
||||
</ul>
|
||||
</details>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<details>
|
||||
<summary>Android</summary>
|
||||
<ul>
|
||||
<li>Install <a href="https://play.google.com/store/apps/details?id=de.kai_morich.serial_usb_terminal">Serial USB Terminal</a> if it isn't already.</li>
|
||||
<li>Open the app and go to the Connections screen in the hamburger menu <em>(3 bars icon)</em></li>
|
||||
<li>Connect your Flipper via USB.</li>
|
||||
<li>Click the refresh icon if it doesn't automatically show up.</li>
|
||||
<li>Allow Serial USB Terminal to access Flipper if prompted.</li>
|
||||
<li>If it doesn't automatically connect, click the connect icon in the upper right. <em>(2 plugs icon)</em></li>
|
||||
<li><strong>Done!</strong></li>
|
||||
<li><em>Note: To exit log mode, you'll have to disconnect and reconnect using the icon.</em></li>
|
||||
</ul>
|
||||
</details>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<details>
|
||||
<summary>iPhone</summary>
|
||||
Unfortunately, iOS is incapable of accessing a serial terminal over USB; try one of the other methods<br />
|
||||
<ul>
|
||||
<li>On the Flipper, open the settings, go to System, and set Log Level to Debug. <em>(You can keep Debug set to off unless someone asks you to turn it on)</em></li>
|
||||
<li>Once you have the CLI open, type <code>log</code> and press enter to start watching logs. Press <kbd>Ctrl-C</kbd> or <kbd>Cmd-C</kbd> to exit log mode.</li>
|
||||
</ul>
|
||||
</details>
|
||||
</blockquote>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
**CLI FAQ Source + Check out this FAQ for more info:**<br /><br />
|
||||
https://github.com/djsime1/awesome-flipperzero/blob/main/FAQ.md
|
||||
@@ -1,40 +0,0 @@
|
||||
# Run time checks and forced system crash {#furi_check}
|
||||
|
||||
The best way to protect system integrity is to reduce amount cases that we must handle and crash the system as early as possible.
|
||||
For that purpose, we have a bunch of helpers located in Furi Core `check.h`.
|
||||
|
||||
## Couple notes before start
|
||||
|
||||
- Definition of Crash — log event, save crash information in RTC and reboot the system.
|
||||
- Definition of Halt — log event, stall the system.
|
||||
- Debug and production builds behave differently: debug build will never reset system in order to preserve state for debugging.
|
||||
- If you have debugger connected we will stop before reboot automatically.
|
||||
- All helpers accept optional MESSAGE_CSTR: it can be in RAM or Flash memory, but only messages from Flash will be shown after system reboot.
|
||||
- MESSAGE_CSTR can be NULL, but macros magic already doing it for you, so just don't.
|
||||
|
||||
## `furi_assert(CONDITION)` or `furi_assert(CONDITION, MESSAGE_CSTR)`
|
||||
|
||||
Assert condition in development environment and crash the system if CONDITION is false.
|
||||
|
||||
- Should be used at development stage in apps and services.
|
||||
- Keep in mind that release never contains this check.
|
||||
- Keep in mind that libraries never contain this check by default, use `LIB_DEBUG=1` if you need it.
|
||||
- Avoid putting function calls into CONDITION, since it may be omitted in some builds.
|
||||
|
||||
## `furi_check(CONDITION)` or `furi_check(CONDITION, MESSAGE_CSTR)`
|
||||
|
||||
Always assert condition and crash the system if CONDITION is false.
|
||||
|
||||
- Use it if you always need to check conditions
|
||||
|
||||
## `furi_crash()` or `furi_crash(MESSAGE_CSTR)`
|
||||
|
||||
Crash the system.
|
||||
|
||||
- Use it to crash the system. For example, if an abnormal condition is detected.
|
||||
|
||||
## `furi_halt()` or `furi_halt(MESSAGE_CSTR)`
|
||||
|
||||
Halt the system.
|
||||
|
||||
- We use it internally to shutdown Flipper if poweroff is not possible.
|
||||
@@ -1,117 +0,0 @@
|
||||
# Using FuriHalBus API {#furi_hal_bus}
|
||||
|
||||
## Basic info
|
||||
|
||||
On system startup, most of the peripheral devices are under reset and not clocked by default. This is done to reduce power consumption and to guarantee that the device will always be in the same state before use.
|
||||
|
||||
Some crucial peripherals are enabled right away by the system, others must be explicitly enabled by the user code.
|
||||
|
||||
**NOTE:** Here and afterwards, the word *"system"* refers to any code belonging to the operating system, hardware drivers or built-in apps.
|
||||
|
||||
To **ENABLE** a peripheral, call `furi_hal_bus_enable()`. At the time of the call, the peripheral in question **MUST** be disabled;
|
||||
otherwise a crash will occur to indicate improper use. This means that any given peripheral cannot be enabled twice or more without disabling it first.
|
||||
|
||||
To **DISABLE** a peripheral, call `furi_hal_bus_disable()`. Likewise, the peripheral in question **MUST** be enabled, otherwise a crash will occur.
|
||||
|
||||
To **RESET** a peripheral, call `furi_hal_bus_reset()`. The peripheral in question MUST be enabled, otherwise a crash will occur.
|
||||
This method is used whenever it is necessary to reset all the peripheral's registers to their initial states without disabling it.
|
||||
|
||||
## Peripherals
|
||||
|
||||
Built-in peripherals are divided into three categories:
|
||||
- Enabled by the system on startup, never disabled;
|
||||
- Enabled and disabled by the system on demand;
|
||||
- Enabled and disabled by the user code.
|
||||
|
||||
### Always-on peripherals
|
||||
|
||||
Below is the list of peripherals that are enabled by the system. The user code must **NEVER** attempt to disable them.
|
||||
|
||||
*Table 1* — Peripherals enabled by the system
|
||||
|
||||
| Peripheral | Enabled at |
|
||||
|:-------------:|:---------------------------:|
|
||||
| DMA1 | `furi_hal_dma.c` |
|
||||
| DMA2 | -- |
|
||||
| DMAMUX | -- |
|
||||
| GPIOA | `furi_hal_resources.c` |
|
||||
| GPIOB | -- |
|
||||
| GPIOC | -- |
|
||||
| GPIOD | -- |
|
||||
| GPIOE | -- |
|
||||
| GPIOH | -- |
|
||||
| PKA | `furi_hal_bt.c` |
|
||||
| AES2 | -- |
|
||||
| HSEM | -- |
|
||||
| IPCC | -- |
|
||||
| FLASH | enabled by hardware |
|
||||
|
||||
### On-demand system peripherals
|
||||
|
||||
Below is the list of peripherals that are enabled and disabled by the system. The user code must avoid using them directly, preferring the respective APIs instead.
|
||||
|
||||
When not using the API, these peripherals MUST be enabled by the user code and then disabled when not needed anymore.
|
||||
|
||||
*Table 2* — Peripherals enabled and disabled by the system
|
||||
|
||||
| Peripheral | API header file |
|
||||
|:--------------:|:------------------------:|
|
||||
| RNG | `furi_hal_random.h` |
|
||||
| SPI1 | `furi_hal_spi.h` |
|
||||
| SPI2 | -- |
|
||||
| I2C1 | `furi_hal_i2c.h` |
|
||||
| I2C3 | -- |
|
||||
| USART1 | `furi_hal_serial.h` |
|
||||
| LPUART1 | -- |
|
||||
| USB | `furi_hal_usb.h` |
|
||||
|
||||
### On-demand shared peripherals
|
||||
|
||||
Below is the list of peripherals that are not enabled by default and **MUST** be enabled by the user code each time it accesses them.
|
||||
|
||||
Note that some of these peripherals may also be used by the system to implement its certain features.
|
||||
|
||||
The system will take over any given peripheral only when the respective feature is in use.
|
||||
|
||||
*Table 3* — Peripherals enabled and disabled by user
|
||||
|
||||
| Peripheral | System | Purpose |
|
||||
|:----------:|:------:|:----------------------------------------|
|
||||
| CRC | | |
|
||||
| TSC | | |
|
||||
| ADC | | |
|
||||
| QUADSPI | | |
|
||||
| TIM1 | yes | subghz, lfrfid, nfc, infrared, etc... |
|
||||
| TIM2 | yes | subghz, infrared, etc... |
|
||||
| TIM16 | yes | speaker |
|
||||
| TIM17 | yes | cc1101_ext |
|
||||
| LPTIM1 | yes | tickless idle timer |
|
||||
| LPTIM2 | yes | pwm |
|
||||
| SAI1 | | |
|
||||
| LCD | | |
|
||||
|
||||
## DMA
|
||||
|
||||
The `DMA1`, `DMA2` peripherals are a special case in that they have multiple independent channels.
|
||||
Some channels may be in use by the system.
|
||||
|
||||
Below is the list of DMA channels and their usage by the system.
|
||||
|
||||
*Table 4* — DMA channels
|
||||
|
||||
| DMA | Channel | System | Purpose |
|
||||
|:------:|:-------:|:------:|:-----------------------------|
|
||||
| DMA1 | 1 | yes | digital signal |
|
||||
| -- | 2 | yes | -- |
|
||||
| -- | 3 | | |
|
||||
| -- | 4 | yes | pulse reader |
|
||||
| -- | 5 | | |
|
||||
| -- | 6 | yes | USART_Rx |
|
||||
| -- | 7 | yes | LPUART_Rx |
|
||||
| DMA2 | 1 | yes | infrared, lfrfid, subghz, |
|
||||
| -- | 2 | yes | -- |
|
||||
| -- | 3 | yes | cc1101_ext |
|
||||
| -- | 4 | yes | cc1101_ext |
|
||||
| -- | 5 | yes | cc1101_ext |
|
||||
| -- | 6 | yes | SPI |
|
||||
| -- | 7 | yes | SPI |
|
||||
@@ -1,30 +0,0 @@
|
||||
# Furi HAL Debugging {#furi_hal_debugging}
|
||||
|
||||
Some Furi subsystems have additional debugging features that can be enabled by adding additional defines to firmware compilation.
|
||||
Usually, they are used for low level tracing and profiling or signal redirection/duplication.
|
||||
|
||||
|
||||
## FuriHalOs
|
||||
|
||||
`--extra-define=FURI_HAL_OS_DEBUG` enables tick, tick suppression, idle and time flow.
|
||||
|
||||
There are 3 signals that will be exposed to external GPIO pins:
|
||||
|
||||
- `AWAKE` — `PA7` — High when system is busy with computations, low when sleeping. Can be used to track transitions to sleep mode.
|
||||
- `TICK` — `PA6` — Flipped on system tick, only flips when no tick suppression in progress. Can be used to track tick skew and abnormal task scheduling.
|
||||
- `SECOND` — `PA4` — Flipped each second. Can be used for tracing RT issue: time flow disturbance means system doesn't conform Hard RT.
|
||||
|
||||
|
||||
|
||||
## FuriHalPower
|
||||
|
||||
`--extra-define=FURI_HAL_POWER_DEBUG` enables power subsystem mode transitions tracing.
|
||||
|
||||
There are 2 signals that will be exposed to external GPIO pins:
|
||||
|
||||
- `WFI` — `PB2` — Light sleep (wait for interrupt) used. Basically, this is the lightest and most non-breaking things power save mode. All functions and debug should work correctly in this mode.
|
||||
- `STOP` — `PC3` — STOP mode used. Platform deep sleep mode. Extremely fragile mode where most of the silicon is disabled or in unusable state. Debugging MCU in this mode is nearly impossible.
|
||||
|
||||
## FuriHalSD
|
||||
|
||||
`--extra-define=FURI_HAL_SD_SPI_DEBUG` enables SD card SPI bus logging.
|
||||
@@ -1,44 +0,0 @@
|
||||
## What a Firmware Target is {#hardware_targets}
|
||||
|
||||
Flipper's firmware is modular and supports different hardware configurations in a common code base. It encapsulates hardware-specific differences in `furi_hal`, board initialization code, linker files, SDK data and other information in a _target definition_.
|
||||
|
||||
Target-specific files are placed in a single sub-folder in `targets`. It must contain a target definition file, `target.json`, and may contain other files if they are referenced by current target's definition. By default, `fbt` gathers all source files in target folder, unless they are explicitly excluded.
|
||||
|
||||
Targets can inherit most code parts from other targets, to reduce common code duplication.
|
||||
|
||||
|
||||
## Target Definition File
|
||||
|
||||
A target definition file, `target.json`, is a JSON file that can contain the following fields:
|
||||
|
||||
* `include_paths`: list of strings, folder paths relative to current target folder to add to global C/C++ header path lookup list.
|
||||
* `sdk_header_paths`: list of strings, folder paths relative to current target folder to gather headers from for including in SDK.
|
||||
* `startup_script`: filename of a startup script, performing initial hardware initialization.
|
||||
* `linker_script_flash`: filename of a linker script for creating the main firmware image.
|
||||
* `linker_script_ram`: filename of a linker script to use in "updater" build configuration.
|
||||
* `linker_script_app`: filename of a linker script to use for linking .fap files.
|
||||
* `sdk_symbols`: filename of a .csv file containing current SDK configuration for this target.
|
||||
* `linker_dependencies`: list of libraries to link the firmware with. Note that those not in the list won't be built by `fbt`. Also several link passes might be needed, in such case you may need to specify same library name twice.
|
||||
* `inherit`: string, specifies hardware target to borrow main configuration from. Current configuration may specify additional values for parameters that are lists of strings, or override values that are not lists.
|
||||
* `excluded_sources`: list of filenames from the inherited configuration(s) NOT to be built.
|
||||
* `excluded_headers`: list of headers from the inherited configuration(s) NOT to be included in generated SDK.
|
||||
* `excluded_modules`: list of strings specifying fbt library (module) names to exclude from being used to configure build environment.
|
||||
|
||||
|
||||
## Apps & Hardware
|
||||
|
||||
Not all apps are available on different hardware targets.
|
||||
|
||||
* For apps built into the firmware, you have to specify a compatible app set using `FIRMWARE_APP_SET=...` fbt option. See [fbt docs](./fbt.md) for details on build configurations.
|
||||
|
||||
* For apps built as external FAPs, you have to explicitly specify compatible targets in the app's manifest, `application.fam`. For example, to limit the app to a single target, add `targets=["f7"],` to the manifest. It won't be built for other targets.
|
||||
|
||||
For details on app manifests, check out [their docs page](./AppManifests.md).
|
||||
|
||||
|
||||
## Building Firmware for a Specific Target
|
||||
|
||||
You have to specify TARGET_HW (and, optionally, FIRMWARE_APP_SET) for `fbt` to build firmware for a non-default target. For example, building and flashing debug firmware for f18 can be done with
|
||||
|
||||
./fbt TARGET_HW=18 flash_usb_full
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
# How to Build by yourself:
|
||||
|
||||
## Install required software
|
||||
|
||||
- Git - [Download](https://git-scm.com/downloads) for Windows, on Linux/Mac install via package manager (`brew`, `apt`, ...)
|
||||
|
||||
For development:
|
||||
- Git
|
||||
- VSCode
|
||||
|
||||
## Clone the Repository
|
||||
|
||||
You should clone with
|
||||
```shell
|
||||
$ git clone --recursive https://github.com/DarkFlippers/unleashed-firmware.git
|
||||
```
|
||||
|
||||
## VSCode integration
|
||||
|
||||
`fbt` includes basic development environment configuration for VSCode. Run `./fbt vscode_dist` to deploy it. That will copy the initial environment configuration to the `.vscode` folder. After that, you can use that configuration by starting VSCode and choosing the firmware root folder in the `File > Open Folder` menu.
|
||||
|
||||
# Build on Linux/macOS
|
||||
|
||||
Check out `documentation/fbt.md` for details on building and flashing firmware.
|
||||
|
||||
### Compile plugin and run it on connected flipper
|
||||
|
||||
```sh
|
||||
./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=applications_user/yourplugin
|
||||
```
|
||||
|
||||
|
||||
### Compile everything + get updater package to update from microSD card
|
||||
|
||||
```sh
|
||||
./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
```
|
||||
|
||||
Check `dist/` for build outputs.
|
||||
|
||||
Use `flipper-z-{target}-update-{suffix}.tgz` to flash your device.
|
||||
|
||||
# Build on Windows
|
||||
|
||||
Check out `documentation/fbt.md` for details on building and flashing firmware.
|
||||
|
||||
|
||||
### Compile everything + get updater package to update from microSD card
|
||||
|
||||
```powershell
|
||||
./fbt.cmd COMPACT=1 DEBUG=0 updater_package
|
||||
```
|
||||
|
||||
**You may need to change `/` to `\` in front of fbt command (Only for Windows)!**
|
||||
|
||||
Check `dist/` for build outputs.
|
||||
|
||||
Use `flipper-z-{target}-update-{suffix}.tgz` to flash your device.
|
||||
|
||||
If compilation fails, make sure all submodules are all initialized. Either clone with `--recursive` or use `git submodule update --init --recursive`.
|
||||
@@ -1,142 +0,0 @@
|
||||
|
||||
# Update firmware
|
||||
|
||||
## [Get Latest Firmware from GitHub Releases](https://github.com/DarkFlippers/unleashed-firmware/releases)
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
### **If installing for first time - Update to the latest official firmware before proceeding**
|
||||
### **If you are already using unleashed - no need to install any other FW or version before installing update, just install latest version on top of your current one, all will be fine**
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## With Unleashed FW Web Installer
|
||||
|
||||
- Be sure you updated to latest official release before(only if installing for the first time), and verify that microSD card is installed
|
||||
- Open [-> Unleashed FW Web Installer](https://web.unleashedflip.com)
|
||||
- Connect your device and press `Connect` button - Select your device in popup window (be sure to use Chromium based browser)
|
||||
- Select Release or Dev branch
|
||||
- Press `Install` button
|
||||
|
||||
- And wait, if all flashed
|
||||
successfully - you will have all needed assets pre installed
|
||||
- Done
|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## With Flipper Lab - Web Updater
|
||||
|
||||
- Be sure you updated to latest official release before(only if installing for the first time), and verify that microSD card is installed
|
||||
- Open latest release page - [Releases](https://github.com/DarkFlippers/unleashed-firmware/releases/latest)
|
||||
- Connect your device and follow link - `Install via Web Updater`
|
||||
after that on web updater page - press `Connect` button
|
||||
- Press `Install` button
|
||||
|
||||
- And wait, if all flashed
|
||||
successfully - you will have all needed assets pre installed
|
||||
- Done
|
||||

|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## With iOS mobile app
|
||||
|
||||
- Be sure you updated to latest official release before(only if installing for the first time), and verify that microSD card is installed
|
||||
- Open latest release page - [Releases](https://github.com/DarkFlippers/unleashed-firmware/releases/latest)
|
||||
- Download `flipper-z-f7-update-(version).tgz`
|
||||
- Open downloads in ios Files app, select downloaded `.tgz` file, click Share, select Flipper App
|
||||
- In flipper app click green `Update` button, be sure it shows `Custom flipper-z-f7-update...` in Update Channel
|
||||
- Wait until update is finished
|
||||
- Error in ios app will show up, but flipper will be updated successfully
|
||||
- And if all flashed successfully - you will have all needed assets pre installed
|
||||
- Done
|
||||

|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## With Android mobile app (with .tgz download)
|
||||
|
||||
- Be sure you updated to latest official release before(only if installing for the first time), and verify that microSD card is installed
|
||||
- Open latest release page - [Releases](https://github.com/DarkFlippers/unleashed-firmware/releases/latest)
|
||||
- Download `flipper-z-f7-update-(version).tgz`
|
||||
- In flipper app click `Update channel` button, select `Custom`
|
||||
- Select downloaded `.tgz` file
|
||||
- Click Update
|
||||
- Wait until update is finished
|
||||
- And if all flashed successfully - you will have all needed assets pre installed
|
||||
- Done
|
||||

|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## With Android mobile app (via web updater link)
|
||||
|
||||
- Be sure you updated to latest official release before(only if installing for the first time), and verify that microSD card is installed
|
||||
- Open latest release page - [Releases](https://github.com/DarkFlippers/unleashed-firmware/releases/latest)
|
||||
- Click `Install via Web Updater`
|
||||
- It will ask to open with browser or Flipper app, select Flipper App
|
||||
- Continue to install
|
||||
- Wait until update is finished
|
||||
- And if all flashed successfully - you will have all needed assets pre installed
|
||||
- Done
|
||||

|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## With qFlipper (1.2.0+)
|
||||
|
||||
- Download qFlipper that allows `.tgz` installation [Download qFlipper (official link)](https://flipperzero.one/update)
|
||||
- Be sure you updated to latest official release before(only if installing for the first time), and verify that microSD card is installed
|
||||
- Open latest release page - [Releases](https://github.com/DarkFlippers/unleashed-firmware/releases/latest)
|
||||
- Download `flipper-z-f7-update-(version).tgz`
|
||||
- Launch qFlipper
|
||||
- Connect your device and select `Install from file`
|
||||
- Select `flipper-z-f7-update-(version).tgz` that you downloaded
|
||||
- Update will start
|
||||
- And wait, if all flashed successfully - you will have all needed assets pre installed
|
||||
- Done
|
||||

|
||||
|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## With offline update on flipper
|
||||
|
||||
### **Replace (CURRENT VERSION) with version that you downloaded from releases**
|
||||
- Unpack `flipper-z-f7-update-(CURRENT VERSION).tgz` (or `.zip`) into any free folder on your PC or smartphone
|
||||
- You should find folder named `f7-update-(CURRENT VERSION)` that contains files like `update.fuf`, `resources.tar` and etc..
|
||||
- Remove microSD card from flipper and insert it into PC or smartphone (you can skip this step and upload all files using qFlipper)
|
||||
- Create new folder `update` on the root of the microSD card and move folder that you previously extracted from archive - `f7-update-(CURRENT VERSION)` into `update` on microSD card
|
||||
- So result should look like `update/f7-update-(CURRENT VERSION)/` with all files in this folder on microSD card, remember iOS default Files app doesn't show all files properly (3 instead of 6), so you need to use another app for unpacking or use PC or Android
|
||||
- Verify that all files are present on your microSD card
|
||||
- After all you need to insert microSD card back into flipper, navigate into filebrowser, open this file
|
||||
`update/f7-update-(CURRENT VERSION)/update.fuf`
|
||||
- Update will start, wait for all stages
|
||||
- Done
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
# After install:
|
||||
|
||||
- ## [Read instructions how to use plugins and more](https://github.com/DarkFlippers/unleashed-firmware#instructions)
|
||||
|
||||
- ## [How To: Configure Sub-GHz Remote App](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
|
||||
@@ -1,83 +0,0 @@
|
||||
# Infrared Captures
|
||||
|
||||
**Credits go to @gsurkov, @skotopes, @knrn-ai, @DrZlo13 and @ahumeniy for making and contributing to the original `UniversalRemotes.md` Documentation located [Here](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/UniversalRemotes.md).**
|
||||
|
||||
**slightly adapted by @amec0e**
|
||||
|
||||
## Televisions, Fans, Audio and Projectors
|
||||
|
||||
Each signal is recorded using the following process:
|
||||
|
||||
1. Get the remote and point it to Flipper's IR receiver.
|
||||
2. Start learning a new remote if it's the first button or press `+` to add a new button otherwise.
|
||||
3. Do a Quick Press of a remote button and save it under a corresponding name. **(NOTE: Don't hold the remote button down, this will result in long captures and long playbacks ultimately slowing down the universal remotes performance)**
|
||||
4. Repeat steps 2-3 until all required signals are saved.
|
||||
|
||||
The signal names are self-explanatory. Remember to make sure that every recorded signal does what it's supposed to.
|
||||
|
||||
**NOTE:** It's possible some devices around you will cause interference and may force your capture into raw data instead of a parsed code.
|
||||
If you notice you get a parsed code when capturing it's best to click "Retry" a few times on the flipper when capturing to ensure the device is not suffering from any interference, and that the cleanest capture is possible.
|
||||
|
||||
## Types of data
|
||||
|
||||
**Parsed data**
|
||||
|
||||
This is the cleanest type of data because it means it is a recognized code.
|
||||
|
||||
```
|
||||
name: EXAMPLE
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 07 00 00 00
|
||||
command: 02 00 00 00
|
||||
```
|
||||
|
||||
**Raw Data**
|
||||
|
||||
With raw data its important not to hold the remotes button down when capturing on your flipper as this increases not only the size of the capture but the repeats and also how long it takes to send the signal back. Below is an ideal button capture.
|
||||
|
||||
```
|
||||
#
|
||||
name: EXAMPLE
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 2410 597 1189 599 592 600 1186 602 589 603 1183 606 595 597 593 598 1208 605 596 596 594 597 593 599 592 25604 2403 604 1182 606 595 597 1189 599 591 601 1185 603 618 573 617 575 1211 602 588 603 588 605 596 596 594 25605 2402 604 1192 596 594 597 1189 599 592 601 1185 628 593 598 593 600 1186 602 589 603 588 604 597 595 596
|
||||
```
|
||||
|
||||
**Capturing Raw Data:**
|
||||
|
||||
If you are sure your remote is using raw data the best way to capture it will be to do a quick button press **(don't hold the remotes button down)** and look at how many samples you get, the general idea here is to get the lowest amount of raw data samples captured (around 100 samples is about right) while making sure that the playback on the device is still working. This is usually accomplished by doing a quick button press on the remote when capturing.
|
||||
|
||||
## Air Conditioners
|
||||
|
||||
Air conditioners differ from most other infrared-controlled devices because their state is tracked by the remote.
|
||||
The majority of A/C remotes have a small display that shows the current mode, temperature, and other settings.
|
||||
When the user presses a button, a whole set of parameters is transmitted to the device, which must be recorded and used as a whole.
|
||||
|
||||
In order to capture a particular air conditioner, there is a particular process require to capturing and this is done using the following process:
|
||||
|
||||
1. Get the remote and press the **Power Button** so that the display shows that A/C is ON.
|
||||
2. Set the A/C to the corresponding mode (see table below), leaving other parameters such as fan speed or vane on **AUTO** (if applicable).
|
||||
3. Press the **POWER** button to switch the A/C off.
|
||||
4. Start learning a new remote on Flipper if it's the first button or press `+` to add a new button otherwise.
|
||||
5. Point the remote to Flipper's IR receiver as directed and press **POWER** button once again.
|
||||
6. Save the resulting signal under the specified name.
|
||||
7. Repeat steps 2-6 for each signal from the table below.
|
||||
|
||||
| Signal | Mode | Temperature | Note |
|
||||
| :-----: | :--------: | :---------: | ----------------------------------- |
|
||||
| Dh | Dehumidify | N/A | |
|
||||
| Cool_hi | Cooling | See note | Lowest temperature in cooling mode |
|
||||
| Cool_lo | Cooling | 23°C | |
|
||||
| Heat_hi | Heating | See note | Highest temperature in heating mode |
|
||||
| Heat_lo | Heating | 23°C | |
|
||||
|
||||
Finally, record the `Off` signal:
|
||||
|
||||
1. Make sure the display shows that the A/C is ON.
|
||||
2. Start learning a new signal on Flipper and point the remote towards the IR receiver.
|
||||
3. Press the **POWER** button so that the remote shows the OFF state.
|
||||
4. Save the resulting signal under the name `Off`.
|
||||
|
||||
Test the file against the actual device. Make sure that every signal does what it's supposed to.
|
||||
@@ -1,119 +0,0 @@
|
||||
# Key Combos {#key_combos}
|
||||
|
||||
There are times when your Flipper feels blue and doesn't respond to any of your commands due to a software issue. This guide will help you solve this problem.
|
||||
|
||||
## Basic combos
|
||||
|
||||
### Hardware reset
|
||||
|
||||
- Press `LEFT` and `BACK` and hold for a couple of seconds
|
||||
- Release `LEFT` and `BACK`
|
||||
|
||||
This combo performs a hardware reset by pulling the MCU reset line down.
|
||||
Main components involved: Keys → DD8(NC7SZ32M5X, OR-gate) → DD1(STM32WB55, MCU).
|
||||
|
||||
It won't work only in one case:
|
||||
|
||||
- The MCU debug block is active and holding the reset line from inside.
|
||||
|
||||
### Hardware Power Reset
|
||||
|
||||
- Disconnect the USB cable and any external power supplies
|
||||
- Disconnect the USB once again
|
||||
- Make sure you've disconnected the USB and any external power supplies
|
||||
- Press `BACK` and hold for 30 seconds (this will only work with the USB disconnected)
|
||||
- If you haven't disconnected the USB, then disconnect it and repeat the previous step
|
||||
- Release the `BACK` key
|
||||
|
||||
This combo performs a reset by switching SYS power line off and then on.
|
||||
Main components involved: Keys → DD6(bq25896, charger).
|
||||
|
||||
It won't work only in one case:
|
||||
|
||||
- Power supply is connected to USB or 5V_ext
|
||||
|
||||
### Software DFU
|
||||
|
||||
- Press `LEFT` on boot to enter DFU with Flipper boot-loader
|
||||
|
||||
It won't work only in one case:
|
||||
|
||||
- Flipper boot-loader is damaged or absent
|
||||
|
||||
### Hardware DFU
|
||||
|
||||
- Press `OK` on boot to enter DFU with ST boot-loader
|
||||
|
||||
It won't work only in one case:
|
||||
|
||||
- Option Bytes are damaged or set to ignore the `OK` key
|
||||
|
||||
## DFU combos
|
||||
|
||||
### Hardware Reset + Software DFU
|
||||
|
||||
- Press `LEFT` and `BACK` and hold for a couple of seconds
|
||||
- Release `BACK`
|
||||
- Device will enter DFU with an indication (Blue LED + DFU Screen)
|
||||
- Release `LEFT`
|
||||
|
||||
This combo performs a hardware reset by pulling the MCU reset line down. Then, the `LEFT` key indicates to the boot-loader that DFU mode is requested.
|
||||
|
||||
It won't work in two cases:
|
||||
|
||||
- The MCU debug block is active and holding the reset line from inside
|
||||
- Flipper boot-loader is damaged or absent
|
||||
|
||||
### Hardware Reset + Hardware DFU
|
||||
|
||||
- Press `LEFT`, `BACK` and `OK` and hold for a couple of seconds
|
||||
- Release `BACK` and `LEFT`
|
||||
- The device will enter DFU without an indication
|
||||
|
||||
This combo performs a hardware reset by pulling the MCU reset line down. Then, the `OK` key forces MCU to load the internal boot-loader.
|
||||
|
||||
It won't work in two cases:
|
||||
|
||||
- The MCU debug block is active and holding the reset line from inside
|
||||
- Option Bytes are damaged or set to ignore the `OK` key
|
||||
|
||||
### Hardware Power Reset + Software DFU
|
||||
|
||||
- Disconnect the USB and any external power supplies
|
||||
- Press `BACK` and `LEFT` for 30 seconds
|
||||
- Release `BACK`
|
||||
- The device will enter DFU with an indication (Blue LED + DFU Screen)
|
||||
- Release `LEFT`
|
||||
- Plug in the USB
|
||||
|
||||
This combo performs a reset by switching the SYS power line off and then on. Next, the `LEFT` key indicates to the boot-loader that DFU mode is requested.
|
||||
|
||||
It won't work in two cases:
|
||||
|
||||
- Power supply is connected to USB or 5V_ext
|
||||
- Flipper boot-loader is damaged or absent
|
||||
|
||||
### Hardware Power Reset + Hardware DFU
|
||||
|
||||
- Disconnect the USB and any external power supplies
|
||||
- Press `BACK` and `OK` and hold for 30 seconds
|
||||
- Release `BACK` and `OK`
|
||||
- The device will enter DFU without indication
|
||||
- Plug in the USB
|
||||
|
||||
This combo performs a reset by switching the SYS power line off and then on. Next, the `OK` key forces MCU to load the internal boot-loader.
|
||||
|
||||
It won't work in two cases:
|
||||
|
||||
- Power supply is connected to USB or 5V_ext
|
||||
- Option Bytes are damaged or set to ignore the `OK` key
|
||||
|
||||
# Alternative ways to recover your device
|
||||
|
||||
If none of the described methods helped you:
|
||||
|
||||
- Make sure the battery charged
|
||||
- Disconnect the battery and connect again (requires disassembly)
|
||||
- Try to flash the device with ST-Link or another programmer that supports SWD
|
||||
|
||||
If you're still here and your device is not working: it's not a software issue.
|
||||
@@ -1,23 +0,0 @@
|
||||
# Reading RAW RFID data {#lfrfid_raw}
|
||||
|
||||
Flipper Zero has the option to read RAW data from 125 kHz cards that allows you to record the card's data and save it, similar to how a dictaphone records sound.
|
||||
|
||||
To use this function, you need to activate the Debug mode on your Flipper Zero by doing the following:
|
||||
|
||||
1. Go to **Main Menu** → **Settings** → **System**.
|
||||
|
||||
2. Set **Debug** to **ON**.
|
||||
|
||||
Once the Debug mode is activated on your Flipper Zero, you can read RAW data from 125 kHz RFID cards:
|
||||
|
||||
1. Go to **Main Menu** → **125 kHz RFID** → **Extra Actions**.
|
||||
|
||||
2. Select **RAW RFID** data and name the raw file.
|
||||
|
||||
3. Read instructions and press **OK**.
|
||||
|
||||
4. Apply the card to Flipper Zero's back.
|
||||
|
||||
5. Once the reading is finished, press **OK**.
|
||||
|
||||
Two files with data (with ASK and PSK modulations) will be saved in the `lfrfid` folder on the microSD card. Now, you can share it and the card's photo with developers by creating an issue on GitHub.
|
||||
@@ -1,61 +0,0 @@
|
||||
# MultiConverter
|
||||
|
||||
## Author: [theisolinearchip](https://github.com/theisolinearchip/flipperzero_stuff/tree/main/applications/multi_converter)
|
||||
|
||||
An expanded version of my previous __Dec/Hex Converter__, this time allowing more units and a _(probably poorly made from a design-point-of-view)_ selector mode
|
||||
to swap between different unit groups.
|
||||
|
||||
I wrote it with the idea of _expanding the unit list_ on mind, so adding new ones it's a matter of increasing an array of constants + defining the proper conversion functions.
|
||||
|
||||
(Actually the whole project is more about "making the framework" rather than providing _ALL_ of the possible units : D)
|
||||
|
||||
 
|
||||
|
||||
## Current conversions
|
||||
|
||||
- `Decimal / Hexadecimal / Binary`
|
||||
- `Celsius / Fahrenheit / Kelvin`
|
||||
- `Kilometers / Meters / Centimeters / Miles / Feet / Inches`
|
||||
- `Degree / Radian`
|
||||
|
||||
## Usage
|
||||
|
||||
Base keyboard allows numbers from `0` to `F`, being disabled (or not) according to the current selected unit.
|
||||
|
||||
Long press on `0` toggles a __negative__ value; long press on `1` sets a __decimal point__ (only if allowed by the current selected unit).
|
||||
|
||||
`<` removes the last character; `#` changes to __Unit Select Mode__.
|
||||
|
||||
### Unit Select Mode
|
||||
|
||||
`Left` and `Right` to swap between __origin unit__ and __destination unit__ (notice the _destination_ will change according to the current selected _origin_).
|
||||
|
||||
`Ok` to save the changes and go back to the __Display Mode__; `Back` to go back without changing any unit.
|
||||
|
||||
## Adding new units
|
||||
|
||||
1. Add the new units in the `MultiConverterUnitType` enum on `multi_converter_definitions.h` (basic definitions header). Notice each enum element will be used as an array index later.
|
||||
|
||||
2. Increase the `MULTI_CONVERTER_AVAILABLE_UNITS` constant on `multi_converter_units.h` (units main header file).
|
||||
|
||||
3. Set a pair of functions for __converting__ units and to __check__ if a target unit is allowed to work with the destination unit (both on `multi_converter_units.h`
|
||||
and `multi_converter_units.c`; follow the already built-in units for more info).
|
||||
|
||||
4. Add the proper `MultiConverterUnit` structs for each new unit.
|
||||
|
||||
5. Add each new struct to the main `multi_converter_available_units` array.
|
||||
|
||||
And that's it! The system will fetch the new units and display it!
|
||||
|
||||
## Known issues, TODO-list, etc.
|
||||
|
||||
This is an initial release, so expect some bugs and issues (also I don't work with C that much, so there're probably lots of things that can be improved and/or changed!).
|
||||
|
||||
- I've noticed some small decimal variations when "going deep" with some units (like converting __miles__ to __centimeters__ and things like that); probably due to the precision-level required. Need to check that.
|
||||
- Pending: improve overflow checks.
|
||||
- The way some long numbers are shown could probably be improved to look fancier.
|
||||
- Both _origin_ and _destination buffers_ are the same. The destination one could probably be longer in order to avoid certain _overflow scenarios_.
|
||||
- The GUI needs improvement too: there's a whole __widget/views system__ built in the Flipper that allows things like setting up keys, showing "Save/Back/Cancel" messages with
|
||||
callbacks and stuff like that. Didn't know anything about them, so I moved on with something more basic (which is probably fine since it's not a "very big project"); but
|
||||
a more "standard" way with the regular GUI stuff provided by the firmware will be interesting...
|
||||
- More GUI stuff: the _long click buttons_ for adding a decimal point / negative number aren't very clear on the view itself (I tried to add a small dot / dash symbol, but I think those are small enough to be a little bit confusing)
|
||||
@@ -1,51 +0,0 @@
|
||||
# flipperzero-nrf24
|
||||
|
||||
## Author: [mothball187](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker)
|
||||
|
||||
An [NRF24](https://www.sparkfun.com/datasheets/Components/SMD/nRF24L01Pluss_Preliminary_Product_Specification_v1_0.pdf) driver for the [Flipper Zero](https://flipperzero.one/) device. The NRF24 is a popular line of 2.4GHz radio transceivers from Nordic Semiconductors. This library is not currently complete, but functional.
|
||||
|
||||
# How to use
|
||||
- Connect NRF24 to flipper using provided pinouts
|
||||
- Open NRF24: Sniffer, and scan channels, switch between modes/channels using buttons
|
||||
- When you got address -> Open NRF24: Mouse Jacker
|
||||
- Select Address and open badusb file
|
||||
- Done
|
||||
|
||||
# Demo (YouTube)
|
||||
[](https://www.youtube.com/watch?v=C5hbyAjuU4k)
|
||||
|
||||
## Warning
|
||||
These apps are for **educational purposes** only. Please use this code responsibly and only use these apps on your own equipment.
|
||||
|
||||
## Acknowledgments
|
||||
The NRF24 sniffing technique was discovered and shared by Travis Goodspeed in [his blog](http://travisgoodspeed.blogspot.com/2011/02/promiscuity-is-nrf24l01s-duty.html).
|
||||
|
||||
The mousejack vulnerabilities were discovered and reported by Marc Newlin, see [the blog](https://www.bastille.net/research/vulnerabilities/mousejack/technical-details) for technical details.
|
||||
|
||||
Much of the driver code was inspired by [RadioHead's Arduino library](https://www.airspayce.com/mikem/arduino/RadioHead/classRH__NRF24.html).
|
||||
Much of the mousejack code was inspired by the [Jackit project](https://github.com/insecurityofthings/jackit).
|
||||
|
||||
|
||||
# Pinout from from NoComp/Frog
|
||||
<img src="https://media.discordapp.net/attachments/937479784726949900/994495234618687509/unknown.png?width=567&height=634">
|
||||
|
||||
# Mousejacker / NRF24 pinout by UberGuidoZ
|
||||
2/A7 on FZ goes to MOSI/6 on nrf24l01<br>
|
||||
3/A6 on FZ goes to MISO/7 on nrf24l01<br>
|
||||
4/A4 on FZ goes to CSN/4 on nrf24l01<br>
|
||||
5/B3 on FZ goes to SCK/5 on nrf24l01<br>
|
||||
6/B2 on FZ goes to CE/3 on nrf24l01<br>
|
||||
8/GND on FZ goes to GND/1 on nrf24l01<br>
|
||||
9/3V3 on FZ goes to VCC/2 on nrf24l01<br>
|
||||
IRQ/8 is left disconnected on nrf24l01<br>
|
||||
|
||||

|
||||
|
||||
If the nRF module is acting a bit flakey, try adding a capacitor to the vcc/gnd lines!
|
||||
I've not tried the Plus model so it may have a bigger need for a cap.
|
||||
Otherwise, I haven't had any major issues.
|
||||
Anything from a 3.3 uF to 10 uF should do. (Watch your positive/negative placement! Negative to ground.)
|
||||
I learned if you wanna get fancy, include a 0.1 uF cap in parallel.
|
||||
The 3.3 uF to 10 uF will respond to slow freq changes while the 0.1 uF will respond to the high freq switching spikes that the larger one cannot. That said, a single 10 uF will likely suffice for the Mousejack attack. ¯\\\_(ツ)_/¯
|
||||
|
||||

|
||||
@@ -1,145 +0,0 @@
|
||||
# Flipper Zero OTA update process {#ota_updates}
|
||||
|
||||
## Executing code from RAM
|
||||
|
||||
In Flipper firmware, we have a special boot mode that loads a specially crafted system image into RAM and transfers control to it. The system image executing in RAM has full write access to Flipper's entire flash memory — something that's not possible when running main code from the same flash.
|
||||
|
||||
We leverage that boot mode to perform OTA firmware updates, including operations on a radio stack running on the second MCU core.
|
||||
|
||||
## How does Flipper OTA work?
|
||||
|
||||
Installation of OTA updates goes through 3 stages:
|
||||
|
||||
### 1. Backing up internal storage (/int)
|
||||
|
||||
It is a special partition of Flipper's flash memory, taking up all available space not used by the firmware code. Newer versions of firmware may be of different size, and simply installing them would cause flash repartitioning and data loss.
|
||||
|
||||
So, before taking any action on the firmware, we back up the current configuration from `/int` into a plain tar archive on the SD card.
|
||||
|
||||
### 2. Performing device update
|
||||
|
||||
The main firmware loads an updater image — a customized build of the main Flipper firmware — into RAM and runs it. Updater performs operations on system flash as described by an Update manifest file.
|
||||
|
||||
First, if there's a Radio stack image bundled with the update, updater compares its version with the currently installed one. If they don't match, updater performs stack deinstallation followed by writing and installing a new one. The installation itself is performed by proprietary software FUS running on Core2, and leads to a series of system restarts.
|
||||
|
||||
Then, updater validates and corrects Option Bytes — a special memory region containing low-level configuration for Flipper's MCU.
|
||||
|
||||
After that, updater loads a `.dfu` file with firmware to be flashed, checks its integrity using CRC32, writes it to system flash and validates written data.
|
||||
|
||||
### 3. Restoring internal storage and updating resources
|
||||
|
||||
After performing operations on flash memory, the system restarts into newly flashed firmware. Then it performs restoration of previously backed up `/int` contents.
|
||||
|
||||
If the update package contains an additional resources archive, it is extracted onto the SD card.
|
||||
|
||||
## Update manifest
|
||||
|
||||
An update package comes with a manifest that contains a description of its contents. The manifest is in Flipper File Format — a simple text file, comprised of key-value pairs.
|
||||
|
||||
### Mandatory fields
|
||||
|
||||
An update manifest must contain the following keys in the given order:
|
||||
|
||||
- **Filetype**: a constant string, "Flipper firmware upgrade configuration".
|
||||
|
||||
- **Version**: manifest version. The current value is 2.
|
||||
|
||||
- **Info**: arbitrary string, describing package contents.
|
||||
|
||||
- **Target**: hardware revision for which the package is built.
|
||||
|
||||
- **Loader**: file name of stage 2 loader that is executed from RAM.
|
||||
|
||||
- **Loader CRC**: CRC32 of loader file. Note that it is represented in little-endian hex.
|
||||
|
||||
### Optional fields
|
||||
|
||||
Other fields may have empty values. In this case, updater skips all operations related to these values.
|
||||
|
||||
- **Radio**: file name of radio stack image, provided by STM.
|
||||
|
||||
- **Radio address**: address to install the radio stack at. It is specified in Release Notes by STM.
|
||||
|
||||
- **Radio version**: radio major, minor and sub versions followed by branch, release and stack type packed into 6 hex-encoded bytes.
|
||||
|
||||
- **Radio CRC**: CRC32 of radio image.
|
||||
|
||||
- **Resources**: file name of TAR archive with resources to be extracted onto the SD card.
|
||||
|
||||
- **OB reference**, **OB mask**, **OB write mask**: reference values for validating and correcting option bytes.
|
||||
|
||||
## OTA update error codes
|
||||
|
||||
We designed the OTA update process to be as fail-safe as possible. We don't start any risky operations before validating all related pieces of data to ensure we don't leave the device in a partially updated, or bricked, state.
|
||||
|
||||
Even if something goes wrong, updater allows you to retry failed operations and reports its state with an error code. These error codes have an `[XX-YY]` format, where `XX` encodes the failed operation, and `YY` contains extra details on its progress where the error occurred.
|
||||
|
||||
| Stage description | Code | Progress | Description |
|
||||
| :---------------------: | -----: | ---------- | ------------------------------------------ |
|
||||
| Loading update manifest | **1** | **13** | Updater reported hardware version mismatch |
|
||||
| | | **20** | Failed to get saved manifest path |
|
||||
| | | **30** | Failed to load manifest |
|
||||
| | | **40** | Unsupported update package version |
|
||||
| | | **50** | Package has mismatching HW target |
|
||||
| | | **60** | Missing DFU file |
|
||||
| | | **80** | Missing radio firmware file |
|
||||
| Backing up configuration| **2** | **0-100** | FS read/write error |
|
||||
| Checking radio FW | **3** | **0-99** | Error reading radio firmware file |
|
||||
| | | **100** | CRC mismatch |
|
||||
| Uninstalling radio FW | **4** | **0** | SHCI Delete command error |
|
||||
| | | **80** | Error awaiting command status |
|
||||
| Writing radio FW | **5** | **0-100** | Block read/write error |
|
||||
| Installing radio FW | **6** | **10** | SHCI Install command error |
|
||||
| | | **80** | Error awaiting command status |
|
||||
| Core2 is busy | **7** | **10** | Couldn't start C2 |
|
||||
| | | **20** | Failed to switch C2 to FUS mode |
|
||||
| | | **30** | Error in FUS operation |
|
||||
| | | **50** | Failed to switch C2 to stack mode |
|
||||
| Validating opt. bytes | **8** | **yy** | Option byte code |
|
||||
| Checking DFU file | **9** | **0** | Error opening DFU file |
|
||||
| | | **1-98** | Error reading DFU file |
|
||||
| | | **99-100** | Corrupted DFU file |
|
||||
| Writing flash | **10** | **0-100** | Block read/write error |
|
||||
| Validating flash | **11** | **0-100** | Block read/write error |
|
||||
| Restoring configuration | **12** | **0-100** | FS read/write error |
|
||||
| Updating resources | **13-15** | **0-100** | SD card read/write error |
|
||||
|
||||
## Building update packages
|
||||
|
||||
### Full package
|
||||
|
||||
To build a full update package, including firmware, radio stack and resources for the SD card, run:
|
||||
|
||||
`./fbt COMPACT=1 DEBUG=0 updater_package`
|
||||
|
||||
### Minimal package
|
||||
|
||||
To build a minimal update package, including only firmware, run:
|
||||
|
||||
`./fbt COMPACT=1 DEBUG=0 updater_minpackage`
|
||||
|
||||
### Customizing update bundles
|
||||
|
||||
Default update packages are built with Bluetooth Light stack.
|
||||
You can pick a different stack if your firmware version supports it, and build a bundle with it by passing the stack type and binary name to `fbt`:
|
||||
|
||||
`./fbt updater_package COMPACT=1 DEBUG=0 COPRO_OB_DATA=scripts/ob_custradio.data COPRO_STACK_BIN=stm32wb5x_BLE_Stack_full_fw.bin COPRO_STACK_TYPE=ble_full`
|
||||
|
||||
Note that `COPRO_OB_DATA` must point to a valid file in the `scripts` folder containing reference Option Byte data matching your radio stack type.
|
||||
|
||||
In certain cases, you might have to confirm your intentions by adding `COPRO_DISCLAIMER=...` to the build command line.
|
||||
|
||||
### Building partial update packages
|
||||
|
||||
You can customize package contents by calling `scripts/update.py` directly.
|
||||
For example, to build a package only for installing BLE FULL stack:
|
||||
|
||||
```shell
|
||||
scripts/update.py generate \
|
||||
-t f7 -d r13.3_full -v "BLE FULL 13.3" \
|
||||
--stage dist/f7/flipper-z-f7-updater-*.bin \
|
||||
--radio lib/stm32wb_copro/firmware/stm32wb5x_BLE_Stack_full_fw.bin \
|
||||
--radiotype ble_full
|
||||
```
|
||||
|
||||
For the full list of options, check `scripts/update.py generate` help.
|
||||
@@ -1,17 +0,0 @@
|
||||
# Sentry Safe plugin
|
||||
|
||||
## Author: [H4ckd4ddy](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin)
|
||||
|
||||
Flipper zero exploiting vulnerability to open any Sentry Safe and Master Lock electronic safe without any pin code.
|
||||
|
||||
[Demo and Vulnerability described here](https://github.com/H4ckd4ddy/bypass-sentry-safe)
|
||||
|
||||
### Usage
|
||||
|
||||
- Start "Sentry Safe" plugin
|
||||
- Place wires as described on the plugin screen
|
||||
<br>(Flipper GPIO) 8/GND -> Black wire (Safe)
|
||||
<br>(Flipper GPIO) 15/C1 -> Green wire (Safe)
|
||||
|
||||
- Press enter
|
||||
- Open safe
|
||||
@@ -1,223 +0,0 @@
|
||||
# SubGHz Counter Experimental Mode
|
||||
|
||||
## Overview
|
||||
|
||||
Experimental Counter Mode is an advanced feature that allows you to customize how rolling codes increment when transmitting SubGHz signals. Different protocols support different counter modes, which can be useful for specific cases, main purpose is to make clone of the original remote that will not conflict with original remote, so both Flipper and original remote can be used at same time in rolling code systems without desync or other issues.
|
||||
|
||||
**Be aware, do not experiment with equipment you don't have access to, if you are not sure what mode works for you and can't reprogram your original remote to the receiver - do not use these modes!!!**
|
||||
|
||||
In case you have access to the receiver and can do some tests, try some of these modes on your system and let us know how it works for you, in github issues or our communities, thanks!
|
||||
|
||||
## How to Use Experimental Counter Mode
|
||||
|
||||
To enable a specific counter mode, you need to manually edit your `.sub` file and add a `CounterMode` line.
|
||||
|
||||
### Steps:
|
||||
|
||||
1. Locate your `.sub` file (in `/ext/subghz/` on your Flipper Zero SD card)
|
||||
2. Open the file in a text editor
|
||||
3. Add the following line at the end of the file:
|
||||
```
|
||||
CounterMode: X
|
||||
```
|
||||
Where `X` is the mode number (0, 1, 2, etc.)
|
||||
|
||||
### Example .sub File:
|
||||
|
||||
```
|
||||
Filetype: Flipper SubGhz Key File
|
||||
Version: 1
|
||||
Frequency: 433920000
|
||||
Preset: FuriHalSubGhzPresetOok650Async
|
||||
Protocol: Nice FloR-S
|
||||
Bit: 52
|
||||
Key: AA AA AA AA AA AA AA
|
||||
CounterMode: 1
|
||||
```
|
||||
|
||||
## Supported Protocols and Counter Modes
|
||||
|
||||
### 1. Nice Flor S
|
||||
|
||||
**Mode 0 (Default):**
|
||||
- Standard - acts like regular remote
|
||||
- Uses rolling counter multiplier from global settings (default +1)
|
||||
- Counter increments based on the multiplier value (default +1)
|
||||
- Resets to 0 when overflow occurs (> 0xFFFF)
|
||||
|
||||
**Mode 1 (floxi2r):**
|
||||
- Counter sequence: `0x0001 / 0xFFFE`
|
||||
- For receiver model floxi2r
|
||||
|
||||
**Mode 2 (ox2):**
|
||||
- Counter sequence: `0x0000 / 0x0001`
|
||||
- For receiver model ox2
|
||||
|
||||
---
|
||||
|
||||
### 2. Came Atomo
|
||||
|
||||
**Mode 0 (Default):**
|
||||
- Standard - acts like regular remote
|
||||
- Uses rolling counter multiplier from global settings (default +1)
|
||||
- Counter increments based on the multiplier value (default +1)
|
||||
- Resets to 0 when overflow occurs (> 0xFFFF)
|
||||
|
||||
**Mode 1:**
|
||||
- Counter sequence: `0x0000 / 0x0001 / 0xFFFE / 0xFFFF`
|
||||
- Works with external CAME RE432 receiver, may work with other type of receivers
|
||||
|
||||
**Mode 2:**
|
||||
- Counter sequence: `0x807B / 0x807C / 0x007B / 0x007C`
|
||||
- Works with external CAME RE432 receiver, may work with other type of receivers
|
||||
|
||||
**Mode 3:**
|
||||
- Counter freeze - do not increment
|
||||
|
||||
---
|
||||
|
||||
### 3. Alutech AT-4N
|
||||
|
||||
**Mode 0 (Default):**
|
||||
- Standard - acts like regular remote
|
||||
- Uses rolling counter multiplier from global settings (default +1)
|
||||
- Counter increments based on the multiplier value (default +1)
|
||||
- Resets to 0 when overflow occurs (> 0xFFFF)
|
||||
|
||||
**Mode 1:**
|
||||
- Counter sequence: `0x0000 / 0x0001 / 0xFFFE / 0xFFFF`
|
||||
- For receiver model MCSW-3.3M
|
||||
|
||||
**Mode 2:**
|
||||
- Counter sequence: `0x0000 / 0x0001 / 0x0002 / 0x0003 / 0x0004 / 0x0005`
|
||||
- For other receiver boards
|
||||
|
||||
---
|
||||
|
||||
### 4. KeeLoq
|
||||
|
||||
**Mode 0 (Default):**
|
||||
- Standard - acts like regular remote
|
||||
- Uses rolling counter multiplier from global settings (default +1)
|
||||
- Counter increments based on the multiplier value (default +1)
|
||||
- Resets to 0 when overflow occurs (> 0xFFFF)
|
||||
|
||||
**Mode 1:**
|
||||
- Counter sequence: `0x0000 / 0x0001 / 0xFFFE / 0xFFFF`
|
||||
- Might work with some systems (let us know!)
|
||||
|
||||
**Mode 2:**
|
||||
- Incremental mode: `+0x3333` each transmission
|
||||
- Adds 0x3333 (13107 in decimal) to counter each time
|
||||
- Might work with Doorhan, seen in some "universal remotes"
|
||||
|
||||
**Mode 3:**
|
||||
- Counter sequence: `0x8006 / 0x8007 / 0x0006 / 0x0007`
|
||||
- Might work with some systems like Hormann EcoStar
|
||||
|
||||
**Mode 4:**
|
||||
- Counter sequence: `0x807B / 0x807C / 0x007B / 0x007C`
|
||||
- Might work with some systems like Nice Smilo
|
||||
|
||||
**Mode 5:**
|
||||
- Counter sequence: `0x0000 / 0xFFFF`
|
||||
- Alternates between 0 and maximum value (65535)
|
||||
- Might work with some systems (let us know!)
|
||||
|
||||
**Mode 6:**
|
||||
- Counter freeze - do not increment
|
||||
|
||||
**Mode 7:**
|
||||
- Incremental mode: `+0x3333` 5 times to current counter and return original value back adding +1 - 2 times - 7 signals in pack total
|
||||
- Might work with Doorhan, seen in some "universal remotes"
|
||||
- One click of Send button on flipper may bypass receiver counter, wait for full transmission
|
||||
|
||||
|
||||
---
|
||||
|
||||
### 5. V2 Phoenix (Phox)
|
||||
|
||||
**Mode 0 (Default):**
|
||||
- Standard - acts like regular remote
|
||||
- Uses rolling counter multiplier from global settings (default +1)
|
||||
- Counter increments based on the multiplier value (default +1)
|
||||
- Resets to 0 when overflow occurs (> 0xFFFF)
|
||||
|
||||
**Mode 1 (ofex like):**
|
||||
- Counter sequence: `0x0000 / 0x0001 / 0xFFFE / 0xFFFF`
|
||||
- Verified as working
|
||||
|
||||
**Mode 2 (0 - 4):**
|
||||
- Counter sequence: `0x0000 / 0x0001 / 0x0002 / 0x0003 / 0x0004`
|
||||
- Might work (let us know!)
|
||||
|
||||
---
|
||||
|
||||
## Notes and Warnings
|
||||
|
||||
### Important Considerations:
|
||||
|
||||
1. **Default Behavior:**
|
||||
- If you don't specify a `CounterMode`, Regular remote simulation (cnt +1) is used by default
|
||||
- Regular remote simulation is the standard mode and works with most cases
|
||||
|
||||
2. **Protocol Compatibility:**
|
||||
- Not all protocols support all counter modes
|
||||
- Using an unsupported mode number may result in unexpected behavior
|
||||
- Always test your configuration before relying on it
|
||||
|
||||
### Troubleshooting:
|
||||
|
||||
- If your file doesn't work after adding `CounterMode`:
|
||||
1. Double-check the syntax: `CounterMode: X` (with space after colon)
|
||||
2. Verify the mode number is valid for your protocol
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Example Configurations
|
||||
|
||||
### Example 1: Nice Flor S with Mode 1
|
||||
```
|
||||
Filetype: Flipper SubGhz Key File
|
||||
Version: 1
|
||||
Frequency: 433920000
|
||||
Preset: FuriHalSubGhzPresetOok650Async
|
||||
Protocol: Nice FloR-S
|
||||
Bit: 52
|
||||
Key: 01 23 45 67 89 AB CD
|
||||
CounterMode: 1
|
||||
```
|
||||
|
||||
### Example 2: KeeLoq with Mode 2 (+0x3333 (Doorhan))
|
||||
```
|
||||
Filetype: Flipper SubGhz Key File
|
||||
Version: 1
|
||||
Frequency: 433920000
|
||||
Preset: FuriHalSubGhzPresetOok650Async
|
||||
Protocol: KeeLoq
|
||||
Bit: 64
|
||||
Key: DE AD BE EF CA FE BA BE
|
||||
Manufacture: Doorhan
|
||||
CounterMode: 2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: Will this damage my remote or receiver?**
|
||||
A: Yes it may do that - depending on the receiver, it may desync your remote, be aware and don't experiment with equipment you don't have access to
|
||||
|
||||
**Q: Which mode should I use?**
|
||||
A: Do not use those mods if you are not sure
|
||||
|
||||
**Q: What happens if I use an invalid mode number?**
|
||||
A: Last mode from the list will be used
|
||||
|
||||
**Q: Do I need to add CounterMode to every .sub file?**
|
||||
A: No, only add it if you need non-default behavior. Mode 0 is automatic if not specified.
|
||||
|
||||
---
|
||||
|
||||
*Made for Unleashed FW, please mention source when copying*
|
||||
@@ -1,76 +0,0 @@
|
||||
# Sub-GHz Remote
|
||||
|
||||
|
||||
# UPDATE!!!!!!
|
||||
## Now you can create and edit map files directly on flipper, go into Sub-GHz Remote and click back button
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
|
||||
### The SubGHz Remote Tool *requires* the creation of custom user map with `.txt` extension in the `subghz_remote` folder on the sdcard.
|
||||
|
||||
#### If these files are not exist or not configured properly, **you will receive an error each time you try to select wrong file in the UniRF Tool**.
|
||||
|
||||
## You can add as many `.txt` map files as you want, file name doesn't matter!
|
||||
|
||||
|
||||
## Incorrect or unconfigured file error
|
||||
|
||||
If the `.txt` file has not been properly configured, the following error will be thrown when trying to run the UniRF Remix app:
|
||||
|
||||
```
|
||||
Config is incorrect.
|
||||
|
||||
Please configure map
|
||||
|
||||
Press Back to Exit
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Setting up the `subghz_remote/example.txt` file:
|
||||
|
||||
```
|
||||
UP: /ext/subghz/Up.sub
|
||||
DOWN: /ext/subghz/Down.sub
|
||||
LEFT: /ext/subghz/Left.sub
|
||||
RIGHT: /ext/subghz/Right.sub
|
||||
OK: /ext/subghz/Ok.sub
|
||||
ULABEL: Up Label
|
||||
DLABEL: Down Label
|
||||
LLABEL: Left Label
|
||||
RLABEL: Right Label
|
||||
OKLABEL: Ok Label
|
||||
```
|
||||
|
||||
The UP/DOWN/LEFT/RIGHT/OK file locations must be set to the specific file you want mapped to that directional pad direction.
|
||||
|
||||
The ULABEL/DLABEL/LLABEL/RLABEL/OKLABEL variables should be set to the text to be displayed for each of the files set earlier.
|
||||
|
||||
## Example:
|
||||
|
||||
```
|
||||
UP: /ext/subghz/Fan1.sub
|
||||
DOWN: /ext/subghz/Fan2.sub
|
||||
LEFT: /ext/subghz/Door.sub
|
||||
RIGHT: /ext/subghz/Garage3.sub
|
||||
OK: /ext/subghz/Garage3l.sub
|
||||
ULABEL: Fan ON
|
||||
DLABEL: Fan OFF
|
||||
LLABEL: Doorbell
|
||||
RLABEL: Garage OPEN
|
||||
OKLABEL: Garage CLOSE
|
||||
```
|
||||
|
||||
## Notes
|
||||
* ##### App Usage
|
||||
- Press a button to send the assigned capture file.
|
||||
- Press Back button to exit app.
|
||||
|
||||
* ##### SubGHz Remote Map
|
||||
- File path should not have any spaces or special characters (- and _ excluded).
|
||||
- Labels are limited to 16 characters.
|
||||
- Why? This is to prevent overlapping elements on screen.
|
||||
- For example: If you set your label or file to ```WWWWWWWWWWWWWWW``` you'll be over the screen limits.
|
||||
@@ -1,244 +0,0 @@
|
||||
# How to use Flipper as a new SubGHz remote (not clone of original remote)
|
||||
|
||||
### If your system is not added here that doesn't mean flipper don't support it! Look into add manually menu, and search for your manufacturers inscturctions!
|
||||
### Also many supported systems can be used only from `Read` mode, `Add Manually` is used only to make new remotes that can be binded with receiver
|
||||
|
||||
## FAAC SLH (NEW!)
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> FAAC SLH (select your frequency)
|
||||
2. Open your new remote file
|
||||
3. Open your receiver box, find programming button on the receiver board.
|
||||
4. Hold Up arrow button on the flipper to send programming signal - at same time press and hold programming button on the receiver board.
|
||||
5. Led on the receiver board will light on, then off, then on, then off again then on again
|
||||
6. Release all buttons
|
||||
7. Press send button on the flipper couple times holding it for 1-3 seconds
|
||||
8. Done!
|
||||
Watch this video to learn more : https://www.youtube.com/watch?v=NfZmMy37XUs
|
||||
|
||||
...
|
||||
How to get Seed value from your original remote or bind new remote using existing (master) remote?
|
||||
1. Go to SubGHz -> Read - Select frequency 868.35 or 433.92 and modulation AM650
|
||||
2. Hold two buttons on the original master remote until led turns on
|
||||
3. Click one button that you want to get seed from (Seed is unique for each button on original remote!)
|
||||
4. You will get signal in the read screen on flipper, open that and see your original remote seed for button you used
|
||||
5. You can create new remote using that seed and bind that to receiver without opening the box! Faac has procedure that allows to bind new remotes using master remote, you can use flipper for that
|
||||
6. Go to SubGHz -> Add Manually -> FAAC SLH Man. (your Freq)
|
||||
7. Enter those values -> REPLACE `R` with any random digits like 1,2,3..
|
||||
FIX -> A0 RR RR R6
|
||||
COUNTER -> 00 00 02
|
||||
SEED -> Your seed from the remote button you got earlier
|
||||
8. Flipper will act as new remote, press Send button couple times near the receiver to register new remote
|
||||
9. Done!
|
||||
|
||||
## Dea Mio
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> Dea Mio 433Mhz
|
||||
2. Open your new remote file
|
||||
3. Right arrow button on the flipper simulates press of hidden button in original remote
|
||||
4. Send button simulates one of basic buttons of the remote, can be programmed into the receiver
|
||||
5. Follow manufacturer instructions on new remotes programming
|
||||
|
||||
## AN-Motors AT4
|
||||
|
||||
**This instruction for older boards, if your has no** `Learn` **button but has buttons** `F`, `CL`, `+`, `-` **read instruction from Alutech AT4N**
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> AN-Motors AT4 433Mhz
|
||||
2. Open your new remote file
|
||||
3. Open your receiver box, find button `Learn` click it one time, led will turn on.
|
||||
4. Press `Send` on your flipper one time, led on receiver board will turn off.
|
||||
5. Press `Send` on your flipper again, led on receiver will start flashing, wait couple seconds until led turns off.
|
||||
6. Done
|
||||
|
||||
Watch this video to learn more (video in Russian language): https://www.youtube.com/watch?v=URVMtTELcnU
|
||||
|
||||
## Alutech AT4N (AN-Motors)
|
||||
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> Alutech AT4N 433Mhz
|
||||
2. Open your new remote file
|
||||
3. Open your receiver box, find button `F` press it for ~3sec, display will show `Pr`.
|
||||
4. Click `F` button couple times until you see `Lr` on screen
|
||||
5. Using buttons `+` / `-` select free number that has no remotes in it (if it has remote programmed on that number, it will show a red dot on the down right corner)
|
||||
6. Press `Send` on your flipper one time, display on receiver board will flash and red dot will appear next to remote number.
|
||||
7. Press button `F` on receiver board for ~3sec to exit programming mode
|
||||
8. Done
|
||||
|
||||
Watch this video to learn more and see how different boards can be programmed (video in Russian language): https://www.youtube.com/watch?v=XrOVVYhFXDg
|
||||
|
||||
## Aprimatic TR
|
||||
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> KL: Aprimatic 433Mhz
|
||||
2. Open your new remote file
|
||||
3. Push all 4 buttons at same time on your existing remote thats already works with receiver
|
||||
4. Receiver makes a continuous beep
|
||||
5. Press `Send` on your flipper for ~2 seconds
|
||||
6. Wait until receiver stops beeping
|
||||
7. Done?
|
||||
|
||||
## Doorhan
|
||||
|
||||
With access to the receiver box:
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> KL: Doorhan 433Mhz or 315Mhz depends on your receiver (find out by reading your existing remote or follow guide below)
|
||||
- Finding frequency
|
||||
|
||||
There are 2 frequencies for DoorHan: 315.00 / 433.92. To determine them it is enough to create a DoorHan remote control with one of the frequencies via Sub-GHz -> Add manually, press the button and watch the receiver's reaction. If you have guessed the frequency, the light bulb will turn on when we press the button on the FZ and turn off when we release it.
|
||||
|
||||
2. Binding the remote control
|
||||
|
||||
Once you have access to the receiver (removed the protective cover), look at the buttons:
|
||||
- If there are 4 buttons (Radio, Reverse, Auto, ...) then press and hold Radio until the LED lights up, then press the FZ button 2 times and the LED goes out;
|
||||
- If there are 4 buttons (R, P, +, -) and display, press R, then press 2 times the button on FZ and wait +/- 10 seconds;
|
||||
- If there are 4 buttons (+, -, F, TR) and display, press TR, then press 2 times the button on FZ and wait +/- 10 seconds;
|
||||
- In other cases there is a “universal” instruction: Press and hold the button “P” +/- 2 seconds until the LED flashes, then press 2 times the button on the FZ and the LED goes out.
|
||||
|
||||
In all cases it is recommended to wait until the receiver returns to normal mode.
|
||||
|
||||
With existing remote:
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> KL: Doorhan 433Mhz or 315Mhz depends on your receiver (find out by reading your existing remote)
|
||||
2. Open your new remote file
|
||||
3. For next steps be close to the receiver board, around 1-2 meters
|
||||
4. Press second button (lowest one) on the old remote, do not release second button and press 1st (upper) button, hold buttons for 1 sec and release them
|
||||
5. Press working button on the old remote (the button you use for operating the receiver, aka opening the gate, etc) hold for 1 sec and release
|
||||
6. Actions with old remote must be done in 5 seconds time, do not hold buttons for too long, and do not make it very fast
|
||||
7. Receiver will beep, you will have 10 seconds to add new remote, now press Send on new remote on flipper two times holding for at least 1 sec
|
||||
8. Receiver will beep again telling that new remote is added sucessfuly!
|
||||
9. Done!
|
||||
|
||||
With copy of existing remote on flipper:
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> KL: Doorhan 433Mhz or 315Mhz depends on your receiver (find out by reading your existing remote)
|
||||
2. Open your existing remote (original) file
|
||||
3. For next steps be close to the receiver board, around 1-2 meters
|
||||
4. Press left button (0x8) on the flipper, hold for 1 sec and release the button and press right (0xA) button, hold button for 1 sec and release
|
||||
5. Press working button on the flipper, should be center one aka Send (the button you use for operating the receiver, aka opening the gate, etc) hold for 1 sec and release
|
||||
6. Actions with original remote copy must be done in 5 seconds time, do not hold buttons for too long, and do not make it very fast
|
||||
7. Receiver will beep, now hold back and open new remote file, you will have 10 seconds to add new remote, press Send on new remote on flipper two times holding for at least 1 sec
|
||||
8. Receiver will beep again telling that new remote is added sucessfuly!
|
||||
9. Done!
|
||||
|
||||
Watch this videos to learn more (videos in Russian language): https://www.youtube.com/watch?v=wZ5121HYv50 / https://www.youtube.com/watch?v=1ucrDKF3vWc
|
||||
|
||||
## Somfy Telis
|
||||
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> Somfy Telis 433Mhz
|
||||
2. Open your new remote file
|
||||
3. Long press (hold) the ‘Prog’ button on a remote that is already registered to the device, until the blinds move shortly up and down.
|
||||
4. Press and hold the ‘Prog’ button on the flipper (Left Arrow), until the blinds move shortly up and down again.
|
||||
5. Done?
|
||||
|
||||
## BFT Mitto
|
||||
|
||||
How to create new remote and bind it to receiver (will not conflict with original remotes):
|
||||
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> BFT Mitto 433Mhz
|
||||
2. Open your new remote file
|
||||
3. You need to be in minimum 3 meters to receiver
|
||||
4. Original Remote: Press hidden button on back of remote with a pin or paper clip OR press Button 1 & 2 together until remote LED lights.
|
||||
5. Original Remote: Momentarily press button that opens device
|
||||
6. Long press (Right Arrow) - (0xF button - Btn:F) on Flipper for like 3-5 sec
|
||||
7. Press the button you want to bind to open the device on the flipper
|
||||
8. Press (Right Arrow) - (0xF button - Btn:F) again
|
||||
9. Done?
|
||||
|
||||
OR
|
||||
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> BFT Mitto 433Mhz
|
||||
2. Open your new remote file
|
||||
3. Open your receiver board box
|
||||
4. **Watch this video**: https://www.youtube.com/watch?v=5QXMBKI_-Ls
|
||||
5. Long press (Right Arrow) - (0xF button - Btn:F) on Flipper for like 3-5 sec -> Will act like holding Button 1 & 2 on original remote as shown on video
|
||||
6. Done?
|
||||
|
||||
--
|
||||
|
||||
How to get seed to make full clone of your remote (**will conflict with original remote!!!!!**):
|
||||
|
||||
**WARNING!!!! This method can desync your original remote, please avoid using it! It can be used in rare cases like when your remote works poorly or has broken buttons and you want to replace it with flipper**
|
||||
|
||||
1. Open `Read` in SubGHz on your flipper
|
||||
2. (ONLY FOR ORIGINAL REMOTES) Hold all buttons on your remote at same time, example -> for 2 button remote - press them both at same time and hold OR press hidden button on back of remote with a pin or paper clip
|
||||
For 4 buttons remote press & hold two buttons at upper row
|
||||
3. You will receive signal on your flipper, open that signal and see `Fix:` value, it should start from `F` like `F00F1C9B`
|
||||
4. If `Fix:` is showing first `F` see `Hop:` value -> This is your remote Seed (except first digit `F` (this is the button code, aka programming button pressed means `F`))
|
||||
5. Write down Hop value and replace first digit - `F` with `0`
|
||||
6. Press button on your remote that you want to clone and receive its signal on your flipper
|
||||
7. Open and write down `Fix:` value where first digit will be same as your button ID `Btn:`
|
||||
8. Create new remote using BFT Mitto [Manual] - Enter FIX from step 7, enter counter `FF F9`, enter seed from step 5
|
||||
9. Using counter values like `FF F9` can help bypassing current original remote counter value, and in result it also can fully desync original remote, only one remote can work at same time using this method
|
||||
10. Also you can do this: Save your signal of the original remote (will say KL: Unknown),
|
||||
then copy file to the PC and edit it and insert/replace those values after the `Key: 01 23 45 67 89 AB CD EF` (your key will have different value)
|
||||
```
|
||||
Seed: 0X XX XX XX
|
||||
Manufacture: BFT
|
||||
```
|
||||
Replace `X`'s with digits from your Seed that you obtained by reading two button hold at the first steps,
|
||||
Save and copy that file back to the flipper
|
||||
Now you will have exact clone of your remote that will have same counter, by making couple presses you will make it higher than original and receiver will work with it, but original remote will reguire same amount of presses to work again, and vice versa.
|
||||
11. Also your original remote may become non working since it needs to be re-added into receiver board if you made counter much higher than original :C
|
||||
|
||||
## CAME Atomo
|
||||
Known names are: TOP42R / TOP44R - TOP44RGR (806TS-0130)
|
||||
|
||||
How to create new remote and bind it to receiver (will not conflict with original remotes):
|
||||
|
||||
With original remote (or copy of the original remote):
|
||||
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> CAME Atomo 433MHz or 868MHz
|
||||
2. Open your new remote file
|
||||
3. You need to be in minimum 3 meters to receiver
|
||||
4. Original Remote: Press and hold button that is bound with that receiver (the one you use with it), and hold it for about 10 seconds.
|
||||
5. You will have about 20 seconds to add new remote
|
||||
6. Long press Send on Flipper in new remote for like 3-4 sec and release - this will add new remote to the receiver
|
||||
7. Press and hold Send again after waiting 20 seconds - this will trigger the receiver
|
||||
8. Done, when using CAME Atomo from flipper please hold Send button for at least 2 seconds to allow code to be fully transmit, flipper transmits only while button is held
|
||||
|
||||
Note: Static 24/12 bit or TWEE remotes cannot trigger programming mode in the receiver and cannot be bound if programming mode was triggered by Atomo type remote, only Atomo remotes can be added if remote programming was done by Atomo remote, Static remotes have option to clone from one remote to another, but it requires first remote to be added to the receiver via button on the receiver board
|
||||
|
||||
With access to receiver box:
|
||||
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> CAME Atomo 433MHz or 868MHz
|
||||
2. Open your new remote file
|
||||
3. Open the receiver box and find programming button related to the used channel, for example RE432M/RE862M receiver has two independent channels which can have different remotes / buttons on them, when you found connected channel press "1" or "2" button on the receiver board to enter programming mode
|
||||
4. Long press Send on Flipper new remote for like 3-4 sec and release - this will add new remote to the receiver
|
||||
5. Click CLEAR button one time on the receiver board to exit programming mode, or wait about 20 seconds it will exit from programming mode automatically
|
||||
6. Done, when using CAME Atomo from flipper please hold Send button for at least 2 seconds to allow code to be fully transmit, flipper transmits only while button is held
|
||||
|
||||
|
||||
Watch this video to learn more (video in Russian language): https://www.youtube.com/watch?v=XeHUwfcSS30
|
||||
|
||||
## Nice Flor S
|
||||
|
||||
- Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> Nice FloR-S 433Mhz
|
||||
- Open your new remote file
|
||||
|
||||
### Coding using an existing remote
|
||||
To enter the code of a new remote control without using your receiver, you will need
|
||||
an authorised remote control (note: the first remote control must always be entered
|
||||
using the receiver key). Now, with the two remote controls (your already coded
|
||||
remote, and your new remote), which we shall call NEW (the one whose code we want
|
||||
to enter) and OLD (the authorised one), position yourself within 3m of the gate/garage
|
||||
receiver and then:
|
||||
1. Press and hold the `Send` button on the flipper for at least 5 seconds and then
|
||||
release.
|
||||
2. Press the button on the already programmed remote 3 times slowly.
|
||||
3. Press the `Send` button on the flipper slowly and then release.
|
||||
|
||||
### Coding directly to your receiver
|
||||
Your new remote will program to your receiver as per your original remote
|
||||
instructions, so please refer to your manual. But for a typical NICE FLOX2R Receiver,
|
||||
the programming procedure is as follows:
|
||||
1. Press the learning button on your receiver for 1-2 seconds. The LED will turn on
|
||||
for 5 seconds. Within 5 seconds, complete the next step.
|
||||
2. Press a `Send` button on your flipper until the LED on your receiver turns off.
|
||||
3. Release the remote button and wait for 2 seconds.
|
||||
4. Press the `Send` button on your flipper again. The LED on your receiver
|
||||
will now flash 3 times. This indicates that your remote has been successfully
|
||||
coded. If this does not happen, repeat the whole procedure from the
|
||||
beginning, and try again.
|
||||
5. Wait 5 seconds. Press the button on your new remote to test if it opens your
|
||||
garage/gate.
|
||||
|
||||
|
||||
#### Follow links below to find more detailed instructions!!!
|
||||
|
||||
#### Materials used:
|
||||
- [FAAC SLH](https://www.youtube.com/watch?v=NfZmMy37XUs)
|
||||
- [Somfy Telis](https://pushstack.wordpress.com/somfy-rts-protocol/)
|
||||
- [BFT Mitto](https://www.retroremotes.com.au/wp-content/uploads/2017/03/BFT-MITTO-2-4-19-6-17.pdf)
|
||||
- [NICE FLOX2R Receiver Programming](https://apollogateopeners.com/store/pdf/apollo-flor-s-receiver-programming-guide.pdf)
|
||||
- [Nice Flor S Programming](https://motepro.com.au/Instructions/Nice.pdf)
|
||||
@@ -1,110 +0,0 @@
|
||||
## How to add new SubGHz frequencies
|
||||
|
||||
#### CC1101 Frequency range specs: 300-348 MHz, 386-464 MHz, and 778-928 MHz (+ 350MHz and 467MHz was added to default range)
|
||||
|
||||
Edit user settings file located on your microSD card - `subghz/assets/setting_user` (remove .example from name to use config)
|
||||
|
||||
in this file you will find we already have extra frequencies added
|
||||
if you need your custom one, make sure it doesn't listed here
|
||||
|
||||
### Default frequency list
|
||||
```
|
||||
/* 300 - 348 */
|
||||
300000000,
|
||||
302757000,
|
||||
303000000,
|
||||
303875000,
|
||||
303900000,
|
||||
304250000,
|
||||
307000000,
|
||||
307500000,
|
||||
307800000,
|
||||
309000000,
|
||||
310000000,
|
||||
312000000,
|
||||
312100000,
|
||||
312200000,
|
||||
313000000,
|
||||
313850000,
|
||||
314000000,
|
||||
314350000,
|
||||
314980000,
|
||||
315000000,
|
||||
318000000,
|
||||
320000000,
|
||||
320150000,
|
||||
330000000,
|
||||
345000000,
|
||||
348000000,
|
||||
350000000,
|
||||
|
||||
/* 387 - 464 */
|
||||
387000000,
|
||||
390000000,
|
||||
418000000,
|
||||
430000000,
|
||||
430500000,
|
||||
431000000,
|
||||
431500000,
|
||||
433075000, /* LPD433 first */
|
||||
433220000,
|
||||
433420000,
|
||||
433657070,
|
||||
433889000,
|
||||
433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */
|
||||
434075000,
|
||||
434176948,
|
||||
434190000,
|
||||
434390000,
|
||||
434420000,
|
||||
434620000,
|
||||
434775000, /* LPD433 last channels */
|
||||
438900000,
|
||||
440175000,
|
||||
462750000,
|
||||
464000000,
|
||||
467750000,
|
||||
|
||||
/* 779 - 928 */
|
||||
779000000,
|
||||
868350000,
|
||||
868400000,
|
||||
868460000,
|
||||
868800000,
|
||||
868950000,
|
||||
906400000,
|
||||
915000000,
|
||||
925000000,
|
||||
928000000,
|
||||
```
|
||||
|
||||
### User frequencies added AFTER that default list! You need to continue until you reach the end of that list
|
||||
|
||||
### If you want to disable default list and use ONLY user added frequencies from user settings file
|
||||
Change that line
|
||||
`#Add_standard_frequencies: true`
|
||||
to
|
||||
`Add_standard_frequencies: false`
|
||||
|
||||
**You need to have custom frequencies added in both lists! in main frequency list and in hopping list! Replacing only hopping freqs will not work with that setting set on false, you need to add something in main list since it will be empty**
|
||||
|
||||
### To add your own frequency to user list
|
||||
Just add new line
|
||||
`Frequency: 928000000` - where `928000000` is your frequency, keep it in that format! it should be 9 digits!
|
||||
|
||||
### Hopper frequency list
|
||||
To add new frequency to hopper:
|
||||
add new line `Hopper_frequency: 345000000`<br>
|
||||
But remember! You should keep it as small as possible, or hopper functionality would be useless!<br>
|
||||
If `#Add_standard_frequencies: true` is not changed<br>
|
||||
Your frequencies will be added after default ones
|
||||
|
||||
### Default hopper list
|
||||
```
|
||||
315000000,
|
||||
390000000,
|
||||
430500000,
|
||||
433920000,
|
||||
434420000,
|
||||
868350000,
|
||||
```
|
||||
@@ -1,180 +0,0 @@
|
||||
# Sub-GHz Supported Protocols
|
||||
|
||||
This file lists all supported Sub-GHz protocols available in Unleashed Firmware, both tested and untested.
|
||||
|
||||
That list is only for default SubGHz app, apps like *Weather Station* have their own protocols list
|
||||
|
||||
|
||||
## Static & Dynamic protocols list
|
||||
|
||||
*433 MHz usually means `433.92MHz` and 868 MHz = `868.35MHz`*
|
||||
|
||||
*If you see no frequency after protocol name, that means we don't know it, let us know in issues tab!*
|
||||
|
||||
*`AM650`, `FM`, `FSK476` - means modulation to use when reading the remote*
|
||||
|
||||
*`FM` means you should try any existing FM modulations, `FSK???` means `FM???` in SubGHz - Read - Config*
|
||||
|
||||
### Garage Door Openers & Gate Openers (Boom barriers, roller shutters, etc.)
|
||||
- Alutech AT-4N `433.92MHz` `AM650` (72 bits, Dynamic)
|
||||
- AN-Motors (Alutech) AT4 `433.92MHz` `AM650` (64 bits, Pseudo-Dynamic, KeeLoq based)
|
||||
- Ansonic `433MHz` `FM` (12 bits, Static)
|
||||
- BETT `433.92MHz` `AM650` (18 bits, Static)
|
||||
- Beninca ARC (TOGO2VA) `433.92MHz` `AM650` (128 bits, Dynamic AES) (button code `0` emulates `hidden button` option on the remote)
|
||||
- BFT Mitto `433.92MHz` `AM650` (64 bits, Dynamic, KeeLoq based with Seed)
|
||||
- CAME Atomo `433.92MHz, 868MHz` `AM650` (62 bits, Dynamic)
|
||||
- CAME TWEE `433.92MHz` `AM650` (54 bits, Static)
|
||||
- CAME `433.92MHz, 868MHz` `AM650` (12, 24 bits, Static)
|
||||
- Prastel `433.92MHz, 868MHz` `AM650` (25, 42 bits, Static)
|
||||
- Airforce `433.92MHz, 868MHz` `AM650` (18 bits, Static)
|
||||
- Chamberlain Code `AM650` (10 bits, Static)
|
||||
- Clemsa `AM650` (18 bits, Static)
|
||||
- Dickert MAHS `AM650` (36 bits, Static)
|
||||
- Doitrand `AM650` (37 bits, Dynamic)
|
||||
- Elplast/P-11B/3BK/E.C.A `433MHz` `AM650` (18 bits, Static)
|
||||
- FAAC SLH `433.92MHz, 868MHz` `AM650` (64 bits, Dynamic)
|
||||
- Gate TX `433.92MHz` `AM650` (64 bits, Static)
|
||||
- Hormann `868MHz` `AM650` (44 bits, Static)
|
||||
- HCS101 `AM650` (64 bits, Simple Dynamic, KeeLoq-like)
|
||||
- IDO `433MHz` `AM650` (48 bits, Dynamic)
|
||||
- KingGates Stylo 4k `433.92MHz` `AM650` (89 bits, Dynamic, KeeLoq based)
|
||||
- Mastercode `AM650` (36 bits, Static)
|
||||
- Megacode `AM650` (24 bits, Static)
|
||||
- Nero Sketch `AM650` (40 bits, Static)
|
||||
- Nice Flo `433.92MHz` `AM650` (12, 24 bits, Static)
|
||||
- Nice FloR-S `433.92MHz` `AM650` (52 bits, Dynamic)
|
||||
- Nice One `433.92MHz` `AM650` (72 bits, Dynamic)
|
||||
- Revers RB2 (Реверс РБ-2 (М)) `433.92MHz` `AM650` (64 bits, Static)
|
||||
- Roger `433.92MHz` `AM650` (28 bits, Static)
|
||||
- V2 Phoenix (Phox) `433.92MHz` `AM650` (52 bits, Dynamic) (receivers have option to enable Static mode, making them ignore rolling part of the key)
|
||||
- Marantec `433.92MHz, 868MHz` `AM650` (49 bits, Static)
|
||||
- Marantec24 `868MHz` `AM650` (24 bits, Static)
|
||||
- Somfy Keytis `433.92MHz, 868MHz` `AM650` (80 bits, Dynamic)
|
||||
- ZKTeco `430.5MHz` `AM650` (24 bits, Static - Princeton based) - (Button codes (already mapped to arrow keys): `0x30 (UP)`, `0x03 (STOP)`, `0x0C (DOWN)`)
|
||||
- Linear `300MHz` `AM650` (10 bits, Static)
|
||||
- Linear Delta3 `AM650` (8 bits, Static)
|
||||
- Nero Radio `434.42MHz` `AM650` (56 bits, Static mode only, Dynamic is unsupported)
|
||||
- Security+1.0 `315MHz, 433.92MHz, 390MHz` `AM650` (42 bits, Dynamic)
|
||||
- Security+2.0 `310MHz, 390MHz, 868MHz` `AM650` (62 bits, Dynamic)
|
||||
|
||||
### Sensors & Smart home
|
||||
- Intertechno V3 `AM650` (32 bits, Static) - Lights, sockets, other.
|
||||
- Dooya `AM650` (40 bits, Static) - Electric blinds
|
||||
- Power Smart `AM650` (64 bits, Static) - Blinds, shutters
|
||||
- Legrand `AM650` (18 bits, Static) - Doorbells
|
||||
- Somfy Telis `433.92MHz` `AM650` (56 bits, Dynamic)
|
||||
- Feron `433.92MHz` `AM650` (32 bits, Static) - RGB LED remotes, other.
|
||||
- Honeywell `AM650` (64 bits, Static) - Alarm, Sensor
|
||||
- Honeywell WDB `AM650` (48 bits, Static) - Doorbell
|
||||
- Magellan `433.92MHz` `AM650` (32 bits, Static) - Sensor, alarm
|
||||
- Jarolift `433.92MHz` `AM650` (72 bits, Dynamic, KeeLoq based) - Automatic roller shutters
|
||||
|
||||
### Alarms
|
||||
- Hollarm `433.92MHz` `AM650` (42 bits, Static) - Bike alarms
|
||||
- GangQi `433.92MHz` `AM650` (34 bits, Static) - Bike alarms
|
||||
|
||||
|
||||
### Generic any branded remotes
|
||||
- Holtek `AM650` (40 bits, Static)
|
||||
- Holtek HT12X `AM650` (12 bits, Static)
|
||||
- Princeton (PT2262, PT****) `315MHz, 433.92MHz, Any other frequency` `AM650` (24 bits, Static)
|
||||
- SMC5326 `315MHz, 433.92MHz, Any other frequency` `AM650` (25 bits, Static)
|
||||
- Hay21 `433.92MHz` `AM650` (21 bits, Dynamic)
|
||||
- Treadmill37 (QH-433) `433.92MHz` `AM650` (37 bits, Static)
|
||||
|
||||
---
|
||||
|
||||
## KeeLoq Rolling Code Supported Manufacturers list
|
||||
|
||||
KeeLoq is a rolling code encryption system used by many garage door openers and gate systems.
|
||||
The following manufacturers have KeeLoq support in Unleashed firmware:
|
||||
|
||||
*Default value for encryption type "learning" is `simple` and `10bits` for serial part in Hop*
|
||||
|
||||
*In case if remote uses other serial bits or different encryption type and it was verified - it will be stated in the end*
|
||||
|
||||
### Garage Door Openers & Gate Openers (Boom barriers, roller shutters, etc.)
|
||||
- Allmatic - `868MHz` `AM650` (KeeLoq, 64 bits) (no serial part in Hop - magic XOR)
|
||||
- Aprimatic - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial number art in Hop + 2bit "parity" in front of it replacing first 2 bits of serial)
|
||||
- Beninca - `433.92MHz, 868MHz` `AM650` (KeeLoq, 64 bits) (no serial part in Hop - magic XOR)
|
||||
- CAME Space - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - simple learning)
|
||||
- Cardin S449 - `433.92MHz` `FSK12K` (KeeLoq, 64 bits) (12bit (original remotes) or 10bit (chinese remotes) serial part in Hop - normal learning) (receiver checks for 10bit only (unverified))
|
||||
- Centurion - `433.92MHz` `AM650` (KeeLoq, 64 bits) (no serial in Hop, uses fixed value 0x1CE - normal learning)
|
||||
- Comunello - `433.92MHz, 868MHz` `AM650` (KeeLoq, 64 bits) (normal learning)
|
||||
- DEA Mio - `433.92MHz` `AM650` (KeeLoq, 64 bits) (modified serial in Hop, uses last 3 digits modifying first one (example - 419 -> C19) - simple learning)
|
||||
- DoorHan - 315MHz, `433.92MHz` `AM650` (KeeLoq, 64 bits)
|
||||
- DTM Neo - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - simple learning)
|
||||
- Elmes Poland - `433.92MHz` `AM650` (KeeLoq, 64 bits) (normal learning)
|
||||
- FAAC RC,XT - `433.92MHz, 868MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - normal learning)
|
||||
- Genius Bravo - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - normal learning)
|
||||
- Gibidi - `433.92MHz` `AM650` (KeeLoq, 64 bits)
|
||||
- GSN - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - normal learning)
|
||||
- Hormann EcoStar - `433.92MHz` `AM650` (KeeLoq, 64 bits) (normal learning)
|
||||
- IronLogic IL-100 - `433.92MHz` `AM650` (KeeLoq, 64 bits)
|
||||
- IronLogic IL-100 Smart PPult - `433.92MHz` `AM650` (KeeLoq, 64 bits)
|
||||
- JCM Tech - `433.92MHz` `AM650` (KeeLoq, 64 bits) (8bit serial part in Hop - simple learning)
|
||||
- Jolly Motors - `433.92MHz` `AM650` (KeeLoq, 64 bits)
|
||||
- KEY (KeeLoq, 64 bits)
|
||||
- Monarch - `433.92MHz` `AM650` (KeeLoq, 64 bits) (no serial in Hop, uses fixed value 0x100 - normal learning)
|
||||
- Motorline - `433.92MHz` `AM650` (KeeLoq, 64 bits) (normal learning)
|
||||
- Mutanco/Mutancode (KeeLoq, 64 bits) (12bit serial part in Hop - normal learning)
|
||||
- Mhouse - `433.92MHz` `AM650` (KeeLoq, 64 bits) (8bit serial part in Hop - simple learning)
|
||||
- Nice Smilo - `433.92MHz` `AM650` (KeeLoq, 64 bits) (8bit serial part in Hop - simple learning)
|
||||
- Normstahl - `433.92MHz` `AM650` (KeeLoq, 64 bits)
|
||||
- Novoferm - `433.92MHz` `AM650` (KeeLoq, 64 bits)
|
||||
- Sommer `434.42MHz, 868.80MHz` `FSK12K (or FSK476)` (KeeLoq, 64 bits) (normal learning) (TX03-868-4, Pearl, and maybe other models are supported (SOMloq))
|
||||
- Steelmate - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - normal learning)
|
||||
- Stilmatic (R-Tech) - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - normal learning) (receiver checks for 10bit only (unverified))
|
||||
|
||||
### Alarms, unknown origin, etc.
|
||||
- APS-1100/APS-2550 (KeeLoq, 64 bits)
|
||||
- Alligator (KeeLoq, 64 bits)
|
||||
- Alligator S-275 (KeeLoq, 64 bits)
|
||||
- Cenmax (KeeLoq, 64 bits)
|
||||
- Cenmax St-5 (KeeLoq, 64 bits)
|
||||
- Cenmax St-7 (KeeLoq, 64 bits)
|
||||
- Faraon (KeeLoq, 64 bits)
|
||||
- Guard RF-311A (KeeLoq, 64 bits) (normal learning)
|
||||
- Harpoon (KeeLoq, 64 bits)
|
||||
- KGB/Subaru (KeeLoq, 64 bits) (magic serial type 1)
|
||||
- Leopard (KeeLoq, 64 bits)
|
||||
- Magic 1 (KeeLoq, 64 bits) (magic serial type 2)
|
||||
- Magic 2 (KeeLoq, 64 bits) (magic serial type 2)
|
||||
- Magic 3 (KeeLoq, 64 bits) (magic serial type 3)
|
||||
- Magic 4 (KeeLoq, 64 bits) (magic serial type 3)
|
||||
- Merlin (KeeLoq, 64 bits) (no serial part in Hop - simple XOR)
|
||||
- Mongoose (KeeLoq, 64 bits) (normal learning)
|
||||
- Pantera (KeeLoq, 64 bits)
|
||||
- Pantera CLK (KeeLoq, 64 bits)
|
||||
- Pantera XS/Jaguar (KeeLoq, 64 bits)
|
||||
- Partisan RX (KeeLoq, 64 bits)
|
||||
- Pecinin (KeeLoq, 64 bits) (12bit serial part in Hop - simple learning)
|
||||
- Reff (KeeLoq, 64 bits)
|
||||
- Rossi (KeeLoq, 64 bits) (12bit serial part in Hop - simple learning)
|
||||
- Rosh (KeeLoq, 64 bits) (12bit serial part in Hop - simple learning)
|
||||
- Sheriff (KeeLoq, 64 bits)
|
||||
- SL A2-A4 (KeeLoq, 64 bits)
|
||||
- SL A6-A9/Tomahawk 9010 (KeeLoq, 64 bits)
|
||||
- SL B6,B9 dop (KeeLoq, 64 bits)
|
||||
- Teco (KeeLoq, 64 bits)
|
||||
- Tomahawk TZ-9030 (KeeLoq, 64 bits)
|
||||
- Tomahawk Z,X 3-5 (KeeLoq, 64 bits)
|
||||
- ZX-730-750-1055 (KeeLoq, 64 bits)
|
||||
|
||||
*Note: Most KeeLoq manufacturers operate in the 433 MHz and 868 MHz frequency bands with AM650 modulation. Some operate at other frequencies or modulations. Not all KeeLoq systems are supported for full decoding or emulation.*
|
||||
|
||||
---
|
||||
|
||||
## Protocol Type Reference
|
||||
|
||||
Unleashed firmware supports various protocol types:
|
||||
|
||||
- **Static Code**: Fixed transmission codes (e.g., Roger, Princeton, Marantec, Revers RB2)
|
||||
- **Rolling Code (Dynamic) (KeeLoq)**: Dynamic codes with rolling counter using KeeLoq encryption (60+ manufacturer systems supported)
|
||||
- **Rolling Code (Dynamic)**: Other dynamic systems with custom encoding (e.g., CAME Atomo, Nice Flor S, Somfy Telis, FAAC SLH, Alutech AT-4N, Security+)
|
||||
|
||||
For more information on how to use some of these protocols, see also [SubGHzRemoteProg.md](/documentation/SubGHzRemoteProg.md) and the main [ReadMe.md](/ReadMe.md).
|
||||
|
||||
---
|
||||
|
||||
*Docs made for Unleashed FW, please mention source when copying*
|
||||
@@ -1,64 +0,0 @@
|
||||
# Unit tests {#unit_tests}
|
||||
|
||||
## Intro
|
||||
|
||||
Unit tests are special pieces of code that apply known inputs to the feature code and check the results to see if they are correct.
|
||||
They are crucial for writing robust, bug-free code.
|
||||
|
||||
Flipper Zero firmware includes a separate app called [unit_tests](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/debug/unit_tests).
|
||||
It is run directly on Flipper devices in order to employ their hardware features and rule out any platform-related differences.
|
||||
|
||||
When contributing code to the Flipper Zero firmware, it is highly desirable to supply unit tests along with the proposed features.
|
||||
Running existing unit tests is useful to ensure that the new code doesn't introduce any regressions.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
To run the unit tests, follow these steps:
|
||||
|
||||
1. Compile the firmware with the tests enabled: `./fbt FIRMWARE_APP_SET=unit_tests updater_package`.
|
||||
2. Flash the firmware using your preferred method, including SD card resources (`build/latest/resources`).
|
||||
3. Launch the CLI session and run the `unit_tests` command.
|
||||
|
||||
**NOTE:** To run a particular test (and skip all others), specify its name as the command argument.
|
||||
Test names match application names defined [here](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/debug/unit_tests/application.fam).
|
||||
|
||||
## Adding unit tests
|
||||
|
||||
### General
|
||||
|
||||
#### Entry point
|
||||
|
||||
The common entry point for all tests is the [unit_tests](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/debug/unit_tests) app. Test-specific code is packaged as a `PLUGIN` app placed in a subdirectory of `tests` in the `unit_tests` mother-app and referenced in the common `application.fam`. Look at other tests for an example.
|
||||
|
||||
#### Test assets
|
||||
|
||||
Some unit tests require external data in order to function. These files (commonly called assets) reside in the [unit_tests](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/debug/unit_tests/resources/unit_tests) directory in their respective subdirectories. Asset files can be of any type (plain text, FlipperFormat (FFF), binary, etc.).
|
||||
|
||||
### App-specific
|
||||
|
||||
#### Infrared
|
||||
|
||||
Each infrared protocol has a corresponding set of unit tests, so it makes sense to implement one when adding support for a new protocol.
|
||||
To add unit tests for your protocol, follow these steps:
|
||||
|
||||
1. Create a file named `test_<your_protocol_name>.irtest` in the [assets](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/debug/unit_tests/resources/unit_tests/infrared) directory.
|
||||
2. Fill it with the test data (more on it below).
|
||||
3. Add the test code to [infrared_test.c](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/debug/unit_tests/tests/infrared/infrared_test.c).
|
||||
4. Build and install firmware with resources, install it on your Flipper and run the tests to see if they pass.
|
||||
|
||||
##### Test data format
|
||||
|
||||
Each unit test has three sections:
|
||||
|
||||
1. `decoder` — takes in a raw signal and outputs decoded messages.
|
||||
2. `encoder` — takes in decoded messages and outputs a raw signal.
|
||||
3. `encoder_decoder` — takes in decoded messages, turns them into a raw signal, and then decodes again.
|
||||
|
||||
Infrared test asset files have an `.irtest` extension and are regular `.ir` files with a few additions.
|
||||
Decoder input data has signal names `decoder_input_N`, where N is a test sequence number. Expected data goes under the name `decoder_expected_N`. When testing the encoder, these two are switched.
|
||||
|
||||
Decoded data is represented in arrays (since a single raw signal may be decoded into several messages). If there is only one signal, then it has to be an array of size 1. Use the existing files as syntax examples.
|
||||
|
||||
##### Getting raw signals
|
||||
|
||||
Recording raw IR signals is possible using Flipper Zero. Launch the CLI session, run `ir rx raw`, then point the remote towards the Flipper's receiver and send the signals. The raw signal data will be printed to the console in a convenient format.
|
||||
@@ -1,76 +0,0 @@
|
||||
# Universal Remotes {#universal_remotes}
|
||||
|
||||
## Televisions
|
||||
|
||||
Adding your TV set to the universal remote is quite straightforward. Up to 6 signals can be recorded: `Power`, `Mute`, `Vol_up`, `Vol_dn`, `Ch_next`, and `Ch_prev`. Any of them can be omitted if not supported by your TV.
|
||||
|
||||
Each signal is recorded using the following algorithm:
|
||||
|
||||
1. Get the remote and point it to Flipper's IR receiver.
|
||||
2. Start learning a new remote if it's the first button or press `+` to add a new button otherwise.
|
||||
3. Press a remote button and save it under a corresponding name.
|
||||
4. Repeat steps 2-3 until all required signals are saved.
|
||||
|
||||
The signal names are self-explanatory. Remember to make sure that every recorded signal does what it's supposed to.
|
||||
|
||||
If everything checks out, append these signals **to the end** of the [TV universal remote file](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/main/infrared/resources/infrared/assets/tv.ir).
|
||||
|
||||
## Audio players
|
||||
|
||||
Adding your audio player to the universal remote is done in the same manner as described above. Up to 8 signals can be recorded: `Power`, `Play`, `Pause`, `Vol_up`, `Vol_dn`, `Next`, `Prev`, and `Mute`. Any of them can be omitted if not supported by the player.
|
||||
|
||||
The signal names are self-explanatory.
|
||||
On many remotes, the `Play` button doubles as `Pause`. In this case, record it as `Play` omitting the `Pause`.
|
||||
Make sure that every signal does what it's supposed to.
|
||||
|
||||
If everything checks out, append these signals **to the end** of the [audio player universal remote file](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/main/infrared/resources/infrared/assets/audio.ir).
|
||||
|
||||
## Projectors
|
||||
|
||||
Adding your projector to the universal remote is really simple. Up to 4 signals can be recorded: `Power`, `Mute`, `Vol_up`, `Vol_dn`. Any of them can be omitted if not supported by your projector.
|
||||
To save time, please make sure every recording has been named accordingly.
|
||||
In case of omitting, on most projectors with the 4 following buttons, you should not have a problem.
|
||||
|
||||
|
||||
## Air conditioners
|
||||
|
||||
Air conditioners differ from most other infrared-controlled devices because their state is tracked by the remote.
|
||||
The majority of A/C remotes have a small display that shows the current mode, temperature, and other settings.
|
||||
When the user presses a button, a whole set of parameters is transmitted to the device, which must be recorded and used as a whole.
|
||||
|
||||
In order to add a particular air conditioner to the universal remote, 6 signals must be recorded: `Off`, `Dh`, `Cool_hi`, `Cool_lo`, `Heat_hi`, and `Heat_lo`.
|
||||
Each signal (except `Off`) is recorded using the following algorithm:
|
||||
|
||||
1. Get the remote and press the **POWER** button so that the display shows that A/C is ON.
|
||||
2. Set the A/C to the corresponding mode (see table below), leaving other parameters such as fan speed or vane on **AUTO** (if applicable).
|
||||
3. Press the **POWER** button to switch the A/C off.
|
||||
4. Start learning a new remote on Flipper if it's the first button or press `+` to add a new button otherwise.
|
||||
5. Point the remote to Flipper's IR receiver as directed and press the **POWER** button once again.
|
||||
6. Save the resulting signal under the specified name.
|
||||
7. Repeat steps 2-6 for each signal from the table below.
|
||||
|
||||
| Signal | Mode | Temperature | Note |
|
||||
| :-----: | :--------: | :---------: | ----------------------------------- |
|
||||
| Dh | Dehumidify | N/A | |
|
||||
| Cool_hi | Cooling | See note | Lowest temperature in cooling mode |
|
||||
| Cool_lo | Cooling | 23°C | |
|
||||
| Heat_hi | Heating | See note | Highest temperature in heating mode |
|
||||
| Heat_lo | Heating | 23°C | |
|
||||
|
||||
Finally, record the `Off` signal:
|
||||
|
||||
1. Make sure the display shows that the A/C is ON.
|
||||
2. Start learning a new signal on Flipper and point the remote towards the IR receiver.
|
||||
3. Press the **POWER** button so that the remote shows the OFF state.
|
||||
4. Save the resulting signal under the name `Off`.
|
||||
|
||||
The resulting remote file should now contain 6 signals. You can omit any of them, but you then won't be able to use their functionality.
|
||||
Test the file against the actual device. Make sure that every signal does what it's supposed to.
|
||||
|
||||
If everything checks out, append these signals **to the end** of the [A/C universal remote file](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/main/infrared/resources/infrared/assets/ac.ir).
|
||||
|
||||
## Final steps
|
||||
|
||||
The order of signals is not important, but they should be preceded by the following comment: `# Model: <Your model name>` in order to keep the library organized.
|
||||
|
||||
When done, open a pull request containing the changed file.
|
||||
@@ -1,88 +0,0 @@
|
||||
# Debugging via the Devboard {#dev_board_debugging_guide}
|
||||
|
||||
On this page, you'll learn about how debugging via the Wi-Fi Developer Board works. To illustrate this process, we'll start a debug session for Flipper Zero's firmware in VS Code using the native Flipper Build Tool.
|
||||
|
||||
***
|
||||
|
||||
## Overview
|
||||
|
||||
The Developer Board acts as the debug probe, which provides a bridge between the IDE (integrated development environment) with a debugger running on a host computer and the target microcontroller (in your Flipper Zero). The user controls the debugging process on the computer connected to the Developer Board via [Wi-Fi](#dev_board_wifi_connection) or [USB cable](#dev_board_usb_connection).
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_WiFi_hardware_CDN.jpg width=700
|
||||
|
||||
Data exchange between the Wi-Fi Developer Board and your Flipper Zero is conducted via the Serial Wire Debug interface. The following GPIO pins serve this purpose:
|
||||
|
||||
- **Pin 10:** Serial Wire Clock (SWCLK)
|
||||
|
||||
- **Pin 12:** Serial Wire Debug Data I/O (SWDIO)
|
||||
|
||||
To learn more about Flipper Zero pinout, visit [GPIO & modules in Flipper Docs](https://docs.flipper.net/gpio-and-modules).
|
||||
|
||||
***
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Step 1. Installing Git
|
||||
|
||||
You'll need Git installed on your computer to clone the firmware repository. If you don't have Git, install it following the [official installation guide](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
|
||||
|
||||
### Step 2. Building the firmware
|
||||
|
||||
Before starting debugging, you need to clone and build Flipper Zero firmware:
|
||||
|
||||
1. Open the **Terminal** (on Linux & macOS) or **PowerShell** (on Windows) in the directory where you want to store the firmware source code.
|
||||
|
||||
2. Clone the firmware repository:
|
||||
|
||||
```
|
||||
git clone --recursive https://github.com/flipperdevices/flipperzero-firmware.git
|
||||
cd flipperzero-firmware
|
||||
```
|
||||
|
||||
3. Run the **Flipper Build Tool (FBT)** to build the firmware:
|
||||
|
||||
```
|
||||
./fbt
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Debugging the firmware
|
||||
|
||||
From the **flipperzero-firmware** directory that you cloned earlier, run the following command:
|
||||
|
||||
```
|
||||
./fbt flash
|
||||
```
|
||||
|
||||
This will upload the firmware you've just built to your Flipper Zero via the Developer Board. After that, you can start debugging the firmware. We recommend using **VS Code** with the recommended extensions (as described below), and we have pre-made configurations for it.
|
||||
|
||||
To debug in **VS Code**, do the following:
|
||||
|
||||
1. In VS Code, open the **flipperzero-firmware** directory.
|
||||
|
||||
2. You should see a notification about recommended extensions. Install them.
|
||||
|
||||
If there were no notifications, open the **Extensions** tab, enter `@recommended` in the search bar, and install the workspace recommendations.
|
||||
|
||||
3. Run the `./fbt vscode_dist` command. This will generate the VS Code configuration files needed for debugging.
|
||||
|
||||
4. In VS Code, open the **Run and Debug** tab and select a debugger from the dropdown menu:
|
||||
|
||||
- **Attach FW (blackmagic):** Can be used via **Wi-Fi** or **USB**
|
||||
- **Attach FW (DAP):** Can be used via **USB** only
|
||||
|
||||
Note that when debugging via USB, you need to make sure the selected debugger matches the debug mode on your Devboard. To check the debug mode on your Devboard, access the Devboard's web interface as described [here](#dev_board_wifi_connection) and check the **USB mode** field. If you want to use a different debug mode, enable this mode by following the steps in [Devboard debug modes](#dev_board_debug_modes).
|
||||
|
||||
5. If needed, flash your Flipper Zero with the `./fbt flash` command, then click the ▷ **Start Debugging** button in the debug sidebar to start the debugging session.
|
||||
|
||||
6. Note that starting a debug session halts the execution of the firmware, so you'll need to click the I▷ **Continue** button on the toolbar at the top of your VS Code window to continue execution.
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_devboard_VS_Code.jpg width=900
|
||||
|
||||
> [!note]
|
||||
> If you want to use a different debug mode on your Developer Board, visit [Devboard debug modes](#dev_board_debug_modes).
|
||||
>
|
||||
> If you want to read logs via the Developer Board, see [Reading logs via the Devboard](#dev_board_reading_logs).
|
||||
>
|
||||
> To learn about debugging in VS Code, see [VS Code official guide](https://code.visualstudio.com/docs/editor/debugging).
|
||||
@@ -1,33 +0,0 @@
|
||||
# Devboard debug modes {#dev_board_debug_modes}
|
||||
|
||||
The Wi-Fi Devboard for Flipper Zero supports **Black Magic** and **DAPLink** debug modes, and you can switch between them depending on your needs. Note that available modes depend on connection:
|
||||
|
||||
- **Wi-Fi:** Only **Black Magic** mode is available.
|
||||
- **USB:** Switch between **Black Magic** (default) and **DAPLink**. Learn more about switching debug modes for USB connection below.
|
||||
|
||||
> [!note]
|
||||
> Black Magic mode doesn't support RTOS threads, but you can still perform other debugging operations.
|
||||
|
||||
***
|
||||
|
||||
## Switching debug modes for USB connection
|
||||
|
||||
Switching debug modes for working via USB has to be done wirelessly (yes, you read that correctly). Additionally, depending on how the Devboard wireless connection is configured, you may need to follow different steps for **Wi-Fi access point mode** or **Wi-Fi client mode**:
|
||||
|
||||
1. If the Devboard isn't connected to your Flipper Zero, turn off your Flipper Zero and connect the Developer Board, then turn the device back on.
|
||||
|
||||
2. Access the Devboard's web interface:
|
||||
|
||||
- [Wi-Fi access point mode](#wifi-access-point)
|
||||
|
||||
- [Wi-Fi client mode](#wifi-client-mode)
|
||||
|
||||
3. In the **WiFi** tab, click the **USB mode** option and select **BlackMagicProbe** or **DapLink**.
|
||||
|
||||
4. Click **SAVE**, then click **REBOOT** to apply the changes.
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_WiFi_devboard_switching_modes_CDN.jpg width=700
|
||||
|
||||
> [!note]
|
||||
> After switching debug modes on your Devboard, remember to select the same debugger in **VS Code** in the **Run and Debug** tab, and click the ▷ **Start Debugging** button.
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
# Firmware update on Developer Board {#dev_board_fw_update}
|
||||
|
||||
It's important to regularly update your Developer Board to ensure that you have access to the latest features and bug fixes. This page will guide you through the necessary steps to update the firmware of your Developer Board.
|
||||
|
||||
> [!note]
|
||||
> This guide assumes that you're familiar with the basics of the command line. If you're new to it, we recommend checking out these [Windows](https://learn.microsoft.com/en-us/powershell/scripting/learn/ps101/01-getting-started?view=powershell-7.4) or [macOS/Linux](https://ubuntu.com/tutorials/command-line-for-beginners#1-overview) command line tutorials.
|
||||
|
||||
If you’re not, please refer to the [Windows](https://www.digitalcitizen.life/command-prompt-how-use-basic-commands/) or [MacOS / Linux](https://ubuntu.com/tutorials/command-line-for-beginners#1-overview) command line tutorials.
|
||||
|
||||
## Step 1. Install the micro Flipper Build Tool
|
||||
|
||||
[micro Flipper Build Tool (uFBT)](https://pypi.org/project/ufbt/) is a cross-platform tool developed and supported by our team that enables basic development tasks for Flipper Zero, such as building and debugging applications, flashing firmware, creating VS Code development configurations, and flashing firmware to the Wi-Fi Developer Board.
|
||||
|
||||
**On Linux & macOS:**
|
||||
|
||||
1. Open a terminal.
|
||||
2. Install `pipx` by following the instructions on the [official website](https://pipx.pypa.io/stable/installation/).
|
||||
3. Restart the terminal.
|
||||
4. Install `ufbt`:
|
||||
```
|
||||
pipx install ufbt
|
||||
```
|
||||
|
||||
**On Windows:**
|
||||
|
||||
1. Download the latest version of Python on [the official website](https://www.python.org/downloads/windows/) and install it.
|
||||
2. Open PowerShell.
|
||||
3. Install `pipx`:
|
||||
```
|
||||
py -m pip install --user pipx
|
||||
```
|
||||
4. Add `pipx` to PATH:
|
||||
```
|
||||
py -m pipx ensurepath
|
||||
```
|
||||
5. Restart PowerShell.
|
||||
6. Install `ufbt`:
|
||||
```
|
||||
pipx install ufbt
|
||||
```
|
||||
***
|
||||
|
||||
## Step 2. Connect the Devboard to PC
|
||||
|
||||
To update the firmware, you need to switch your Developer Board to Bootloader mode, connect to a PC via a USB cable, and make sure that the PC detects the Developer Board:
|
||||
|
||||
1. List all of the serial devices on your computer.
|
||||
|
||||
- **macOS:** Run the `ls /dev/cu.*` command in the Terminal.
|
||||
|
||||
- **Linux:** Run the `ls /dev/tty*` command in the Terminal.
|
||||
|
||||
- **Windows:** Go to **Device Manager** and expand the **Ports (COM & LPT)** section.
|
||||
|
||||
2. Connect the Developer Board to your computer using a USB-C cable.
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_devboard_update_wired_connection.jpg width=700
|
||||
|
||||
3. Switch your Developer Board to Bootloader mode:
|
||||
|
||||
3.1. Press and hold the **BOOT** button.
|
||||
|
||||
3.2. Press and release the **RESET** button while holding the **BOOT** button.
|
||||
|
||||
3.3. Release the **BOOT** button.
|
||||
\image html https://cdn.flipper.net/Flipper_Zero_devboard_bootloader.jpg width=700
|
||||
|
||||
4. Repeat the first command above (listing serial devices) and view the name of your Developer Board that appeared in the list.
|
||||
|
||||
***
|
||||
|
||||
## Step 3. Flash the firmware
|
||||
|
||||
**On Linux & macOS:**
|
||||
|
||||
```
|
||||
python3 -m ufbt devboard_flash
|
||||
```
|
||||
|
||||
**On Windows:** Run the following command in PowerShell:
|
||||
|
||||
```
|
||||
py -m ufbt devboard_flash
|
||||
```
|
||||
|
||||
You should see the following message: `WiFi board flashed successfully`.
|
||||
|
||||
### If flashing fails
|
||||
|
||||
Occasionally, you might get an error message during the flashing process, such as:
|
||||
|
||||
```
|
||||
A fatal error occurred: Serial data stream stopped: Possible serial noise or corruption.
|
||||
```
|
||||
|
||||
*or*
|
||||
|
||||
```
|
||||
FileNotFoundError: [Errno 2] No such file or directory: '/dev/cu.usbmodem01'
|
||||
```
|
||||
|
||||
To fix it, try doing the following:
|
||||
|
||||
- Disconnect the Developer Board from your computer, then reconnect it. After that, switch your Developer Board to Bootloader mode once again, as described in Step 2.
|
||||
|
||||
- Use a different USB port on your computer.
|
||||
|
||||
- Use a different USB-C cable.
|
||||
|
||||
***
|
||||
|
||||
## Step 4. Finish the installation
|
||||
|
||||
1. Reboot the Developer Board by pressing the **RESET** button.
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_devboard_reboot_after_flashing.jpg width=700
|
||||
|
||||
2. Disconnect and reconnect the USB-C cable.
|
||||
|
||||
You've successfully updated the firmware of your Developer Board!
|
||||
|
||||
If you followed the **Get started with the Devboard** guide, you're ready for the next step: [Step 3. Plug the Devboard into Flipper Zero](#dev_board_get_started_step-3).
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
# Get started with the Devboard {#dev_board_get_started}
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_WiFi_developer_board_box_CDN.jpg width=700
|
||||
|
||||
Before you start using your Devboard, you need to prepare your Flipper Zero and Devboard for debugging. In this guide, we'll walk you through all the necessary steps and provide links to explore the Devboard's capabilities further.
|
||||
|
||||
***
|
||||
|
||||
## Step 1. Enable Debug Mode on your Flipper Zero
|
||||
|
||||
Since the main purpose of the Developer board is to debug applications on Flipper Zero, you first need to enable Debug Mode. To do so, go to **Settings → System** and set **Debug** to **ON**.
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_enamble_debug_CDN.jpg width=700
|
||||
|
||||
> [!note]
|
||||
> Debug Mode needs to be re-enabled after each update of Flipper Zero's firmware.
|
||||
|
||||
Debug Mode allows you to debug your apps for Flipper Zero, as well as access debugging options in apps via the user interface and CLI. To learn more about Flipper Zero CLI, visit [Command-line interface in Flipper Docs](https://docs.flipper.net/development/cli).
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Command_Line_Interface_CDN.jpg width=700
|
||||
|
||||
***
|
||||
|
||||
## Step 2. Update firmware on the Developer Board
|
||||
|
||||
The Developer Board comes with stock firmware that may not include all the latest features and bug fixes. To ensure optimal performance, please update your board's firmware using the instructions in [Firmware update on Devboard](#dev_board_fw_update).
|
||||
|
||||
***
|
||||
|
||||
## Step 3. Plug the Devboard into Flipper Zero {#dev_board_get_started_step-3}
|
||||
|
||||
Once your Developer Board firmware is up to date, you can proceed to plug it into your Flipper Zero. Two important things to keep in mind:
|
||||
|
||||
1. **Power off your Flipper Zero before plugging in the Developer Board.**
|
||||
|
||||
If you skip this step, you may corrupt the data stored on the microSD card. Connecting external modules with a large capacitive load may affect the microSD card's power supply since both the microSD card and external module are powered from the same 3.3 V power source inside Flipper Zero.
|
||||
|
||||
2. **Make sure the Developer Board is inserted all the way in.**
|
||||
|
||||
If your Flipper Zero isn't in a silicone case, insert the module all the way in so there is no gap between your Flipper Zero and the Devboard. You may need to apply more force to insert it completely. After that, press and hold the **BACK** button to power on your Flipper Zero.
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_external_module_without_case_CDN.jpg width=700
|
||||
|
||||
If your Flipper Zero is in a silicone case, insert the module all the way in so there is no gap in the middle between the silicone case and the module. After that, press and hold the **BACK** button to power on your Flipper Zero.
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_external_module_with_case_CDN.jpg width=700
|
||||
|
||||
***
|
||||
|
||||
## Step 4. Connect to a computer
|
||||
|
||||
Now, you can connect the Developer Board to your computer via USB or Wi-Fi, depending on your needs. We described both methods in separate documents:
|
||||
|
||||
- **[Via USB cable](#dev_board_usb_connection)** for debugging in DAP Link or Black Magic mode, and reading logs.
|
||||
- [Via Wi-Fi](#dev_board_wifi_connection) for debugging in Black Magic mode.
|
||||
|
||||
***
|
||||
|
||||
## Next steps
|
||||
|
||||
You are ready to debug now! To further explore what you can do with the Devboard, check out these pages:
|
||||
|
||||
- [Debugging via the Devboard](#dev_board_debugging_guide)
|
||||
- [Devboard debug modes](#dev_board_debug_modes)
|
||||
- [Reading logs via the Devboard](#dev_board_reading_logs)
|
||||
|
||||
These guides should help you get started with your Devboard. If you have any questions or you want to share your experience, don't hesitate to join our community on [Reddit](https://www.reddit.com/r/flipperzero/) and [Discord](https://discord.com/invite/flipper), where we have a dedicated #wifi-devboard channel.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
# Reading logs via the Devboard {#dev_board_reading_logs}
|
||||
|
||||
The Developer Board allows you to read Flipper Zero logs via UART. Unlike reading logs via the command-line interface (CLI), the Developer Board enables you to collect logs from the device directly to a serial console independently from the operating system of Flipper Zero. It allows you to see the device's logs when it's loading, updating, or crashing. It's useful for debugging and troubleshooting during software development.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Flipper Zero logs can only be viewed when the developer board is connected via USB.
|
||||
> The option to view logs over Wi-Fi will be added in future updates.
|
||||
|
||||
## Setting the log level
|
||||
|
||||
Depending on your needs, you can set the log level by going to **Main Menu → Settings → Log Level**. To learn more about logging levels, visit [Settings](https://docs.flipper.net/basics/settings#d5TAt).
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_log_level.jpg "You can manually set the preferred log level" width=700
|
||||
|
||||
## Viewing Flipper Zero logs
|
||||
|
||||
Depending on your operating system, you need to install an additional application on your computer to read logs via the Developer Board:
|
||||
|
||||
### macOS
|
||||
|
||||
On macOS, you need to install the **minicom** communication program by doing the following:
|
||||
|
||||
1. [Install Homebrew](https://brew.sh/) by running the following command in the Terminal:
|
||||
```bash
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
```
|
||||
2. After installation of Homebrew, run the following command to install `minicom`:
|
||||
```bash
|
||||
brew install minicom
|
||||
```
|
||||
|
||||
After installation of `minicom` on your macOS computer, you can connect to the Developer Board to read Flipper Zero logs by doing the following:
|
||||
|
||||
1. Cold-plug the Developer Board into your Flipper Zero by turning off the Flipper Zero, connecting the developer board, and then turning it back on.
|
||||
2. On your computer, open the Terminal and run the following command:
|
||||
```bash
|
||||
ls /dev/cu.*
|
||||
```
|
||||
> [!NOTE]
|
||||
>
|
||||
> The list of devices.
|
||||
3. Connect the developer board to your computer using a USB Type-C cable.
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_developer_board_wired.png width=700
|
||||
|
||||
4. Rerun the command. Two new devices have to appear: this is the Developer Board.
|
||||
|
||||
```text
|
||||
/dev/cu.usbmodemblackmagic1
|
||||
```
|
||||
```bash
|
||||
/dev/cu.usbmodemblackmagic3
|
||||
```
|
||||
> [!NOTE]
|
||||
>
|
||||
> Your Developer Board might have different names.
|
||||
6. Run the following command:
|
||||
```bash
|
||||
minicom -D /dev/<port> -b 230400
|
||||
```
|
||||
Where `<port>` is the name of your device with a bigger number.
|
||||
Example:
|
||||
```bash
|
||||
minicom -D /dev/cu.usbmodemblackmagic3 -b 230400
|
||||
```
|
||||
7. View logs of your Flipper Zero in the Terminal.
|
||||
8. To quit, close the `minicom` window or quit via the `minicom` menu.
|
||||
|
||||
### Linux
|
||||
|
||||
On Linux, you need to install the `minicom` communication program. For example, on Ubuntu, run in the Terminal the following command:
|
||||
|
||||
```bash
|
||||
sudo apt install minicom
|
||||
```
|
||||
|
||||
After installation of `minicom` on your Linux computer, you can connect to the Developer Board to read Flipper Zero logs by doing the following:
|
||||
|
||||
1. Cold-plug the Developer Board into your Flipper Zero by turning off the Flipper Zero, connecting the developer board, and then turning it back on.
|
||||
2. On your computer, open the Terminal and run the following command:
|
||||
```bash
|
||||
ls /dev/tty*
|
||||
```
|
||||
Note the list of devices.
|
||||
3. Connect the developer board to your computer using a USB Type-C cable.
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_developer_board_wired.png width=700
|
||||
|
||||
4. Rerun the command. Two new devices have to appear: this is the Developer Board.
|
||||
```bash
|
||||
/dev/ttyACM0
|
||||
```
|
||||
```bash
|
||||
/dev/ttyACM1
|
||||
```
|
||||
> [!NOTE]
|
||||
>
|
||||
> Your Developer Board might have different names.
|
||||
5. Run the following command:
|
||||
```bash
|
||||
minicom -D /dev/<port> -b 230400
|
||||
```
|
||||
Where `<port>` is the name of your device with a bigger number.
|
||||
Example:
|
||||
```bash
|
||||
minicom -D /dev/cu.usbmodemblackmagic3 -b 230400
|
||||
```
|
||||
6. View logs of your Flipper Zero in the Terminal.
|
||||
> [!NOTE]
|
||||
>
|
||||
> If no logs are shown in the Terminal,
|
||||
> try running the command from Step 5 with another device name.
|
||||
>
|
||||
7. To quit, close the minicom window or quit via the minicom menu.
|
||||
|
||||
### Windows
|
||||
|
||||
On Windows, do the following:
|
||||
|
||||
1. On your computer, [install the PuTTY application](https://www.chiark.greenend.org.uk/\~sgtatham/putty/latest.html).
|
||||
2. Cold-plug the Developer Board into your Flipper Zero by turning off the Flipper Zero, connecting the developer board, and then turning it back on.
|
||||
3. Connect the developer board to your computer using a USB Type-C cable.
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_developer_board_wired.png width=700
|
||||
|
||||
4. Find the serial port that the developer board is connected to by going to **Device Manager → Ports (COM & LPT)** and looking for a new port that appears when you connect the Wi-Fi developer board.
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_devboard_Device_Manager.png width=700
|
||||
|
||||
5. Run the PuTTY application and select **Serial** as the connection type.
|
||||
|
||||
6. Enter the port number you found in the previous step into the **Serial line** field.
|
||||
|
||||
7. Set the **Speed** parameter to **230400** and click **Open**.
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_devboard_PuTTy.jpg width=700
|
||||
|
||||
8. View logs of your Flipper Zero in the PuTTY terminal window.
|
||||
|
||||
9. To quit, close the PuTTY window.
|
||||
@@ -1,22 +0,0 @@
|
||||
# USB connection to the Devboard {#dev_board_usb_connection}
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_WiFi_devboard_USB_connection_CDN.jpg width=700
|
||||
|
||||
To connect to the Developer Board via USB, do the following:
|
||||
|
||||
1. If the Devboard isn't connected to your Flipper Zero, turn off your Flipper Zero and connect the Developer Board to it. Then, turn your Flipper Zero back on.
|
||||
|
||||
2. On your computer, check the list of serial devices.
|
||||
|
||||
- **macOS:** On your computer, run `ls /dev/cu.*` in the Terminal.
|
||||
|
||||
- **Linux:** On your computer, run `ls /dev/tty*` in the Terminal.
|
||||
|
||||
- **Windows:** Go to **Device Manager** and expand the **Ports (COM & LPT)** section.
|
||||
|
||||
3. Connect the Devboard to your computer via a USB-C cable.
|
||||
|
||||
4. Repeat **Step 2**. Two new devices will appear — this is the Developer Board.
|
||||
|
||||
> [!warning]
|
||||
> If the Developer Board doesn't appear in the list of devices, try using a different cable, USB port, or computer.
|
||||
@@ -1,59 +0,0 @@
|
||||
# Wi-Fi connection to the Devboard {#dev_board_wifi_connection}
|
||||
|
||||
You can connect to the Developer Board wirelessly in two ways:
|
||||
|
||||
- **Wi-Fi access point mode (default):** The Devboard creates its own Wi-Fi network, which you can connect to in order to access its web interface and debug via Wi-Fi. The downside is that you will need to disconnect from your current Wi-Fi network, resulting in a loss of internet connection.
|
||||
|
||||
- **Wi-Fi client mode:** You can connect to the Devboard through an existing Wi-Fi network, allowing you to access the Devboard web interface and debug via Wi-Fi without losing your internet connection.
|
||||
|
||||
Let's go over both of these modes below.
|
||||
|
||||
***
|
||||
|
||||
## Wi-Fi access point (AP) mode {#wifi-access-point}
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_WiFi_devboard_Access_Point_CDN.jpg width=700
|
||||
|
||||
Out of the box, the Developer Board is configured to work as a Wi-Fi access point. To connect the Developer Board in this mode, do the following:
|
||||
|
||||
1. Plug the Wi-Fi Devboard into your Flipper Zero by turning off your Flipper Zero and connecting the Developer Board, and then turning it back on.
|
||||
|
||||
2. Open Wi-Fi settings on your client device (phone, laptop, or other).
|
||||
|
||||
3. Connect to the network:
|
||||
|
||||
Name: `blackmagic`
|
||||
Password: `iamwitcher`
|
||||
|
||||
If your computer fails to find the **blackmagic** network, read the [troubleshooting section](#wifi-access-point_troubleshooting) below.
|
||||
|
||||
4. To access the Devboard's web interface, open a browser and go to <http://192.168.4.1> or <http://blackmagic.local>.
|
||||
|
||||
### If your computer fails to find the black magic network {#wifi-access-point_troubleshooting}
|
||||
|
||||
- Reset Wi-Fi connection on your computer.
|
||||
|
||||
- The Developer Board is probably configured to work in Wi-Fi client mode. → Reset your Developer Board settings to default by pressing and holding the **BOOT** button for **10 seconds**, then wait for the Devboard to reboot. After the reset, the Devboard will work in Wi-Fi access point mode.
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_Wi-Fi_devboard_reboot.jpg width=700
|
||||
|
||||
***
|
||||
|
||||
## Wi-Fi client (STA) mode {#wifi-client-mode}
|
||||
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_WiFi_devboard_STA_CDN.jpg width=700
|
||||
|
||||
To connect the Developer Board in **Wi-Fi client** mode, you need to configure it to connect to your Wi-Fi network by doing the following:
|
||||
|
||||
1. Plug the Wi-Fi Devboard into your Flipper Zero by turning off your Flipper Zero and connecting the Developer Board, and then turning the device back on.
|
||||
|
||||
2. Connect to the Developer Board in [Wi-Fi access point](#wifi-access-point) mode.
|
||||
|
||||
3. In a browser, go to the Devboard's web interface at <http://192.168.4.1> or <http://blackmagic.local>.
|
||||
|
||||
4. Select the **STA** mode and enter your network's **SSID** (name) and **password**. For convenience, you can click the **+** button to see the list of nearby 2.4 GHz networks (5 GHz networks aren't supported).
|
||||
|
||||
5. Save the configuration and reboot the Developer Board.
|
||||
\image html https://cdn.flipperzero.one/Flipper_Zero_WiFi_devboard_connect_to_WiFi_CDN.jpg width=700
|
||||
|
||||
6. Now, you can access the Devboard's web interface at [http://blackmagic.local](https://blackmagic.local) via the existing Wi-Fi network without losing connection to the internet.
|
||||
@@ -1,155 +0,0 @@
|
||||
# Flipper Build Tool {#fbt}
|
||||
|
||||
FBT is the entry point for firmware-related commands and utilities.
|
||||
It is invoked by `./fbt` in the firmware project root directory. Internally, it is a wrapper around [scons](https://scons.org/) build system.
|
||||
|
||||
If you don't need all features of `fbt` — like building the whole firmware — and only want to build and debug a single app, you can use [ufbt](https://pypi.org/project/ufbt/).
|
||||
|
||||
## Environment
|
||||
|
||||
To use `fbt`, you only need `git` installed in your system.
|
||||
|
||||
`fbt` by default downloads and unpacks a pre-built toolchain, and then modifies environment variables for itself to use it.
|
||||
It does not contaminate your global system's path with the toolchain.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> However, if you wish to use tools supplied with the toolchain outside `fbt`,
|
||||
> you can open an *fbt shell*, with properly configured environment.
|
||||
>
|
||||
> - On Windows, simply run `scripts/toolchain/fbtenv.cmd`.
|
||||
> - On Linux & MacOS, run `source scripts/toolchain/fbtenv.sh` in a new shell.
|
||||
> - You can also type ```. `./fbt -s env` ``` in your shell. (Keep the "." at the beginning.)
|
||||
|
||||
If your system is not supported by pre-built toolchain variants or you want to use custom versions of dependencies, you can `set FBT_NOENV=1`.
|
||||
|
||||
`fbt` will skip toolchain & environment configuration and will expect all tools to be available on your system's `PATH`. *(this option is not available on Windows)*
|
||||
|
||||
If `FBT_TOOLCHAIN_PATH` variable is set, `fbt` will use that directory to unpack toolchain into. By default, it downloads toolchain into `toolchain` subdirectory repo's root.
|
||||
|
||||
If you want to enable extra debug output for `fbt` and toolchain management scripts, you can `set FBT_VERBOSE=1`.
|
||||
|
||||
`fbt` always performs `git submodule update --init` on start, unless you set `FBT_NO_SYNC=1` in the environment:
|
||||
- On Windows, it's `set "FBT_NO_SYNC=1"` in the shell you're running `fbt` from
|
||||
- On \*nix, it's `$ FBT_NO_SYNC=1 ./fbt ...`
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> There are more variables controlling basic `fbt` behavior.
|
||||
> See `fbt` & `fbtenv` scripts' sources for details.
|
||||
>
|
||||
|
||||
## Invoking FBT
|
||||
|
||||
To build with FBT, call it and specify configuration options & targets to build. For example:
|
||||
|
||||
`./fbt COMPACT=1 DEBUG=0 VERBOSE=1 updater_package copro_dist`
|
||||
|
||||
To run cleanup (think of `make clean`) for specified targets, add the `-c` option.
|
||||
|
||||
## Build directories
|
||||
|
||||
`fbt` builds updater & firmware in separate subdirectories in `build`, and their names depend on optimization settings (`COMPACT` & `DEBUG` options).
|
||||
|
||||
However, for ease of integration with IDEs, the latest built variant's directory is always linked as `built/latest`.
|
||||
|
||||
Additionally, `compile_commands.json` is generated in that folder (it is used for code completion support in IDEs).
|
||||
|
||||
`build/latest` symlink & compilation database are only updated upon *firmware build targets* — that is, when you're re-building the firmware itself. Running other tasks, like firmware flashing or building update bundles *for a different debug/release configuration or hardware target*, does not update `built/latest` dir to point to that configuration.
|
||||
|
||||
Running other tasks, like firmware flashing or building update bundles *for a different debug/release configuration or hardware target*, does not update `built/latest` dir to point to that configuration.
|
||||
|
||||
## VSCode integration
|
||||
|
||||
`fbt` includes basic development environment configuration for VS Code. Run `./fbt vscode_dist` to deploy it. That will copy the initial environment configuration to the `.vscode` folder. After that, you can use that configuration by starting VS Code and choosing the firmware root folder in the "File > Open Folder" menu.
|
||||
|
||||
That will copy the initial environment configuration to the `.vscode` folder.
|
||||
|
||||
After that, you can use that configuration by starting VSCode and choosing the firmware root folder in the <kbd>File > Open Folder</kbd> menu.
|
||||
|
||||
To use language servers other than the default VS Code C/C++ language server, use `./fbt vscode_dist LANG_SERVER=<language-server>` instead.
|
||||
|
||||
Currently `fbt` supports the default language server (`cpptools`) and `clangd`.
|
||||
|
||||
- On the first start, you'll be prompted to install recommended plugins. We highly recommend installing them for the best development experience. _You can find a list of them in `.vscode/extensions.json`._
|
||||
- Basic build tasks are invoked in the <kbd>Ctrl + Shift + B</kbd> menu.
|
||||
- Debugging requires a supported probe. That includes:
|
||||
- Wi-Fi Devboard with stock firmware (blackmagic).
|
||||
- ST-Link and compatible devices.
|
||||
- J-Link for flashing and debugging (in VSCode only). _Note that J-Link tools are not included with our toolchain and you have to [download](https://www.segger.com/downloads/jlink/) them yourself and put them on your system's `PATH`.
|
||||
- Without a supported probe, you can install firmware on Flipper using the USB installation method.
|
||||
|
||||
## FBT targets
|
||||
|
||||
`fbt` keeps track of internal dependencies, so you only need to build the highest-level target you need, and `fbt` will make sure everything they depend on is up-to-date.
|
||||
|
||||
### High-level (what you most likely need)
|
||||
|
||||
- `fw_dist` — build & publish firmware to the `dist` folder. This is a default target when no others are specified.
|
||||
- `fap_dist` — build external plugins & publish to the `dist` folder.
|
||||
- `updater_package`, `updater_minpackage` — build a self-update package. The minimal version only includes the firmware's DFU file; the full version also includes a radio stack & resources for the SD card.
|
||||
- `copro_dist` — bundle Core2 FUS+stack binaries for qFlipper.
|
||||
- `flash` — flash the attached device over SWD interface with supported probes. Probe is detected automatically; you can override it with `SWD_TRANSPORT=...` variable. If multiple probes are attached, you can specify the serial number of the probe to use with `SWD_TRANSPORT_SERIAL=...`.
|
||||
- `flash_usb`, `flash_usb_full` — build, upload and install the update package to the device over USB. See details on `updater_package` and `updater_minpackage`.
|
||||
- `debug` — build and flash firmware, then attach with gdb with firmware's .elf loaded.
|
||||
- `debug_other`, `debug_other_blackmagic` — attach GDB without loading any `.elf`. It will allow you to manually add external `.elf` files with `add-symbol-file` in GDB.
|
||||
- `updater_debug` — attach GDB with the updater's `.elf` loaded.
|
||||
- `devboard_flash` — Update WiFi dev board. Supports `ARGS="..."` to pass extra arguments to the update script, e.g. `ARGS="-c dev"`.
|
||||
- `blackmagic` — debug firmware with Blackmagic probe (WiFi dev board).
|
||||
- `openocd` — just start OpenOCD. You can pass extra arguments with `ARGS="..."`.
|
||||
- `get_blackmagic` — output the blackmagic address in the GDB remote format. Useful for IDE integration.
|
||||
- `get_stlink` — output serial numbers for attached STLink probes. Used for specifying an adapter with `SWD_TRANSPORT_SERIAL=...`.
|
||||
- `lint`, `format` — run clang-format on the C source code to check and reformat it according to the `.clang-format` specs. Supports `ARGS="..."` to pass extra arguments to clang-format.
|
||||
- `lint_py`, `format_py` — run [black](https://black.readthedocs.io/en/stable/index.html) on the Python source code, build system files & app manifests. Supports `ARGS="..."` to pass extra arguments to black.
|
||||
- `lint_img`, `format_img` — check the image assets for errors and format them. Enforces color depth and strips metadata.
|
||||
- `lint_all`, `format_all` — run all linters and formatters.
|
||||
- `firmware_pvs` — generate a PVS Studio report for the firmware. Requires PVS Studio to be available on your system's `PATH`.
|
||||
- `doxygen` — generate Doxygen documentation for the firmware. `doxy` target also opens web browser to view the generated documentation.
|
||||
- `cli` — start a Flipper CLI session over USB.
|
||||
|
||||
### Firmware targets
|
||||
|
||||
- `faps` — build all external & plugin apps as [`.faps`](AppsOnSDCard.md).
|
||||
- `fbt` also defines per-app targets. For example, for an app with `appid=snake_game` target names are:
|
||||
- `fap_snake_game`, etc. — build single app as `.fap` by its app ID.
|
||||
- Check out [--extra-ext-apps](#command-line-parameters) for force adding extra apps to external build.
|
||||
- `fap_snake_game_list`, etc — generate source + assembler listing for app's `.fap`.
|
||||
- `flash`, `firmware_flash` — flash the current version to the attached device over SWD.
|
||||
- `jflash` — flash the current version to the attached device with JFlash using a J-Link probe. The JFlash executable must be on your `$PATH`.
|
||||
- `firmware_all`, `updater_all` — build a basic set of binaries.
|
||||
- `firmware_list`, `updater_list` — generate source + assembler listing.
|
||||
- `firmware_cdb`, `updater_cdb` — generate a `compilation_database.json` file for external tools and IDEs. It can be created without actually building the firmware.
|
||||
|
||||
### Assets
|
||||
|
||||
- `resources` — build resources and their manifest files
|
||||
- `dolphin_ext` — process dolphin animations for the SD card
|
||||
- `icons` — generate `.c+.h` for icons from PNG assets
|
||||
- `proto` — generate `.pb.c+.pb.h` for `.proto` sources
|
||||
- `proto_ver` — generate `.h` with a protobuf version
|
||||
- `dolphin_internal`, `dolphin_blocking` — generate `.c+.h` for corresponding dolphin assets
|
||||
|
||||
## Command-line parameters {#command-line-parameters}
|
||||
|
||||
- `--options optionfile.py` (default value `fbt_options.py`) — load a file with multiple configuration values
|
||||
- `--extra-int-apps=app1,app2,appN` — force listed apps to be built as internal with the `firmware` target
|
||||
- `--extra-ext-apps=app1,app2,appN` — force listed apps to be built as external with the `firmware_extapps` target
|
||||
- `--extra-define=A --extra-define=B=C ` — extra global defines that will be passed to the C/C++ compiler, can be specified multiple times
|
||||
- `--proxy-env=VAR1,VAR2` — additional environment variables to expose to subprocesses spawned by `fbt`. By default, `fbt` sanitizes the execution environment and doesn't forward all inherited environment variables. You can find the list of variables that are always forwarded in the `environ.scons` file.
|
||||
|
||||
## Configuration
|
||||
|
||||
Default configuration variables are set in the configuration file: `fbt_options.py`.
|
||||
|
||||
Values set in the command line have higher precedence over the configuration file.
|
||||
|
||||
You can also create a file called `fbt_options_local.py` that will be evaluated when loading default options file, enabling persistent overriding of default options without modifying default configuration.
|
||||
|
||||
You can find out available options with `./fbt -h`.
|
||||
|
||||
### Firmware application set
|
||||
|
||||
You can create customized firmware builds by modifying the list of apps to be included in the build. App presets are configured with the `FIRMWARE_APPS` option, which is a `map(configuration_name:str → application_list:tuple(str))`. To specify an app set to use in the build, set `FIRMWARE_APP_SET` to its name.
|
||||
For example, to build a firmware image with unit tests, run `./fbt FIRMWARE_APP_SET=unit_tests`.
|
||||
|
||||
Check out `fbt_options.py` for details.
|
||||
@@ -1,207 +0,0 @@
|
||||
# BadUSB File Format {#badusb_file_format}
|
||||
|
||||
## Command syntax
|
||||
|
||||
BadUsb app uses extended DuckyScript syntax.
|
||||
|
||||
It is compatible with classic USB Rubber Ducky 1.0 scripts but provides some additional commands and features,
|
||||
such as custom USB ID, `ALT` + `Numpad` input method, `SYSRQ` command, and more functional keys.
|
||||
|
||||
## Script file format
|
||||
|
||||
BadUsb app can execute only text scripts from `.txt` files, no compilation is required. Both `\n` and `\r\n` line endings are supported. Empty lines are allowed. You can use spaces or tabs for line indentation.
|
||||
|
||||
## Command set
|
||||
|
||||
### Comment line
|
||||
|
||||
Just a single comment line. The interpreter will ignore all text after the `REM` command.
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:---------|:--------------|:--------|
|
||||
| REM | Comment text | |
|
||||
|
||||
### Delay
|
||||
|
||||
Pause script execution by a defined time.
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:--------------|:--------------------------|:--------------------------------------|
|
||||
| DELAY | Delay value in ms | Single delay |
|
||||
| DEFAULT_DELAY | Delay value in ms | Add delay before every next command |
|
||||
| DEFAULTDELAY | Delay value in ms | Same as DEFAULT_DELAY |
|
||||
|
||||
### Special keys
|
||||
|
||||
| Command | Notes |
|
||||
|:--------------------|:------------------|
|
||||
| DOWNARROW / DOWN | |
|
||||
| LEFTARROW / LEFT | |
|
||||
| RIGHTARROW / RIGHT | |
|
||||
| UPARROW / UP | |
|
||||
| ENTER | |
|
||||
| DELETE | |
|
||||
| BACKSPACE | |
|
||||
| END | |
|
||||
| HOME | |
|
||||
| ESCAPE / ESC | |
|
||||
| INSERT | |
|
||||
| PAGEUP | |
|
||||
| PAGEDOWN | |
|
||||
| CAPSLOCK | |
|
||||
| NUMLOCK | |
|
||||
| SCROLLLOCK | |
|
||||
| PRINTSCREEN | |
|
||||
| BREAK | Pause/Break key |
|
||||
| PAUSE | Pause/Break key |
|
||||
| SPACE | |
|
||||
| TAB | |
|
||||
| MENU | Context menu key |
|
||||
| APP | Same as MENU |
|
||||
| Fx | F1-F12 keys |
|
||||
|
||||
### Modifier keys
|
||||
|
||||
The following modifier keys are recognized:
|
||||
| Command | Notes |
|
||||
| ------- | ------------ |
|
||||
| CTRL | |
|
||||
| CONTROL | Same as CTRL |
|
||||
| SHIFT | |
|
||||
| ALT | |
|
||||
| GUI | |
|
||||
| WINDOWS | Same as GUI |
|
||||
|
||||
You can chain multiple modifier keys together using hyphens (`-`) or spaces.
|
||||
|
||||
## Key hold and release
|
||||
|
||||
Up to 5 keys can be hold simultaneously.
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:---------|:---------------------------------|:------------------------------------------|
|
||||
| HOLD | Special key or single character | Press and hold key until RELEASE command |
|
||||
| RELEASE | Special key or single character | Release key |
|
||||
|
||||
## String
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:----------|:-------------|:--------------------------------------------|
|
||||
| STRING | Text string | Print text string |
|
||||
| STRINGLN | Text string | Print text string and press enter after it |
|
||||
|
||||
## String delay
|
||||
|
||||
Delay between key presses.
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:----------------------|:-------------------|:-----------------------------------------------|
|
||||
| STRING_DELAY | Delay value in ms | Applied once to next appearing STRING command |
|
||||
| STRINGDELAY | Delay value in ms | Same as STRING_DELAY |
|
||||
| DEFAULT_STRING_DELAY | Delay value in ms | Apply to every appearing STRING command |
|
||||
| DEFAULTSTRINGDELAY | Delay value in ms | Same as DEFAULT_STRING_DELAY |
|
||||
|
||||
### Repeat
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:---------|:------------------------------|:-------------------------|
|
||||
| REPEAT | Number of additional repeats | Repeat previous command |
|
||||
|
||||
### ALT+Numpad input
|
||||
|
||||
On Windows and some Linux systems, you can print characters by holding `ALT` key and entering its code on Numpad.
|
||||
| Command | Parameters | Notes |
|
||||
| :---------- | :--------------- | :--------------------------------------------------------------- |
|
||||
| ALTCHAR | Character code | Print single character |
|
||||
| ALTSTRING | Text string | Print text string using ALT+Numpad method |
|
||||
| ALTCODE | Text string | Same as ALTSTRING, presents in some DuckyScript implementations |
|
||||
|
||||
### SysRq
|
||||
|
||||
Send [SysRq command](https://en.wikipedia.org/wiki/Magic_SysRq_key)
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:---------|:------------------|:-------|
|
||||
| SYSRQ | Single character | |
|
||||
|
||||
## Media keys
|
||||
|
||||
Some Media/Consumer Control keys can be pressed with `MEDIA` command
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:---------|:---------------------------|:------|
|
||||
| MEDIA | Media key, see list below | |
|
||||
|
||||
|
||||
| Key name | Notes |
|
||||
|:-------------------|:-------------------------------|
|
||||
| POWER | |
|
||||
| REBOOT | |
|
||||
| SLEEP | |
|
||||
| LOGOFF | |
|
||||
| EXIT | |
|
||||
| HOME | |
|
||||
| BACK | |
|
||||
| FORWARD | |
|
||||
| REFRESH | |
|
||||
| SNAPSHOT | Take photo in a camera app |
|
||||
| PLAY | |
|
||||
| PAUSE | |
|
||||
| PLAY_PAUSE | |
|
||||
| NEXT_TRACK | |
|
||||
| PREV_TRACK | |
|
||||
| STOP | |
|
||||
| EJECT | |
|
||||
| MUTE | |
|
||||
| VOLUME_UP | |
|
||||
| VOLUME_DOWN | |
|
||||
| FN | Fn/Globe key on Mac keyboard |
|
||||
| BRIGHT_UP | Increase display brightness |
|
||||
| BRIGHT_DOWN | Decrease display brightness |
|
||||
|
||||
## Fn/Globe key commands (Mac/iPad)
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:---------|:---------------------------------|:-------|
|
||||
| GLOBE | Special key or single character | |
|
||||
|
||||
## Wait for button press
|
||||
|
||||
Will wait indefinitely for a button to be pressed
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:----------------------|:-----------|:------------------------------------------------------------------------------|
|
||||
| WAIT_FOR_BUTTON_PRESS | None | Will wait for the user to press a button to continue script execution |
|
||||
|
||||
## USB device ID
|
||||
|
||||
You can set the custom ID of the Flipper USB HID device. ID command should be in the **first line** of script, it is executed before script run.
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
|:---------|:------------------------------|:-------|
|
||||
| ID | VID:PID Manufacturer:Product | |
|
||||
|
||||
Example:
|
||||
```text
|
||||
ID 1234:abcd Flipper Devices:Flipper Zero
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> VID and PID are hex codes and are mandatory.
|
||||
> Manufacturer and Product are text strings and are optional.
|
||||
|
||||
## Mouse Commands
|
||||
|
||||
Mouse movement and click commands. Mouse click commands support HOLD functionality.
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
| ------------- | -------------------------------| -------------------------------- |
|
||||
| LEFTCLICK | None | |
|
||||
| LEFT_CLICK | None | functionally same as LEFTCLICK |
|
||||
| RIGHTCLICK | None | |
|
||||
| RIGHT_CLICK | None | functionally same as RIGHTCLICK |
|
||||
| MOUSEMOVE | x y: int move mount/direction | |
|
||||
| MOUSE_MOVE | x y: int move mount/direction | functionally same as MOUSEMOVE |
|
||||
| MOUSESCROLL | delta: int scroll distance | |
|
||||
| MOUSE_SCROLL | delta: int scroll distance | functionally same as MOUSESCROLL |
|
||||
@@ -1,145 +0,0 @@
|
||||
# Infrared Flipper File Formats {#infrared_file_format}
|
||||
|
||||
## Supported protocols list for "type: parsed"
|
||||
|
||||
```
|
||||
NEC
|
||||
NECext
|
||||
NEC42
|
||||
NEC42ext
|
||||
Samsung32
|
||||
RC6
|
||||
RC5
|
||||
RC5X
|
||||
SIRC
|
||||
SIRC15
|
||||
SIRC20
|
||||
Kaseikyo
|
||||
RCA
|
||||
```
|
||||
|
||||
## Infrared Remote File Format
|
||||
|
||||
### Example
|
||||
|
||||
Filetype: IR signals file
|
||||
Version: 1
|
||||
#
|
||||
name: Button_1
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: EE 87 00 00
|
||||
command: 5D A0 00 00
|
||||
#
|
||||
name: Button_2
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 504 3432 502 483 500 484 510 502 502 482 501 485 509 1452 504 1458 509 1452 504 481 501 474 509 3420 503
|
||||
#
|
||||
name: Button_3
|
||||
type: parsed
|
||||
protocol: SIRC
|
||||
address: 01 00 00 00
|
||||
command: 15 00 00 00
|
||||
|
||||
### Description
|
||||
|
||||
Filename extension: `.ir`
|
||||
|
||||
This file format is used to store an infrared remote that consists of an arbitrary number of buttons.
|
||||
Each button is separated from others by a comment character (`#`) for better readability.
|
||||
|
||||
Known protocols are represented in the `parsed` form, whereas non-recognized signals may be saved and re-transmitted as `raw` data.
|
||||
|
||||
#### Version history
|
||||
|
||||
1. Initial version.
|
||||
|
||||
#### Format fields
|
||||
|
||||
| Name | Use | Type | Description |
|
||||
| ---------- | ------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| name | both | string | Name of the button. Only printable ASCII characters are allowed. |
|
||||
| type | both | string | Type of the signal. Must be `parsed` or `raw`. |
|
||||
| protocol | parsed | string | Name of the infrared protocol. Refer to `ir` console command for the complete list of supported protocols. |
|
||||
| address | parsed | hex | Payload address. Must be 4 bytes long. |
|
||||
| command | parsed | hex | Payload command. Must be 4 bytes long. |
|
||||
| frequency | raw | uint32 | Carrier frequency, in Hertz, usually 38000 Hz. |
|
||||
| duty_cycle | raw | float | Carrier duty cycle, usually 0.33. |
|
||||
| data | raw | uint32 | Raw signal timings, in microseconds between logic level changes. Individual elements must be space-separated. Maximum timings amount is 1024. |
|
||||
|
||||
## Infrared Library File Format
|
||||
|
||||
### Examples
|
||||
|
||||
- [TV Universal Library](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/main/infrared/resources/infrared/assets/tv.ir)
|
||||
- [A/C Universal Library](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/main/infrared/resources/infrared/assets/ac.ir)
|
||||
- [Audio Universal Library](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/main/infrared/resources/infrared/assets/audio.ir)
|
||||
|
||||
### Description
|
||||
|
||||
Filename extension: `.ir`
|
||||
|
||||
This file format is used to store universal remote libraries. It is identical to the previous format, differing only in the `Filetype` field.
|
||||
It also has predefined button names for each universal library type, so that the universal remote application can understand them.
|
||||
See [Universal Remotes](../UniversalRemotes.md) for more information.
|
||||
|
||||
### Version history
|
||||
|
||||
1. Initial version.
|
||||
|
||||
## Infrared Test File Format
|
||||
|
||||
### Examples
|
||||
|
||||
See [Infrared Unit Tests](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/debug/unit_tests/resources/unit_tests/infrared) for various examples.
|
||||
|
||||
### Description
|
||||
|
||||
Filename extension: `.irtest`
|
||||
|
||||
This file format is used to store technical test data that is too large to keep directly in the firmware.
|
||||
It is mostly similar to the two previous formats, with the main difference being the addition of the parsed signal arrays.
|
||||
|
||||
Each infrared protocol must have corresponding unit tests complete with an `.irtest` file.
|
||||
|
||||
Known protocols are represented in the `parsed_array` form, whereas raw data has the `raw` type.
|
||||
Note: a single parsed signal must be represented as an array of size 1.
|
||||
|
||||
### Version history
|
||||
|
||||
1. Initial version.
|
||||
|
||||
#### Format fields
|
||||
|
||||
| Name | Use | Type | Description |
|
||||
| ---------- | ------------ | ------ | ---------------------------------------------------------------- |
|
||||
| name | both | string | Name of the signal. Only printable ASCII characters are allowed. |
|
||||
| type | both | string | Type of the signal. Must be `parsed_array` or `raw`. |
|
||||
| count | parsed_array | uint32 | The number of parsed signals in an array. Must be at least 1. |
|
||||
| protocol | parsed_array | string | Same as in previous formats. |
|
||||
| address | parsed_array | hex | Ditto. |
|
||||
| command | parsed_array | hex | Ditto. |
|
||||
| repeat | parsed_array | bool | Indicates whether the signal is a repeated button press. |
|
||||
| frequency | raw | uint32 | Same as in previous formats. |
|
||||
| duty_cycle | raw | float | Ditto. |
|
||||
| data | raw | uint32 | Ditto. |
|
||||
|
||||
#### Signal names
|
||||
|
||||
The signal names in an `.irtest` file follow a convention `<name><test_number>`, where the name is one of:
|
||||
|
||||
- decoder_input
|
||||
- decoder_expected
|
||||
- encoder_decoder_input,
|
||||
|
||||
and the number is a sequential integer: 1, 2, 3, etc., which produces names like `decoder_input1`, `encoder_decoder_input3`, and so on.
|
||||
|
||||
| Name | Type | Description |
|
||||
| --------------------- | ------------ | ----------------------------------------------------------------------------------------------------- |
|
||||
| decoder_input | raw | A raw signal containing the decoder input. Also used as the expected encoder output. |
|
||||
| decoder_expected | parsed_array | An array of parsed signals containing the expected decoder output. Also used as the encoder input. |
|
||||
| encoder_decoder_input | parsed_array | An array of parsed signals containing both the encoder-decoder input and expected output. |
|
||||
|
||||
See [Unit Tests](../UnitTests.md) for more info.
|
||||
@@ -1,50 +0,0 @@
|
||||
# LF RFID key file format {#lfrfid_file_format}
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
Filetype: Flipper RFID key
|
||||
Version: 1
|
||||
Key type: EM4100
|
||||
Data: 01 23 45 67 89
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Filename extension: `.rfid`
|
||||
|
||||
The file stores a single RFID key of the type defined by the `Key type` parameter.
|
||||
|
||||
### Version history
|
||||
|
||||
1. Initial version.
|
||||
|
||||
### Format fields
|
||||
|
||||
| Name | Description |
|
||||
| -------- | --------------------- |
|
||||
| Key type | Key protocol type |
|
||||
| Data | Key data (HEX values) |
|
||||
|
||||
### Supported key types
|
||||
|
||||
| Type | Full name |
|
||||
| ----------- | ----------------- |
|
||||
| EM4100 | EM-Micro EM4100 |
|
||||
| H10301 | HID H10301 |
|
||||
| Idteck | IDTECK |
|
||||
| Indala26 | Motorola Indala26 |
|
||||
| IOProxXSF | Kantech IOProxXSF |
|
||||
| AWID | AWID |
|
||||
| FDX-A | FECAVA FDX-A |
|
||||
| FDX-B | ISO FDX-B |
|
||||
| HIDProx | Generic HIDProx |
|
||||
| HIDExt | Generic HIDExt |
|
||||
| Pyramid | Farpointe Pyramid |
|
||||
| Viking | Viking |
|
||||
| Jablotron | Jablotron |
|
||||
| Paradox | Paradox |
|
||||
| PAC/Stanley | PAC/Stanley |
|
||||
| Keri | Keri |
|
||||
| Gallagher | Gallagher |
|
||||
| GProxII | Guardall GProx II |
|
||||
@@ -1,347 +0,0 @@
|
||||
# NFC Flipper File Formats {#nfc_file_format}
|
||||
|
||||
## UID + Header (General format)
|
||||
|
||||
### Example
|
||||
|
||||
Filetype: Flipper NFC device
|
||||
Version: 4
|
||||
# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire
|
||||
Device type: ISO14443-4A
|
||||
# UID is common for all formats
|
||||
UID: 04 48 6A 32 33 58 80
|
||||
-------------------------
|
||||
(Device-specific data)
|
||||
|
||||
### Description
|
||||
|
||||
This file format is used to store the device type and the UID of an NFC device. It does not store any internal data, so it is only used as a header for other formats.
|
||||
|
||||
Version differences:
|
||||
|
||||
1. Initial version, deprecated
|
||||
2. LSB ATQA (e.g. 4400 instead of 0044)
|
||||
3. MSB ATQA (current version)
|
||||
4. Replace UID device type with ISO14443-3A
|
||||
|
||||
## ISO14443-3A
|
||||
|
||||
Filetype: Flipper NFC device
|
||||
Version: 4
|
||||
# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire
|
||||
Device type: ISO14443-3A
|
||||
# UID is common for all formats
|
||||
UID: 34 19 6D 41 14 56 E6
|
||||
# ISO14443-3A specific data
|
||||
ATQA: 00 44
|
||||
SAK: 00
|
||||
|
||||
### Description
|
||||
|
||||
This file format is used to store the UID, SAK and ATQA of an ISO14443-3A device.
|
||||
UID must be either 4 or 7 bytes long. ATQA is 2 bytes long. SAK is 1 byte long.
|
||||
|
||||
Version differences:
|
||||
None, there are no versions yet.
|
||||
|
||||
## ISO14443-3B
|
||||
|
||||
Filetype: Flipper NFC device
|
||||
Version: 4
|
||||
# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire
|
||||
Device type: ISO14443-3B
|
||||
# UID is common for all formats
|
||||
UID: 30 1D B3 28
|
||||
# ISO14443-3B specific data
|
||||
Application data: 00 12 34 FF
|
||||
Protocol info: 11 81 E1
|
||||
|
||||
### Description
|
||||
|
||||
This file format is used to store the UID, Application data and Protocol info of a ISO14443-3B device.
|
||||
UID must be 4 bytes long. Application data is 4 bytes long. Protocol info is 3 bytes long.
|
||||
|
||||
Version differences:
|
||||
None, there are no versions yet.
|
||||
|
||||
## ISO14443-4A
|
||||
|
||||
### Example
|
||||
|
||||
Filetype: Flipper NFC device
|
||||
Version: 4
|
||||
# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire
|
||||
Device type: ISO14443-4A
|
||||
# UID is common for all formats
|
||||
UID: 04 48 6A 32 33 58 80
|
||||
# ISO14443-3A specific data
|
||||
ATQA: 03 44
|
||||
SAK: 20
|
||||
# ISO14443-4A specific data
|
||||
ATS: 06 75 77 81 02 80
|
||||
|
||||
### Description
|
||||
|
||||
This file format is used to store the UID, SAK and ATQA of a ISO14443-4A device. It also stores the Answer to Select (ATS) data of the card.
|
||||
ATS must be no less than 5 bytes long.
|
||||
|
||||
Version differences:
|
||||
None, there are no versions yet.
|
||||
|
||||
## NTAG/Ultralight
|
||||
|
||||
### Example
|
||||
|
||||
Filetype: Flipper NFC device
|
||||
Version: 4
|
||||
# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire
|
||||
Device type: NTAG/Ultralight
|
||||
# UID is common for all formats
|
||||
UID: 04 85 90 54 12 98 23
|
||||
# ISO14443-3A specific data
|
||||
ATQA: 00 44
|
||||
SAK: 00
|
||||
# NTAG/Ultralight specific data
|
||||
Data format version: 2
|
||||
NTAG/Ultralight type: NTAG216
|
||||
Signature: 1B 84 EB 70 BD 4C BD 1B 1D E4 98 0B 18 58 BD 7C 72 85 B4 E4 7B 38 8E 96 CF 88 6B EE A3 43 AD 90
|
||||
Mifare version: 00 04 04 02 01 00 13 03
|
||||
Counter 0: 0
|
||||
Tearing 0: 00
|
||||
Counter 1: 0
|
||||
Tearing 1: 00
|
||||
Counter 2: 0
|
||||
Tearing 2: 00
|
||||
Pages total: 231
|
||||
Pages read: 231
|
||||
Page 0: 04 85 92 9B
|
||||
Page 1: 8A A0 61 81
|
||||
Page 2: CA 48 0F 00
|
||||
...
|
||||
Page 224: 00 00 00 00
|
||||
Page 225: 00 00 00 00
|
||||
Page 226: 00 00 7F BD
|
||||
Page 227: 04 00 00 E2
|
||||
Page 228: 00 05 00 00
|
||||
Page 229: 00 00 00 00
|
||||
Page 230: 00 00 00 00
|
||||
Failed authentication attempts: 0
|
||||
|
||||
### Description
|
||||
|
||||
This file format is used to store the UID, SAK and ATQA of a Mifare Ultralight/NTAG device. It also stores the internal data of the card, the signature, the version, and the counters. The data is stored in pages, just like on the card itself.
|
||||
|
||||
The "NTAG/Ultralight type" field contains the concrete device type. It must be one of: Mifare Ultralight, Mifare Ultralight 11, Mifare Ultralight 21, NTAG203, NTAG213, NTAG215, NTAG216, NTAG I2C 1K, NTAG I2C 2K, NTAG I2C Plus 1K, NTAG I2C Plus 2K.
|
||||
|
||||
The "Signature" field contains the reply of the tag to the READ_SIG command. More on that can be found here: <https://www.nxp.com/docs/en/data-sheet/MF0ULX1.pdf> (page 31)
|
||||
|
||||
The "Mifare version" field is not related to the file format version but to the Mifare Ultralight version. It contains the response of the tag to the GET_VERSION command. More on that can be found here: <https://www.nxp.com/docs/en/data-sheet/MF0ULX1.pdf> (page 21)
|
||||
|
||||
Other fields are the direct representation of the card's internal state. Learn more about them in the same datasheet.
|
||||
|
||||
Version differences:
|
||||
|
||||
1. Mifare Ultralight type is stored directly in Device type field
|
||||
2. Current version, Mifare Ultralight type is stored in the same-named field
|
||||
|
||||
## Mifare Classic
|
||||
|
||||
### Example
|
||||
|
||||
Filetype: Flipper NFC device
|
||||
Version: 4
|
||||
# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire
|
||||
Device type: Mifare Classic
|
||||
# UID is common for all formats
|
||||
UID: BA E2 7C 9D
|
||||
# ISO14443-3A specific data
|
||||
ATQA: 00 02
|
||||
SAK: 18
|
||||
# Mifare Classic specific data
|
||||
Mifare Classic type: 4K
|
||||
Data format version: 2
|
||||
# Mifare Classic blocks, '??' means unknown data
|
||||
Block 0: BA E2 7C 9D B9 18 02 00 46 44 53 37 30 56 30 31
|
||||
Block 1: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 3: FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF
|
||||
Block 4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 5: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 6: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 7: FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF
|
||||
...
|
||||
Block 238: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 239: FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF
|
||||
Block 240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 241: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 242: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 243: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 244: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 245: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 246: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 247: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 248: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 249: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 251: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 252: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 253: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 254: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 255: FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF
|
||||
|
||||
### Description
|
||||
|
||||
This file format is used to store the NFC-A and Mifare Classic specific data of a Mifare Classic card. Aside from the NFC-A data, it stores the card type (1K/4K) and the internal data of the card. The data is stored in blocks, there is no sector grouping. If the block's data is unknown, it is represented by '??'. Otherwise, the data is represented as a hex string.
|
||||
|
||||
Version differences:
|
||||
|
||||
1. Initial version, has Key A and Key B masks instead of marking unknown data with '??'.
|
||||
|
||||
Example:
|
||||
|
||||
...
|
||||
Data format version: 1
|
||||
# Key map is the bit mask indicating valid key in each sector
|
||||
Key A map: 000000000000FFFF
|
||||
Key B map: 000000000000FFFF
|
||||
# Mifare Classic blocks
|
||||
...
|
||||
|
||||
2. Current version
|
||||
|
||||
## Mifare DESFire
|
||||
|
||||
### Example
|
||||
|
||||
Filetype: Flipper NFC device
|
||||
Version: 4
|
||||
# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire
|
||||
Device type: Mifare DESFire
|
||||
# UID is common for all formats
|
||||
UID: 04 2F 19 0A CD 66 80
|
||||
# ISO14443-3A specific data
|
||||
ATQA: 03 44
|
||||
SAK: 20
|
||||
# ISO14443-4A specific data
|
||||
ATS: 06 75 77 81 02 80
|
||||
# Mifare DESFire specific data
|
||||
PICC Version: 04 01 01 12 00 1A 05 04 01 01 02 01 1A 05 04 2F 19 0A CD 66 80 CE ED D4 51 80 31 19
|
||||
PICC Free Memory: 7520
|
||||
PICC Change Key ID: 00
|
||||
PICC Config Changeable: true
|
||||
PICC Free Create Delete: true
|
||||
PICC Free Directory List: true
|
||||
PICC Key Changeable: true
|
||||
PICC Max Keys: 01
|
||||
PICC Key 0 Version: 00
|
||||
Application Count: 1
|
||||
Application IDs: 56 34 12
|
||||
Application 563412 Change Key ID: 00
|
||||
Application 563412 Config Changeable: true
|
||||
Application 563412 Free Create Delete: true
|
||||
Application 563412 Free Directory List: true
|
||||
Application 563412 Key Changeable: true
|
||||
Application 563412 Max Keys: 0E
|
||||
Application 563412 Key 0 Version: 00
|
||||
Application 563412 Key 1 Version: 00
|
||||
Application 563412 Key 2 Version: 00
|
||||
Application 563412 Key 3 Version: 00
|
||||
Application 563412 Key 4 Version: 00
|
||||
Application 563412 Key 5 Version: 00
|
||||
Application 563412 Key 6 Version: 00
|
||||
Application 563412 Key 7 Version: 00
|
||||
Application 563412 Key 8 Version: 00
|
||||
Application 563412 Key 9 Version: 00
|
||||
Application 563412 Key 10 Version: 00
|
||||
Application 563412 Key 11 Version: 00
|
||||
Application 563412 Key 12 Version: 00
|
||||
Application 563412 Key 13 Version: 00
|
||||
Application 563412 File IDs: 01
|
||||
Application 563412 File 1 Type: 00
|
||||
Application 563412 File 1 Communication Settings: 00
|
||||
Application 563412 File 1 Access Rights: EE EE
|
||||
Application 563412 File 1 Size: 256
|
||||
Application 563412 File 1: 13 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
### Description
|
||||
|
||||
This file format is used to store the NFC-A and Mifare DESFire specific data of a Mifare DESFire card. Aside from the NFC-A data, it stores the card type (DESFire) and the internal data of the card. The data is stored per-application, and per-file. Here, the card was written using those pm3 commands:
|
||||
|
||||
hf mfdes createapp --aid 123456 --fid 2345 --dfname astra
|
||||
hf mfdes createfile --aid 123456 --fid 01 --isofid 0001 --size 000100
|
||||
hf mfdes write --aid 123456 --fid 01 -d 1337
|
||||
|
||||
Version differences:
|
||||
None, there are no versions yet.
|
||||
|
||||
## Mifare Classic Dictionary
|
||||
|
||||
### Example
|
||||
|
||||
# Key dictionary from https://github.com/ikarus23/MifareClassicTool.git
|
||||
|
||||
# More well known keys!
|
||||
# Standard keys
|
||||
FFFFFFFFFFFF
|
||||
A0A1A2A3A4A5
|
||||
D3F7D3F7D3F7
|
||||
000000000000
|
||||
|
||||
# Keys from mfoc
|
||||
B0B1B2B3B4B5
|
||||
4D3A99C351DD
|
||||
1A982C7E459A
|
||||
AABBCCDDEEFF
|
||||
714C5C886E97
|
||||
587EE5F9350F
|
||||
A0478CC39091
|
||||
533CB6C723F6
|
||||
8FD0A4F256E9
|
||||
...
|
||||
|
||||
### Description
|
||||
|
||||
This file contains a list of Mifare Classic keys. Each key is represented as a hex string. Lines starting with '#' are ignored as comments. Blank lines are ignored as well.
|
||||
|
||||
## Mifare Ultralight C Dictionary
|
||||
|
||||
### Example
|
||||
|
||||
# Hexadecimal-Reversed Sample Key
|
||||
12E4143455F495649454D4B414542524
|
||||
# Byte-Reversed Sample Key (!NACUOYFIEMKAERB)
|
||||
214E4143554F594649454D4B41455242
|
||||
# Sample Key (BREAKMEIFYOUCAN!)
|
||||
425245414B4D454946594F5543414E21
|
||||
# Semnox Key (IEMKAERB!NACUOY )
|
||||
49454D4B41455242214E4143554F5900
|
||||
# Modified Semnox Key (IEMKAERB!NACUOYF)
|
||||
49454D4B41455242214E4143554F5946
|
||||
...
|
||||
|
||||
### Description
|
||||
|
||||
This file contains a list of Mifare Ultralight C keys. Each key is represented as a hex string. Lines starting with '#' are ignored as comments. Blank lines are ignored as well.
|
||||
|
||||
## EMV resources
|
||||
|
||||
### Example
|
||||
|
||||
Filetype: Flipper EMV resources
|
||||
Version: 1
|
||||
# EMV currency code: currency name
|
||||
0997: USN
|
||||
0994: XSU
|
||||
0990: CLF
|
||||
0986: BRL
|
||||
0985: PLN
|
||||
0984: BOV
|
||||
...
|
||||
|
||||
### Description
|
||||
|
||||
This file stores a list of EMV currency codes, country codes, or AIDs and their names. Each line contains a hex value and a name separated by a colon and a space.
|
||||
|
||||
Version differences:
|
||||
|
||||
1. Initial version
|
||||
@@ -1,304 +0,0 @@
|
||||
# SubGhz Subsystem File Formats {#subghz_file_format}
|
||||
|
||||
## .sub File Format
|
||||
|
||||
Flipper uses `.sub` files to store SubGhz signals. These files use the Flipper File Format. `.sub` files can contain either a SubGhz Key with a certain protocol or SubGhz RAW data.
|
||||
|
||||
A `.sub` file consist of 3 parts:
|
||||
|
||||
- **header**, contains the file type, version, and frequency
|
||||
- **preset information**, preset type and, in case of a custom preset, transceiver configuration data
|
||||
- **protocol and its data**, contains protocol name and its specific data, such as key, bit length, etc., or RAW data
|
||||
|
||||
Flipper's SubGhz subsystem uses presets to configure the radio transceiver. Presets are used to configure modulation, bandwidth, filters, etc. There are several presets available in stock firmware, and there is a way to create custom presets. See [SubGhz Presets](#adding-a-custom-preset) section for more details.
|
||||
|
||||
## Header format
|
||||
|
||||
Header is a mandatory part of a `.sub` file. It contains the file type, version, and frequency.
|
||||
|
||||
| Field | Type | Description |
|
||||
| ----------- | ------ | ----------------------------------------------------------------- |
|
||||
| `Filetype` | string | Filetype of subghz file format, must be `Flipper SubGhz Key File` |
|
||||
| `Version` | uint | Version of subghz file format, current version is 1 |
|
||||
| `Frequency` | uint | Frequency in Hertz |
|
||||
|
||||
## Preset information
|
||||
|
||||
Preset information is a mandatory part for `.sub` files. It contains preset type and, in case of custom preset, transceiver configuration data.
|
||||
|
||||
When using one of the standard presets, only `Preset` field is required. When using a custom preset, `Custom_preset_module` and `Custom_preset_data` fields are required.
|
||||
|
||||
| Field | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `Preset` | Radio preset name (configures modulation, bandwidth, filters, etc.). When using a custom preset, must be `FuriHalSubGhzPresetCustom` |
|
||||
| `Custom_preset_module` | Transceiver identifier, `CC1101` for Flipper Zero |
|
||||
| `Custom_preset_data` | Transceiver configuration data |
|
||||
|
||||
Built-in presets:
|
||||
|
||||
- `FuriHalSubGhzPresetOok270Async` — On/Off Keying, 270kHz bandwidth, async(IO throw GP0)
|
||||
- `FuriHalSubGhzPresetOok650Async` — On/Off Keying, 650kHz bandwidth, async(IO throw GP0)
|
||||
- `FuriHalSubGhzPreset2FSKDev238Async` — 2 Frequency Shift Keying, deviation 2kHz, 270kHz bandwidth, async(IO throw GP0)
|
||||
- `FuriHalSubGhzPreset2FSKDev12KAsync` — 2 Frequency Shift Keying, deviation 12kHz, 270kHz bandwidth, async(IO throw GP0)
|
||||
- `FuriHalSubGhzPreset2FSKDev476Async` — 2 Frequency Shift Keying, deviation 47kHz, 270kHz bandwidth, async(IO throw GP0)
|
||||
|
||||
### Transceiver Configuration Data {#transceiver-configuration-data}
|
||||
|
||||
Transceiver configuration data is a string of bytes, encoded in hex format, separated by spaces. For CC1101 data structure is: `XX YY XX YY .. 00 00 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ`, where:
|
||||
|
||||
- **XX**, holds register address,
|
||||
- **YY**, contains register value,
|
||||
- **00 00**, marks register block end,
|
||||
- **ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ**, 8 byte PA table (Power amplifier ramp table).
|
||||
|
||||
You can find more details in the [CC1101 datasheet](https://www.ti.com/lit/ds/symlink/cc1101.pdf) and `furi_hal_subghz` code.
|
||||
|
||||
## File Data
|
||||
|
||||
`.sub` file data section can either contain key data, consisting of a protocol name and its specific data, bit length, etc., or RAW data, which consists of an array of signal timings, recorded without any protocol-specific processing.
|
||||
|
||||
### Key Files
|
||||
|
||||
`.sub` files with key data files contain protocol name and its specific data, such as key value, bit length, etc.
|
||||
Check out the protocol registry for the full list of supported protocol names.
|
||||
|
||||
Example of a key data block in Princeton format:
|
||||
|
||||
```
|
||||
...
|
||||
Protocol: Princeton
|
||||
Bit: 24
|
||||
Key: 00 00 00 00 00 95 D5 D4
|
||||
TE: 400
|
||||
```
|
||||
|
||||
Protocol-specific fields in this example:
|
||||
|
||||
| Field | Description |
|
||||
| ----- | --------------------------------- |
|
||||
| `Bit` | Princeton payload length, in bits |
|
||||
| `Key` | Princeton payload data |
|
||||
| `TE` | Princeton quantization interval |
|
||||
|
||||
This file may contain additional fields, more details on available fields can be found in subghz protocols library.
|
||||
|
||||
### RAW Files
|
||||
|
||||
RAW `.sub` files contain raw signal data that is not processed through protocol-specific decoding. These files are useful for testing or sending data not supported by any known protocol.
|
||||
|
||||
For RAW files, 2 fields are required:
|
||||
|
||||
- **Protocol**, must be `RAW`
|
||||
- **RAW_Data**, contains an array of timings, specified in microseconds. Values must be non-zero, start with a positive number, and interleaved (change sign with each value). Up to 512 values per line. Can be specified multiple times to store multiple lines of data.
|
||||
|
||||
Example of RAW data:
|
||||
|
||||
Protocol: RAW
|
||||
RAW_Data: 29262 361 -68 2635 -66 24113 -66 11 ...
|
||||
|
||||
A long payload that doesn't fit into the internal memory buffer and consists of short duration timings (< 10us) may not be read fast enough from the SD card. That might cause the signal transmission to stop before reaching the end of the payload. Ensure that your SD Card has good performance before transmitting long or complex RAW payloads.
|
||||
|
||||
### BIN_RAW Files
|
||||
|
||||
BinRAW `.sub` files and `RAW` files both contain data that has not been decoded by any protocol. However, unlike `RAW`, `BinRAW` files only record a useful repeating sequence of durations with a restored byte transfer rate and without broadcast noise. These files can emulate nearly all static protocols, whether Flipper knows them or not.
|
||||
|
||||
- Usually, you have to receive the signal a little longer so that Flipper accumulates sufficient data to analyze it correctly.
|
||||
|
||||
For `BinRAW` files, the following parameters are required and must be aligned to the left:
|
||||
|
||||
- **Protocol**, must be `BinRAW`.
|
||||
- **Bit**, is the length of the payload of the entire file, in bits (max 4096).
|
||||
- **TE**, is the quantization interval, in us.
|
||||
- **Bit_RAW**, is the length of the payload in the next Data_RAW parameter, in bits.
|
||||
- **Data_RAW**, is an encoded sequence of durations, where each bit in the sequence encodes one TE interval: 1 - high level (there is a carrier), 0 - low (no carrier).
|
||||
For example, TE=100, Bit_RAW=8, Data_RAW=0x37 => 0b00110111, that is, `-200 200 -100 300` will be transmitted.
|
||||
When sending uploads, `Bit_RAW` and `Data_RAW` form a repeating block. Several such blocks are necessary if you want to send different sequences sequentially. However, usually, there will be only one block.
|
||||
|
||||
Example data from a `BinRAW` file:
|
||||
|
||||
```
|
||||
...
|
||||
Protocol: BinRAW
|
||||
Bit: 1572
|
||||
TE: 597
|
||||
Bit_RAW: 260
|
||||
Data_RAW: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F 4A B5 55 4C B3 52 AC D5 2D 53 52 AD 4A D5 35 00
|
||||
Bit_RAW: 263
|
||||
Data_RAW: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 04 D5 32 D2 AB 2B 33 32 CB 2C CC B3 52 D3 00
|
||||
Bit_RAW: 259
|
||||
Data_RAW: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 4A AB 55 34 D5 2D 4C CD 33 4A CD 55 4C D2 B3 00
|
||||
Bit_RAW: 263
|
||||
Data_RAW: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F 7F 4A AA D5 2A CC B2 B4 CB 34 CC AA AB 4D 53 53 00
|
||||
Bit_RAW: 264
|
||||
Data_RAW: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FC 00 00 15 2C CB 34 D3 35 35 4D 4B 32 B2 D3 33 00
|
||||
Bit_RAW: 263
|
||||
Data_RAW: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 DE 02 D3 54 D5 4C D2 CC AD 4B 2C B2 B5 54 CC AB 00
|
||||
```
|
||||
|
||||
## File examples
|
||||
|
||||
### Key file, standard preset
|
||||
|
||||
Filetype: Flipper SubGhz Key File
|
||||
Version: 1
|
||||
Frequency: 433920000
|
||||
Preset: FuriHalSubGhzPresetOok650Async
|
||||
Protocol: Princeton
|
||||
Bit: 24
|
||||
Key: 00 00 00 00 00 95 D5 D4
|
||||
TE: 400
|
||||
|
||||
### Key file, custom preset
|
||||
|
||||
Filetype: Flipper SubGhz Key File
|
||||
Version: 1
|
||||
Frequency: 433920000
|
||||
Preset: FuriHalSubGhzPresetCustom
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00
|
||||
Protocol: Princeton
|
||||
Bit: 24
|
||||
Key: 00 00 00 00 00 95 D5 D4
|
||||
TE: 400
|
||||
|
||||
### RAW file, standard preset
|
||||
|
||||
Filetype: Flipper SubGhz RAW File
|
||||
Version: 1
|
||||
Frequency: 433920000
|
||||
Preset: FuriHalSubGhzPresetOok650Async
|
||||
Protocol: RAW
|
||||
RAW_Data: 29262 361 -68 2635 -66 24113 -66 11 ...
|
||||
RAW_Data: -424 205 -412 159 -412 381 -240 181 ...
|
||||
RAW_Data: -1448 361 -17056 131 -134 233 -1462 131 -166 953 -100 ...
|
||||
|
||||
### RAW file, custom preset
|
||||
|
||||
Filetype: Flipper SubGhz RAW File
|
||||
Version: 1
|
||||
Frequency: 433920000
|
||||
Preset: FuriHalSubGhzPresetCustom
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00
|
||||
Protocol: RAW
|
||||
RAW_Data: 29262 361 -68 2635 -66 24113 -66 11 ...
|
||||
RAW_Data: -424 205 -412 159 -412 381 -240 181 ...
|
||||
RAW_Data: -1448 361 -17056 131 -134 233 -1462 131 -166 953 -100 ...
|
||||
|
||||
# SubGhz configuration files
|
||||
|
||||
SubGhz application provides support for adding extra radio presets and additional keys for decoding transmissions in certain protocols.
|
||||
|
||||
## SubGhz keeloq_mfcodes_user file
|
||||
|
||||
This file contains additional manufacturer keys for Keeloq protocol. It is used to decode Keeloq transmissions.
|
||||
This file is loaded at subghz application start and is located at path `/ext/subghz/assets/keeloq_mfcodes_user`.
|
||||
|
||||
### File format
|
||||
|
||||
File contains a header and a list of manufacturer keys.
|
||||
|
||||
File header format:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------ | ------ | ------------------------------------------------------------------ |
|
||||
| `Filetype` | string | SubGhz Keystore file format, always `Flipper SubGhz Keystore File` |
|
||||
| `Version` | uint | File format version, 0 |
|
||||
| `Encryption` | uint | File encryption: for user-provided file, set to 0 (disabled) |
|
||||
|
||||
Following the header, file contains a list of user-provided manufacture keys, one key per line.
|
||||
For each key, a name and encryption method must be specified, according to comment in file header. More information can be found in keeloq decoder source code.
|
||||
|
||||
### Example
|
||||
|
||||
# to use manual settings and prevent them from being deleted on upgrade, rename *_user.example files to *_user
|
||||
# for adding manufacture keys
|
||||
# AABBCCDDEEFFAABB:X:NAME
|
||||
# AABBCCDDEEFFAABB - man 64 bit
|
||||
# X - encryption method:
|
||||
# - 0 - iterates over both previous and man in direct and reverse byte sequence
|
||||
# - 1 - Simple Learning
|
||||
# - 2 - Normal_Learning
|
||||
# - 3 - Secure_Learning
|
||||
# - 4 - Magic_xor_type1 Learning
|
||||
#
|
||||
# NAME - name (string without spaces) max 64 characters long
|
||||
Filetype: Flipper SubGhz Keystore File
|
||||
Version: 0
|
||||
Encryption: 0
|
||||
AABBCCDDEEFFAABB:1:Test1
|
||||
AABBCCDDEEFFAABB:1:Test2
|
||||
|
||||
## SubGhz setting_user file
|
||||
|
||||
This file contains additional radio presets and frequencies for SubGhz application. It is used to add new presets and frequencies for existing presets. This file is being loaded on subghz application start and is located at path `/ext/subghz/assets/setting_user`.
|
||||
|
||||
### File format
|
||||
|
||||
File contains a header, basic options, and optional lists of presets and frequencies.
|
||||
|
||||
Header must contain the following fields:
|
||||
|
||||
- `Filetype`: SubGhz setting file format, must be `Flipper SubGhz Setting File`.
|
||||
- `Version`: file format version, current is `1`.
|
||||
|
||||
#### Basic settings
|
||||
|
||||
- `Add_standard_frequencies`: bool, flag indicating whether to load standard frequencies shipped with firmware. If set to `false`, only frequencies specified in this file will be used.
|
||||
- `Default_frequency`: uint, default frequency used in SubGhz application.
|
||||
|
||||
#### Adding more frequencies
|
||||
|
||||
- `Frequency`: uint — additional frequency for the subghz application frequency list. Used in Read and Read RAW. You can specify multiple frequencies, one per line.
|
||||
|
||||
#### Adding more hopper frequencies
|
||||
|
||||
- `Hopper_frequency`: uint — additional frequency for subghz application frequency hopping. Used in Frequency Analyzer. You can specify multiple frequencies, one per line.
|
||||
|
||||
Repeating the same frequency will cause Flipper to listen to this frequency more often.
|
||||
|
||||
#### Adding a Custom Preset {#adding-a-custom-preset}
|
||||
|
||||
You can have as many presets as you want. Presets are embedded into `.sub` files, so another Flipper can load them directly from that file.
|
||||
Each preset is defined by the following fields:
|
||||
|
||||
| Field | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| `Custom_preset_name` | string, preset name that will be shown in SubGHz application |
|
||||
| `Custom_preset_module` | string, transceiver identifier. Set to `CC1101` for Flipper Zero |
|
||||
| `Custom_preset_data` | transceiver configuration data. See [Transceiver Configuration Data](#transceiver-configuration-data) for details. |
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
# to use manual settings and prevent them from being deleted on upgrade, rename *_user.example files to *_user
|
||||
Filetype: Flipper SubGhz Setting File
|
||||
Version: 1
|
||||
|
||||
# Add Standard frequencies for your region
|
||||
Add_standard_frequencies: true
|
||||
|
||||
# Default Frequency: used as default for "Read" and "Read Raw"
|
||||
Default_frequency: 433920000
|
||||
|
||||
# Frequencies used for "Read", "Read Raw" and "Frequency Analyzer"
|
||||
Frequency: 300000000
|
||||
Frequency: 310000000
|
||||
Frequency: 320000000
|
||||
|
||||
# Frequencies used for hopping mode (keep this list small or Flipper will miss the signal)
|
||||
Hopper_frequency: 300000000
|
||||
Hopper_frequency: 310000000
|
||||
Hopper_frequency: 310000000
|
||||
|
||||
# Custom preset
|
||||
# format for CC1101 "Custom_preset_data:" XX YY XX YY .. 00 00 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ, where: XX-register, YY - register data, 00 00 - end load register, ZZ - 8 byte Pa table register
|
||||
|
||||
#Custom_preset_name: AM_1
|
||||
Custom_preset_module: CC1101
|
||||
Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00
|
||||
|
||||
#Custom_preset_name: AM_2
|
||||
#Custom_preset_module: CC1101
|
||||
#Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00
|
||||
```
|
||||