Merge branch 'main' into fix_unlock

This commit is contained in:
MMX
2026-09-16 02:02:32 -04:00
8 changed files with 93 additions and 40 deletions
+18 -5
View File
@@ -17,6 +17,7 @@ void protopirate_settings_set_defaults(ProtoPirateSettings* settings) {
settings->preset_index = 0;
settings->tx_power = 0;
settings->auto_save = false;
settings->sound = false;
settings->hopping_enabled = false;
settings->emulate_feature_enabled = false;
settings->check_saved = false;
@@ -118,15 +119,22 @@ void protopirate_settings_load(ProtoPirateSettings* settings) {
}
settings->check_saved = (check_saved_temp == 1);
uint32_t sound_temp = 0;
if(!flipper_format_read_uint32(ff, "Sound", &sound_temp, 1)) {
check_saved_temp = 0;
}
settings->sound = (sound_temp == 1);
FURI_LOG_I(
TAG,
"Settings loaded: freq=%lu, preset=%u, auto_save=%d, hopping=%d, emulate=%d, check_saved=%d",
"Settings loaded: freq=%lu, preset=%u, auto_save=%d, hopping=%d, emulate=%d, check_saved=%d, sound = %d",
settings->frequency,
settings->preset_index,
settings->auto_save,
settings->hopping_enabled,
settings->emulate_feature_enabled,
settings->check_saved);
settings->check_saved,
settings->sound);
} while(false);
@@ -200,18 +208,23 @@ void protopirate_settings_save(ProtoPirateSettings* settings) {
FURI_LOG_E(TAG, "Failed to write check saved");
break;
}
uint32_t sound_temp = settings->sound ? 1 : 0;
if(!flipper_format_write_uint32(ff, "Sound", &sound_temp, 1)) {
FURI_LOG_E(TAG, "Failed to write Sound.");
break;
}
write_ok = true;
FURI_LOG_I(
TAG,
"Settings saved: freq=%lu, preset=%u, auto_save=%d, hopping=%d, emulate=%d, check_saved=%d",
"Settings saved: freq=%lu, preset=%u, auto_save=%d, hopping=%d, emulate=%d, check_saved=%d, sound=%d",
settings->frequency,
settings->preset_index,
settings->auto_save,
settings->hopping_enabled,
settings->emulate_feature_enabled,
settings->check_saved);
settings->check_saved,
settings->sound);
} while(false);
+1
View File
@@ -14,6 +14,7 @@ typedef struct {
uint8_t preset_index;
uint8_t tx_power;
bool auto_save;
bool sound;
bool hopping_enabled;
bool emulate_feature_enabled;
bool check_saved;
+14
View File
@@ -133,6 +133,13 @@ uint32_t protopirate_rx(ProtoPirateApp* app, uint32_t frequency) {
subghz_devices_idle(app->txrx->radio_device);
uint32_t value = subghz_devices_set_frequency(app->txrx->radio_device, frequency);
subghz_devices_flush_rx(app->txrx->radio_device);
//Enable the Speaker so I can hear the keys.
if(app->sound) {
if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
app->txrx->radio_device->interconnect->set_async_mirror_pin(&gpio_speaker);
}
}
subghz_devices_set_rx(app->txrx->radio_device);
subghz_devices_start_async_rx(
@@ -169,6 +176,13 @@ void protopirate_rx_end(ProtoPirateApp* app) {
subghz_devices_idle(app->txrx->radio_device);
}
if(app->sound) {
if(furi_hal_speaker_is_mine()) {
subghz_devices_set_async_mirror_pin(app->txrx->radio_device, NULL);
furi_hal_speaker_release();
}
}
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
}
+34 -33
View File
@@ -65,6 +65,8 @@ struct SubGhzProtocolDecoderRenaultV1 {
uint64_t last_data;
uint64_t last_data_2;
bool last_frame_valid;
uint32_t seed;
uint64_t data_2;
};
#if PROTOPIRATE_WITH_ENCODER
@@ -74,6 +76,8 @@ struct SubGhzProtocolEncoderRenaultV1 {
SubGhzProtocolBlockEncoder encoder;
SubGhzBlockGeneric generic;
uint32_t seed;
uint64_t data_2;
uint8_t recovered;
uint8_t hitag2_key[6];
uint8_t tail_bits;
@@ -637,9 +641,9 @@ static void hitag2_apply_check_remote(
static void renault_v1_check_remote_controller(SubGhzProtocolDecoderRenaultV1* instance) {
hitag2_apply_check_remote(
instance->generic.data,
instance->generic.data_2,
instance->data_2,
instance->recovered,
instance->generic.seed,
instance->seed,
&instance->generic.serial,
&instance->generic.btn,
&instance->generic.cnt,
@@ -669,7 +673,7 @@ static bool hitag2_encoder_next_frame(
uint32_t hop = hitag2_authenticator(uid, tx_btn, cnt10, instance->hitag2_key);
hitag2_pack_auth_frame(uid, tx_btn, cnt10, hop, tail, raw);
hitag2_apply_raw(raw, &instance->generic.data, &instance->generic.data_2);
hitag2_apply_raw(raw, &instance->generic.data, &instance->data_2);
instance->generic.serial = uid;
instance->generic.btn = tx_btn;
instance->generic.cnt = cnt10;
@@ -767,7 +771,7 @@ static bool renault_v1_encoder_get_upload(SubGhzProtocolEncoderRenaultV1* instan
size_t index = 0;
LevelDuration* upload = instance->encoder.upload;
const uint64_t key = instance->generic.data;
const uint64_t key_2 = instance->generic.data_2 & 0xFFFFFFULL;
const uint64_t key_2 = instance->data_2 & 0xFFFFFFULL;
for(size_t i = 0; i < HITAG2_PREAMBLE_PAIRS; i++) {
if(!hitag2_encoder_add_level(upload, &index, true, HITAG2_TE_US)) return false;
@@ -814,10 +818,9 @@ SubGhzProtocolStatus
ret = SubGhzProtocolStatusErrorParserOthers;
break;
}
instance->generic.data_2 = hitag2_bytes_to_u64_be(key2, sizeof(key2));
instance->data_2 = hitag2_bytes_to_u64_be(key2, sizeof(key2));
hitag2_read_recovered_and_seed(
flipper_format, &instance->recovered, &instance->generic.seed);
hitag2_read_recovered_and_seed(flipper_format, &instance->recovered, &instance->seed);
if(!flipper_format_rewind(flipper_format)) {
ret = SubGhzProtocolStatusErrorParserOthers;
@@ -831,7 +834,7 @@ SubGhzProtocolStatus
uint16_t wire_cnt10 = 0;
hitag2_unpack_frame(
instance->generic.data,
instance->generic.data_2,
instance->data_2,
&wire_serial,
&wire_btn,
&wire_cnt10,
@@ -839,9 +842,9 @@ SubGhzProtocolStatus
&tail);
hitag2_apply_check_remote(
instance->generic.data,
instance->generic.data_2,
instance->data_2,
instance->recovered,
instance->generic.seed,
instance->seed,
&instance->generic.serial,
&instance->generic.btn,
&instance->generic.cnt,
@@ -886,14 +889,13 @@ SubGhzProtocolStatus
instance->generic.serial,
instance->generic.cnt,
instance->generic.btn,
instance->generic.seed,
instance->seed,
out,
iv);
instance->generic.data = hitag2_bytes_to_u64_be(out, 8);
instance->generic.data_2 = ((uint64_t)out[8] << 16U) | ((uint64_t)out[9] << 8U) |
out[10];
instance->generic.seed = ((uint32_t)iv[0] << 24U) | ((uint32_t)iv[1] << 16U) |
((uint32_t)iv[2] << 8U) | iv[3];
instance->data_2 = ((uint64_t)out[8] << 16U) | ((uint64_t)out[9] << 8U) | out[10];
instance->seed = ((uint32_t)iv[0] << 24U) | ((uint32_t)iv[1] << 16U) |
((uint32_t)iv[2] << 8U) | iv[3];
} else if(!instance->hitag2_key_valid && instance->recovered != HITAG2_RECOVERED_YES) {
ret = SubGhzProtocolStatusErrorParserOthers;
break;
@@ -917,7 +919,7 @@ SubGhzProtocolStatus
ret = SubGhzProtocolStatusErrorParserOthers;
break;
}
hitag2_u64_to_bytes_be(instance->generic.data_2, key_data, 8);
hitag2_u64_to_bytes_be(instance->data_2, key_data, 8);
if(!flipper_format_insert_or_update_hex(
flipper_format, "Key_2", key_data, sizeof(key_data))) {
ret = SubGhzProtocolStatusErrorParserOthers;
@@ -930,7 +932,7 @@ SubGhzProtocolStatus
ret = SubGhzProtocolStatusErrorParserOthers;
break;
}
if(!hitag2_write_hex_be(flipper_format, "Seed", instance->generic.seed, 4)) {
if(!hitag2_write_hex_be(flipper_format, "Seed", instance->seed, 4)) {
ret = SubGhzProtocolStatusErrorParserOthers;
break;
}
@@ -939,7 +941,7 @@ SubGhzProtocolStatus
{
uint32_t hop = 0;
hitag2_unpack_frame(
instance->generic.data, instance->generic.data_2, NULL, NULL, NULL, &hop, NULL);
instance->generic.data, instance->data_2, NULL, NULL, NULL, &hop, NULL);
hitag2_write_named_fields(
flipper_format,
instance->generic.serial,
@@ -1024,14 +1026,14 @@ static bool hitag2_accept_frame(SubGhzProtocolDecoderRenaultV1* instance, uint64
return false;
}
instance->generic.data_2 = key_2;
instance->data_2 = key_2;
instance->generic.data_count_bit = HITAG2_MIN_COUNT_BIT;
instance->recovered = 0;
instance->generic.seed = 0;
instance->seed = 0;
uint16_t cnt10 = 0;
hitag2_unpack_frame(
instance->generic.data,
instance->generic.data_2,
instance->data_2,
&instance->generic.serial,
&instance->generic.btn,
&cnt10,
@@ -1180,26 +1182,26 @@ SubGhzProtocolStatus subghz_protocol_decoder_renault_v1_serialize(
const uint32_t serial = instance->generic.serial;
const uint8_t btn = instance->generic.btn;
const uint32_t cnt = instance->generic.cnt;
const uint32_t seed = instance->generic.seed;
const uint64_t data_2 = instance->generic.data_2;
const uint32_t seed = instance->seed;
const uint64_t data_2 = instance->data_2;
instance->generic.serial = 0;
instance->generic.btn = 0;
instance->generic.cnt = 0;
instance->generic.seed = 0;
instance->generic.data_2 = 0;
instance->seed = 0;
instance->data_2 = 0;
SubGhzProtocolStatus ret =
subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
instance->generic.serial = serial;
instance->generic.btn = btn;
instance->generic.cnt = cnt;
instance->generic.seed = seed;
instance->generic.data_2 = data_2;
instance->seed = seed;
instance->data_2 = data_2;
if(ret != SubGhzProtocolStatusOk) {
return ret;
}
ret = hitag2_write_extra_fields(
flipper_format, instance->generic.data_2, instance->recovered, instance->generic.seed);
flipper_format, instance->data_2, instance->recovered, instance->seed);
if(ret != SubGhzProtocolStatusOk) {
return ret;
}
@@ -1231,10 +1233,9 @@ SubGhzProtocolStatus
ret = SubGhzProtocolStatusErrorParserOthers;
break;
}
instance->generic.data_2 = hitag2_bytes_to_u64_be(key2, sizeof(key2));
instance->data_2 = hitag2_bytes_to_u64_be(key2, sizeof(key2));
hitag2_read_recovered_and_seed(
flipper_format, &instance->recovered, &instance->generic.seed);
hitag2_read_recovered_and_seed(flipper_format, &instance->recovered, &instance->seed);
renault_v1_check_remote_controller(instance);
instance->hitag2_key_valid = false;
@@ -1264,7 +1265,7 @@ void subghz_protocol_decoder_renault_v1_get_string(void* context, FuriString* ou
"%s\r\nK1:%016llX\r\nK2:%06llX Sn:%08lX\r\nBtn:%02X [%s] %db",
instance->generic.protocol_name,
(unsigned long long)instance->generic.data,
(unsigned long long)(instance->generic.data_2 & 0xFFFFFFULL),
(unsigned long long)(instance->data_2 & 0xFFFFFFULL),
(unsigned long)instance->generic.serial,
instance->generic.btn,
hitag2_get_button_name(instance->generic.btn),
@@ -1274,7 +1275,7 @@ void subghz_protocol_decoder_renault_v1_get_string(void* context, FuriString* ou
furi_string_cat_printf(
output,
"\r\nIV:%08lX Cnt:%04lX",
(unsigned long)instance->generic.seed,
(unsigned long)instance->seed,
(unsigned long)(instance->generic.cnt & 0xFFFFU));
} else if(instance->recovered == HITAG2_RECOVERED_BF_MISS) {
furi_string_cat_printf(output, "\r\nBF not found");
+2
View File
@@ -88,6 +88,7 @@ ProtoPirateApp* protopirate_app_alloc() {
// Apply auto-save setting
app->auto_save = settings.auto_save;
app->sound = settings.sound;
app->check_saved = settings.check_saved;
app->tx_power = settings.tx_power;
#ifdef ENABLE_EMULATE_FEATURE
@@ -176,6 +177,7 @@ void protopirate_app_free(ProtoPirateApp* app) {
ProtoPirateSettings settings;
settings.frequency = app->txrx->preset->frequency;
settings.auto_save = app->auto_save;
settings.sound = app->sound;
settings.check_saved = app->check_saved;
settings.tx_power = app->tx_power;
settings.hopping_enabled = (app->txrx->hopper_state != ProtoPirateHopperStateOFF);
+1
View File
@@ -83,6 +83,7 @@ struct ProtoPirateApp {
FuriString* loaded_file_path;
bool auto_save;
bool check_saved;
bool sound;
bool radio_initialized;
uint32_t start_tx_time;
uint8_t tx_power;
+4 -2
View File
@@ -56,8 +56,10 @@ static void protopirate_scene_receiver_callback(
protopirate_history_add_to_history(app->txrx->history, decoder_base, app->txrx->preset);
if(added) {
notification_message(app->notifications, &sequence_semi_success);
if(!(app->sound))
notification_message(app->notifications, &sequence_semi_success);
else
notification_message(app->notifications, &sequence_single_vibro);
FURI_LOG_I(
TAG,
"Added to history, total items: %u",
@@ -9,6 +9,7 @@ enum ProtoPirateSettingIndex {
ProtoPirateSettingIndexTXPower,
#endif
ProtoPirateSettingIndexAutoSave,
ProtoPirateSettingIndexSound,
ProtoPirateSettingIndexCheckSaved,
ProtoPirateSettingIndexLock,
};
@@ -188,6 +189,14 @@ static void protopirate_scene_receiver_config_set_check_saved(VariableItem* item
variable_item_set_current_value_text(item, check_saved_text[index]);
}
static void protopirate_scene_receiver_config_set_sound(VariableItem* item) {
ProtoPirateApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
app->sound = (index == 1);
variable_item_set_current_value_text(item, auto_save_text[index]);
}
#ifdef ENABLE_EMULATE_FEATURE
static void protopirate_scene_receiver_config_set_tx_power(VariableItem* item) {
ProtoPirateApp* app = variable_item_get_context(item);
@@ -292,6 +301,16 @@ void protopirate_scene_receiver_config_on_enter(void* context) {
variable_item_set_current_value_index(item, app->check_saved ? 1 : 0);
variable_item_set_current_value_text(item, check_saved_text[app->check_saved ? 1 : 0]);
// Sound option
item = variable_item_list_add(
app->variable_item_list,
"Sound:",
AUTO_SAVE_COUNT,
protopirate_scene_receiver_config_set_sound,
app);
variable_item_set_current_value_index(item, app->sound);
variable_item_set_current_value_text(item, auto_save_text[(!app->sound) ? 0 : 1]);
variable_item_list_add(app->variable_item_list, "Lock Keyboard", 1, NULL, NULL);
variable_item_list_set_enter_callback(
app->variable_item_list, protopirate_scene_receiver_config_var_list_enter_callback, app);