1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-13 13:09:49 +04:00

Compare commits

...

212 Commits

Author SHA1 Message Date
MX
32e64fd29e update changelog 2022-10-04 18:40:57 +03:00
MX
8f9d81b972 Merge pull request #84 from colingrady/wrap_rfid_fuzzer_menu
Allow the RFID protocol menu to wrap
2022-10-04 18:25:29 +03:00
MX
23e0566273 Merge pull request #85 from mvanzanten/adding-on-the-fly-changes-ui-addition
Improve UI for added on-the-fly feature
2022-10-04 18:25:07 +03:00
MX
4141483147 NFC update detect reader
OFW PR 1820 by gornekich
2022-10-04 18:23:11 +03:00
Matt Van Zanten
30e005d5c4 improve UI for added on the fly feature 2022-10-04 08:07:53 -07:00
MX
e3a2711eb3 Remove bank card uid emulation & fix emv info
OFW PR 1823 by gornekich
2022-10-04 18:05:57 +03:00
MX
8569641ce6 Infrared error message
OFW PR 1827 by gsurkov
2022-10-04 18:02:21 +03:00
MX
cafd06c71b Don't turn off the backlight on MFC dict attack
OFW PR 1826 by Astrrra
2022-10-04 17:59:22 +03:00
MX
06a7bda69b block hopping and detect raw at same time
and fix freq analyzer feedback display backlight
2022-10-04 17:58:12 +03:00
Colin Grady
c43ce93936 Allow the RFID protocol menu to wrap 2022-10-04 08:53:58 -06:00
MX
2288855163 update assets and changelog 2022-10-04 03:29:02 +03:00
MX
c0765c1114 rfid fuzzer H10301 support and bug fixes 2022-10-04 03:15:28 +03:00
MX
683c6254da Merge remote-tracking branch 'origin/dev' into dev 2022-10-04 02:36:19 +03:00
MX
2ef515ef56 Merge pull request #83 from mvanzanten/adding-on-the-fly-changes-2
Adding on the fly bit changes
2022-10-04 02:35:57 +03:00
MX
667be798fc rfid fuzzer, fix bugs, improve gui, add PAC/Stanley support
add more example files
2022-10-04 02:33:39 +03:00
MX
0f9598099a fix rfid fuzzer crash, fix bug when dict attack can't be restarted 2022-10-04 01:15:15 +03:00
MX
0d6f729386 CLI: log command argument (log level)
OFW PR 1817 by DrZlo13
2022-10-04 00:48:25 +03:00
MX
b452b6fd32 FFF trailing space fix
OFW PR 1811 by gsurkov
2022-10-04 00:45:09 +03:00
Matt Van Zanten
9403128a03 moving to center nicer 2022-10-03 11:32:10 -07:00
Matt Van Zanten
71589b28a7 removing debug logs 2022-10-03 11:09:51 -07:00
Matt Van Zanten
8b0fa6d0b1 running fbt format 2022-10-03 11:07:16 -07:00
Matt Van Zanten
cf47da0ff4 Merge branch 'dev' into adding-on-the-fly-changes-2 2022-10-03 10:47:17 -07:00
Matt Van Zanten
d6b7fae7e4 working version of the on the fly bit switcher 2022-10-03 10:29:04 -07:00
MX
110dc48b96 Merge remote-tracking branch 'origin/dev' into dev 2022-10-03 18:42:52 +03:00
MX
37c666ddf5 Merge pull request #82 from TQMatvey/pr_temp
SubGhz: Enable backlight on new signal
2022-10-03 18:42:18 +03:00
MX
6ddca568b9 correct notification sequence 2022-10-03 18:41:37 +03:00
MX
8993db56b8 this was not part of previous change 2022-10-03 18:40:22 +03:00
MX
3c1efda1db return carrier test included with non debug builds 2022-10-03 18:36:06 +03:00
MX
b62b7956a6 Merge pull request #80 from derskythe/fix-read-in-readraw-crash
Fix-read-in-readraw-crash
2022-10-03 18:27:54 +03:00
MX
dce5af5c2e hmm 2022-10-03 18:22:09 +03:00
MX
fbacdc5b7b fix critical bug with subghz rpc 2022-10-03 18:21:18 +03:00
MX
8dba4f25ae unused 2022-10-03 18:20:49 +03:00
derskythe
43ef4046ed Add stubs for split 2022-10-03 19:00:35 +04:00
mvanzanten
1e63f57bf7 working version, change bits on the fly 2022-10-02 12:06:06 -07:00
Matt Van Zanten
649887fe0f progress, adding on the fly 2022-10-02 08:18:01 -07:00
derskythe
be42c390f2 Save on SD Card only RAW files 2022-10-02 16:57:32 +04:00
derskythe
cbda5d996f Fix uncommited merge 2022-10-02 16:50:03 +04:00
derskythe
de1ec97512 Merge remote-tracking branch 'refs/remotes/origin/fix-read-in-readraw-crash' into fix-read-in-readraw-crash 2022-10-02 16:20:18 +04:00
MX
8af749c965 enable saving detect raw state via define 2022-10-02 13:50:29 +03:00
MX
4d3f45e911 Don’t show temp history dir in filebrowser 2022-10-02 10:18:31 +03:00
MX
63fee41a1f enable worker back 2022-10-02 09:51:27 +03:00
TQMatvey
f441fed68d SubGhz: Follow system backlight timer 2022-10-02 13:48:06 +07:00
TQMatvey
6e0eeed773 SubGhz: turn on display for new signal 2022-10-02 13:29:16 +07:00
MX
6bf306200e make loading subghz file from favourites a bit faster 2022-10-02 08:50:41 +03:00
MX
e2faf31b45 debug in subghz only when compiled with DEBUG=1 2022-10-02 07:34:39 +03:00
MX
85eb740559 do not save detect raw on/off settings 2022-10-02 06:38:34 +03:00
MX
cea14ae9c5 fix dir creation bug, save files only for RAW
TODO: files are broken when they have more than 512 elements in one line
Split file to 512 element chunks as it done in regular Read RAW
2022-10-02 06:23:09 +03:00
MX
e9a11cfce0 Merge branch 'dev' into fix-read-in-readraw-crash 2022-10-02 04:06:01 +03:00
MX
87a14b96e1 Merge branch 'fz-dev' into dev 2022-10-02 04:05:07 +03:00
derskythe
bbd3f9cf71 Fixed all bugs with saving directly to file, also fixed misspeled if/ifdef in all app 2022-10-02 03:18:30 +04:00
derskythe
230f09dddd enable delete temp files 2022-10-01 08:47:44 +04:00
derskythe
24e744f1d1 Added saving DetectRAW settings, trying to write files on SD instead of memory 2022-10-01 08:39:51 +04:00
あく
0f9ea925d3 UnitTests: fix thread join test (#1808) 2022-09-30 22:03:57 +09:00
Nikolay Minaylov
836de3df16 [FL-2825] iButton GUI fixes (#1805)
* Ibutton GUI fixes
* Fix memory leak in lfRFID write

Co-authored-by: あく <alleteam@gmail.com>
2022-09-30 21:56:12 +09:00
Sergey Gavrilov
c92217a109 Thread: Clear TLS after thread stop (#1807) 2022-09-30 19:59:11 +09:00
MX
41c93431c8 update changelog, readme, assets 2022-09-30 03:46:06 +03:00
MX
f0ea8f3a84 fix clock am/pm logic 2022-09-29 23:50:49 +03:00
MX
4d8f294e7a Merge pull request #79 from derskythe/subghz-freq-analyzer-long-press
Long press OK button in SubGHz Frequency analyzer switch to Read menu
2022-09-29 23:26:02 +03:00
derskythe
f543753873 Long press OK button in SubGHz Frequency analyzer switch to Read menu with selected frequency 2022-09-29 23:46:54 +04:00
MX
1fb1a68842 iButton GUI fixes
OFW PR 1805 by nminaylov
2022-09-29 20:56:04 +03:00
MX
54fedb9bc8 Merge pull request #78 from alexberkowitz/dev
Increase Sub-GHz remote label line length to 16
2022-09-29 18:34:22 +03:00
MX
8af9c00ddb Merge branch 'fz-dev' into dev 2022-09-29 18:20:05 +03:00
Sergey Gavrilov
5a22803bbc Revert "Revert "Furi Thread: don't use thread pointer after FuriThreadStateStopped callback (#1799)""
This reverts commit 7df70d7c62.
2022-09-29 18:15:02 +03:00
Alex Berkowitz
824f5ea027 Merge branch 'Eng1n33r:dev' into dev 2022-09-29 10:04:21 -05:00
hedger
76d38e832e fbt: reproducible manifest builds & improvements (#1801)
* fbt: reproducible manifest builds, less rebuild on small updates; scripts: assets: using timestamp from commandline af available
* fbt: added app import validation for launch_app & single app build targets
* fbt: COMSTR for app imports validation
* docs: minor fixes
* docs: markdown fix
* vscode: comments for RTOS startup

Co-authored-by: あく <alleteam@gmail.com>
2022-09-29 20:00:22 +09:00
Sergey Gavrilov
aba20b6af8 Furi Thread: fixed furi_thread_join, check if thread has not been started (#1803)
* furi thread: fixed furi_thread_join, check if thread has not been started
* Furi: correct returns in furi_thread_join

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
2022-09-29 19:42:15 +09:00
MX
226f8517f3 update readme and changelog 2022-09-29 11:01:15 +03:00
Sergey Gavrilov
7df70d7c62 Revert "Furi Thread: don't use thread pointer after FuriThreadStateStopped callback (#1799)"
This reverts commit 5883e134d4.
2022-09-29 09:27:03 +03:00
MX
9176387b9f update assets and changelog 2022-09-29 09:14:47 +03:00
MX
972c0dcb4a hide layouts folder in badusb app 2022-09-29 08:20:30 +03:00
MX
62e56e2618 rename apps to make it look a bit better in Apps tab in archive app
now old assets are removed so we can avoid duplicates
2022-09-29 08:20:00 +03:00
MX
f202d27206 Merge branch 'fz-dev' into dev 2022-09-29 05:57:02 +03:00
Mewa
bcfb12bf28 Keyboard: show Uppercase keys when replacing content (#1548)
Co-authored-by: あく <alleteam@gmail.com>
2022-09-29 02:44:24 +09:00
Sergey Gavrilov
5883e134d4 Furi Thread: don't use thread pointer after FuriThreadStateStopped callback (#1799)
* Furi Thread: correct furi_thread_join, do not use thread pointer after FuriThreadStateStopped callback
* Furi: a little bit easier way to do harakiri
* Furi: crash on thread self join attempt

Co-authored-by: あく <alleteam@gmail.com>
2022-09-29 02:37:07 +09:00
hedger
f8b532f063 [FL-2831] Resources cleanup in updater (#1796)
* updater: remove files from existing resources Manifest file before deploying new resources
* toolbox: tar: single file extraction API

Co-authored-by: あく <alleteam@gmail.com>
2022-09-29 02:13:12 +09:00
Vyacheslav Tumanov
e25b424188 Typos fix in some strings/comments #1794
Co-authored-by: あく <alleteam@gmail.com>
2022-09-29 01:52:46 +09:00
Nikolay Minaylov
4241ad24a3 [FL-2797] Signal Generator app (#1793)
* Signal Generator app
* MCO pin initialization in app
* furi_hal_pwm documentation

Co-authored-by: あく <alleteam@gmail.com>
2022-09-29 01:37:24 +09:00
MX
6bcc6f363b add 868.8 mhz for sommer systems 2022-09-28 16:35:40 +03:00
MX
3dcd8a73f1 update changelog 2022-09-28 08:06:47 +03:00
MX
9ad7f7825d update projector asset
by @Amec0e
2022-09-28 07:50:43 +03:00
MX
aa00606d22 remove unnecessary checks from brute plugin, subghz improvements
fix subghz gui in add manually, add BETT protocol in add manually
2022-09-28 07:50:09 +03:00
MX
9c62e1f6ac Merge pull request #77 from derskythe/subghz-save-settings-v2
SubGHz save settings version 2
2022-09-28 07:00:15 +03:00
MX
b934c41ed0 close file 2022-09-28 06:51:13 +03:00
MX
0ebb3f060e add a bit of changes 2022-09-28 06:46:45 +03:00
derskythe
8f2bd3be57 Update list of frequencies and change name of file of settings to not able to run in browser 2022-09-28 07:14:38 +04:00
derskythe
cc02d57857 Merge remote-tracking branch 'origin/subghz-save-settings-v2' into subghz-save-settings-v2
# Conflicts:
#	applications/main/subghz/subghz_last_settings.c
2022-09-28 07:09:58 +04:00
MX
0c5f11f713 return fix 2022-09-28 06:02:23 +03:00
derskythe
006d27ed93 Add removed fixed 2022-09-28 06:53:52 +04:00
MX
746b732034 remove unused code 2022-09-28 05:49:21 +03:00
Der Skythe
2ec9aeeefa Merge branch 'Eng1n33r:dev' into subghz-save-settings-v2 2022-09-28 06:32:54 +04:00
derskythe
8be08093e2 Change name of file to not able to "Run in App" in Browser 2022-09-28 06:28:23 +04:00
derskythe
406247c5d8 Ok button in frequency analyzer will set this frequency to receiver 2022-09-28 06:22:02 +04:00
derskythe
22a87d5707 struct doesn't correct written 2022-09-28 05:49:06 +04:00
MX
4271246d8a Merge branch 'fz-dev' into dev 2022-09-28 04:04:12 +03:00
derskythe
a3db6718c2 fix bug with invalid settings values in config 2022-09-28 04:31:29 +04:00
derskythe
0f0473bee6 fix bug with invalid settings values in config 2022-09-28 03:27:47 +04:00
derskythe
497be7ccb0 Last SubGHz settings is ready 2022-09-28 02:01:09 +04:00
Georgii Surkov
12a6290e91 [FL-2853] Reorganise Universal A/C library (#1792)
* Reorganise A/C universal remote library file
* Refactor infrared brute force code
* Update UniversalRemotes.md

Co-authored-by: あく <alleteam@gmail.com>
2022-09-28 02:11:28 +09:00
Tom Samstag
e6e1e7fe15 Add formatting to DESfire data dump (#1784)
Co-authored-by: gornekich <n.gorbadey@gmail.com>
2022-09-28 02:02:18 +09:00
MX
cb14d23108 format, add chamberlain 9bit 300mhz 2022-09-27 04:31:52 +03:00
MX
c4783664c0 subghz bruteforcer plugin: move title a bit 2022-09-27 00:51:36 +03:00
MX
91f3774246 update changelog 2022-09-26 23:55:39 +03:00
MX
1f8a034a71 Merge pull request #76 from derskythe/subbrute-deep-refactor
Fix speed problems with linear and some bugs
2022-09-26 23:09:13 +03:00
MX
8cc3e2f35a remove extra environment alloc 2022-09-26 23:07:53 +03:00
MX
069dd29f08 Revert "some fixes, trying to speed up bruteforce(unsuccessful)"
This reverts commit 61fee8e269.
2022-09-26 22:52:22 +03:00
derskythe
91c06a2168 fix disable env allocation many times 2022-09-26 21:41:49 +04:00
derskythe
545c4349d6 add vibro on finish and main menu set left 2022-09-26 21:26:51 +04:00
derskythe
a40e1a2be2 set big step to 50 2022-09-26 21:15:46 +04:00
derskythe
286300b35b fix disable env allocation many times 2022-09-26 21:15:02 +04:00
derskythe
633145495c fix twice button press in manual mode 2022-09-26 21:10:41 +04:00
derskythe
a0bcbf731d fix error on back when selecting existing dump 2022-09-26 21:01:14 +04:00
MX
60242cd7c4 fix nfc device typo, doesn’t affect resulting keys 2022-09-26 19:46:12 +03:00
Alex Berkowitz
3e9409a1a8 Merge branch 'dev' of https://github.com/alexberkowitz/flipperzero-firmware into dev 2022-09-26 11:43:31 -05:00
MX
a9210b2849 Merge branch 'fz-dev' into dev 2022-09-26 19:37:37 +03:00
derskythe
a58807c57a Add SubGhzTxRxWorker for later use 2022-09-26 20:14:33 +04:00
Sergey Gavrilov
5bb7cabea6 Applications loader: do not use view dispatcher queue #1788 2022-09-27 00:59:28 +09:00
phreakocious
f201062819 Add Hisense A/C IR signals.. (#1773)
* add Hisense A/C IR signals.. note that using any will toggle the power and apply the settings
* re-order the entries to be grouped by function

Co-authored-by: あく <alleteam@gmail.com>
2022-09-27 00:42:29 +09:00
Shane Synan
9f501034c3 Power: Also ask charger if charge done (#1378)
* power: Also ask charger if charge done
* F7: bump API Symbols version
* Lib: remove double include in bq25896.c

Co-authored-by: あく <alleteam@gmail.com>
2022-09-27 00:34:59 +09:00
derskythe
7bd0c8ff2c application.fam revert 2022-09-26 18:30:04 +04:00
derskythe
cdcf80ed05 speed-up linear to 07:10 2022-09-26 18:27:58 +04:00
Georgii Surkov
3e3a167764 [FL-2852] Update Universal Remote documentation (#1786)
* Update Universal Remote documentation
* Change formatting
2022-09-26 22:49:18 +09:00
MX
fa9602bd68 Merge branch 'fz-dev' into dev 2022-09-26 15:27:24 +03:00
hedger
efb09380bd [FL-2836] Fast flash programming mode (#1782)
* updater: lowered logging level for resources unpacking; hal: implemented fast flash write mode
* hal: reworked fast flash programming; clearing most error flags on flash init; changed some flash functions return type from bool to void; scripts: fixed malformed CRC values in update bundles in certain cases;
* hal: flash: larger critical section
* hal: flash: enabling fast write inside critical section
* api_symbols: bump minor version
2022-09-26 20:03:21 +09:00
MX
61fee8e269 some fixes, trying to speed up bruteforce(unsuccessful) 2022-09-26 06:24:47 +03:00
MX
5e30b14d90 update changelog 2022-09-26 02:12:11 +03:00
MX
c07e3a34dd Merge pull request #75 from derskythe/subbrute-deep-refactor
SubBrute deep refactor
2022-09-26 02:08:45 +03:00
MX
be7e11e60f Merge branch 'dev' into subbrute-deep-refactor 2022-09-26 02:06:50 +03:00
MX
e96e414561 Merge branch 'fz-dev' into dev 2022-09-26 02:06:09 +03:00
derskythe
0c99cb52ec free transmitter during subbrute_worker_init_manual_transmit 2022-09-26 02:45:09 +04:00
derskythe
ad9e1ce4df set furi_hal_subghz_set_path to FuriHalSubGhzPathIsolate on each manual iteration 2022-09-26 02:42:39 +04:00
derskythe
22dc5190d1 remove furi_hal_power_suppress_charge_enter/exit from other places 2022-09-26 02:39:17 +04:00
derskythe
f2fd97d9c5 fix memory leaks 2022-09-26 02:36:38 +04:00
derskythe
08084d5763 fix first send signal equals last transferred or 0x00 2022-09-26 02:03:36 +04:00
derskythe
add1ad6949 fix manual select key on max and min values 2022-09-26 01:48:51 +04:00
DerSkythe
87654e60b8 Merge remote-tracking branch 'origin/subbrute-deep-refactor' into subbrute-deep-refactor 2022-09-26 01:10:21 +04:00
DerSkythe
6f92cd645e fixed frame width to scroll 2022-09-26 01:09:00 +04:00
DerSkythe
23f6ea2e05 refactor worker moved it to SubBruteState 2022-09-26 01:07:16 +04:00
David Coles
a6b98ccbbe Preliminary Rust support (#1781)
* Add support for R_ARM_THM_MOVW_ABS_NC/THM_MOVT_ABS

These are sometimes emitted by the Rust LLVM compiler.

Ref: https://github.com/ARM-software/abi-aa/blob/main/aaelf32/aaelf32.rst#56relocation

* Discard LLVM bitcode from extension applications

LLVM-based compilers may include uncompressed bitcode in object files
to help with link-time optimization. However this can bloat binary sizes
from KB to MB.

* Expose alligned_malloc/free functions to applications

This is required to implement a global allocator in Rust.
2022-09-26 07:06:46 +10:00
DerSkythe
ba5f590dab switched to manual transmit 2022-09-26 00:07:14 +04:00
Der Skythe
f1048733d2 Merge branch 'Eng1n33r:dev' into subbrute-deep-refactor 2022-09-25 23:16:27 +04:00
DerSkythe
ea7f68fcab fixed load existing dump 2022-09-25 23:12:31 +04:00
MX
8013aacd94 oops 2022-09-25 21:03:32 +03:00
MX
be8f409098 update changelog 2022-09-25 21:01:12 +03:00
MX
97e6fe8f4e update universal remote assets
by @amec0e
2022-09-25 20:39:22 +03:00
DerSkythe
54757428e6 fix bug with return to main menu when choice file 2022-09-25 21:31:33 +04:00
MX
bd39d81324 Merge branch 'fz-dev' into dev 2022-09-25 19:55:35 +03:00
Chris van Marle
2a2078d9b5 Text input overwrite max size template (#1687) 2022-09-26 01:17:09 +09:00
MX
01ca588488 Merge branch 'fz-dev' into dev 2022-09-25 18:27:58 +03:00
Kowalski Dragon
f86eada292 Remove unused headers (#1751) 2022-09-25 23:39:06 +09:00
Skorpionm
bc777b2eff SubGhz: fix config menu (#1748)
* SubGhz: fix config menu
* SubGhz: fix gui Magellen protocol
* SubGhz: fix gui Transmit SubGhz
* SubGhz: keeloq, new gen manufacture code
* SubGhz: Update keeloq_mfcodes

Co-authored-by: あく <alleteam@gmail.com>
2022-09-25 23:34:52 +09:00
DerSkythe
6f91fa42f0 Added additional graphic decorations 2022-09-25 18:26:10 +04:00
Sergey Gavrilov
e6d22ed147 ELF-Loader: C++ plugin support, loader overhaul. (#1744)
* fap-loader: load all code and data sections
* fap-loader: relocate all code and data sections
* fap-loader: remove old elf loader
* fap-loader: new jmp call relocation
* openocd: resume on detach
* fap-loader: trampoline for big jumps
* fap-loader: rename cache
* fap-loader: init_array support
* fap-loader: untangled flipper_application into separate entities
* fap-loader: fix debug
* fap-loader: optimize section container
* fap-loader: optimize key for section container
* fap-loader: disable debug log
* documentation
* F7: bump api symbols version
* Lib: cleanup elf_file.c

Co-authored-by: あく <alleteam@gmail.com>
2022-09-25 23:11:29 +09:00
MX
436f70b69b Merge branch 'fz-dev' into dev 2022-09-25 16:46:23 +03:00
DerSkythe
ec9ce0cad7 Working prototype, but not yet tested on a real device 2022-09-25 17:05:52 +04:00
Jauder Ho
7e2008095e Bump protobuf from 3.20.1 to 3.20.2 in /scripts (#1774) 2022-09-25 20:56:53 +09:00
Sergey Gavrilov
92e440c77d Core: simplify record container (#1776)
Co-authored-by: あく <alleteam@gmail.com>
2022-09-25 20:48:57 +09:00
DerSkythe
666821e9ce SubBruteMainView is ready 2022-09-25 00:46:43 +04:00
MX
1bca477a43 update install instructions
thanks to @Svaarich !
2022-09-24 22:20:13 +03:00
MX
41571ce9ad SubGHz RAW - datetime in default names (+ format changed)
OFW PR 1772 by Skorpionm / printf text format changed by me
2022-09-24 22:15:06 +03:00
MX
038d098c85 Merge branch 'fz-dev' into dev 2022-09-24 21:56:17 +03:00
DerSkythe
b03cc8ddc3 trying to fix load failure 2022-09-24 22:30:08 +04:00
DerSkythe
c8e3d9b040 fix repeat call of view_dispatcher_alloc 2022-09-24 22:15:09 +04:00
DerSkythe
aeb02500de Deep refactor of SubBrute was made, but it doesn't start. Debug device needed 2022-09-24 21:47:21 +04:00
ghettorce
eadd7801af fbt: exclude user site-packages directory from sys.path (#1778)
* fbt: exclude user site-packages directory from sys.path
* fbt: python path fixes for *nix
* fbt: fixed cli target on Windows

Co-authored-by: hedger <hedger@users.noreply.github.com>
2022-09-24 15:30:19 +04:00
Yoanndp
6d2b0a3b6c Update ReadMe.md (#1766) 2022-09-24 19:36:11 +09:00
Alex Berkowitz
8093721c24 Change Sub-Ghz Remote line length max to 16 2022-09-23 20:37:02 -05:00
MX
32a7642761 remove duplicate function, update changelog 2022-09-22 21:51:47 +03:00
MX
e8bb45496d Merge branch 'fz-dev' into dev 2022-09-22 21:45:26 +03:00
Andrea Sacchi
3846852f2b NFC Fix Mifare Classic (#1769)
* Fix Mifare Classic key str to int conversion: Wrong cast lead to unexpected behavior converting key from str to int.
* Nfc: fix type cast in mf_classic_dict and add basic unit tests

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
2022-09-23 02:35:28 +09:00
Georgii Surkov
17d01f5c29 [FL-2848] Universal Remote fix (#1770)
* Reset BruteForce on exit from Universal Remote
* Reset current button in ButtonPanel
2022-09-23 01:13:00 +09:00
MX
e6bcba6959 update changelog, minor fixes 2022-09-22 18:23:32 +03:00
MX
e13edc2f70 keeeloq update 2022-09-22 18:01:54 +03:00
MX
de6ff1d9c9 update changelog 2022-09-21 23:07:39 +03:00
MX
bea15134ba fix mousejacker gui 2022-09-21 22:29:42 +03:00
MX
28a55bf576 Merge branch 'fz-dev' into dev 2022-09-21 22:02:02 +03:00
gornekich
e70121e20f [FL-2843] NFC fixes (#1764)
* nfc: fix empty desfire card message
* nfc: limit total user keys to list
* nfc: increase popup timeout

Co-authored-by: あく <alleteam@gmail.com>
2022-09-22 00:53:25 +09:00
hedger
432ff41d6a [FL-2844] desktop: removing slideshow file when leaving slideshow view (#1762)
* [FL-2844] desktop: removing slideshow file when leaving slideshow view; vscode: fix for BM port fetcher; fap api: more symbols for LL
* desktop: actually removing slideshow file
* desktop: moved slideshow removal to scene code; fbt: better blackmagic device handling
* fbt: disabled pagination for gdb
* vscode: restored blackmagic command line
* fbt: fixed debug_other target; added debug_other_blackmagic
* furi: added furi_thread_suspend API group; fixed null-pointer deref for thread name; cleaned up RTOS config
* furi: changed thread state check to eTaskGetState
2022-09-21 23:42:59 +09:00
MX
87393a086c fix rfid fuzzer crashes, some new random names 2022-09-21 08:43:07 +03:00
MX
6000d47a0f allow saving only for protocols without encoder 2022-09-21 07:12:09 +03:00
MX
d986ef4104 fix nice flor s crash, fix debug pack for debug builds 2022-09-21 06:52:34 +03:00
MX
f85dc1675d update changelog, rm unused var from clock 2022-09-21 01:00:56 +03:00
MX
7c7ac07e6a Merge pull request #74 from mvanzanten/adding-support-for-hidprox
adding support for HIDProx, updating the UI to switch between protocols
2022-09-20 23:25:45 +03:00
MX
ca02826cfd set time between cards to 6, run fbt format 2022-09-20 23:24:34 +03:00
MX
96ad7f3cef fix nfc list crash, fix magellen gui, fix transmitter gui 2022-09-20 23:13:15 +03:00
Matt Van Zanten
c213ff596a adding support for HIDProx, updating the UI to switch between protocols 2022-09-20 11:45:16 -07:00
MX
b2589698ff Merge branch 'fz-dev' into dev 2022-09-20 21:39:22 +03:00
Max Lapan
3360f818a1 Subghz: Adding checks for get_upload functions (#1704)
* Adding checks for get_upload functions
  Almost in every protocol, function which generates upload might fail and return false.
  But we don't check this result, which might end up sending random memory contents to the air.
* Format sources and fix crash on ivalid bit count in chamberlain

Co-authored-by: あく <alleteam@gmail.com>
2022-09-20 14:29:10 +09:00
Georgii Surkov
066da4080b [FL-2792] AC Universal Remote (#1725)
* Add Universal AC Remote scene
* Implement AC gui
* Basic working implemetation
* Another Universal AC Remote implementation
* Update icons
* Adjust button positions
* Revert old ButtonPanel class
* Update resource manifest
* [FL-2627] Flipper applications: SDK, build and debug system (#1387)
* Update api definitions
* Add UniversalRemotes documentation
* Use more Flipper-friendly signal names

Co-authored-by: SG <who.just.the.doctor@gmail.com>
2022-09-20 14:09:37 +09:00
MX
b2c118f267 fix null pointer dereference in archive -> Info
and fix long path display
2022-09-20 05:52:13 +03:00
MX
a8db46124e update docs & changelog 2022-09-20 04:09:14 +03:00
MX
672e27f258 fix icon name 2022-09-20 03:23:22 +03:00
MX
e762a68265 Merge pull request #72 from RogueMaster/ApplicationsFromArchive
Applications from archive
2022-09-20 03:20:25 +03:00
MX
8659becc9d fix tab name and add new icon
icon by @Svaarich
2022-09-20 03:19:31 +03:00
RogueMaster
82e1e8af6a Enable fap support on Archive app 2022-09-19 18:47:22 -04:00
RogueMaster
a71d05a114 Update archive_browser.h 2022-09-19 18:39:38 -04:00
MX
8d68bf62a5 update changelog 2022-09-19 23:34:31 +03:00
MX
2c85adb270 remove unused icon, update api symbols and unirf 2022-09-19 21:21:31 +03:00
MX
e2123c55bb Merge branch 'fz-dev' into dev 2022-09-19 21:15:04 +03:00
David
f5ff6438d1 NFC user dict list, delete, and de-duplication. (#1533)
* Add MFC user keys list
* Leakey submenu fix
* Set next target for Save/Delete success scenes
* Delete individual user keys
* Update count of total keys
* Fix memory leak
* Check for duplicate keys
* Remove a submodule that I never added?
* Swap and position icons
* Revamp according to design doc
* Rename icons to include size and replace keychain icon with smaller variant
* Fix typos
* Final fixes
* Fufill requested changes
* Cleanup comments
* Merge dev after SD app loading
* Fixing icon names
* Revert merge mistakes and API version
* Scene switching adjustments
* F7: add/change/remove some nfc icons in api_symbols.csv

Co-authored-by: あく <alleteam@gmail.com>
2022-09-20 01:43:53 +09:00
Astra
9f3b80e606 Add new card parsers (#1503)
* Add the "Two cities" parser
* Add plantain and plantain4k parsers
* Add new parsers to the supported list
* United card PoC
* Fix nfc device not sleeping
* Completely read the 4K troika variants
* Correct naming
* Update to reflect upstream changes
* Add support for MfUl info
* Fix parsers
* Card type detection fixes
* Remove debug info
* Fixes for the verification of cards
* nfc: fix verification for supported cards
* nfc: remove unused vars
* Improve card reading reliability and fix plantain
* plantain: change log level

Co-authored-by: gornekich <n.gorbadey@gmail.com>
2022-09-20 01:05:04 +09:00
MX
111656d2c1 Merge branch 'fz-dev' into dev 2022-09-19 18:50:20 +03:00
MX
2045a29d3f lower frame rate in custom anim to save a bit of battery charge 2022-09-19 18:40:50 +03:00
MX
26e46f9267 Merge pull request #71 from TasyDevilsky/patch-1
Update setting_user
2022-09-19 17:47:12 +03:00
Max Lapan
d003db0404 SubGhz: Oregon v2.1 decoder (#1678)
* Oregon v2.1 decoder
* Refactor FSM to switch
* Refactor headers
* Format strings
* Unit tests of oregon2
* Cleanups
* Add oregon2 raw data to random_test_raw.sub
* Adjust count of packets detected on random test
* Format sources

Co-authored-by: あく <alleteam@gmail.com>
2022-09-19 23:24:24 +09:00
MX
5a31e35dc2 Merge branch 'fz-dev' into dev 2022-09-19 17:21:31 +03:00
Patrick Cunningham
c7cd5721ed Picopass: detect and show SE / SIO (#1701)
* detect and show SE / SIO
* fix fault
* remove bad read check

Co-authored-by: あく <alleteam@gmail.com>
2022-09-19 22:37:12 +09:00
Nikolay Minaylov
fb476c29e6 RFID: fix read info screen (#1723)
* RFID: fix read info screen
* Fix line break for long data string
* Protocol data redecoding before write

Co-authored-by: SG <who.just.the.doctor@gmail.com>
Co-authored-by: あく <alleteam@gmail.com>
2022-09-19 22:21:40 +09:00
Nikolay Minaylov
d80329b323 [FL-2815, FL-2821] Dummy mode (#1739)
* Dummy mode implementation
* dumb -> dummy
* F7: Add new api_symbols: game icon
* Starting snake game from dummy mode

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
2022-09-19 22:03:42 +09:00
Astra
3d3c422751 [FL-2674] Show error popup when NFC chip is not init/disconnected (#1722)
* Show error popup when NFC chip is not init/disconnected
* Move to dialogs for the error message
* Fix a memory leak and wrap the hal check
* F7: update api_symbols.csv, add furi_hal_nfc_is_init

Co-authored-by: SG <who.just.the.doctor@gmail.com>
Co-authored-by: あく <alleteam@gmail.com>
2022-09-19 21:46:56 +09:00
hedger
ed385594a3 faploader: more subsystem headers in API table (#1742)
* faploader: more subsystem headers in API table; not counting header entries for SDK version change
* subghz: removed dead function
* Adjusted API version
* hal: removed furi_hal_power_get_system_voltage
* lib: mbedtls: additional flags for .fap linkage
* fbt: rebuilding assets when git commit id changes
* fbt: removed assets rebuild on git commit id change; added explicit dependency for SDK source on compiled assets parts; removed unneeded sdk regeneration runs
* fbt: changed stock plugins to EXTERNAL apps; restored building app as a PLUGIN as a part of main fw as well as a .fap; readme fixes
* fbt: restored certain apps to PLUGIN type
* fbt: app manifests: renamed version->fap_version, added extra fields
* fbt: fixed version processing after rename

Co-authored-by: あく <alleteam@gmail.com>
2022-09-19 21:39:00 +09:00
Astra
787df44c79 [FL-2800] Fix Mifare Classic 4K reading of the last 8 sectors (#1712)
* Fix FURI_BIT_SET

Co-authored-by: gornekich <n.gorbadey@gmail.com>
Co-authored-by: SG <who.just.the.doctor@gmail.com>
2022-09-19 21:30:18 +09:00
TasmanDevil
f0eedc3243 Update setting_user
Adding the 868.95 frequency for the Sommer device, the `Sommer(fsk476)` protocol was recently added but Flipper could not read it until now.
2022-09-19 08:59:13 +02:00
328 changed files with 11023 additions and 3383 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @xMasterX

View File

@@ -9,6 +9,10 @@
"type": "command",
"command": "shellCommand.execute",
"args": {
"useSingleResult": true,
"env": {
"PATH": "${workspaceFolder};${env:PATH}"
},
"command": "./fbt get_blackmagic",
"description": "Get Blackmagic device",
}
@@ -24,13 +28,14 @@
"servertype": "openocd",
"device": "stlink",
"svdFile": "./debug/STM32WB55_CM4.svd",
// If you're debugging early in the boot process, before OS scheduler is running,
// you have to comment out the following line.
"rtos": "FreeRTOS",
"configFiles": [
"interface/stlink.cfg",
"./debug/stm32wbx.cfg",
],
"postAttachCommands": [
// "attach 1",
// "compare-sections",
"source debug/flipperapps.py",
// "source debug/FreeRTOS/FreeRTOS.py",

View File

@@ -22,4 +22,4 @@
"SConstruct": "python",
"*.fam": "python",
}
}
}

View File

@@ -1,17 +1,22 @@
### New changes
* Spectrum Analyzer moved into Applications -> Tools
* Fixed bug with subghz remote (unirf) that was causing issues with power state
* Added 868.4 MHz into subghz user config
* Updated universal IR assets (by @Amec0e)
* Fixed debug builds - add this parameter to fbt command `FIRMWARE_APP_SET=debug_pack` if you building full fw in debug mode
* SubGHz: Now Hopping can't be used at same time with detect RAW feature, fixes issue with freeze
* SubGHz: Frequency Analyzer -> turn display on on all feedback modes
* PR: RFID Fuzzer - Allow the RFID protocol menu to wrap (by @colingrady | PR #84)
* PR: RFID Fuzzer - Improve UI for added on-the-fly feature (by @mvanzanten | PR #85)
* OFW PR: NFC update detect reader (OFW PR 1820 by gornekich)
* OFW PR: Remove bank card uid emulation & fix emv info (OFW PR 1823 by gornekich)
* OFW PR: Don't turn off the backlight on MFC dict attack (OFW PR 1826 by Astrrra)
* OFW PR: Infrared error message (OFW PR 1827 by gsurkov)
#### **DFU files no longer included in releases to avoid issues with wrong manual installation of assets - use web updater or microSD update package**
#### [🎲 Download extra apps pack](https://download-directory.github.io/?url=https://github.com/UberGuidoZ/Flipper/tree/main/Applications/Unleashed)
[- How to install](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/HowToInstall.md)
[-> How to install firmware](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/HowToInstall.md)
**Note: To avoid issues prefer installing using web updater or by self update package, all needed assets will be installed**
[-> Download qFlipper 1.2.0 (allows .tgz installation) (official link)](https://update.flipperzero.one/builds/qFlipper/1.2.0/)
Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or `.tgz` for iOS mobile app
**Note: To avoid issues with .dfu, prefer installing using .tgz with qFlipper, web updater or by self update package, all needed assets will be installed**
DFU for update using qFlipper is no longer included in releases to avoid issues with assets - Use Web Updater or self-update package!
Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or download `.tgz` for iOS mobile app / qFlipper
Update using qFlipper (1.2.0) is now possible with `.tgz` update package! Also you can use Web Updater or self-update package.

View File

@@ -36,9 +36,12 @@ Our Discord Community:
* Universal remote for Projectors, Fans, A/Cs and Audio(soundbars, etc.)
* BadUSB keyboard layouts
* Customizable Flipper name
* SubGHz -> Press OK in frequency analyzer to use detected frequency in Read modes
* SubGHz -> Long press OK button in SubGHz Frequency analyzer to switch to Read menu
* Other small fixes and changes throughout
* See other changes in changelog and in readme below
See changelog in releases for latest updates!
Also check changelog in releases for latest updates!
### Current modified and new SubGHz protocols list:
- HCS101
@@ -49,7 +52,7 @@ See changelog in releases for latest updates!
- Keeloq [Not ALL systems supported yet!]
- Nice Flor S
- Security+ v1 & v2
- Star Line
- Star Line (saving only)
## Support us so we can buy equipment and develop new features
* ETH/BSC/ERC20-Tokens: `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`
@@ -59,8 +62,8 @@ See changelog in releases for latest updates!
### Community apps included:
- RFID Fuzzer plugin [(by Ganapati)](https://github.com/Eng1n33r/flipperzero-firmware/pull/54) with some changes by xMasterX
- Sub-GHz bruteforce plugin [(by Ganapati & xMasterX)](https://github.com/Eng1n33r/flipperzero-firmware/pull/57)
- RFID Fuzzer plugin [(by Ganapati)](https://github.com/Eng1n33r/flipperzero-firmware/pull/54) with changes by @xMasterX & New protocols by @mvanzanten
- Sub-GHz bruteforce plugin [(by Ganapati & xMasterX)](https://github.com/Eng1n33r/flipperzero-firmware/pull/57) & Refactored by @derskythe
- Sub-GHz playlist plugin [(by darmiel)](https://github.com/Eng1n33r/flipperzero-firmware/pull/62)
- ESP8266 Deauther plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module)
- WiFi Scanner plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module)
@@ -85,9 +88,11 @@ Games:
### Other changes
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
- SubGHz -> New frequency analyzer - [(by ClusterM)](https://github.com/ClusterM)
- SubGHz -> New frequency analyzer - [(by ClusterM)](https://github.com/Eng1n33r/flipperzero-firmware/pull/43)
- SubGHz -> Detect RAW feature - [(by perspecdev)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/152)
- SubGHz -> Save last used config settings - [(by derskythe)](https://github.com/Eng1n33r/flipperzero-firmware/pull/67)
- SubGHz -> Save last used frequency and moduluation [(by derskythe)](https://github.com/Eng1n33r/flipperzero-firmware/pull/77)
- SubGHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/Eng1n33r/flipperzero-firmware/pull/77)
* SubGHz -> Long press OK button in SubGHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/Eng1n33r/flipperzero-firmware/pull/79)
# Instructions
## [- How to install firmware](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/HowToInstall.md)
@@ -100,7 +105,7 @@ Games:
### **Plugins**
## [- 💎 Extra plugins precompiled for Unleashed](https://github.com/UberGuidoZ/Flipper/tree/main/Applications/Unleashed)
## [- 🎲 Download Extra plugins for Unleashed](https://github.com/UberGuidoZ/Flipper/tree/main/Applications/Unleashed)
## [- Configure Sub-GHz Remote App](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
@@ -140,9 +145,10 @@ Games:
<br>
# Where I can find IR, SubGhz, ... files, DBs, and other stuff?
## [Awesome Flipper Zero - Github](https://github.com/djsime1/awesome-flipperzero)
## [UberGuidoZ Playground - Large collection of files - Github](https://github.com/UberGuidoZ/Flipper)
## [Awesome Flipper Zero - Github](https://github.com/djsime1/awesome-flipperzero)
## [CAME-12bit, NICE-12bit, Linear-10bit, PT-2240 - SubGHz fixed code bruteforce](https://github.com/tobiabocchi/flipperzero-bruteforce)
## [SMC5326, UNILARM - SubGHz fixed code bruteforce](https://github.com/Hong5489/flipperzero-gate-bruteforce)
<br>
<br>
@@ -167,4 +173,4 @@ Games:
- `site_scons` - Build helpers
- `scripts` - Supplementary scripts and python libraries home
Also pay attention to `ReadMe.md` files inside of those directories.
Also pay attention to `ReadMe.md` files inside those directories.

View File

@@ -44,6 +44,8 @@ distenv = coreenv.Clone(
"target extended-remote ${GDBREMOTE}",
"-ex",
"set confirm off",
"-ex",
"set pagination off",
],
GDBOPTS_BLACKMAGIC=[
"-ex",
@@ -234,10 +236,19 @@ distenv.PhonyTarget(
distenv.PhonyTarget(
"debug_other",
"${GDBPYCOM}",
GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ',
GDBOPTS="${GDBOPTS_BASE}",
GDBREMOTE="${OPENOCD_GDB_PIPE}",
GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ',
)
distenv.PhonyTarget(
"debug_other_blackmagic",
"${GDBPYCOM}",
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
GDBREMOTE="$${BLACKMAGIC_ADDR}",
)
# Just start OpenOCD
distenv.PhonyTarget(
"openocd",

View File

@@ -7,8 +7,8 @@ App(
"vibro_test",
"keypad_test",
"usb_test",
"usb_mouse",
"uart_echo",
"USB_Mouse",
"UART_Echo",
"display_test",
"text_box_test",
"file_browser_test",

View File

@@ -1,5 +1,5 @@
App(
appid="uart_echo",
appid="UART_Echo",
name="UART Echo",
apptype=FlipperAppType.PLUGIN,
entry_point="uart_echo_app",

View File

@@ -57,6 +57,23 @@ static const char* test_data_win = "Filetype: Flipper File test\r\n"
"Hex data: DE AD BE";
#define READ_TEST_FLP "ff_flp.test"
#define READ_TEST_ODD "ff_oddities.test"
static const char* test_data_odd = "Filetype: Flipper File test\n"
// Tabs before newline
"Version: 666\t\t\n"
"# This is comment\n"
// Windows newline in a UNIX file
"String data: String\r\n"
// Trailing whitespace
"Int32 data: 1234 -6345 7813 0 \n"
// Extra whitespace
"Uint32 data: 1234 0 5678 9098 7654321 \n"
// Mixed whitespace
"Float data: 1.5\t \t1000.0\n"
// Leading tabs after key
"Bool data:\t\ttrue false\n"
// Mixed trailing whitespace
"Hex data: DE AD BE\t ";
// data created by user on linux machine
static const char* test_file_linux = TEST_DIR READ_TEST_NIX;
@@ -64,6 +81,8 @@ static const char* test_file_linux = TEST_DIR READ_TEST_NIX;
static const char* test_file_windows = TEST_DIR READ_TEST_WIN;
// data created by flipper itself
static const char* test_file_flipper = TEST_DIR READ_TEST_FLP;
// data containing odd user input
static const char* test_file_oddities = TEST_DIR READ_TEST_ODD;
static bool storage_write_string(const char* path, const char* data) {
Storage* storage = furi_record_open(RECORD_STORAGE);
@@ -503,6 +522,12 @@ MU_TEST(flipper_format_multikey_test) {
mu_assert(test_read_multikey(TEST_DIR "ff_multiline.test"), "Multikey read test error");
}
MU_TEST(flipper_format_oddities_test) {
mu_assert(
storage_write_string(test_file_oddities, test_data_odd), "Write test error [Oddities]");
mu_assert(test_read(test_file_linux), "Read test error [Oddities]");
}
MU_TEST_SUITE(flipper_format) {
tests_setup();
MU_RUN_TEST(flipper_format_write_test);
@@ -516,6 +541,7 @@ MU_TEST_SUITE(flipper_format) {
MU_RUN_TEST(flipper_format_update_2_test);
MU_RUN_TEST(flipper_format_update_2_result_test);
MU_RUN_TEST(flipper_format_multikey_test);
MU_RUN_TEST(flipper_format_oddities_test);
tests_teardown();
}

View File

@@ -3,6 +3,7 @@
#include <storage/storage.h>
#include <lib/flipper_format/flipper_format.h>
#include <lib/nfc/protocols/nfca.h>
#include <lib/nfc/helpers/mf_classic_dict.h>
#include <lib/digital_signal/digital_signal.h>
#include <lib/flipper_format/flipper_format_i.h>
@@ -170,10 +171,59 @@ MU_TEST(nfc_digital_signal_test) {
"NFC long digital signal test failed\r\n");
}
MU_TEST(mf_classic_dict_test) {
MfClassicDict* instance = NULL;
uint64_t key = 0;
string_t temp_str;
string_init(temp_str);
instance = mf_classic_dict_alloc(MfClassicDictTypeUnitTest);
mu_assert(instance != NULL, "mf_classic_dict_alloc\r\n");
mu_assert(
mf_classic_dict_get_total_keys(instance) == 0,
"mf_classic_dict_get_total_keys == 0 assert failed\r\n");
string_set(temp_str, "2196FAD8115B");
mu_assert(
mf_classic_dict_add_key_str(instance, temp_str),
"mf_classic_dict_add_key == true assert failed\r\n");
mu_assert(
mf_classic_dict_get_total_keys(instance) == 1,
"mf_classic_dict_get_total_keys == 1 assert failed\r\n");
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
mu_assert(
mf_classic_dict_get_key_at_index_str(instance, temp_str, 0),
"mf_classic_dict_get_key_at_index_str == true assert failed\r\n");
mu_assert(
string_cmp(temp_str, "2196FAD8115B") == 0,
"string_cmp(temp_str, \"2196FAD8115B\") == 0 assert failed\r\n");
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
mu_assert(
mf_classic_dict_get_key_at_index(instance, &key, 0),
"mf_classic_dict_get_key_at_index == true assert failed\r\n");
mu_assert(key == 0x2196FAD8115B, "key == 0x2196FAD8115B assert failed\r\n");
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
mu_assert(
mf_classic_dict_delete_index(instance, 0),
"mf_classic_dict_delete_index == true assert failed\r\n");
mf_classic_dict_free(instance);
string_clear(temp_str);
}
MU_TEST_SUITE(nfc) {
nfc_test_alloc();
MU_RUN_TEST(nfc_digital_signal_test);
MU_RUN_TEST(mf_classic_dict_test);
nfc_test_free();
}

View File

@@ -58,7 +58,7 @@ MU_TEST(storage_file_open_lock) {
storage_file_close(file);
// file_locker thread stop
mu_check(furi_thread_join(locker_thread) == FuriStatusOk);
mu_check(furi_thread_join(locker_thread));
furi_thread_free(locker_thread);
// clean data
@@ -148,7 +148,7 @@ MU_TEST(storage_dir_open_lock) {
storage_dir_close(file);
// file_locker thread stop
mu_check(furi_thread_join(locker_thread) == FuriStatusOk);
mu_check(furi_thread_join(locker_thread));
furi_thread_free(locker_thread);
// clean data

View File

@@ -13,7 +13,7 @@
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
#define TEST_RANDOM_COUNT_PARSE 232
#define TEST_RANDOM_COUNT_PARSE 233
#define TEST_TIMEOUT 10000
static SubGhzEnvironment* environment_handler;
@@ -434,6 +434,13 @@ MU_TEST(subghz_decoder_clemsa_test) {
"Test decoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n");
}
MU_TEST(subghz_decoder_oregon2_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/oregon2_raw.sub"), SUBGHZ_PROTOCOL_OREGON2_NAME),
"Test decoder " SUBGHZ_PROTOCOL_OREGON2_NAME " error\r\n");
}
//test encoders
MU_TEST(subghz_encoder_princeton_test) {
mu_assert(
@@ -595,6 +602,7 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_decoder_magellen_test);
MU_RUN_TEST(subghz_decoder_intertechno_v3_test);
MU_RUN_TEST(subghz_decoder_clemsa_test);
MU_RUN_TEST(subghz_decoder_oregon2_test);
MU_RUN_TEST(subghz_encoder_princeton_test);
MU_RUN_TEST(subghz_encoder_came_test);

View File

@@ -1,5 +1,5 @@
App(
appid="usb_mouse",
appid="USB_Mouse",
name="USB Mouse",
apptype=FlipperAppType.PLUGIN,
entry_point="usb_mouse_app",

View File

@@ -24,13 +24,13 @@ App(
apptype=FlipperAppType.METAPACKAGE,
provides=[
"gpio",
"ibutton",
#"ibutton",
"infrared",
"lfrfid",
"nfc",
"subghz",
"bad_usb",
"u2f",
#"bad_usb",
#"u2f",
"fap_loader",
"archive",
],

View File

@@ -16,6 +16,7 @@ static const char* tab_default_paths[] = {
[ArchiveTabInfrared] = ANY_PATH("infrared"),
[ArchiveTabBadUsb] = ANY_PATH("badusb"),
[ArchiveTabU2f] = "/app:u2f",
[ArchiveTabApps] = ANY_PATH("apps"),
[ArchiveTabBrowser] = STORAGE_ANY_PATH_PREFIX,
};
@@ -27,6 +28,7 @@ static const char* known_ext[] = {
[ArchiveFileTypeInfrared] = ".ir",
[ArchiveFileTypeBadUsb] = ".txt",
[ArchiveFileTypeU2f] = "?",
[ArchiveFileTypeApps] = ".fap",
[ArchiveFileTypeUpdateManifest] = ".fuf",
[ArchiveFileTypeFolder] = "?",
[ArchiveFileTypeUnknown] = "*",
@@ -41,6 +43,7 @@ static const ArchiveFileTypeEnum known_type[] = {
[ArchiveTabInfrared] = ArchiveFileTypeInfrared,
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
[ArchiveTabU2f] = ArchiveFileTypeU2f,
[ArchiveTabApps] = ArchiveFileTypeApps,
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
};

View File

@@ -13,6 +13,7 @@ typedef enum {
ArchiveFileTypeInfrared,
ArchiveFileTypeBadUsb,
ArchiveFileTypeU2f,
ArchiveFileTypeApps,
ArchiveFileTypeUpdateManifest,
ArchiveFileTypeFolder,
ArchiveFileTypeUnknown,

View File

@@ -42,10 +42,7 @@ ARRAY_DEF(
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
// Using in applications/archive/views/archive_browser_view.c
static void archive_menu_add_item(
ArchiveContextMenuItem_t* obj,
string_t text,
uint32_t event) {
static void archive_menu_add_item(ArchiveContextMenuItem_t* obj, string_t text, uint32_t event) {
string_init_move(obj->text, text);
obj->event = event;
}

View File

@@ -19,6 +19,7 @@ static const char* flipper_app_name[] = {
[ArchiveFileTypeInfrared] = "Infrared",
[ArchiveFileTypeBadUsb] = "Bad USB",
[ArchiveFileTypeU2f] = "U2F",
[ArchiveFileTypeApps] = "Applications",
[ArchiveFileTypeUpdateManifest] = "UpdaterApp",
};
@@ -132,7 +133,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
case ArchiveBrowserEventFileMenuRename:
if(favorites) {
browser->callback(ArchiveBrowserEventEnterFavMove, browser->context);
//} else if((archive_is_known_app(selected->type)) && (selected->is_app == false)) {
//} else if((archive_is_known_app(selected->type)) && (selected->is_app == false)) {
} else {
// Added ability to rename files and folders
archive_show_file_menu(browser, false);

View File

@@ -37,7 +37,11 @@ void archive_scene_info_on_enter(void* context) {
// Directory path
path_extract_dirname(string_get_cstr(current->path), dirname);
string_replace_str(dirname, STORAGE_ANY_PATH_PREFIX, "");
if(strcmp(string_get_cstr(dirname), "/any") == 0) {
string_replace_str(dirname, STORAGE_ANY_PATH_PREFIX, "/");
} else {
string_replace_str(dirname, STORAGE_ANY_PATH_PREFIX, "");
}
// File size
FileInfo fileinfo;
@@ -60,7 +64,7 @@ void archive_scene_info_on_enter(void* context) {
string_get_cstr(dirname));
}
widget_add_text_box_element(
instance->widget, 0, 25, 128, 25, AlignLeft, AlignCenter, file_info_message, false);
instance->widget, 0, 25, 128, 25, AlignLeft, AlignCenter, file_info_message, true);
// This one to return and cursor select this file
path_extract_filename_no_ext(string_get_cstr(current->path), filename);

View File

@@ -16,6 +16,7 @@ static const char* ArchiveTabNames[] = {
[ArchiveTabInfrared] = "Infrared",
[ArchiveTabBadUsb] = "Bad USB",
[ArchiveTabU2f] = "U2F",
[ArchiveTabApps] = "Apps",
[ArchiveTabBrowser] = "Browser",
};
@@ -27,6 +28,7 @@ static const Icon* ArchiveItemIcons[] = {
[ArchiveFileTypeInfrared] = &I_ir_10px,
[ArchiveFileTypeBadUsb] = &I_badusb_10px,
[ArchiveFileTypeU2f] = &I_u2f_10px,
[ArchiveFileTypeApps] = &I_Apps_10px,
[ArchiveFileTypeUpdateManifest] = &I_update_10px,
[ArchiveFileTypeFolder] = &I_dir_10px,
[ArchiveFileTypeUnknown] = &I_unknown_10px,

View File

@@ -27,6 +27,7 @@ typedef enum {
ArchiveTabIButton,
ArchiveTabBadUsb,
ArchiveTabU2f,
ArchiveTabApps,
ArchiveTabBrowser,
ArchiveTabTotal,
} ArchiveTabEnum;

View File

@@ -8,6 +8,7 @@ static bool bad_usb_file_select(BadUsbApp* bad_usb) {
DialogsFileBrowserOptions browser_options;
dialog_file_browser_set_basic_options(
&browser_options, BAD_USB_APP_SCRIPT_EXTENSION, &I_badusb_10px);
browser_options.skip_assets = true;
// Input events and views are managed by file_browser
bool res = dialog_file_browser_show(

View File

@@ -38,6 +38,7 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
time_string, TIME_LEN, CLOCK_TIME_FORMAT, curr_dt.hour, curr_dt.minute, curr_dt.second);
} else {
bool pm = curr_dt.hour > 12;
bool pm12 = curr_dt.hour >= 12;
snprintf(
time_string,
TIME_LEN,
@@ -50,7 +51,7 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
meridian_string,
MERIDIAN_LEN,
MERIDIAN_FORMAT,
pm ? MERIDIAN_STRING_PM : MERIDIAN_STRING_AM);
pm12 ? MERIDIAN_STRING_PM : MERIDIAN_STRING_AM);
}
if(state->settings.date_format == Iso) {

View File

@@ -33,5 +33,4 @@ typedef enum {
typedef struct {
TimeFormat time_format;
DateFormat date_format;
uint8_t increment_precision;
} ClockSettings;

View File

@@ -15,6 +15,9 @@ typedef struct {
DialogsApp* dialogs;
Gui* gui;
string_t fap_path;
ViewDispatcher* view_dispatcher;
Loading* loading;
} FapLoader;
static bool
@@ -25,7 +28,7 @@ static bool
FlipperApplication* app = flipper_application_alloc(loader->storage, &hashtable_api_interface);
FlipperApplicationPreloadStatus preload_res =
flipper_application_preload(app, string_get_cstr(path));
flipper_application_preload_manifest(app, string_get_cstr(path));
bool load_success = false;
@@ -144,12 +147,12 @@ int32_t fap_loader_app(void* p) {
loader->dialogs = furi_record_open(RECORD_DIALOGS);
loader->gui = furi_record_open(RECORD_GUI);
ViewDispatcher* view_dispatcher = view_dispatcher_alloc();
Loading* loading = loading_alloc();
loader->view_dispatcher = view_dispatcher_alloc();
loader->loading = loading_alloc();
view_dispatcher_enable_queue(view_dispatcher);
view_dispatcher_attach_to_gui(view_dispatcher, loader->gui, ViewDispatcherTypeFullscreen);
view_dispatcher_add_view(view_dispatcher, 0, loading_get_view(loading));
view_dispatcher_attach_to_gui(
loader->view_dispatcher, loader->gui, ViewDispatcherTypeFullscreen);
view_dispatcher_add_view(loader->view_dispatcher, 0, loading_get_view(loader->loading));
if(p) {
string_init_set(loader->fap_path, (const char*)p);
@@ -158,14 +161,14 @@ int32_t fap_loader_app(void* p) {
string_init_set(loader->fap_path, EXT_PATH("apps"));
while(fap_loader_select_app(loader)) {
view_dispatcher_switch_to_view(view_dispatcher, 0);
view_dispatcher_switch_to_view(loader->view_dispatcher, 0);
fap_loader_run_selected_app(loader);
};
}
view_dispatcher_remove_view(view_dispatcher, 0);
loading_free(loading);
view_dispatcher_free(view_dispatcher);
view_dispatcher_remove_view(loader->view_dispatcher, 0);
loading_free(loader->loading);
view_dispatcher_free(loader->view_dispatcher);
string_clear(loader->fap_path);
furi_record_close(RECORD_GUI);

View File

@@ -23,7 +23,7 @@ void ibutton_scene_delete_confirm_on_enter(void* context) {
ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", string_get_cstr(key_name));
widget_add_text_box_element(
widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, false);
widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, true);
widget_add_button_element(
widget, GuiButtonTypeLeft, "Cancel", ibutton_scene_delete_confirm_widget_callback, ibutton);
widget_add_button_element(
@@ -47,24 +47,24 @@ void ibutton_scene_delete_confirm_on_enter(void* context) {
key_data[6],
key_data[7]);
widget_add_string_element(
widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas");
widget, 64, 34, AlignCenter, AlignBottom, FontSecondary, "Dallas");
break;
case iButtonKeyCyfral:
ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]);
widget_add_string_element(
widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral");
widget, 64, 34, AlignCenter, AlignBottom, FontSecondary, "Cyfral");
break;
case iButtonKeyMetakom:
ibutton_text_store_set(
ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]);
widget_add_string_element(
widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Metakom");
widget, 64, 34, AlignCenter, AlignBottom, FontSecondary, "Metakom");
break;
}
widget_add_string_element(
widget, 64, 33, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store);
widget, 64, 46, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);

View File

@@ -15,7 +15,7 @@ static void ibutton_scene_emulate_callback(void* context, bool emulated) {
void ibutton_scene_emulate_on_enter(void* context) {
iButton* ibutton = context;
Popup* popup = ibutton->popup;
Widget* widget = ibutton->widget;
iButtonKey* key = ibutton->key;
const uint8_t* key_data = ibutton_key_get_data_p(key);
@@ -26,20 +26,18 @@ void ibutton_scene_emulate_on_enter(void* context) {
path_extract_filename(ibutton->file_path, key_name, true);
}
uint8_t line_count = 2;
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
// check that stored key has name
if(!string_empty_p(key_name)) {
ibutton_text_store_set(ibutton, "emulating\n%s", string_get_cstr(key_name));
line_count = 2;
ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name));
} else {
// if not, show key data
switch(ibutton_key_get_type(key)) {
case iButtonKeyDS1990:
ibutton_text_store_set(
ibutton,
"emulating\n%02X %02X %02X %02X\n%02X %02X %02X %02X",
"%02X %02X %02X %02X\n%02X %02X %02X %02X",
key_data[0],
key_data[1],
key_data[2],
@@ -48,40 +46,24 @@ void ibutton_scene_emulate_on_enter(void* context) {
key_data[5],
key_data[6],
key_data[7]);
line_count = 3;
break;
case iButtonKeyCyfral:
ibutton_text_store_set(ibutton, "emulating\n%02X %02X", key_data[0], key_data[1]);
line_count = 2;
ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]);
break;
case iButtonKeyMetakom:
ibutton_text_store_set(
ibutton,
"emulating\n%02X %02X %02X %02X",
key_data[0],
key_data[1],
key_data[2],
key_data[3]);
line_count = 2;
ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]);
break;
}
}
switch(line_count) {
case 3:
popup_set_header(popup, "iButton", 82, 18, AlignCenter, AlignBottom);
popup_set_text(popup, ibutton->text_store, 82, 22, AlignCenter, AlignTop);
break;
widget_add_string_multiline_element(
widget, 90, 10, AlignCenter, AlignTop, FontPrimary, "iButton\nemulating");
widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44);
widget_add_text_box_element(
widget, 54, 39, 75, 22, AlignCenter, AlignCenter, ibutton->text_store, true);
default:
popup_set_header(popup, "iButton", 82, 24, AlignCenter, AlignBottom);
popup_set_text(popup, ibutton->text_store, 82, 28, AlignCenter, AlignTop);
break;
}
popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
ibutton_worker_emulate_set_callback(
ibutton->key_worker, ibutton_scene_emulate_callback, ibutton);
@@ -122,10 +104,7 @@ bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) {
void ibutton_scene_emulate_on_exit(void* context) {
iButton* ibutton = context;
Popup* popup = ibutton->popup;
ibutton_worker_stop(ibutton->key_worker);
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
widget_reset(ibutton->widget);
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
}

View File

@@ -14,7 +14,7 @@ void ibutton_scene_info_on_enter(void* context) {
ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name));
widget_add_text_box_element(
widget, 0, 0, 128, 28, AlignCenter, AlignCenter, ibutton->text_store, false);
widget, 0, 0, 128, 23, AlignCenter, AlignCenter, ibutton->text_store, true);
switch(ibutton_key_get_type(key)) {
case iButtonKeyDS1990:
@@ -29,26 +29,24 @@ void ibutton_scene_info_on_enter(void* context) {
key_data[5],
key_data[6],
key_data[7]);
widget_add_string_element(
widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Dallas");
widget_add_string_element(widget, 64, 36, AlignCenter, AlignBottom, FontPrimary, "Dallas");
break;
case iButtonKeyMetakom:
ibutton_text_store_set(
ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]);
widget_add_string_element(
widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Metakom");
widget, 64, 36, AlignCenter, AlignBottom, FontPrimary, "Metakom");
break;
case iButtonKeyCyfral:
ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]);
widget_add_string_element(
widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Cyfral");
widget_add_string_element(widget, 64, 36, AlignCenter, AlignBottom, FontPrimary, "Cyfral");
break;
}
widget_add_string_element(
widget, 64, 35, AlignCenter, AlignBottom, FontPrimary, ibutton->text_store);
widget, 64, 50, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);

View File

@@ -29,10 +29,8 @@ bool ibutton_scene_save_success_on_event(void* context, SceneManagerEvent event)
if(event.type == SceneManagerEventTypeCustom) {
consumed = true;
if(event.event == iButtonCustomEventBack) {
const uint32_t possible_scenes[] = {
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};
scene_manager_search_and_switch_to_previous_scene_one_of(
ibutton->scene_manager, possible_scenes, COUNT_OF(possible_scenes));
scene_manager_search_and_switch_to_another_scene(
ibutton->scene_manager, iButtonSceneSelectKey);
}
}

View File

@@ -14,8 +14,8 @@ static void ibutton_scene_write_callback(void* context, iButtonWorkerWriteResult
void ibutton_scene_write_on_enter(void* context) {
iButton* ibutton = context;
Popup* popup = ibutton->popup;
iButtonKey* key = ibutton->key;
Widget* widget = ibutton->widget;
iButtonWorker* worker = ibutton->key_worker;
const uint8_t* key_data = ibutton_key_get_data_p(key);
@@ -26,19 +26,16 @@ void ibutton_scene_write_on_enter(void* context) {
path_extract_filename(ibutton->file_path, key_name, true);
}
uint8_t line_count = 2;
// check that stored key has name
if(!string_empty_p(key_name)) {
ibutton_text_store_set(ibutton, "writing\n%s", string_get_cstr(key_name));
line_count = 2;
ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name));
} else {
// if not, show key data
switch(ibutton_key_get_type(key)) {
case iButtonKeyDS1990:
ibutton_text_store_set(
ibutton,
"writing\n%02X %02X %02X %02X\n%02X %02X %02X %02X",
"%02X %02X %02X %02X\n%02X %02X %02X %02X",
key_data[0],
key_data[1],
key_data[2],
@@ -47,40 +44,24 @@ void ibutton_scene_write_on_enter(void* context) {
key_data[5],
key_data[6],
key_data[7]);
line_count = 3;
break;
case iButtonKeyCyfral:
ibutton_text_store_set(ibutton, "writing\n%02X %02X", key_data[0], key_data[1]);
line_count = 2;
ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]);
break;
case iButtonKeyMetakom:
ibutton_text_store_set(
ibutton,
"writing\n%02X %02X %02X %02X",
key_data[0],
key_data[1],
key_data[2],
key_data[3]);
line_count = 2;
ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]);
break;
}
}
switch(line_count) {
case 3:
popup_set_header(popup, "iButton", 82, 18, AlignCenter, AlignBottom);
popup_set_text(popup, ibutton->text_store, 82, 22, AlignCenter, AlignTop);
break;
widget_add_string_multiline_element(
widget, 90, 10, AlignCenter, AlignTop, FontPrimary, "iButton\nwriting");
widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44);
widget_add_text_box_element(
widget, 54, 39, 75, 22, AlignCenter, AlignCenter, ibutton->text_store, true);
default:
popup_set_header(popup, "iButton", 82, 24, AlignCenter, AlignBottom);
popup_set_text(popup, ibutton->text_store, 82, 28, AlignCenter, AlignTop);
break;
}
popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton);
ibutton_worker_write_start(worker, key);
@@ -114,11 +95,8 @@ bool ibutton_scene_write_on_event(void* context, SceneManagerEvent event) {
void ibutton_scene_write_on_exit(void* context) {
iButton* ibutton = context;
Popup* popup = ibutton->popup;
ibutton_worker_stop(ibutton->key_worker);
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
widget_reset(ibutton->widget);
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
}

View File

@@ -23,34 +23,41 @@ struct InfraredBruteForce {
FlipperFormat* ff;
const char* db_filename;
string_t current_record_name;
InfraredSignal* current_signal;
InfraredBruteForceRecordDict_t records;
bool is_started;
};
InfraredBruteForce* infrared_brute_force_alloc() {
InfraredBruteForce* brute_force = malloc(sizeof(InfraredBruteForce));
brute_force->ff = NULL;
brute_force->db_filename = NULL;
brute_force->current_signal = NULL;
brute_force->is_started = false;
string_init(brute_force->current_record_name);
InfraredBruteForceRecordDict_init(brute_force->records);
return brute_force;
}
void infrared_brute_force_clear_records(InfraredBruteForce* brute_force) {
furi_assert(!brute_force->is_started);
InfraredBruteForceRecordDict_reset(brute_force->records);
}
void infrared_brute_force_free(InfraredBruteForce* brute_force) {
furi_assert(!brute_force->ff);
furi_assert(!brute_force->is_started);
InfraredBruteForceRecordDict_clear(brute_force->records);
string_clear(brute_force->current_record_name);
free(brute_force);
}
void infrared_brute_force_set_db_filename(InfraredBruteForce* brute_force, const char* db_filename) {
furi_assert(!brute_force->is_started);
brute_force->db_filename = db_filename;
}
bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
furi_assert(!brute_force->is_started);
furi_assert(brute_force->db_filename);
bool success = false;
@@ -80,6 +87,7 @@ bool infrared_brute_force_start(
InfraredBruteForce* brute_force,
uint32_t index,
uint32_t* record_count) {
furi_assert(!brute_force->is_started);
bool success = false;
*record_count = 0;
@@ -100,50 +108,37 @@ bool infrared_brute_force_start(
if(*record_count) {
Storage* storage = furi_record_open(RECORD_STORAGE);
brute_force->ff = flipper_format_buffered_file_alloc(storage);
brute_force->current_signal = infrared_signal_alloc();
brute_force->is_started = true;
success =
flipper_format_buffered_file_open_existing(brute_force->ff, brute_force->db_filename);
if(!success) {
flipper_format_free(brute_force->ff);
brute_force->ff = NULL;
furi_record_close(RECORD_STORAGE);
}
if(!success) infrared_brute_force_stop(brute_force);
}
return success;
}
bool infrared_brute_force_is_started(InfraredBruteForce* brute_force) {
return brute_force->ff;
return brute_force->is_started;
}
void infrared_brute_force_stop(InfraredBruteForce* brute_force) {
furi_assert(string_size(brute_force->current_record_name));
furi_assert(brute_force->ff);
furi_assert(brute_force->is_started);
string_reset(brute_force->current_record_name);
infrared_signal_free(brute_force->current_signal);
flipper_format_free(brute_force->ff);
furi_record_close(RECORD_STORAGE);
brute_force->current_signal = NULL;
brute_force->ff = NULL;
brute_force->is_started = false;
furi_record_close(RECORD_STORAGE);
}
bool infrared_brute_force_send_next(InfraredBruteForce* brute_force) {
furi_assert(string_size(brute_force->current_record_name));
furi_assert(brute_force->ff);
bool success = false;
string_t signal_name;
string_init(signal_name);
InfraredSignal* signal = infrared_signal_alloc();
do {
success = infrared_signal_read(signal, brute_force->ff, signal_name);
} while(success && !string_equal_p(brute_force->current_record_name, signal_name));
furi_assert(brute_force->is_started);
const bool success = infrared_signal_search_and_read(
brute_force->current_signal, brute_force->ff, brute_force->current_record_name);
if(success) {
infrared_signal_transmit(signal);
infrared_signal_transmit(brute_force->current_signal);
}
infrared_signal_free(signal);
string_clear(signal_name);
return success;
}

View File

@@ -146,6 +146,26 @@ static inline bool infrared_signal_read_raw(InfraredSignal* signal, FlipperForma
return success;
}
static bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) {
string_t tmp;
string_init(tmp);
bool success = false;
do {
if(!flipper_format_read_string(ff, "type", tmp)) break;
if(string_equal_p(tmp, "raw")) {
success = infrared_signal_read_raw(signal, ff);
} else if(string_equal_p(tmp, "parsed")) {
success = infrared_signal_read_message(signal, ff);
} else {
FURI_LOG_E(TAG, "Unknown signal type");
}
} while(false);
string_clear(tmp);
return success;
}
InfraredSignal* infrared_signal_alloc() {
InfraredSignal* signal = malloc(sizeof(InfraredSignal));
@@ -227,24 +247,41 @@ bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char*
}
bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, string_t name) {
string_t buf;
string_init(buf);
string_t tmp;
string_init(tmp);
bool success = false;
do {
if(!flipper_format_read_string(ff, "name", buf)) break;
string_set(name, buf);
if(!flipper_format_read_string(ff, "type", buf)) break;
if(!string_cmp_str(buf, "raw")) {
success = infrared_signal_read_raw(signal, ff);
} else if(!string_cmp_str(buf, "parsed")) {
success = infrared_signal_read_message(signal, ff);
} else {
FURI_LOG_E(TAG, "Unknown type of signal (allowed - raw/parsed) ");
}
if(!flipper_format_read_string(ff, "name", tmp)) break;
string_set(name, tmp);
if(!infrared_signal_read_body(signal, ff)) break;
success = true;
} while(0);
string_clear(buf);
string_clear(tmp);
return success;
}
bool infrared_signal_search_and_read(
InfraredSignal* signal,
FlipperFormat* ff,
const string_t name) {
bool success = false;
string_t tmp;
string_init(tmp);
do {
bool is_name_found = false;
while(flipper_format_read_string(ff, "name", tmp)) {
is_name_found = string_equal_p(name, tmp);
if(is_name_found) break;
}
if(!is_name_found) break;
if(!infrared_signal_read_body(signal, ff)) break;
success = true;
} while(false);
string_clear(tmp);
return success;
}

View File

@@ -37,5 +37,9 @@ InfraredMessage* infrared_signal_get_message(InfraredSignal* signal);
bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name);
bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, string_t name);
bool infrared_signal_search_and_read(
InfraredSignal* signal,
FlipperFormat* ff,
const string_t name);
void infrared_signal_transmit(InfraredSignal* signal);

View File

@@ -33,8 +33,6 @@ static void infrared_scene_universal_common_hide_popup(Infrared* infrared) {
void infrared_scene_universal_common_on_enter(void* context) {
Infrared* infrared = context;
infrared_brute_force_clear_records(infrared->brute_force);
button_panel_reset_selection(infrared->button_panel);
view_stack_add_view(infrared->view_stack, button_panel_get_view(infrared->button_panel));
}
@@ -89,5 +87,6 @@ void infrared_scene_universal_common_on_exit(void* context) {
Infrared* infrared = context;
ButtonPanel* button_panel = infrared->button_panel;
view_stack_remove_view(infrared->view_stack, button_panel_get_view(button_panel));
infrared_brute_force_clear_records(infrared->brute_force);
button_panel_reset(button_panel);
}

View File

@@ -50,8 +50,10 @@ bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent e
if(success) {
scene_manager_next_scene(scene_manager, InfraredSceneLearnDone);
} else {
scene_manager_search_and_switch_to_previous_scene(
scene_manager, InfraredSceneRemoteList);
dialog_message_show_storage_error(infrared->dialogs, "Failed to save file");
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
scene_manager_search_and_switch_to_previous_scene_one_of(
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
}
consumed = true;
}

View File

@@ -38,7 +38,6 @@ void lfrfid_scene_write_on_enter(void* context) {
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
app->old_key_data = (uint8_t*)malloc(size);
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
lfrfid_worker_start_thread(app->lfworker);
@@ -92,5 +91,4 @@ void lfrfid_scene_write_on_exit(void* context) {
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
free(app->old_key_data);
}

View File

@@ -16,7 +16,7 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
LfRfidReadViewModel* model = _model;
canvas_set_color(canvas, ColorBlack);
canvas_draw_icon(canvas, 0, 8, &I_NFC_manual);
canvas_draw_icon(canvas, 0, 8, &I_NFC_manual_60x50);
canvas_set_font(canvas, FontPrimary);

View File

@@ -231,7 +231,30 @@ void nfc_show_loading_popup(void* context, bool show) {
}
}
static bool nfc_is_hal_ready() {
if(!furi_hal_nfc_is_init()) {
// No connection to the chip, show an error screen
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc();
dialog_message_set_text(
message,
"Error!\nNFC chip failed to start\n\n\nSend a photo of this to:\nsupport@flipperzero.one",
0,
0,
AlignLeft,
AlignTop);
dialog_message_show(dialogs, message);
dialog_message_free(message);
furi_record_close(RECORD_DIALOGS);
return false;
} else {
return true;
}
}
int32_t nfc_app(void* p) {
if(!nfc_is_hal_ready()) return 0;
Nfc* nfc = nfc_alloc();
char* args = p;
@@ -254,6 +277,8 @@ int32_t nfc_app(void* p) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate);
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
}

View File

@@ -33,8 +33,14 @@
#include <nfc/scenes/nfc_scene.h>
#include <nfc/helpers/nfc_custom_event.h>
#include <dialogs/dialogs.h>
#include "rpc/rpc_app.h"
#include <m-array.h>
ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST);
#define NFC_TEXT_STORE_SIZE 128
typedef enum {
@@ -58,6 +64,7 @@ struct Nfc {
char text_store[NFC_TEXT_STORE_SIZE + 1];
string_t text_box_store;
uint8_t byte_input_store[6];
MfClassicUserKeys_t mfc_key_strs; // Used in MFC key listing
void* rpc_ctx;
NfcRpcState rpc_state;

View File

@@ -32,6 +32,9 @@ ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu)
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd)
ADD_SCENE(nfc, mf_classic_keys_list, MfClassicKeysList)
ADD_SCENE(nfc, mf_classic_keys_delete, MfClassicKeysDelete)
ADD_SCENE(nfc, mf_classic_keys_warn_duplicate, MfClassicKeysWarnDuplicate)
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
ADD_SCENE(nfc, emv_menu, EmvMenu)

View File

@@ -25,8 +25,13 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneFileSelect);
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
} else {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
}
}
}
return consumed;

View File

@@ -1,6 +1,15 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
#define NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX (10U)
static const NotificationSequence sequence_detect_reader = {
&message_green_255,
&message_blue_255,
&message_do_not_reset,
NULL,
};
bool nfc_detect_reader_worker_callback(NfcWorkerEvent event, void* context) {
UNUSED(event);
furi_assert(context);
@@ -20,21 +29,26 @@ void nfc_scene_detect_reader_on_enter(void* context) {
DOLPHIN_DEED(DolphinDeedNfcEmulate);
detect_reader_set_callback(nfc->detect_reader, nfc_scene_detect_reader_callback, nfc);
detect_reader_set_nonces_max(nfc->detect_reader, NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX);
// Store number of collected nonces in scene state
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDetectReader, 0);
notification_message(nfc->notifications, &sequence_detect_reader);
nfc_worker_start(
nfc->worker,
NfcWorkerStateAnalyzeReader,
&nfc->dev->dev_data,
nfc_detect_reader_worker_callback,
nfc);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDetectReader);
nfc_blink_read_start(nfc);
}
bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
uint32_t nonces_collected =
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDetectReader);
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
@@ -42,8 +56,29 @@ bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyNoncesInfo);
consumed = true;
} else if(event.event == NfcWorkerEventDetectReaderMfkeyCollected) {
detect_reader_inc_nonce_cnt(nfc->detect_reader);
nonces_collected += 2;
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneDetectReader, nonces_collected);
detect_reader_set_nonces_collected(nfc->detect_reader, nonces_collected);
if(nonces_collected >= NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) {
detect_reader_set_state(nfc->detect_reader, DetectReaderStateDone);
nfc_blink_stop(nfc);
notification_message(nfc->notifications, &sequence_single_vibro);
notification_message(nfc->notifications, &sequence_set_green_255);
nfc_worker_stop(nfc->worker);
}
consumed = true;
} else if(event.event == NfcWorkerEventDetectReaderDetected) {
if(nonces_collected < NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) {
notification_message(nfc->notifications, &sequence_blink_start_cyan);
detect_reader_set_state(nfc->detect_reader, DetectReaderStateReaderDetected);
}
} else if(event.event == NfcWorkerEventDetectReaderLost) {
if(nonces_collected < NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) {
nfc_blink_stop(nfc);
notification_message(nfc->notifications, &sequence_detect_reader);
detect_reader_set_state(nfc->detect_reader, DetectReaderStateReaderLost);
}
}
}
@@ -59,5 +94,7 @@ void nfc_scene_detect_reader_on_exit(void* context) {
// Clear view
detect_reader_reset(nfc->detect_reader);
// Stop notifications
nfc_blink_stop(nfc);
notification_message(nfc->notifications, &sequence_reset_green);
}

View File

@@ -47,7 +47,9 @@ void nfc_scene_device_info_on_enter(void* context) {
}
string_clear(country_name);
}
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
} else if(
dev_data->protocol == NfcDeviceProtocolMifareClassic ||
dev_data->protocol == NfcDeviceProtocolMifareUl) {
string_set(temp_str, nfc->dev->dev_data.parsed_data);
}

View File

@@ -31,7 +31,10 @@ bool nfc_scene_dict_not_found_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneExtraActions);
} else {

View File

@@ -17,7 +17,7 @@ void nfc_scene_extra_actions_on_enter(void* context) {
submenu_add_item(
submenu,
"Mf Classic Keys",
"Mifare Classic Keys",
SubmenuIndexMfClassicKeys,
nfc_scene_extra_actions_submenu_callback,
nfc);

View File

@@ -91,6 +91,7 @@ void nfc_scene_mf_classic_dict_attack_on_enter(void* context) {
nfc_scene_mf_classic_dict_attack_prepare_view(nfc, DictAttackStateIdle);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDictAttack);
nfc_blink_read_start(nfc);
notification_message(nfc->notifications, &sequence_display_backlight_enforce_on);
}
bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent event) {
@@ -167,4 +168,5 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) {
}
dict_attack_reset(nfc->dict_attack);
nfc_blink_stop(nfc);
notification_message(nfc->notifications, &sequence_display_backlight_enforce_auto);
}

View File

@@ -26,15 +26,25 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) {
}
widget_add_string_element(
nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MF Classic Keys");
nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Mifare Classic Keys");
char temp_str[32];
snprintf(temp_str, sizeof(temp_str), "Flipper dict: %ld", flipper_dict_keys_total);
snprintf(temp_str, sizeof(temp_str), "Flipper list: %ld", flipper_dict_keys_total);
widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str);
snprintf(temp_str, sizeof(temp_str), "User dict: %ld", user_dict_keys_total);
snprintf(temp_str, sizeof(temp_str), "User list: %ld", user_dict_keys_total);
widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str);
widget_add_button_element(
nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc);
widget_add_icon_element(nfc->widget, 90, 12, &I_Keychain);
widget_add_button_element(
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_mf_classic_keys_widget_callback, nfc);
widget_add_icon_element(nfc->widget, 87, 13, &I_Keychain_39x36);
if(user_dict_keys_total > 0) {
widget_add_button_element(
nfc->widget,
GuiButtonTypeRight,
"List",
nfc_scene_mf_classic_keys_widget_callback,
nfc);
}
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}
@@ -47,6 +57,12 @@ bool nfc_scene_mf_classic_keys_on_event(void* context, SceneManagerEvent event)
if(event.event == GuiButtonTypeCenter) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysAdd);
consumed = true;
} else if(event.event == GuiButtonTypeLeft) {
scene_manager_previous_scene(nfc->scene_manager);
consumed = true;
} else if(event.event == GuiButtonTypeRight) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysList);
consumed = true;
}
}

View File

@@ -29,15 +29,16 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventByteInputDone) {
// Add key to dict
bool key_added = false;
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
if(dict) {
if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
key_added = true;
if(mf_classic_dict_is_key_present(dict, nfc->byte_input_store)) {
scene_manager_next_scene(
nfc->scene_manager, NfcSceneMfClassicKeysWarnDuplicate);
} else if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
}
}
if(key_added) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
}

View File

@@ -0,0 +1,77 @@
#include "../nfc_i.h"
void nfc_scene_mf_classic_keys_delete_widget_callback(
GuiButtonType result,
InputType type,
void* context) {
Nfc* nfc = context;
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
}
void nfc_scene_mf_classic_keys_delete_on_enter(void* context) {
Nfc* nfc = context;
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
uint32_t key_index =
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
// Setup Custom Widget view
string_t key_str;
string_init(key_str);
widget_add_string_element(
nfc->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Delete this key?");
widget_add_button_element(
nfc->widget,
GuiButtonTypeLeft,
"Cancel",
nfc_scene_mf_classic_keys_delete_widget_callback,
nfc);
widget_add_button_element(
nfc->widget,
GuiButtonTypeRight,
"Delete",
nfc_scene_mf_classic_keys_delete_widget_callback,
nfc);
mf_classic_dict_get_key_at_index_str(dict, key_str, key_index);
widget_add_string_element(
nfc->widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(key_str));
string_clear(key_str);
mf_classic_dict_free(dict);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}
bool nfc_scene_mf_classic_keys_delete_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
uint32_t key_index =
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
} else if(event.event == GuiButtonTypeRight) {
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
if(mf_classic_dict_delete_index(dict, key_index)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
} else {
scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
}
mf_classic_dict_free(dict);
consumed = true;
}
}
return consumed;
}
void nfc_scene_mf_classic_keys_delete_on_exit(void* context) {
Nfc* nfc = context;
widget_reset(nfc->widget);
}

View File

@@ -0,0 +1,100 @@
#include "../nfc_i.h"
#define NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX (100)
void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) {
furi_assert(context);
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
void nfc_scene_mf_classic_keys_list_popup_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
}
void nfc_scene_mf_classic_keys_list_prepare(Nfc* nfc, MfClassicDict* dict) {
Submenu* submenu = nfc->submenu;
uint32_t index = 0;
string_t temp_key;
string_init(temp_key);
submenu_set_header(submenu, "Select key to delete:");
while(mf_classic_dict_get_next_key_str(dict, temp_key)) {
char* current_key = (char*)malloc(sizeof(char) * 13);
strncpy(current_key, string_get_cstr(temp_key), 12);
MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key);
FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key);
submenu_add_item(
submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc);
}
string_clear(temp_key);
}
void nfc_scene_mf_classic_keys_list_on_enter(void* context) {
Nfc* nfc = context;
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
MfClassicUserKeys_init(nfc->mfc_key_strs);
if(dict) {
uint32_t total_user_keys = mf_classic_dict_get_total_keys(dict);
if(total_user_keys < NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX) {
nfc_scene_mf_classic_keys_list_prepare(nfc, dict);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
} else {
popup_set_header(nfc->popup, "Too many keys!", 64, 0, AlignCenter, AlignTop);
popup_set_text(
nfc->popup,
"Edit user dictionary\nwith file browser",
64,
12,
AlignCenter,
AlignTop);
popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback);
popup_set_context(nfc->popup, nfc);
popup_set_timeout(nfc->popup, 3000);
popup_enable_timeout(nfc->popup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
mf_classic_dict_free(dict);
} else {
popup_set_header(
nfc->popup, "Failed to load dictionary", 64, 32, AlignCenter, AlignCenter);
popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback);
popup_set_context(nfc->popup, nfc);
popup_set_timeout(nfc->popup, 3000);
popup_enable_timeout(nfc->popup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
}
bool nfc_scene_mf_classic_keys_list_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
consumed = scene_manager_previous_scene(nfc->scene_manager);
} else {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event);
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
consumed = true;
}
}
return consumed;
}
void nfc_scene_mf_classic_keys_list_on_exit(void* context) {
Nfc* nfc = context;
MfClassicUserKeys_it_t it;
for(MfClassicUserKeys_it(it, nfc->mfc_key_strs); !MfClassicUserKeys_end_p(it);
MfClassicUserKeys_next(it)) {
free(*MfClassicUserKeys_ref(it));
}
MfClassicUserKeys_clear(nfc->mfc_key_strs);
submenu_reset(nfc->submenu);
popup_reset(nfc->popup);
}

View File

@@ -0,0 +1,47 @@
#include "../nfc_i.h"
void nfc_scene_mf_classic_keys_warn_duplicate_popup_callback(void* context) {
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
}
void nfc_scene_mf_classic_keys_warn_duplicate_on_enter(void* context) {
Nfc* nfc = context;
// Setup view
Popup* popup = nfc->popup;
popup_set_icon(popup, 72, 16, &I_DolphinCommon_56x48);
popup_set_header(popup, "Key already exists!", 64, 3, AlignCenter, AlignTop);
popup_set_text(
popup,
"Please enter a\n"
"different key.",
4,
24,
AlignLeft,
AlignTop);
popup_set_timeout(popup, 5000);
popup_set_context(popup, nfc);
popup_set_callback(popup, nfc_scene_mf_classic_keys_warn_duplicate_popup_callback);
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
bool nfc_scene_mf_classic_keys_warn_duplicate_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeysAdd);
}
}
return consumed;
}
void nfc_scene_mf_classic_keys_warn_duplicate_on_exit(void* context) {
Nfc* nfc = context;
popup_reset(nfc->popup);
}

View File

@@ -7,6 +7,13 @@ enum SubmenuIndex {
SubmenuIndexDynamic, // dynamic indexes start here
};
void nfc_scene_mf_desfire_popup_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
}
MifareDesfireApplication* nfc_scene_mf_desfire_app_get_app(Nfc* nfc) {
uint32_t app_idx = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp) >>
1;
@@ -25,46 +32,45 @@ void nfc_scene_mf_desfire_app_submenu_callback(void* context, uint32_t index) {
void nfc_scene_mf_desfire_app_on_enter(void* context) {
Nfc* nfc = context;
Submenu* submenu = nfc->submenu;
MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc);
if(!app) {
popup_set_icon(nfc->popup, 5, 5, &I_WarningDolphin_45x42);
popup_set_header(nfc->popup, "Internal Error!", 55, 12, AlignLeft, AlignBottom);
popup_set_text(
nfc->popup,
"No app selected.\nThis should\nnever happen,\nplease file a bug.",
55,
15,
AlignLeft,
AlignTop);
popup_set_header(nfc->popup, "Empty card!", 55, 12, AlignLeft, AlignBottom);
popup_set_callback(nfc->popup, nfc_scene_mf_desfire_popup_callback);
popup_set_context(nfc->popup, nfc);
popup_set_timeout(nfc->popup, 3000);
popup_enable_timeout(nfc->popup);
popup_set_text(nfc->popup, "No application\nfound.", 55, 15, AlignLeft, AlignTop);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
FURI_LOG_E(TAG, "Bad state. No app selected?");
return;
}
} else {
text_box_set_font(nfc->text_box, TextBoxFontHex);
submenu_add_item(
nfc->submenu,
"App info",
SubmenuIndexAppInfo,
nfc_scene_mf_desfire_app_submenu_callback,
nfc);
text_box_set_font(nfc->text_box, TextBoxFontHex);
submenu_add_item(
submenu, "App info", SubmenuIndexAppInfo, nfc_scene_mf_desfire_app_submenu_callback, nfc);
uint16_t cap = NFC_TEXT_STORE_SIZE;
char* buf = nfc->text_store;
int idx = SubmenuIndexDynamic;
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
int size = snprintf(buf, cap, "File %d", file->id);
if(size < 0 || size >= cap) {
FURI_LOG_W(
TAG,
"Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated");
break;
uint16_t cap = NFC_TEXT_STORE_SIZE;
char* buf = nfc->text_store;
int idx = SubmenuIndexDynamic;
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
int size = snprintf(buf, cap, "File %d", file->id);
if(size < 0 || size >= cap) {
FURI_LOG_W(
TAG,
"Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated");
break;
}
char* label = buf;
cap -= size + 1;
buf += size + 1;
submenu_add_item(
nfc->submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc);
}
char* label = buf;
cap -= size + 1;
buf += size + 1;
submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc);
}
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
}
bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) {
@@ -73,26 +79,30 @@ bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) {
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp);
if(event.type == SceneManagerEventTypeCustom) {
MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc);
TextBox* text_box = nfc->text_box;
string_reset(nfc->text_box_store);
if(event.event == SubmenuIndexAppInfo) {
mf_df_cat_application_info(app, nfc->text_box_store);
if(event.event == NfcCustomEventViewExit) {
consumed = scene_manager_previous_scene(nfc->scene_manager);
} else {
uint16_t index = event.event - SubmenuIndexDynamic;
MifareDesfireFile* file = app->file_head;
for(int i = 0; file && i < index; i++) {
file = file->next;
MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc);
TextBox* text_box = nfc->text_box;
string_reset(nfc->text_box_store);
if(event.event == SubmenuIndexAppInfo) {
mf_df_cat_application_info(app, nfc->text_box_store);
} else {
uint16_t index = event.event - SubmenuIndexDynamic;
MifareDesfireFile* file = app->file_head;
for(int i = 0; file && i < index; i++) {
file = file->next;
}
if(!file) {
return false;
}
mf_df_cat_file(file, nfc->text_box_store);
}
if(!file) {
return false;
}
mf_df_cat_file(file, nfc->text_box_store);
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
consumed = true;
}
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
consumed = true;
} else if(event.type == SceneManagerEventTypeBack) {
if(state & 1) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
@@ -108,6 +118,7 @@ void nfc_scene_mf_desfire_app_on_exit(void* context) {
Nfc* nfc = context;
// Clear views
popup_reset(nfc->popup);
text_box_reset(nfc->text_box);
string_reset(nfc->text_box_store);
submenu_reset(nfc->submenu);

View File

@@ -27,7 +27,7 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState
popup_reset(nfc->popup);
popup_set_text(
nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
} else if(state == NfcSceneMfUlReadStateReading) {
popup_reset(nfc->popup);
popup_set_header(

View File

@@ -34,15 +34,19 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
nfc);
string_t temp_str;
string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true));
string_cat_printf(temp_str, "UID:");
for(size_t i = 0; i < data->uid_len; i++) {
string_cat_printf(temp_str, " %02X", data->uid[i]);
}
string_cat_printf(
temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
if(mf_ul_data->data_read != mf_ul_data->data_size) {
string_cat_printf(temp_str, "\nPassword-protected pages!");
if(string_size(nfc->dev->dev_data.parsed_data)) {
string_init_set(temp_str, nfc->dev->dev_data.parsed_data);
} else {
string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true));
string_cat_printf(temp_str, "UID:");
for(size_t i = 0; i < data->uid_len; i++) {
string_cat_printf(temp_str, " %02X", data->uid[i]);
}
string_cat_printf(
temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4);
if(mf_ul_data->data_read != mf_ul_data->data_size) {
string_cat_printf(temp_str, "\nPassword-protected pages!");
}
}
widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str));
string_clear(temp_str);

View File

@@ -20,7 +20,7 @@ void nfc_scene_mf_ultralight_unlock_menu_on_enter(void* context) {
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
submenu_add_item(
submenu,
"Enter Password Manually",
"Enter PWD Manually",
SubmenuIndexMfUlUnlockMenuManual,
nfc_scene_mf_ultralight_unlock_menu_submenu_callback,
nfc);

View File

@@ -16,14 +16,14 @@ void nfc_scene_mfkey_nonces_info_on_enter(void* context) {
uint16_t nonces_saved = mfkey32_get_auth_sectors(temp_str);
widget_add_text_scroll_element(nfc->widget, 0, 22, 128, 42, string_get_cstr(temp_str));
string_printf(temp_str, "Nonces saved %d", nonces_saved);
string_printf(temp_str, "Nonce pairs saved %d", nonces_saved);
widget_add_string_element(
nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, string_get_cstr(temp_str));
widget_add_string_element(
nfc->widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Authenticated sectors:");
widget_add_button_element(
nfc->widget, GuiButtonTypeRight, "Next", nfc_scene_mfkey_nonces_info_callback, nfc);
nfc->widget, GuiButtonTypeCenter, "OK", nfc_scene_mfkey_nonces_info_callback, nfc);
string_clear(temp_str);
@@ -35,7 +35,7 @@ bool nfc_scene_mfkey_nonces_info_on_event(void* context, SceneManagerEvent event
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeRight) {
if(event.event == GuiButtonTypeCenter) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyComplete);
consumed = true;
}

View File

@@ -26,7 +26,7 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) {
popup_reset(nfc->popup);
popup_set_text(
nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual);
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
} else if(state == NfcSceneReadStateReading) {
popup_reset(nfc->popup);
popup_set_header(

View File

@@ -11,7 +11,7 @@ void nfc_scene_restore_original_confirm_on_enter(void* context) {
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_header(dialog_ex, "Restore Card Data?", 64, 0, AlignCenter, AlignTop);
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring);
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring_38x32);
dialog_ex_set_text(
dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop);
dialog_ex_set_left_button_text(dialog_ex, "Cancel");

View File

@@ -27,7 +27,10 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicKeys);
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneSavedMenu);
} else {

View File

@@ -20,8 +20,7 @@ void nfc_scene_saved_menu_on_enter(void* context) {
Submenu* submenu = nfc->submenu;
if(nfc->dev->format == NfcDeviceSaveFormatUid ||
nfc->dev->format == NfcDeviceSaveFormatMifareDesfire ||
nfc->dev->format == NfcDeviceSaveFormatBankCard) {
nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) {
submenu_add_item(
submenu,
"Emulate UID",
@@ -91,7 +90,9 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
bool application_info_present = false;
if(dev_data->protocol == NfcDeviceProtocolEMV) {
application_info_present = true;
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
} else if(
dev_data->protocol == NfcDeviceProtocolMifareClassic ||
dev_data->protocol == NfcDeviceProtocolMifareUl) {
application_info_present = nfc_supported_card_verify_and_parse(dev_data);
}

View File

@@ -10,29 +10,50 @@ struct DetectReader {
typedef struct {
uint16_t nonces;
uint16_t nonces_max;
DetectReaderState state;
} DetectReaderViewModel;
static void detect_reader_draw_callback(Canvas* canvas, void* model) {
DetectReaderViewModel* m = model;
char text[32] = {};
snprintf(text, sizeof(text), "Tap the reader several times");
canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Tap the reader several times");
// Draw header and icon
canvas_draw_icon(canvas, 0, 16, &I_Modern_reader_18x34);
if(m->state == DetectReaderStateStart) {
snprintf(text, sizeof(text), "Touch the reader");
canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39);
} else if(m->state == DetectReaderStateReaderDetected) {
snprintf(text, sizeof(text), "Move the Flipper away");
canvas_draw_icon(canvas, 24, 25, &I_Release_arrow_18x15);
} else if(m->state == DetectReaderStateReaderLost) {
snprintf(text, sizeof(text), "Touch the reader again");
canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39);
}
if(m->nonces == 0) {
canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, text);
// Draw collected nonces
if(m->state == DetectReaderStateStart) {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 52, 22, AlignLeft, AlignTop, "Emulating...");
canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Emulating...");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 52, 35, AlignLeft, AlignTop, "MIFARE Classic");
canvas_draw_icon(canvas, 0, 13, &I_Tap_reader_36x38);
canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, "MIFARE MFkey32");
} else {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 54, 22, AlignLeft, AlignTop, "Collecting...");
if(m->state == DetectReaderStateDone) {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Completed!");
} else {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Collecting...");
}
canvas_set_font(canvas, FontSecondary);
snprintf(text, sizeof(text), "Nonces: %d", m->nonces);
canvas_draw_str_aligned(canvas, 54, 35, AlignLeft, AlignTop, text);
elements_button_right(canvas, "Next");
canvas_draw_icon(canvas, 6, 15, &I_ArrowC_1_36x36);
snprintf(text, sizeof(text), "Nonce pairs: %d/%d", m->nonces, m->nonces_max);
canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, text);
}
// Draw button
if(m->nonces > 0) {
elements_button_center(canvas, "Done");
}
}
@@ -49,7 +70,7 @@ static bool detect_reader_input_callback(InputEvent* event, void* context) {
});
if(event->type == InputTypeShort) {
if(event->key == InputKeyRight) {
if(event->key == InputKeyOk) {
if(nonces > 0) {
detect_reader->callback(detect_reader->context);
consumed = true;
@@ -84,6 +105,8 @@ void detect_reader_reset(DetectReader* detect_reader) {
with_view_model(
detect_reader->view, (DetectReaderViewModel * model) {
model->nonces = 0;
model->nonces_max = 0;
model->state = DetectReaderStateStart;
return false;
});
}
@@ -105,11 +128,31 @@ void detect_reader_set_callback(
detect_reader->context = context;
}
void detect_reader_inc_nonce_cnt(DetectReader* detect_reader) {
void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_max) {
furi_assert(detect_reader);
with_view_model(
detect_reader->view, (DetectReaderViewModel * model) {
model->nonces++;
model->nonces_max = nonces_max;
return false;
});
}
void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected) {
furi_assert(detect_reader);
with_view_model(
detect_reader->view, (DetectReaderViewModel * model) {
model->nonces = nonces_collected;
return false;
});
}
void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state) {
furi_assert(detect_reader);
with_view_model(
detect_reader->view, (DetectReaderViewModel * model) {
model->state = state;
return true;
});
}

View File

@@ -5,6 +5,13 @@
typedef struct DetectReader DetectReader;
typedef enum {
DetectReaderStateStart,
DetectReaderStateReaderDetected,
DetectReaderStateReaderLost,
DetectReaderStateDone,
} DetectReaderState;
typedef void (*DetectReaderDoneCallback)(void* context);
DetectReader* detect_reader_alloc();
@@ -20,4 +27,8 @@ void detect_reader_set_callback(
DetectReaderDoneCallback callback,
void* context);
void detect_reader_inc_nonce_cnt(DetectReader* detect_reader);
void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_max);
void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected);
void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state);

View File

@@ -14,6 +14,7 @@ typedef enum {
SubmenuIndexNiceFlo24bit,
SubmenuIndexCAME12bit,
SubmenuIndexCAME24bit,
SubmenuIndexBETT_433,
SubmenuIndexCAMETwee,
SubmenuIndexNeroSketch,
SubmenuIndexNeroRadio,

View File

@@ -86,3 +86,5 @@ typedef enum {
SubGhzViewReceiverModeLive,
SubGhzViewReceiverModeFile,
} SubGhzViewReceiverMode;
#define SUBGHZ_HISTORY_REMOVE_SAVED_ITEMS 1

View File

@@ -13,9 +13,11 @@ ADD_SCENE(subghz, saved_menu, SavedMenu)
ADD_SCENE(subghz, delete, Delete)
ADD_SCENE(subghz, delete_success, DeleteSuccess)
ADD_SCENE(subghz, test, Test)
ADD_SCENE(subghz, test_static, TestStatic)
ADD_SCENE(subghz, test_carrier, TestCarrier)
#if FURI_DEBUG
ADD_SCENE(subghz, test_static, TestStatic)
ADD_SCENE(subghz, test_packet, TestPacket)
#endif
ADD_SCENE(subghz, set_type, SetType)
ADD_SCENE(subghz, set_fix_faac_868, SetFixFaac868)
ADD_SCENE(subghz, set_cnt_faac_868, SetCntFaac868)

View File

@@ -1,7 +1,8 @@
#include "../subghz_i.h"
#include "../views/subghz_frequency_analyzer.h"
#include <dolphin/dolphin.h>
#define TAG "SubGhzSceneFrequencyAnalyzer"
void subghz_scene_frequency_analyzer_callback(SubGhzCustomEvent event, void* context) {
furi_assert(context);
SubGhz* subghz = context;
@@ -17,8 +18,26 @@ void subghz_scene_frequency_analyzer_on_enter(void* context) {
}
bool subghz_scene_frequency_analyzer_on_event(void* context, SceneManagerEvent event) {
UNUSED(context);
UNUSED(event);
SubGhz* subghz = context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventViewReceiverOK) {
uint32_t frequency =
subghz_frequency_analyzer_get_frequency_to_save(subghz->subghz_frequency_analyzer);
if(frequency > 0) {
subghz->last_settings->frequency = frequency;
subghz_last_settings_save(subghz->last_settings);
}
return true;
} else if(event.event == SubGhzCustomEventViewReceiverUnlock) {
// Don't need to save, we already saved on short event
#ifdef FURI_DEBUG
FURI_LOG_W(TAG, "Goto next scene!");
#endif
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
return true;
}
}
return false;
}

View File

@@ -50,8 +50,8 @@ bool subghz_scene_need_saving_on_event(void* context, SceneManagerEvent event) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
subghz_preset_init(
subghz,
"AM650",
subghz_setting_get_default_frequency(subghz->setting),
subghz_setting_get_preset_name(subghz->setting, subghz->last_settings->preset),
subghz->last_settings->frequency,
NULL,
0);
scene_manager_search_and_switch_to_previous_scene(

View File

@@ -134,12 +134,22 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
} else {
//Restore default setting
subghz_preset_init(
subghz,
"AM650",
subghz_setting_get_default_frequency(subghz->setting),
NULL,
0);
if(subghz->raw_send_only) {
subghz_preset_init(
subghz,
"AM650",
subghz_setting_get_default_frequency(subghz->setting),
NULL,
0);
} else {
subghz_preset_init(
subghz,
subghz_setting_get_preset_name(
subghz->setting, subghz->last_settings->preset),
subghz->last_settings->frequency,
NULL,
0);
}
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneSaved)) {
if(!scene_manager_search_and_switch_to_previous_scene(
@@ -340,6 +350,10 @@ void subghz_scene_read_raw_on_exit(void* context) {
subghz->state_notifications = SubGhzNotificationStateIDLE;
notification_message(subghz->notifications, &sequence_reset_rgb);
//filter restoration
//filter restoration
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
#endif
}

View File

@@ -1,9 +1,13 @@
#include "../subghz_i.h"
#include "../views/receiver.h"
#define TAG "SubGhzSceneReceiver"
const NotificationSequence subghz_sequence_rx = {
&message_green_255,
&message_display_backlight_on,
&message_vibro_on,
&message_note_c6,
&message_delay_50,
@@ -103,7 +107,11 @@ void subghz_scene_receiver_on_enter(void* context) {
if(subghz->txrx->rx_key_state == SubGhzRxKeyStateIDLE) {
subghz_preset_init(
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
subghz,
subghz_setting_get_preset_name(subghz->setting, subghz->last_settings->preset),
subghz->last_settings->frequency,
NULL,
0);
subghz_history_reset(subghz->txrx->history);
subghz->txrx->rx_key_state = SubGhzRxKeyStateStart;
}
@@ -169,8 +177,8 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
subghz_preset_init(
subghz,
"AM650",
subghz_setting_get_default_frequency(subghz->setting),
subghz_setting_get_preset_name(subghz->setting, subghz->last_settings->preset),
subghz->last_settings->frequency,
NULL,
0);
scene_manager_search_and_switch_to_previous_scene(
@@ -179,6 +187,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
consumed = true;
break;
case SubGhzCustomEventViewReceiverOK:
// Show file info, scene: receiver_info
subghz->txrx->idx_menu_chosen =
subghz_view_receiver_get_idx_menu(subghz->subghz_receiver);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo);
@@ -188,6 +197,8 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
subghz->state_notifications = SubGhzNotificationStateIDLE;
subghz->txrx->idx_menu_chosen =
subghz_view_receiver_get_idx_menu(subghz->subghz_receiver);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzViewIdReceiver, SubGhzCustomEventManagerSet);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
consumed = true;
break;

View File

@@ -2,6 +2,8 @@
#include <lib/subghz/protocols/raw.h>
#define TAG "SubGhzSceneReceiverConfig"
enum SubGhzSettingIndex {
SubGhzSettingIndexFrequency,
SubGhzSettingIndexHopping,
@@ -27,10 +29,12 @@ const char* const detect_raw_text[DETECT_RAW_COUNT] = {
"ON",
};
#ifndef SUBGHZ_SAVE_DETECT_RAW_SETTING
const SubGhzProtocolFlag detect_raw_value[DETECT_RAW_COUNT] = {
SubGhzProtocolFlag_Decodable,
SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW,
};
#endif
#define RSSI_THRESHOLD_COUNT 7
const char* const rssi_threshold_text[RSSI_THRESHOLD_COUNT] = {
@@ -103,6 +107,7 @@ uint8_t subghz_scene_receiver_config_hopper_value_index(
}
}
#ifndef SUBGHZ_SAVE_DETECT_RAW_SETTING
uint8_t subghz_scene_receiver_config_detect_raw_value_index(
const SubGhzProtocolFlag value,
const SubGhzProtocolFlag values[],
@@ -116,6 +121,7 @@ uint8_t subghz_scene_receiver_config_detect_raw_value_index(
}
return index;
}
#endif
uint8_t subghz_scene_receiver_config_rssi_threshold_value_index(
const int value,
@@ -145,6 +151,8 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
(subghz_setting_get_frequency(subghz->setting, index) % 1000000) / 10000);
variable_item_set_current_value_text(item, text_buf);
subghz->txrx->preset->frequency = subghz_setting_get_frequency(subghz->setting, index);
subghz->last_settings->frequency = subghz->txrx->preset->frequency;
subghz_setting_set_default_frequency(subghz->setting, subghz->txrx->preset->frequency);
} else {
variable_item_set_current_value_index(
item, subghz_setting_get_frequency_default_index(subghz->setting));
@@ -154,11 +162,13 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(
item, subghz_setting_get_preset_name(subghz->setting, index));
const char* preset_name = subghz_setting_get_preset_name(subghz->setting, index);
variable_item_set_current_value_text(item, preset_name);
subghz->last_settings->preset = index;
subghz_preset_init(
subghz,
subghz_setting_get_preset_name(subghz->setting, index),
preset_name,
subghz->txrx->preset->frequency,
subghz_setting_get_preset_data(subghz->setting, index),
subghz_setting_get_preset_data_size(subghz->setting, index));
@@ -179,49 +189,64 @@ static void subghz_scene_receiver_config_set_detect_raw(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, detect_raw_text[index]);
subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]);
if(subghz->txrx->hopper_state == 0) {
variable_item_set_current_value_text(item, detect_raw_text[index]);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz->last_settings->detect_raw = index;
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
(index == 1));
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]);
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
(index == 1));
#endif
} else {
variable_item_set_current_value_index(item, 0);
}
}
static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, hopping_text[index]);
if(hopping_value[index] == SubGhzHopperStateOFF) {
char text_buf[10] = {0};
snprintf(
text_buf,
sizeof(text_buf),
"%lu.%02lu",
subghz_setting_get_default_frequency(subghz->setting) / 1000000,
(subghz_setting_get_default_frequency(subghz->setting) % 1000000) / 10000);
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
text_buf);
subghz->txrx->preset->frequency = subghz_setting_get_default_frequency(subghz->setting);
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_setting_get_frequency_default_index(subghz->setting));
} else {
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
" -----");
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_setting_get_frequency_default_index(subghz->setting));
}
if(subghz_receiver_get_filter(subghz->txrx->receiver) == SubGhzProtocolFlag_Decodable) {
variable_item_set_current_value_text(item, hopping_text[index]);
if(hopping_value[index] == SubGhzHopperStateOFF) {
char text_buf[10] = {0};
snprintf(
text_buf,
sizeof(text_buf),
"%lu.%02lu",
subghz_setting_get_default_frequency(subghz->setting) / 1000000,
(subghz_setting_get_default_frequency(subghz->setting) % 1000000) / 10000);
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
text_buf);
subghz->txrx->preset->frequency =
subghz_setting_get_default_frequency(subghz->setting);
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_setting_get_frequency_default_index(subghz->setting));
} else {
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
" -----");
variable_item_set_current_value_index(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz_setting_get_frequency_default_index(subghz->setting));
}
subghz->txrx->hopper_state = hopping_value[index];
subghz->txrx->hopper_state = hopping_value[index];
} else {
variable_item_set_current_value_index(item, 0);
}
}
static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {
@@ -238,6 +263,13 @@ void subghz_scene_receiver_config_on_enter(void* context) {
VariableItem* item;
uint8_t value_index;
#ifdef FURI_DEBUG
FURI_LOG_D(
TAG,
"Last frequency: %d, Preset: %d",
subghz->last_settings->frequency,
subghz->last_settings->preset);
#endif
item = variable_item_list_add(
subghz->variable_item_list,
"Frequency:",
@@ -258,20 +290,6 @@ void subghz_scene_receiver_config_on_enter(void* context) {
(subghz_setting_get_frequency(subghz->setting, value_index) % 1000000) / 10000);
variable_item_set_current_value_text(item, text_buf);
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
item = variable_item_list_add(
subghz->variable_item_list,
"Hopping:",
HOPPING_COUNT,
subghz_scene_receiver_config_set_hopping_running,
subghz);
value_index = subghz_scene_receiver_config_hopper_value_index(
subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, hopping_text[value_index]);
}
item = variable_item_list_add(
subghz->variable_item_list,
"Modulation:",
@@ -286,22 +304,37 @@ void subghz_scene_receiver_config_on_enter(void* context) {
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
// Hopping
item = variable_item_list_add(
subghz->variable_item_list,
"Hopping:",
HOPPING_COUNT,
subghz_scene_receiver_config_set_hopping_running,
subghz);
value_index = subghz_scene_receiver_config_hopper_value_index(
subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, hopping_text[value_index]);
// Detect Raw
item = variable_item_list_add(
subghz->variable_item_list,
"Detect Raw:",
DETECT_RAW_COUNT,
subghz_scene_receiver_config_set_detect_raw,
subghz);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
value_index = subghz->last_settings->detect_raw;
#else
value_index = subghz_scene_receiver_config_detect_raw_value_index(
subghz_receiver_get_filter(subghz->txrx->receiver),
detect_raw_value,
DETECT_RAW_COUNT);
#endif
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, detect_raw_text[value_index]);
}
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
// RSSI
item = variable_item_list_add(
subghz->variable_item_list,
"RSSI for Raw:",
@@ -315,10 +348,8 @@ void subghz_scene_receiver_config_on_enter(void* context) {
RSSI_THRESHOLD_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, rssi_threshold_text[value_index]);
}
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
// Lock keyboard
variable_item_list_add(subghz->variable_item_list, "Lock Keyboard", 1, NULL, NULL);
variable_item_list_set_enter_callback(
subghz->variable_item_list,
@@ -347,6 +378,7 @@ void subghz_scene_receiver_config_on_exit(void* context) {
SubGhz* subghz = context;
variable_item_list_set_selected_item(subghz->variable_item_list, 0);
variable_item_list_reset(subghz->variable_item_list);
subghz_last_settings_save(subghz->last_settings);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet);
}

View File

@@ -26,6 +26,7 @@ static bool subghz_scene_receiver_info_update_parser(void* context) {
subghz->txrx->receiver,
subghz_history_get_protocol_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen));
if(subghz->txrx->decoder_result) {
// In this case flipper format was changed to short file content
subghz_protocol_decoder_base_deserialize(
subghz->txrx->decoder_result,
subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen));

View File

@@ -1,4 +1,6 @@
#include "../subghz_i.h"
#include <lib/subghz/protocols/keeloq.h>
#include <lib/subghz/protocols/star_line.h>
typedef enum {
SubGhzRpcStateIdle,
@@ -97,4 +99,9 @@ void subghz_scene_rpc_on_exit(void* context) {
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
keeloq_reset_mfname();
keeloq_reset_kl_type();
star_line_reset_mfname();
star_line_reset_kl_type();
}

View File

@@ -14,6 +14,22 @@ void subghz_scene_save_name_text_input_callback(void* context) {
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneSaveName);
}
void subghz_scene_save_name_get_timefilename(string_t name, uint32_t frequency) {
FuriHalRtcDateTime datetime = {0};
furi_hal_rtc_get_datetime(&datetime);
string_printf(
name,
"RAW_%.4d.%.2d.%.2d-%.2d.%.2d.%.2d-%d.%.2dMHz",
datetime.year,
datetime.month,
datetime.day,
datetime.hour,
datetime.minute,
datetime.second,
frequency / 1000000,
(frequency / 10000) % 100);
}
void subghz_scene_save_name_on_enter(void* context) {
SubGhz* subghz = context;
@@ -42,9 +58,9 @@ void subghz_scene_save_name_on_enter(void* context) {
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
SubGhzCustomEventManagerSetRAW) {
dev_name_empty = true;
subghz_get_next_name_file(subghz, SUBGHZ_MAX_LEN_NAME);
subghz_scene_save_name_get_timefilename(
file_name, subghz->txrx->preset->frequency);
}
path_extract_filename(subghz->file_path, file_name, true);
}
string_set(subghz->file_path, dir_name);
}

View File

@@ -69,61 +69,67 @@ void subghz_scene_set_type_on_enter(void* context) {
submenu_add_item(
subghz->submenu,
"Faac SLH_868",
"Faac SLH 868MHz",
SubmenuIndexFaacSLH_868,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Faac SLH_433",
"Faac SLH 433MHz",
SubmenuIndexFaacSLH_433,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"BFT Mitto",
"BFT Mitto 433MHz",
SubmenuIndexBFT,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Princeton_433",
"Princeton 433MHz",
SubmenuIndexPricenton,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Nice Flo 12bit_433",
"Nice Flo 12bit 433MHz",
SubmenuIndexNiceFlo12bit,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Nice Flo 24bit_433",
"Nice Flo 24bit 433MHz",
SubmenuIndexNiceFlo24bit,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"CAME 12bit_433",
"CAME 12bit 433MHz",
SubmenuIndexCAME12bit,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"CAME 24bit_433",
"CAME 24bit 433MHz",
SubmenuIndexCAME24bit,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Linear_300",
"BETT 433MHz",
SubmenuIndexBETT_433,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Linear 300MHz",
SubmenuIndexLinear_300_00,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"CAME TWEE",
"CAME TWEE 433MHz",
SubmenuIndexCAMETwee,
subghz_scene_set_type_submenu_callback,
subghz);
@@ -133,49 +139,49 @@ void subghz_scene_set_type_on_enter(void* context) {
// subghz->submenu, "Nero Radio", SubmenuIndexNeroRadio, subghz_scene_set_type_submenu_callback, subghz);
submenu_add_item(
subghz->submenu,
"Gate TX_433",
"Gate TX 433MHz",
SubmenuIndexGateTX,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"DoorHan_315",
"DoorHan 315MHz",
SubmenuIndexDoorHan_315_00,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"DoorHan_433",
"DoorHan 433MHz",
SubmenuIndexDoorHan_433_92,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"LiftMaster_315",
"Security+1.0 315MHz",
SubmenuIndexLiftMaster_315_00,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"LiftMaster_390",
"Security+1.0 390MHz",
SubmenuIndexLiftMaster_390_00,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Security+2.0_310",
"Security+2.0 310MHz",
SubmenuIndexSecPlus_v2_310_00,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Security+2.0_315",
"Security+2.0 315MHz",
SubmenuIndexSecPlus_v2_315_00,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Security+2.0_390",
"Security+2.0 390MHz",
SubmenuIndexSecPlus_v2_390_00,
subghz_scene_set_type_submenu_callback,
subghz);
@@ -247,6 +253,13 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
generated_protocol = true;
}
break;
case SubmenuIndexBETT_433:
key = (key & 0x0000FFF0);
if(subghz_scene_set_type_submenu_gen_data_protocol(
subghz, SUBGHZ_PROTOCOL_BETT_NAME, key, 18, 433920000, "AM650")) {
generated_protocol = true;
}
break;
case SubmenuIndexCAMETwee:
key = (key & 0x0FFFFFF0);
key = 0x003FFF7200000000 | (key ^ 0xE0E0E0EE);

View File

@@ -21,11 +21,15 @@ void subghz_scene_start_on_enter(void* context) {
if(subghz->state_notifications == SubGhzNotificationStateStarting) {
subghz->state_notifications = SubGhzNotificationStateIDLE;
}
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
false);
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
#endif
submenu_add_item(
subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz);
@@ -93,6 +97,7 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer);
return true;
} else if(event.event == SubmenuIndexTest) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest);

View File

@@ -20,11 +20,12 @@ void subghz_scene_test_on_enter(void* context) {
SubmenuIndexCarrier,
subghz_scene_test_submenu_callback,
subghz);
#if FURI_DEBUG
submenu_add_item(
subghz->submenu, "Packet", SubmenuIndexPacket, subghz_scene_test_submenu_callback, subghz);
submenu_add_item(
subghz->submenu, "Static", SubmenuIndexStatic, subghz_scene_test_submenu_callback, subghz);
#endif
submenu_set_selected_item(
subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneTest));
@@ -40,7 +41,9 @@ bool subghz_scene_test_on_event(void* context, SceneManagerEvent event) {
subghz->scene_manager, SubGhzSceneTest, SubmenuIndexCarrier);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestCarrier);
return true;
} else if(event.event == SubmenuIndexPacket) {
}
#if FURI_DEBUG
else if(event.event == SubmenuIndexPacket) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneTest, SubmenuIndexPacket);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestPacket);
@@ -51,6 +54,7 @@ bool subghz_scene_test_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestStatic);
return true;
}
#endif
}
return false;
}

View File

@@ -27,4 +27,4 @@ bool subghz_scene_test_carrier_on_event(void* context, SceneManagerEvent event)
void subghz_scene_test_carrier_on_exit(void* context) {
UNUSED(context);
}
}

View File

@@ -1,3 +1,4 @@
#if FURI_DEBUG
#include "../subghz_i.h"
#include "../views/subghz_test_packet.h"
@@ -28,3 +29,4 @@ bool subghz_scene_test_packet_on_event(void* context, SceneManagerEvent event) {
void subghz_scene_test_packet_on_exit(void* context) {
UNUSED(context);
}
#endif

View File

@@ -1,3 +1,4 @@
#if FURI_DEBUG
#include "../subghz_i.h"
#include "../views/subghz_test_static.h"
@@ -28,3 +29,4 @@ bool subghz_scene_test_static_on_event(void* context, SceneManagerEvent event) {
void subghz_scene_test_static_on_exit(void* context) {
UNUSED(context);
}
#endif

View File

@@ -5,6 +5,8 @@
#include <lib/toolbox/path.h>
#include "subghz_i.h"
#define TAG "SubGhzApp"
bool subghz_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);
SubGhz* subghz = context;
@@ -59,7 +61,7 @@ void subghz_blink_stop(SubGhz* instance) {
notification_message(instance->notifications, &sequence_blink_stop);
}
SubGhz* subghz_alloc() {
SubGhz* subghz_alloc(bool alloc_for_tx_only) {
SubGhz* subghz = malloc(sizeof(SubGhz));
string_init(subghz->file_path);
@@ -86,38 +88,43 @@ SubGhz* subghz_alloc() {
// Open Notification record
subghz->notifications = furi_record_open(RECORD_NOTIFICATION);
// SubMenu
subghz->submenu = submenu_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher, SubGhzViewIdMenu, submenu_get_view(subghz->submenu));
// Receiver
subghz->subghz_receiver = subghz_view_receiver_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdReceiver,
subghz_view_receiver_get_view(subghz->subghz_receiver));
if(!alloc_for_tx_only) {
// SubMenu
subghz->submenu = submenu_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher, SubGhzViewIdMenu, submenu_get_view(subghz->submenu));
// Receiver
subghz->subghz_receiver = subghz_view_receiver_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdReceiver,
subghz_view_receiver_get_view(subghz->subghz_receiver));
}
// Popup
subghz->popup = popup_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher, SubGhzViewIdPopup, popup_get_view(subghz->popup));
if(!alloc_for_tx_only) {
// Text Input
subghz->text_input = text_input_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdTextInput,
text_input_get_view(subghz->text_input));
// Text Input
subghz->text_input = text_input_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher, SubGhzViewIdTextInput, text_input_get_view(subghz->text_input));
// Byte Input
subghz->byte_input = byte_input_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher, SubGhzViewIdByteInput, byte_input_get_view(subghz->byte_input));
// Custom Widget
subghz->widget = widget_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher, SubGhzViewIdWidget, widget_get_view(subghz->widget));
// Byte Input
subghz->byte_input = byte_input_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdByteInput,
byte_input_get_view(subghz->byte_input));
// Custom Widget
subghz->widget = widget_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher, SubGhzViewIdWidget, widget_get_view(subghz->widget));
}
//Dialog
subghz->dialogs = furi_record_open(RECORD_DIALOGS);
@@ -127,35 +134,36 @@ SubGhz* subghz_alloc() {
subghz->view_dispatcher,
SubGhzViewIdTransmitter,
subghz_view_transmitter_get_view(subghz->subghz_transmitter));
if(!alloc_for_tx_only) {
// Variable Item List
subghz->variable_item_list = variable_item_list_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdVariableItemList,
variable_item_list_get_view(subghz->variable_item_list));
// Variable Item List
subghz->variable_item_list = variable_item_list_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdVariableItemList,
variable_item_list_get_view(subghz->variable_item_list));
// Frequency Analyzer
subghz->subghz_frequency_analyzer = subghz_frequency_analyzer_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdFrequencyAnalyzer,
subghz_frequency_analyzer_get_view(subghz->subghz_frequency_analyzer));
// Frequency Analyzer
subghz->subghz_frequency_analyzer = subghz_frequency_analyzer_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdFrequencyAnalyzer,
subghz_frequency_analyzer_get_view(subghz->subghz_frequency_analyzer));
// Carrier Test Module
subghz->subghz_test_carrier = subghz_test_carrier_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdTestCarrier,
subghz_test_carrier_get_view(subghz->subghz_test_carrier));
}
// Read RAW
subghz->subghz_read_raw = subghz_read_raw_alloc();
subghz->subghz_read_raw = subghz_read_raw_alloc(alloc_for_tx_only);
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdReadRAW,
subghz_read_raw_get_view(subghz->subghz_read_raw));
// Carrier Test Module
subghz->subghz_test_carrier = subghz_test_carrier_alloc();
view_dispatcher_add_view(
subghz->view_dispatcher,
SubGhzViewIdTestCarrier,
subghz_test_carrier_get_view(subghz->subghz_test_carrier));
#if FURI_DEBUG
// Packet Test
subghz->subghz_test_packet = subghz_test_packet_alloc();
view_dispatcher_add_view(
@@ -169,24 +177,64 @@ SubGhz* subghz_alloc() {
subghz->view_dispatcher,
SubGhzViewIdStatic,
subghz_test_static_get_view(subghz->subghz_test_static));
#endif
//init setting
subghz->setting = subghz_setting_alloc();
subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user"));
if(alloc_for_tx_only) {
subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user"), false);
} else {
subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user"), true);
}
// Load last used values for Read, Read RAW, etc. or default
if(!alloc_for_tx_only) {
subghz->last_settings = subghz_last_settings_alloc();
subghz_last_settings_load(
subghz->last_settings, subghz_setting_get_preset_count(subghz->setting));
#if FURI_DEBUG
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
FURI_LOG_D(
TAG,
"last frequency: %d, preset: %d, detect_raw: %d",
subghz->last_settings->frequency,
subghz->last_settings->preset,
subghz->last_settings->detect_raw);
#else
FURI_LOG_D(
TAG,
"last frequency: %d, preset: %d",
subghz->last_settings->frequency,
subghz->last_settings->preset);
#endif
#endif
subghz_setting_set_default_frequency(subghz->setting, subghz->last_settings->frequency);
}
//init Worker & Protocol & History & KeyBoard
subghz->lock = SubGhzLockOff;
subghz->txrx = malloc(sizeof(SubGhzTxRx));
subghz->txrx->preset = malloc(sizeof(SubGhzPresetDefinition));
string_init(subghz->txrx->preset->name);
subghz_preset_init(
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
if(!alloc_for_tx_only) {
subghz_preset_init(
subghz,
subghz_setting_get_preset_name(subghz->setting, subghz->last_settings->preset),
subghz->last_settings->frequency,
NULL,
0);
} else {
subghz_preset_init(
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
}
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
subghz->txrx->history = subghz_history_alloc();
if(!alloc_for_tx_only) {
subghz->txrx->history = subghz_history_alloc();
}
subghz->txrx->worker = subghz_worker_alloc();
subghz->txrx->fff_data = flipper_format_string_alloc();
subghz->txrx->secure_data = malloc(sizeof(SecureData));
@@ -195,8 +243,13 @@ SubGhz* subghz_alloc() {
subghz->txrx->environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
#endif
subghz_worker_set_overrun_callback(
subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset);
@@ -210,7 +263,7 @@ SubGhz* subghz_alloc() {
return subghz;
}
void subghz_free(SubGhz* subghz) {
void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) {
furi_assert(subghz);
if(subghz->rpc_ctx) {
@@ -220,57 +273,60 @@ void subghz_free(SubGhz* subghz) {
subghz->rpc_ctx = NULL;
}
#if FURI_DEBUG
// Packet Test
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestPacket);
subghz_test_packet_free(subghz->subghz_test_packet);
// Carrier Test
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestCarrier);
subghz_test_carrier_free(subghz->subghz_test_carrier);
// Static
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdStatic);
subghz_test_static_free(subghz->subghz_test_static);
#endif
// Receiver
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdReceiver);
subghz_view_receiver_free(subghz->subghz_receiver);
if(!alloc_for_tx_only) {
// Carrier Test
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestCarrier);
subghz_test_carrier_free(subghz->subghz_test_carrier);
// TextInput
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTextInput);
text_input_free(subghz->text_input);
// Receiver
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdReceiver);
subghz_view_receiver_free(subghz->subghz_receiver);
// ByteInput
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
byte_input_free(subghz->byte_input);
// TextInput
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTextInput);
text_input_free(subghz->text_input);
// Custom Widget
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdWidget);
widget_free(subghz->widget);
// ByteInput
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
byte_input_free(subghz->byte_input);
// Custom Widget
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdWidget);
widget_free(subghz->widget);
}
//Dialog
furi_record_close(RECORD_DIALOGS);
// Transmitter
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTransmitter);
subghz_view_transmitter_free(subghz->subghz_transmitter);
if(!alloc_for_tx_only) {
// Variable Item List
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
variable_item_list_free(subghz->variable_item_list);
// Variable Item List
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
variable_item_list_free(subghz->variable_item_list);
// Frequency Analyzer
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdFrequencyAnalyzer);
subghz_frequency_analyzer_free(subghz->subghz_frequency_analyzer);
// Frequency Analyzer
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdFrequencyAnalyzer);
subghz_frequency_analyzer_free(subghz->subghz_frequency_analyzer);
}
// Read RAW
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdReadRAW);
subghz_read_raw_free(subghz->subghz_read_raw);
// Submenu
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdMenu);
submenu_free(subghz->submenu);
if(!alloc_for_tx_only) {
// Submenu
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdMenu);
submenu_free(subghz->submenu);
}
// Popup
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdPopup);
popup_free(subghz->popup);
@@ -287,13 +343,21 @@ void subghz_free(SubGhz* subghz) {
//setting
subghz_setting_free(subghz->setting);
if(!alloc_for_tx_only) {
subghz_last_settings_free(subghz->last_settings);
}
//Worker & Protocol & History
subghz_receiver_free(subghz->txrx->receiver);
subghz_environment_free(subghz->txrx->environment);
subghz_worker_free(subghz->txrx->worker);
flipper_format_free(subghz->txrx->fff_data);
subghz_history_free(subghz->txrx->history);
if(!alloc_for_tx_only) {
subghz_history_free(subghz->txrx->history);
}
string_clear(subghz->txrx->preset->name);
free(subghz->txrx->preset);
free(subghz->txrx->secure_data);
@@ -315,7 +379,20 @@ void subghz_free(SubGhz* subghz) {
}
int32_t subghz_app(void* p) {
SubGhz* subghz = subghz_alloc();
bool alloc_for_tx;
if(p && strlen(p)) {
alloc_for_tx = true;
} else {
alloc_for_tx = false;
}
SubGhz* subghz = subghz_alloc(alloc_for_tx);
if(alloc_for_tx) {
subghz->raw_send_only = true;
} else {
subghz->raw_send_only = false;
}
//Load database
bool load_database = subghz_environment_load_keystore(
@@ -374,7 +451,7 @@ int32_t subghz_app(void* p) {
furi_hal_power_suppress_charge_exit();
subghz_free(subghz);
subghz_free(subghz, alloc_for_tx);
return 0;
}

View File

@@ -1,14 +1,28 @@
#include "subghz_history.h"
#include "subghz_history_private.h"
#include <lib/subghz/receiver.h>
#include <furi.h>
#include <m-string.h>
#include <flipper_format/flipper_format_i.h>
#define SUBGHZ_HISTORY_MAX 65
/**
* @brief Settings for temporary files
*
*/
#define SUBGHZ_HISTORY_TMP_DIR EXT_PATH("subghz/tmp_history")
#define SUBGHZ_HISTORY_TMP_EXTENSION ".tmp"
#define SUBGHZ_HISTORY_TMP_SIGNAL_MAX_LEVEL_DURATION 700
#define SUBGHZ_HISTORY_TMP_SIGNAL_MIN_LEVEL_DURATION 100
#define SUBGHZ_HISTORY_TMP_REMOVE_FILES false
#define SUBGHZ_HISTORY_TMP_RAW_KEY "RAW_Data"
#define TAG "SubGhzHistory"
typedef struct {
string_t item_str;
FlipperFormat* flipper_string;
string_t protocol_name;
bool is_file;
uint8_t type;
SubGhzPresetDefinition* preset;
} SubGhzHistoryItem;
@@ -26,30 +40,143 @@ struct SubGhzHistory {
uint16_t last_index_write;
uint8_t code_last_hash_data;
string_t tmp_string;
bool write_tmp_files;
Storage* storage;
SubGhzHistoryStruct* history;
};
#ifdef FURI_DEBUG
#define LOG_DELAY 0
#endif
void subghz_history_generate_temp_filename(string_t filename, uint32_t index) {
FuriHalRtcDateTime datetime = {0};
furi_hal_rtc_get_datetime(&datetime);
string_init_printf(filename, "%03d%s", index, SUBGHZ_HISTORY_TMP_EXTENSION);
}
bool subghz_history_is_tmp_dir_exists(SubGhzHistory* instance) {
FileInfo file_info;
storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &file_info);
if(storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &file_info) == FSE_OK) {
if(file_info.flags & FSF_DIRECTORY) {
return true;
}
}
return false;
}
bool subghz_history_check_sdcard(SubGhzHistory* instance) {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "check_sdcard");
uint32_t start_time = furi_get_tick();
#endif
bool result = false;
// Stage 0 - check SD Card
FS_Error status = storage_sd_status(instance->storage);
if(status == FSE_OK) {
result = subghz_history_is_tmp_dir_exists(instance);
if(!subghz_history_is_tmp_dir_exists(instance)) {
result = storage_simply_mkdir(instance->storage, SUBGHZ_HISTORY_TMP_DIR);
}
} else {
FURI_LOG_W(TAG, "SD storage not installed! Status: %d", status);
}
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Running time (check_sdcard): %d ms", furi_get_tick() - start_time);
#endif
return result;
}
void subghz_history_clear_tmp_dir(SubGhzHistory* instance) {
furi_assert(instance);
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "clear_tmp_dir");
#endif
if(!instance->write_tmp_files) {
// Nothing to do here!
return;
}
uint32_t start_time = furi_get_tick();
#ifdef SUBGHZ_HISTORY_TMP_REMOVE_FILES
// Stage 0 - Dir exists?
bool res = subghz_history_is_tmp_dir_exists(instance);
if(res) {
// Stage 1 - delete all content if exists
FileInfo fileinfo;
storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &fileinfo);
res = fileinfo.flags & FSF_DIRECTORY ?
storage_simply_remove_recursive(instance->storage, SUBGHZ_HISTORY_TMP_DIR) :
(storage_common_remove(instance->storage, SUBGHZ_HISTORY_TMP_DIR) == FSE_OK);
}
// Stage 2 - create dir if necessary
res = !storage_simply_mkdir(instance->storage, SUBGHZ_HISTORY_TMP_DIR);
if(!res) {
FURI_LOG_E(TAG, "Cannot process temp dir!");
}
#endif
uint32_t stop_time = furi_get_tick() - start_time;
FURI_LOG_I(TAG, "Running time (clear_tmp_dir): %d ms", stop_time);
}
SubGhzHistory* subghz_history_alloc(void) {
SubGhzHistory* instance = malloc(sizeof(SubGhzHistory));
string_init(instance->tmp_string);
instance->history = malloc(sizeof(SubGhzHistoryStruct));
SubGhzHistoryItemArray_init(instance->history->data);
instance->storage = furi_record_open(RECORD_STORAGE);
instance->write_tmp_files = subghz_history_check_sdcard(instance);
if(!instance->write_tmp_files) {
FURI_LOG_E(TAG, "Unstable work! Cannot use SD Card!");
}
return instance;
}
void subghz_history_item_free(void* current_item) {
furi_assert(current_item);
SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item;
string_clear(item->item_str);
string_clear(item->preset->name);
string_clear(item->protocol_name);
free(item->preset);
item->type = 0;
item->is_file = false;
if(item->flipper_string != NULL) {
flipper_format_free(item->flipper_string);
}
}
void subghz_history_clean_item_array(SubGhzHistory* instance) {
for
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
subghz_history_item_free(item);
}
}
void subghz_history_free(SubGhzHistory* instance) {
furi_assert(instance);
string_clear(instance->tmp_string);
for
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
string_clear(item->item_str);
string_clear(item->preset->name);
free(item->preset);
flipper_format_free(item->flipper_string);
item->type = 0;
}
subghz_history_clean_item_array(instance);
SubGhzHistoryItemArray_clear(instance->history->data);
free(instance->history);
// Delete all temporary file, on exit it's ok
subghz_history_clear_tmp_dir(instance);
furi_record_close(RECORD_STORAGE);
free(instance);
}
@@ -74,14 +201,9 @@ const char* subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) {
void subghz_history_reset(SubGhzHistory* instance) {
furi_assert(instance);
string_reset(instance->tmp_string);
for
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
string_clear(item->item_str);
string_clear(item->preset->name);
free(item->preset);
flipper_format_free(item->flipper_string);
item->type = 0;
}
subghz_history_clean_item_array(instance);
SubGhzHistoryItemArray_reset(instance->history->data);
instance->last_index_write = 0;
instance->code_last_hash_data = 0;
@@ -101,12 +223,8 @@ uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx)
const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t idx) {
furi_assert(instance);
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
flipper_format_rewind(item->flipper_string);
if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) {
FURI_LOG_E(TAG, "Missing Protocol");
string_reset(instance->tmp_string);
}
return string_get_cstr(instance->tmp_string);
return string_get_cstr(item->protocol_name);
}
FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx) {
@@ -115,17 +233,67 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx
if(item->flipper_string) {
return item->flipper_string;
} else {
return NULL;
bool result_ok = false;
if(instance->write_tmp_files && item->is_file) {
// We have files!
string_t filename;
string_t dir_path;
string_init(filename);
string_init(dir_path);
subghz_history_generate_temp_filename(filename, idx);
string_init_printf(
dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, string_get_cstr(filename));
if(storage_file_exists(instance->storage, string_get_cstr(dir_path))) {
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "Exist: %s", dir_path);
furi_delay_ms(LOG_DELAY);
#endif
// Set to current anyway it has NULL value
item->flipper_string = flipper_format_string_alloc();
Stream* dst_stream = flipper_format_get_raw_stream(item->flipper_string);
stream_clean(dst_stream);
size_t size = stream_load_from_file(
dst_stream, instance->storage, string_get_cstr(dir_path));
if(size > 0) {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save ok!");
furi_delay_ms(LOG_DELAY);
#endif
// We changed contents of file, so we no needed to load
// content from disk for the next time
item->is_file = false;
result_ok = true;
} else {
FURI_LOG_E(TAG, "Stream copy failed!");
flipper_format_free(item->flipper_string);
}
} else {
FURI_LOG_E(TAG, "Can't convert filename to file");
}
string_clear(filename);
string_clear(dir_path);
} else {
#ifdef FURI_DEBUG
FURI_LOG_W(TAG, "Write TMP files failed!");
furi_delay_ms(LOG_DELAY);
#endif
}
return result_ok ? item->flipper_string : NULL;
}
}
bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output) {
furi_assert(instance);
if(instance->last_index_write == SUBGHZ_HISTORY_MAX) {
if(output != NULL) string_printf(output, "Memory is FULL");
return true;
}
if(output != NULL)
if(output != NULL) {
string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX);
}
return false;
}
@@ -141,7 +309,9 @@ bool subghz_history_add_to_history(
furi_assert(instance);
furi_assert(context);
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false;
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) {
return false;
}
SubGhzProtocolDecoderBase* decoder_base = context;
if((instance->code_last_hash_data ==
@@ -153,7 +323,6 @@ bool subghz_history_add_to_history(
instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base);
instance->last_update_timestamp = furi_get_tick();
string_t text;
string_init(text);
SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data);
@@ -166,6 +335,11 @@ bool subghz_history_add_to_history(
item->preset->data_size = preset->data_size;
string_init(item->item_str);
string_init(item->protocol_name);
bool tmp_file_for_raw = false;
// At this point file mapped to memory otherwise file cannot decode
item->flipper_string = flipper_format_string_alloc();
subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset);
@@ -177,6 +351,8 @@ bool subghz_history_add_to_history(
if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) {
FURI_LOG_E(TAG, "Missing Protocol");
break;
} else {
string_init_printf(item->protocol_name, "%s", string_get_cstr(instance->tmp_string));
}
if(!strcmp(string_get_cstr(instance->tmp_string), "RAW")) {
string_printf(
@@ -188,7 +364,7 @@ bool subghz_history_add_to_history(
if(!flipper_format_rewind(item->flipper_string)) {
FURI_LOG_E(TAG, "Rewind error");
}
tmp_file_for_raw = true;
break;
} else if(!strcmp(string_get_cstr(instance->tmp_string), "KeeLoq")) {
string_set_str(instance->tmp_string, "KL ");
@@ -234,7 +410,72 @@ bool subghz_history_add_to_history(
}
} while(false);
// If we can write to files
if(instance->write_tmp_files && tmp_file_for_raw) {
string_t filename;
string_t dir_path;
string_init(filename);
string_init(dir_path);
subghz_history_generate_temp_filename(filename, instance->last_index_write);
string_cat_printf(dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, string_get_cstr(filename));
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save temp file: %s", string_get_cstr(dir_path));
#endif
if(!subghz_history_tmp_write_file_split(instance, item, dir_path)) {
// Plan B!
subghz_history_tmp_write_file_full(instance, item, dir_path);
}
string_clear(filename);
string_clear(dir_path);
} else {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Old fashion way");
#endif
}
string_clear(text);
instance->last_index_write++;
return true;
}
bool subghz_history_tmp_write_file_split(
SubGhzHistory* instance,
void* current_item,
string_t dir_path) {
UNUSED(instance);
UNUSED(current_item);
UNUSED(dir_path);
/*furi_assert(instance);
furi_assert(current_item);
furi_assert(dir_path);*/
//SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item;
return false;
}
void subghz_history_tmp_write_file_full(
SubGhzHistory* instance,
void* current_item,
string_t dir_path) {
SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item;
#ifdef FURI_DEBUG
FURI_LOG_W(TAG, "Save temp file full: %s", string_get_cstr(dir_path));
#endif
Stream* dst = flipper_format_get_raw_stream(item->flipper_string);
stream_rewind(dst);
if(stream_save_to_file(dst, instance->storage, string_get_cstr(dir_path), FSOM_CREATE_ALWAYS) >
0) {
flipper_format_free(item->flipper_string);
item->flipper_string = NULL;
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save done!");
#endif
// This item contains fake data to load from SD
item->is_file = true;
} else {
FURI_LOG_E(TAG, "Stream copy failed!");
}
}

View File

@@ -0,0 +1,79 @@
#pragma once
#include "subghz_history.h"
/**
* @brief Generate filename like 000.tmp
*
* @param filename - input parameter
* @param index - index of file, timestamp doesn't accepted!
*/
void subghz_history_generate_temp_filename(string_t filename, uint32_t index);
/**
* @brief Check if directory for temporary files is exists
*
* @param instance SubGhzHistory*
* @return true
* @return false
*/
bool subghz_history_is_tmp_dir_exists(SubGhzHistory* instance);
/**
* @brief Check SD card and create temporary dir if not exists,
* Result write_tmp_files without this unstable work is GUARANTEED
*
* @param instance - SubGhzHistory*
* @return - true all ok
* @return - false we have a problems
*/
bool subghz_history_check_sdcard(SubGhzHistory* instance);
/**
* @brief Recursive delete dir and files and create new temp dir
*
* @param instance - SubGhzHistory*
* @return true - if all ok
* @return false - if something failed
*/
void subghz_history_clear_tmp_dir(SubGhzHistory* instance);
/**
* @brief Free item and free all resources
*
* @param current_item - SubGhzHistoryItem*
*/
void subghz_history_item_free(void* current_item);
/**
* @brief free all items in array
*
* @param instance
*/
void subghz_history_clean_item_array(SubGhzHistory* instance);
/**
* @brief Write temp file fully, without spliting
*
* @param instance - SubGhzHistory*
* @param current_item - SubGhzHistoryItem*
* @param dir_path - full path to file
*/
void subghz_history_tmp_write_file_full(
SubGhzHistory* instance,
void* current_item,
string_t dir_path);
/**
* @brief Write temp splited to lines
*
* @param instance - SubGhzHistory*
* @param current_item - SubGhzHistoryItem*
* @param dir_path - full path to file
* @return true - file saved
* @return false - error occured
*/
bool subghz_history_tmp_write_file_split(
SubGhzHistory* instance,
void* current_item,
string_t dir_path);

View File

@@ -7,10 +7,11 @@
#include "views/subghz_frequency_analyzer.h"
#include "views/subghz_read_raw.h"
#include "views/subghz_test_static.h"
#include "views/subghz_test_carrier.h"
#if FURI_DEBUG
#include "views/subghz_test_static.h"
#include "views/subghz_test_packet.h"
#endif
// #include <furi.h>
// #include <furi_hal.h>
#include <gui/gui.h>
@@ -33,6 +34,7 @@
#include "subghz_history.h"
#include "subghz_setting.h"
#include "subghz_last_settings.h"
#include <gui/modules/variable_item_list.h>
#include <lib/toolbox/path.h>
@@ -95,15 +97,18 @@ struct SubGhz {
SubGhzFrequencyAnalyzer* subghz_frequency_analyzer;
SubGhzReadRAW* subghz_read_raw;
SubGhzTestStatic* subghz_test_static;
bool raw_send_only;
SubGhzTestCarrier* subghz_test_carrier;
#if FURI_DEBUG
SubGhzTestStatic* subghz_test_static;
SubGhzTestPacket* subghz_test_packet;
#endif
string_t error_str;
SubGhzSetting* setting;
SubGhzLastSettings* last_settings;
SubGhzLock lock;
bool in_decoder_scene;
void* rpc_ctx;
};

View File

@@ -0,0 +1,153 @@
#include "subghz_last_settings.h"
#include "subghz_i.h"
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
#include <lib/subghz/protocols/raw.h>
#endif
#define TAG "SubGhzLastSettings"
#define SUBGHZ_LAST_SETTING_FILE_TYPE "Flipper SubGhz Last Setting File"
#define SUBGHZ_LAST_SETTING_FILE_VERSION 1
#define SUBGHZ_LAST_SETTINGS_PATH EXT_PATH("subghz/assets/last_subghz.settings")
// 1 = "AM650"
// "AM270", "AM650", "FM238", "FM476",
#define SUBGHZ_LAST_SETTING_DEFAULT_PRESET 1
#define SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY 433920000
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
#define SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW 0
#define SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW "DetectRaw"
#endif
#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY "Frequency"
#define SUBGHZ_LAST_SETTING_FIELD_PRESET "Preset"
SubGhzLastSettings* subghz_last_settings_alloc(void) {
SubGhzLastSettings* instance = malloc(sizeof(SubGhzLastSettings));
return instance;
}
void subghz_last_settings_free(SubGhzLastSettings* instance) {
furi_assert(instance);
free(instance);
}
void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count) {
furi_assert(instance);
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "subghz_last_settings_load");
#endif
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
uint32_t temp_frequency = 0;
int32_t temp_preset = 0;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
uint32_t temp_read_raw = 0;
#endif
if(FSE_OK == storage_sd_status(storage) && SUBGHZ_LAST_SETTINGS_PATH &&
flipper_format_file_open_existing(fff_data_file, SUBGHZ_LAST_SETTINGS_PATH)) {
flipper_format_read_int32(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_PRESET, (int32_t*)&temp_preset, 1);
flipper_format_read_uint32(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, (uint32_t*)&temp_frequency, 1);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
flipper_format_read_uint32(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, (uint32_t*)&temp_read_raw, 1);
#endif
} else {
FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH);
}
if(temp_frequency == 0 || !furi_hal_subghz_is_tx_allowed(temp_frequency)) {
FURI_LOG_W(TAG, "Last used frequency not found or can't be used!");
instance->frequency = SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY;
instance->preset = SUBGHZ_LAST_SETTING_DEFAULT_PRESET;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
instance->detect_raw = SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW;
#endif
} else {
instance->frequency = temp_frequency;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
instance->detect_raw = temp_read_raw;
#endif
if(temp_preset > (int32_t)preset_count - 1 || temp_preset < 0) {
FURI_LOG_W(TAG, "Last used preset no found");
instance->preset = SUBGHZ_LAST_SETTING_DEFAULT_PRESET;
} else {
instance->preset = temp_preset;
}
}
flipper_format_file_close(fff_data_file);
flipper_format_free(fff_data_file);
furi_record_close(RECORD_STORAGE);
}
bool subghz_last_settings_save(SubGhzLastSettings* instance) {
furi_assert(instance);
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "last_settings_save");
#endif
bool saved = false;
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* file = flipper_format_file_alloc(storage);
do {
if(FSE_OK != storage_sd_status(storage)) {
break;
}
// Open file
if(!flipper_format_file_open_always(file, SUBGHZ_LAST_SETTINGS_PATH)) break;
// Write header
if(!flipper_format_write_header_cstr(
file, SUBGHZ_LAST_SETTING_FILE_TYPE, SUBGHZ_LAST_SETTING_FILE_VERSION))
break;
if(!flipper_format_insert_or_update_int32(
file, SUBGHZ_LAST_SETTING_FIELD_PRESET, &instance->preset, 1)) {
break;
}
if(!flipper_format_insert_or_update_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, &instance->frequency, 1)) {
break;
}
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
if(!flipper_format_insert_or_update_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, &instance->detect_raw, 1)) {
break;
}
#endif
saved = true;
} while(0);
if(!saved) {
FURI_LOG_E(TAG, "Error save file %s", SUBGHZ_LAST_SETTINGS_PATH);
}
flipper_format_file_close(file);
flipper_format_free(file);
furi_record_close(RECORD_STORAGE);
return saved;
}
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
void subghz_last_settings_set_detect_raw_values(void* context) {
furi_assert(context);
SubGhz* instance = (SubGhz*)context;
bool is_detect_raw = instance->last_settings->detect_raw > 0;
subghz_receiver_set_filter(
instance->txrx->receiver, is_detect_raw ? DETECT_RAW_TRUE : DETECT_RAW_FALSE);
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
instance->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
is_detect_raw);
}
#endif

View File

@@ -0,0 +1,33 @@
#pragma once
// Enable saving detect raw setting state
// #define SUBGHZ_SAVE_DETECT_RAW_SETTING 1
#include <furi_hal.h>
#include <stdint.h>
#include <stdbool.h>
#include <storage/storage.h>
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
#include <lib/subghz/protocols/base.h>
#define DETECT_RAW_FALSE SubGhzProtocolFlag_Decodable
#define DETECT_RAW_TRUE SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW
#endif
typedef struct {
uint32_t frequency;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
uint32_t detect_raw;
#endif
int32_t preset;
} SubGhzLastSettings;
SubGhzLastSettings* subghz_last_settings_alloc(void);
void subghz_last_settings_free(SubGhzLastSettings* instance);
void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count);
bool subghz_last_settings_save(SubGhzLastSettings* instance);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
void subghz_last_settings_set_detect_raw_values(void* context);
#endif

View File

@@ -181,7 +181,7 @@ void subghz_setting_load_default(SubGhzSetting* instance) {
instance, subghz_frequency_list, subghz_hopper_frequency_list);
}
void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
void subghz_setting_load(SubGhzSetting* instance, const char* file_path, bool not_skip_frequencies) {
furi_assert(instance);
Storage* storage = furi_record_open(RECORD_STORAGE);
@@ -214,59 +214,56 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
}
// Standard frequencies (optional)
temp_bool = true;
flipper_format_read_bool(fff_data_file, "Add_standard_frequencies", &temp_bool, 1);
if(!temp_bool) {
FURI_LOG_I(TAG, "Removing standard frequencies");
FrequencyList_reset(instance->frequencies);
FrequencyList_reset(instance->hopper_frequencies);
} else {
FURI_LOG_I(TAG, "Keeping standard frequencies");
}
// Load frequencies
if(!flipper_format_rewind(fff_data_file)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
while(flipper_format_read_uint32(
fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) {
if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32);
FrequencyList_push_back(instance->frequencies, temp_data32);
if(not_skip_frequencies) {
temp_bool = true;
flipper_format_read_bool(fff_data_file, "Add_standard_frequencies", &temp_bool, 1);
if(!temp_bool) {
FURI_LOG_I(TAG, "Removing standard frequencies");
FrequencyList_reset(instance->frequencies);
FrequencyList_reset(instance->hopper_frequencies);
} else {
FURI_LOG_E(TAG, "Frequency not supported %lu", temp_data32);
FURI_LOG_I(TAG, "Keeping standard frequencies");
}
}
// Load hopper frequencies
if(!flipper_format_rewind(fff_data_file)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
while(flipper_format_read_uint32(
fff_data_file, "Hopper_frequency", (uint32_t*)&temp_data32, 1)) {
if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
FURI_LOG_I(TAG, "Hopper frequency loaded %lu", temp_data32);
FrequencyList_push_back(instance->hopper_frequencies, temp_data32);
} else {
FURI_LOG_E(TAG, "Hopper frequency not supported %lu", temp_data32);
// Load frequencies
if(!flipper_format_rewind(fff_data_file)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
}
// Default frequency (optional)
if(!flipper_format_rewind(fff_data_file)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
if(flipper_format_read_uint32(fff_data_file, "Default_frequency", &temp_data32, 1)) {
for
M_EACH(frequency, instance->frequencies, FrequencyList_t) {
*frequency &= FREQUENCY_MASK;
if(*frequency == temp_data32) {
*frequency |= FREQUENCY_FLAG_DEFAULT;
}
while(flipper_format_read_uint32(
fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) {
if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32);
FrequencyList_push_back(instance->frequencies, temp_data32);
} else {
FURI_LOG_E(TAG, "Frequency not supported %lu", temp_data32);
}
}
// Load hopper frequencies
if(!flipper_format_rewind(fff_data_file)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
while(flipper_format_read_uint32(
fff_data_file, "Hopper_frequency", (uint32_t*)&temp_data32, 1)) {
if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
FURI_LOG_I(TAG, "Hopper frequency loaded %lu", temp_data32);
FrequencyList_push_back(instance->hopper_frequencies, temp_data32);
} else {
FURI_LOG_E(TAG, "Hopper frequency not supported %lu", temp_data32);
}
}
// Default frequency (optional)
if(!flipper_format_rewind(fff_data_file)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
if(flipper_format_read_uint32(
fff_data_file, "Default_frequency", &temp_data32, 1)) {
subghz_setting_set_default_frequency(instance, temp_data32);
}
}
// custom preset (optional)
@@ -294,6 +291,16 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
}
}
void subghz_setting_set_default_frequency(SubGhzSetting* instance, uint32_t frequency_to_setup) {
for
M_EACH(frequency, instance->frequencies, FrequencyList_t) {
*frequency &= FREQUENCY_MASK;
if(*frequency == frequency_to_setup) {
*frequency |= FREQUENCY_FLAG_DEFAULT;
}
}
}
size_t subghz_setting_get_frequency_count(SubGhzSetting* instance) {
furi_assert(instance);
return FrequencyList_size(instance->frequencies);
@@ -311,6 +318,9 @@ size_t subghz_setting_get_preset_count(SubGhzSetting* instance) {
const char* subghz_setting_get_preset_name(SubGhzSetting* instance, size_t idx) {
furi_assert(instance);
if(idx >= SubGhzSettingCustomPresetItemArray_size(instance->preset->data)) {
idx = 0;
}
SubGhzSettingCustomPresetItem* item =
SubGhzSettingCustomPresetItemArray_get(instance->preset->data, idx);
return string_get_cstr(item->custom_preset_name);

View File

@@ -14,7 +14,7 @@ SubGhzSetting* subghz_setting_alloc(void);
void subghz_setting_free(SubGhzSetting* instance);
void subghz_setting_load(SubGhzSetting* instance, const char* file_path);
void subghz_setting_load(SubGhzSetting* instance, const char* file_path, bool not_skip_frequencies);
size_t subghz_setting_get_frequency_count(SubGhzSetting* instance);
@@ -46,3 +46,5 @@ uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx
uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance);
uint32_t subghz_setting_get_default_frequency(SubGhzSetting* instance);
void subghz_setting_set_default_frequency(SubGhzSetting* instance, uint32_t frequency_to_setup);

View File

@@ -30,6 +30,32 @@ static const NotificationSequence sequence_hw_blink_stop = {
NULL,
};
static const NotificationSequence sequence_saved = {
&message_blink_stop,
&message_blue_0,
&message_green_255,
&message_red_0,
&message_vibro_on,
&message_delay_100,
&message_vibro_off,
NULL,
};
//static const NotificationSequence sequence_not_saved = {
// &message_blink_stop,
// &message_green_255,
// &message_blue_255,
// &message_red_255,
// NULL,
//};
static const uint32_t subghz_frequency_list[] = {
300000000, 302757000, 303875000, 304250000, 307000000, 307500000, 307800000,
309000000, 310000000, 312000000, 312100000, 313000000, 313850000, 314000000,
314350000, 315000000, 318000000, 345000000, 348000000, 387000000, 390000000,
418000000, 433075000, 433220000, 433420000, 433657070, 433889000, 433920000,
434176948, 434420000, 434775000, 438900000, 464000000, 779000000, 868350000,
868400000, 868950000, 906400000, 915000000, 925000000, 928000000};
typedef enum {
SubGhzFrequencyAnalyzerStatusIDLE,
} SubGhzFrequencyAnalyzerStatus;
@@ -50,6 +76,7 @@ struct SubGhzFrequencyAnalyzer {
typedef struct {
uint32_t frequency;
uint32_t frequency_last;
uint32_t frequency_to_save;
float rssi;
float rssi_last;
float trigger;
@@ -163,6 +190,33 @@ void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel
elements_button_right(canvas, "T+");
}
uint32_t subghz_frequency_find_correct(uint32_t input) {
uint32_t prev_freq = 0;
uint32_t current = 0;
uint32_t result = 0;
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "input: %d", input);
#endif
for(size_t i = 0; i < sizeof(subghz_frequency_list); i++) {
current = subghz_frequency_list[i];
if(current == input) {
result = current;
break;
}
if(current > input && prev_freq < input) {
if(current - input < input - prev_freq) {
result = current;
} else {
result = prev_freq;
}
break;
}
prev_freq = current;
}
return result;
}
bool subghz_frequency_analyzer_input(InputEvent* event, void* context) {
furi_assert(context);
SubGhzFrequencyAnalyzer* instance = context;
@@ -201,6 +255,69 @@ bool subghz_frequency_analyzer_input(InputEvent* event, void* context) {
need_redraw = true;
}
if(event->key == InputKeyOk) {
bool updated = false;
with_view_model(
instance->view, (SubGhzFrequencyAnalyzerModel * model) {
uint32_t prev_freq_to_save = model->frequency_to_save;
uint32_t frequency_candidate = 0;
if(model->frequency != 0) {
frequency_candidate = model->frequency;
} else if(model->frequency_last != 0) {
frequency_candidate = model->frequency_last;
}
if(frequency_candidate == 0 ||
!furi_hal_subghz_is_frequency_valid(frequency_candidate) ||
prev_freq_to_save == frequency_candidate) {
frequency_candidate = 0;
} else {
frequency_candidate = subghz_frequency_find_correct(frequency_candidate);
}
if(frequency_candidate > 0 && frequency_candidate != model->frequency_to_save) {
#ifdef FURI_DEBUG
FURI_LOG_D(
TAG,
"frequency_to_save: %d, candidate: %d",
model->frequency_to_save,
frequency_candidate);
#endif
model->frequency_to_save = frequency_candidate;
notification_message(instance->notifications, &sequence_saved);
notification_message(instance->notifications, &sequence_hw_blink);
updated = true;
}
return true;
});
#ifdef FURI_DEBUG
FURI_LOG_I(
TAG,
"updated: %d, long: %d, type: %d",
updated,
(event->type == InputTypeLong),
event->type);
#endif
if(updated) {
instance->callback(SubGhzCustomEventViewReceiverOK, instance->context);
}
// First device receive short, then when user release button we get long
if(event->type == InputTypeLong) {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Longpress!");
#endif
// Stop blinking
notification_message(instance->notifications, &sequence_hw_blink_stop);
// Stop worker
if(subghz_frequency_analyzer_worker_is_running(instance->worker)) {
subghz_frequency_analyzer_worker_stop(instance->worker);
}
instance->callback(SubGhzCustomEventViewReceiverUnlock, instance->context);
}
}
if(need_redraw) {
SubGhzFrequencyAnalyzer* instance = context;
with_view_model(
@@ -250,11 +367,13 @@ void subghz_frequency_analyzer_pair_callback(void* context, uint32_t frequency,
switch(instance->feedback_level) {
case 1: // 1 - only vibro
notification_message(instance->notifications, &sequence_single_vibro);
notification_message(instance->notifications, &sequence_display_backlight_on);
break;
case 2: // 2 - vibro and beep
notification_message(instance->notifications, &sequence_success);
break;
default: // 0 - no feedback
notification_message(instance->notifications, &sequence_display_backlight_on);
break;
}
@@ -309,6 +428,7 @@ void subghz_frequency_analyzer_enter(void* context) {
model->rssi_last = 0;
model->frequency = 0;
model->frequency_last = 0;
model->frequency_to_save = 0;
model->trigger = RSSI_MIN;
return true;
});
@@ -359,4 +479,16 @@ void subghz_frequency_analyzer_free(SubGhzFrequencyAnalyzer* instance) {
View* subghz_frequency_analyzer_get_view(SubGhzFrequencyAnalyzer* instance) {
furi_assert(instance);
return instance->view;
}
uint32_t subghz_frequency_analyzer_get_frequency_to_save(SubGhzFrequencyAnalyzer* instance) {
furi_assert(instance);
uint32_t frequency;
with_view_model(
instance->view, (SubGhzFrequencyAnalyzerModel * model) {
frequency = model->frequency_to_save;
return false;
});
return frequency;
}

View File

@@ -17,3 +17,5 @@ SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc();
void subghz_frequency_analyzer_free(SubGhzFrequencyAnalyzer* subghz_static);
View* subghz_frequency_analyzer_get_view(SubGhzFrequencyAnalyzer* subghz_static);
uint32_t subghz_frequency_analyzer_get_frequency_to_save(SubGhzFrequencyAnalyzer* instance);

View File

@@ -27,6 +27,7 @@ typedef struct {
uint8_t ind_write;
uint8_t ind_sin;
SubGhzReadRAWStatus status;
bool raw_send_only;
} SubGhzReadRAWModel;
void subghz_read_raw_set_callback(
@@ -232,9 +233,11 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) {
elements_button_right(canvas, "Save");
break;
case SubGhzReadRAWStatusLoadKeyIDLE:
elements_button_left(canvas, "New");
if(!model->raw_send_only) {
elements_button_left(canvas, "New");
elements_button_right(canvas, "More");
}
elements_button_center(canvas, "Send");
elements_button_right(canvas, "More");
elements_text_box(
canvas,
4,
@@ -362,31 +365,35 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
with_view_model(
instance->view, (SubGhzReadRAWModel * model) {
if(model->status == SubGhzReadRAWStatusStart) {
//Config
instance->callback(SubGhzCustomEventViewReadRAWConfig, instance->context);
} else if(
(model->status == SubGhzReadRAWStatusIDLE) ||
(model->status == SubGhzReadRAWStatusLoadKeyIDLE)) {
//Erase
model->status = SubGhzReadRAWStatusStart;
model->rssi_history_end = false;
model->ind_write = 0;
string_set_str(model->sample_write, "0 spl.");
string_reset(model->file_name);
instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context);
if(!model->raw_send_only) {
if(model->status == SubGhzReadRAWStatusStart) {
//Config
instance->callback(SubGhzCustomEventViewReadRAWConfig, instance->context);
} else if(
(model->status == SubGhzReadRAWStatusIDLE) ||
(model->status == SubGhzReadRAWStatusLoadKeyIDLE)) {
//Erase
model->status = SubGhzReadRAWStatusStart;
model->rssi_history_end = false;
model->ind_write = 0;
string_set_str(model->sample_write, "0 spl.");
string_reset(model->file_name);
instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context);
}
}
return true;
});
} else if(event->key == InputKeyRight && event->type == InputTypeShort) {
with_view_model(
instance->view, (SubGhzReadRAWModel * model) {
if(model->status == SubGhzReadRAWStatusIDLE) {
//Save
instance->callback(SubGhzCustomEventViewReadRAWSave, instance->context);
} else if(model->status == SubGhzReadRAWStatusLoadKeyIDLE) {
//More
instance->callback(SubGhzCustomEventViewReadRAWMore, instance->context);
if(!model->raw_send_only) {
if(model->status == SubGhzReadRAWStatusIDLE) {
//Save
instance->callback(SubGhzCustomEventViewReadRAWSave, instance->context);
} else if(model->status == SubGhzReadRAWStatusLoadKeyIDLE) {
//More
instance->callback(SubGhzCustomEventViewReadRAWMore, instance->context);
}
}
return true;
});
@@ -487,7 +494,7 @@ void subghz_read_raw_exit(void* context) {
});
}
SubGhzReadRAW* subghz_read_raw_alloc() {
SubGhzReadRAW* subghz_read_raw_alloc(bool raw_send_only) {
SubGhzReadRAW* instance = malloc(sizeof(SubGhzReadRAW));
// View allocation and configuration
@@ -505,6 +512,7 @@ SubGhzReadRAW* subghz_read_raw_alloc() {
string_init(model->preset_str);
string_init(model->sample_write);
string_init(model->file_name);
model->raw_send_only = raw_send_only;
model->rssi_history = malloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t));
return true;
});

View File

@@ -25,7 +25,7 @@ void subghz_read_raw_set_callback(
SubGhzReadRAWCallback callback,
void* context);
SubGhzReadRAW* subghz_read_raw_alloc();
SubGhzReadRAW* subghz_read_raw_alloc(bool raw_send_only);
void subghz_read_raw_free(SubGhzReadRAW* subghz_static);

View File

@@ -45,7 +45,7 @@ void subghz_view_transmitter_add_data_to_show(
}
static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str) {
const uint8_t button_height = 13;
const uint8_t button_height = 12;
const uint8_t vertical_offset = 3;
const uint8_t horizontal_offset = 1;
const uint8_t string_width = canvas_string_width(canvas, str);
@@ -69,7 +69,10 @@ static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str
canvas_invert_color(canvas);
canvas_draw_icon(
canvas, x + horizontal_offset, y - button_height + vertical_offset, &I_ButtonCenter_7x7);
canvas,
x + horizontal_offset,
y - button_height + vertical_offset - 1,
&I_ButtonCenter_7x7);
canvas_draw_str(
canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str);
canvas_invert_color(canvas);

View File

@@ -178,7 +178,7 @@ void unirfremix_cfg_set_check(UniRFRemix* app, string_t file_name) {
app->right_enabled = 1;
app->ok_enabled = 1;
int label_len = 12;
int label_len = 16;
//check that map file exists
if(!flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_name))) {
@@ -790,7 +790,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
break;
case 1:
canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13);
canvas_draw_icon(canvas, 116, 17, &I_Pin_arrow_up7x9);
canvas_draw_icon(canvas, 116, 17, &I_Pin_arrow_up_7x9);
break;
case 2:
canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13);
@@ -827,7 +827,7 @@ static void input_callback(InputEvent* input_event, void* ctx) {
void unirfremix_subghz_alloc(UniRFRemix* app) {
// load subghz presets
app->setting = subghz_setting_alloc();
subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user"));
subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user"), false);
// load mfcodes
app->environment = subghz_environment_alloc();

View File

@@ -1,5 +1,5 @@
App(
appid="arkanoid_game",
appid="Arkanoid",
name="Arkanoid",
apptype=FlipperAppType.EXTERNAL,
entry_point="arkanoid_game_app",

View File

@@ -1,5 +1,5 @@
App(
appid="barcode_generator",
appid="Barcode_Generator",
name="UPC-A Generator",
apptype=FlipperAppType.EXTERNAL,
entry_point="barcode_UPCA_generator_app",

View File

@@ -1,5 +1,5 @@
App(
appid="bt_hid",
appid="Bluetooth_Remote",
name="Bluetooth Remote",
apptype=FlipperAppType.PLUGIN,
entry_point="bt_hid_app",

View File

@@ -109,7 +109,7 @@ const BtHidKeyboardKey bt_hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = {
{.width = 1, .icon = NULL, .key = "-", .shift_key = "_", .value = HID_KEYBOARD_MINUS},
},
{
{.width = 1, .icon = &I_Pin_arrow_up7x9, .value = HID_KEYBOARD_L_SHIFT},
{.width = 1, .icon = &I_Pin_arrow_up_7x9, .value = HID_KEYBOARD_L_SHIFT},
{.width = 1, .icon = NULL, .key = ",", .shift_key = "<", .value = HID_KEYPAD_COMMA},
{.width = 1, .icon = NULL, .key = ".", .shift_key = ">", .value = HID_KEYBOARD_DOT},
{.width = 4, .icon = NULL, .key = " ", .value = HID_KEYBOARD_SPACEBAR},

View File

@@ -53,7 +53,7 @@ static void bt_hid_mouse_draw_callback(Canvas* canvas, void* context) {
canvas_set_bitmap_mode(canvas, 0);
canvas_set_color(canvas, ColorWhite);
}
canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up7x9);
canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up_7x9);
canvas_set_color(canvas, ColorBlack);
// Down

View File

@@ -1,5 +1,5 @@
App(
appid="game_doom",
appid="DOOM",
name="DOOM",
apptype=FlipperAppType.EXTERNAL,
entry_point="doom_app",

View File

@@ -1,5 +1,5 @@
App(
appid="esp8266_deauth",
appid="ESP8266_Deauther",
name="[ESP8266] Deauther",
apptype=FlipperAppType.EXTERNAL,
entry_point="esp8266_deauth_app",

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