Skip to content

Commit 6e710c5

Browse files
committed
Merge branch 'dev' into release
2 parents fd56ac3 + 5340ebe commit 6e710c5

30 files changed

+826
-138
lines changed

CHANGELOG.md

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
### New changes
2-
* If you have copied apps into `apps` folder - remove `apps` folder on your microSD before installing this release to avoid issues!
3-
* Dev Builds: Add extra pack dev branch to avoid "bug" reports with `API mismatch`
4-
* App Loader: Add option to ignore api mismatch (warning! some apps WILL not work, please update them to avoid any issues) -> (by @Willy-JL | PR #395)
5-
* SubGHz: Add manually -> GSN protocol support
6-
* SubGHz: Add 318 and 418 MHz back to hopping list
7-
* SubGHz: Fix hopper stuck at 433.42 due to wide range signals -
8-
When we using 433.92 remote flipper in hopping mode will stuck at 433.42 and may loose signal because of that, need to avoid using close freqs in hopping, only freqs with bigger difference like 310 -> 315
9-
* Plugins: Update **TOTP (Authenticator)** [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) -> BadBT Support
10-
* OFW: Screen streaming improvements
11-
* OFW: 1-Wire Overdrive Mode -> **Breaking API change, api was changed from 19.x to 20.x**
12-
* OFW: Disable UART IRQs by default
13-
* OFW: BadUSB: implement boot protocol
14-
* OFW: Remove hmac_sha256 from public API -> **Breaking API change, api was changed from 18.x to 19.x**
15-
**(this will make your manually copied plugins not work, update them in same way you installed them, or delete `apps` folder and then install firmware, if you using extra pack builds (with `e` in version) all apps in _Extra will be updated automatically)**
2+
* SubGHz: AN-Motors AT4 + Alutech AT4N - Add Manually support
3+
* SubGHz: Aprimatic keeloq emulation support + Add Manually
4+
* NFC: MF Classic User Dict -> Fix deleting of the key in extra actions menu
5+
* Plugins: Update WiFi Marauder [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion)
6+
* Plugins: Fix POCSAG pager `RIC:` text repetition and overlap (by @Willy-JL | PR #398)
7+
* OFW: NFC: MF Classic - Additional checks before invalidating the key (Fixes issues with not using MF keys from user dict)
8+
* OFW: Fix crash when emulating a DSGeneric key
169

1710
#### [🎲 Download latest extra apps pack](https://github.com/xMasterX/all-the-plugins/archive/refs/heads/main.zip)
1811

ReadMe.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ Our Discord Community:
5252
- Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
5353
- Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
5454
- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107)
55-
* Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes
56-
* Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu
57-
* Sub-GHz -> External CC1101 module support
55+
* Sub-GHz -> Short press OK in frequency analyzer to save detected frequency for usage in Read modes
56+
* Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu and automatically use selected frequency
57+
* Sub-GHz -> External CC1101 module support (Hardware SPI used)
5858
* SubGHz -> **Hold right in received signal list to delete selected signal**
5959
* SubGHz -> **Custom buttons for Keeloq / Alutech AT4N / Nice Flor S / Somfy Telis / Security+ 2.0** - now you can use arrow buttons to send signal with different button code
6060
* SubGHz -> BFT Mitto / Somfy Telis / Nice Flor S manual creation with programming new remote into receiver (use button 0xF for BFT Mitto, 0x8 (Prog) on Somfy Telis)
@@ -84,10 +84,11 @@ Encoders/sending made by Eng1n33r & @xMasterX:
8484
- Keeloq: Beninca
8585
- Keeloq: Stilmatic / Schellenberg
8686
- Keeloq: CAME Space
87+
- Keeloq: Aprimatic (model TR and similar)
8788
- CAME Atomo
8889
- Nice Flor S
8990
- FAAC SLH (Spa) [External seed calculation required (For info contact me in Discord: Nano#8998)]
90-
- Keeloq: BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)]
91+
- Keeloq: BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)] -> Update! check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
9192
- Security+ v1 & v2
9293
- Star Line
9394

@@ -189,7 +190,7 @@ Games:
189190

190191
## [- How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
191192

192-
## [- How to use Flipper as new remote (Nice FlorS, BFT Mitto, Somfy Telis)](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
193+
## [- How to use Flipper as new remote (Nice FlorS, BFT Mitto, Somfy Telis, Aprimatic, AN-Motors, etc..)](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
193194

194195
## [- Configure Sub-GHz Remote App](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
195196

applications/external/pocsag_pager/protocols/pocsag.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,7 @@ static bool pocsag_decode_message_word(SubGhzProtocolDecoderPocsag* instance, ui
157157
// Function called when current message got decoded, but other messages might follow
158158
static void pocsag_message_done(SubGhzProtocolDecoderPocsag* instance) {
159159
// append the message to the long-term storage string
160-
furi_string_cat_printf(
161-
instance->generic.result_ric, "\e#RIC: %" PRIu32 "\e# | ", instance->ric);
160+
furi_string_printf(instance->generic.result_ric, "\e#RIC: %" PRIu32 "\e# | ", instance->ric);
162161
furi_string_cat_str(instance->generic.result_ric, func_msg[instance->func]);
163162
if(instance->func != POCSAG_FUNC_ALERT1) {
164163
furi_string_cat(instance->done_msg, instance->msg);

applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,8 @@ bool totp_scene_generate_token_handle_event(
373373

374374
SceneState* scene_state;
375375
if(event->input.type == InputTypeLong) {
376-
if(event->input.key == InputKeyDown && plugin_state->automation_method & AutomationMethodBadUsb) {
376+
if(event->input.key == InputKeyDown &&
377+
plugin_state->automation_method & AutomationMethodBadUsb) {
377378
scene_state = (SceneState*)plugin_state->current_scene_state;
378379
totp_usb_type_code_worker_notify(
379380
scene_state->usb_type_code_worker_context, TotpUsbTypeCodeWorkerEventType);
@@ -383,7 +384,9 @@ bool totp_scene_generate_token_handle_event(
383384
return true;
384385
}
385386
#ifdef TOTP_BADBT_TYPE_ENABLED
386-
else if(event->input.key == InputKeyUp && plugin_state->automation_method & AutomationMethodBadBt) {
387+
else if(
388+
event->input.key == InputKeyUp &&
389+
plugin_state->automation_method & AutomationMethodBadBt) {
387390
scene_state = (SceneState*)plugin_state->current_scene_state;
388391
totp_bt_type_code_worker_notify(
389392
plugin_state->bt_type_code_worker_context, TotpBtTypeCodeWorkerEventType);

applications/external/wifi_marauder_companion/application.fam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ App(
44
apptype=FlipperAppType.EXTERNAL,
55
entry_point="wifi_marauder_app",
66
requires=["gui"],
7-
stack_size=1 * 1024,
7+
stack_size=4 * 1024,
88
order=90,
99
fap_icon="wifi_10px.png",
1010
fap_category="GPIO",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
ADD_SCENE(wifi_marauder, start, Start)
22
ADD_SCENE(wifi_marauder, console_output, ConsoleOutput)
33
ADD_SCENE(wifi_marauder, text_input, TextInput)
4+
ADD_SCENE(wifi_marauder, settings_init, SettingsInit)
5+
ADD_SCENE(wifi_marauder, log_viewer, LogViewer)

applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ void wifi_marauder_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, vo
44
furi_assert(context);
55
WifiMarauderApp* app = context;
66

7+
if(app->is_writing_log) {
8+
app->has_saved_logs_this_session = true;
9+
storage_file_write(app->log_file, buf, len);
10+
}
11+
712
// If text box store gets too big, then truncate it
813
app->text_box_store_strlen += len;
914
if(app->text_box_store_strlen >= WIFI_MARAUDER_TEXT_BOX_STORE_SIZE - 1) {
@@ -21,15 +26,7 @@ void wifi_marauder_console_output_handle_rx_packets_cb(uint8_t* buf, size_t len,
2126
furi_assert(context);
2227
WifiMarauderApp* app = context;
2328

24-
// If it is a sniff function, open the pcap file for recording
25-
if(strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0 && !app->is_writing) {
26-
app->is_writing = true;
27-
if(!app->capture_file || !storage_file_is_open(app->capture_file)) {
28-
wifi_marauder_create_pcap_file(app);
29-
}
30-
}
31-
32-
if(app->is_writing) {
29+
if(app->is_writing_pcap) {
3330
storage_file_write(app->capture_file, buf, len);
3431
}
3532
}
@@ -49,8 +46,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
4946
furi_string_reset(app->text_box_store);
5047
app->text_box_store_strlen = 0;
5148
if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) {
52-
const char* help_msg = "Marauder companion " WIFI_MARAUDER_APP_VERSION
53-
"\nby @0xchocolate\nmodified by @tcpassos\n";
49+
const char* help_msg = "Marauder companion " WIFI_MARAUDER_APP_VERSION "\n";
5450
furi_string_cat_str(app->text_box_store, help_msg);
5551
app->text_box_store_strlen += strlen(help_msg);
5652
}
@@ -62,7 +58,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
6258
}
6359
}
6460

65-
// Set starting text - for "View Log", this will just be what was already in the text box store
61+
// Set starting text - for "View Log from end", this will just be what was already in the text box store
6662
text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
6763

6864
scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneConsoleOutput, 0);
@@ -76,8 +72,23 @@ void wifi_marauder_scene_console_output_on_enter(void* context) {
7672
app->lp_uart,
7773
wifi_marauder_console_output_handle_rx_packets_cb); // setup callback for packets rx thread
7874

79-
// Send command with newline '\n'
75+
// Get ready to send command
8076
if(app->is_command && app->selected_tx_string) {
77+
// Create files *before* sending command
78+
// (it takes time to iterate through the directory)
79+
if(app->ok_to_save_logs) {
80+
app->is_writing_log = true;
81+
wifi_marauder_create_log_file(app);
82+
}
83+
84+
// If it is a sniff function, open the pcap file for recording
85+
if(app->ok_to_save_pcaps &&
86+
strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0) {
87+
app->is_writing_pcap = true;
88+
wifi_marauder_create_pcap_file(app);
89+
}
90+
91+
// Send command with newline '\n'
8192
wifi_marauder_uart_tx(
8293
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
8394
wifi_marauder_uart_tx((uint8_t*)("\n"), 1);
@@ -111,8 +122,13 @@ void wifi_marauder_scene_console_output_on_exit(void* context) {
111122
wifi_marauder_uart_tx((uint8_t*)("stopscan\n"), strlen("stopscan\n"));
112123
}
113124

114-
app->is_writing = false;
125+
app->is_writing_pcap = false;
115126
if(app->capture_file && storage_file_is_open(app->capture_file)) {
116127
storage_file_close(app->capture_file);
117128
}
129+
130+
app->is_writing_log = false;
131+
if(app->log_file && storage_file_is_open(app->log_file)) {
132+
storage_file_close(app->log_file);
133+
}
118134
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#include "../wifi_marauder_app_i.h"
2+
3+
void wifi_marauder_scene_log_viewer_widget_callback(
4+
GuiButtonType result,
5+
InputType type,
6+
void* context) {
7+
WifiMarauderApp* app = context;
8+
if(type == InputTypeShort) {
9+
view_dispatcher_send_custom_event(app->view_dispatcher, result);
10+
}
11+
}
12+
13+
static void _read_log_page_into_text_store(WifiMarauderApp* app) {
14+
char temp[64 + 1];
15+
storage_file_seek(
16+
app->log_file, WIFI_MARAUDER_TEXT_BOX_STORE_SIZE * (app->open_log_file_page - 1), true);
17+
furi_string_reset(app->text_box_store);
18+
for(uint16_t i = 0; i < (WIFI_MARAUDER_TEXT_BOX_STORE_SIZE / (sizeof(temp) - 1)); i++) {
19+
uint16_t num_bytes = storage_file_read(app->log_file, temp, sizeof(temp) - 1);
20+
if(num_bytes == 0) {
21+
break;
22+
}
23+
temp[num_bytes] = '\0';
24+
furi_string_cat_str(app->text_box_store, temp);
25+
}
26+
}
27+
28+
void wifi_marauder_scene_log_viewer_setup_widget(WifiMarauderApp* app, bool called_from_browse) {
29+
Widget* widget = app->widget;
30+
bool is_open = storage_file_is_open(app->log_file);
31+
bool should_open_log = (app->has_saved_logs_this_session || called_from_browse);
32+
if(is_open) {
33+
_read_log_page_into_text_store(app);
34+
} else if(
35+
should_open_log &&
36+
storage_file_open(app->log_file, app->log_file_path, FSAM_READ, FSOM_OPEN_EXISTING)) {
37+
uint64_t filesize = storage_file_size(app->log_file);
38+
app->open_log_file_num_pages = filesize / WIFI_MARAUDER_TEXT_BOX_STORE_SIZE;
39+
int extra_page = (filesize % WIFI_MARAUDER_TEXT_BOX_STORE_SIZE != 0) ? 1 : 0;
40+
app->open_log_file_num_pages = (filesize / WIFI_MARAUDER_TEXT_BOX_STORE_SIZE) + extra_page;
41+
app->open_log_file_page = 1;
42+
_read_log_page_into_text_store(app);
43+
} else {
44+
app->open_log_file_page = 0;
45+
app->open_log_file_num_pages = 0;
46+
}
47+
48+
widget_reset(widget);
49+
50+
if(furi_string_empty(app->text_box_store)) {
51+
char help_msg[256];
52+
snprintf(
53+
help_msg,
54+
sizeof(help_msg),
55+
"The log is empty! :(\nTry sending a command?\n\nSaving pcaps to flipper sdcard: %s\nSaving logs to flipper sdcard: %s",
56+
app->ok_to_save_pcaps ? "ON" : "OFF",
57+
app->ok_to_save_logs ? "ON" : "OFF");
58+
furi_string_set_str(app->text_box_store, help_msg);
59+
}
60+
61+
widget_add_text_scroll_element(
62+
widget, 0, 0, 128, 53, furi_string_get_cstr(app->text_box_store));
63+
64+
if(1 < app->open_log_file_page && app->open_log_file_page < app->open_log_file_num_pages) {
65+
// hide "Browse" text for middle pages
66+
widget_add_button_element(
67+
widget, GuiButtonTypeCenter, "", wifi_marauder_scene_log_viewer_widget_callback, app);
68+
} else {
69+
// only show "Browse" text on first and last page
70+
widget_add_button_element(
71+
widget,
72+
GuiButtonTypeCenter,
73+
"Browse",
74+
wifi_marauder_scene_log_viewer_widget_callback,
75+
app);
76+
}
77+
78+
char pagecounter[100];
79+
snprintf(
80+
pagecounter,
81+
sizeof(pagecounter),
82+
"%d/%d",
83+
app->open_log_file_page,
84+
app->open_log_file_num_pages);
85+
if(app->open_log_file_page > 1) {
86+
if(app->open_log_file_page == app->open_log_file_num_pages) {
87+
// only show left side page-count on last page
88+
widget_add_button_element(
89+
widget,
90+
GuiButtonTypeLeft,
91+
pagecounter,
92+
wifi_marauder_scene_log_viewer_widget_callback,
93+
app);
94+
} else {
95+
widget_add_button_element(
96+
widget, GuiButtonTypeLeft, "", wifi_marauder_scene_log_viewer_widget_callback, app);
97+
}
98+
}
99+
if(app->open_log_file_page < app->open_log_file_num_pages) {
100+
widget_add_button_element(
101+
widget,
102+
GuiButtonTypeRight,
103+
pagecounter,
104+
wifi_marauder_scene_log_viewer_widget_callback,
105+
app);
106+
}
107+
}
108+
109+
void wifi_marauder_scene_log_viewer_on_enter(void* context) {
110+
WifiMarauderApp* app = context;
111+
112+
app->open_log_file_page = 0;
113+
app->open_log_file_num_pages = 0;
114+
bool saved_logs_exist = false;
115+
if(!app->has_saved_logs_this_session && furi_string_empty(app->text_box_store)) {
116+
// no commands sent yet this session, find last saved log
117+
if(storage_dir_open(app->log_file, MARAUDER_APP_FOLDER_LOGS)) {
118+
char name[70];
119+
char lastname[70];
120+
while(storage_dir_read(app->log_file, NULL, name, sizeof(name))) {
121+
// keep reading directory until last file is reached
122+
strlcpy(lastname, name, sizeof(lastname));
123+
saved_logs_exist = true;
124+
}
125+
if(saved_logs_exist) {
126+
snprintf(
127+
app->log_file_path,
128+
sizeof(app->log_file_path),
129+
"%s/%s",
130+
MARAUDER_APP_FOLDER_LOGS,
131+
lastname);
132+
}
133+
}
134+
storage_dir_close(app->log_file);
135+
}
136+
137+
wifi_marauder_scene_log_viewer_setup_widget(app, saved_logs_exist);
138+
139+
view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewWidget);
140+
}
141+
142+
bool wifi_marauder_scene_log_viewer_on_event(void* context, SceneManagerEvent event) {
143+
WifiMarauderApp* app = context;
144+
bool consumed = false;
145+
146+
if(event.type == SceneManagerEventTypeCustom) {
147+
if(event.event == GuiButtonTypeCenter) {
148+
// Browse
149+
FuriString* predefined_filepath = furi_string_alloc_set_str(MARAUDER_APP_FOLDER_LOGS);
150+
FuriString* selected_filepath = furi_string_alloc();
151+
if(dialog_file_browser_show(
152+
app->dialogs, selected_filepath, predefined_filepath, NULL)) {
153+
strncpy(
154+
app->log_file_path,
155+
furi_string_get_cstr(selected_filepath),
156+
sizeof(app->log_file_path));
157+
if(storage_file_is_open(app->log_file)) {
158+
storage_file_close(app->log_file);
159+
}
160+
wifi_marauder_scene_log_viewer_setup_widget(app, true);
161+
}
162+
furi_string_free(selected_filepath);
163+
furi_string_free(predefined_filepath);
164+
consumed = true;
165+
} else if(event.event == GuiButtonTypeRight) {
166+
// Advance page
167+
++app->open_log_file_page;
168+
wifi_marauder_scene_log_viewer_setup_widget(app, false);
169+
} else if(event.event == GuiButtonTypeLeft) {
170+
// Previous page
171+
--app->open_log_file_page;
172+
wifi_marauder_scene_log_viewer_setup_widget(app, false);
173+
}
174+
}
175+
176+
return consumed;
177+
}
178+
179+
void wifi_marauder_scene_log_viewer_on_exit(void* context) {
180+
WifiMarauderApp* app = context;
181+
widget_reset(app->widget);
182+
if(storage_file_is_open(app->log_file)) {
183+
storage_file_close(app->log_file);
184+
}
185+
}

0 commit comments

Comments
 (0)