mirror of
https://github.com/D4C1-Labs/Flipper-ARF.git
synced 2026-07-12 21:18:54 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7286b5c529 | |||
| 6a49fd89a1 | |||
| c4378c2e20 | |||
| 6e5ba9ec22 | |||
| 502570a18b | |||
| e606c5b24f | |||
| b34a73b08a | |||
| 069a42d697 | |||
| 2a182a2f5c |
@@ -361,6 +361,49 @@ SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat*
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool subghz_txrx_rebuild_from_fff(SubGhzTxRx* instance, FlipperFormat* flipper_format) {
|
||||
furi_assert(instance);
|
||||
furi_assert(flipper_format);
|
||||
|
||||
subghz_txrx_stop(instance);
|
||||
|
||||
bool rebuilt = false;
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
SubGhzTransmitter* transmitter = NULL;
|
||||
|
||||
do {
|
||||
if(!flipper_format_rewind(flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Rewind error");
|
||||
break;
|
||||
}
|
||||
if(!flipper_format_read_string(flipper_format, "Protocol", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
transmitter =
|
||||
subghz_transmitter_alloc_init(instance->environment, furi_string_get_cstr(temp_str));
|
||||
if(!transmitter) {
|
||||
FURI_LOG_E(TAG, "Protocol not found");
|
||||
break;
|
||||
}
|
||||
|
||||
rebuilt =
|
||||
subghz_transmitter_deserialize(transmitter, flipper_format) == SubGhzProtocolStatusOk;
|
||||
if(!rebuilt) {
|
||||
FURI_LOG_E(TAG, "Protocol rebuild failed");
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(transmitter) {
|
||||
subghz_transmitter_free(transmitter);
|
||||
}
|
||||
furi_string_free(temp_str);
|
||||
|
||||
return rebuilt;
|
||||
}
|
||||
|
||||
void subghz_txrx_rx_start(SubGhzTxRx* instance) {
|
||||
furi_assert(instance);
|
||||
subghz_txrx_stop(instance);
|
||||
|
||||
@@ -105,6 +105,15 @@ void subghz_txrx_get_frequency_and_modulation(
|
||||
*/
|
||||
SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Rebuild protocol data without starting TX.
|
||||
*
|
||||
* @param instance Pointer to a SubGhzTxRx
|
||||
* @param flipper_format Pointer to a FlipperFormat
|
||||
* @return bool True when encoder deserialization updated protocol data successfully
|
||||
*/
|
||||
bool subghz_txrx_rebuild_from_fff(SubGhzTxRx* instance, FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Start RX CC1101
|
||||
*
|
||||
|
||||
@@ -34,7 +34,7 @@ typedef struct {
|
||||
bool stop_pending; /* stop requested before MIN_TX_TICKS elapsed */
|
||||
uint32_t tx_start_tick;
|
||||
|
||||
/* Pending button key (InputKey) decoded from the packed custom event */
|
||||
/* Resolved custom button repeated while the physical key is held */
|
||||
uint8_t pending_button;
|
||||
} CarEmulateState;
|
||||
|
||||
@@ -252,12 +252,34 @@ static bool car_emulate_start_tx(SubGhz* subghz, uint8_t custom_btn_id) {
|
||||
|
||||
/** Stop an active transmission. */
|
||||
static void car_emulate_stop_tx(SubGhz* subghz) {
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
subghz_txrx_stop(subghz->txrx);
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
notification_message(subghz->notifications, &sequence_blink_stop);
|
||||
FURI_LOG_I(TAG, "TX stopped");
|
||||
}
|
||||
|
||||
static bool car_emulate_restart_tx(SubGhz* subghz) {
|
||||
furi_assert(s_state);
|
||||
|
||||
car_emulate_update_fff(subghz, s_state->current_counter);
|
||||
subghz_block_generic_global.endless_tx = true;
|
||||
|
||||
if(car_emulate_start_tx(subghz, s_state->pending_button)) {
|
||||
s_state->is_transmitting = true;
|
||||
subghz->state_notifications = SubGhzNotificationStateTx;
|
||||
notification_message(subghz->notifications, &sequence_blink_magenta_10);
|
||||
FURI_LOG_D(TAG, "TX restarted while button is held");
|
||||
return true;
|
||||
}
|
||||
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
s_state->is_transmitting = false;
|
||||
s_state->stop_pending = false;
|
||||
notification_message(subghz->notifications, &sequence_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════════
|
||||
* View callback (fired from the View's input handler)
|
||||
* ═════════════════════════════════════════════════════════════════════════*/
|
||||
@@ -293,6 +315,7 @@ void subghz_scene_car_emulate_on_enter(void* context) {
|
||||
s_state = malloc(sizeof(CarEmulateState));
|
||||
furi_check(s_state);
|
||||
memset(s_state, 0, sizeof(CarEmulateState));
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
|
||||
/* ── Read metadata from the loaded fff_data ── */
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
@@ -401,8 +424,11 @@ bool subghz_scene_car_emulate_on_event(void* context, SceneManagerEvent event) {
|
||||
s_state->tx_start_tick = (uint32_t)furi_get_tick();
|
||||
|
||||
uint8_t cur_btn = subghz_custom_btn_get();
|
||||
s_state->pending_button = cur_btn;
|
||||
subghz_block_generic_global.endless_tx = true;
|
||||
if(!car_emulate_start_tx(subghz, cur_btn)) {
|
||||
s_state->is_transmitting = false;
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
notification_message(subghz->notifications, &sequence_error);
|
||||
}
|
||||
|
||||
@@ -411,11 +437,13 @@ bool subghz_scene_car_emulate_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
/* ── Stop ── */
|
||||
} else if(event.event == SubGhzCustomEventCarEmulateStop) {
|
||||
if(s_state->is_transmitting &&
|
||||
subghz->state_notifications == SubGhzNotificationStateTx) {
|
||||
if(s_state->is_transmitting) {
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
|
||||
uint32_t elapsed = (uint32_t)furi_get_tick() - s_state->tx_start_tick;
|
||||
if(elapsed >= MIN_TX_TICKS) {
|
||||
if(
|
||||
elapsed >= MIN_TX_TICKS &&
|
||||
subghz->state_notifications == SubGhzNotificationStateTx) {
|
||||
car_emulate_stop_tx(subghz);
|
||||
s_state->is_transmitting = false;
|
||||
s_state->stop_pending = false;
|
||||
@@ -431,6 +459,7 @@ bool subghz_scene_car_emulate_on_event(void* context, SceneManagerEvent event) {
|
||||
if(subghz->state_notifications == SubGhzNotificationStateTx) {
|
||||
car_emulate_stop_tx(subghz);
|
||||
}
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneSavedMenu);
|
||||
consumed = true;
|
||||
@@ -450,6 +479,8 @@ bool subghz_scene_car_emulate_on_event(void* context, SceneManagerEvent event) {
|
||||
s_state->is_transmitting = false;
|
||||
s_state->stop_pending = false;
|
||||
notification_message(subghz->notifications, &sequence_blink_stop);
|
||||
} else {
|
||||
car_emulate_restart_tx(subghz);
|
||||
}
|
||||
} else {
|
||||
/* Still transmitting – blink LED */
|
||||
@@ -485,6 +516,7 @@ void subghz_scene_car_emulate_on_exit(void* context) {
|
||||
car_emulate_stop_tx(subghz);
|
||||
}
|
||||
|
||||
subghz_block_generic_global.endless_tx = false;
|
||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||
notification_message(subghz->notifications, &sequence_blink_stop);
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubGhzCustomEventSceneSaveName) {
|
||||
if(strcmp(subghz->file_name_tmp, "") != 0) {
|
||||
furi_string_reset(subghz->error_str);
|
||||
furi_string_cat_printf(
|
||||
subghz->file_path,
|
||||
"/%s%s",
|
||||
|
||||
@@ -12,8 +12,14 @@ void subghz_scene_save_success_on_enter(void* context) {
|
||||
// Setup view
|
||||
Popup* popup = subghz->popup;
|
||||
// [NO_DOLPHIN] popup_set_icon(popup, 36, 5, &I_DolphinSaved_92x58);
|
||||
popup_set_header(popup, "Saved", 15, 19, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
if(furi_string_size(subghz->error_str)) {
|
||||
popup_set_header(popup, "Saved", 15, 4, AlignLeft, AlignTop);
|
||||
popup_set_text(popup, furi_string_get_cstr(subghz->error_str), 4, 18, AlignLeft, AlignTop);
|
||||
popup_set_timeout(popup, 2500);
|
||||
} else {
|
||||
popup_set_header(popup, "Saved", 15, 19, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
}
|
||||
popup_set_context(popup, subghz);
|
||||
popup_set_callback(popup, subghz_scene_save_success_popup_callback);
|
||||
popup_enable_timeout(popup);
|
||||
@@ -72,4 +78,5 @@ void subghz_scene_save_success_on_exit(void* context) {
|
||||
Popup* popup = subghz->popup;
|
||||
|
||||
popup_reset(popup);
|
||||
furi_string_reset(subghz->error_str);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexSignalSettings,
|
||||
SubmenuIndexPsaDecrypt,
|
||||
SubmenuIndexEdit,
|
||||
SubmenuIndexDelete,
|
||||
SubmenuIndexSignalSettings,
|
||||
SubmenuIndexCounterBf, /* <-- comma was missing here */
|
||||
SubmenuIndexCarEmulateSettings,
|
||||
};
|
||||
@@ -20,17 +20,20 @@ void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
bool is_psa_encrypted = false;
|
||||
bool has_signal_editor = false;
|
||||
bool has_counter = false;
|
||||
if(fff) {
|
||||
FuriString* proto = furi_string_alloc();
|
||||
flipper_format_rewind(fff);
|
||||
if(flipper_format_read_string(fff, "Protocol", proto)) {
|
||||
has_signal_editor = !furi_string_equal_str(proto, "RAW");
|
||||
if(furi_string_equal_str(proto, "PSA GROUP")) {
|
||||
FuriString* type_str = furi_string_alloc();
|
||||
flipper_format_rewind(fff);
|
||||
if(!flipper_format_read_string(fff, "Type", type_str) ||
|
||||
furi_string_equal_str(type_str, "00")) {
|
||||
is_psa_encrypted = true;
|
||||
has_signal_editor = false;
|
||||
}
|
||||
furi_string_free(type_str);
|
||||
}
|
||||
@@ -53,6 +56,15 @@ void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
SubmenuIndexEmulate,
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
|
||||
if(has_signal_editor) {
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"Signal Editor",
|
||||
SubmenuIndexSignalSettings,
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
}
|
||||
}
|
||||
|
||||
if(is_psa_encrypted) {
|
||||
@@ -85,15 +97,6 @@ void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"Signal Settings",
|
||||
SubmenuIndexSignalSettings,
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
}
|
||||
|
||||
if(has_counter) {
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <machine/endian.h>
|
||||
#include <toolbox/strint.h>
|
||||
#include <lib/subghz/blocks/generic.h>
|
||||
#include <lib/subghz/blocks/custom_btn_i.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "SubGhzSceneSignalSettings"
|
||||
|
||||
@@ -21,6 +23,14 @@ static uint8_t btn_byte_count = 1;
|
||||
static uint8_t* btn_byte_ptr = NULL;
|
||||
|
||||
static uint8_t submenu_called = 0;
|
||||
static bool button_uses_custom_btn = false;
|
||||
static uint8_t button_custom_id = SUBGHZ_CUSTOM_BTN_OK;
|
||||
|
||||
enum {
|
||||
SignalSettingsIndexCounterMode,
|
||||
SignalSettingsIndexCounter,
|
||||
SignalSettingsIndexButton,
|
||||
};
|
||||
|
||||
#define COUNTER_MODE_COUNT 8
|
||||
static const char* const counter_mode_text[COUNTER_MODE_COUNT] = {
|
||||
@@ -45,6 +55,24 @@ static const int32_t counter_mode_value[COUNTER_MODE_COUNT] = {
|
||||
7,
|
||||
};
|
||||
|
||||
static const char* const button_text[] = {
|
||||
"Original",
|
||||
"Up",
|
||||
"Down",
|
||||
"Left",
|
||||
"Right",
|
||||
};
|
||||
|
||||
static const uint8_t button_value[] = {
|
||||
SUBGHZ_CUSTOM_BTN_OK,
|
||||
SUBGHZ_CUSTOM_BTN_UP,
|
||||
SUBGHZ_CUSTOM_BTN_DOWN,
|
||||
SUBGHZ_CUSTOM_BTN_LEFT,
|
||||
SUBGHZ_CUSTOM_BTN_RIGHT,
|
||||
};
|
||||
|
||||
#define BUTTON_VALUE_COUNT (sizeof(button_value) / sizeof(button_value[0]))
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
uint8_t mode_count;
|
||||
@@ -61,6 +89,140 @@ static Protocols protocols[] = {
|
||||
|
||||
#define PROTOCOLS_COUNT (sizeof(protocols) / sizeof(Protocols));
|
||||
|
||||
static bool subghz_scene_signal_settings_update_uint32_field(
|
||||
FlipperFormat* fff,
|
||||
const char* key,
|
||||
uint32_t value) {
|
||||
flipper_format_rewind(fff);
|
||||
return flipper_format_insert_or_update_uint32(fff, key, &value, 1);
|
||||
}
|
||||
|
||||
static bool subghz_scene_signal_settings_hex_digit(char c, uint8_t* value) {
|
||||
if(c >= '0' && c <= '9') {
|
||||
*value = c - '0';
|
||||
return true;
|
||||
} else if(c >= 'a' && c <= 'f') {
|
||||
*value = c - 'a' + 10;
|
||||
return true;
|
||||
} else if(c >= 'A' && c <= 'F') {
|
||||
*value = c - 'A' + 10;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool subghz_scene_signal_settings_parse_hex_field(
|
||||
const char* text,
|
||||
const char* marker,
|
||||
uint32_t* value,
|
||||
uint8_t* length_bit) {
|
||||
const char* field = strstr(text, marker);
|
||||
if(!field) return false;
|
||||
|
||||
field += strlen(marker);
|
||||
while(*field == ' ' || *field == '\t') {
|
||||
field++;
|
||||
}
|
||||
|
||||
uint32_t parsed = 0;
|
||||
uint8_t digits = 0;
|
||||
uint8_t digit_value = 0;
|
||||
while(digits < 8 && subghz_scene_signal_settings_hex_digit(*field, &digit_value)) {
|
||||
parsed = (parsed << 4) | digit_value;
|
||||
digits++;
|
||||
field++;
|
||||
}
|
||||
|
||||
if(digits == 0) return false;
|
||||
|
||||
*value = parsed;
|
||||
*length_bit = digits * 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void subghz_scene_signal_settings_apply_text_fallback(FuriString* decoded_text) {
|
||||
uint32_t value = 0;
|
||||
uint8_t length_bit = 0;
|
||||
const char* text = furi_string_get_cstr(decoded_text);
|
||||
|
||||
if(!subghz_block_generic_global.cnt_is_available &&
|
||||
subghz_scene_signal_settings_parse_hex_field(text, "Cnt:", &value, &length_bit)) {
|
||||
subghz_block_generic_global.cnt_is_available = true;
|
||||
subghz_block_generic_global.current_cnt = value;
|
||||
subghz_block_generic_global.cnt_length_bit = length_bit;
|
||||
}
|
||||
|
||||
if(!subghz_block_generic_global.btn_is_available &&
|
||||
subghz_scene_signal_settings_parse_hex_field(text, "Btn:", &value, &length_bit)) {
|
||||
subghz_block_generic_global.btn_is_available = true;
|
||||
subghz_block_generic_global.current_btn = value & 0xFF;
|
||||
subghz_block_generic_global.btn_length_bit = length_bit > 8 ? 8 : length_bit;
|
||||
}
|
||||
}
|
||||
|
||||
static void subghz_scene_signal_settings_apply_file_fallback(FlipperFormat* fff) {
|
||||
uint32_t value = 0;
|
||||
|
||||
if(!subghz_block_generic_global.cnt_is_available) {
|
||||
flipper_format_rewind(fff);
|
||||
if(flipper_format_read_uint32(fff, "Cnt", &value, 1)) {
|
||||
subghz_block_generic_global.cnt_is_available = true;
|
||||
subghz_block_generic_global.current_cnt = value;
|
||||
subghz_block_generic_global.cnt_length_bit = 32;
|
||||
}
|
||||
}
|
||||
|
||||
if(!subghz_block_generic_global.btn_is_available) {
|
||||
flipper_format_rewind(fff);
|
||||
if(flipper_format_read_uint32(fff, "Btn", &value, 1)) {
|
||||
subghz_block_generic_global.btn_is_available = true;
|
||||
subghz_block_generic_global.current_btn = value & 0xFF;
|
||||
subghz_block_generic_global.btn_length_bit = 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool subghz_scene_signal_settings_rebuild_save_reload(
|
||||
SubGhz* subghz,
|
||||
bool use_custom_btn,
|
||||
uint8_t custom_btn_id) {
|
||||
const char* file_path = furi_string_get_cstr(subghz->file_path);
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
|
||||
bool updated = false;
|
||||
int32_t counter_mult = furi_hal_subghz_get_rolling_counter_mult();
|
||||
furi_hal_subghz_set_rolling_counter_mult(0);
|
||||
|
||||
if(use_custom_btn) {
|
||||
subghz_custom_btn_set(custom_btn_id);
|
||||
} else {
|
||||
subghz_custom_btns_reset();
|
||||
}
|
||||
|
||||
do {
|
||||
if(!subghz_txrx_rebuild_from_fff(subghz->txrx, fff)) {
|
||||
FURI_LOG_E(TAG, "Error rebuilding protocol data");
|
||||
break;
|
||||
}
|
||||
if(!subghz_save_protocol_to_file(subghz, fff, file_path)) {
|
||||
FURI_LOG_E(TAG, "Error saving edited signal");
|
||||
break;
|
||||
}
|
||||
if(!subghz_key_load(subghz, file_path, false)) {
|
||||
FURI_LOG_E(TAG, "Error reloading edited signal");
|
||||
break;
|
||||
}
|
||||
updated = true;
|
||||
} while(false);
|
||||
|
||||
furi_hal_subghz_set_rolling_counter_mult(counter_mult);
|
||||
|
||||
if(!updated) {
|
||||
dialog_message_show_storage_error(subghz->dialogs, "Cannot save\nsignal");
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
void subghz_scene_signal_settings_counter_mode_changed(VariableItem* item) {
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, counter_mode_text[index]);
|
||||
@@ -99,6 +261,21 @@ void subghz_scene_signal_settings_counter_mode_changed(VariableItem* item) {
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_scene_signal_settings_button_changed(VariableItem* item) {
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
if(index >= BUTTON_VALUE_COUNT) index = 0;
|
||||
|
||||
variable_item_set_current_value_text(item, button_text[index]);
|
||||
button_custom_id = button_value[index];
|
||||
|
||||
if(!button_uses_custom_btn) return;
|
||||
|
||||
SubGhz* subghz = variable_item_get_context(item);
|
||||
furi_assert(subghz);
|
||||
|
||||
subghz_scene_signal_settings_rebuild_save_reload(subghz, true, button_custom_id);
|
||||
}
|
||||
|
||||
void subghz_scene_signal_settings_byte_input_callback(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
|
||||
@@ -108,8 +285,10 @@ void subghz_scene_signal_settings_variable_item_list_enter_callback(void* contex
|
||||
SubGhz* subghz = context;
|
||||
|
||||
// when we click OK on "Edit counter" item
|
||||
if(index == 1) {
|
||||
if(index == SignalSettingsIndexCounter) {
|
||||
if(!cnt_byte_ptr || cnt_byte_count == 0) return;
|
||||
submenu_called = 1;
|
||||
furi_string_set_str(byte_input_text, "Enter ");
|
||||
furi_string_cat_printf(byte_input_text, "%i", subghz_block_generic_global.cnt_length_bit);
|
||||
furi_string_cat_str(byte_input_text, "-bits counter in HEX");
|
||||
|
||||
@@ -127,8 +306,10 @@ void subghz_scene_signal_settings_variable_item_list_enter_callback(void* contex
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
|
||||
}
|
||||
// when we click OK on "Edit button" item
|
||||
if(index == 2) {
|
||||
if(index == SignalSettingsIndexButton && !button_uses_custom_btn) {
|
||||
if(!btn_byte_ptr || btn_byte_count == 0) return;
|
||||
submenu_called = 2;
|
||||
furi_string_set_str(byte_input_text, "Enter ");
|
||||
furi_string_cat_printf(byte_input_text, "%i", subghz_block_generic_global.btn_length_bit);
|
||||
furi_string_cat_str(byte_input_text, "-bits button in HEX");
|
||||
|
||||
@@ -150,6 +331,19 @@ void subghz_scene_signal_settings_variable_item_list_enter_callback(void* contex
|
||||
void subghz_scene_signal_settings_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
counter32 = 0;
|
||||
counter16 = 0;
|
||||
cnt_byte_count = 0;
|
||||
cnt_byte_ptr = NULL;
|
||||
button = 0;
|
||||
btn_byte_count = 1;
|
||||
btn_byte_ptr = NULL;
|
||||
submenu_called = 0;
|
||||
button_uses_custom_btn = false;
|
||||
button_custom_id = SUBGHZ_CUSTOM_BTN_OK;
|
||||
subghz_block_generic_global_reset(NULL);
|
||||
subghz_custom_btns_reset();
|
||||
|
||||
// ### Counter mode section ###
|
||||
|
||||
// When we open saved file we do some check and fill up subghz->file_path.
|
||||
@@ -224,6 +418,8 @@ void subghz_scene_signal_settings_on_enter(void* context) {
|
||||
if(subghz_protocol_decoder_base_deserialize(decoder, subghz_txrx_get_fff_data(subghz->txrx)) ==
|
||||
SubGhzProtocolStatusOk) {
|
||||
subghz_protocol_decoder_base_get_string(decoder, tmp_text);
|
||||
subghz_scene_signal_settings_apply_text_fallback(tmp_text);
|
||||
subghz_scene_signal_settings_apply_file_fallback(subghz_txrx_get_fff_data(subghz->txrx));
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Cant deserialize this subghz file");
|
||||
}
|
||||
@@ -232,6 +428,7 @@ void subghz_scene_signal_settings_on_enter(void* context) {
|
||||
|
||||
if(!subghz_block_generic_global.cnt_is_available) {
|
||||
counter_mode = 0xff;
|
||||
furi_string_set_str(tmp_text, "-");
|
||||
FURI_LOG_D(TAG, "Counter mode and edit not available for this protocol");
|
||||
} else {
|
||||
counter_not_available = false;
|
||||
@@ -262,24 +459,43 @@ void subghz_scene_signal_settings_on_enter(void* context) {
|
||||
// ### Button edit section ###
|
||||
|
||||
if(!subghz_block_generic_global.btn_is_available) {
|
||||
furi_string_set_str(tmp_text, "-");
|
||||
FURI_LOG_D(TAG, "Button edit not available for this protocol");
|
||||
} else {
|
||||
button_not_available = false;
|
||||
button = subghz_block_generic_global.current_btn;
|
||||
furi_string_printf(tmp_text, "%X", button);
|
||||
btn_byte_ptr = (uint8_t*)&button;
|
||||
|
||||
if(subghz_custom_btn_is_allowed()) {
|
||||
uint8_t max_custom_btn = subghz_custom_btn_get_max();
|
||||
uint8_t button_count = max_custom_btn + 1;
|
||||
if(button_count > BUTTON_VALUE_COUNT) button_count = BUTTON_VALUE_COUNT;
|
||||
button_uses_custom_btn = button_count > 1;
|
||||
}
|
||||
|
||||
if(button_uses_custom_btn) {
|
||||
furi_string_set_str(tmp_text, button_text[0]);
|
||||
} else {
|
||||
furi_string_printf(tmp_text, "%X", button);
|
||||
}
|
||||
}
|
||||
|
||||
item = variable_item_list_add(variable_item_list, "Edit Button", 1, NULL, subghz);
|
||||
uint8_t button_count = 1;
|
||||
if(button_uses_custom_btn) {
|
||||
button_count = subghz_custom_btn_get_max() + 1;
|
||||
if(button_count > BUTTON_VALUE_COUNT) button_count = BUTTON_VALUE_COUNT;
|
||||
}
|
||||
item = variable_item_list_add(
|
||||
variable_item_list,
|
||||
button_uses_custom_btn ? "Button" : "Edit Button",
|
||||
button_count,
|
||||
button_uses_custom_btn ? subghz_scene_signal_settings_button_changed : NULL,
|
||||
subghz);
|
||||
variable_item_set_current_value_index(item, 0);
|
||||
variable_item_set_current_value_text(item, furi_string_get_cstr(tmp_text));
|
||||
variable_item_set_locked(item, (button_not_available), "Not available\nfor this\nprotocol !");
|
||||
//
|
||||
|
||||
furi_assert(cnt_byte_ptr);
|
||||
furi_assert(cnt_byte_count > 0);
|
||||
furi_assert(btn_byte_ptr);
|
||||
|
||||
furi_string_free(tmp_text);
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
|
||||
@@ -290,23 +506,25 @@ bool subghz_scene_signal_settings_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubGhzCustomEventByteInputDone) {
|
||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||
|
||||
switch(submenu_called) {
|
||||
// edit counter
|
||||
case 1:
|
||||
switch(cnt_byte_count) {
|
||||
case 2:
|
||||
// set new cnt value and override_flag to global variable and call transmit to generate and save subghz signal
|
||||
counter16 = __bswap16(counter16);
|
||||
subghz_scene_signal_settings_update_uint32_field(fff, "Cnt", counter16);
|
||||
subghz_block_generic_global_counter_override_set(counter16);
|
||||
subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx));
|
||||
subghz_txrx_stop(subghz->txrx);
|
||||
subghz_scene_signal_settings_rebuild_save_reload(
|
||||
subghz, false, SUBGHZ_CUSTOM_BTN_OK);
|
||||
break;
|
||||
case 4:
|
||||
// the same for 32 bit Counter
|
||||
counter32 = __bswap32(counter32);
|
||||
subghz_scene_signal_settings_update_uint32_field(fff, "Cnt", counter32);
|
||||
subghz_block_generic_global_counter_override_set(counter32);
|
||||
subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx));
|
||||
subghz_txrx_stop(subghz->txrx);
|
||||
subghz_scene_signal_settings_rebuild_save_reload(
|
||||
subghz, false, SUBGHZ_CUSTOM_BTN_OK);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -314,14 +532,10 @@ bool subghz_scene_signal_settings_on_event(void* context, SceneManagerEvent even
|
||||
break;
|
||||
// edit button
|
||||
case 2:
|
||||
subghz_scene_signal_settings_update_uint32_field(fff, "Btn", button);
|
||||
subghz_block_generic_global_button_override_set(button);
|
||||
// save counter mult to rewrite subghz singnal without changing counter
|
||||
int32_t tmp_counter = furi_hal_subghz_get_rolling_counter_mult();
|
||||
furi_hal_subghz_set_rolling_counter_mult(0);
|
||||
subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx));
|
||||
subghz_txrx_stop(subghz->txrx);
|
||||
// restore counter mult
|
||||
furi_hal_subghz_set_rolling_counter_mult(tmp_counter);
|
||||
subghz_scene_signal_settings_rebuild_save_reload(
|
||||
subghz, false, SUBGHZ_CUSTOM_BTN_OK);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -330,13 +544,10 @@ bool subghz_scene_signal_settings_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -352,4 +563,5 @@ void subghz_scene_signal_settings_on_exit(void* context) {
|
||||
byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(subghz->byte_input, "");
|
||||
furi_string_free(byte_input_text);
|
||||
subghz_custom_btns_reset();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ uint8_t subghz_custom_btn_get(void) {
|
||||
return custom_btn_id;
|
||||
}
|
||||
|
||||
uint8_t subghz_custom_btn_get_max(void) {
|
||||
return custom_btn_max_btns;
|
||||
}
|
||||
|
||||
void subghz_custom_btn_set_original(uint8_t btn_code) {
|
||||
custom_btn_original = btn_code;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ void subghz_custom_btn_set_original(uint8_t btn_code);
|
||||
|
||||
void subghz_custom_btn_set_max(uint8_t b);
|
||||
|
||||
uint8_t subghz_custom_btn_get_max(void);
|
||||
|
||||
void subghz_custom_btn_set_prog_mode(ProgMode prog_mode);
|
||||
|
||||
ProgMode subghz_custom_btn_get_prog_mode(void);
|
||||
|
||||
@@ -407,7 +407,7 @@ LevelDuration subghz_protocol_encoder_fiat_spa_yield(void* context) {
|
||||
}
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -364,7 +364,7 @@ LevelDuration subghz_protocol_encoder_ford_v0_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1278,8 +1278,9 @@ LevelDuration subghz_protocol_encoder_ford_v1_yield(void* context) {
|
||||
"Encoder yield: finished one full %lu-word frame (all %u bursts); repeats_left=%u",
|
||||
(unsigned long)instance->encoder.size_upload,
|
||||
(unsigned)FORD_V1_ENC_BURST_COUNT,
|
||||
(unsigned)instance->encoder.repeat - 1U);
|
||||
instance->encoder.repeat--;
|
||||
subghz_block_generic_global.endless_tx ? (unsigned)instance->encoder.repeat :
|
||||
(unsigned)instance->encoder.repeat - 1U);
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
} else if(instance->encoder.front <= 4U) {
|
||||
uint32_t raw_word;
|
||||
|
||||
@@ -615,7 +615,7 @@ LevelDuration subghz_protocol_encoder_ford_v2_yield(void* context) {
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.front = 0U;
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -154,7 +154,7 @@ LevelDuration subghz_protocol_encoder_kia_yield(void* context) {
|
||||
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
@@ -594,4 +594,3 @@ void subghz_protocol_decoder_kia_get_string(void* context, FuriString* output) {
|
||||
received_crc,
|
||||
crc_valid ? "(OK)" : "(FAIL)");
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ LevelDuration subghz_protocol_encoder_kia_v1_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ LevelDuration subghz_protocol_encoder_kia_v2_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -648,7 +648,7 @@ LevelDuration subghz_protocol_encoder_kia_v3_v4_yield(void* context) {
|
||||
instance->crc_iter = (uint8_t)((instance->crc_iter + 1U) & 0x0FU);
|
||||
subghz_protocol_encoder_kia_v3_v4_patch_crc(instance);
|
||||
instance->encoder.front = 0;
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
if(instance->bursts_sent < 16U) {
|
||||
instance->bursts_sent++;
|
||||
}
|
||||
|
||||
@@ -327,15 +327,29 @@ SubGhzProtocolStatus
|
||||
uint32_t encrypted = (uint32_t)(yek & 0xFFFFFFFF);
|
||||
instance->generic.cnt = mixer_decode(encrypted);
|
||||
|
||||
uint32_t mult = furi_hal_subghz_get_rolling_counter_mult();
|
||||
instance->generic.cnt = (instance->generic.cnt + mult) & 0xFFFF;
|
||||
FURI_LOG_I(TAG, "deserialize #%lu, cnt after=%04lX", call_count, (uint32_t)instance->generic.cnt);
|
||||
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->generic.btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(4);
|
||||
|
||||
uint32_t override_cnt = 0;
|
||||
if(subghz_block_generic_global_counter_override_get(&override_cnt)) {
|
||||
instance->generic.cnt = override_cnt & 0xFFFF;
|
||||
} else {
|
||||
uint32_t mult = furi_hal_subghz_get_rolling_counter_mult();
|
||||
instance->generic.cnt = (instance->generic.cnt + mult) & 0xFFFF;
|
||||
}
|
||||
FURI_LOG_I(
|
||||
TAG, "deserialize #%lu, cnt after=%04lX", call_count, (uint32_t)instance->generic.cnt);
|
||||
|
||||
uint8_t btn = subghz_custom_btn_get() == SUBGHZ_CUSTOM_BTN_OK ?
|
||||
subghz_custom_btn_get_original() :
|
||||
subghz_custom_btn_get();
|
||||
if(subghz_block_generic_global_button_override_get(&btn)) {
|
||||
FURI_LOG_D(TAG, "Button changed to 0x%X", btn);
|
||||
}
|
||||
instance->generic.btn = btn & 0x0F;
|
||||
|
||||
instance->generic.data = kia_v5_encode_data(
|
||||
instance->generic.serial, instance->generic.cnt, instance->generic.btn);
|
||||
instance->replay_data = instance->generic.data;
|
||||
@@ -456,7 +470,7 @@ LevelDuration subghz_protocol_encoder_kia_v5_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
@@ -687,10 +701,13 @@ SubGhzProtocolStatus
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderKiaV5* instance = context;
|
||||
|
||||
SubGhzProtocolStatus ret = subghz_block_generic_deserialize_check_count_bit(
|
||||
&instance->generic,
|
||||
flipper_format,
|
||||
subghz_protocol_kia_v5_const.min_count_bit_for_found);
|
||||
SubGhzProtocolStatus ret = subghz_block_generic_deserialize(&instance->generic, flipper_format);
|
||||
|
||||
if((ret == SubGhzProtocolStatusOk) &&
|
||||
(instance->generic.data_count_bit <
|
||||
subghz_protocol_kia_v5_const.min_count_bit_for_found)) {
|
||||
ret = SubGhzProtocolStatusErrorParserBitCount;
|
||||
}
|
||||
|
||||
if(ret == SubGhzProtocolStatusOk) {
|
||||
flipper_format_rewind(flipper_format);
|
||||
|
||||
@@ -791,7 +791,7 @@ LevelDuration subghz_protocol_encoder_kia_v6_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
instance->encoder.front++;
|
||||
if(instance->encoder.front >= instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -431,7 +431,7 @@ LevelDuration kia_protocol_encoder_v7_yield(void* context) {
|
||||
LevelDuration duration = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -969,7 +969,7 @@ LevelDuration subghz_protocol_encoder_land_rover_v0_yield(void* context) {
|
||||
|
||||
if(instance->encoder.front >= instance->encoder.size_upload) {
|
||||
/* One full repetition done; count it down */
|
||||
if(instance->encoder.repeat > 0) {
|
||||
if(instance->encoder.repeat > 0 && !subghz_block_generic_global.endless_tx) {
|
||||
instance->encoder.repeat--;
|
||||
}
|
||||
instance->encoder.front = 0;
|
||||
|
||||
@@ -499,7 +499,7 @@ LevelDuration subghz_protocol_encoder_mazda_v0_yield(void* context) {
|
||||
LevelDuration out = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ LevelDuration subghz_protocol_encoder_mitsubishi_v0_yield(void* context) {
|
||||
if(!instance->encoder.is_running || instance->encoder.repeat == 0) return level_duration_reset();
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -621,7 +621,7 @@ LevelDuration subghz_protocol_encoder_porsche_cayenne_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1932,7 +1932,7 @@ LevelDuration subghz_protocol_encoder_psa_yield(void* context) {
|
||||
instance->encoder.front++;
|
||||
if(instance->encoder.front >= instance->encoder.size_upload) {
|
||||
instance->encoder.front = 0;
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
if(instance->encoder.repeat <= 0) instance->is_running = false;
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -622,7 +622,7 @@ LevelDuration subghz_protocol_encoder_scher_khan_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -418,7 +418,7 @@ LevelDuration subghz_protocol_encoder_sheriff_cfm_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -556,7 +556,7 @@ LevelDuration subghz_protocol_encoder_star_line_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -527,7 +527,7 @@ LevelDuration subghz_protocol_encoder_subaru_yield(void* context) {
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -494,7 +494,7 @@ LevelDuration subghz_protocol_encoder_suzuki_yield(void *context)
|
||||
|
||||
if (++instance->encoder.front == instance->encoder.size_upload)
|
||||
{
|
||||
instance->encoder.repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1358,7 +1358,7 @@ LevelDuration subghz_protocol_encoder_vag_yield(void* context) {
|
||||
|
||||
if(instance->front >= instance->size_upload) {
|
||||
instance->front = 0;
|
||||
instance->repeat--;
|
||||
if(!subghz_block_generic_global.endless_tx) instance->repeat--;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
+26
-3
@@ -4,6 +4,7 @@ import os
|
||||
import struct
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
|
||||
@@ -16,6 +17,17 @@ from flipper.app import App
|
||||
VERSION = 1
|
||||
|
||||
|
||||
def replace_file_with_retry(source: str, target: str, attempts: int = 50) -> None:
|
||||
for attempt in range(attempts):
|
||||
try:
|
||||
os.replace(source, target)
|
||||
return
|
||||
except PermissionError:
|
||||
if attempt == attempts - 1:
|
||||
raise
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
@dataclass
|
||||
class RelData:
|
||||
section: int
|
||||
@@ -136,10 +148,15 @@ class Main(App):
|
||||
)
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
for section in sections:
|
||||
current_fap_path = fap_path
|
||||
|
||||
for section_index, section in enumerate(sections):
|
||||
data = serialize_relsection_data(section.data)
|
||||
hash_name = hashlib.md5(section.name.encode()).hexdigest()
|
||||
filename = f"{temp_dir}/{hash_name}.bin"
|
||||
filename = os.path.join(temp_dir, f"{section_index}_{hash_name}.bin")
|
||||
patched_fap_path = os.path.join(
|
||||
temp_dir, f"{section_index}_{hash_name}.fap"
|
||||
)
|
||||
|
||||
if os.path.isfile(filename):
|
||||
self.logger.error(f"File {filename} already exists")
|
||||
@@ -153,7 +170,8 @@ class Main(App):
|
||||
objcopy_path,
|
||||
"--add-section",
|
||||
f"{section.name}={filename}",
|
||||
fap_path,
|
||||
current_fap_path,
|
||||
patched_fap_path,
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
@@ -162,6 +180,11 @@ class Main(App):
|
||||
self.logger.error("objcopy failed")
|
||||
return 1
|
||||
|
||||
current_fap_path = patched_fap_path
|
||||
|
||||
if current_fap_path != fap_path:
|
||||
replace_file_with_retry(current_fap_path, fap_path)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user