Actually working progmode, new add manually options + bonus fixes

This commit is contained in:
MX 2023-09-05 05:31:03 +03:00
parent 2a789ae1c1
commit 0eb06ba2b7
No known key found for this signature in database
GPG Key ID: 7CCC66B7DBDD1C83
13 changed files with 208 additions and 89 deletions

View File

@ -6,6 +6,8 @@ typedef enum {
SubGhzCustomEventManagerSetRAW,
//SubmenuIndex
SubmenuIndexFaacSLH_Manual_433,
SubmenuIndexFaacSLH_Manual_868,
SubmenuIndexFaacSLH_433,
SubmenuIndexFaacSLH_868,
SubmenuIndexBFTClone,

View File

@ -665,6 +665,8 @@ void subghz_txrx_reset_dynamic_and_custom_btns(SubGhzTxRx* instance) {
furi_assert(instance);
subghz_environment_reset_keeloq(instance->environment);
faac_slh_reset_prog_mode();
subghz_custom_btns_reset();
}

View File

@ -132,7 +132,12 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
furi_string_set(subghz->file_path, subghz->file_path_tmp);
}
}
scene_manager_previous_scene(subghz->scene_manager);
if(scene_manager_has_previous_scene(subghz->scene_manager, SubGhzSceneSetSeed)) {
scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneSetType);
} else {
scene_manager_previous_scene(subghz->scene_manager);
}
return true;
} else if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventSceneSaveName) {

View File

@ -18,7 +18,7 @@ void subghz_scene_set_cnt_on_enter(void* context) {
switch(state) {
case SubmenuIndexBFTClone:
byte_input_set_header_text(byte_input, "Enter COUNTER in hex");
byte_input_set_header_text(byte_input, "Enter COUNTER in Hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_cnt_byte_input_callback,
@ -27,9 +27,9 @@ void subghz_scene_set_cnt_on_enter(void* context) {
subghz->secure_data->cnt,
2);
break;
case SubmenuIndexFaacSLH_433:
case SubmenuIndexFaacSLH_868:
byte_input_set_header_text(byte_input, "Enter COUNTER in hex [20 bits]");
case SubmenuIndexFaacSLH_Manual_433:
case SubmenuIndexFaacSLH_Manual_868:
byte_input_set_header_text(byte_input, "Enter COUNTER in Hex 20 bits");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_cnt_byte_input_callback,

View File

@ -13,7 +13,7 @@ void subghz_scene_set_fix_on_enter(void* context) {
// Setup view
ByteInput* byte_input = subghz->byte_input;
byte_input_set_header_text(byte_input, "Enter FIX in hex");
byte_input_set_header_text(byte_input, "Enter FIX in Hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_fix_byte_input_callback,

View File

@ -14,7 +14,7 @@ void subghz_scene_set_seed_on_enter(void* context) {
// Setup view
ByteInput* byte_input = subghz->byte_input;
byte_input_set_header_text(byte_input, "Enter SEED in hex");
byte_input_set_header_text(byte_input, "Enter SEED in Hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_seed_byte_input_callback,
@ -62,8 +62,8 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) {
}
consumed = true;
break;
case SubmenuIndexFaacSLH_433:
case SubmenuIndexFaacSLH_868:
case SubmenuIndexFaacSLH_Manual_433:
case SubmenuIndexFaacSLH_Manual_868:
fix_part = subghz->secure_data->fix[0] << 24 | subghz->secure_data->fix[1] << 16 |
subghz->secure_data->fix[2] << 8 | subghz->secure_data->fix[3];
@ -73,7 +73,7 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) {
seed = subghz->secure_data->seed[0] << 24 | subghz->secure_data->seed[1] << 16 |
subghz->secure_data->seed[2] << 8 | subghz->secure_data->seed[3];
if(state == SubmenuIndexFaacSLH_433) {
if(state == SubmenuIndexFaacSLH_Manual_433) {
generated_protocol = subghz_txrx_gen_faac_slh_protocol(
subghz->txrx,
"AM650",
@ -83,7 +83,7 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) {
(cnt & 0xFFFFF),
seed,
"FAAC_SLH");
} else if(state == SubmenuIndexFaacSLH_868) {
} else if(state == SubmenuIndexFaacSLH_Manual_868) {
generated_protocol = subghz_txrx_gen_faac_slh_protocol(
subghz->txrx,
"AM650",

View File

@ -13,6 +13,24 @@ void subghz_scene_set_type_submenu_callback(void* context, uint32_t index) {
void subghz_scene_set_type_on_enter(void* context) {
SubGhz* subghz = context;
submenu_add_item(
subghz->submenu,
"Faac SLH [Man.] 868MHz",
SubmenuIndexFaacSLH_Manual_868,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Faac SLH [Man.] 433MHz",
SubmenuIndexFaacSLH_Manual_433,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"BFT [Manual] 433MHz",
SubmenuIndexBFTClone,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Faac SLH 868MHz",
@ -25,12 +43,6 @@ void subghz_scene_set_type_on_enter(void* context) {
SubmenuIndexFaacSLH_433,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"BFT [Manual] 433MHz",
SubmenuIndexBFTClone,
subghz_scene_set_type_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"BFT Mitto 433MHz",
@ -319,10 +331,10 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
uint32_t key = (uint32_t)rand();
switch(event.event) {
case SubmenuIndexFaacSLH_868:
case SubmenuIndexFaacSLH_Manual_868:
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFix);
break;
case SubmenuIndexFaacSLH_433:
case SubmenuIndexFaacSLH_Manual_433:
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFix);
break;
case SubmenuIndexBFTClone:
@ -390,6 +402,38 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
generated_protocol = subghz_txrx_gen_data_protocol(
subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_GATE_TX_NAME, rev_key, 24);
break;
case SubmenuIndexFaacSLH_433:
generated_protocol = subghz_txrx_gen_faac_slh_protocol(
subghz->txrx,
"AM650",
433920000,
((key & 0x00FFFFF0) | 0xA0000006) >> 4,
0x6,
0x00002,
key,
"FAAC_SLH");
if(!generated_protocol) {
furi_string_set(
subghz->error_str, "Function requires\nan SD card with\nfresh databases.");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
}
break;
case SubmenuIndexFaacSLH_868:
generated_protocol = subghz_txrx_gen_faac_slh_protocol(
subghz->txrx,
"AM650",
868350000,
((key & 0x00FFFFF0) | 0xA0000006) >> 4,
0x6,
0x00002,
key,
"FAAC_SLH");
if(!generated_protocol) {
furi_string_set(
subghz->error_str, "Function requires\nan SD card with\nfresh databases.");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
}
break;
case SubmenuIndexBeninca433:
generated_protocol = subghz_txrx_gen_keeloq_protocol(
subghz->txrx,

View File

@ -20,7 +20,6 @@ bool subghz_scene_transmitter_update_data_show(void* context) {
FuriString* frequency_str = furi_string_alloc();
FuriString* modulation_str = furi_string_alloc();
if(subghz_protocol_decoder_base_deserialize(
decoder, subghz_txrx_get_fff_data(subghz->txrx)) == SubGhzProtocolStatusOk) {
subghz_protocol_decoder_base_get_string(decoder, key_str);
@ -83,6 +82,10 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
// Calling restore!
subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx));
subghz_txrx_stop(subghz->txrx);
// Calling restore 2nd time special for FAAC SLH!
// TODO: Find better way to restore after custom button is used!!!
subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx));
subghz_txrx_stop(subghz->txrx);
furi_hal_subghz_set_rolling_counter_mult(tmp_counter);
}
return true;

View File

@ -48,4 +48,4 @@ void subghz_custom_btn_set_prog_mode(ProgMode prog_mode) {
ProgMode subghz_custom_btn_get_prog_mode() {
return controller_programming_mode;
}
}

View File

@ -5,7 +5,6 @@
#define PROG_MODE_OFF (0U)
#define PROG_MODE_KEELOQ_BFT (1U)
#define PROG_MODE_KEELOQ_APRIMATIC (2U)
#define PROG_MODE_FAAC_SLH (3U)
typedef uint8_t ProgMode;
@ -15,4 +14,4 @@ void subghz_custom_btn_set_max(uint8_t b);
void subghz_custom_btn_set_prog_mode(ProgMode prog_mode);
ProgMode subghz_custom_btn_get_prog_mode();
ProgMode subghz_custom_btn_get_prog_mode();

View File

@ -25,8 +25,6 @@ struct SubGhzBlockGeneric {
uint32_t cnt;
uint8_t cnt_2;
uint32_t seed;
bool prg_mode : 1;
bool allow_zero_seed : 1;
};
/**

View File

@ -8,6 +8,8 @@
#include "../blocks/generic.h"
#include "../blocks/math.h"
#include "../blocks/custom_btn_i.h"
#define TAG "SubGhzProtocolFaacSLH"
static const SubGhzBlockConst subghz_protocol_faac_slh_const = {
@ -17,6 +19,18 @@ static const SubGhzBlockConst subghz_protocol_faac_slh_const = {
.min_count_bit_for_found = 64,
};
static uint32_t temp_fix_backup = 0;
static uint32_t temp_counter_backup = 0;
static bool faac_prog_mode = false;
static bool allow_zero_seed = false;
void faac_slh_reset_prog_mode() {
temp_fix_backup = 0;
temp_counter_backup = 0;
faac_prog_mode = false;
allow_zero_seed = false;
}
struct SubGhzProtocolDecoderFaacSLH {
SubGhzProtocolDecoderBase base;
@ -110,18 +124,35 @@ void subghz_protocol_encoder_faac_slh_free(void* context) {
}
static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* instance) {
if(instance->generic.allow_zero_seed || (instance->generic.seed != 0x0)) {
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
FURI_LOG_I(TAG, "Counter ++");
} else if(instance->generic.prg_mode == true) {
// TODO: Stupid bypass for custom button, remake later
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(0xF);
}
uint8_t custom_btn_id = subghz_custom_btn_get();
bool button_for_programming = false;
// If custom button left is pressed, enable programming mode and disable it on Ok button
if((custom_btn_id == SUBGHZ_CUSTOM_BTN_OK)) {
button_for_programming = false;
} else if(custom_btn_id == SUBGHZ_CUSTOM_BTN_UP) {
button_for_programming = true;
}
// If we are using UP button - generate programming mode key and send it, otherwise - send regular key if possible
if(button_for_programming) {
uint8_t data_tmp = 0;
uint8_t data_prg[8];
instance->generic.cnt_2++;
data_prg[0] = 0x00;
data_prg[1] = instance->generic.cnt_2;
if(allow_zero_seed || (instance->generic.seed != 0x0)) {
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
if(temp_counter_backup != 0x0) {
temp_counter_backup += furi_hal_subghz_get_rolling_counter_mult();
}
}
data_prg[1] = instance->generic.cnt & 0xFF;
data_prg[2] = (uint8_t)(instance->generic.seed & 0xFF);
data_prg[3] = (uint8_t)(instance->generic.seed >> 8 & 0xFF);
@ -133,27 +164,42 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
data_prg[4] ^= data_prg[1];
data_prg[5] ^= data_prg[1];
for(uint8_t i=data_prg[1] & 0x0F ; i!=0; i--) {
data_tmp = data_prg[5];
for(uint8_t i = data_prg[1] & 0x0F; i != 0; i--) {
data_tmp = data_prg[5];
data_prg[5] = ((data_prg[5] << 1) & 0xFF) | (data_prg[4] & 0x80) >> 7;
data_prg[4] = ((data_prg[4] << 1) & 0xFF) | (data_prg[3] & 0x80) >> 7;
data_prg[3] = ((data_prg[3] << 1) & 0xFF) | (data_prg[2] & 0x80) >> 7;
data_prg[2] = ((data_prg[2] << 1) & 0xFF) | (data_tmp & 0x80) >> 7;
}
data_prg[5] = ((data_prg[5] << 1) & 0xFF) | (data_prg[4] & 0x80) >> 7;
data_prg[4] = ((data_prg[4] << 1) & 0xFF) | (data_prg[3] & 0x80) >> 7;
data_prg[3] = ((data_prg[3] << 1) & 0xFF) | (data_prg[2] & 0x80) >> 7;
data_prg[2] = ((data_prg[2] << 1) & 0xFF) | (data_tmp & 0x80) >> 7;
}
data_prg[6] = 0x0F;
data_prg[7] = 0x52;
uint32_t enc_prg_1 = data_prg[7] << 24 | data_prg[6] << 16 | data_prg[5] << 8 | data_prg[4];
uint32_t enc_prg_2 = data_prg[3] << 24 | data_prg[2] << 16 | data_prg[1] << 8 | data_prg[0];
uint32_t enc_prg_1 = data_prg[7] << 24 | data_prg[6] << 16 | data_prg[5] << 8 |
data_prg[4];
uint32_t enc_prg_2 = data_prg[3] << 24 | data_prg[2] << 16 | data_prg[1] << 8 |
data_prg[0];
instance->generic.data = (uint64_t)enc_prg_1 << 32 | enc_prg_2;
FURI_LOG_I(TAG, "New MasterKey encrypted : %016llX", instance->generic.data);
//FURI_LOG_D(TAG, "New Prog Mode Key Generated: %016llX\r", instance->generic.data);
return true;
} else {
// Do not generate new data, send data from buffer
FURI_LOG_I(TAG, "Unknown / Static mode");
return true;
if(!allow_zero_seed && (instance->generic.seed == 0x0)) {
// Do not generate new data, send data from buffer
return true;
}
// If we are in prog mode and regular Send button is used - Do not generate new data, send data from buffer
if((faac_prog_mode == true) && (instance->generic.serial == 0x0) &&
(instance->generic.btn == 0x0) && (temp_fix_backup == 0x0)) {
return true;
}
}
// Restore main remote data when we exit programming mode
if((instance->generic.serial == 0x0) && (instance->generic.btn == 0x0) &&
(temp_fix_backup != 0x0) && !faac_prog_mode) {
instance->generic.serial = temp_fix_backup >> 4;
instance->generic.btn = temp_fix_backup & 0xF;
instance->generic.cnt = temp_counter_backup;
}
uint32_t fix = instance->generic.serial << 4 | instance->generic.btn;
uint32_t hop = 0;
@ -165,6 +211,11 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
for(int i = 0; i < 8; i++) {
fixx[i] = (fix >> (shiftby -= 4)) & 0xF;
}
if(allow_zero_seed || (instance->generic.seed != 0x0)) {
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
}
if((instance->generic.cnt % 2) == 0) {
decrypt = fixx[6] << 28 | fixx[7] << 24 | fixx[5] << 20 |
(instance->generic.cnt & 0xFFFFF);
@ -211,7 +262,7 @@ bool subghz_protocol_faac_slh_create_data(
instance->generic.seed = seed;
instance->manufacture_name = manufacture_name;
instance->generic.data_count_bit = 64;
instance->generic.allow_zero_seed = true;
allow_zero_seed = true;
bool res = subghz_protocol_faac_slh_gen_data(instance);
if(res) {
return SubGhzProtocolStatusOk ==
@ -282,13 +333,11 @@ SubGhzProtocolStatus
FURI_LOG_E(TAG, "Missing Seed");
break;
}
bool allow_zero_seed;
if(flipper_format_read_bool(flipper_format, "AllowZeroSeed", &allow_zero_seed, 1)) {
instance->generic.allow_zero_seed = true;
FURI_LOG_I(TAG, "Enc. des. TRUE");
bool tmp_allow_zero_seed;
if(flipper_format_read_bool(flipper_format, "AllowZeroSeed", &tmp_allow_zero_seed, 1)) {
allow_zero_seed = true;
} else {
instance->generic.allow_zero_seed = false;
FURI_LOG_I(TAG, "Enc. des. FALSE");
allow_zero_seed = false;
}
instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 |
@ -452,11 +501,16 @@ static void subghz_protocol_faac_slh_check_remote_controller(
const char** manufacture_name) {
uint32_t code_fix = instance->data >> 32;
uint32_t code_hop = instance->data & 0xFFFFFFFF;
instance->serial = code_fix >> 4;
instance->btn = code_fix & 0xF;
uint32_t decrypt = 0;
uint64_t man;
// TODO: Stupid bypass for custom button, remake later
if(subghz_custom_btn_get_original() == 0) {
subghz_custom_btn_set_original(0xF);
}
subghz_custom_btn_set_max(1);
uint8_t data_tmp = 0;
uint8_t data_prg[8];
data_prg[0] = (code_hop & 0xFF);
@ -468,36 +522,40 @@ static void subghz_protocol_faac_slh_check_remote_controller(
data_prg[6] = ((code_fix >> 16) & 0xFF);
data_prg[7] = (code_fix >> 24);
if( (data_prg[7] == 0x52) && (data_prg[6] == 0x0F) && (data_prg[0] == 0x00) ) {
instance->prg_mode = true;
if(((data_prg[7] == 0x52) && (data_prg[6] == 0x0F) && (data_prg[0] == 0x00))) {
faac_prog_mode = true;
// ProgMode ON
FURI_LOG_I(TAG, "Master Key detected!");
for(uint8_t i = data_prg[1] & 0xF; i != 0; i--) {
data_tmp = data_prg[2];
data_tmp = data_prg[2];
data_prg[2] = data_prg[2] >> 1 | (data_prg[3] & 1) << 7;
data_prg[3] = data_prg[3] >> 1 | (data_prg[4] & 1) << 7;
data_prg[4] = data_prg[4] >> 1 | (data_prg[5] & 1) << 7;
data_prg[5] = data_prg[5] >> 1 | (data_tmp & 1) << 7;
}
data_prg[2] ^= data_prg[1];
data_prg[3] ^= data_prg[1];
data_prg[4] ^= data_prg[1];
data_prg[5] ^= data_prg[1];
FURI_LOG_I(TAG, "Got SEED value!");
instance->seed = data_prg[5] << 24 | data_prg[4] << 16 | data_prg[3] << 8 | data_prg[2];
FURI_LOG_I(TAG, "SEED = %08lX", instance->seed);
uint32_t dec_prg_1 = data_prg[7] << 24 | data_prg[6] << 16 | data_prg[5] << 8 | data_prg[4];
uint32_t dec_prg_2 = data_prg[3] << 24 | data_prg[2] << 16 | data_prg[1] << 8 | data_prg[0];
instance->data_2 = (uint64_t)dec_prg_1 << 32 | dec_prg_2;
FURI_LOG_I(TAG, "MasterKey decrypted : %016llX", instance->data_2);
instance->cnt_2 = data_prg[1];
} else {
instance->prg_mode = false;
data_prg[2] = data_prg[2] >> 1 | (data_prg[3] & 1) << 7;
data_prg[3] = data_prg[3] >> 1 | (data_prg[4] & 1) << 7;
data_prg[4] = data_prg[4] >> 1 | (data_prg[5] & 1) << 7;
data_prg[5] = data_prg[5] >> 1 | (data_tmp & 1) << 7;
}
data_prg[2] ^= data_prg[1];
data_prg[3] ^= data_prg[1];
data_prg[4] ^= data_prg[1];
data_prg[5] ^= data_prg[1];
instance->seed = data_prg[5] << 24 | data_prg[4] << 16 | data_prg[3] << 8 | data_prg[2];
uint32_t dec_prg_1 = data_prg[7] << 24 | data_prg[6] << 16 | data_prg[5] << 8 |
data_prg[4];
uint32_t dec_prg_2 = data_prg[3] << 24 | data_prg[2] << 16 | data_prg[1] << 8 |
data_prg[0];
instance->data_2 = (uint64_t)dec_prg_1 << 32 | dec_prg_2;
instance->cnt = data_prg[1];
*manufacture_name = "FAAC_SLH";
return;
} else {
if(code_fix != 0x0) {
temp_fix_backup = code_fix;
instance->serial = code_fix >> 4;
instance->btn = code_fix & 0xF;
}
faac_prog_mode = false;
}
for
M_EACH(manufacture_code, *subghz_keystore_get_data(keystore), SubGhzKeyArray_t) {
@ -512,6 +570,10 @@ static void subghz_protocol_faac_slh_check_remote_controller(
}
}
instance->cnt = decrypt & 0xFFFFF;
// Backup counter in case when we need to use programming mode
if(code_fix != 0x0) {
temp_counter_backup = instance->cnt;
}
}
uint8_t subghz_protocol_decoder_faac_slh_get_hash_data(void* context) {
@ -530,6 +592,7 @@ SubGhzProtocolStatus subghz_protocol_decoder_faac_slh_serialize(
// Reset seed leftover from previous decoded signal
instance->generic.seed = 0x0;
temp_fix_backup = 0x0;
SubGhzProtocolStatus res =
subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
@ -577,13 +640,11 @@ SubGhzProtocolStatus
FURI_LOG_E(TAG, "Missing Seed");
break;
}
bool allow_zero_seed;
if(flipper_format_read_bool(flipper_format, "AllowZeroSeed", &allow_zero_seed, 1)) {
instance->generic.allow_zero_seed = true;
FURI_LOG_I(TAG, "Dec. des. TRUE");
bool tmp_allow_zero_seed;
if(flipper_format_read_bool(flipper_format, "AllowZeroSeed", &tmp_allow_zero_seed, 1)) {
allow_zero_seed = true;
} else {
instance->generic.allow_zero_seed = false;
FURI_LOG_I(TAG, "Dec. des. FALSE");
allow_zero_seed = false;
}
instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 |
seed_data[3];
@ -606,10 +667,11 @@ void subghz_protocol_decoder_faac_slh_get_string(void* context, FuriString* outp
uint32_t code_fix = instance->generic.data >> 32;
uint32_t code_hop = instance->generic.data & 0xFFFFFFFF;
if(instance->generic.prg_mode == true) {
if(faac_prog_mode == true) {
furi_string_cat_printf(
output,
"%s %dbit\r\n"
"Master Remote Prog Mode\r\n"
"Ke:%lX%08lX\r\n"
"Kd:%lX%08lX\r\n"
"Seed:%08lX mCnt:%02X",
@ -620,8 +682,8 @@ void subghz_protocol_decoder_faac_slh_get_string(void* context, FuriString* outp
(uint32_t)(instance->generic.data_2 >> 32),
(uint32_t)instance->generic.data_2,
instance->generic.seed,
instance->generic.cnt_2);
} else if(instance->generic.allow_zero_seed == false) {
(uint8_t)(instance->generic.cnt & 0xFF));
} else if(allow_zero_seed == false) {
furi_string_cat_printf(
output,
"%s %dbit\r\n"

View File

@ -129,3 +129,7 @@ SubGhzProtocolStatus
* @param output Resulting text
*/
void subghz_protocol_decoder_faac_slh_get_string(void* context, FuriString* output);
// Reset prog mode vars
// TODO: Remake in proper way
void faac_slh_reset_prog_mode();