Merge branch 'DarkFlippers:dev' into 420darkupds

This commit is contained in:
RogueMaster
2022-10-10 01:39:56 -04:00
committed by GitHub
14 changed files with 141 additions and 111 deletions

View File

@@ -1,37 +1,7 @@
### New changes ### New changes
* Issues with hopping in subghz are fixed in this release * SubGHz: Fixed bugs with Decode option for RAW signals (blank screen, broken files)
* OFW PR: Desktop: Set external apps as favorites (OFW PR 1816 by @djsime1) (and fixed forgotten furi_record_close) * SubGHz: Allowed usage of hopper with detect raw feature (with attempt to fix) - WARNING -> This feature is very unstable, may cause crashes(with lost of captured signal), use at your own risk, it was enabled due to many requests from users
* PR -> Plugins: Add CAME 12bit 303MHz to SubGHz Bruteforcer (by @derskythe | PR #87) * PR -> Docs, fix description - Slight update for newest dev method (by @UberGuidoZ | PR #93)
* PR -> BadUSB: Added Norwegian keyboard layout for BadUSB (by @jd-raymaker | PR #88)
* PR -> Plugins: Feature: allow to set ball speed in Arkanoid (by @an4tur0r | PR #92)
* Add USB Keyboard (& Mouse) plugin, replacing default USB Mouse demo included (plugin by @huuck) [Link to original](https://github.com/huuck/FlipperZeroUSBKeyboard)
* Fix USB Keyboard plugin wrong icon in mouse screen, rewrite view models to new type
* Updated universal remote assets (by @Amec0e)
* Plugins: SubGHz Bruteforcer - Fix wrong max value in BF existing dump
* API 3.0 -> 3.2 (all previous compiled apps still compatible)
* Add 312.2 MHz to subghz user config
* SubGHz: Fix double click after delete scene, fix rename bug
* SubGHz: proper free of rainbow tables
* SubGHz: Fixed stability issues with Came atomo, Nice Flor S, limited max history items to 60 (was 65)
* SubGHz: Fix Read screen GUI (still bugged in OFW)
* Adapted all plugins and other code to new FuriString, fixed all new issues with new string type
* Adapted all plugins to new printf format
* Adapted all plugins to new view model format (aka Removing lambdas)
* Adapted all plugins to new furi_stream
* OFW: Elf loader: do not load .ARM.* sections
* OFW: Removing lambdas
* OFW: BadUSB: add SYSRQ keys
* OFW: Gui: fix memory leak in file browser module
* OFW: music_player: Return to browser instead of exiting on back button
* OFW: More correct elf loader
* OFW: Furi stream buffer
* OFW: Printf function attributes
* OFW: App name in CLI loader command, RFID data edit fix
* OFW: Show in-app icons & names in archive browser
* OFW: M*LIB: non-inlined strings, FuriString primitive
* OFW: Remove string_push_uint64
* OFW: Mifare Classic read improvements
* OFW PR: updated icon names (OFW PR 1829 by nminaylov)
#### [🎲 Download extra apps pack](https://download-directory.github.io/?url=https://github.com/UberGuidoZ/Flipper/tree/main/Applications/Unleashed) #### [🎲 Download extra apps pack](https://download-directory.github.io/?url=https://github.com/UberGuidoZ/Flipper/tree/main/Applications/Unleashed)

View File

@@ -7,6 +7,6 @@ App(
requires=["gui"], requires=["gui"],
stack_size=2 * 1024, stack_size=2 * 1024,
order=70, order=70,
fap_icon="../../../assets/icons/Archive/keyboard_10px.png", fap_icon="uart_10px.png",
fap_category="Misc", fap_category="Misc",
) )

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -22,15 +22,6 @@
// [X] Find good value for SAMPLES_TO_READ_PER_TICK // [X] Find good value for SAMPLES_TO_READ_PER_TICK
// [X] Fix: read errors (slow flash) after aborting decode read // [X] Fix: read errors (slow flash) after aborting decode read
typedef enum {
SubGhzDecodeRawStateStart,
SubGhzDecodeRawStateLoading,
SubGhzDecodeRawStateLoaded,
} SubGhzDecodeRawState;
SubGhzDecodeRawState decode_raw_state = SubGhzDecodeRawStateStart;
SubGhzFileEncoderWorker* file_worker_encoder;
static void subghz_scene_receiver_update_statusbar(void* context) { static void subghz_scene_receiver_update_statusbar(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
FuriString* history_stat_str; FuriString* history_stat_str;
@@ -114,8 +105,9 @@ bool subghz_scene_decode_raw_start(SubGhz* subghz) {
if(success) { if(success) {
//FURI_LOG_I(TAG, "Listening at \033[0;33m%s\033[0m.", furi_string_get_cstr(file_name)); //FURI_LOG_I(TAG, "Listening at \033[0;33m%s\033[0m.", furi_string_get_cstr(file_name));
file_worker_encoder = subghz_file_encoder_worker_alloc(); subghz->decode_raw_file_worker_encoder = subghz_file_encoder_worker_alloc();
if(subghz_file_encoder_worker_start(file_worker_encoder, furi_string_get_cstr(file_name))) { if(subghz_file_encoder_worker_start(
subghz->decode_raw_file_worker_encoder, furi_string_get_cstr(file_name))) {
//the worker needs a file in order to open and read part of the file //the worker needs a file in order to open and read part of the file
furi_delay_ms(100); furi_delay_ms(100);
} else { } else {
@@ -123,7 +115,7 @@ bool subghz_scene_decode_raw_start(SubGhz* subghz) {
} }
if(!success) { if(!success) {
subghz_file_encoder_worker_free(file_worker_encoder); subghz_file_encoder_worker_free(subghz->decode_raw_file_worker_encoder);
} }
} }
@@ -135,13 +127,14 @@ bool subghz_scene_decode_raw_next(SubGhz* subghz) {
LevelDuration level_duration; LevelDuration level_duration;
for(uint32_t read = SAMPLES_TO_READ_PER_TICK; read > 0; --read) { for(uint32_t read = SAMPLES_TO_READ_PER_TICK; read > 0; --read) {
level_duration = subghz_file_encoder_worker_get_level_duration(file_worker_encoder); level_duration =
subghz_file_encoder_worker_get_level_duration(subghz->decode_raw_file_worker_encoder);
if(!level_duration_is_reset(level_duration)) { if(!level_duration_is_reset(level_duration)) {
bool level = level_duration_get_level(level_duration); bool level = level_duration_get_level(level_duration);
uint32_t duration = level_duration_get_duration(level_duration); uint32_t duration = level_duration_get_duration(level_duration);
subghz_receiver_decode(subghz->txrx->receiver, level, duration); subghz_receiver_decode(subghz->txrx->receiver, level, duration);
} else { } else {
decode_raw_state = SubGhzDecodeRawStateLoaded; subghz->decode_raw_state = SubGhzDecodeRawStateLoaded;
subghz->state_notifications = SubGhzNotificationStateIDLE; subghz->state_notifications = SubGhzNotificationStateIDLE;
subghz_view_receiver_add_data_progress(subghz->subghz_receiver, "100%"); subghz_view_receiver_add_data_progress(subghz->subghz_receiver, "100%");
@@ -152,7 +145,8 @@ bool subghz_scene_decode_raw_next(SubGhz* subghz) {
// Update progress info // Update progress info
FuriString* progress_str; FuriString* progress_str;
progress_str = furi_string_alloc(); progress_str = furi_string_alloc();
subghz_file_encoder_worker_get_text_progress(file_worker_encoder, progress_str); subghz_file_encoder_worker_get_text_progress(
subghz->decode_raw_file_worker_encoder, progress_str);
subghz_view_receiver_add_data_progress( subghz_view_receiver_add_data_progress(
subghz->subghz_receiver, furi_string_get_cstr(progress_str)); subghz->subghz_receiver, furi_string_get_cstr(progress_str));
@@ -183,11 +177,11 @@ void subghz_scene_decode_raw_on_enter(void* context) {
false); false);
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
if(decode_raw_state == SubGhzDecodeRawStateStart) { if(subghz->decode_raw_state == SubGhzDecodeRawStateStart) {
//Decode RAW to history //Decode RAW to history
subghz_history_reset(subghz->txrx->history); subghz_history_reset(subghz->txrx->history);
if(subghz_scene_decode_raw_start(subghz)) { if(subghz_scene_decode_raw_start(subghz)) {
decode_raw_state = SubGhzDecodeRawStateLoading; subghz->decode_raw_state = SubGhzDecodeRawStateLoading;
subghz->state_notifications = SubGhzNotificationStateRx; subghz->state_notifications = SubGhzNotificationStateRx;
} }
} else { } else {
@@ -216,14 +210,14 @@ bool subghz_scene_decode_raw_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
switch(event.event) { switch(event.event) {
case SubGhzCustomEventViewReceiverBack: case SubGhzCustomEventViewReceiverBack:
decode_raw_state = SubGhzDecodeRawStateStart; subghz->decode_raw_state = SubGhzDecodeRawStateStart;
subghz->txrx->idx_menu_chosen = 0; subghz->txrx->idx_menu_chosen = 0;
subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz); subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz);
if(subghz_file_encoder_worker_is_running(file_worker_encoder)) { if(subghz_file_encoder_worker_is_running(subghz->decode_raw_file_worker_encoder)) {
subghz_file_encoder_worker_stop(file_worker_encoder); subghz_file_encoder_worker_stop(subghz->decode_raw_file_worker_encoder);
} }
subghz_file_encoder_worker_free(file_worker_encoder); subghz_file_encoder_worker_free(subghz->decode_raw_file_worker_encoder);
subghz->state_notifications = SubGhzNotificationStateIDLE; subghz->state_notifications = SubGhzNotificationStateIDLE;
scene_manager_set_scene_state( scene_manager_set_scene_state(
@@ -268,7 +262,7 @@ bool subghz_scene_decode_raw_on_event(void* context, SceneManagerEvent event) {
break; break;
} }
switch(decode_raw_state) { switch(subghz->decode_raw_state) {
case SubGhzDecodeRawStateLoading: case SubGhzDecodeRawStateLoading:
subghz_scene_decode_raw_next(subghz); subghz_scene_decode_raw_next(subghz);
break; break;

View File

@@ -167,6 +167,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
subghz_sleep(subghz); subghz_sleep(subghz);
} }
subghz->txrx->hopper_state = SubGhzHopperStateOFF; subghz->txrx->hopper_state = SubGhzHopperStateOFF;
subghz_history_set_hopper_state(subghz->txrx->history, false);
subghz->txrx->idx_menu_chosen = 0; subghz->txrx->idx_menu_chosen = 0;
subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz); subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz);

View File

@@ -189,64 +189,64 @@ static void subghz_scene_receiver_config_set_detect_raw(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item); SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item); uint8_t index = variable_item_get_current_value_index(item);
if(subghz->txrx->hopper_state == 0) { //if(subghz->txrx->hopper_state == 0) {
variable_item_set_current_value_text(item, detect_raw_text[index]); variable_item_set_current_value_text(item, detect_raw_text[index]);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING #ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz->last_settings->detect_raw = index; subghz->last_settings->detect_raw = index;
subghz_last_settings_set_detect_raw_values(subghz); subghz_last_settings_set_detect_raw_values(subghz);
#else #else
subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]); subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]);
subghz_protocol_decoder_raw_set_auto_mode( subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name( subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME), subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
(index == 1)); (index == 1));
#endif #endif
} else { /*} else {
variable_item_set_current_value_index(item, 0); variable_item_set_current_value_index(item, 0);
} }*/
} }
static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) { static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item); SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item); uint8_t index = variable_item_get_current_value_index(item);
if(subghz_receiver_get_filter(subghz->txrx->receiver) == SubGhzProtocolFlag_Decodable) { //if(subghz_receiver_get_filter(subghz->txrx->receiver) == SubGhzProtocolFlag_Decodable) {
variable_item_set_current_value_text(item, hopping_text[index]); variable_item_set_current_value_text(item, hopping_text[index]);
if(hopping_value[index] == SubGhzHopperStateOFF) { if(hopping_value[index] == SubGhzHopperStateOFF) {
char text_buf[10] = {0}; char text_buf[10] = {0};
snprintf( snprintf(
text_buf, text_buf,
sizeof(text_buf), sizeof(text_buf),
"%lu.%02lu", "%lu.%02lu",
subghz_setting_get_default_frequency(subghz->setting) / 1000000, subghz_setting_get_default_frequency(subghz->setting) / 1000000,
(subghz_setting_get_default_frequency(subghz->setting) % 1000000) / 10000); (subghz_setting_get_default_frequency(subghz->setting) % 1000000) / 10000);
variable_item_set_current_value_text( variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state( (VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig), subghz->scene_manager, SubGhzSceneReceiverConfig),
text_buf); text_buf);
subghz->txrx->preset->frequency = subghz->txrx->preset->frequency = subghz_setting_get_default_frequency(subghz->setting);
subghz_setting_get_default_frequency(subghz->setting); variable_item_set_current_value_index(
variable_item_set_current_value_index( (VariableItem*)scene_manager_get_scene_state(
(VariableItem*)scene_manager_get_scene_state( subghz->scene_manager, SubGhzSceneReceiverConfig),
subghz->scene_manager, SubGhzSceneReceiverConfig), subghz_setting_get_frequency_default_index(subghz->setting));
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];
} else { } else {
variable_item_set_current_value_index(item, 0); 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_history_set_hopper_state(subghz->txrx->history, (index == 1));
/*} else {
variable_item_set_current_value_index(item, 0);
}*/
} }
static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) { static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {

View File

@@ -186,6 +186,10 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) == if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) ==
SubGhzProtocolFlag_Save) { SubGhzProtocolFlag_Save) {
subghz_file_name_clear(subghz); subghz_file_name_clear(subghz);
if(subghz->in_decoder_scene) {
subghz->in_decoder_scene_skip = true;
}
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
} }
return true; return true;
@@ -214,7 +218,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
void subghz_scene_receiver_info_on_exit(void* context) { void subghz_scene_receiver_info_on_exit(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
if(subghz->in_decoder_scene) { if(subghz->in_decoder_scene && !subghz->in_decoder_scene_skip) {
subghz->in_decoder_scene = false; subghz->in_decoder_scene = false;
} }
widget_reset(subghz->widget); widget_reset(subghz->widget);

View File

@@ -27,17 +27,36 @@ bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent event)
SubGhz* subghz = context; SubGhz* subghz = context;
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventSceneSaveSuccess) { if(event.event == SubGhzCustomEventSceneSaveSuccess) {
if(!scene_manager_search_and_switch_to_previous_scene( if(!subghz->in_decoder_scene) {
subghz->scene_manager, SubGhzSceneReceiver)) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWSave;
if(!scene_manager_search_and_switch_to_previous_scene( if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneReadRAW)) { subghz->scene_manager, SubGhzSceneReceiver)) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWSave;
if(!scene_manager_search_and_switch_to_previous_scene( if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneSaved)) { subghz->scene_manager, SubGhzSceneReadRAW)) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved); subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneSaved)) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
}
} }
} }
} else {
subghz->decode_raw_state = SubGhzDecodeRawStateStart;
subghz->txrx->idx_menu_chosen = 0;
subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz);
if(subghz_file_encoder_worker_is_running(subghz->decode_raw_file_worker_encoder)) {
subghz_file_encoder_worker_stop(subghz->decode_raw_file_worker_encoder);
}
subghz_file_encoder_worker_free(subghz->decode_raw_file_worker_encoder);
subghz->state_notifications = SubGhzNotificationStateIDLE;
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet);
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneSaved)) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
}
} }
return true; return true;
} }
@@ -48,6 +67,11 @@ bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent event)
void subghz_scene_save_success_on_exit(void* context) { void subghz_scene_save_success_on_exit(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
if(subghz->in_decoder_scene) {
subghz->in_decoder_scene = false;
subghz->in_decoder_scene_skip = false;
}
// Clear view // Clear view
Popup* popup = subghz->popup; Popup* popup = subghz->popup;
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);

View File

@@ -70,6 +70,7 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
subghz->gui = furi_record_open(RECORD_GUI); subghz->gui = furi_record_open(RECORD_GUI);
subghz->in_decoder_scene = false; subghz->in_decoder_scene = false;
subghz->in_decoder_scene_skip = false;
// View Dispatcher // View Dispatcher
subghz->view_dispatcher = view_dispatcher_alloc(); subghz->view_dispatcher = view_dispatcher_alloc();

View File

@@ -41,6 +41,7 @@ struct SubGhzHistory {
uint8_t code_last_hash_data; uint8_t code_last_hash_data;
FuriString* tmp_string; FuriString* tmp_string;
bool write_tmp_files; bool write_tmp_files;
bool is_hopper_running;
Storage* storage; Storage* storage;
SubGhzHistoryStruct* history; SubGhzHistoryStruct* history;
}; };
@@ -134,6 +135,8 @@ SubGhzHistory* subghz_history_alloc(void) {
instance->storage = furi_record_open(RECORD_STORAGE); instance->storage = furi_record_open(RECORD_STORAGE);
instance->write_tmp_files = subghz_history_check_sdcard(instance); instance->write_tmp_files = subghz_history_check_sdcard(instance);
instance->is_hopper_running = false;
if(!instance->write_tmp_files) { if(!instance->write_tmp_files) {
FURI_LOG_E(TAG, "Unstable work! Cannot use SD Card!"); FURI_LOG_E(TAG, "Unstable work! Cannot use SD Card!");
} }
@@ -209,6 +212,12 @@ void subghz_history_reset(SubGhzHistory* instance) {
instance->code_last_hash_data = 0; instance->code_last_hash_data = 0;
} }
void subghz_history_set_hopper_state(SubGhzHistory* instance, bool hopper_state) {
furi_assert(instance);
instance->is_hopper_running = hopper_state;
}
uint16_t subghz_history_get_item(SubGhzHistory* instance) { uint16_t subghz_history_get_item(SubGhzHistory* instance) {
furi_assert(instance); furi_assert(instance);
return instance->last_index_write; return instance->last_index_write;
@@ -354,16 +363,23 @@ bool subghz_history_add_to_history(
item->protocol_name, "%s", furi_string_get_cstr(instance->tmp_string)); item->protocol_name, "%s", furi_string_get_cstr(instance->tmp_string));
} }
if(!strcmp(furi_string_get_cstr(instance->tmp_string), "RAW")) { if(!strcmp(furi_string_get_cstr(instance->tmp_string), "RAW")) {
// Check if hopper enabled we need to add little delay
if(instance->is_hopper_running) {
furi_delay_ms(40);
}
// Enable writing temp files to micro sd
tmp_file_for_raw = true;
// Write display name
furi_string_printf( furi_string_printf(
item->item_str, item->item_str,
"RAW %03ld.%02ld", "RAW %03ld.%02ld",
preset->frequency / 1000000 % 1000, preset->frequency / 1000000 % 1000,
preset->frequency / 10000 % 100); preset->frequency / 10000 % 100);
// Rewind
if(!flipper_format_rewind(item->flipper_string)) { if(!flipper_format_rewind(item->flipper_string)) {
FURI_LOG_E(TAG, "Rewind error"); FURI_LOG_E(TAG, "Rewind error");
} }
tmp_file_for_raw = true;
break; break;
} else if(!strcmp(furi_string_get_cstr(instance->tmp_string), "KeeLoq")) { } else if(!strcmp(furi_string_get_cstr(instance->tmp_string), "KeeLoq")) {
furi_string_set(instance->tmp_string, "KL "); furi_string_set(instance->tmp_string, "KL ");

View File

@@ -103,3 +103,10 @@ bool subghz_history_add_to_history(
* @return SubGhzProtocolCommonLoad* * @return SubGhzProtocolCommonLoad*
*/ */
FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx); FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
/** Set hopper state for internal usage in history
*
* @param instance - SubGhzHistory instance
* @param hopper_state - bool is hopper running?
*/
void subghz_history_set_hopper_state(SubGhzHistory* instance, bool hopper_state);

View File

@@ -29,6 +29,8 @@
#include <lib/subghz/subghz_worker.h> #include <lib/subghz/subghz_worker.h>
#include <lib/subghz/subghz_file_encoder_worker.h>
#include <lib/subghz/receiver.h> #include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h> #include <lib/subghz/transmitter.h>
@@ -49,6 +51,12 @@ typedef struct {
uint8_t seed[4]; uint8_t seed[4];
} SecureData; } SecureData;
typedef enum {
SubGhzDecodeRawStateStart,
SubGhzDecodeRawStateLoading,
SubGhzDecodeRawStateLoaded,
} SubGhzDecodeRawState;
struct SubGhzTxRx { struct SubGhzTxRx {
SubGhzWorker* worker; SubGhzWorker* worker;
@@ -109,6 +117,11 @@ struct SubGhz {
SubGhzLock lock; SubGhzLock lock;
bool in_decoder_scene; bool in_decoder_scene;
bool in_decoder_scene_skip;
SubGhzDecodeRawState decode_raw_state;
SubGhzFileEncoderWorker* decode_raw_file_worker_encoder;
void* rpc_ctx; void* rpc_ctx;
}; };

Binary file not shown.

View File

@@ -13,7 +13,7 @@ FAPs are created and developed the same way as internal applications that are pa
To build your application as a FAP, just create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest — and set its *apptype* to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details. To build your application as a FAP, just create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest — and set its *apptype* to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details.
* To build your application, run `./fbt firmware_{APPID}`, where APPID is your application's ID in its manifest. * To build your application, run `./fbt fap_{APPID}`, where APPID is your application's ID in its manifest.
* To build your app, then upload it over USB & run it on Flipper, use `./fbt launch_app APPSRC=applications/path/to/app`. This command is configured in default [VSCode profile](../.vscode/ReadMe.md) as "Launch App on Flipper" build action (Ctrl+Shift+B menu). * To build your app, then upload it over USB & run it on Flipper, use `./fbt launch_app APPSRC=applications/path/to/app`. This command is configured in default [VSCode profile](../.vscode/ReadMe.md) as "Launch App on Flipper" build action (Ctrl+Shift+B menu).
* To build all FAPs, run `./fbt plugin_dist`. * To build all FAPs, run `./fbt plugin_dist`.