mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-13 05:06:30 +04:00
Compare commits
130 Commits
un1-a6b98c
...
un4-0f9ea9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8b48771e4 | ||
|
|
1424878d65 | ||
|
|
a37b0d464c | ||
|
|
96502e21ae | ||
|
|
b5d6d60535 | ||
|
|
32e64fd29e | ||
|
|
8f9d81b972 | ||
|
|
23e0566273 | ||
|
|
4141483147 | ||
|
|
30e005d5c4 | ||
|
|
e3a2711eb3 | ||
|
|
8569641ce6 | ||
|
|
cafd06c71b | ||
|
|
06a7bda69b | ||
|
|
c43ce93936 | ||
|
|
2288855163 | ||
|
|
c0765c1114 | ||
|
|
683c6254da | ||
|
|
2ef515ef56 | ||
|
|
667be798fc | ||
|
|
0f9598099a | ||
|
|
0d6f729386 | ||
|
|
b452b6fd32 | ||
|
|
9403128a03 | ||
|
|
71589b28a7 | ||
|
|
8b0fa6d0b1 | ||
|
|
cf47da0ff4 | ||
|
|
d6b7fae7e4 | ||
|
|
110dc48b96 | ||
|
|
37c666ddf5 | ||
|
|
6ddca568b9 | ||
|
|
8993db56b8 | ||
|
|
3c1efda1db | ||
|
|
b62b7956a6 | ||
|
|
dce5af5c2e | ||
|
|
fbacdc5b7b | ||
|
|
8dba4f25ae | ||
|
|
43ef4046ed | ||
|
|
1e63f57bf7 | ||
|
|
649887fe0f | ||
|
|
be42c390f2 | ||
|
|
cbda5d996f | ||
|
|
de1ec97512 | ||
|
|
8af749c965 | ||
|
|
4d3f45e911 | ||
|
|
63fee41a1f | ||
|
|
f441fed68d | ||
|
|
6e0eeed773 | ||
|
|
6bf306200e | ||
|
|
e2faf31b45 | ||
|
|
85eb740559 | ||
|
|
cea14ae9c5 | ||
|
|
e9a11cfce0 | ||
|
|
87a14b96e1 | ||
|
|
bbd3f9cf71 | ||
|
|
230f09dddd | ||
|
|
24e744f1d1 | ||
|
|
0f9ea925d3 | ||
|
|
836de3df16 | ||
|
|
c92217a109 | ||
|
|
41c93431c8 | ||
|
|
f0ea8f3a84 | ||
|
|
4d8f294e7a | ||
|
|
f543753873 | ||
|
|
1fb1a68842 | ||
|
|
54fedb9bc8 | ||
|
|
8af9c00ddb | ||
|
|
5a22803bbc | ||
|
|
824f5ea027 | ||
|
|
76d38e832e | ||
|
|
aba20b6af8 | ||
|
|
226f8517f3 | ||
|
|
7df70d7c62 | ||
|
|
9176387b9f | ||
|
|
972c0dcb4a | ||
|
|
62e56e2618 | ||
|
|
f202d27206 | ||
|
|
bcfb12bf28 | ||
|
|
5883e134d4 | ||
|
|
f8b532f063 | ||
|
|
e25b424188 | ||
|
|
4241ad24a3 | ||
|
|
6bcc6f363b | ||
|
|
3dcd8a73f1 | ||
|
|
9ad7f7825d | ||
|
|
aa00606d22 | ||
|
|
9c62e1f6ac | ||
|
|
b934c41ed0 | ||
|
|
0ebb3f060e | ||
|
|
8f2bd3be57 | ||
|
|
cc02d57857 | ||
|
|
0c5f11f713 | ||
|
|
006d27ed93 | ||
|
|
746b732034 | ||
|
|
2ec9aeeefa | ||
|
|
8be08093e2 | ||
|
|
406247c5d8 | ||
|
|
22a87d5707 | ||
|
|
4271246d8a | ||
|
|
a3db6718c2 | ||
|
|
0f0473bee6 | ||
|
|
497be7ccb0 | ||
|
|
12a6290e91 | ||
|
|
e6e1e7fe15 | ||
|
|
cb14d23108 | ||
|
|
c4783664c0 | ||
|
|
91f3774246 | ||
|
|
1f8a034a71 | ||
|
|
8cc3e2f35a | ||
|
|
069dd29f08 | ||
|
|
91c06a2168 | ||
|
|
545c4349d6 | ||
|
|
a40e1a2be2 | ||
|
|
286300b35b | ||
|
|
633145495c | ||
|
|
a0bcbf731d | ||
|
|
60242cd7c4 | ||
|
|
3e9409a1a8 | ||
|
|
a9210b2849 | ||
|
|
a58807c57a | ||
|
|
5bb7cabea6 | ||
|
|
f201062819 | ||
|
|
9f501034c3 | ||
|
|
7bd0c8ff2c | ||
|
|
cdcf80ed05 | ||
|
|
3e3a167764 | ||
|
|
fa9602bd68 | ||
|
|
efb09380bd | ||
|
|
61fee8e269 | ||
|
|
8093721c24 |
3
.vscode/example/launch.json
vendored
3
.vscode/example/launch.json
vendored
@@ -28,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",
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
### New changes
|
||||
* PR: SubGHz bruteforcer plugin - deep refactoring (huge thanks to @derskythe ! | PR #75)
|
||||
* OFW: Preliminary Rust support
|
||||
* Plugins: RFID Fuzzer - ability to change time delay (between cards), useful for slow readers, you can adjust it on the go
|
||||
|
||||
#### **DFU files no longer included in releases to avoid issues with wrong manual installation of assets - use .tgz file with qFlipper, or install automatically via web updater or use 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)
|
||||
|
||||
[- Download qFlipper 1.2.0 (allows .tgz installation) (official link)](https://update.flipperzero.one/builds/qFlipper/1.2.0/)
|
||||
[-> Download qFlipper 1.2.0 (allows .tgz installation) (official link)](https://update.flipperzero.one/builds/qFlipper/1.2.0/)
|
||||
|
||||
**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**
|
||||
|
||||
|
||||
19
ReadMe.md
19
ReadMe.md
@@ -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
|
||||
@@ -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,8 +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 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)
|
||||
@@ -99,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)
|
||||
|
||||
@@ -139,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>
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="uart_echo",
|
||||
appid="UART_Echo",
|
||||
name="UART Echo",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="uart_echo_app",
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="usb_mouse",
|
||||
appid="USB_Mouse",
|
||||
name="USB Mouse",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="usb_mouse_app",
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -15,6 +15,9 @@ typedef struct {
|
||||
DialogsApp* dialogs;
|
||||
Gui* gui;
|
||||
string_t fap_path;
|
||||
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Loading* loading;
|
||||
} FapLoader;
|
||||
|
||||
static bool
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -277,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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -14,6 +14,7 @@ typedef enum {
|
||||
SubmenuIndexNiceFlo24bit,
|
||||
SubmenuIndexCAME12bit,
|
||||
SubmenuIndexCAME24bit,
|
||||
SubmenuIndexBETT_433,
|
||||
SubmenuIndexCAMETwee,
|
||||
SubmenuIndexNeroSketch,
|
||||
SubmenuIndexNeroRadio,
|
||||
|
||||
@@ -86,3 +86,5 @@ typedef enum {
|
||||
SubGhzViewReceiverModeLive,
|
||||
SubGhzViewReceiverModeFile,
|
||||
} SubGhzViewReceiverMode;
|
||||
|
||||
#define SUBGHZ_HISTORY_REMOVE_SAVED_ITEMS 1
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
79
applications/main/subghz/subghz_history_private.h
Normal file
79
applications/main/subghz/subghz_history_private.h
Normal 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);
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
153
applications/main/subghz/subghz_last_settings.c
Normal file
153
applications/main/subghz/subghz_last_settings.c
Normal 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
|
||||
33
applications/main/subghz/subghz_last_settings.h
Normal file
33
applications/main/subghz/subghz_last_settings.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -30,6 +30,51 @@ 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_frequency = {
|
||||
&message_display_backlight_on,
|
||||
&message_green_255,
|
||||
&message_vibro_on,
|
||||
&message_delay_100,
|
||||
&message_green_0,
|
||||
&message_blue_255,
|
||||
&message_vibro_off,
|
||||
&message_delay_100,
|
||||
&message_blue_0,
|
||||
&message_green_255,
|
||||
&message_vibro_on,
|
||||
&message_delay_100,
|
||||
&message_green_0,
|
||||
&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 +95,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 +209,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 +274,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(
|
||||
@@ -249,12 +385,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_frequency);
|
||||
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 +446,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 +497,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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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))) {
|
||||
@@ -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();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="arkanoid_game",
|
||||
appid="Arkanoid",
|
||||
name="Arkanoid",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="arkanoid_game_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="barcode_generator",
|
||||
appid="Barcode_Generator",
|
||||
name="UPC-A Generator",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="barcode_UPCA_generator_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="bt_hid",
|
||||
appid="Bluetooth_Remote",
|
||||
name="Bluetooth Remote",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="bt_hid_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="game_doom",
|
||||
appid="DOOM",
|
||||
name="DOOM",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="doom_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="esp8266_deauth",
|
||||
appid="ESP8266_Deauther",
|
||||
name="[ESP8266] Deauther",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="esp8266_deauth_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="game_flappybird",
|
||||
appid="FlappyBird",
|
||||
name="Flappy Bird",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="flappy_game_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="flipfrid",
|
||||
appid="RFID_Fuzzer",
|
||||
name="RFID Fuzzer",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="flipfrid_start",
|
||||
|
||||
@@ -31,6 +31,8 @@ typedef enum {
|
||||
typedef enum {
|
||||
EM4100,
|
||||
HIDProx,
|
||||
PAC,
|
||||
H10301,
|
||||
} FlipFridProtos;
|
||||
|
||||
typedef enum {
|
||||
@@ -79,6 +81,8 @@ typedef struct {
|
||||
ProtocolDict* dict;
|
||||
ProtocolId protocol;
|
||||
|
||||
uint8_t time_between_cards;
|
||||
|
||||
// Used for custom dictionnary
|
||||
Stream* uids_stream;
|
||||
} FlipFridState;
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "flipfrid_scene_entrypoint.h"
|
||||
|
||||
string_t menu_items[4];
|
||||
string_t menu_proto_items[2];
|
||||
string_t menu_proto_items[4];
|
||||
|
||||
void flipfrid_scene_entrypoint_menu_callback(
|
||||
FlipFridState* context,
|
||||
@@ -41,6 +41,14 @@ void flipfrid_scene_entrypoint_menu_callback(
|
||||
context->proto = HIDProx;
|
||||
string_set_str(context->proto_name, "HIDProx");
|
||||
break;
|
||||
case PAC:
|
||||
context->proto = PAC;
|
||||
string_set_str(context->proto_name, "PAC/Stanley");
|
||||
break;
|
||||
case H10301:
|
||||
context->proto = H10301;
|
||||
string_set_str(context->proto_name, "H10301");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -66,12 +74,14 @@ void flipfrid_scene_entrypoint_on_enter(FlipFridState* context) {
|
||||
string_set(menu_items[3], "Load uids from file");
|
||||
|
||||
context->menu_proto_index = 0;
|
||||
for(uint32_t i = 0; i < 2; i++) {
|
||||
for(uint32_t i = 0; i < 4; i++) {
|
||||
string_init(menu_proto_items[i]);
|
||||
}
|
||||
|
||||
string_set(menu_proto_items[0], "EM4100");
|
||||
string_set(menu_proto_items[1], "HIDProx");
|
||||
string_set(menu_proto_items[2], "PAC/Stanley");
|
||||
string_set(menu_proto_items[3], "H10301");
|
||||
}
|
||||
|
||||
void flipfrid_scene_entrypoint_on_exit(FlipFridState* context) {
|
||||
@@ -80,7 +90,7 @@ void flipfrid_scene_entrypoint_on_exit(FlipFridState* context) {
|
||||
string_clear(menu_items[i]);
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < 2; i++) {
|
||||
for(uint32_t i = 0; i < 4; i++) {
|
||||
string_clear(menu_proto_items[i]);
|
||||
}
|
||||
}
|
||||
@@ -106,11 +116,15 @@ void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* cont
|
||||
case InputKeyLeft:
|
||||
if(context->menu_proto_index > EM4100) {
|
||||
context->menu_proto_index--;
|
||||
} else if(context->menu_proto_index == EM4100) {
|
||||
context->menu_proto_index = H10301;
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(context->menu_proto_index < HIDProx) {
|
||||
if(context->menu_proto_index < H10301) {
|
||||
context->menu_proto_index++;
|
||||
} else if(context->menu_proto_index == H10301) {
|
||||
context->menu_proto_index = EM4100;
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
@@ -167,7 +181,7 @@ void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 34, 4, AlignCenter, AlignTop, "<");
|
||||
canvas_draw_str_aligned(canvas, 27, 4, AlignCenter, AlignTop, "<");
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(
|
||||
@@ -179,9 +193,9 @@ void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
string_get_cstr(menu_proto_items[context->menu_proto_index]));
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 94, 4, AlignCenter, AlignTop, ">");
|
||||
canvas_draw_str_aligned(canvas, 101, 4, AlignCenter, AlignTop, ">");
|
||||
|
||||
if(context->menu_proto_index < HIDProx) {
|
||||
if(context->menu_proto_index < H10301) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
|
||||
@@ -44,6 +44,20 @@ bool flipfrid_load(FlipFridState* context, const char* file_path) {
|
||||
string_set_str(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == PAC) {
|
||||
if(strcmp(string_get_cstr(temp_str), "PAC/Stanley") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == H10301) {
|
||||
if(strcmp(string_get_cstr(temp_str), "H10301") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(strcmp(string_get_cstr(temp_str), "HIDProx") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
@@ -70,6 +84,20 @@ bool flipfrid_load(FlipFridState* context, const char* file_path) {
|
||||
string_set_str(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == PAC) {
|
||||
if(string_size(context->data_str) != 11) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == H10301) {
|
||||
if(string_size(context->data_str) != 8) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
string_reset(context->notification_msg);
|
||||
string_set_str(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(string_size(context->data_str) != 17) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <gui/elements.h>
|
||||
|
||||
uint8_t counter = 0;
|
||||
#define TIME_BETWEEN_CARDS 6
|
||||
|
||||
uint8_t id_list[17][5] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
@@ -40,12 +40,54 @@ uint8_t id_list_hid[14][6] = {
|
||||
{0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
uint8_t id_list_pac[17][4] = {
|
||||
{0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78}, // Incremental UID
|
||||
{0x9A, 0x78, 0x56, 0x34}, // Decremental UID
|
||||
{0x04, 0xd0, 0x9b, 0x0d}, // From arha
|
||||
{0x34, 0x00, 0x29, 0x3d}, // From arha
|
||||
{0x04, 0xdf, 0x00, 0x00}, // From arha
|
||||
{0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
uint8_t id_list_h[14][3] = {
|
||||
{0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56}, // Incremental UID
|
||||
{0x56, 0x34, 0x12}, // Decremental UID
|
||||
{0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
void flipfrid_scene_run_attack_on_enter(FlipFridState* context) {
|
||||
context->time_between_cards = 10;
|
||||
context->attack_step = 0;
|
||||
context->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
context->worker = lfrfid_worker_alloc(context->dict);
|
||||
if(context->proto == HIDProx) {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "HIDProx");
|
||||
} else if(context->proto == PAC) {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "PAC/Stanley");
|
||||
} else if(context->proto == H10301) {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "H10301");
|
||||
} else {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "EM4100");
|
||||
}
|
||||
@@ -79,7 +121,38 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
context->payload[3] = id_list[context->attack_step][3];
|
||||
context->payload[4] = id_list[context->attack_step][4];
|
||||
|
||||
if(context->attack_step == 15) {
|
||||
if(context->attack_step == 16) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == PAC) {
|
||||
context->payload[0] = id_list_pac[context->attack_step][0];
|
||||
context->payload[1] = id_list_pac[context->attack_step][1];
|
||||
context->payload[2] = id_list_pac[context->attack_step][2];
|
||||
context->payload[3] = id_list_pac[context->attack_step][3];
|
||||
|
||||
if(context->attack_step == 16) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == H10301) {
|
||||
context->payload[0] = id_list_h[context->attack_step][0];
|
||||
context->payload[1] = id_list_h[context->attack_step][1];
|
||||
context->payload[2] = id_list_h[context->attack_step][2];
|
||||
|
||||
if(context->attack_step == 13) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
@@ -97,7 +170,7 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
context->payload[4] = id_list_hid[context->attack_step][4];
|
||||
context->payload[5] = id_list_hid[context->attack_step][5];
|
||||
|
||||
if(context->attack_step == 15) {
|
||||
if(context->attack_step == 13) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
@@ -118,6 +191,37 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
context->payload[3] = 0x00;
|
||||
context->payload[4] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == PAC) {
|
||||
context->payload[0] = context->attack_step;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == H10301) {
|
||||
context->payload[0] = context->attack_step;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
@@ -158,6 +262,43 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == PAC) {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
context->payload[3] = context->data[3];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == H10301) {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
@@ -194,6 +335,7 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
|
||||
case FlipFridAttackLoadFileCustomUids:
|
||||
if(context->proto == EM4100) {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
@@ -202,13 +344,24 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(string_size(context->data_str) != 11) continue;
|
||||
if(string_size(context->data_str) != 11) break;
|
||||
break;
|
||||
}
|
||||
if(end_of_list) break;
|
||||
FURI_LOG_D(TAG, string_get_cstr(context->data_str));
|
||||
if(string_size(context->data_str) != 11) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
@@ -219,7 +372,8 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
} else if(context->proto == PAC) {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
@@ -228,13 +382,100 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(string_size(context->data_str) != 13) continue;
|
||||
if(string_size(context->data_str) != 9) break;
|
||||
break;
|
||||
}
|
||||
if(end_of_list) break;
|
||||
FURI_LOG_D(TAG, string_get_cstr(context->data_str));
|
||||
if(string_size(context->data_str) != 9) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 4; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == H10301) {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(string_size(context->data_str) != 7) break;
|
||||
break;
|
||||
}
|
||||
if(end_of_list) break;
|
||||
FURI_LOG_D(TAG, string_get_cstr(context->data_str));
|
||||
if(string_size(context->data_str) != 7) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 3; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(string_size(context->data_str) != 13) break;
|
||||
break;
|
||||
}
|
||||
FURI_LOG_D(TAG, string_get_cstr(context->data_str));
|
||||
if(end_of_list) break;
|
||||
if(string_size(context->data_str) != 13) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 6; i++) {
|
||||
@@ -249,7 +490,7 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
}
|
||||
}
|
||||
|
||||
if(counter > TIME_BETWEEN_CARDS) {
|
||||
if(counter > context->time_between_cards) {
|
||||
counter = 0;
|
||||
} else {
|
||||
counter++;
|
||||
@@ -262,9 +503,22 @@ void flipfrid_scene_run_attack_on_event(FlipFridEvent event, FlipFridState* cont
|
||||
if(event.input_type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
break;
|
||||
case InputKeyUp:
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards > 0) {
|
||||
context->time_between_cards--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards < 60) {
|
||||
context->time_between_cards++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
counter = 0;
|
||||
@@ -303,9 +557,10 @@ void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
// Title
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 8, AlignCenter, AlignTop, string_get_cstr(context->attack_name));
|
||||
canvas, 64, 2, AlignCenter, AlignTop, string_get_cstr(context->attack_name));
|
||||
|
||||
char uid[18];
|
||||
char speed[16];
|
||||
if(context->proto == HIDProx) {
|
||||
snprintf(
|
||||
uid,
|
||||
@@ -317,6 +572,23 @@ void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
context->payload[3],
|
||||
context->payload[4],
|
||||
context->payload[5]);
|
||||
} else if(context->proto == PAC) {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2],
|
||||
context->payload[3]);
|
||||
} else if(context->proto == H10301) {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2]);
|
||||
} else {
|
||||
snprintf(
|
||||
uid,
|
||||
@@ -329,15 +601,25 @@ void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
context->payload[4]);
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, uid);
|
||||
canvas_draw_str_aligned(canvas, 64, 38, AlignCenter, AlignTop, uid);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 26, AlignCenter, AlignTop, string_get_cstr(context->proto_name));
|
||||
|
||||
snprintf(speed, sizeof(speed), "Time delay: %d", context->time_between_cards);
|
||||
|
||||
//canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignTop, "Speed:");
|
||||
canvas_draw_str_aligned(canvas, 64, 14, AlignCenter, AlignTop, speed);
|
||||
//char start_stop_msg[20];
|
||||
if(context->is_attacking) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
//snprintf(start_stop_msg, sizeof(start_stop_msg), " Press OK to stop ");
|
||||
} else {
|
||||
elements_button_center(canvas, "Start");
|
||||
elements_button_left(canvas, "TD -");
|
||||
elements_button_right(canvas, "+ TD");
|
||||
}
|
||||
//canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignTop, start_stop_msg);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,31 @@
|
||||
#include "flipfrid_scene_select_field.h"
|
||||
|
||||
void flipfrid_center_displayed_key(FlipFridState* context, uint8_t index) {
|
||||
const char* key_cstr = string_get_cstr(context->data_str);
|
||||
char key_cstr[18];
|
||||
uint8_t key_len = 18;
|
||||
uint8_t str_index = (index * 3);
|
||||
int data_len = sizeof(context->data) / sizeof(context->data[0]);
|
||||
int key_index = 0;
|
||||
|
||||
if(context->proto == EM4100) {
|
||||
key_len = 16;
|
||||
}
|
||||
if(context->proto == PAC) {
|
||||
key_len = 13;
|
||||
}
|
||||
if(context->proto == H10301) {
|
||||
key_len = 10;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < data_len; i++) {
|
||||
if(context->data[i] < 9) {
|
||||
key_index +=
|
||||
snprintf(&key_cstr[key_index], key_len - key_index, "0%X ", context->data[i]);
|
||||
} else {
|
||||
key_index +=
|
||||
snprintf(&key_cstr[key_index], key_len - key_index, "%X ", context->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
char display_menu[17] = {
|
||||
'X', 'X', ' ', 'X', 'X', ' ', '<', 'X', 'X', '>', ' ', 'X', 'X', ' ', 'X', 'X', '\0'};
|
||||
@@ -62,6 +85,7 @@ void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* co
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
const char* key_cstr = string_get_cstr(context->data_str);
|
||||
int data_len = sizeof(context->data) / sizeof(context->data[0]);
|
||||
|
||||
// don't look, it's ugly but I'm a python dev so...
|
||||
uint8_t nb_bytes = 0;
|
||||
@@ -73,7 +97,18 @@ void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* co
|
||||
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
for(uint8_t i = 0; i < data_len; i++) {
|
||||
if(context->key_index == i) {
|
||||
context->data[i] = (context->data[i] - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyUp:
|
||||
for(uint8_t i = 0; i < data_len; i++) {
|
||||
if(context->key_index == i) {
|
||||
context->data[i] = (context->data[i] + 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(context->key_index > 0) {
|
||||
@@ -90,6 +125,7 @@ void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* co
|
||||
context->current_scene = SceneAttack;
|
||||
break;
|
||||
case InputKeyBack:
|
||||
context->key_index = 0;
|
||||
string_reset(context->notification_msg);
|
||||
context->current_scene = SceneSelectFile;
|
||||
break;
|
||||
@@ -106,16 +142,17 @@ void flipfrid_scene_select_field_on_draw(Canvas* canvas, FlipFridState* context)
|
||||
// Frame
|
||||
//canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
|
||||
// Title
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "Use < > to select byte.");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(canvas, 12, 5, AlignLeft, AlignTop, "Left and right: select byte");
|
||||
canvas_draw_str_aligned(canvas, 12, 15, AlignLeft, AlignTop, "Up and down: adjust byte");
|
||||
|
||||
char msg_index[18];
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
snprintf(msg_index, sizeof(msg_index), "Field index : %d", context->key_index);
|
||||
canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index);
|
||||
canvas_draw_str_aligned(canvas, 64, 30, AlignCenter, AlignTop, msg_index);
|
||||
|
||||
flipfrid_center_displayed_key(context, context->key_index);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 40, AlignCenter, AlignTop, string_get_cstr(context->notification_msg));
|
||||
canvas, 64, 45, AlignCenter, AlignTop, string_get_cstr(context->notification_msg));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="mouse_jacker",
|
||||
appid="NRF24_Mouse_Jacker",
|
||||
name="[NRF24] Mouse Jacker",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="mousejacker_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="multi_converter",
|
||||
appid="Multi_Converter",
|
||||
name="Multi Converter",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="multi_converter_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="music_player",
|
||||
appid="Music_Player",
|
||||
name="Music Player",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="music_player_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="nrf_sniff",
|
||||
appid="NRF24_Sniffer",
|
||||
name="[NRF24] Sniffer",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="nrfsniff_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="picopass",
|
||||
appid="Picopass",
|
||||
name="PicoPass Reader",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="picopass_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="sub_playlist",
|
||||
appid="SubGHz_Playlist",
|
||||
name="Sub-GHz Playlist",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="playlist_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="sentry_safe",
|
||||
appid="GPIO_Sentry_Safe",
|
||||
name="[GPIO] Sentry Safe",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="sentry_safe_app",
|
||||
|
||||
12
applications/plugins/signal_generator/application.fam
Normal file
12
applications/plugins/signal_generator/application.fam
Normal file
@@ -0,0 +1,12 @@
|
||||
App(
|
||||
appid="Signal_Generator",
|
||||
name="Signal Generator",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="signal_gen_app",
|
||||
cdefines=["APP_SIGNAL_GEN"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
order=50,
|
||||
fap_icon="signal_gen_10px.png",
|
||||
fap_category="Tools",
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "../signal_gen_app_i.h"
|
||||
|
||||
// Generate scene on_enter handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||
void (*const signal_gen_scene_on_enter_handlers[])(void*) = {
|
||||
#include "signal_gen_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||
bool (*const signal_gen_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||
#include "signal_gen_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||
void (*const signal_gen_scene_on_exit_handlers[])(void* context) = {
|
||||
#include "signal_gen_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Initialize scene handlers configuration structure
|
||||
const SceneManagerHandlers signal_gen_scene_handlers = {
|
||||
.on_enter_handlers = signal_gen_scene_on_enter_handlers,
|
||||
.on_event_handlers = signal_gen_scene_on_event_handlers,
|
||||
.on_exit_handlers = signal_gen_scene_on_exit_handlers,
|
||||
.scene_num = SignalGenSceneNum,
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// Generate scene id and total number
|
||||
#define ADD_SCENE(prefix, name, id) SignalGenScene##id,
|
||||
typedef enum {
|
||||
#include "signal_gen_scene_config.h"
|
||||
SignalGenSceneNum,
|
||||
} SignalGenScene;
|
||||
#undef ADD_SCENE
|
||||
|
||||
extern const SceneManagerHandlers signal_gen_scene_handlers;
|
||||
|
||||
// Generate scene on_enter handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||
#include "signal_gen_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) \
|
||||
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||
#include "signal_gen_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||
#include "signal_gen_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
@@ -0,0 +1,3 @@
|
||||
ADD_SCENE(signal_gen, start, Start)
|
||||
ADD_SCENE(signal_gen, pwm, Pwm)
|
||||
ADD_SCENE(signal_gen, mco, Mco)
|
||||
@@ -0,0 +1,145 @@
|
||||
#include "../signal_gen_app_i.h"
|
||||
|
||||
typedef enum {
|
||||
LineIndexPin,
|
||||
LineIndexSource,
|
||||
LineIndexDivision,
|
||||
} LineIndex;
|
||||
|
||||
static const char* const mco_pin_names[] = {
|
||||
"13(Tx)",
|
||||
};
|
||||
|
||||
static const char* const mco_source_names[] = {
|
||||
"32768Hz",
|
||||
"64MHz",
|
||||
"~100K",
|
||||
"~200K",
|
||||
"~400K",
|
||||
"~800K",
|
||||
"~1MHz",
|
||||
"~2MHz",
|
||||
"~4MHz",
|
||||
"~8MHz",
|
||||
"~16MHz",
|
||||
"~24MHz",
|
||||
"~32MHz",
|
||||
"~48MHz",
|
||||
};
|
||||
|
||||
static const FuriHalClockMcoSourceId mco_sources[] = {
|
||||
FuriHalClockMcoLse,
|
||||
FuriHalClockMcoSysclk,
|
||||
FuriHalClockMcoMsi100k,
|
||||
FuriHalClockMcoMsi200k,
|
||||
FuriHalClockMcoMsi400k,
|
||||
FuriHalClockMcoMsi800k,
|
||||
FuriHalClockMcoMsi1m,
|
||||
FuriHalClockMcoMsi2m,
|
||||
FuriHalClockMcoMsi4m,
|
||||
FuriHalClockMcoMsi8m,
|
||||
FuriHalClockMcoMsi16m,
|
||||
FuriHalClockMcoMsi24m,
|
||||
FuriHalClockMcoMsi32m,
|
||||
FuriHalClockMcoMsi48m,
|
||||
};
|
||||
|
||||
static const char* const mco_divisor_names[] = {
|
||||
"1",
|
||||
"2",
|
||||
"4",
|
||||
"8",
|
||||
"16",
|
||||
};
|
||||
|
||||
static const FuriHalClockMcoDivisorId mco_divisors[] = {
|
||||
FuriHalClockMcoDiv1,
|
||||
FuriHalClockMcoDiv2,
|
||||
FuriHalClockMcoDiv4,
|
||||
FuriHalClockMcoDiv8,
|
||||
FuriHalClockMcoDiv16,
|
||||
};
|
||||
|
||||
static void mco_source_list_change_callback(VariableItem* item) {
|
||||
SignalGenApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, mco_source_names[index]);
|
||||
|
||||
app->mco_src = mco_sources[index];
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenMcoEventUpdate);
|
||||
}
|
||||
|
||||
static void mco_divisor_list_change_callback(VariableItem* item) {
|
||||
SignalGenApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, mco_divisor_names[index]);
|
||||
|
||||
app->mco_div = mco_divisors[index];
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenMcoEventUpdate);
|
||||
}
|
||||
|
||||
void signal_gen_scene_mco_on_enter(void* context) {
|
||||
SignalGenApp* app = context;
|
||||
VariableItemList* var_item_list = app->var_item_list;
|
||||
|
||||
VariableItem* item;
|
||||
|
||||
item = variable_item_list_add(var_item_list, "GPIO Pin", COUNT_OF(mco_pin_names), NULL, NULL);
|
||||
variable_item_set_current_value_index(item, 0);
|
||||
variable_item_set_current_value_text(item, mco_pin_names[0]);
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list,
|
||||
"Frequency",
|
||||
COUNT_OF(mco_source_names),
|
||||
mco_source_list_change_callback,
|
||||
app);
|
||||
variable_item_set_current_value_index(item, 0);
|
||||
variable_item_set_current_value_text(item, mco_source_names[0]);
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list,
|
||||
"Freq. divider",
|
||||
COUNT_OF(mco_divisor_names),
|
||||
mco_divisor_list_change_callback,
|
||||
app);
|
||||
variable_item_set_current_value_index(item, 0);
|
||||
variable_item_set_current_value_text(item, mco_divisor_names[0]);
|
||||
|
||||
variable_item_list_set_selected_item(var_item_list, LineIndexSource);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SignalGenViewVarItemList);
|
||||
|
||||
app->mco_src = FuriHalClockMcoLse;
|
||||
app->mco_div = FuriHalClockMcoDiv1;
|
||||
furi_hal_clock_mco_enable(app->mco_src, app->mco_div);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_tx, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn0MCO);
|
||||
}
|
||||
|
||||
bool signal_gen_scene_mco_on_event(void* context, SceneManagerEvent event) {
|
||||
SignalGenApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SignalGenMcoEventUpdate) {
|
||||
consumed = true;
|
||||
furi_hal_clock_mco_enable(app->mco_src, app->mco_div);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void signal_gen_scene_mco_on_exit(void* context) {
|
||||
SignalGenApp* app = context;
|
||||
variable_item_list_reset(app->var_item_list);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_tx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn7USART1);
|
||||
furi_hal_clock_mco_disable();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "../signal_gen_app_i.h"
|
||||
|
||||
static const FuriHalPwmOutputId pwm_ch_id[] = {
|
||||
FuriHalPwmOutputIdTim1PA7,
|
||||
FuriHalPwmOutputIdLptim2PA4,
|
||||
};
|
||||
|
||||
#define DEFAULT_FREQ 1000
|
||||
#define DEFAULT_DUTY 50
|
||||
|
||||
static void
|
||||
signal_gen_pwm_callback(uint8_t channel_id, uint32_t freq, uint8_t duty, void* context) {
|
||||
SignalGenApp* app = context;
|
||||
|
||||
app->pwm_freq = freq;
|
||||
app->pwm_duty = duty;
|
||||
|
||||
if(app->pwm_ch != pwm_ch_id[channel_id]) {
|
||||
app->pwm_ch_prev = app->pwm_ch;
|
||||
app->pwm_ch = pwm_ch_id[channel_id];
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenPwmEventChannelChange);
|
||||
} else {
|
||||
app->pwm_ch = pwm_ch_id[channel_id];
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenPwmEventUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
void signal_gen_scene_pwm_on_enter(void* context) {
|
||||
SignalGenApp* app = context;
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SignalGenViewPwm);
|
||||
|
||||
signal_gen_pwm_set_callback(app->pwm_view, signal_gen_pwm_callback, app);
|
||||
|
||||
signal_gen_pwm_set_params(app->pwm_view, 0, DEFAULT_FREQ, DEFAULT_DUTY);
|
||||
furi_hal_pwm_start(pwm_ch_id[0], DEFAULT_FREQ, DEFAULT_DUTY);
|
||||
}
|
||||
|
||||
bool signal_gen_scene_pwm_on_event(void* context, SceneManagerEvent event) {
|
||||
SignalGenApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SignalGenPwmEventUpdate) {
|
||||
consumed = true;
|
||||
furi_hal_pwm_set_params(app->pwm_ch, app->pwm_freq, app->pwm_duty);
|
||||
} else if(event.event == SignalGenPwmEventChannelChange) {
|
||||
consumed = true;
|
||||
furi_hal_pwm_stop(app->pwm_ch_prev);
|
||||
furi_hal_pwm_start(app->pwm_ch, app->pwm_freq, app->pwm_duty);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void signal_gen_scene_pwm_on_exit(void* context) {
|
||||
SignalGenApp* app = context;
|
||||
variable_item_list_reset(app->var_item_list);
|
||||
furi_hal_pwm_stop(app->pwm_ch);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "../signal_gen_app_i.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexPwm,
|
||||
SubmenuIndexClockOutput,
|
||||
} SubmenuIndex;
|
||||
|
||||
void signal_gen_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
SignalGenApp* app = context;
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void signal_gen_scene_start_on_enter(void* context) {
|
||||
SignalGenApp* app = context;
|
||||
Submenu* submenu = app->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu, "PWM Generator", SubmenuIndexPwm, signal_gen_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Clock Generator",
|
||||
SubmenuIndexClockOutput,
|
||||
signal_gen_scene_start_submenu_callback,
|
||||
app);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(app->scene_manager, SignalGenSceneStart));
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SignalGenViewSubmenu);
|
||||
}
|
||||
|
||||
bool signal_gen_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
SignalGenApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexPwm) {
|
||||
scene_manager_next_scene(app->scene_manager, SignalGenScenePwm);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexClockOutput) {
|
||||
scene_manager_next_scene(app->scene_manager, SignalGenSceneMco);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(app->scene_manager, SignalGenSceneStart, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void signal_gen_scene_start_on_exit(void* context) {
|
||||
SignalGenApp* app = context;
|
||||
|
||||
submenu_reset(app->submenu);
|
||||
}
|
||||
BIN
applications/plugins/signal_generator/signal_gen_10px.png
Normal file
BIN
applications/plugins/signal_generator/signal_gen_10px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
93
applications/plugins/signal_generator/signal_gen_app.c
Normal file
93
applications/plugins/signal_generator/signal_gen_app.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "signal_gen_app_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
static bool signal_gen_app_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
SignalGenApp* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||
}
|
||||
|
||||
static bool signal_gen_app_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SignalGenApp* app = context;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void signal_gen_app_tick_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SignalGenApp* app = context;
|
||||
scene_manager_handle_tick_event(app->scene_manager);
|
||||
}
|
||||
|
||||
SignalGenApp* signal_gen_app_alloc() {
|
||||
SignalGenApp* app = malloc(sizeof(SignalGenApp));
|
||||
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
app->scene_manager = scene_manager_alloc(&signal_gen_scene_handlers, app);
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
app->view_dispatcher, signal_gen_app_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, signal_gen_app_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
app->view_dispatcher, signal_gen_app_tick_event_callback, 100);
|
||||
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
app->var_item_list = variable_item_list_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
SignalGenViewVarItemList,
|
||||
variable_item_list_get_view(app->var_item_list));
|
||||
|
||||
app->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, SignalGenViewSubmenu, submenu_get_view(app->submenu));
|
||||
|
||||
app->pwm_view = signal_gen_pwm_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, SignalGenViewPwm, signal_gen_pwm_get_view(app->pwm_view));
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, SignalGenSceneStart);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void signal_gen_app_free(SignalGenApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
// Views
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SignalGenViewVarItemList);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SignalGenViewSubmenu);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SignalGenViewPwm);
|
||||
|
||||
submenu_free(app->submenu);
|
||||
variable_item_list_free(app->var_item_list);
|
||||
signal_gen_pwm_free(app->pwm_view);
|
||||
|
||||
// View dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
scene_manager_free(app->scene_manager);
|
||||
|
||||
// Close records
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t signal_gen_app(void* p) {
|
||||
UNUSED(p);
|
||||
SignalGenApp* signal_gen_app = signal_gen_app_alloc();
|
||||
|
||||
view_dispatcher_run(signal_gen_app->view_dispatcher);
|
||||
|
||||
signal_gen_app_free(signal_gen_app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
46
applications/plugins/signal_generator/signal_gen_app_i.h
Normal file
46
applications/plugins/signal_generator/signal_gen_app_i.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "scenes/signal_gen_scene.h"
|
||||
|
||||
#include "furi_hal_clock.h"
|
||||
#include "furi_hal_pwm.h"
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include "views/signal_gen_pwm.h"
|
||||
|
||||
typedef struct SignalGenApp SignalGenApp;
|
||||
|
||||
struct SignalGenApp {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
|
||||
VariableItemList* var_item_list;
|
||||
Submenu* submenu;
|
||||
SignalGenPwm* pwm_view;
|
||||
|
||||
FuriHalClockMcoSourceId mco_src;
|
||||
FuriHalClockMcoDivisorId mco_div;
|
||||
|
||||
FuriHalPwmOutputId pwm_ch_prev;
|
||||
FuriHalPwmOutputId pwm_ch;
|
||||
uint32_t pwm_freq;
|
||||
uint8_t pwm_duty;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SignalGenViewVarItemList,
|
||||
SignalGenViewSubmenu,
|
||||
SignalGenViewPwm,
|
||||
} SignalGenAppView;
|
||||
|
||||
typedef enum {
|
||||
SignalGenMcoEventUpdate,
|
||||
SignalGenPwmEventUpdate,
|
||||
SignalGenPwmEventChannelChange,
|
||||
} SignalGenCustomEvent;
|
||||
301
applications/plugins/signal_generator/views/signal_gen_pwm.c
Normal file
301
applications/plugins/signal_generator/views/signal_gen_pwm.c
Normal file
@@ -0,0 +1,301 @@
|
||||
#include "../signal_gen_app_i.h"
|
||||
#include "furi_hal.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
typedef enum {
|
||||
LineIndexChannel,
|
||||
LineIndexFrequency,
|
||||
LineIndexDuty,
|
||||
LineIndexTotalCount
|
||||
} LineIndex;
|
||||
|
||||
static const char* const pwm_ch_names[] = {"2(A7)", "4(A4)"};
|
||||
|
||||
struct SignalGenPwm {
|
||||
View* view;
|
||||
SignalGenPwmViewCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
LineIndex line_sel;
|
||||
bool edit_mode;
|
||||
uint8_t edit_digit;
|
||||
|
||||
uint8_t channel_id;
|
||||
uint32_t freq;
|
||||
uint8_t duty;
|
||||
|
||||
} SignalGenPwmViewModel;
|
||||
|
||||
#define ITEM_H 64 / 3
|
||||
#define ITEM_W 128
|
||||
|
||||
#define VALUE_X 100
|
||||
#define VALUE_W 45
|
||||
|
||||
#define FREQ_VALUE_X 62
|
||||
#define FREQ_MAX 1000000UL
|
||||
#define FREQ_DIGITS_NB 7
|
||||
|
||||
static void pwm_set_config(SignalGenPwm* pwm) {
|
||||
FuriHalPwmOutputId channel;
|
||||
uint32_t freq;
|
||||
uint8_t duty;
|
||||
|
||||
with_view_model(
|
||||
pwm->view, (SignalGenPwmViewModel * model) {
|
||||
channel = model->channel_id;
|
||||
freq = model->freq;
|
||||
duty = model->duty;
|
||||
return false;
|
||||
});
|
||||
|
||||
furi_assert(pwm->callback);
|
||||
pwm->callback(channel, freq, duty, pwm->context);
|
||||
}
|
||||
|
||||
static void pwm_channel_change(SignalGenPwmViewModel* model, InputEvent* event) {
|
||||
if(event->key == InputKeyLeft) {
|
||||
if(model->channel_id > 0) {
|
||||
model->channel_id--;
|
||||
}
|
||||
} else if(event->key == InputKeyRight) {
|
||||
if(model->channel_id < (COUNT_OF(pwm_ch_names) - 1)) {
|
||||
model->channel_id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pwm_duty_change(SignalGenPwmViewModel* model, InputEvent* event) {
|
||||
if(event->key == InputKeyLeft) {
|
||||
if(model->duty > 0) {
|
||||
model->duty--;
|
||||
}
|
||||
} else if(event->key == InputKeyRight) {
|
||||
if(model->duty < 100) {
|
||||
model->duty++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool pwm_freq_edit(SignalGenPwmViewModel* model, InputEvent* event) {
|
||||
bool consumed = false;
|
||||
if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) {
|
||||
if(event->key == InputKeyRight) {
|
||||
if(model->edit_digit > 0) {
|
||||
model->edit_digit--;
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
if(model->edit_digit < (FREQ_DIGITS_NB - 1)) {
|
||||
model->edit_digit++;
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyUp) {
|
||||
uint32_t step = 1;
|
||||
for(uint8_t i = 0; i < model->edit_digit; i++) {
|
||||
step *= 10;
|
||||
}
|
||||
if((model->freq + step) < FREQ_MAX) {
|
||||
model->freq += step;
|
||||
} else {
|
||||
model->freq = FREQ_MAX;
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
uint32_t step = 1;
|
||||
for(uint8_t i = 0; i < model->edit_digit; i++) {
|
||||
step *= 10;
|
||||
}
|
||||
if(model->freq > (step + 1)) {
|
||||
model->freq -= step;
|
||||
} else {
|
||||
model->freq = 1;
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void signal_gen_pwm_draw_callback(Canvas* canvas, void* _model) {
|
||||
SignalGenPwmViewModel* model = _model;
|
||||
char* line_label = NULL;
|
||||
char val_text[16];
|
||||
|
||||
for(uint8_t line = 0; line < LineIndexTotalCount; line++) {
|
||||
if(line == LineIndexChannel) {
|
||||
line_label = "GPIO Pin";
|
||||
} else if(line == LineIndexFrequency) {
|
||||
line_label = "Frequency";
|
||||
} else if(line == LineIndexDuty) {
|
||||
line_label = "Pulse width";
|
||||
}
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
if(line == model->line_sel) {
|
||||
elements_slightly_rounded_box(canvas, 0, ITEM_H * line + 1, ITEM_W, ITEM_H - 1);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
|
||||
uint8_t text_y = ITEM_H * line + ITEM_H / 2 + 2;
|
||||
|
||||
canvas_draw_str_aligned(canvas, 6, text_y, AlignLeft, AlignCenter, line_label);
|
||||
|
||||
if(line == LineIndexChannel) {
|
||||
snprintf(val_text, sizeof(val_text), "%s", pwm_ch_names[model->channel_id]);
|
||||
canvas_draw_str_aligned(canvas, VALUE_X, text_y, AlignCenter, AlignCenter, val_text);
|
||||
if(model->channel_id != 0) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas, VALUE_X - VALUE_W / 2, text_y, AlignCenter, AlignCenter, "<");
|
||||
}
|
||||
if(model->channel_id != (COUNT_OF(pwm_ch_names) - 1)) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas, VALUE_X + VALUE_W / 2, text_y, AlignCenter, AlignCenter, ">");
|
||||
}
|
||||
} else if(line == LineIndexFrequency) {
|
||||
snprintf(val_text, sizeof(val_text), "%7lu Hz", model->freq);
|
||||
canvas_set_font(canvas, FontKeyboard);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, FREQ_VALUE_X, text_y, AlignLeft, AlignCenter, val_text);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
if(model->edit_mode) {
|
||||
uint8_t icon_x = (FREQ_VALUE_X) + (FREQ_DIGITS_NB - model->edit_digit - 1) * 6;
|
||||
canvas_draw_icon(canvas, icon_x, text_y - 9, &I_SmallArrowUp_4x7);
|
||||
canvas_draw_icon(canvas, icon_x, text_y + 5, &I_SmallArrowDown_4x7);
|
||||
}
|
||||
} else if(line == LineIndexDuty) {
|
||||
snprintf(val_text, sizeof(val_text), "%d%%", model->duty);
|
||||
canvas_draw_str_aligned(canvas, VALUE_X, text_y, AlignCenter, AlignCenter, val_text);
|
||||
if(model->duty != 0) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas, VALUE_X - VALUE_W / 2, text_y, AlignCenter, AlignCenter, "<");
|
||||
}
|
||||
if(model->duty != 100) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas, VALUE_X + VALUE_W / 2, text_y, AlignCenter, AlignCenter, ">");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool signal_gen_pwm_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
SignalGenPwm* pwm = context;
|
||||
bool consumed = false;
|
||||
bool need_update = false;
|
||||
|
||||
with_view_model(
|
||||
pwm->view, (SignalGenPwmViewModel * model) {
|
||||
if(model->edit_mode == false) {
|
||||
if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) {
|
||||
if(event->key == InputKeyUp) {
|
||||
if(model->line_sel == 0) {
|
||||
model->line_sel = LineIndexTotalCount - 1;
|
||||
} else {
|
||||
model->line_sel =
|
||||
CLAMP(model->line_sel - 1, LineIndexTotalCount - 1, 0);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
if(model->line_sel == LineIndexTotalCount - 1) {
|
||||
model->line_sel = 0;
|
||||
} else {
|
||||
model->line_sel =
|
||||
CLAMP(model->line_sel + 1, LineIndexTotalCount - 1, 0);
|
||||
}
|
||||
consumed = true;
|
||||
} else if((event->key == InputKeyLeft) || (event->key == InputKeyRight)) {
|
||||
if(model->line_sel == LineIndexChannel) {
|
||||
pwm_channel_change(model, event);
|
||||
need_update = true;
|
||||
} else if(model->line_sel == LineIndexDuty) {
|
||||
pwm_duty_change(model, event);
|
||||
need_update = true;
|
||||
} else if(model->line_sel == LineIndexFrequency) {
|
||||
model->edit_mode = true;
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyOk) {
|
||||
if(model->line_sel == LineIndexFrequency) {
|
||||
model->edit_mode = true;
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if((event->key == InputKeyOk) || (event->key == InputKeyBack)) {
|
||||
if(event->type == InputTypeShort) {
|
||||
model->edit_mode = false;
|
||||
consumed = true;
|
||||
}
|
||||
} else {
|
||||
if(model->line_sel == LineIndexFrequency) {
|
||||
consumed = pwm_freq_edit(model, event);
|
||||
need_update = consumed;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if(need_update) {
|
||||
pwm_set_config(pwm);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
SignalGenPwm* signal_gen_pwm_alloc() {
|
||||
SignalGenPwm* pwm = malloc(sizeof(SignalGenPwm));
|
||||
|
||||
pwm->view = view_alloc();
|
||||
view_allocate_model(pwm->view, ViewModelTypeLocking, sizeof(SignalGenPwmViewModel));
|
||||
view_set_context(pwm->view, pwm);
|
||||
view_set_draw_callback(pwm->view, signal_gen_pwm_draw_callback);
|
||||
view_set_input_callback(pwm->view, signal_gen_pwm_input_callback);
|
||||
|
||||
return pwm;
|
||||
}
|
||||
|
||||
void signal_gen_pwm_free(SignalGenPwm* pwm) {
|
||||
furi_assert(pwm);
|
||||
view_free(pwm->view);
|
||||
free(pwm);
|
||||
}
|
||||
|
||||
View* signal_gen_pwm_get_view(SignalGenPwm* pwm) {
|
||||
furi_assert(pwm);
|
||||
return pwm->view;
|
||||
}
|
||||
|
||||
void signal_gen_pwm_set_callback(
|
||||
SignalGenPwm* pwm,
|
||||
SignalGenPwmViewCallback callback,
|
||||
void* context) {
|
||||
furi_assert(pwm);
|
||||
furi_assert(callback);
|
||||
|
||||
with_view_model(
|
||||
pwm->view, (SignalGenPwmViewModel * model) {
|
||||
UNUSED(model);
|
||||
pwm->callback = callback;
|
||||
pwm->context = context;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void signal_gen_pwm_set_params(SignalGenPwm* pwm, uint8_t channel_id, uint32_t freq, uint8_t duty) {
|
||||
with_view_model(
|
||||
pwm->view, (SignalGenPwmViewModel * model) {
|
||||
model->channel_id = channel_id;
|
||||
model->freq = freq;
|
||||
model->duty = duty;
|
||||
return true;
|
||||
});
|
||||
|
||||
furi_assert(pwm->callback);
|
||||
pwm->callback(channel_id, freq, duty, pwm->context);
|
||||
}
|
||||
21
applications/plugins/signal_generator/views/signal_gen_pwm.h
Normal file
21
applications/plugins/signal_generator/views/signal_gen_pwm.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../signal_gen_app_i.h"
|
||||
|
||||
typedef struct SignalGenPwm SignalGenPwm;
|
||||
typedef void (
|
||||
*SignalGenPwmViewCallback)(uint8_t channel_id, uint32_t freq, uint8_t duty, void* context);
|
||||
|
||||
SignalGenPwm* signal_gen_pwm_alloc();
|
||||
|
||||
void signal_gen_pwm_free(SignalGenPwm* pwm);
|
||||
|
||||
View* signal_gen_pwm_get_view(SignalGenPwm* pwm);
|
||||
|
||||
void signal_gen_pwm_set_callback(
|
||||
SignalGenPwm* pwm,
|
||||
SignalGenPwmViewCallback callback,
|
||||
void* context);
|
||||
|
||||
void signal_gen_pwm_set_params(SignalGenPwm* pwm, uint8_t channel_id, uint32_t freq, uint8_t duty);
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="snake_game",
|
||||
appid="Snake",
|
||||
name="Snake Game",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="snake_game_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="spectrum_analyzer",
|
||||
appid="Spectrum_Analyzer",
|
||||
name="Spectrum Analyzer",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="spectrum_analyzer_app",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
App(
|
||||
appid="subbrute",
|
||||
appid="SubGHz_Bruteforcer",
|
||||
name="Sub-GHz Bruteforcer",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="subbrute_app",
|
||||
|
||||
@@ -3,14 +3,16 @@
|
||||
#include <subghz/environment.h>
|
||||
#include <subghz/transmitter.h>
|
||||
#include <flipper_format_i.h>
|
||||
#include <lib/subghz/subghz_tx_rx_worker.h>
|
||||
|
||||
#define TAG "SubBruteWorker"
|
||||
|
||||
struct SubBruteWorker {
|
||||
FuriThread* thread;
|
||||
SubGhzTxRxWorker* subghz_txrx;
|
||||
volatile bool worker_running;
|
||||
volatile bool worker_manual_mode;
|
||||
bool is_manual_init;
|
||||
bool is_continuous_worker;
|
||||
|
||||
SubGhzEnvironment* environment;
|
||||
SubGhzTransmitter* transmitter;
|
||||
@@ -31,80 +33,25 @@ struct SubBruteWorker {
|
||||
#define SUBBRUTE_TXRX_WORKER_BUF_SIZE 2048
|
||||
#define SUBBRUTE_TXRX_WORKER_MAX_TXRX_SIZE 60
|
||||
#define SUBBRUTE_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40
|
||||
#define SUBBRUTE_TX_TIMEOUT 50
|
||||
#define SUBBRUTE_SEND_DELAY 260
|
||||
|
||||
/**
|
||||
* Entrypoint for worker
|
||||
*
|
||||
* @param context SubBruteWorker*
|
||||
* @return 0 if ok
|
||||
*/
|
||||
int32_t subbrute_worker_thread(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteWorker* instance = (SubBruteWorker*)context;
|
||||
|
||||
if(!instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Worker is not set to running state!");
|
||||
return -1;
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Worker start");
|
||||
#endif
|
||||
|
||||
instance->environment = subghz_environment_alloc();
|
||||
instance->transmitter = subghz_transmitter_alloc_init(
|
||||
instance->environment, string_get_cstr(instance->protocol_name));
|
||||
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_load_preset(instance->preset);
|
||||
instance->frequency = furi_hal_subghz_set_frequency_and_path(instance->frequency);
|
||||
|
||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(&gpio_cc1101_g0, true);
|
||||
|
||||
// Set ready to transmit value
|
||||
instance->last_time_tx_data = furi_get_tick() - SUBBRUTE_SEND_DELAY;
|
||||
|
||||
while(instance->worker_running) {
|
||||
// Transmit
|
||||
if(!furi_hal_subghz_tx()) {
|
||||
FURI_LOG_E(TAG, "Cannot transmit!");
|
||||
break;
|
||||
}
|
||||
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
||||
}
|
||||
|
||||
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
||||
furi_hal_subghz_sleep();
|
||||
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Worker stop");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#define SUBBRUTE_TX_TIMEOUT 5
|
||||
#define SUBBRUTE_SEND_DELAY 20
|
||||
|
||||
SubBruteWorker* subbrute_worker_alloc() {
|
||||
SubBruteWorker* instance = malloc(sizeof(SubBruteWorker));
|
||||
|
||||
instance->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(instance->thread, "SubBruteAttackWorker");
|
||||
furi_thread_set_stack_size(instance->thread, 2048);
|
||||
furi_thread_set_context(instance->thread, instance);
|
||||
furi_thread_set_callback(instance->thread, subbrute_worker_thread);
|
||||
|
||||
//instance->status = SubBruteWorkerStatusIDLE;
|
||||
instance->worker_running = false;
|
||||
instance->worker_manual_mode = false;
|
||||
|
||||
//instance->environment = subghz_environment_alloc();
|
||||
instance->transmitter = NULL;
|
||||
|
||||
instance->flipper_format = flipper_format_string_alloc();
|
||||
string_init(instance->protocol_name);
|
||||
|
||||
// SubGhzTxRxWorker
|
||||
instance->subghz_txrx = subghz_tx_rx_worker_alloc();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -117,16 +64,18 @@ void subbrute_worker_free(SubBruteWorker* instance) {
|
||||
instance->transmitter = NULL;
|
||||
}
|
||||
|
||||
if(instance->environment != NULL) {
|
||||
/*if(instance->environment != NULL) {
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
}
|
||||
}*/
|
||||
|
||||
furi_thread_free(instance->thread);
|
||||
flipper_format_free(instance->flipper_format);
|
||||
|
||||
string_clear(instance->protocol_name);
|
||||
|
||||
// SubGhzTxRxWorker
|
||||
subghz_tx_rx_worker_free(instance->subghz_txrx);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
@@ -138,6 +87,7 @@ bool subbrute_worker_start(
|
||||
furi_assert(instance);
|
||||
|
||||
if(instance->worker_manual_mode) {
|
||||
FURI_LOG_W(TAG, "Invalid mode for starting worker!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -156,19 +106,20 @@ bool subbrute_worker_start(
|
||||
furi_hal_subghz_set_frequency_and_path(instance->frequency);
|
||||
furi_hal_subghz_flush_rx();
|
||||
|
||||
if(furi_hal_subghz_is_tx_allowed(frequency)) {
|
||||
instance->frequency = frequency;
|
||||
res = true;
|
||||
}
|
||||
//if(furi_hal_subghz_is_tx_allowed(frequency)) {
|
||||
instance->frequency = frequency;
|
||||
res = true;
|
||||
//}
|
||||
instance->worker_running = res;
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Frequency: %d", frequency);
|
||||
#endif
|
||||
instance->preset = preset;
|
||||
|
||||
furi_thread_start(instance->thread);
|
||||
|
||||
if(res) {
|
||||
instance->worker_running = res =
|
||||
subghz_tx_rx_worker_start(instance->subghz_txrx, frequency);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -177,10 +128,21 @@ void subbrute_worker_stop(SubBruteWorker* instance) {
|
||||
|
||||
instance->worker_running = false;
|
||||
|
||||
furi_thread_join(instance->thread);
|
||||
if(subghz_tx_rx_worker_is_running(instance->subghz_txrx)) {
|
||||
subghz_tx_rx_worker_stop(instance->subghz_txrx);
|
||||
}
|
||||
}
|
||||
|
||||
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
||||
furi_hal_subghz_sleep();
|
||||
void subbrute_worker_set_continuous_worker(SubBruteWorker* instance, bool is_continuous_worker) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->is_continuous_worker = is_continuous_worker;
|
||||
}
|
||||
|
||||
bool subbrute_worker_get_continuous_worker(SubBruteWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->is_continuous_worker;
|
||||
}
|
||||
|
||||
bool subbrute_worker_is_running(SubBruteWorker* instance) {
|
||||
@@ -195,6 +157,18 @@ bool subbrute_worker_can_transmit(SubBruteWorker* instance) {
|
||||
return (furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_SEND_DELAY;
|
||||
}
|
||||
|
||||
bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance, bool is_button_pressed) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(is_button_pressed) {
|
||||
// It's human pressed, trying to reset twice pressing
|
||||
return !instance->worker_manual_mode &&
|
||||
(furi_get_tick() - instance->last_time_tx_data) > 500;
|
||||
} else {
|
||||
return !instance->worker_manual_mode;
|
||||
}
|
||||
}
|
||||
|
||||
bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->worker_running);
|
||||
@@ -210,14 +184,20 @@ bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload) {
|
||||
//FURI_LOG_D(TAG, "payload: %s", payload);
|
||||
#endif
|
||||
|
||||
Stream* stream = flipper_format_get_raw_stream(instance->flipper_format);
|
||||
stream_clean(stream);
|
||||
stream_write_cstring(stream, payload);
|
||||
subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format);
|
||||
while(!subghz_tx_rx_worker_write(instance->subghz_txrx, (uint8_t*)payload, strlen(payload))) {
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
|
||||
furi_hal_subghz_flush_tx();
|
||||
// Stream* stream = flipper_format_get_raw_stream(instance->flipper_format);
|
||||
// stream_clean(stream);
|
||||
// stream_write_cstring(stream, payload);
|
||||
// subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Init MANUAL
|
||||
bool subbrute_worker_init_manual_transmit(
|
||||
SubBruteWorker* instance,
|
||||
uint32_t frequency,
|
||||
@@ -230,7 +210,8 @@ bool subbrute_worker_init_manual_transmit(
|
||||
frequency,
|
||||
protocol_name);
|
||||
#endif
|
||||
if(instance->worker_manual_mode || !subbrute_worker_can_transmit(instance)) {
|
||||
if(instance->worker_manual_mode || !subbrute_worker_can_manual_transmit(instance, false) ||
|
||||
instance->worker_running) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "cannot transmit");
|
||||
#endif
|
||||
@@ -264,19 +245,18 @@ bool subbrute_worker_init_manual_transmit(
|
||||
furi_hal_subghz_set_frequency_and_path(instance->frequency);
|
||||
furi_hal_subghz_flush_rx();
|
||||
|
||||
if(!furi_hal_subghz_is_tx_allowed(frequency)) {
|
||||
/*if(!furi_hal_subghz_is_tx_allowed(frequency)) {
|
||||
FURI_LOG_E(TAG, "Frequency: %d invalid!", frequency);
|
||||
|
||||
instance->frequency = frequency;
|
||||
instance->worker_manual_mode = false;
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Frequency: %d", frequency);
|
||||
#endif
|
||||
|
||||
instance->environment = subghz_environment_alloc();
|
||||
instance->transmitter = subghz_transmitter_alloc_init(
|
||||
instance->environment, string_get_cstr(instance->protocol_name));
|
||||
|
||||
@@ -310,8 +290,6 @@ void subbrute_worker_manual_transmit_stop(SubBruteWorker* instance) {
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
}
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
|
||||
instance->is_manual_init = false;
|
||||
}
|
||||
@@ -326,9 +304,7 @@ bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* paylo
|
||||
return false;
|
||||
}
|
||||
if(instance->worker_running) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_worker_stop");
|
||||
#endif
|
||||
FURI_LOG_W(TAG, "Worker was working for manual mode. Shutdown thread");
|
||||
subbrute_worker_stop(instance);
|
||||
}
|
||||
if(!instance->is_manual_init) {
|
||||
|
||||
@@ -23,13 +23,17 @@ bool subbrute_worker_start(
|
||||
FuriHalSubGhzPreset preset,
|
||||
const char* protocol_name);
|
||||
void subbrute_worker_stop(SubBruteWorker* instance);
|
||||
bool subbrute_worker_get_continuous_worker(SubBruteWorker* instance);
|
||||
void subbrute_worker_set_continuous_worker(SubBruteWorker* instance, bool is_continuous_worker);
|
||||
//bool subbrute_worker_write(SubBruteWorker* instance, uint8_t* data, size_t size);
|
||||
bool subbrute_worker_is_running(SubBruteWorker* instance);
|
||||
bool subbrute_worker_can_transmit(SubBruteWorker* instance);
|
||||
bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance, bool is_button_pressed);
|
||||
bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload);
|
||||
bool subbrute_worker_init_manual_transmit(SubBruteWorker* instance,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
const char* protocol_name);
|
||||
bool subbrute_worker_init_manual_transmit(
|
||||
SubBruteWorker* instance,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
const char* protocol_name);
|
||||
bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* payload);
|
||||
void subbrute_worker_manual_transmit_stop(SubBruteWorker* instance);
|
||||
@@ -45,19 +45,22 @@ void subbrute_scene_load_file_on_enter(void* context) {
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(load_result == SubBruteFileResultOk) {
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadSelect);
|
||||
if(load_result == SubBruteFileResultOk) {
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadSelect);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Returned error: %d", load_result);
|
||||
|
||||
string_t dialog_msg;
|
||||
string_init(dialog_msg);
|
||||
string_cat_printf(
|
||||
dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result));
|
||||
dialog_message_show_storage_error(instance->dialogs, string_get_cstr(dialog_msg));
|
||||
string_clear(dialog_msg);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, SubBruteSceneStart);
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Returned error: %d", load_result);
|
||||
|
||||
string_t dialog_msg;
|
||||
string_init(dialog_msg);
|
||||
string_cat_printf(
|
||||
dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result));
|
||||
dialog_message_show_storage_error(instance->dialogs, string_get_cstr(dialog_msg));
|
||||
string_clear(dialog_msg);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, SubBruteSceneStart);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "../views/subbrute_attack_view.h"
|
||||
#include "../helpers/subbrute_worker.h"
|
||||
|
||||
#define TAG "SubBruteSceneRunAttack"
|
||||
|
||||
static void subbrute_scene_run_attack_callback(SubBruteCustomEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
@@ -10,10 +12,57 @@ static void subbrute_scene_run_attack_callback(SubBruteCustomEvent event, void*
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, event);
|
||||
}
|
||||
|
||||
//static void subbrute_scene_run_attack_worker_callback(void* context) {
|
||||
// SubBruteState* instance = (SubBruteState*)context;
|
||||
//
|
||||
// if(instance->locked || instance->device->key_index + 1 > instance->device->max_value) {
|
||||
// return;
|
||||
// }
|
||||
// instance->locked = true;
|
||||
//
|
||||
// if(subbrute_worker_can_manual_transmit(instance->worker)) {
|
||||
// // Blink
|
||||
// notification_message(instance->notifications, &sequence_blink_yellow_100);
|
||||
// subbrute_device_create_packet_parsed(instance->device, instance->device->key_index, true);
|
||||
//
|
||||
//#ifdef FURI_DEBUG
|
||||
// FURI_LOG_I(TAG, "subbrute_worker_manual_transmit");
|
||||
//#endif
|
||||
// if(subbrute_worker_manual_transmit(instance->worker, instance->device->payload)) {
|
||||
//#ifdef FURI_DEBUG
|
||||
// FURI_LOG_I(TAG, "transmit ok");
|
||||
//#endif
|
||||
// // Make payload for new iteration or exit
|
||||
// if(instance->device->key_index + 1 <= instance->device->max_value) {
|
||||
// instance->device->key_index++;
|
||||
// } else {
|
||||
// view_dispatcher_send_custom_event(
|
||||
// instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Stop
|
||||
// notification_message(instance->notifications, &sequence_blink_stop);
|
||||
// }
|
||||
//
|
||||
// instance->locked = false;
|
||||
// subbrute_attack_view_set_current_step(instance->view_attack, instance->device->key_index);
|
||||
//}
|
||||
|
||||
void subbrute_scene_run_attack_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
// SubBruteAttackState* state = (SubBruteAttackState*)scene_manager_get_scene_state(
|
||||
// instance->scene_manager, SubBruteSceneRunAttack);
|
||||
// furi_assert(state);
|
||||
//
|
||||
// furi_timer_free(state->timer);
|
||||
// free(state);
|
||||
|
||||
if(subbrute_worker_get_continuous_worker(instance->worker)) {
|
||||
subbrute_worker_stop(instance->worker);
|
||||
}
|
||||
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
|
||||
@@ -21,6 +70,10 @@ void subbrute_scene_run_attack_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
SubBruteAttackView* view = instance->view_attack;
|
||||
//
|
||||
// SubBruteAttackState* state = malloc(sizeof(SubBruteAttackState));
|
||||
// scene_manager_set_scene_state(
|
||||
// instance->scene_manager, SubBruteSceneRunAttack, (uint32_t)state);
|
||||
|
||||
instance->current_view = SubBruteViewAttack;
|
||||
subbrute_attack_view_set_callback(view, subbrute_scene_run_attack_callback, instance);
|
||||
@@ -33,47 +86,107 @@ void subbrute_scene_run_attack_on_enter(void* context) {
|
||||
instance->device->key_index,
|
||||
true);
|
||||
|
||||
// Start worker if not started
|
||||
subbrute_worker_init_manual_transmit(
|
||||
instance->worker,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
string_get_cstr(instance->device->protocol_name));
|
||||
if(subbrute_worker_get_continuous_worker(instance->worker)) {
|
||||
// Init Continuous worker with values!
|
||||
if(!subbrute_worker_start(
|
||||
instance->worker,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
string_get_cstr(instance->device->protocol_name))) {
|
||||
FURI_LOG_W(TAG, "Worker Continuous init failed!");
|
||||
}
|
||||
} else {
|
||||
// Init worker with values
|
||||
if(!subbrute_worker_init_manual_transmit(
|
||||
instance->worker,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
string_get_cstr(instance->device->protocol_name))) {
|
||||
FURI_LOG_W(TAG, "Worker init failed!");
|
||||
}
|
||||
|
||||
// state->timer = furi_timer_alloc(
|
||||
// subbrute_scene_run_attack_worker_callback, FuriTimerTypePeriodic, instance);
|
||||
// furi_timer_start(state->timer, pdMS_TO_TICKS(100)); // 20 ms
|
||||
}
|
||||
}
|
||||
|
||||
bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) {
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
SubBruteAttackView* view = instance->view_attack;
|
||||
// SubBruteAttackState* state = (SubBruteAttackState*)scene_manager_get_scene_state(
|
||||
// instance->scene_manager, SubBruteSceneRunAttack);
|
||||
// furi_assert(state);
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
SubBruteAttackView* view = instance->view_attack;
|
||||
|
||||
if(event.event == SubBruteCustomEventTypeTransmitNotStarted ||
|
||||
event.event == SubBruteCustomEventTypeTransmitFinished ||
|
||||
event.event == SubBruteCustomEventTypeBackPressed) {
|
||||
// furi_timer_stop(state->timer);
|
||||
// Stop transmit
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
notification_message(instance->notifications, &sequence_display_backlight_on);
|
||||
notification_message(instance->notifications, &sequence_single_vibro);
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
consumed = true;
|
||||
} else if(event.event == SubBruteCustomEventTypeUpdateView) {
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subbrute_worker_can_transmit(instance->worker)) {
|
||||
// Blink
|
||||
notification_message(instance->notifications, &sequence_blink_yellow_100);
|
||||
if(subbrute_worker_get_continuous_worker(instance->worker)) {
|
||||
if(subbrute_worker_can_transmit(instance->worker)) {
|
||||
// Blink
|
||||
notification_message(instance->notifications, &sequence_blink_yellow_100);
|
||||
|
||||
if(subbrute_worker_manual_transmit(instance->worker, instance->device->payload)) {
|
||||
// Make payload for new iteration or exit
|
||||
if(instance->device->key_index + 1 > instance->device->max_value) {
|
||||
// End of list
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
} else {
|
||||
instance->device->key_index++;
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
subbrute_device_create_packet_parsed(
|
||||
instance->device, instance->device->key_index);
|
||||
subbrute_device_create_packet_parsed(
|
||||
instance->device, instance->device->key_index, true);
|
||||
|
||||
if(subbrute_worker_transmit(instance->worker, instance->device->payload)) {
|
||||
// Make payload for new iteration or exit
|
||||
if(instance->device->key_index + 1 > instance->device->max_value) {
|
||||
// End of list
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
||||
} else {
|
||||
instance->device->key_index++;
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeUpdateView);
|
||||
//subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
// Stop
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
} else {
|
||||
if(subbrute_worker_can_manual_transmit(instance->worker, false)) {
|
||||
// Blink
|
||||
notification_message(instance->notifications, &sequence_blink_yellow_100);
|
||||
|
||||
subbrute_device_create_packet_parsed(
|
||||
instance->device, instance->device->key_index, true);
|
||||
|
||||
if(subbrute_worker_manual_transmit(instance->worker, instance->device->payload)) {
|
||||
// Make payload for new iteration or exit
|
||||
if(instance->device->key_index + 1 > instance->device->max_value) {
|
||||
// End of list
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
||||
} else {
|
||||
instance->device->key_index++;
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeUpdateView);
|
||||
//subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
|
||||
@@ -21,7 +21,7 @@ bool subbrute_scene_save_success_on_event(void* context, SceneManagerEvent event
|
||||
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
//SubBruteMainView* view = instance->view_main;
|
||||
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubBruteCustomEventTypePopupClosed) {
|
||||
if(!scene_manager_search_and_switch_to_previous_scene(
|
||||
|
||||
@@ -27,11 +27,13 @@ void subbrute_scene_setup_attack_on_enter(void* context) {
|
||||
instance->device->key_index,
|
||||
false);
|
||||
|
||||
subbrute_worker_init_manual_transmit(
|
||||
instance->worker,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
string_get_cstr(instance->device->protocol_name));
|
||||
if(!subbrute_worker_init_manual_transmit(
|
||||
instance->worker,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
string_get_cstr(instance->device->protocol_name))) {
|
||||
FURI_LOG_W(TAG, "Worker init failed!");
|
||||
}
|
||||
|
||||
instance->current_view = SubBruteViewAttack;
|
||||
subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance);
|
||||
@@ -55,7 +57,13 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubBruteCustomEventTypeTransmitStarted) {
|
||||
subbrute_device_create_packet_parsed(instance->device, instance->device->key_index);
|
||||
subbrute_worker_set_continuous_worker(instance->worker, false);
|
||||
subbrute_attack_view_set_worker_type(view, false);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack);
|
||||
} else if(event.event == SubBruteCustomEventTypeTransmitContinuousStarted) {
|
||||
// Setting different type of worker
|
||||
subbrute_worker_set_continuous_worker(instance->worker, true);
|
||||
subbrute_attack_view_set_worker_type(view, true);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack);
|
||||
} else if(event.event == SubBruteCustomEventTypeSaveFile) {
|
||||
subbrute_worker_manual_transmit_stop(instance->worker);
|
||||
@@ -94,8 +102,8 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
||||
}
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) {
|
||||
// +100
|
||||
uint64_t value = instance->device->key_index + 100;
|
||||
// +50
|
||||
uint64_t value = instance->device->key_index + 50;
|
||||
if(value == instance->device->max_value) {
|
||||
instance->device->key_index += value;
|
||||
} else {
|
||||
@@ -118,8 +126,8 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
||||
}
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) {
|
||||
// -100
|
||||
uint64_t value = ((instance->device->key_index - 100) + instance->device->max_value);
|
||||
// -50
|
||||
uint64_t value = ((instance->device->key_index - 50) + instance->device->max_value);
|
||||
if(value == instance->device->max_value) {
|
||||
instance->device->key_index = value;
|
||||
} else {
|
||||
@@ -127,7 +135,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
||||
}
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
} else if(event.event == SubBruteCustomEventTypeTransmitCustom) {
|
||||
if(subbrute_worker_can_transmit(instance->worker)) {
|
||||
if(subbrute_worker_can_manual_transmit(instance->worker, true)) {
|
||||
// Blink
|
||||
notification_message(instance->notifications, &sequence_blink_green_100);
|
||||
|
||||
@@ -139,7 +147,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
||||
// string_get_cstr(instance->device->protocol_name));
|
||||
// }
|
||||
subbrute_device_create_packet_parsed(
|
||||
instance->device, instance->device->key_index);
|
||||
instance->device, instance->device->key_index, false);
|
||||
subbrute_worker_manual_transmit(instance->worker, instance->device->payload);
|
||||
|
||||
// Stop
|
||||
|
||||
@@ -21,29 +21,31 @@
|
||||
#define TAG "SubBruteApp"
|
||||
|
||||
static const char* subbrute_menu_names[] = {
|
||||
[SubBruteAttackCAME12bit307] = "CAME 12bit 307mhz",
|
||||
[SubBruteAttackCAME12bit433] = "CAME 12bit 433mhz",
|
||||
[SubBruteAttackCAME12bit868] = "CAME 12bit 868mhz",
|
||||
[SubBruteAttackChamberlain9bit315] = "Chamberlain 9bit 315mhz",
|
||||
[SubBruteAttackChamberlain9bit390] = "Chamberlain 9bit 390mhz",
|
||||
[SubBruteAttackLinear10bit300] = "Linear 10bit 300mhz",
|
||||
[SubBruteAttackLinear10bit310] = "Linear 10bit 310mhz",
|
||||
[SubBruteAttackNICE12bit433] = "NICE 12bit 433mhz",
|
||||
[SubBruteAttackNICE12bit868] = "NICE 12bit 868mhz",
|
||||
[SubBruteAttackCAME12bit307] = "CAME 12bit 307MHz",
|
||||
[SubBruteAttackCAME12bit433] = "CAME 12bit 433MHz",
|
||||
[SubBruteAttackCAME12bit868] = "CAME 12bit 868MHz",
|
||||
[SubBruteAttackNICE12bit433] = "NICE 12bit 433MHz",
|
||||
[SubBruteAttackNICE12bit868] = "NICE 12bit 868MHz",
|
||||
[SubBruteAttackChamberlain9bit300] = "Chamberlain 9bit 300MHz",
|
||||
[SubBruteAttackChamberlain9bit315] = "Chamberlain 9bit 315MHz",
|
||||
[SubBruteAttackChamberlain9bit390] = "Chamberlain 9bit 390MHz",
|
||||
[SubBruteAttackLinear10bit300] = "Linear 10bit 300MHz",
|
||||
[SubBruteAttackLinear10bit310] = "Linear 10bit 310MHz",
|
||||
[SubBruteAttackLoadFile] = "BF existing dump",
|
||||
[SubBruteAttackTotalCount] = "Total Count",
|
||||
};
|
||||
|
||||
static const char* subbrute_menu_names_small[] = {
|
||||
[SubBruteAttackCAME12bit307] = "CAME 307mhz",
|
||||
[SubBruteAttackCAME12bit433] = "CAME 433mhz",
|
||||
[SubBruteAttackCAME12bit868] = "CAME 868mhz",
|
||||
[SubBruteAttackChamberlain9bit315] = "Cham 315mhz",
|
||||
[SubBruteAttackChamberlain9bit390] = "Cham 390mhz",
|
||||
[SubBruteAttackLinear10bit300] = "Linear 300mhz",
|
||||
[SubBruteAttackLinear10bit310] = "Linear 310mhz",
|
||||
[SubBruteAttackNICE12bit433] = "NICE 433mhz",
|
||||
[SubBruteAttackNICE12bit868] = "NICE 868mhz",
|
||||
[SubBruteAttackCAME12bit307] = "CAME 307MHz",
|
||||
[SubBruteAttackCAME12bit433] = "CAME 433MHz",
|
||||
[SubBruteAttackCAME12bit868] = "CAME 868MHz",
|
||||
[SubBruteAttackNICE12bit433] = "NICE 433MHz",
|
||||
[SubBruteAttackNICE12bit868] = "NICE 868MHz",
|
||||
[SubBruteAttackChamberlain9bit300] = "Cham 300MHz",
|
||||
[SubBruteAttackChamberlain9bit315] = "Cham 315MHz",
|
||||
[SubBruteAttackChamberlain9bit390] = "Cham 390MHz",
|
||||
[SubBruteAttackLinear10bit300] = "Linear 300MHz",
|
||||
[SubBruteAttackLinear10bit310] = "Linear 310MHz",
|
||||
[SubBruteAttackLoadFile] = "Existing",
|
||||
[SubBruteAttackTotalCount] = "Total Count",
|
||||
};
|
||||
@@ -81,7 +83,7 @@ SubBruteState* subbrute_alloc() {
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
instance->view_dispatcher, subbrute_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
instance->view_dispatcher, subbrute_tick_event_callback, 100);
|
||||
instance->view_dispatcher, subbrute_tick_event_callback, 10);
|
||||
|
||||
//Dialog
|
||||
instance->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
@@ -142,12 +144,6 @@ SubBruteState* subbrute_alloc() {
|
||||
void subbrute_free(SubBruteState* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
// SubBruteDevice
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteDevice");
|
||||
#endif
|
||||
subbrute_device_free(instance->device);
|
||||
|
||||
// SubBruteWorker
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteDevice");
|
||||
@@ -155,6 +151,12 @@ void subbrute_free(SubBruteState* instance) {
|
||||
subbrute_worker_stop(instance->worker);
|
||||
subbrute_worker_free(instance->worker);
|
||||
|
||||
// SubBruteDevice
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteDevice");
|
||||
#endif
|
||||
subbrute_device_free(instance->device);
|
||||
|
||||
// Notifications
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free Notifications");
|
||||
@@ -297,6 +299,7 @@ int32_t subbrute_app(void* p) {
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart);
|
||||
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
notification_message(instance->notifications, &sequence_display_backlight_on);
|
||||
view_dispatcher_run(instance->view_dispatcher);
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
subbrute_free(instance);
|
||||
|
||||
@@ -10,11 +10,12 @@ typedef enum {
|
||||
SubBruteCustomEventTypeBackPressed,
|
||||
SubBruteCustomEventTypeIndexSelected,
|
||||
SubBruteCustomEventTypeTransmitStarted,
|
||||
SubBruteCustomEventTypeTransmitContinuousStarted,
|
||||
SubBruteCustomEventTypeTransmitFinished,
|
||||
SubBruteCustomEventTypeTransmitNotStarted,
|
||||
SubBruteCustomEventTypeTransmitCustom,
|
||||
SubBruteCustomEventTypeSaveFile,
|
||||
SubBruteCustomEventTypeSaveSuccess,
|
||||
SubBruteCustomEventTypeUpdateView,
|
||||
SubBruteCustomEventTypeChangeStepUp,
|
||||
SubBruteCustomEventTypeChangeStepDown,
|
||||
SubBruteCustomEventTypeChangeStepUpMore,
|
||||
|
||||
@@ -37,6 +37,8 @@ static const char* subbrute_key_file_start =
|
||||
"Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d";
|
||||
static const char* subbrute_key_file_key = "%s\nKey: %s\n";
|
||||
static const char* subbrute_key_file_princeton_end = "%s\nKey: %s\nTE: %d\n";
|
||||
static const char* subbrute_key_small_no_tail = "Bit: %d\nKey: %s\n";
|
||||
static const char* subbrute_key_small_with_tail = "Bit: %d\nKey: %s\nTE: %d\n";
|
||||
|
||||
// Why nobody set in as const in all codebase?
|
||||
static const char* preset_ook270_async = "FuriHalSubGhzPresetOok270Async";
|
||||
@@ -58,7 +60,7 @@ SubBruteDevice* subbrute_device_alloc() {
|
||||
|
||||
instance->decoder_result = NULL;
|
||||
instance->receiver = NULL;
|
||||
instance->environment = NULL;
|
||||
instance->environment = subghz_environment_alloc();
|
||||
|
||||
subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit307);
|
||||
|
||||
@@ -82,13 +84,8 @@ void subbrute_device_free(SubBruteDevice* instance) {
|
||||
instance->receiver = NULL;
|
||||
}
|
||||
|
||||
if(instance->environment != NULL) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subghz_environment_free");
|
||||
#endif
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
}
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "before free");
|
||||
@@ -107,7 +104,7 @@ bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_na
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_save_file: %s", dev_file_name);
|
||||
#endif
|
||||
bool result = subbrute_device_create_packet_parsed(instance, instance->key_index);
|
||||
bool result = subbrute_device_create_packet_parsed(instance, instance->key_index, false);
|
||||
|
||||
if(!result) {
|
||||
FURI_LOG_E(TAG, "subbrute_device_create_packet_parsed failed!");
|
||||
@@ -191,7 +188,7 @@ const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t step) {
|
||||
bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t step, bool small) {
|
||||
furi_assert(instance);
|
||||
|
||||
//char step_payload[32];
|
||||
@@ -234,21 +231,40 @@ bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t ste
|
||||
FURI_LOG_D(TAG, "candidate: %s, step: %d", string_get_cstr(candidate), step);
|
||||
#endif
|
||||
|
||||
if(instance->has_tail) {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_file_princeton_end,
|
||||
instance->file_template,
|
||||
string_get_cstr(candidate),
|
||||
instance->te);
|
||||
if(small) {
|
||||
if(instance->has_tail) {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_small_with_tail,
|
||||
instance->bit,
|
||||
string_get_cstr(candidate),
|
||||
instance->te);
|
||||
} else {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_small_no_tail,
|
||||
instance->bit,
|
||||
string_get_cstr(candidate));
|
||||
}
|
||||
} else {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_file_key,
|
||||
instance->file_template,
|
||||
string_get_cstr(candidate));
|
||||
if(instance->has_tail) {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_file_princeton_end,
|
||||
instance->file_template,
|
||||
string_get_cstr(candidate),
|
||||
instance->te);
|
||||
} else {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_file_key,
|
||||
instance->file_template,
|
||||
string_get_cstr(candidate));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
@@ -290,14 +306,16 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute
|
||||
string_set_str(instance->protocol_name, protocol_came);
|
||||
string_set_str(instance->preset_name, preset_ook650_async);
|
||||
break;
|
||||
case SubBruteAttackChamberlain9bit300:
|
||||
case SubBruteAttackChamberlain9bit315:
|
||||
instance->frequency = 315000000;
|
||||
instance->bit = 9;
|
||||
string_set_str(instance->protocol_name, protocol_cham_code);
|
||||
string_set_str(instance->preset_name, preset_ook650_async);
|
||||
break;
|
||||
case SubBruteAttackChamberlain9bit390:
|
||||
instance->frequency = 390000000;
|
||||
if(type == SubBruteAttackChamberlain9bit300) {
|
||||
instance->frequency = 300000000;
|
||||
} else if(type == SubBruteAttackChamberlain9bit315) {
|
||||
instance->frequency = 315000000;
|
||||
} else /* ALWAYS TRUE if(type == SubBruteAttackChamberlain9bit390) */ {
|
||||
instance->frequency = 390000000;
|
||||
}
|
||||
instance->bit = 9;
|
||||
string_set_str(instance->protocol_name, protocol_cham_code);
|
||||
string_set_str(instance->preset_name, preset_ook650_async);
|
||||
@@ -331,13 +349,12 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute
|
||||
return SubBruteFileResultProtocolNotFound; // RETURN
|
||||
}
|
||||
|
||||
if(!furi_hal_subghz_is_tx_allowed(instance->frequency)) {
|
||||
/*if(!furi_hal_subghz_is_tx_allowed(instance->frequency)) {
|
||||
FURI_LOG_E(TAG, "Frequency invalid: %d", instance->frequency);
|
||||
return SubBruteFileResultMissingOrIncorrectFrequency; // RETURN
|
||||
}
|
||||
}*/
|
||||
|
||||
// For non-file types we didn't set SubGhzProtocolDecoderBase
|
||||
instance->environment = subghz_environment_alloc();
|
||||
instance->receiver = subghz_receiver_alloc_init(instance->environment);
|
||||
subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable);
|
||||
furi_hal_subghz_reset();
|
||||
@@ -359,10 +376,8 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute
|
||||
protocol_check_result = SubBruteFileResultOk;
|
||||
}
|
||||
|
||||
subghz_environment_free(instance->environment);
|
||||
subghz_receiver_free(instance->receiver);
|
||||
instance->receiver = NULL;
|
||||
instance->environment = NULL;
|
||||
|
||||
if(protocol_check_result != SubBruteFileResultOk) {
|
||||
return SubBruteFileResultProtocolNotFound;
|
||||
@@ -407,7 +422,7 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute
|
||||
#endif
|
||||
|
||||
// Init payload
|
||||
subbrute_device_create_packet_parsed(instance, instance->key_index);
|
||||
subbrute_device_create_packet_parsed(instance, instance->key_index, false);
|
||||
|
||||
return SubBruteFileResultOk;
|
||||
}
|
||||
@@ -426,7 +441,6 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_p
|
||||
string_init(temp_str);
|
||||
uint32_t temp_data32;
|
||||
|
||||
instance->environment = subghz_environment_alloc();
|
||||
instance->receiver = subghz_receiver_alloc_init(instance->environment);
|
||||
subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable);
|
||||
furi_hal_subghz_reset();
|
||||
@@ -561,12 +575,10 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_p
|
||||
flipper_format_free(fff_data_file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
subghz_environment_free(instance->environment);
|
||||
subghz_receiver_free(instance->receiver);
|
||||
|
||||
instance->decoder_result = NULL;
|
||||
instance->receiver = NULL;
|
||||
instance->environment = NULL;
|
||||
|
||||
if(result == SubBruteFileResultOk) {
|
||||
#ifdef FURI_DEBUG
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user