From 17e60cd38e423353b7e3bda2cb24097afbea1b73 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:01:58 +0300 Subject: [PATCH] use generic struct in psa --- protocols/psa.c | 1004 ++++++++++++++++++++++++++--------------------- 1 file changed, 565 insertions(+), 439 deletions(-) diff --git a/protocols/psa.c b/protocols/psa.c index f85e926..19c37fc 100644 --- a/protocols/psa.c +++ b/protocols/psa.c @@ -9,21 +9,21 @@ static const SubGhzBlockConst subghz_protocol_psa_const = { .min_count_bit_for_found = 128, }; -#define PSA_TE_SHORT_125 0x7d -#define PSA_TE_LONG_250 0xfa -#define PSA_TE_END_1000 1000 -#define PSA_TE_END_500 500 -#define PSA_TOLERANCE_99 99 -#define PSA_TOLERANCE_100 100 -#define PSA_TOLERANCE_49 0x31 -#define PSA_TOLERANCE_50 0x32 +#define PSA_TE_SHORT_125 0x7d +#define PSA_TE_LONG_250 0xfa +#define PSA_TE_END_1000 1000 +#define PSA_TE_END_500 500 +#define PSA_TOLERANCE_99 99 +#define PSA_TOLERANCE_100 100 +#define PSA_TOLERANCE_49 0x31 +#define PSA_TOLERANCE_50 0x32 #define PSA_PATTERN_THRESHOLD_1 0x46 #define PSA_PATTERN_THRESHOLD_2 0x45 -#define PSA_MAX_BITS 0x79 -#define PSA_KEY1_BITS 0x40 -#define PSA_KEY2_BITS 0x50 +#define PSA_MAX_BITS 0x79 +#define PSA_KEY1_BITS 0x40 +#define PSA_KEY2_BITS 0x50 -#define TEA_DELTA 0x9E3779B9U +#define TEA_DELTA 0x9E3779B9U #define TEA_ROUNDS 32 #define PSA_BF1_CONST_U4 0x0E0F5C41U @@ -44,9 +44,9 @@ static const uint32_t PSA_BF2_KEY_SCHEDULE[4] = { }; #define PSA_BF1_START 0x23000000U -#define PSA_BF1_END 0x24000000U +#define PSA_BF1_END 0x24000000U #define PSA_BF2_START 0xF3000000U -#define PSA_BF2_END 0xF4000000U +#define PSA_BF2_END 0xF4000000U typedef enum { PSADecoderState0 = 0, @@ -59,33 +59,25 @@ typedef enum { struct SubGhzProtocolDecoderPSA { SubGhzProtocolDecoderBase base; SubGhzBlockDecoder decoder; - + SubGhzBlockGeneric generic; + uint32_t state; uint32_t prev_duration; - + uint32_t decode_data_low; uint32_t decode_data_high; uint8_t decode_count_bit; - - uint32_t seed; - uint32_t key1_low; - uint32_t key1_high; + uint16_t validation_field; - uint32_t key2_low; - uint32_t key2_high; - + uint32_t status_flag; uint16_t decrypted; uint8_t mode_serialize; - + uint16_t pattern_counter; ManchesterState manchester_state; - - uint8_t decrypted_button; - uint32_t decrypted_serial; - uint32_t decrypted_counter; + uint16_t decrypted_crc; - uint32_t decrypted_seed; uint8_t decrypted_type; }; @@ -93,15 +85,11 @@ struct SubGhzProtocolEncoderPSA { SubGhzProtocolEncoderBase base; SubGhzProtocolBlockEncoder encoder; SubGhzBlockGeneric generic; - - uint32_t key1_low; - uint32_t key1_high; + uint16_t validation_field; - uint32_t key2_low; uint32_t counter; uint8_t button; uint8_t type; - uint8_t seed; uint8_t mode; uint32_t serial; uint16_t crc; @@ -136,17 +124,16 @@ const SubGhzProtocol psa_protocol = { .encoder = &subghz_protocol_psa_encoder, }; -static void psa_setup_byte_buffer(uint8_t* buffer, uint32_t key1_low, uint32_t key1_high, uint32_t key2_low); +static void psa_setup_byte_buffer(uint8_t* buffer, uint64_t key1, uint64_t key2); static void psa_calculate_checksum(uint8_t* buffer); static uint8_t psa_calculate_tea_crc(uint32_t v0, uint32_t v1); static void psa_tea_encrypt(uint32_t* v0, uint32_t* v1, const uint32_t* key); static void psa_unpack_tea_result_to_buffer(uint8_t* buffer, uint32_t v0, uint32_t v1); static void psa_second_stage_xor_encrypt(uint8_t* buffer) { - uint8_t E6 = buffer[8]; uint8_t E7 = buffer[9]; - + uint8_t P[6]; P[0] = buffer[2]; P[1] = buffer[3]; @@ -154,14 +141,14 @@ static void psa_second_stage_xor_encrypt(uint8_t* buffer) { P[3] = buffer[5]; P[4] = buffer[6]; P[5] = buffer[7]; - + uint8_t E5 = P[5] ^ E7 ^ E6; uint8_t E0 = P[2] ^ E5; uint8_t E2 = P[4] ^ E0; uint8_t E4 = P[3] ^ E2; uint8_t E3 = P[0] ^ E5; uint8_t E1 = P[1] ^ E3; - + buffer[2] = E0; buffer[3] = E1; buffer[4] = E2; @@ -170,15 +157,21 @@ static void psa_second_stage_xor_encrypt(uint8_t* buffer) { buffer[7] = E5; } -static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer, uint8_t* preserve_buffer01) { - +static void psa_build_buffer_mode23( + SubGhzProtocolEncoderPSA* instance, + uint8_t* buffer, + uint8_t* preserve_buffer01) { FURI_LOG_I(TAG, "=== MODE 0x23 ENCRYPTION ==="); - FURI_LOG_I(TAG, "Input: Ser:%06lX Cnt:%08lX CRC:%02X Btn:%01X", - (unsigned long)instance->serial, (unsigned long)instance->counter, - (unsigned int)instance->crc, (unsigned int)instance->button); - + FURI_LOG_I( + TAG, + "Input: Ser:%06lX Cnt:%08lX CRC:%02X Btn:%01X", + (unsigned long)instance->serial, + (unsigned long)instance->counter, + (unsigned int)instance->crc, + (unsigned int)instance->button); + memset(buffer, 0, 48); - + buffer[2] = (uint8_t)((instance->serial >> 16) & 0xFF); buffer[3] = (uint8_t)((instance->serial >> 8) & 0xFF); buffer[4] = (uint8_t)(instance->serial & 0xFF); @@ -186,23 +179,36 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer[6] = (uint8_t)(instance->counter & 0xFF); buffer[7] = (uint8_t)(instance->crc & 0xFF); buffer[8] = (uint8_t)(instance->button & 0xF); - + uint8_t original_buffer9 = 0; uint8_t original_buffer8 = 0; - bool has_original_key2 = (instance->key2_low != 0); + bool has_original_key2 = (instance->generic.data_2 != 0); if(has_original_key2) { - original_buffer9 = (uint8_t)(instance->key2_low & 0xFF); - original_buffer8 = (uint8_t)((instance->key2_low >> 8) & 0xFF); + original_buffer9 = (uint8_t)(instance->generic.data_2 & 0xFF); + original_buffer8 = (uint8_t)((instance->generic.data_2 >> 8) & 0xFF); buffer[9] = original_buffer9; - FURI_LOG_D(TAG, "Original Key2: 0x%04X, buffer[8]=0x%02X buffer[9]=0x%02X, preserving buffer[9]", - (unsigned int)instance->key2_low, original_buffer8, original_buffer9); + FURI_LOG_D( + TAG, + "Original Key2: 0x%04X, buffer[8]=0x%02X buffer[9]=0x%02X, preserving buffer[9]", + (unsigned int)(instance->generic.data_2 & 0xFFFF), + original_buffer8, + original_buffer9); } else { FURI_LOG_D(TAG, "No original Key2, will find valid buffer[9]"); } - - FURI_LOG_D(TAG, "Plaintext buffer[2-9]: %02X %02X %02X %02X %02X %02X %02X %02X", - buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9]); - + + FURI_LOG_D( + TAG, + "Plaintext buffer[2-9]: %02X %02X %02X %02X %02X %02X %02X %02X", + buffer[2], + buffer[3], + buffer[4], + buffer[5], + buffer[6], + buffer[7], + buffer[8], + buffer[9]); + uint8_t initial_plaintext[6]; initial_plaintext[0] = buffer[2]; initial_plaintext[1] = buffer[3]; @@ -211,14 +217,13 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* initial_plaintext[4] = buffer[6]; initial_plaintext[5] = buffer[7]; uint8_t initial_button = buffer[8] & 0xF; - + bool found = false; uint8_t buffer9_to_use = has_original_key2 ? original_buffer9 : 0; uint8_t buffer9_end = has_original_key2 ? original_buffer9 + 1 : 255; - + for(uint8_t buffer9_try = buffer9_to_use; buffer9_try < buffer9_end && !found; buffer9_try++) { for(uint8_t buffer8_high_try = 0; buffer8_high_try < 16 && !found; buffer8_high_try++) { - buffer[2] = initial_plaintext[0]; buffer[3] = initial_plaintext[1]; buffer[4] = initial_plaintext[2]; @@ -227,24 +232,28 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer[7] = initial_plaintext[5]; buffer[8] = initial_button | (buffer8_high_try << 4); buffer[9] = buffer9_try; - + psa_second_stage_xor_encrypt(buffer); - + psa_calculate_checksum(buffer); uint8_t checksum_after = buffer[11]; uint8_t key2_high_after = checksum_after & 0xF0; - + uint8_t validation = (checksum_after ^ buffer[8]) & 0xF0; if(validation == 0) { buffer[8] = (buffer[8] & 0x0F) | key2_high_after; buffer[13] = buffer[9] ^ buffer[8]; found = true; - FURI_LOG_D(TAG, "Found valid Key2: buffer[8]=0x%02X buffer[9]=0x%02X", buffer[8], buffer[9]); + FURI_LOG_D( + TAG, + "Found valid Key2: buffer[8]=0x%02X buffer[9]=0x%02X", + buffer[8], + buffer[9]); break; } } } - + if(!found) { FURI_LOG_W(TAG, "Brute force failed, using default approach"); buffer[2] = initial_plaintext[0]; @@ -255,7 +264,7 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer[7] = initial_plaintext[5]; buffer[8] = initial_button; buffer[9] = has_original_key2 ? original_buffer9 : 0x23; - + psa_second_stage_xor_encrypt(buffer); psa_calculate_checksum(buffer); uint8_t checksum_after = buffer[11]; @@ -263,110 +272,152 @@ static void psa_build_buffer_mode23(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer[8] = (buffer[8] & 0x0F) | key2_high_after; buffer[13] = buffer[9] ^ buffer[8]; } - + if(preserve_buffer01 != NULL) { buffer[0] = preserve_buffer01[0]; buffer[1] = preserve_buffer01[1]; - FURI_LOG_D(TAG, "Preserved buffer[0-1] from original Key1: %02X %02X", buffer[0], buffer[1]); + FURI_LOG_D( + TAG, "Preserved buffer[0-1] from original Key1: %02X %02X", buffer[0], buffer[1]); } else { buffer[0] = buffer[2] ^ buffer[6]; buffer[1] = buffer[3] ^ buffer[7]; FURI_LOG_D(TAG, "Derived buffer[0-1]: %02X %02X", buffer[0], buffer[1]); } - - FURI_LOG_I(TAG, "Encrypted buffer[0-9]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9]); + + FURI_LOG_I( + TAG, + "Encrypted buffer[0-9]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + buffer[0], + buffer[1], + buffer[2], + buffer[3], + buffer[4], + buffer[5], + buffer[6], + buffer[7], + buffer[8], + buffer[9]); } -static void psa_build_buffer_mode36(SubGhzProtocolEncoderPSA* instance, uint8_t* buffer, uint8_t* preserve_buffer01) { +static void psa_build_buffer_mode36( + SubGhzProtocolEncoderPSA* instance, + uint8_t* buffer, + uint8_t* preserve_buffer01) { FURI_LOG_I(TAG, "=== MODE 0x36 ENCRYPTION ==="); - FURI_LOG_I(TAG, "Input: Ser:%06lX Cnt:%08lX CRC:%02X Btn:%01X", - (unsigned long)instance->serial, (unsigned long)instance->counter, - (unsigned int)instance->crc, (unsigned int)instance->button); - + FURI_LOG_I( + TAG, + "Input: Ser:%06lX Cnt:%08lX CRC:%02X Btn:%01X", + (unsigned long)instance->serial, + (unsigned long)instance->counter, + (unsigned int)instance->crc, + (unsigned int)instance->button); + memset(buffer, 0, 48); - - uint32_t v0 = ((instance->serial & 0xFFFFFF) << 8) | - ((instance->counter >> 24) & 0xFF); - uint32_t v1 = ((instance->counter & 0xFFFFFF) << 8) | - ((instance->button & 0xF) << 4) | - (instance->crc & 0xFF); - - FURI_LOG_D(TAG, "Packed v0:0x%08lX v1:0x%08lX (before CRC)", (unsigned long)v0, (unsigned long)v1); - + + uint32_t v0 = ((instance->serial & 0xFFFFFF) << 8) | ((instance->counter >> 24) & 0xFF); + uint32_t v1 = ((instance->counter & 0xFFFFFF) << 8) | ((instance->button & 0xF) << 4) | + (instance->crc & 0xFF); + + FURI_LOG_D( + TAG, "Packed v0:0x%08lX v1:0x%08lX (before CRC)", (unsigned long)v0, (unsigned long)v1); + uint8_t crc = psa_calculate_tea_crc(v0, v1); v1 = (v1 & 0xFFFFFF00) | crc; - - FURI_LOG_D(TAG, "Calculated CRC: 0x%02X, v1 after CRC: 0x%08lX", (unsigned int)crc, (unsigned long)v1); - + + FURI_LOG_D( + TAG, "Calculated CRC: 0x%02X, v1 after CRC: 0x%08lX", (unsigned int)crc, (unsigned long)v1); + uint32_t bf_counter = PSA_BF1_START | (instance->serial & 0xFFFFFF); FURI_LOG_D(TAG, "BF counter: 0x%08lX (BF1_START | serial)", (unsigned long)bf_counter); - + uint32_t working_key[4]; - + uint32_t wk2 = PSA_BF1_CONST_U4; uint32_t wk3 = bf_counter; psa_tea_encrypt(&wk2, &wk3, PSA_BF1_KEY_SCHEDULE); - + uint32_t wk0 = (bf_counter << 8) | 0x0E; uint32_t wk1 = PSA_BF1_CONST_U5; psa_tea_encrypt(&wk0, &wk1, PSA_BF1_KEY_SCHEDULE); - + working_key[0] = wk0; working_key[1] = wk1; working_key[2] = wk2; working_key[3] = wk3; - + psa_tea_encrypt(&v0, &v1, working_key); - + FURI_LOG_D(TAG, "TEA encrypted v0:0x%08lX v1:0x%08lX", (unsigned long)v0, (unsigned long)v1); - FURI_LOG_D(TAG, "Working key: %08lX %08lX %08lX %08lX", - (unsigned long)working_key[0], (unsigned long)working_key[1], - (unsigned long)working_key[2], (unsigned long)working_key[3]); - + FURI_LOG_D( + TAG, + "Working key: %08lX %08lX %08lX %08lX", + (unsigned long)working_key[0], + (unsigned long)working_key[1], + (unsigned long)working_key[2], + (unsigned long)working_key[3]); + psa_unpack_tea_result_to_buffer(buffer, v0, v1); - + if(preserve_buffer01 != NULL) { buffer[0] = preserve_buffer01[0]; buffer[1] = preserve_buffer01[1]; - FURI_LOG_D(TAG, "Preserved buffer[0-1] from original Key1: %02X %02X", buffer[0], buffer[1]); + FURI_LOG_D( + TAG, "Preserved buffer[0-1] from original Key1: %02X %02X", buffer[0], buffer[1]); } else { buffer[0] = buffer[2] ^ buffer[6]; buffer[1] = buffer[3] ^ buffer[7]; FURI_LOG_D(TAG, "Derived buffer[0-1]: %02X %02X", buffer[0], buffer[1]); } - - FURI_LOG_I(TAG, "Encrypted buffer[0-9]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9]); + + FURI_LOG_I( + TAG, + "Encrypted buffer[0-9]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + buffer[0], + buffer[1], + buffer[2], + buffer[3], + buffer[4], + buffer[5], + buffer[6], + buffer[7], + buffer[8], + buffer[9]); } static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { furi_assert(instance); - + FURI_LOG_I(TAG, "=== ENCODER BUILD UPLOAD ==="); - FURI_LOG_I(TAG, "Mode: 0x%02X, Serial:%06lX Counter:%08lX CRC:%02X Button:%01X", - (unsigned int)instance->mode, (unsigned long)instance->serial, - (unsigned long)instance->counter, (unsigned int)instance->crc, + FURI_LOG_I( + TAG, + "Mode: 0x%02X, Serial:%06lX Counter:%08lX CRC:%02X Button:%01X", + (unsigned int)instance->mode, + (unsigned long)instance->serial, + (unsigned long)instance->counter, + (unsigned int)instance->crc, (unsigned int)instance->button); - + uint8_t buffer[48] = {0}; - + uint8_t preserve_buffer01[2] = {0}; uint8_t* preserve_ptr = NULL; - - if(instance->key1_low != 0 || instance->key1_high != 0) { + + if(instance->generic.data != 0) { uint8_t orig_buffer[48] = {0}; - psa_setup_byte_buffer(orig_buffer, instance->key1_low, instance->key1_high, instance->key2_low); + psa_setup_byte_buffer(orig_buffer, instance->generic.data, instance->generic.data_2); preserve_buffer01[0] = orig_buffer[0]; preserve_buffer01[1] = orig_buffer[1]; preserve_ptr = preserve_buffer01; - FURI_LOG_D(TAG, "Original Key1: %08lX%08lX, preserving buffer[0-1]: %02X %02X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - preserve_buffer01[0], preserve_buffer01[1]); + FURI_LOG_D( + TAG, + "Original Key1: %016llX, preserving buffer[0-1]: %02X %02X", + (unsigned long long)instance->generic.data, + preserve_buffer01[0], + preserve_buffer01[1]); } else { FURI_LOG_D(TAG, "No original Key1, will derive buffer[0-1]"); } - + if(instance->mode == 0x23) { psa_build_buffer_mode23(instance, buffer, preserve_ptr); } else if(instance->mode == 0x36) { @@ -375,33 +426,33 @@ static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { FURI_LOG_E(TAG, "Unknown mode: 0x%02X", instance->mode); return; } - + uint32_t key1_high = ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) | ((uint32_t)buffer[2] << 8) | (uint32_t)buffer[3]; uint32_t key1_low = ((uint32_t)buffer[4] << 24) | ((uint32_t)buffer[5] << 16) | ((uint32_t)buffer[6] << 8) | (uint32_t)buffer[7]; uint16_t validation_field = ((uint16_t)buffer[8] << 8) | (uint16_t)buffer[9]; - + FURI_LOG_I(TAG, "=== ENCRYPTED KEYS ==="); FURI_LOG_I(TAG, "Key1: %08lX%08lX", (unsigned long)key1_high, (unsigned long)key1_low); FURI_LOG_I(TAG, "Key2: %04X", (unsigned int)validation_field); - + size_t index = 0; uint32_t te = PSA_TE_LONG_250; - + for(int i = 0; i < 80; i++) { if(index >= instance->encoder.size_upload - 2) break; instance->encoder.upload[index++] = level_duration_make(true, te); instance->encoder.upload[index++] = level_duration_make(false, te); } - + uint32_t te_long_transition = subghz_protocol_psa_const.te_long; if(index < instance->encoder.size_upload - 3) { instance->encoder.upload[index++] = level_duration_make(false, te); instance->encoder.upload[index++] = level_duration_make(true, te_long_transition); instance->encoder.upload[index++] = level_duration_make(false, te); } - + uint64_t key1_data = ((uint64_t)key1_high << 32) | key1_low; for(int bit = 63; bit >= 0; bit--) { if(index >= instance->encoder.size_upload - 2) break; @@ -414,7 +465,7 @@ static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { instance->encoder.upload[index++] = level_duration_make(true, te); } } - + for(int bit = 15; bit >= 0; bit--) { if(index >= instance->encoder.size_upload - 2) break; bool bit_value = (validation_field >> bit) & 1; @@ -426,22 +477,29 @@ static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { instance->encoder.upload[index++] = level_duration_make(true, te); } } - + uint32_t end_duration = PSA_TE_END_1000; if(index < instance->encoder.size_upload - 1) { instance->encoder.upload[index++] = level_duration_make(true, end_duration); instance->encoder.upload[index++] = level_duration_make(false, end_duration); } - + instance->encoder.size_upload = index; instance->encoder.front = 0; instance->encoder.repeat = 10; - + FURI_LOG_I(TAG, "=== TRANSMISSION PARAMETERS ==="); - FURI_LOG_I(TAG, "TE: %lu, TE_LONG_TRANS: %lu, TE_END: %lu", - (unsigned long)te, (unsigned long)te_long_transition, (unsigned long)end_duration); - FURI_LOG_I(TAG, "Upload size: %zu levels, Repeat: %d", - instance->encoder.size_upload, instance->encoder.repeat); + FURI_LOG_I( + TAG, + "TE: %lu, TE_LONG_TRANS: %lu, TE_END: %lu", + (unsigned long)te, + (unsigned long)te_long_transition, + (unsigned long)end_duration); + FURI_LOG_I( + TAG, + "Upload size: %zu levels, Repeat: %d", + instance->encoder.size_upload, + instance->encoder.repeat); FURI_LOG_I(TAG, "Key1 data (64-bit): %016llX", (unsigned long long)key1_data); FURI_LOG_I(TAG, "Key2 data (16-bit): %04X", (unsigned int)validation_field); FURI_LOG_I(TAG, "=== END ENCODER BUILD ==="); @@ -450,12 +508,12 @@ static void psa_encoder_build_upload(SubGhzProtocolEncoderPSA* instance) { void* subghz_protocol_encoder_psa_alloc(SubGhzEnvironment* environment) { UNUSED(environment); SubGhzProtocolEncoderPSA* instance = malloc(sizeof(SubGhzProtocolEncoderPSA)); - + if(instance) { memset(instance, 0, sizeof(SubGhzProtocolEncoderPSA)); instance->base.protocol = &psa_protocol; instance->generic.protocol_name = instance->base.protocol->name; - + instance->encoder.size_upload = 600; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); instance->encoder.repeat = 10; @@ -463,14 +521,14 @@ void* subghz_protocol_encoder_psa_alloc(SubGhzEnvironment* environment) { instance->encoder.is_running = false; instance->is_running = false; } - + return instance; } void subghz_protocol_encoder_psa_free(void* context) { furi_assert(context); SubGhzProtocolEncoderPSA* instance = context; - + if(instance->encoder.upload) { free(instance->encoder.upload); } @@ -481,23 +539,25 @@ SubGhzProtocolStatus subghz_protocol_encoder_psa_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderPSA* instance = context; - + FURI_LOG_I(TAG, "=== ENCODER DESERIALIZE ==="); - + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; FuriString* temp_str = furi_string_alloc(); uint8_t hex_buffer[8]; - + do { if(!flipper_format_read_string(flipper_format, "Key", temp_str)) { if(!flipper_format_read_hex(flipper_format, "Key1", hex_buffer, 8)) { FURI_LOG_E(TAG, "Failed to read Key1"); break; } - instance->key1_low = ((uint32_t)hex_buffer[0] << 24) | ((uint32_t)hex_buffer[1] << 16) | - ((uint32_t)hex_buffer[2] << 8) | (uint32_t)hex_buffer[3]; - instance->key1_high = ((uint32_t)hex_buffer[4] << 24) | ((uint32_t)hex_buffer[5] << 16) | - ((uint32_t)hex_buffer[6] << 8) | (uint32_t)hex_buffer[7]; + uint32_t key1_low = ((uint32_t)hex_buffer[0] << 24) | ((uint32_t)hex_buffer[1] << 16) | + ((uint32_t)hex_buffer[2] << 8) | (uint32_t)hex_buffer[3]; + uint32_t key1_high = ((uint32_t)hex_buffer[4] << 24) | + ((uint32_t)hex_buffer[5] << 16) | ((uint32_t)hex_buffer[6] << 8) | + (uint32_t)hex_buffer[7]; + instance->generic.data = ((uint64_t)key1_high << 32) | key1_low; } else { const char* key_str = furi_string_get_cstr(temp_str); uint64_t key1 = 0; @@ -517,10 +577,9 @@ SubGhzProtocolStatus } key1 = (key1 << 4) | nibble; } - instance->key1_low = (uint32_t)(key1 & 0xFFFFFFFF); - instance->key1_high = (uint32_t)((key1 >> 32) & 0xFFFFFFFF); + instance->generic.data = key1; } - + flipper_format_rewind(flipper_format); if(flipper_format_read_string(flipper_format, "Key_2", temp_str)) { const char* key2_str = furi_string_get_cstr(temp_str); @@ -541,37 +600,37 @@ SubGhzProtocolStatus } key2 = (key2 << 4) | nibble; } - instance->key2_low = (uint32_t)(key2 & 0xFFFFFFFF); + instance->generic.data_2 = key2; instance->validation_field = (uint16_t)(key2 & 0xFFFF); } else { uint32_t val_field_val; if(flipper_format_read_uint32(flipper_format, "ValidationField", &val_field_val, 1)) { instance->validation_field = (uint16_t)(val_field_val & 0xFFFF); - instance->key2_low = instance->validation_field; - } else { - uint8_t val_field[2]; + instance->generic.data_2 = (uint64_t)instance->validation_field; + } else { + uint8_t val_field[2]; if(flipper_format_read_hex(flipper_format, "ValidationField", val_field, 2)) { instance->validation_field = ((uint16_t)val_field[0] << 8) | val_field[1]; - instance->key2_low = instance->validation_field; + instance->generic.data_2 = (uint64_t)instance->validation_field; } else { FURI_LOG_E(TAG, "ValidationField not found"); break; } } } - + flipper_format_rewind(flipper_format); if(!flipper_format_read_uint32(flipper_format, "Serial", &instance->serial, 1)) { FURI_LOG_E(TAG, "Serial not found"); break; } - + flipper_format_rewind(flipper_format); if(!flipper_format_read_uint32(flipper_format, "Cnt", &instance->counter, 1)) { FURI_LOG_E(TAG, "Counter not found"); break; } - + flipper_format_rewind(flipper_format); uint32_t btn_val = 0; if(!flipper_format_read_uint32(flipper_format, "Btn", &btn_val, 1)) { @@ -579,7 +638,7 @@ SubGhzProtocolStatus break; } instance->button = (uint8_t)(btn_val & 0xFF); - + flipper_format_rewind(flipper_format); uint32_t type_val = 0; if(!flipper_format_read_uint32(flipper_format, "Type", &type_val, 1)) { @@ -587,7 +646,7 @@ SubGhzProtocolStatus break; } instance->type = (uint8_t)(type_val & 0xFF); - + flipper_format_rewind(flipper_format); uint32_t crc_val = 0; if(!flipper_format_read_uint32(flipper_format, "CRC", &crc_val, 1)) { @@ -595,15 +654,15 @@ SubGhzProtocolStatus break; } instance->crc = (uint16_t)(crc_val & 0xFFFF); - + flipper_format_rewind(flipper_format); uint32_t seed_val = 0; if(!flipper_format_read_uint32(flipper_format, "Seed", &seed_val, 1)) { FURI_LOG_E(TAG, "Seed not found"); break; } - instance->seed = (uint8_t)(seed_val & 0xFF); - + instance->generic.seed = (uint8_t)(seed_val & 0xFF); + instance->mode = instance->type; if(instance->mode == 0x23 || instance->mode == 0) { instance->mode = 0x23; @@ -612,21 +671,29 @@ SubGhzProtocolStatus } else { instance->mode = 0x23; } - + FURI_LOG_I(TAG, "=== LOADED VALUES ==="); - FURI_LOG_I(TAG, "Key1: %08lX%08lX", (unsigned long)instance->key1_high, (unsigned long)instance->key1_low); - FURI_LOG_I(TAG, "Key2: %04X (validation_field: %04X)", - (unsigned int)instance->key2_low, (unsigned int)instance->validation_field); - FURI_LOG_I(TAG, "Serial: %06lX, Counter: %08lX, CRC: %02X, Button: %01X, Type/Mode: 0x%02X", - (unsigned long)instance->serial, (unsigned long)instance->counter, - (unsigned int)instance->crc, (unsigned int)instance->button, (unsigned int)instance->mode); - + FURI_LOG_I(TAG, "Key1: %016llX", (unsigned long long)instance->generic.data); + FURI_LOG_I( + TAG, + "Key2: %04X (validation_field: %04X)", + (unsigned int)(instance->generic.data_2 & 0xFFFF), + (unsigned int)instance->validation_field); + FURI_LOG_I( + TAG, + "Serial: %06lX, Counter: %08lX, CRC: %02X, Button: %01X, Type/Mode: 0x%02X", + (unsigned long)instance->serial, + (unsigned long)instance->counter, + (unsigned int)instance->crc, + (unsigned int)instance->button, + (unsigned int)instance->mode); + psa_encoder_build_upload(instance); - + instance->is_running = true; ret = SubGhzProtocolStatusOk; } while(false); - + furi_string_free(temp_str); return ret; } @@ -641,15 +708,15 @@ void subghz_protocol_encoder_psa_stop(void* context) { LevelDuration subghz_protocol_encoder_psa_yield(void* context) { furi_assert(context); SubGhzProtocolEncoderPSA* instance = context; - + if(!instance->is_running || instance->encoder.size_upload == 0) { instance->is_running = false; return level_duration_reset(); } - + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; instance->encoder.front++; - + if(instance->encoder.front >= instance->encoder.size_upload) { instance->encoder.front = 0; instance->encoder.repeat--; @@ -657,7 +724,7 @@ LevelDuration subghz_protocol_encoder_psa_yield(void* context) { instance->is_running = false; } } - + return ret; } @@ -669,19 +736,13 @@ static uint32_t psa_abs_diff(uint32_t a, uint32_t b) { } } -static void psa_setup_byte_buffer(uint8_t* buffer, uint32_t key1_low, uint32_t key1_high, uint32_t key2_low) { +static void psa_setup_byte_buffer(uint8_t* buffer, uint64_t key1, uint64_t key2) { for(int i = 0; i < 8; i++) { int shift = i * 8; - uint8_t byte_val; - if(shift < 32) { - byte_val = (uint8_t)((key1_low >> shift) & 0xFF); - } else { - byte_val = (uint8_t)((key1_high >> (shift - 32)) & 0xFF); - } - buffer[7 - i] = byte_val; + buffer[7 - i] = (uint8_t)((key1 >> shift) & 0xFF); } - buffer[9] = (uint8_t)(key2_low & 0xFF); - buffer[8] = (uint8_t)((key2_low >> 8) & 0xFF); + buffer[9] = (uint8_t)(key2 & 0xFF); + buffer[8] = (uint8_t)((key2 >> 8) & 0xFF); } static void psa_calculate_checksum(uint8_t* buffer) { @@ -741,15 +802,14 @@ static void psa_tea_decrypt(uint32_t* v0, uint32_t* v1, const uint32_t* key) { } static void psa_prepare_tea_data(uint8_t* buffer, uint32_t* w0, uint32_t* w1) { - *w0 = ((uint32_t)buffer[3] << 16) | ((uint32_t)buffer[2] << 24) | - ((uint32_t)buffer[4] << 8) | (uint32_t)buffer[5]; - *w1 = ((uint32_t)buffer[7] << 16) | ((uint32_t)buffer[6] << 24) | - ((uint32_t)buffer[8] << 8) | (uint32_t)buffer[9]; + *w0 = ((uint32_t)buffer[3] << 16) | ((uint32_t)buffer[2] << 24) | ((uint32_t)buffer[4] << 8) | + (uint32_t)buffer[5]; + *w1 = ((uint32_t)buffer[7] << 16) | ((uint32_t)buffer[6] << 24) | ((uint32_t)buffer[8] << 8) | + (uint32_t)buffer[9]; } static uint8_t psa_calculate_tea_crc(uint32_t v0, uint32_t v1) { - uint32_t crc = ((v0 >> 24) & 0xFF) + ((v0 >> 16) & 0xFF) + - ((v0 >> 8) & 0xFF) + (v0 & 0xFF); + uint32_t crc = ((v0 >> 24) & 0xFF) + ((v0 >> 16) & 0xFF) + ((v0 >> 8) & 0xFF) + (v0 & 0xFF); crc += ((v1 >> 24) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v1 >> 8) & 0xFF); return (uint8_t)(crc & 0xFF); } @@ -782,40 +842,44 @@ static void psa_unpack_tea_result_to_buffer(uint8_t* buffer, uint32_t v0, uint32 } static void psa_extract_fields_mode23(uint8_t* buffer, SubGhzProtocolDecoderPSA* instance) { - instance->decrypted_button = buffer[8] & 0xF; - instance->decrypted_serial = ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16) | (uint32_t)buffer[4]; - instance->decrypted_counter = (uint32_t)buffer[6] | ((uint32_t)buffer[5] << 8); + instance->generic.btn = buffer[8] & 0xF; + instance->generic.serial = ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16) | + (uint32_t)buffer[4]; + instance->generic.cnt = (uint32_t)buffer[6] | ((uint32_t)buffer[5] << 8); instance->decrypted_crc = (uint16_t)buffer[7]; instance->decrypted_type = 0x23; - instance->decrypted_seed = instance->decrypted_serial; } static void psa_extract_fields_mode36(uint8_t* buffer, SubGhzProtocolDecoderPSA* instance) { - instance->decrypted_button = (buffer[5] >> 4) & 0xF; - instance->decrypted_serial = ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16) | (uint32_t)buffer[4]; - instance->decrypted_counter = ((uint32_t)buffer[7] << 8) | ((uint32_t)buffer[6] << 16) | - (uint32_t)buffer[8] | (((uint32_t)buffer[5] & 0xF) << 24); + instance->generic.btn = (buffer[5] >> 4) & 0xF; + instance->generic.serial = ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16) | + (uint32_t)buffer[4]; + instance->generic.cnt = ((uint32_t)buffer[7] << 8) | ((uint32_t)buffer[6] << 16) | + (uint32_t)buffer[8] | (((uint32_t)buffer[5] & 0xF) << 24); instance->decrypted_crc = (uint16_t)buffer[9]; instance->decrypted_type = 0x36; - instance->decrypted_seed = instance->decrypted_serial; } -static bool psa_brute_force_decrypt_bf1(SubGhzProtocolDecoderPSA* instance, uint8_t* buffer, uint32_t w0, uint32_t w1) { +static bool psa_brute_force_decrypt_bf1( + SubGhzProtocolDecoderPSA* instance, + uint8_t* buffer, + uint32_t w0, + uint32_t w1) { for(uint32_t counter = PSA_BF1_START; counter < PSA_BF1_END; counter++) { uint32_t wk2 = PSA_BF1_CONST_U4; uint32_t wk3 = counter; psa_tea_encrypt(&wk2, &wk3, PSA_BF1_KEY_SCHEDULE); - + uint32_t wk0 = (counter << 8) | 0x0E; uint32_t wk1 = PSA_BF1_CONST_U5; psa_tea_encrypt(&wk0, &wk1, PSA_BF1_KEY_SCHEDULE); - + uint32_t working_key[4] = {wk0, wk1, wk2, wk3}; - + uint32_t dec_v0 = w0; uint32_t dec_v1 = w1; psa_tea_decrypt(&dec_v0, &dec_v1, working_key); - + if((counter & 0xFFFFFF) == (dec_v0 >> 8)) { uint8_t crc = psa_calculate_tea_crc(dec_v0, dec_v1); if(crc == (dec_v1 & 0xFF)) { @@ -828,7 +892,11 @@ static bool psa_brute_force_decrypt_bf1(SubGhzProtocolDecoderPSA* instance, uint return false; } -static bool psa_brute_force_decrypt_bf2(SubGhzProtocolDecoderPSA* instance, uint8_t* buffer, uint32_t w0, uint32_t w1) { +static bool psa_brute_force_decrypt_bf2( + SubGhzProtocolDecoderPSA* instance, + uint8_t* buffer, + uint32_t w0, + uint32_t w1) { for(uint32_t counter = PSA_BF2_START; counter < PSA_BF2_END; counter++) { uint32_t working_key[4] = { PSA_BF2_KEY_SCHEDULE[0] ^ counter, @@ -836,14 +904,14 @@ static bool psa_brute_force_decrypt_bf2(SubGhzProtocolDecoderPSA* instance, uint PSA_BF2_KEY_SCHEDULE[2] ^ counter, PSA_BF2_KEY_SCHEDULE[3] ^ counter, }; - + uint32_t dec_v0 = w0; uint32_t dec_v1 = w1; psa_tea_decrypt(&dec_v0, &dec_v1, working_key); - + if((counter & 0xFFFFFF) == (dec_v0 >> 8)) { psa_unpack_tea_result_to_buffer(buffer, dec_v0, dec_v1); - + uint8_t crc_buffer[6] = { (uint8_t)((dec_v0 >> 24) & 0xFF), (uint8_t)((dec_v0 >> 8) & 0xFF), @@ -854,7 +922,7 @@ static bool psa_brute_force_decrypt_bf2(SubGhzProtocolDecoderPSA* instance, uint }; uint16_t crc16 = psa_calculate_crc16_bf2(crc_buffer, 6); uint16_t expected_crc = (((dec_v1 >> 16) & 0xFF) << 8) | (dec_v1 & 0xFF); - + if(crc16 == expected_crc) { psa_extract_fields_mode36(buffer, instance); return true; @@ -868,11 +936,15 @@ static bool psa_direct_xor_decrypt(SubGhzProtocolDecoderPSA* instance, uint8_t* psa_calculate_checksum(buffer); uint8_t checksum = buffer[11]; uint8_t key2_high = buffer[8]; - + uint8_t validation_result = (checksum ^ key2_high) & 0xF0; - FURI_LOG_D(TAG, "Direct XOR validation: checksum=0x%02X, key2_high=0x%02X, result=0x%02X", - checksum, key2_high, validation_result); - + FURI_LOG_D( + TAG, + "Direct XOR validation: checksum=0x%02X, key2_high=0x%02X, result=0x%02X", + checksum, + key2_high, + validation_result); + if(validation_result == 0) { buffer[13] = buffer[9] ^ buffer[8]; psa_second_stage_xor_decrypt(buffer); @@ -880,34 +952,43 @@ static bool psa_direct_xor_decrypt(SubGhzProtocolDecoderPSA* instance, uint8_t* FURI_LOG_D(TAG, "Direct XOR decryption completed"); return true; } - FURI_LOG_D(TAG, "Direct XOR validation FAILED: (checksum ^ key2_high) & 0xF0 = 0x%02X (expected 0x00)", + FURI_LOG_D( + TAG, + "Direct XOR validation FAILED: (checksum ^ key2_high) & 0xF0 = 0x%02X (expected 0x00)", validation_result); return false; } static void psa_decrypt_router(SubGhzProtocolDecoderPSA* instance) { FURI_LOG_I(TAG, "=== DECRYPTION ROUTER CALLED ==="); - FURI_LOG_I(TAG, "Key1:%08lX%08lX Key2:%04X mode_serialize:0x%02X decrypted:0x%02X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - (unsigned int)(instance->key2_low & 0xFFFF), - (unsigned int)instance->mode_serialize, (unsigned int)instance->decrypted); - + uint32_t key1_high = (uint32_t)(instance->generic.data >> 32); + uint32_t key1_low = (uint32_t)instance->generic.data; + FURI_LOG_I( + TAG, + "Key1:%08lX%08lX Key2:%04X mode_serialize:0x%02X decrypted:0x%02X", + (unsigned long)key1_high, + (unsigned long)key1_low, + (unsigned int)(instance->generic.data_2 & 0xFFFF), + (unsigned int)instance->mode_serialize, + (unsigned int)instance->decrypted); + uint8_t buffer[48] = {0}; - - psa_setup_byte_buffer(buffer, instance->key1_low, instance->key1_high, instance->key2_low); - + + psa_setup_byte_buffer(buffer, instance->generic.data, instance->generic.data_2); + uint8_t mode = instance->mode_serialize; - + if(mode == 1 || mode == 2) { if(psa_direct_xor_decrypt(instance, buffer)) { mode = 0x23; FURI_LOG_I(TAG, "Converted mode %d -> 0x23 (Direct XOR)", instance->mode_serialize); } else { mode = 0x36; - FURI_LOG_I(TAG, "Converted mode %d -> 0x36 (TEA Brute Force)", instance->mode_serialize); + FURI_LOG_I( + TAG, "Converted mode %d -> 0x36 (TEA Brute Force)", instance->mode_serialize); } } - + if(mode == 0x23) { FURI_LOG_I(TAG, "Attempting Direct XOR decryption (Type 0x23)"); if(psa_direct_xor_decrypt(instance, buffer)) { @@ -919,27 +1000,34 @@ static void psa_decrypt_router(SubGhzProtocolDecoderPSA* instance) { FURI_LOG_W(TAG, "Direct XOR decryption FAILED"); } else if(mode == 0x36) { FURI_LOG_I(TAG, "Attempting TEA brute force decryption (Type 0x36)"); - + uint32_t w0, w1; psa_prepare_tea_data(buffer, &w0, &w1); - FURI_LOG_D(TAG, "Prepared TEA data: w0=0x%08lX w1=0x%08lX", (unsigned long)w0, (unsigned long)w1); - + FURI_LOG_D( + TAG, "Prepared TEA data: w0=0x%08lX w1=0x%08lX", (unsigned long)w0, (unsigned long)w1); + FURI_LOG_I(TAG, "Starting BF1 brute force..."); if(psa_brute_force_decrypt_bf1(instance, buffer, w0, w1)) { instance->mode_serialize = 0x36; instance->decrypted = 0x50; - FURI_LOG_I(TAG, "BF1 brute force SUCCESS - Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, - (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); + FURI_LOG_I( + TAG, + "BF1 brute force SUCCESS - Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->generic.btn, + (unsigned long)instance->generic.serial, + (unsigned long)instance->generic.cnt); return; } FURI_LOG_W(TAG, "BF1 brute force FAILED - trying BF2..."); if(psa_brute_force_decrypt_bf2(instance, buffer, w0, w1)) { instance->mode_serialize = 0x36; instance->decrypted = 0x50; - FURI_LOG_I(TAG, "BF2 brute force SUCCESS - Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, - (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); + FURI_LOG_I( + TAG, + "BF2 brute force SUCCESS - Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->generic.btn, + (unsigned long)instance->generic.serial, + (unsigned long)instance->generic.cnt); return; } FURI_LOG_E(TAG, "Both BF1 and BF2 brute force FAILED"); @@ -951,11 +1039,11 @@ static void psa_decrypt_router(SubGhzProtocolDecoderPSA* instance) { FURI_LOG_I(TAG, "Direct XOR decryption SUCCESS"); return; } - + FURI_LOG_I(TAG, "Direct XOR failed - trying brute force..."); uint32_t w0, w1; psa_prepare_tea_data(buffer, &w0, &w1); - + if(psa_brute_force_decrypt_bf1(instance, buffer, w0, w1)) { instance->mode_serialize = 0x36; instance->decrypted = 0x50; @@ -969,7 +1057,7 @@ static void psa_decrypt_router(SubGhzProtocolDecoderPSA* instance) { return; } } - + FURI_LOG_E(TAG, "=== ALL DECRYPTION ATTEMPTS FAILED ==="); instance->decrypted = 0x00; } @@ -980,6 +1068,7 @@ void* subghz_protocol_decoder_psa_alloc(SubGhzEnvironment* environment) { if(instance) { memset(instance, 0, sizeof(SubGhzProtocolDecoderPSA)); instance->base.protocol = &psa_protocol; + instance->generic.protocol_name = instance->base.protocol->name; instance->manchester_state = ManchesterStateMid1; } return instance; @@ -997,39 +1086,36 @@ void subghz_protocol_decoder_psa_reset(void* context) { instance->state = 0; instance->status_flag = 0; instance->mode_serialize = 0; - instance->key1_low = 0; - instance->key1_high = 0; - instance->key2_low = 0; - instance->key2_high = 0; + instance->generic.data = 0; + instance->generic.data_2 = 0; instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; instance->pattern_counter = 0; instance->manchester_state = ManchesterStateMid1; - instance->decrypted_button = 0; - instance->decrypted_serial = 0; - instance->decrypted_counter = 0; + instance->generic.btn = 0; + instance->generic.serial = 0; + instance->generic.cnt = 0; instance->decrypted_crc = 0; - instance->decrypted_seed = 0; instance->decrypted_type = 0; } void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t duration) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; - + uint32_t tolerance; uint32_t new_state = instance->state; uint32_t prev_dur = instance->prev_duration; uint32_t te_short = subghz_protocol_psa_const.te_short; uint32_t te_long = subghz_protocol_psa_const.te_long; - + switch(instance->state) { case PSADecoderState0: if(!level) { return; } - + if(duration < te_short) { tolerance = te_short - duration; if(tolerance > PSA_TOLERANCE_99) { @@ -1055,7 +1141,7 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } new_state = PSADecoderState1; } - + instance->decode_data_low = 0; instance->decode_data_high = 0; instance->pattern_counter = 0; @@ -1063,21 +1149,20 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->mode_serialize = 0; instance->prev_duration = duration; instance->decrypted_type = 0; - instance->decrypted_button = 0; - instance->decrypted_serial = 0; - instance->decrypted_counter = 0; + instance->generic.btn = 0; + instance->generic.serial = 0; + instance->generic.cnt = 0; instance->decrypted_crc = 0; - instance->decrypted_seed = 0; instance->decrypted = 0x00; - manchester_advance(instance->manchester_state, ManchesterEventReset, - &instance->manchester_state, NULL); + manchester_advance( + instance->manchester_state, ManchesterEventReset, &instance->manchester_state, NULL); break; - + case PSADecoderState1: if(level) { return; } - + if(duration < te_short) { tolerance = te_short - duration; if(tolerance < PSA_TOLERANCE_100) { @@ -1106,14 +1191,19 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } if(long_diff < 100) { if(instance->pattern_counter > PSA_PATTERN_THRESHOLD_1) { - FURI_LOG_I(TAG, "[State1->State2] Transition detected with pattern_cnt=%lu", - (unsigned long)instance->pattern_counter); + FURI_LOG_I( + TAG, + "[State1->State2] Transition detected with pattern_cnt=%lu", + (unsigned long)instance->pattern_counter); new_state = PSADecoderState2; instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; - manchester_advance(instance->manchester_state, ManchesterEventReset, - &instance->manchester_state, NULL); + manchester_advance( + instance->manchester_state, + ManchesterEventReset, + &instance->manchester_state, + NULL); instance->state = new_state; } instance->pattern_counter = 0; @@ -1122,17 +1212,17 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } } } - + new_state = PSADecoderState0; instance->pattern_counter = 0; break; - + case PSADecoderState2: if(instance->decode_count_bit >= PSA_MAX_BITS) { new_state = PSADecoderState0; break; } - + if(level && instance->decode_count_bit == PSA_KEY2_BITS) { if(duration >= 800) { uint32_t end_diff; @@ -1142,7 +1232,7 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati end_diff = duration - PSA_TE_END_1000; } if(end_diff <= 199) { - if(((instance->key1_high >> 16) & 0xF) != 0xA) { + if(((instance->generic.data >> 48) & 0xF) != 0xA) { instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; @@ -1150,44 +1240,54 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->state = new_state; return; } - + uint32_t new_key2_low = instance->decode_data_low; instance->validation_field = (uint16_t)(instance->decode_data_low & 0xFFFF); - + instance->decrypted_type = 0; - instance->decrypted_button = 0; - instance->decrypted_serial = 0; - instance->decrypted_counter = 0; + instance->generic.btn = 0; + instance->generic.serial = 0; + instance->generic.cnt = 0; instance->decrypted_crc = 0; - instance->decrypted_seed = 0; instance->decrypted = 0x00; - - instance->key2_low = new_key2_low; - instance->key2_high = instance->decode_data_high; + + instance->generic.data_2 = ((uint64_t)instance->decode_data_high << 32) | + new_key2_low; instance->mode_serialize = 1; instance->status_flag = 0x80; - - FURI_LOG_I(TAG, "Signal decoded - Key1:%08lX%08lX Key2:%04X ValField:%04X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - (unsigned int)(instance->key2_low & 0xFFFF), (unsigned int)instance->validation_field); - - uint8_t buffer[48] = {0}; - psa_setup_byte_buffer(buffer, instance->key1_low, instance->key1_high, instance->key2_low); - if(psa_direct_xor_decrypt(instance, buffer)) { - instance->mode_serialize = 0x23; - instance->decrypted = 0x50; - FURI_LOG_I(TAG, "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); - } else { - instance->decrypted = 0x00; - instance->mode_serialize = 0x36; - FURI_LOG_I(TAG, "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); - } - - if(instance->base.callback) { - instance->base.callback(&instance->base, instance->base.context); - } - + + FURI_LOG_I( + TAG, + "Signal decoded - Key1:%08lX%08lX Key2:%04X ValField:%04X", + (unsigned long)(instance->generic.data >> 32), + (unsigned long)instance->generic.data, + (unsigned int)(instance->generic.data_2 & 0xFFFF), + (unsigned int)instance->validation_field); + + uint8_t buffer[48] = {0}; + psa_setup_byte_buffer( + buffer, instance->generic.data, instance->generic.data_2); + if(psa_direct_xor_decrypt(instance, buffer)) { + instance->mode_serialize = 0x23; + instance->decrypted = 0x50; + FURI_LOG_I( + TAG, + "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->generic.btn, + (unsigned long)instance->generic.serial, + (unsigned long)instance->generic.cnt); + } else { + instance->decrypted = 0x00; + instance->mode_serialize = 0x36; + FURI_LOG_I( + TAG, + "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); + } + + if(instance->base.callback) { + instance->base.callback(&instance->base, instance->base.context); + } + instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; @@ -1197,10 +1297,10 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } } } - + uint8_t manchester_input = 0; bool should_process = false; - + if(duration < te_short) { tolerance = te_short - duration; if(tolerance >= PSA_TOLERANCE_100) { @@ -1216,7 +1316,7 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } else if(duration < te_long) { uint32_t diff_from_250 = duration - te_short; uint32_t diff_from_500 = te_long - duration; - + if(diff_from_500 < 150 || diff_from_250 > diff_from_500) { if(level == 0) { manchester_input = 6; @@ -1266,32 +1366,34 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } } } - + if(should_process && instance->decode_count_bit < PSA_KEY2_BITS) { bool decoded_bit = false; - - if(manchester_advance(instance->manchester_state, - (ManchesterEvent)manchester_input, - &instance->manchester_state, - &decoded_bit)) { + + if(manchester_advance( + instance->manchester_state, + (ManchesterEvent)manchester_input, + &instance->manchester_state, + &decoded_bit)) { uint32_t carry = (instance->decode_data_low >> 31) & 1; - instance->decode_data_low = (instance->decode_data_low << 1) | (decoded_bit ? 1 : 0); + instance->decode_data_low = (instance->decode_data_low << 1) | + (decoded_bit ? 1 : 0); instance->decode_data_high = (instance->decode_data_high << 1) | carry; instance->decode_count_bit++; - + if(instance->decode_count_bit == PSA_KEY1_BITS) { - instance->key1_low = instance->decode_data_low; - instance->key1_high = instance->decode_data_high; + instance->generic.data = ((uint64_t)instance->decode_data_high << 32) | + instance->decode_data_low; instance->decode_data_low = 0; instance->decode_data_high = 0; } } } - + if(!level) { return; } - + if(!should_process) { uint32_t end_diff; if(duration < PSA_TE_END_1000) { @@ -1303,44 +1405,54 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati if(instance->decode_count_bit != PSA_KEY2_BITS) { return; } - - if(((instance->key1_high >> 16) & 0xF) == 0xA) { + + if(((instance->generic.data >> 48) & 0xF) == 0xA) { uint32_t new_key2_low = instance->decode_data_low; instance->validation_field = (uint16_t)(instance->decode_data_low & 0xFFFF); - + instance->decrypted_type = 0; - instance->decrypted_button = 0; - instance->decrypted_serial = 0; - instance->decrypted_counter = 0; + instance->generic.btn = 0; + instance->generic.serial = 0; + instance->generic.cnt = 0; instance->decrypted_crc = 0; - instance->decrypted_seed = 0; instance->decrypted = 0x00; - - instance->key2_low = new_key2_low; - instance->key2_high = instance->decode_data_high; + + instance->generic.data_2 = ((uint64_t)instance->decode_data_high << 32) | + new_key2_low; instance->status_flag = 0x80; - - FURI_LOG_I(TAG, "Signal decoded (alt path) - Key1:%08lX%08lX Key2:%04X ValField:%04X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - (unsigned int)(instance->key2_low & 0xFFFF), (unsigned int)instance->validation_field); - + + FURI_LOG_I( + TAG, + "Signal decoded (alt path) - Key1:%08lX%08lX Key2:%04X ValField:%04X", + (unsigned long)(instance->generic.data >> 32), + (unsigned long)instance->generic.data, + (unsigned int)(instance->generic.data_2 & 0xFFFF), + (unsigned int)instance->validation_field); + uint8_t buffer[48] = {0}; - psa_setup_byte_buffer(buffer, instance->key1_low, instance->key1_high, instance->key2_low); + psa_setup_byte_buffer( + buffer, instance->generic.data, instance->generic.data_2); if(psa_direct_xor_decrypt(instance, buffer)) { instance->mode_serialize = 0x23; instance->decrypted = 0x50; - FURI_LOG_I(TAG, "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); + FURI_LOG_I( + TAG, + "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->generic.btn, + (unsigned long)instance->generic.serial, + (unsigned long)instance->generic.cnt); } else { instance->decrypted = 0x00; - FURI_LOG_I(TAG, "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); + FURI_LOG_I( + TAG, + "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); instance->mode_serialize = 0x36; } - + if(instance->base.callback) { instance->base.callback(&instance->base, instance->base.context); } - + instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; @@ -1353,19 +1465,24 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } } break; - + case PSADecoderState3: if(duration >= 250) { if(duration >= PSA_TE_LONG_250 && duration < 0x12c) { if(instance->pattern_counter > PSA_PATTERN_THRESHOLD_2) { - FURI_LOG_I(TAG, "[State3->State4] Transition detected with pattern_cnt=%lu", - (unsigned long)instance->pattern_counter); + FURI_LOG_I( + TAG, + "[State3->State4] Transition detected with pattern_cnt=%lu", + (unsigned long)instance->pattern_counter); new_state = PSADecoderState4; instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; - manchester_advance(instance->manchester_state, ManchesterEventReset, - &instance->manchester_state, NULL); + manchester_advance( + instance->manchester_state, + ManchesterEventReset, + &instance->manchester_state, + NULL); instance->state = new_state; instance->pattern_counter = 0; instance->prev_duration = duration; @@ -1376,13 +1493,13 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->pattern_counter = 0; break; } - + if(duration < PSA_TE_SHORT_125) { tolerance = PSA_TE_SHORT_125 - duration; } else { tolerance = duration - PSA_TE_SHORT_125; } - + if(tolerance < PSA_TOLERANCE_50) { uint32_t prev_diff = psa_abs_diff(prev_dur, PSA_TE_SHORT_125); if(prev_diff <= PSA_TOLERANCE_49) { @@ -1393,21 +1510,21 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->prev_duration = duration; return; } - + new_state = PSADecoderState0; instance->pattern_counter = 0; break; - + case PSADecoderState4: if(instance->decode_count_bit >= PSA_MAX_BITS) { new_state = PSADecoderState0; break; } - + if(!level) { uint8_t manchester_input; bool decoded_bit = false; - + if(duration < PSA_TE_SHORT_125) { tolerance = PSA_TE_SHORT_125 - duration; if(tolerance > PSA_TOLERANCE_49) { @@ -1428,19 +1545,21 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati return; } } - - if(manchester_advance(instance->manchester_state, - (ManchesterEvent)manchester_input, - &instance->manchester_state, - &decoded_bit)) { + + if(manchester_advance( + instance->manchester_state, + (ManchesterEvent)manchester_input, + &instance->manchester_state, + &decoded_bit)) { uint32_t carry = (instance->decode_data_low >> 31) & 1; - instance->decode_data_low = (instance->decode_data_low << 1) | (decoded_bit ? 1 : 0); + instance->decode_data_low = (instance->decode_data_low << 1) | + (decoded_bit ? 1 : 0); instance->decode_data_high = (instance->decode_data_high << 1) | carry; instance->decode_count_bit++; - + if(instance->decode_count_bit == PSA_KEY1_BITS) { - instance->key1_low = instance->decode_data_low; - instance->key1_high = instance->decode_data_high; + instance->generic.data = ((uint64_t)instance->decode_data_high << 32) | + instance->decode_data_low; instance->decode_data_low = 0; instance->decode_data_high = 0; } @@ -1456,8 +1575,8 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati if(instance->decode_count_bit != PSA_KEY2_BITS) { return; } - - if(((instance->key1_high >> 16) & 0xF) != 0xA) { + + if(((instance->generic.data >> 48) & 0xF) != 0xA) { instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; @@ -1465,44 +1584,53 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati instance->state = new_state; return; } - + uint32_t new_key2_low = instance->decode_data_low; instance->validation_field = (uint16_t)(instance->decode_data_low & 0xFFFF); - + instance->decrypted_type = 0; - instance->decrypted_button = 0; - instance->decrypted_serial = 0; - instance->decrypted_counter = 0; + instance->generic.btn = 0; + instance->generic.serial = 0; + instance->generic.cnt = 0; instance->decrypted_crc = 0; - instance->decrypted_seed = 0; instance->decrypted = 0x00; - - instance->key2_low = new_key2_low; - instance->key2_high = instance->decode_data_high; + + instance->generic.data_2 = ((uint64_t)instance->decode_data_high << 32) | + new_key2_low; instance->mode_serialize = 2; instance->status_flag = 0x80; - - FURI_LOG_I(TAG, "Signal decoded (state4) - Key1:%08lX%08lX Key2:%04X ValField:%04X", - (unsigned long)instance->key1_high, (unsigned long)instance->key1_low, - (unsigned int)(instance->key2_low & 0xFFFF), (unsigned int)instance->validation_field); - + + FURI_LOG_I( + TAG, + "Signal decoded (state4) - Key1:%08lX%08lX Key2:%04X ValField:%04X", + (unsigned long)(instance->generic.data >> 32), + (unsigned long)instance->generic.data, + (unsigned int)(instance->generic.data_2 & 0xFFFF), + (unsigned int)instance->validation_field); + uint8_t buffer[48] = {0}; - psa_setup_byte_buffer(buffer, instance->key1_low, instance->key1_high, instance->key2_low); + psa_setup_byte_buffer(buffer, instance->generic.data, instance->generic.data_2); if(psa_direct_xor_decrypt(instance, buffer)) { instance->mode_serialize = 0x23; instance->decrypted = 0x50; - FURI_LOG_I(TAG, "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", - (unsigned int)instance->decrypted_button, (unsigned long)instance->decrypted_serial, (unsigned long)instance->decrypted_counter); + FURI_LOG_I( + TAG, + "Direct XOR decryption SUCCESS - Type:0x23 Btn:%02X Ser:%06lX Cnt:%08lX", + (unsigned int)instance->generic.btn, + (unsigned long)instance->generic.serial, + (unsigned long)instance->generic.cnt); } else { instance->decrypted = 0x00; instance->mode_serialize = 0x36; - FURI_LOG_I(TAG, "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); + FURI_LOG_I( + TAG, + "Direct XOR decryption FAILED - marked for brute force (Type:0x36) - deferred to get_string"); } - + if(instance->base.callback) { instance->base.callback(&instance->base, instance->base.context); } - + instance->decode_data_low = 0; instance->decode_data_high = 0; instance->decode_count_bit = 0; @@ -1515,7 +1643,7 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati } break; } - + instance->state = new_state; instance->prev_duration = duration; } @@ -1523,11 +1651,8 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati uint8_t subghz_protocol_decoder_psa_get_hash_data(void* context) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; - uint64_t combined_data = ((uint64_t)instance->key1_high << 32) | instance->key1_low; - SubGhzBlockDecoder decoder = { - .decode_data = combined_data, - .decode_count_bit = 64 - }; + uint64_t combined_data = instance->generic.data; + SubGhzBlockDecoder decoder = {.decode_data = combined_data, .decode_count_bit = 64}; return subghz_protocol_blocks_get_hash_data(&decoder, 16); } @@ -1537,77 +1662,78 @@ SubGhzProtocolStatus subghz_protocol_decoder_psa_serialize( SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; - + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) break; - + if(!flipper_format_write_string_cstr( flipper_format, "Preset", furi_string_get_cstr(preset->name))) break; - + if(!flipper_format_write_string_cstr( flipper_format, "Protocol", instance->base.protocol->name)) break; - + uint32_t bits = 128; if(!flipper_format_write_uint32(flipper_format, "Bit", &bits, 1)) break; - + char key1_str[20]; - uint64_t key1 = ((uint64_t)instance->key1_high << 32) | instance->key1_low; - snprintf(key1_str, sizeof(key1_str), "%016llX", key1); + snprintf( + key1_str, sizeof(key1_str), "%016llX", (unsigned long long)instance->generic.data); if(!flipper_format_write_string_cstr(flipper_format, "Key", key1_str)) break; - + char key2_str[20]; - uint64_t key2 = ((uint64_t)instance->key2_high << 32) | instance->key2_low; - snprintf(key2_str, sizeof(key2_str), "%016llX", key2); + snprintf( + key2_str, sizeof(key2_str), "%016llX", (unsigned long long)instance->generic.data_2); if(!flipper_format_write_string_cstr(flipper_format, "Key_2", key2_str)) break; - + uint32_t val_field = instance->validation_field; flipper_format_write_uint32(flipper_format, "ValidationField", &val_field, 1); - + if(instance->decrypted == 0x50 && instance->decrypted_type != 0) { - flipper_format_write_uint32(flipper_format, "Serial", &instance->decrypted_serial, 1); - - uint32_t btn_temp = instance->decrypted_button; + flipper_format_write_uint32(flipper_format, "Serial", &instance->generic.serial, 1); + + uint32_t btn_temp = instance->generic.btn; flipper_format_write_uint32(flipper_format, "Btn", &btn_temp, 1); - - flipper_format_write_uint32(flipper_format, "Cnt", &instance->decrypted_counter, 1); - + + flipper_format_write_uint32(flipper_format, "Cnt", &instance->generic.cnt, 1); + uint32_t crc_temp = instance->decrypted_crc; flipper_format_write_uint32(flipper_format, "CRC", &crc_temp, 1); - + uint32_t type_temp = instance->decrypted_type; flipper_format_write_uint32(flipper_format, "Type", &type_temp, 1); - - flipper_format_write_uint32(flipper_format, "Seed", &instance->decrypted_seed, 1); + + flipper_format_write_uint32(flipper_format, "Seed", &instance->generic.seed, 1); } - + ret = SubGhzProtocolStatusOk; } while(false); - + return ret; } -SubGhzProtocolStatus subghz_protocol_decoder_psa_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_psa_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; - + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; FuriString* temp_str = furi_string_alloc(); - + do { if(!flipper_format_read_string(flipper_format, "Key", temp_str)) { break; } - + const char* key1_str = furi_string_get_cstr(temp_str); uint64_t key1 = 0; size_t str_len = strlen(key1_str); for(size_t i = 0; i < str_len && i < 16; i++) { char c = key1_str[i]; if(c == ' ') continue; - + uint8_t nibble; if(c >= '0' && c <= '9') { nibble = c - '0'; @@ -1620,20 +1746,19 @@ SubGhzProtocolStatus subghz_protocol_decoder_psa_deserialize(void* context, Flip } key1 = (key1 << 4) | nibble; } - instance->key1_low = (uint32_t)(key1 & 0xFFFFFFFF); - instance->key1_high = (uint32_t)((key1 >> 32) & 0xFFFFFFFF); - + instance->generic.data = key1; + if(!flipper_format_read_string(flipper_format, "Key_2", temp_str)) { break; } - + const char* key2_str = furi_string_get_cstr(temp_str); uint64_t key2 = 0; str_len = strlen(key2_str); for(size_t i = 0; i < str_len && i < 16; i++) { char c = key2_str[i]; if(c == ' ') continue; - + uint8_t nibble; if(c >= '0' && c <= '9') { nibble = c - '0'; @@ -1646,16 +1771,15 @@ SubGhzProtocolStatus subghz_protocol_decoder_psa_deserialize(void* context, Flip } key2 = (key2 << 4) | nibble; } - instance->key2_low = (uint32_t)(key2 & 0xFFFFFFFF); - instance->key2_high = (uint32_t)((key2 >> 32) & 0xFFFFFFFF); - + instance->generic.data_2 = key2; + instance->status_flag = 0x80; - + psa_decrypt_router(instance); - + ret = SubGhzProtocolStatusOk; } while(false); - + furi_string_free(temp_str); return ret; } @@ -1663,19 +1787,21 @@ SubGhzProtocolStatus subghz_protocol_decoder_psa_deserialize(void* context, Flip void subghz_protocol_decoder_psa_get_string(void* context, FuriString* output) { furi_assert(context); SubGhzProtocolDecoderPSA* instance = context; - - if(instance->status_flag == 0x80 && - (instance->key1_low != 0 || instance->key1_high != 0) && + + if(instance->status_flag == 0x80 && (instance->generic.data != 0) && instance->decrypted_type == 0) { FURI_LOG_I(TAG, "get_string: Calling decryption router (decrypted_type=0)"); psa_decrypt_router(instance); } else { - FURI_LOG_D(TAG, "get_string: Skipping router - status_flag=0x%08lX decrypted_type=0x%02X", - (unsigned long)instance->status_flag, (unsigned int)instance->decrypted_type); + FURI_LOG_D( + TAG, + "get_string: Skipping router - status_flag=0x%08lX decrypted_type=0x%02X", + (unsigned long)instance->status_flag, + (unsigned int)instance->decrypted_type); } - - uint16_t key2_value = (uint16_t)(instance->key2_low & 0xFFFF); - + + uint16_t key2_value = (uint16_t)(instance->generic.data_2 & 0xFFFF); + if(instance->decrypted == 0x50 && instance->decrypted_type != 0) { if(instance->decrypted_type == 0x23) { furi_string_printf( @@ -1691,15 +1817,15 @@ void subghz_protocol_decoder_psa_get_string(void* context, FuriString* output) { "Sd:%06lX", instance->base.protocol->name, 128, - instance->key1_high, - instance->key1_low, + (unsigned long)(instance->generic.data >> 32), + (unsigned long)instance->generic.data, key2_value, - instance->decrypted_button, - instance->decrypted_serial, - (uint32_t)instance->decrypted_counter, + instance->generic.btn, + instance->generic.serial, + (uint32_t)instance->generic.cnt, instance->decrypted_crc, instance->decrypted_type, - instance->decrypted_seed); + instance->generic.seed); } else if(instance->decrypted_type == 0x36) { furi_string_printf( output, @@ -1714,15 +1840,15 @@ void subghz_protocol_decoder_psa_get_string(void* context, FuriString* output) { "Sd:%06lX", instance->base.protocol->name, 128, - instance->key1_high, - instance->key1_low, + (unsigned long)(instance->generic.data >> 32), + (unsigned long)instance->generic.data, key2_value, - instance->decrypted_button, - instance->decrypted_serial, - instance->decrypted_counter, + instance->generic.btn, + instance->generic.serial, + instance->generic.cnt, instance->decrypted_crc, instance->decrypted_type, - instance->decrypted_seed); + instance->generic.seed); } else { furi_string_printf( output, @@ -1731,8 +1857,8 @@ void subghz_protocol_decoder_psa_get_string(void* context, FuriString* output) { "Key2:%X", instance->base.protocol->name, 128, - instance->key1_high, - instance->key1_low, + (unsigned long)(instance->generic.data >> 32), + (unsigned long)instance->generic.data, key2_value); } } else { @@ -1743,8 +1869,8 @@ void subghz_protocol_decoder_psa_get_string(void* context, FuriString* output) { "Key2:%X", instance->base.protocol->name, 128, - instance->key1_high, - instance->key1_low, + (unsigned long)(instance->generic.data >> 32), + (unsigned long)instance->generic.data, key2_value); } }