diff --git a/helpers/protopirate_settings.c b/helpers/protopirate_settings.c index 79bf087..d16652a 100644 --- a/helpers/protopirate_settings.c +++ b/helpers/protopirate_settings.c @@ -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); diff --git a/helpers/protopirate_settings.h b/helpers/protopirate_settings.h index c5b3e60..59aa622 100644 --- a/helpers/protopirate_settings.h +++ b/helpers/protopirate_settings.h @@ -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; diff --git a/helpers/protopirate_txrx.c b/helpers/protopirate_txrx.c index afe4480..f2f81d1 100644 --- a/helpers/protopirate_txrx.c +++ b/helpers/protopirate_txrx.c @@ -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; } diff --git a/protocols/renault_v1.c b/protocols/renault_v1.c index 378a719..aa4b56d 100644 --- a/protocols/renault_v1.c +++ b/protocols/renault_v1.c @@ -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"); diff --git a/protopirate_app.c b/protopirate_app.c index e5f7291..c50dfa1 100644 --- a/protopirate_app.c +++ b/protopirate_app.c @@ -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); diff --git a/protopirate_app_i.h b/protopirate_app_i.h index 08884fc..7296a11 100644 --- a/protopirate_app_i.h +++ b/protopirate_app_i.h @@ -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; diff --git a/scenes/protopirate_scene_receiver.c b/scenes/protopirate_scene_receiver.c index b9331b1..01b30f9 100644 --- a/scenes/protopirate_scene_receiver.c +++ b/scenes/protopirate_scene_receiver.c @@ -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", diff --git a/scenes/protopirate_scene_receiver_config.c b/scenes/protopirate_scene_receiver_config.c index 2c21272..e5f7732 100644 --- a/scenes/protopirate_scene_receiver_config.c +++ b/scenes/protopirate_scene_receiver_config.c @@ -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);