diff --git a/CHANGELOG.md b/CHANGELOG.md index 376879fef..8814e0af8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,9 @@ - UL: Treadmill37 protocol support (37bit static) (by @xMasterX) - UL: New modulation FSK with 12KHz deviation (by @xMasterX) - UL: KingGates Stylo 4k Add manually and button switch support and refactoring of encoder (by @xMasterX) - - UL: Stilmatic button 9 support (two buttons hold simulation) (mapped on arrow keys) (by @xMasterX) + - UL: Stilmatic (R-Tech) 12bit discr. fix & button 9 support (two buttons hold simulation) (mapped on arrow keys) (by @xMasterX) - UL: Sommer last button code 0x6 support (mapped on arrow keys) (by @xMasterX) + - UL: V2 Phoenix (Phox) added 2 counter modes support (docs updated) (by @xMasterX) - UL: Add 390MHz and 430.5MHz to default hopper list (6 elements like in OFW) (works well with Hopper RSSI level set for your enviroment) (by @xMasterX) - UL: Docs: Add [full list of supported SubGHz protocols](https://github.com/Next-Flip/Momentum-Firmware/blob/dev/documentation/SubGHzSupportedSystems.md) and their frequencies/modulations that can be used for reading remotes (by @xMasterX) @@ -34,6 +35,9 @@ - UL: Sommer fm2 in Add manually now uses FM12K modulation (Sommer without fm2 tag uses FM476) (try this if regular option doesn't work for you) (by @xMasterX) - UL: Replaced Cars ignore option with Revers RB2 protocol ignore option (by @xMasterX) - UL: Improve docs on low level code (by @Dmitry422) + - UL: KeeLoq display decrypted `Hop` instead of showing encrypted as is (encrypted non byte reversed hop is still displayed in `Key` field) (by @xMasterX) + - UL: BFT KeeLoq try decoding with zero seed too (by @xMasterX) + - UL: KeeLoq display BFT programming mode TX (when arrow button is held) (by @xMasterX) - Archive: Support opening and pinning ProtoPirate files from Archive (#510 by @LeeroysHub) ### Fixed: diff --git a/applications/main/subghz/scenes/subghz_scene_signal_settings.c b/applications/main/subghz/scenes/subghz_scene_signal_settings.c index e74219a28..13c8234e2 100644 --- a/applications/main/subghz/scenes/subghz_scene_signal_settings.c +++ b/applications/main/subghz/scenes/subghz_scene_signal_settings.c @@ -47,6 +47,7 @@ static Protocols protocols[] = { {"CAME Atomo", 4}, {"Alutech AT-4N", 3}, {"KeeLoq", 7}, + {"Phoenix_V2", 3}, }; #define PROTOCOLS_COUNT (sizeof(protocols) / sizeof(Protocols)); diff --git a/documentation/SubGHzCounterMode.md b/documentation/SubGHzCounterMode.md index cac4dc0a0..43932ddfe 100644 --- a/documentation/SubGHzCounterMode.md +++ b/documentation/SubGHzCounterMode.md @@ -131,6 +131,24 @@ CounterMode: 1 --- +### 5. V2 Phoenix (Phox) + +**Mode 0 (Default):** +- Standard - acts like regular remote +- Uses rolling counter multiplier from global settings (default +1) +- Counter increments based on the multiplier value (default +1) +- Resets to 0 when overflow occurs (> 0xFFFF) + +**Mode 1 (ofex like):** +- Counter sequence: `0x0000 / 0x0001 / 0xFFFE / 0xFFFF` +- Verified as working + +**Mode 2 (0 - 4):** +- Counter sequence: `0x0000 / 0x0001 / 0x0002 / 0x0003 / 0x0004` +- Might work (let us know!) + +--- + ## Notes and Warnings ### Important Considerations: diff --git a/documentation/SubGHzSupportedSystems.md b/documentation/SubGHzSupportedSystems.md index 34fe625ef..f950cf150 100644 --- a/documentation/SubGHzSupportedSystems.md +++ b/documentation/SubGHzSupportedSystems.md @@ -24,7 +24,7 @@ That list is only for default SubGHz app, apps like *Weather Station* have their - AN-Motors (Alutech) AT4 `433.92MHz` `AM650` (64 bits, Pseudo-Dynamic, KeeLoq based) - Ansonic `433MHz` `FM` (12 bits, Static) - BETT `433.92MHz` `AM650` (18 bits, Static) -- Beninca ARC (TOGO2VA) `433.92MHz` `AM650` (128 bits, Dynamic AES) +- Beninca ARC (TOGO2VA) `433.92MHz` `AM650` (128 bits, Dynamic AES) (button code `0` emulates `hidden button` option on the remote) - BFT Mitto `433.92MHz` `AM650` (64 bits, Dynamic, KeeLoq based with Seed) - CAME Atomo `433.92MHz, 868MHz` `AM650` (62 bits, Dynamic) - CAME TWEE `433.92MHz` `AM650` (54 bits, Static) @@ -50,7 +50,7 @@ That list is only for default SubGHz app, apps like *Weather Station* have their - Nice One `433.92MHz` `AM650` (72 bits, Dynamic) - Revers RB2 (Реверс РБ-2 (М)) `433.92MHz` `AM650` (64 bits, Static) - Roger `433.92MHz` `AM650` (28 bits, Static) -- V2 Phoenix (Phox) `433.92MHz` `AM650` (52 bits, Dynamic) +- V2 Phoenix (Phox) `433.92MHz` `AM650` (52 bits, Dynamic) (receivers have option to enable Static mode, making them ignore rolling part of the key) - Marantec `433.92MHz, 868MHz` `AM650` (49 bits, Static) - Marantec24 `868MHz` `AM650` (24 bits, Static) - Somfy Keytis `433.92MHz, 868MHz` `AM650` (80 bits, Dynamic) @@ -102,7 +102,7 @@ The following manufacturers have KeeLoq support in Unleashed firmware: - Aprimatic - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial number art in Hop + 2bit "parity" in front of it replacing first 2 bits of serial) - Beninca - `433.92MHz, 868MHz` `AM650` (KeeLoq, 64 bits) (no serial part in Hop - magic XOR) - CAME Space - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - simple learning) -- Cardin S449 - `433.92MHz` `FSK12K` (KeeLoq, 64 bits) (12bit (original remotes) or 10bit (chinese remotes) serial part in Hop - normal learning) +- Cardin S449 - `433.92MHz` `FSK12K` (KeeLoq, 64 bits) (12bit (original remotes) or 10bit (chinese remotes) serial part in Hop - normal learning) (receiver checks for 10bit only (unverified)) - Centurion - `433.92MHz` `AM650` (KeeLoq, 64 bits) (no serial in Hop, uses fixed value 0x1CE - normal learning) - Comunello - `433.92MHz, 868MHz` `AM650` (KeeLoq, 64 bits) (normal learning) - DEA Mio - `433.92MHz` `AM650` (KeeLoq, 64 bits) (modified serial in Hop, uses last 3 digits modifying first one (example - 419 -> C19) - simple learning) @@ -128,7 +128,7 @@ The following manufacturers have KeeLoq support in Unleashed firmware: - Novoferm - `433.92MHz` `AM650` (KeeLoq, 64 bits) - Sommer `434.42MHz, 868.80MHz` `FSK12K (or FSK476)` (KeeLoq, 64 bits) (normal learning) (TX03-868-4, Pearl, and maybe other models are supported (SOMloq)) - Steelmate - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - normal learning) -- Stilmatic - `433.92MHz` `AM650` (KeeLoq, 64 bits) (normal learning) +- Stilmatic (R-Tech) - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - normal learning) (receiver checks for 10bit only (unverified)) ### Alarms, unknown origin, etc. - APS-1100/APS-2550 (KeeLoq, 64 bits) diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index c69e11433..712a7b0a8 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -97,7 +97,7 @@ const SubGhzProtocol subghz_protocol_keeloq = { * @param keystore Pointer to a SubGhzKeystore* instance * @param manufacture_name */ -static void subghz_protocol_keeloq_check_remote_controller( +static uint32_t subghz_protocol_keeloq_check_remote_controller( SubGhzBlockGeneric* instance, SubGhzKeystore* keystore, const char** manufacture_name); @@ -307,12 +307,14 @@ static bool subghz_protocol_keeloq_gen_data( (strcmp(instance->manufacture_name, "Rossi") == 0) || (strcmp(instance->manufacture_name, "Pecinin") == 0) || (strcmp(instance->manufacture_name, "Steelmate") == 0) || - (strcmp(instance->manufacture_name, "Cardin_S449") == 0)) { + (strcmp(instance->manufacture_name, "Cardin_S449") == 0) || + (strcmp(instance->manufacture_name, "Stilmatic") == 0)) { // DTM Neo, Came_Space uses 12bit serial -> simple learning // FAAC_RC,XT , Mutanco_Mutancode, Genius_Bravo, GSN 12bit serial -> normal learning // Rosh, Rossi, Pecinin -> 12bit serial - simple learning // Steelmate -> 12bit serial - normal learning // Cardin_S449 -> 12bit serial - normal learning + // Stilmatic (r-tech) -> 12bit serial - normal learning decrypt = btn << 28 | (instance->generic.serial & 0xFFF) << 16 | instance->generic.cnt; } else if( @@ -901,9 +903,9 @@ static inline bool subghz_protocol_keeloq_check_decrypt_centurion( * @param hop Hop encrypted part of the parcel * @param keystore Pointer to a SubGhzKeystore* instance * @param manufacture_name - * @return true on successful search - */ -static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( + * @return uint32_t decrypt data */ + +static uint32_t subghz_protocol_keeloq_check_remote_controller_selector( SubGhzBlockGeneric* instance, uint32_t fix, uint32_t hop, @@ -926,7 +928,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( const char* mfname = keystore->mfname; if(strcmp(mfname, "Unknown") == 0) { - return 1; + return 0; } else if(strcmp(mfname, "") == 0) { mf_not_set = true; } @@ -940,7 +942,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; - return 1; + return decrypt; } break; case KEELOQ_LEARNING_NORMAL: @@ -953,14 +955,14 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( if(subghz_protocol_keeloq_check_decrypt_centurion(instance, decrypt, btn)) { *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; - return 1; + return decrypt; } } else { if(subghz_protocol_keeloq_check_decrypt( instance, decrypt, btn, end_serial)) { *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; - return 1; + return decrypt; } } break; @@ -978,9 +980,19 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; - return 1; + return decrypt; } else { if(reset_seed_back) instance->seed = 0; + // Try with zero seed (some strange remotes have been reported to use 0 seed) + man = subghz_protocol_keeloq_common_secure_learning( + fix, instance->seed, manufacture_code->key); + decrypt = subghz_protocol_keeloq_common_decrypt(hop, man); + if(subghz_protocol_keeloq_check_decrypt( + instance, decrypt, btn, end_serial)) { + *manufacture_name = furi_string_get_cstr(manufacture_code->name); + keystore->mfname = *manufacture_name; + return decrypt; + } } break; case KEELOQ_LEARNING_MAGIC_XOR_TYPE_1: @@ -990,7 +1002,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; - return 1; + return decrypt; } break; case KEELOQ_LEARNING_MAGIC_SERIAL_TYPE_1: @@ -1000,7 +1012,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; - return 1; + return decrypt; } break; case KEELOQ_LEARNING_MAGIC_SERIAL_TYPE_2: @@ -1010,7 +1022,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; - return 1; + return decrypt; } break; case KEELOQ_LEARNING_MAGIC_SERIAL_TYPE_3: @@ -1020,7 +1032,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) { *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; - return 1; + return decrypt; } break; case KEELOQ_LEARNING_UNKNOWN: @@ -1030,7 +1042,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; keystore->kl_type = 1; - return 1; + return decrypt; } // Check for mirrored man @@ -1046,7 +1058,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; keystore->kl_type = 1; - return 1; + return decrypt; } //########################### @@ -1059,7 +1071,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; keystore->kl_type = 2; - return 1; + return decrypt; } // Check for mirrored man @@ -1069,7 +1081,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; keystore->kl_type = 2; - return 1; + return decrypt; } // Secure Learning @@ -1080,7 +1092,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; keystore->kl_type = 3; - return 1; + return decrypt; } // Check for mirrored man @@ -1091,7 +1103,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; keystore->kl_type = 3; - return 1; + return decrypt; } // Magic xor type1 learning @@ -1102,7 +1114,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; keystore->kl_type = 4; - return 1; + return decrypt; } // Check for mirrored man @@ -1112,7 +1124,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( *manufacture_name = furi_string_get_cstr(manufacture_code->name); keystore->mfname = *manufacture_name; keystore->kl_type = 4; - return 1; + return decrypt; } break; @@ -1128,7 +1140,7 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector( return 0; } -static void subghz_protocol_keeloq_check_remote_controller( +static uint32_t subghz_protocol_keeloq_check_remote_controller( SubGhzBlockGeneric* instance, SubGhzKeystore* keystore, const char** manufacture_name) { @@ -1137,6 +1149,7 @@ static void subghz_protocol_keeloq_check_remote_controller( uint32_t key_fix = key >> 32; uint32_t key_hop = key & 0x00000000ffffffff; static uint16_t temp_counter = 0; // Be careful with prog_mode + uint32_t resdecrypt = 0; // If we are in BFT / Aprimatic / Dea_Mio programming mode we will set previous remembered counter and skip mf keys check ProgMode prog_mode = subghz_custom_btn_get_prog_mode(); @@ -1161,7 +1174,7 @@ static void subghz_protocol_keeloq_check_remote_controller( keystore->mfname = *manufacture_name; instance->cnt = key_hop >> 16; } else { - subghz_protocol_keeloq_check_remote_controller_selector( + resdecrypt = subghz_protocol_keeloq_check_remote_controller_selector( instance, key_fix, key_hop, keystore, manufacture_name); } } else { @@ -1178,7 +1191,7 @@ static void subghz_protocol_keeloq_check_remote_controller( instance->cnt = key_hop >> 16; } else { // Else we have mfname that is not AN-Motors or HCS101 we should check it via default selector - subghz_protocol_keeloq_check_remote_controller_selector( + resdecrypt = subghz_protocol_keeloq_check_remote_controller_selector( instance, key_fix, key_hop, keystore, manufacture_name); } } @@ -1215,6 +1228,8 @@ static void subghz_protocol_keeloq_check_remote_controller( } // Set max custom buttons subghz_custom_btn_set_max(4); + + return resdecrypt; } uint32_t subghz_protocol_decoder_keeloq_get_hash_data(void* context) { @@ -1485,7 +1500,9 @@ void subghz_protocol_decoder_keeloq_get_string(void* context, FuriString* output furi_assert(context); SubGhzProtocolDecoderKeeloq* instance = context; - subghz_protocol_keeloq_check_remote_controller( + uint32_t hopdecrypt = 0; + + hopdecrypt = subghz_protocol_keeloq_check_remote_controller( &instance->generic, instance->keystore, &instance->manufacture_name); uint32_t code_found_hi = instance->generic.data >> 32; @@ -1500,23 +1517,44 @@ void subghz_protocol_decoder_keeloq_get_string(void* context, FuriString* output subghz_block_generic_global.cnt_is_available = true; subghz_block_generic_global.cnt_length_bit = 16; subghz_block_generic_global.current_cnt = instance->generic.cnt; - furi_string_cat_printf( - output, - "%s %dbit\r\n" - "Key:%08lX%08lX\r\n" - "Fix:0x%08lX Cnt:%04lX\r\n" - "Hop:0x%08lX Btn:%01X\r\n" - "MF:%s Sd:%08lX", - instance->generic.protocol_name, - instance->generic.data_count_bit, - code_found_hi, - code_found_lo, - code_found_reverse_hi, - instance->generic.cnt, - code_found_reverse_lo, - instance->generic.btn, - instance->manufacture_name, - instance->generic.seed); + ProgMode prog_mode = subghz_custom_btn_get_prog_mode(); + if(prog_mode == PROG_MODE_KEELOQ_BFT) { + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:%08lX%08lX\r\n" + "Fix:0x%08lX Cnt:%04lX\r\n" + "Hop:0x%08lX Btn:%01X\r\n" + "MF:%s PRG Sd:%08lX", + instance->generic.protocol_name, + instance->generic.data_count_bit, + code_found_hi, + code_found_lo, + code_found_reverse_hi, + instance->generic.cnt, + code_found_reverse_lo, + instance->generic.btn, + instance->manufacture_name, + instance->generic.seed); + } else { + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:%08lX%08lX\r\n" + "Fix:0x%08lX Cnt:%04lX\r\n" + "Hop:0x%08lX Btn:%01X\r\n" + "MF:%s Sd:%08lX", + instance->generic.protocol_name, + instance->generic.data_count_bit, + code_found_hi, + code_found_lo, + code_found_reverse_hi, + instance->generic.cnt, + hopdecrypt, + instance->generic.btn, + instance->manufacture_name, + instance->generic.seed); + } } else if(strcmp(instance->manufacture_name, "Unknown") == 0) { instance->generic.cnt = 0x0; furi_string_cat_printf( @@ -1551,7 +1589,7 @@ void subghz_protocol_decoder_keeloq_get_string(void* context, FuriString* output code_found_lo, code_found_reverse_hi, instance->generic.cnt, - code_found_reverse_lo, + hopdecrypt, instance->generic.btn, instance->manufacture_name); } diff --git a/lib/subghz/protocols/phoenix_v2.c b/lib/subghz/protocols/phoenix_v2.c index 5fb2e4bfd..8e9a4a8f9 100644 --- a/lib/subghz/protocols/phoenix_v2.c +++ b/lib/subghz/protocols/phoenix_v2.c @@ -93,6 +93,8 @@ void subghz_protocol_encoder_phoenix_v2_free(void* context) { free(instance); } +static uint8_t v2_phoenix_counter_mode = 0; + // Pre define functions static uint16_t subghz_protocol_phoenix_v2_encrypt_counter(uint64_t full_key, uint16_t counter); static void subghz_protocol_phoenix_v2_check_remote_controller(SubGhzBlockGeneric* instance); @@ -254,18 +256,30 @@ static bool btn = subghz_protocol_phoenix_v2_get_btn_code(); // Reconstruction of the data - // Check for OFEX (overflow experimental) mode - if(furi_hal_subghz_get_rolling_counter_mult() != -0x7FFFFFFF) { - // standart counter mode. PULL data from subghz_block_generic_global variables - if(!subghz_block_generic_global_counter_override_get(&instance->generic.cnt)) { - // if counter_override_get return FALSE then counter was not changed and we increase counter by standart mult value - if((instance->generic.cnt + furi_hal_subghz_get_rolling_counter_mult()) > 0xFFFF) { + if(v2_phoenix_counter_mode == 0) { + // Check for OFEX (overflow experimental) mode + if(furi_hal_subghz_get_rolling_counter_mult() != -0x7FFFFFFF) { + // standart counter mode. PULL data from subghz_block_generic_global variables + if(!subghz_block_generic_global_counter_override_get(&instance->generic.cnt)) { + // if counter_override_get return FALSE then counter was not changed and we increase counter by standart mult value + if((instance->generic.cnt + furi_hal_subghz_get_rolling_counter_mult()) > 0xFFFF) { + instance->generic.cnt = 0; + } else { + instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult(); + } + } + } else { + if((instance->generic.cnt + 0x1) > 0xFFFF) { instance->generic.cnt = 0; + } else if(instance->generic.cnt >= 0x1 && instance->generic.cnt != 0xFFFE) { + instance->generic.cnt = 0xFFFE; } else { - instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult(); + instance->generic.cnt++; } } - } else { + } else if(v2_phoenix_counter_mode == 1) { + // Mode 1 (ofex like) + // 0000 / 0001 / FFFE / FFFF if((instance->generic.cnt + 0x1) > 0xFFFF) { instance->generic.cnt = 0; } else if(instance->generic.cnt >= 0x1 && instance->generic.cnt != 0xFFFE) { @@ -273,6 +287,14 @@ static bool } else { instance->generic.cnt++; } + } else { + // Mode 2 (0 to 4) + // 0x0000 / 0x0001 / 0x0002 / 0x0003 / 0x0004 + if(instance->generic.cnt >= 0x0004) { + instance->generic.cnt = 0; + } else { + instance->generic.cnt++; + } } uint64_t local_data_rev = subghz_protocol_blocks_reverse_key( @@ -328,6 +350,18 @@ SubGhzProtocolStatus flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + + uint32_t tmp_counter_mode; + if(flipper_format_read_uint32(flipper_format, "CounterMode", &tmp_counter_mode, 1)) { + v2_phoenix_counter_mode = (uint8_t)tmp_counter_mode; + } else { + v2_phoenix_counter_mode = 0; + } + subghz_protocol_phoenix_v2_check_remote_controller(&instance->generic); if(!subghz_protocol_encoder_phoenix_v2_get_upload(instance)) { @@ -335,6 +369,11 @@ SubGhzProtocolStatus break; } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF; @@ -584,10 +623,25 @@ SubGhzProtocolStatus subghz_protocol_decoder_phoenix_v2_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderPhoenix_V2* instance = context; - return subghz_block_generic_deserialize_check_count_bit( + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + + ret = subghz_block_generic_deserialize_check_count_bit( &instance->generic, flipper_format, subghz_protocol_phoenix_v2_const.min_count_bit_for_found); + + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + return SubGhzProtocolStatusError; + } + + uint32_t tmp_counter_mode; + if(flipper_format_read_uint32(flipper_format, "CounterMode", &tmp_counter_mode, 1)) { + v2_phoenix_counter_mode = (uint8_t)tmp_counter_mode; + } else { + v2_phoenix_counter_mode = 0; + } + return ret; } void subghz_protocol_decoder_phoenix_v2_get_string(void* context, FuriString* output) {