mirror of
https://github.com/D4C1-Labs/Flipper-ARF.git
synced 2026-09-17 04:24:23 +00:00
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user