From 778a7aea832efd7edee149ed5432d72d583ded5b Mon Sep 17 00:00:00 2001 From: d4rks1d33 Date: Wed, 9 Sep 2026 00:27:12 +0000 Subject: [PATCH] fix bugs --- lib/subghz/protocols/chrysler.c | 7 ++- lib/subghz/protocols/fiat_v1.c | 71 ++++++++++++++++++++++------ lib/subghz/protocols/ford_v0.c | 5 +- lib/subghz/protocols/ford_v1.c | 3 +- lib/subghz/protocols/ford_v2.c | 6 ++- lib/subghz/protocols/honda_static.c | 7 ++- lib/subghz/protocols/land_rover_v0.c | 6 ++- lib/subghz/protocols/mazda_v0.c | 3 +- 8 files changed, 80 insertions(+), 28 deletions(-) diff --git a/lib/subghz/protocols/chrysler.c b/lib/subghz/protocols/chrysler.c index eca20b56..2d4745b9 100644 --- a/lib/subghz/protocols/chrysler.c +++ b/lib/subghz/protocols/chrysler.c @@ -501,11 +501,10 @@ SubGhzProtocolStatus tx_button = 0x1U; break; case SUBGHZ_CUSTOM_BTN_OK: - /* OK → original; if original is not 1/2 fall back to Unlock */ - tx_button = (original_button == 1U || original_button == 2U) ? original_button : 0x2U; - break; default: - /* DOWN/LEFT/RIGHT: unsupported by Chrysler, keep tx_button */ + // [BUGFIX] OK is the default state after loading a .sub. Replay + // the original captured button rather than force a specific one. + tx_button = original_button; break; } } diff --git a/lib/subghz/protocols/fiat_v1.c b/lib/subghz/protocols/fiat_v1.c index 15fe65e7..538884ae 100644 --- a/lib/subghz/protocols/fiat_v1.c +++ b/lib/subghz/protocols/fiat_v1.c @@ -686,10 +686,12 @@ SubGhzProtocolStatus // [PROTOPIRATE_PORT] custom_btn support // Fiat V1 mapping (4-bit codes, may be outside the {1,2,4,8} valid set): - // Up → 0x8 (Unlock) - // OK → 0x0 - // Down → 0xD - // The 4-bit button code is fed directly into hitag2 authenticator below. + // OK (default) → replay original captured button (do NOT rewrite to 0x0 + // or the hitag2 authenticator will produce a different + // hop and the receiver will reject the frame) + // Up → 0x8 (Unlock) + // Down → 0xD (special code) + // Left/Right → unsupported, keep original { const uint8_t original_btn = (uint8_t)(button & 0x0FU); if(subghz_custom_btn_get_original() == 0) { @@ -705,16 +707,11 @@ SubGhzProtocolStatus button = 0xDU; break; case SUBGHZ_CUSTOM_BTN_OK: - /* OK: use historic 0x0 code if we came from a valid original; - * otherwise keep the original to preserve default TX. */ - if(fiat_v1_button_valid(original_btn)) { - button = 0x0U; - } else { - button = original_btn; - } - break; default: - /* LEFT/RIGHT unsupported by Fiat V1 → keep original */ + // [BUGFIX] OK is the default state after loading a .sub; the old + // code overwrote the button with 0x0 unconditionally, which broke + // the hitag2 authenticator (receiver rejected the frame). Replay + // the captured button instead. button = original_btn; break; } @@ -726,10 +723,16 @@ SubGhzProtocolStatus return SubGhzProtocolStatusErrorParserOthers; } + // [BUGFIX] Hitag2 Key is now OPTIONAL: if not present in the .sub (which + // happens when the capture was serialized before hitag2_key_valid was set, + // or when the file was hand-edited), try to auto-discover the key by + // iterating the 8 known keys against the captured (uid, btn, cnt, hop). + // This mirrors what fiat_v1_verify_hitag2_key() does at RX time. + bool key_loaded = false; flipper_format_rewind(flipper_format); - if(!flipper_format_read_hex( + if(flipper_format_read_hex( flipper_format, FIAT_V1_HITAG2_KEY_FIELD, instance->hitag2_key, 6U)) { - return SubGhzProtocolStatusErrorParserOthers; + key_loaded = true; } uint32_t epoch = 0U; @@ -740,6 +743,44 @@ SubGhzProtocolStatus instance->epoch = 0U; } + if(!key_loaded) { + // Reconstruct captured hop+btn from the Raw field (or from generic if Raw missing) + uint32_t captured_hop = 0U; + uint8_t captured_btn = 0U; + uint16_t captured_cnt = (uint16_t)(control & 0x03FFU); + if(fiat_v1_frame_valid(raw_from_file)) { + captured_hop = fiat_v1_hop(raw_from_file); + captured_btn = raw_from_file[6] >> 4U; + } else { + // Fallback: derive from generic.data (upper 32 bits = serial, lower = hop) + captured_hop = (uint32_t)(instance->generic.data & 0xFFFFFFFFULL); + captured_btn = (uint8_t)(button & 0x0FU); + } + + bool found = false; + for(uint8_t i = 0U; i < FIAT_V1_KNOWN_KEY_COUNT; i++) { + if(fiat_v1_key_matches( + serial, + captured_btn, + captured_cnt, + captured_hop, + fiat_v1_known_keys[i], + instance->epoch)) { + memcpy(instance->hitag2_key, fiat_v1_known_keys[i], 6U); + found = true; + FURI_LOG_I(TAG, "TX: auto-discovered known key %u", i); + break; + } + } + if(!found) { + FURI_LOG_E( + TAG, + "TX: no Hitag2 Key in .sub and no known key matches (uid=%08lX)", + (unsigned long)serial); + return SubGhzProtocolStatusErrorParserOthers; + } + } + control &= 0x03FFU; button &= 0x0FU; instance->generic.serial = serial; diff --git a/lib/subghz/protocols/ford_v0.c b/lib/subghz/protocols/ford_v0.c index a74991d8..1287cc41 100644 --- a/lib/subghz/protocols/ford_v0.c +++ b/lib/subghz/protocols/ford_v0.c @@ -544,7 +544,10 @@ SubGhzProtocolStatus uint8_t custom_btn_id = subghz_custom_btn_get(); switch(custom_btn_id) { case SUBGHZ_CUSTOM_BTN_UP: btn = 0x02U; break; - case SUBGHZ_CUSTOM_BTN_OK: btn = 0x04U; break; + // [BUGFIX] OK is the default state after loading a .sub; do not + // rewrite the button unconditionally or the receiver will get a + // different button code than the one captured. + case SUBGHZ_CUSTOM_BTN_OK: btn = original_btn; break; case SUBGHZ_CUSTOM_BTN_DOWN: btn = 0x08U; break; case SUBGHZ_CUSTOM_BTN_LEFT: btn = 0x01U; break; case SUBGHZ_CUSTOM_BTN_RIGHT: btn = 0x10U; break; diff --git a/lib/subghz/protocols/ford_v1.c b/lib/subghz/protocols/ford_v1.c index e702df38..59a87ffc 100644 --- a/lib/subghz/protocols/ford_v1.c +++ b/lib/subghz/protocols/ford_v1.c @@ -1224,7 +1224,8 @@ SubGhzProtocolStatus uint8_t custom_btn_id = subghz_custom_btn_get(); switch(custom_btn_id) { case SUBGHZ_CUSTOM_BTN_UP: btn = 0x02U; break; - case SUBGHZ_CUSTOM_BTN_OK: btn = 0x04U; break; + // [BUGFIX] OK = default post-load; replay captured button. + case SUBGHZ_CUSTOM_BTN_OK: btn = original_btn; break; case SUBGHZ_CUSTOM_BTN_DOWN: btn = 0x08U; break; case SUBGHZ_CUSTOM_BTN_LEFT: btn = 0x01U; break; default: btn = original_btn; break; diff --git a/lib/subghz/protocols/ford_v2.c b/lib/subghz/protocols/ford_v2.c index a44f9f84..fdcac73f 100644 --- a/lib/subghz/protocols/ford_v2.c +++ b/lib/subghz/protocols/ford_v2.c @@ -483,11 +483,13 @@ static SubGhzProtocolStatus uint8_t new_btn = original_btn; switch(custom_btn_id) { case SUBGHZ_CUSTOM_BTN_UP: new_btn = 0x11U; break; - case SUBGHZ_CUSTOM_BTN_OK: new_btn = 0x10U; break; + // [BUGFIX] OK = default post-load; replay captured button (do not + // overwrite to 0x10 unconditionally). + case SUBGHZ_CUSTOM_BTN_OK: new_btn = original_btn; break; case SUBGHZ_CUSTOM_BTN_DOWN: new_btn = 0x13U; break; case SUBGHZ_CUSTOM_BTN_LEFT: new_btn = 0x14U; break; case SUBGHZ_CUSTOM_BTN_RIGHT: new_btn = 0x15U; break; - default: break; + default: new_btn = original_btn; break; } if(new_btn != original_btn) { instance->raw_bytes[6] = new_btn; diff --git a/lib/subghz/protocols/honda_static.c b/lib/subghz/protocols/honda_static.c index c2a264f1..c5aad700 100644 --- a/lib/subghz/protocols/honda_static.c +++ b/lib/subghz/protocols/honda_static.c @@ -527,11 +527,14 @@ SubGhzProtocolStatus uint8_t new_btn = original_btn; switch(custom_btn_id) { case SUBGHZ_CUSTOM_BTN_UP: new_btn = 0x1U; break; - case SUBGHZ_CUSTOM_BTN_OK: new_btn = 0x2U; break; + // [BUGFIX] OK is the default state after loading a .sub. The old + // code overwrote new_btn with 0x2 unconditionally, which produced a + // TX with a different button than the captured one. Replay original. + case SUBGHZ_CUSTOM_BTN_OK: new_btn = original_btn; break; case SUBGHZ_CUSTOM_BTN_DOWN: new_btn = 0x4U; break; case SUBGHZ_CUSTOM_BTN_LEFT: new_btn = 0x8U; break; case SUBGHZ_CUSTOM_BTN_RIGHT: new_btn = 0x5U; break; - default: break; + default: new_btn = original_btn; break; } if(honda_static_is_valid_button(new_btn)) { instance->decoded.button = new_btn; diff --git a/lib/subghz/protocols/land_rover_v0.c b/lib/subghz/protocols/land_rover_v0.c index 12ddfb0f..705c0b69 100644 --- a/lib/subghz/protocols/land_rover_v0.c +++ b/lib/subghz/protocols/land_rover_v0.c @@ -924,8 +924,10 @@ SubGhzProtocolStatus subghz_protocol_encoder_land_rover_v0_deserialize( uint8_t new_btn = original_btn; switch(custom_btn_id) { case SUBGHZ_CUSTOM_BTN_UP: new_btn = LAND_ROVER_V0_BTN_LOCK; break; - case SUBGHZ_CUSTOM_BTN_OK: new_btn = LAND_ROVER_V0_BTN_UNLOCK; break; - default: break; + // [BUGFIX] OK = default post-load; replay captured button (do + // not overwrite to UNLOCK unconditionally). + case SUBGHZ_CUSTOM_BTN_OK: new_btn = original_btn; break; + default: new_btn = original_btn; break; } if(new_btn != original_btn && new_btn != 0U) { instance->button = new_btn; diff --git a/lib/subghz/protocols/mazda_v0.c b/lib/subghz/protocols/mazda_v0.c index 6ade2702..9598792a 100644 --- a/lib/subghz/protocols/mazda_v0.c +++ b/lib/subghz/protocols/mazda_v0.c @@ -457,7 +457,8 @@ SubGhzProtocolStatus uint8_t custom_btn_id = subghz_custom_btn_get(); switch(custom_btn_id) { case SUBGHZ_CUSTOM_BTN_UP: instance->generic.btn = 0x1U; break; - case SUBGHZ_CUSTOM_BTN_OK: instance->generic.btn = 0x2U; break; + // [BUGFIX] OK = default post-load; replay captured button. + case SUBGHZ_CUSTOM_BTN_OK: instance->generic.btn = original_btn; break; case SUBGHZ_CUSTOM_BTN_DOWN: instance->generic.btn = 0x4U; break; case SUBGHZ_CUSTOM_BTN_RIGHT: instance->generic.btn = 0x8U; break; default: instance->generic.btn = original_btn; break;