From 8887cbff8842c7118e62eeccc9d685f539f335ec Mon Sep 17 00:00:00 2001 From: Louis D Date: Sun, 13 Jul 2025 02:56:04 +0200 Subject: [PATCH 01/14] feat: add option for custom button when creating a new Nice Flor-S or Nice One remote --- .../main/subghz/scenes/subghz_scene_config.h | 1 + .../subghz/scenes/subghz_scene_set_button.c | 88 +++++++++++++++++++ .../subghz/scenes/subghz_scene_set_seed.c | 3 +- .../subghz/scenes/subghz_scene_set_type.c | 36 ++------ applications/main/subghz/subghz_i.h | 1 + 5 files changed, 97 insertions(+), 32 deletions(-) create mode 100644 applications/main/subghz/scenes/subghz_scene_set_button.c diff --git a/applications/main/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h index b9480b349..f682ac7e4 100644 --- a/applications/main/subghz/scenes/subghz_scene_config.h +++ b/applications/main/subghz/scenes/subghz_scene_config.h @@ -13,6 +13,7 @@ ADD_SCENE(subghz, delete, Delete) ADD_SCENE(subghz, delete_success, DeleteSuccess) ADD_SCENE(subghz, set_type, SetType) ADD_SCENE(subghz, set_fix, SetFix) +ADD_SCENE(subghz, set_button, SetButton) ADD_SCENE(subghz, set_cnt, SetCnt) ADD_SCENE(subghz, set_seed, SetSeed) ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) diff --git a/applications/main/subghz/scenes/subghz_scene_set_button.c b/applications/main/subghz/scenes/subghz_scene_set_button.c new file mode 100644 index 000000000..89a47197d --- /dev/null +++ b/applications/main/subghz/scenes/subghz_scene_set_button.c @@ -0,0 +1,88 @@ +#include "../subghz_i.h" +#include "../helpers/subghz_txrx_create_protocol_key.h" + +#define TAG "SubGhzSetButton" + +void subghz_scene_set_button_byte_input_callback(void* context) { + SubGhz* subghz = context; + + view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone); +} + +void subghz_scene_set_button_on_enter(void* context) { + SubGhz* subghz = context; + // Set default value (button 1) for first use + subghz->secure_data->btn = 0x01; + + // Setup view + ByteInput* byte_input = subghz->byte_input; + byte_input_set_header_text(byte_input, "Enter BUTTON in hex"); + byte_input_set_result_callback( + byte_input, + subghz_scene_set_button_byte_input_callback, + NULL, + subghz, + &subghz->secure_data->btn, + 1); + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); +} + +bool subghz_scene_set_button_on_event(void* context, SceneManagerEvent event) { + SubGhz* subghz = context; + bool consumed = false; + bool generated_protocol = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubGhzCustomEventByteInputDone) { + SetType state = + scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType); + + if (state == SetTypeNiceFlorS_433_92 || state == SetTypeNiceOne_433_92) { + uint64_t key = (uint64_t)rand(); + + generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( + subghz->txrx, + "AM650", + 433920000, + key & 0x0FFFFFFF, + subghz->secure_data->btn, + 0x03, + state == SetTypeNiceOne_433_92 + ); + + 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); + } + + consumed = true; + } + } + + // Reset Seed, Fix, Cnt, Btn in secure data after successful or unsuccessful generation + memset(subghz->secure_data->seed, 0, sizeof(subghz->secure_data->seed)); + memset(subghz->secure_data->cnt, 0, sizeof(subghz->secure_data->cnt)); + memset(subghz->secure_data->fix, 0, sizeof(subghz->secure_data->fix)); + subghz->secure_data->btn = 0x01; + + + if(generated_protocol) { + subghz_file_name_clear(subghz); + + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); + return true; + } + } + return consumed; +} + +void subghz_scene_set_button_on_exit(void* context) { + SubGhz* subghz = context; + + // Clear view + byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(subghz->byte_input, ""); +} diff --git a/applications/main/subghz/scenes/subghz_scene_set_seed.c b/applications/main/subghz/scenes/subghz_scene_set_seed.c index c8301745f..01406371d 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_seed.c +++ b/applications/main/subghz/scenes/subghz_scene_set_seed.c @@ -108,10 +108,11 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { } } - // Reset Seed, Fix, Cnt in secure data after successful or unsuccessful generation + // Reset Seed, Fix, Cnt, Btn in secure data after successful or unsuccessful generation memset(subghz->secure_data->seed, 0, sizeof(subghz->secure_data->seed)); memset(subghz->secure_data->cnt, 0, sizeof(subghz->secure_data->cnt)); memset(subghz->secure_data->fix, 0, sizeof(subghz->secure_data->fix)); + subghz->secure_data->btn = 0x01; if(generated_protocol) { subghz_file_name_clear(subghz); diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index b986c2c5d..33177b7de 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -112,7 +112,6 @@ typedef enum { GenKeeloqBFT, GenAlutechAt4n, GenSomfyTelis, - GenNiceFlorS, GenSecPlus1, GenSecPlus2, GenPhoenixV2, @@ -197,6 +196,11 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { return true; } + if (event.event == SetTypeNiceFlorS_433_92 || event.event == SetTypeNiceOne_433_92) { + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetButton); + return true; + } + uint64_t key = (uint64_t)rand(); uint64_t gangqi_key; @@ -722,26 +726,6 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { .keeloq.cnt = 0x03, .keeloq.manuf = "DoorHan"}; break; - case SetTypeNiceFlorS_433_92: - gen_info = (GenInfo){ - .type = GenNiceFlorS, - .mod = "AM650", - .freq = 433920000, - .nice_flor_s.serial = key & 0x0FFFFFFF, - .nice_flor_s.btn = 0x01, - .nice_flor_s.cnt = 0x03, - .nice_flor_s.nice_one = false}; - break; - case SetTypeNiceOne_433_92: - gen_info = (GenInfo){ - .type = GenNiceFlorS, - .mod = "AM650", - .freq = 433920000, - .nice_flor_s.serial = key & 0x0FFFFFFF, - .nice_flor_s.btn = 0x01, - .nice_flor_s.cnt = 0x03, - .nice_flor_s.nice_one = true}; - break; case SetTypeNiceSmilo_433_92: gen_info = (GenInfo){ .type = GenKeeloq, @@ -989,16 +973,6 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { gen_info.somfy_telis.btn, gen_info.somfy_telis.cnt); break; - case GenNiceFlorS: - generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.nice_flor_s.serial, - gen_info.nice_flor_s.btn, - gen_info.nice_flor_s.cnt, - gen_info.nice_flor_s.nice_one); - break; case GenSecPlus1: generated_protocol = subghz_txrx_gen_secplus_v1_protocol(subghz->txrx, gen_info.mod, gen_info.freq); diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index b9fc47f79..6160c48c3 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -48,6 +48,7 @@ typedef struct { uint8_t fix[4]; uint8_t cnt[4]; uint8_t seed[4]; + uint8_t btn; } SecureData; struct SubGhz { From e6cc2852fda66388b685af41e8e031cb6a736054 Mon Sep 17 00:00:00 2001 From: Louis D Date: Tue, 15 Jul 2025 16:53:35 +0200 Subject: [PATCH 02/14] WIP: add sub-menu for all manual additions --- applications/main/subghz/scenes/subghz_scene_start.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/applications/main/subghz/scenes/subghz_scene_start.c b/applications/main/subghz/scenes/subghz_scene_start.c index fd5ce9990..fd59f48a4 100644 --- a/applications/main/subghz/scenes/subghz_scene_start.c +++ b/applications/main/subghz/scenes/subghz_scene_start.c @@ -40,6 +40,12 @@ void subghz_scene_start_on_enter(void* context) { SubmenuIndexAddManually, subghz_scene_start_submenu_callback, subghz); + submenu_add_item( + subghz->submenu, + "Add Manually [Advanced]", + SubmenuIndexAddManually, + subghz_scene_start_submenu_callback, + subghz); submenu_add_item( subghz->submenu, "Frequency Analyzer", From 115734373b86416ba334c07f1e56271762f6816e Mon Sep 17 00:00:00 2001 From: Louis D Date: Wed, 23 Jul 2025 23:24:03 +0200 Subject: [PATCH 03/14] feat: add variation of 'Add Manually' menu with manual value selection for all entries --- .../main/subghz/helpers/subghz_custom_event.h | 3 - .../main/subghz/helpers/subghz_gen_info.c | 725 +++++++++++++++ .../main/subghz/helpers/subghz_gen_info.h | 84 ++ .../main/subghz/scenes/subghz_scene_config.h | 5 +- .../subghz/scenes/subghz_scene_save_name.c | 8 +- .../subghz/scenes/subghz_scene_set_button.c | 109 ++- .../main/subghz/scenes/subghz_scene_set_cnt.c | 66 -- .../subghz/scenes/subghz_scene_set_counter.c | 189 ++++ .../main/subghz/scenes/subghz_scene_set_fix.c | 46 - .../main/subghz/scenes/subghz_scene_set_key.c | 95 ++ .../subghz/scenes/subghz_scene_set_seed.c | 161 ++-- .../subghz/scenes/subghz_scene_set_serial.c | 119 +++ .../subghz/scenes/subghz_scene_set_type.c | 864 ++---------------- .../main/subghz/scenes/subghz_scene_start.c | 18 +- .../main/subghz/scenes/subghz_scene_start.h | 12 + applications/main/subghz/subghz.c | 4 +- applications/main/subghz/subghz_i.h | 10 +- 17 files changed, 1445 insertions(+), 1073 deletions(-) create mode 100644 applications/main/subghz/helpers/subghz_gen_info.c create mode 100644 applications/main/subghz/helpers/subghz_gen_info.h delete mode 100644 applications/main/subghz/scenes/subghz_scene_set_cnt.c create mode 100644 applications/main/subghz/scenes/subghz_scene_set_counter.c delete mode 100644 applications/main/subghz/scenes/subghz_scene_set_fix.c create mode 100644 applications/main/subghz/scenes/subghz_scene_set_key.c create mode 100644 applications/main/subghz/scenes/subghz_scene_set_serial.c create mode 100644 applications/main/subghz/scenes/subghz_scene_start.h diff --git a/applications/main/subghz/helpers/subghz_custom_event.h b/applications/main/subghz/helpers/subghz_custom_event.h index 9fc607889..dffc6d193 100644 --- a/applications/main/subghz/helpers/subghz_custom_event.h +++ b/applications/main/subghz/helpers/subghz_custom_event.h @@ -65,9 +65,6 @@ typedef enum { } SubGhzCustomEvent; typedef enum { - SetTypeFaacSLH_Manual_868, - SetTypeFaacSLH_Manual_433, - SetTypeBFTClone, SetTypeFaacSLH_868, SetTypeFaacSLH_433, SetTypeBFTMitto, diff --git a/applications/main/subghz/helpers/subghz_gen_info.c b/applications/main/subghz/helpers/subghz_gen_info.c new file mode 100644 index 000000000..00ff43abc --- /dev/null +++ b/applications/main/subghz/helpers/subghz_gen_info.c @@ -0,0 +1,725 @@ +#include "subghz_gen_info.h" +#include "../helpers/subghz_txrx_create_protocol_key.h" +#include + + +void subghz_gen_info_reset(GenInfo *gen_info) { + furi_assert(gen_info); + memset(gen_info, 0, sizeof(GenInfo)); +} + +void subghz_scene_set_type_fill_generation_infos(GenInfo* infos_dest, SetType type) { + GenInfo gen_info = { 0 }; + uint64_t key = (uint64_t)rand(); + + uint64_t gangqi_key; + subghz_txrx_gen_serial_gangqi(&gangqi_key); + + uint64_t marantec_key; + subghz_txrx_gen_key_marantec(&marantec_key); + + switch(type) { + case SetTypePricenton433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_PRINCETON_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 400}; + break; + case SetTypePricenton315: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 315000000, + .data.name = SUBGHZ_PROTOCOL_PRINCETON_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 400}; + break; + case SetTypeNiceFlo12bit: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_NICE_FLO_NAME, + .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 + .data.bits = 12, + .data.te = 0}; + break; + case SetTypeNiceFlo24bit: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_NICE_FLO_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeCAME12bit: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_CAME_NAME, + .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 + .data.bits = 12, + .data.te = 0}; + break; + case SetTypeCAME24bit: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_CAME_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeCAME12bit868: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 868350000, + .data.name = SUBGHZ_PROTOCOL_CAME_NAME, + .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 + .data.bits = 12, + .data.te = 0}; + break; + case SetTypeCAME24bit868: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 868350000, + .data.name = SUBGHZ_PROTOCOL_CAME_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeRoger_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_ROGER_NAME, + .data.key = (key & 0xFFFF000) | 0x0000101, // button code 0x1 and (crc?) is 0x01 + .data.bits = 28, + .data.te = 0}; + break; + case SetTypeLinear_300_00: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 300000000, + .data.name = SUBGHZ_PROTOCOL_LINEAR_NAME, + .data.key = (key & 0x3FF), + .data.bits = 10, + .data.te = 0}; + break; + case SetTypeBETT_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_BETT_NAME, + .data.key = (key & 0x0000FFF0), + .data.bits = 18, + .data.te = 0}; + break; + case SetTypeCAMETwee: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_CAME_TWEE_NAME, + .data.key = 0x003FFF7200000000 | ((key & 0x0FFFFFF0) ^ 0xE0E0E0EE), // ???? + .data.bits = 54, + .data.te = 0}; + break; + case SetTypeGateTX: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_GATE_TX_NAME, // btn 0xF, 0xC, 0xA, 0x6 (?) + .data.key = subghz_protocol_blocks_reverse_key((key & 0x00F0FF00) | 0xF0040, 24), + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeGangQi_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = + SUBGHZ_PROTOCOL_GANGQI_NAME, // Add button 0xD arm and crc sum to the end + .data.key = gangqi_key, + .data.bits = 34, + .data.te = 0}; + break; + case SetTypeHollarm_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_HOLLARM_NAME, // Add button 0x2 and crc sum to the end + .data.key = (key & 0x000FFF0000) | 0xF0B0002200 | + ((((((key & 0x000FFF0000) | 0xF0B0002200) >> 32) & 0xFF) + + ((((key & 0x000FFF0000) | 0xF0B0002200) >> 24) & 0xFF) + + ((((key & 0x000FFF0000) | 0xF0B0002200) >> 16) & 0xFF) + + ((((key & 0x000FFF0000) | 0xF0B0002200) >> 8) & 0xFF)) & + 0xFF), + .data.bits = 42, + .data.te = 0}; + break; + case SetTypeReversRB2_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_REVERSRB2_NAME, // 64bits no buttons + .data.key = (key & 0x00000FFFFFFFF000) | 0xFFFFF00000000000 | 0x0000000000000A00, + .data.bits = 64, + .data.te = 0}; + break; + case SetTypeMarantec24_868: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 868350000, + .data.name = SUBGHZ_PROTOCOL_MARANTEC24_NAME, // Add button code 0x8 to the end + .data.key = (key & 0xFFFFF0) | 0x000008, + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeMarantec_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = + SUBGHZ_PROTOCOL_MARANTEC_NAME, // Button code is 0x4 and crc sum to the end + .data.key = marantec_key, + .data.bits = 49, + .data.te = 0}; + break; + case SetTypeMarantec_868: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 868350000, + .data.name = + SUBGHZ_PROTOCOL_MARANTEC_NAME, // Button code is 0x4 and crc sum to the end + .data.key = marantec_key, + .data.bits = 49, + .data.te = 0}; + break; + case SetTypeFaacSLH_433: + gen_info = (GenInfo){ + .type = GenFaacSLH, + .mod = "AM650", + .freq = 433920000, + .faac_slh.serial = ((key & 0x00FFFFF0) | 0xA0000006) >> 4, + .faac_slh.btn = 0x06, + .faac_slh.cnt = 0x02, + .faac_slh.seed = key, + .faac_slh.manuf = "FAAC_SLH"}; + break; + case SetTypeFaacSLH_868: + gen_info = (GenInfo){ + .type = GenFaacSLH, + .mod = "AM650", + .freq = 868350000, + .faac_slh.serial = ((key & 0x00FFFFF0) | 0xA0000006) >> 4, + .faac_slh.btn = 0x06, + .faac_slh.cnt = 0x02, + .faac_slh.seed = (key & 0x0FFFFFFF), + .faac_slh.manuf = "FAAC_SLH"}; + break; + case SetTypeBeninca433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFF00) | 0x00800080, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Beninca"}; + break; + case SetTypeBeninca868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 868350000, + .keeloq.serial = (key & 0x000FFF00) | 0x00800080, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Beninca"}; + break; + case SetTypeComunello433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x08, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Comunello"}; + break; + case SetTypeComunello868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 868460000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x08, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Comunello"}; + break; + case SetTypeAllmatic433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x00FFFF00) | 0x01000011, + .keeloq.btn = 0x0C, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Beninca"}; + break; + case SetTypeAllmatic868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 868350000, + .keeloq.serial = (key & 0x00FFFF00) | 0x01000011, + .keeloq.btn = 0x0C, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Beninca"}; + break; + case SetTypeCenturion433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0000FFFF), + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Centurion"}; + break; + case SetTypeMonarch433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0000FFFF), + .keeloq.btn = 0x0A, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Monarch"}; + break; + case SetTypeJollyMotors433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFFFF), + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Jolly_Motors"}; + break; + case SetTypeElmesElectronic: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x00FFFFFF) | 0x02000000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Elmes_Poland"}; + break; + case SetTypeANMotorsAT4: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFFFF) | 0x04700000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x21, + .keeloq.manuf = "AN-Motors"}; + break; + case SetTypeAprimatic: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFFFF) | 0x00600000, + .keeloq.btn = 0x08, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Aprimatic"}; + break; + case SetTypeGibidi433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Gibidi"}; + break; + case SetTypeGSN: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "GSN"}; + break; + case SetTypeIronLogic: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFF0, + .keeloq.btn = 0x04, + .keeloq.cnt = 0x05, + .keeloq.manuf = "IronLogic"}; + break; + case SetTypeStilmatic: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Stilmatic"}; + break; + case SetTypeSommer_FM_434: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM476", + .freq = 434420000, + .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeSommer_FM_868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM476", + .freq = 868800000, + .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeSommer_FM238_434: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM238", + .freq = 434420000, + .keeloq.serial = key & 0x0000FFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeSommer_FM238_868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM238", + .freq = 868800000, + .keeloq.serial = key & 0x0000FFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeDTMNeo433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x000FFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x05, + .keeloq.manuf = "DTM_Neo"}; + break; + case SetTypeCAMESpace: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x04, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Came_Space"}; + break; + case SetTypeCameAtomo433: + gen_info = (GenInfo){ + .type = GenCameAtomo, + .mod = "AM650", + .freq = 433920000, + .came_atomo.serial = (key & 0x0FFFFFFF) | 0x10000000, + .came_atomo.cnt = 0x03}; + break; + case SetTypeCameAtomo868: + gen_info = (GenInfo){ + .type = GenCameAtomo, + .mod = "AM650", + .freq = 868350000, + .came_atomo.serial = (key & 0x0FFFFFFF) | 0x10000000, + .came_atomo.cnt = 0x03}; + break; + case SetTypeBFTMitto: + gen_info = (GenInfo){ + .type = GenKeeloqBFT, + .mod = "AM650", + .freq = 433920000, + .keeloq_bft.serial = key & 0x000FFFFF, + .keeloq_bft.btn = 0x02, + .keeloq_bft.cnt = 0x02, + .keeloq_bft.seed = key & 0x000FFFFF, + .keeloq_bft.manuf = "BFT"}; + break; + case SetTypeAlutechAT4N: + gen_info = (GenInfo){ + .type = GenAlutechAt4n, + .mod = "AM650", + .freq = 433920000, + .alutech_at_4n.serial = (key & 0x000FFFFF) | 0x00100000, + .alutech_at_4n.btn = 0x44, + .alutech_at_4n.cnt = 0x03}; + break; + case SetTypeSomfyTelis: + gen_info = (GenInfo){ + .type = GenSomfyTelis, + .mod = "AM650", + .freq = 433420000, + .somfy_telis.serial = key & 0x00FFFFFF, + .somfy_telis.btn = 0x02, + .somfy_telis.cnt = 0x03}; + break; + case SetTypeMotorline433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Motorline"}; + break; + case SetTypeDoorHan_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "DoorHan"}; + break; + case SetTypeDoorHan_315_00: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 315000000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "DoorHan"}; + break; + case SetTypeNiceFlorS_433_92: + gen_info = (GenInfo){ + .type = GenNiceFlorS, + .mod = "AM650", + .freq = 433920000, + .nice_flor_s.serial = key & 0x0FFFFFFF, + .nice_flor_s.btn = 0x01, + .nice_flor_s.cnt = 0x03, + .nice_flor_s.nice_one = false}; + break; + case SetTypeNiceOne_433_92: + gen_info = (GenInfo){ + .type = GenNiceFlorS, + .mod = "AM650", + .freq = 433920000, + .nice_flor_s.serial = key & 0x0FFFFFFF, + .nice_flor_s.btn = 0x01, + .nice_flor_s.cnt = 0x03, + .nice_flor_s.nice_one = true}; + break; + case SetTypeNiceSmilo_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "NICE_Smilo"}; + break; + case SetTypeNiceMHouse_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x09, + .keeloq.cnt = 0x03, + .keeloq.manuf = "NICE_MHOUSE"}; + break; + case SetTypeDeaMio433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0FFFF000) | 0x00000869, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Dea_Mio"}; + break; + case SetTypeGeniusBravo433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x06, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Genius_Bravo"}; + break; + case SetTypeJCM_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "JCM_Tech"}; + break; + case SetTypeNovoferm_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0000FFFF) | 0x018F0000, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Novoferm"}; + break; + case SetTypeHormannEcoStar_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFFFF) | 0x02200000, + .keeloq.btn = 0x04, + .keeloq.cnt = 0x03, + .keeloq.manuf = "EcoStar"}; + break; + case SetTypeFAACRCXT_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0000FFFF) | 0x00100000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "FAAC_RC,XT"}; + break; + case SetTypeFAACRCXT_868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 868350000, + .keeloq.serial = (key & 0x0000FFFF) | 0x00100000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "FAAC_RC,XT"}; + break; + case SetTypeNormstahl_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0000FFFF, + .keeloq.btn = 0x04, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Normstahl"}; + break; + case SetTypeHCS101_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x000FFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "HCS101"}; + break; + case SetTypeSecPlus_v1_315_00: + gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 315000000}; + break; + case SetTypeSecPlus_v1_390_00: + gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 390000000}; + break; + case SetTypeSecPlus_v1_433_00: + gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 433920000}; + break; + case SetTypeSecPlus_v2_310_00: + gen_info = (GenInfo){ + .type = GenSecPlus2, + .mod = "AM650", + .freq = 310000000, + .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing + .sec_plus_2.btn = 0x68, + .sec_plus_2.cnt = 0xE500000}; + break; + case SetTypeSecPlus_v2_315_00: + gen_info = (GenInfo){ + .type = GenSecPlus2, + .mod = "AM650", + .freq = 315000000, + .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing + .sec_plus_2.btn = 0x68, + .sec_plus_2.cnt = 0xE500000}; + break; + case SetTypeSecPlus_v2_390_00: + gen_info = (GenInfo){ + .type = GenSecPlus2, + .mod = "AM650", + .freq = 390000000, + .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing + .sec_plus_2.btn = 0x68, + .sec_plus_2.cnt = 0xE500000}; + break; + case SetTypeSecPlus_v2_433_00: + gen_info = (GenInfo){ + .type = GenSecPlus2, + .mod = "AM650", + .freq = 433920000, + .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing + .sec_plus_2.btn = 0x68, + .sec_plus_2.cnt = 0xE500000}; + break; + case SetTypePhoenix_V2_433: + gen_info = (GenInfo){ + .type = GenPhoenixV2, + .mod = "AM650", + .freq = 433920000, + .phoenix_v2.serial = (key & 0x0FFFFFFF) | 0xB0000000, + .phoenix_v2.cnt = 0x025D}; + break; + default: + furi_crash("Not implemented"); + break; + } + *infos_dest = gen_info; +} diff --git a/applications/main/subghz/helpers/subghz_gen_info.h b/applications/main/subghz/helpers/subghz_gen_info.h new file mode 100644 index 000000000..938c6d27a --- /dev/null +++ b/applications/main/subghz/helpers/subghz_gen_info.h @@ -0,0 +1,84 @@ +#pragma once +#include "subghz_types.h" +#include "subghz_custom_event.h" + +typedef enum { + GenData, + GenFaacSLH, + GenKeeloq, + GenCameAtomo, + GenKeeloqBFT, + GenAlutechAt4n, + GenSomfyTelis, + GenNiceFlorS, + GenSecPlus1, + GenSecPlus2, + GenPhoenixV2, +} GenType; + +typedef struct { + GenType type; + const char* mod; + uint32_t freq; + union { + struct { + const char* name; + uint64_t key; + uint8_t bits; + uint16_t te; + } data; + struct { + uint32_t serial; + uint8_t btn; + uint8_t cnt; + uint32_t seed; + const char* manuf; + } faac_slh; + struct { + uint32_t serial; + uint8_t btn; + uint8_t cnt; + const char* manuf; + } keeloq; + struct { + uint32_t serial; + uint8_t cnt; + } came_atomo; + struct { + uint32_t serial; + uint8_t btn; + uint8_t cnt; + uint32_t seed; + const char* manuf; + } keeloq_bft; + struct { + uint32_t serial; + uint8_t btn; + uint8_t cnt; + } alutech_at_4n; + struct { + uint32_t serial; + uint8_t btn; + uint8_t cnt; + } somfy_telis; + struct { + uint32_t serial; + uint8_t btn; + uint8_t cnt; + bool nice_one; + } nice_flor_s; + struct { + uint32_t serial; + uint8_t btn; + uint32_t cnt; + } sec_plus_2; + struct { + uint32_t serial; + uint16_t cnt; + } phoenix_v2; + }; +} GenInfo; + +void subghz_gen_info_reset(GenInfo *gen_info); + +void subghz_scene_set_type_fill_generation_infos(GenInfo* infos_dest, SetType type); diff --git a/applications/main/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h index f682ac7e4..a23a12a2b 100644 --- a/applications/main/subghz/scenes/subghz_scene_config.h +++ b/applications/main/subghz/scenes/subghz_scene_config.h @@ -12,9 +12,10 @@ ADD_SCENE(subghz, saved_menu, SavedMenu) ADD_SCENE(subghz, delete, Delete) ADD_SCENE(subghz, delete_success, DeleteSuccess) ADD_SCENE(subghz, set_type, SetType) -ADD_SCENE(subghz, set_fix, SetFix) +ADD_SCENE(subghz, set_key, SetKey) +ADD_SCENE(subghz, set_serial, SetSerial) ADD_SCENE(subghz, set_button, SetButton) -ADD_SCENE(subghz, set_cnt, SetCnt) +ADD_SCENE(subghz, set_counter, SetCounter) ADD_SCENE(subghz, set_seed, SetSeed) ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) ADD_SCENE(subghz, radio_settings, ExtModuleSettings) diff --git a/applications/main/subghz/scenes/subghz_scene_save_name.c b/applications/main/subghz/scenes/subghz_scene_save_name.c index d31f1ce25..66121545d 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_name.c +++ b/applications/main/subghz/scenes/subghz_scene_save_name.c @@ -103,12 +103,8 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { furi_string_set(subghz->file_path, subghz->file_path_tmp); } } - 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); - } + + scene_manager_previous_scene(subghz->scene_manager); return true; } else if(event.type == SceneManagerEventTypeCustom) { diff --git a/applications/main/subghz/scenes/subghz_scene_set_button.c b/applications/main/subghz/scenes/subghz_scene_set_button.c index 89a47197d..cd5e11f47 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_button.c +++ b/applications/main/subghz/scenes/subghz_scene_set_button.c @@ -11,8 +11,51 @@ void subghz_scene_set_button_byte_input_callback(void* context) { void subghz_scene_set_button_on_enter(void* context) { SubGhz* subghz = context; - // Set default value (button 1) for first use - subghz->secure_data->btn = 0x01; + + uint8_t* byte_ptr = NULL; + uint8_t byte_count = 0; + + switch(subghz->gen_info->type) { + case GenFaacSLH: + byte_ptr = &subghz->gen_info->faac_slh.btn; + byte_count = sizeof(subghz->gen_info->faac_slh.btn); + break; + case GenKeeloq: + byte_ptr = &subghz->gen_info->keeloq.btn; + byte_count = sizeof(subghz->gen_info->keeloq.btn); + break; + case GenKeeloqBFT: + byte_ptr = &subghz->gen_info->keeloq_bft.btn; + byte_count = sizeof(subghz->gen_info->keeloq_bft.btn); + break; + case GenAlutechAt4n: + byte_ptr = &subghz->gen_info->alutech_at_4n.btn; + byte_count = sizeof(subghz->gen_info->alutech_at_4n.btn); + break; + case GenSomfyTelis: + byte_ptr = &subghz->gen_info->somfy_telis.btn; + byte_count = sizeof(subghz->gen_info->somfy_telis.btn); + break; + case GenNiceFlorS: + byte_ptr = &subghz->gen_info->nice_flor_s.btn; + byte_count = sizeof(subghz->gen_info->nice_flor_s.btn); + break; + case GenSecPlus2: + byte_ptr = &subghz->gen_info->sec_plus_2.btn; + byte_count = sizeof(subghz->gen_info->sec_plus_2.btn); + break; + // Not needed for these types + case GenPhoenixV2: + case GenData: + case GenSecPlus1: + case GenCameAtomo: + default: + furi_crash("Not implemented"); + break; + } + + furi_assert(byte_ptr); + furi_assert(byte_count > 0); // Setup view ByteInput* byte_input = subghz->byte_input; @@ -22,58 +65,38 @@ void subghz_scene_set_button_on_enter(void* context) { subghz_scene_set_button_byte_input_callback, NULL, subghz, - &subghz->secure_data->btn, - 1); + byte_ptr, + byte_count); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); } bool subghz_scene_set_button_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; bool consumed = false; - bool generated_protocol = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventByteInputDone) { - SetType state = - scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType); - - if (state == SetTypeNiceFlorS_433_92 || state == SetTypeNiceOne_433_92) { - uint64_t key = (uint64_t)rand(); - - generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( - subghz->txrx, - "AM650", - 433920000, - key & 0x0FFFFFFF, - subghz->secure_data->btn, - 0x03, - state == SetTypeNiceOne_433_92 - ); - - 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); - } - - consumed = true; + switch(subghz->gen_info->type) { + case GenFaacSLH: + case GenKeeloq: + case GenKeeloqBFT: + case GenAlutechAt4n: + case GenSomfyTelis: + case GenNiceFlorS: + case GenSecPlus2: + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetCounter); + break; + // Not needed for these types + case GenCameAtomo: + case GenPhoenixV2: + case GenData: + case GenSecPlus1: + default: + furi_crash("Not implemented"); + break; } - } - // Reset Seed, Fix, Cnt, Btn in secure data after successful or unsuccessful generation - memset(subghz->secure_data->seed, 0, sizeof(subghz->secure_data->seed)); - memset(subghz->secure_data->cnt, 0, sizeof(subghz->secure_data->cnt)); - memset(subghz->secure_data->fix, 0, sizeof(subghz->secure_data->fix)); - subghz->secure_data->btn = 0x01; - - - if(generated_protocol) { - subghz_file_name_clear(subghz); - - scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); - return true; + consumed = true; } } return consumed; diff --git a/applications/main/subghz/scenes/subghz_scene_set_cnt.c b/applications/main/subghz/scenes/subghz_scene_set_cnt.c deleted file mode 100644 index b202d6d91..000000000 --- a/applications/main/subghz/scenes/subghz_scene_set_cnt.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "../subghz_i.h" - -#define TAG "SubGhzSetCnt" - -void subghz_scene_set_cnt_byte_input_callback(void* context) { - SubGhz* subghz = context; - - view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone); -} - -void subghz_scene_set_cnt_on_enter(void* context) { - SubGhz* subghz = context; - - // Setup view - ByteInput* byte_input = subghz->byte_input; - SubGhzCustomEvent state = - scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType); - - switch(state) { - case SetTypeBFTClone: - 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, - NULL, - subghz, - subghz->secure_data->cnt, - 2); - break; - case SetTypeFaacSLH_Manual_433: - case SetTypeFaacSLH_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, - NULL, - subghz, - subghz->secure_data->cnt, - 3); - break; - default: - break; - } - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); -} - -bool subghz_scene_set_cnt_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubGhzCustomEventByteInputDone) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetSeed); - consumed = true; - } - } - return consumed; -} - -void subghz_scene_set_cnt_on_exit(void* context) { - SubGhz* subghz = context; - - // Clear view - byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0); - byte_input_set_header_text(subghz->byte_input, ""); -} diff --git a/applications/main/subghz/scenes/subghz_scene_set_counter.c b/applications/main/subghz/scenes/subghz_scene_set_counter.c new file mode 100644 index 000000000..b9f241258 --- /dev/null +++ b/applications/main/subghz/scenes/subghz_scene_set_counter.c @@ -0,0 +1,189 @@ +#include "../subghz_i.h" +#include "../helpers/subghz_txrx_create_protocol_key.h" + +#define TAG "SubGhzSetCounter" + +void subghz_scene_set_counter_byte_input_callback(void* context) { + SubGhz* subghz = context; + + view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone); +} + +void subghz_scene_set_counter_on_enter(void* context) { + SubGhz* subghz = context; + + uint8_t* byte_ptr = NULL; + uint8_t byte_count = 0; + + switch(subghz->gen_info->type) { + case GenFaacSLH: + byte_ptr = &subghz->gen_info->faac_slh.cnt; + byte_count = sizeof(subghz->gen_info->faac_slh.cnt); + break; + case GenKeeloq: + byte_ptr = &subghz->gen_info->keeloq.cnt; + byte_count = sizeof(subghz->gen_info->keeloq.cnt); + break; + case GenCameAtomo: + byte_ptr = &subghz->gen_info->came_atomo.cnt; + byte_count = sizeof(subghz->gen_info->came_atomo.cnt); + break; + case GenKeeloqBFT: + byte_ptr = &subghz->gen_info->keeloq_bft.cnt; + byte_count = sizeof(subghz->gen_info->keeloq_bft.cnt); + break; + case GenAlutechAt4n: + byte_ptr = &subghz->gen_info->alutech_at_4n.cnt; + byte_count = sizeof(subghz->gen_info->alutech_at_4n.cnt); + break; + case GenSomfyTelis: + byte_ptr = &subghz->gen_info->somfy_telis.cnt; + byte_count = sizeof(subghz->gen_info->somfy_telis.cnt); + break; + case GenNiceFlorS: + byte_ptr = &subghz->gen_info->nice_flor_s.cnt; + byte_count = sizeof(subghz->gen_info->nice_flor_s.cnt); + break; + case GenSecPlus2: + byte_ptr = (uint8_t*)&subghz->gen_info->sec_plus_2.cnt; + byte_count = sizeof(subghz->gen_info->sec_plus_2.cnt); + break; + case GenPhoenixV2: + byte_ptr = (uint8_t*)&subghz->gen_info->phoenix_v2.cnt; + byte_count = sizeof(subghz->gen_info->phoenix_v2.cnt); + break; + // Not needed for these types + case GenData: + case GenSecPlus1: + default: + furi_crash("Not implemented"); + break; + } + + furi_assert(byte_ptr); + furi_assert(byte_count > 0); + + // Setup view + ByteInput* byte_input = subghz->byte_input; + byte_input_set_header_text(byte_input, "Enter COUNTER in hex"); + + byte_input_set_result_callback( + byte_input, + subghz_scene_set_counter_byte_input_callback, + NULL, + subghz, + byte_ptr, + byte_count); + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); +} + +bool subghz_scene_set_counter_on_event(void* context, SceneManagerEvent event) { + SubGhz* subghz = context; + bool consumed = false; + bool generated_protocol = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubGhzCustomEventByteInputDone) { + GenInfo gen_info = *subghz->gen_info; + + switch(gen_info.type) { + case GenFaacSLH: + case GenKeeloqBFT: + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetSeed); + return true; + case GenKeeloq: + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.keeloq.serial, + gen_info.keeloq.btn, + gen_info.keeloq.cnt, + gen_info.keeloq.manuf); + break; + case GenCameAtomo: + generated_protocol = subghz_txrx_gen_came_atomo_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.came_atomo.serial, + gen_info.came_atomo.cnt); + break; + case GenAlutechAt4n: + generated_protocol = subghz_txrx_gen_alutech_at_4n_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.alutech_at_4n.serial, + gen_info.alutech_at_4n.btn, + gen_info.alutech_at_4n.cnt); + break; + case GenSomfyTelis: + generated_protocol = subghz_txrx_gen_somfy_telis_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.somfy_telis.serial, + gen_info.somfy_telis.btn, + gen_info.somfy_telis.cnt); + break; + case GenNiceFlorS: + generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.nice_flor_s.serial, + gen_info.nice_flor_s.btn, + gen_info.nice_flor_s.cnt, + gen_info.nice_flor_s.nice_one); + break; + case GenSecPlus2: + generated_protocol = subghz_txrx_gen_secplus_v2_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.sec_plus_2.serial, + gen_info.sec_plus_2.btn, + gen_info.sec_plus_2.cnt); + break; + case GenPhoenixV2: + generated_protocol = subghz_txrx_gen_phoenix_v2_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.phoenix_v2.serial, + gen_info.phoenix_v2.cnt); + break; + // Not needed for these types + case GenData: + case GenSecPlus1: + default: + furi_crash("Not implemented"); + break; + } + + consumed = true; + + 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); + } else { + subghz_file_name_clear(subghz); + + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); + } + } + } + return consumed; +} + +void subghz_scene_set_counter_on_exit(void* context) { + SubGhz* subghz = context; + + // Clear view + byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(subghz->byte_input, ""); +} diff --git a/applications/main/subghz/scenes/subghz_scene_set_fix.c b/applications/main/subghz/scenes/subghz_scene_set_fix.c deleted file mode 100644 index 93df4e54d..000000000 --- a/applications/main/subghz/scenes/subghz_scene_set_fix.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "../subghz_i.h" - -#define TAG "SubGhzSetFix" - -void subghz_scene_set_fix_byte_input_callback(void* context) { - SubGhz* subghz = context; - - view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone); -} - -void subghz_scene_set_fix_on_enter(void* context) { - SubGhz* subghz = context; - - // Setup view - ByteInput* byte_input = subghz->byte_input; - 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, - NULL, - subghz, - subghz->secure_data->fix, - 4); - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); -} - -bool subghz_scene_set_fix_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubGhzCustomEventByteInputDone) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetCnt); - consumed = true; - } - } - return consumed; -} - -void subghz_scene_set_fix_on_exit(void* context) { - SubGhz* subghz = context; - - // Clear view - byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0); - byte_input_set_header_text(subghz->byte_input, ""); -} diff --git a/applications/main/subghz/scenes/subghz_scene_set_key.c b/applications/main/subghz/scenes/subghz_scene_set_key.c new file mode 100644 index 000000000..f9872fb11 --- /dev/null +++ b/applications/main/subghz/scenes/subghz_scene_set_key.c @@ -0,0 +1,95 @@ +#include "../subghz_i.h" +#include "../helpers/subghz_txrx_create_protocol_key.h" + +#define TAG "SubGhzSetKey" + +void subghz_scene_set_key_byte_input_callback(void* context) { + SubGhz* subghz = context; + + view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone); +} + +void subghz_scene_set_key_on_enter(void* context) { + SubGhz* subghz = context; + + uint8_t* byte_ptr = NULL; + uint8_t byte_count = 0; + + if(subghz->gen_info->type == GenData) { + byte_ptr = (uint8_t*)&subghz->gen_info->data.key; + byte_count = sizeof(subghz->gen_info->data.key); + } else { + furi_crash("Not implemented"); + } + + furi_assert(byte_ptr); + furi_assert(byte_count > 0); + + // Setup view + ByteInput* byte_input = subghz->byte_input; + byte_input_set_header_text(byte_input, "Enter KEY in hex"); + byte_input_set_result_callback( + byte_input, + subghz_scene_set_key_byte_input_callback, + NULL, + subghz, + byte_ptr, + byte_count); + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); +} + +bool subghz_scene_set_key_on_event(void* context, SceneManagerEvent event) { + SubGhz* subghz = context; + bool consumed = false; + bool generated_protocol = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubGhzCustomEventByteInputDone) { + GenInfo gen_info = *subghz->gen_info; + + if(gen_info.type == GenData) { + if(gen_info.data.te) { + generated_protocol = subghz_txrx_gen_data_protocol_and_te( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.data.name, + gen_info.data.key, + gen_info.data.bits, + gen_info.data.te); + } else { + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.data.name, + gen_info.data.key, + gen_info.data.bits); + } + } + + consumed = true; + + 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); + } else { + subghz_file_name_clear(subghz); + + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); + } + } + } + return consumed; +} + +void subghz_scene_set_key_on_exit(void* context) { + SubGhz* subghz = context; + + // Clear view + byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(subghz->byte_input, ""); +} diff --git a/applications/main/subghz/scenes/subghz_scene_set_seed.c b/applications/main/subghz/scenes/subghz_scene_set_seed.c index 01406371d..408460518 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_seed.c +++ b/applications/main/subghz/scenes/subghz_scene_set_seed.c @@ -12,6 +12,36 @@ void subghz_scene_set_seed_byte_input_callback(void* context) { void subghz_scene_set_seed_on_enter(void* context) { SubGhz* subghz = context; + uint8_t* byte_ptr = NULL; + uint8_t byte_count = 0; + + switch(subghz->gen_info->type) { + case GenFaacSLH: + byte_ptr = (uint8_t*)&subghz->gen_info->faac_slh.seed; + byte_count = sizeof(subghz->gen_info->faac_slh.seed); + break; + case GenKeeloqBFT: + byte_ptr = (uint8_t*)&subghz->gen_info->keeloq_bft.seed; + byte_count = sizeof(subghz->gen_info->keeloq_bft.seed); + break; + // Not needed for these types + case GenKeeloq: + case GenAlutechAt4n: + case GenSomfyTelis: + case GenNiceFlorS: + case GenSecPlus2: + case GenPhoenixV2: + case GenData: + case GenSecPlus1: + case GenCameAtomo: + default: + furi_crash("Not implemented"); + break; + } + + furi_assert(byte_ptr); + furi_assert(byte_count > 0); + // Setup view ByteInput* byte_input = subghz->byte_input; byte_input_set_header_text(byte_input, "Enter SEED in hex"); @@ -20,8 +50,8 @@ void subghz_scene_set_seed_on_enter(void* context) { subghz_scene_set_seed_byte_input_callback, NULL, subghz, - subghz->secure_data->seed, - 4); + byte_ptr, + byte_count); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); } @@ -29,98 +59,61 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; bool consumed = false; bool generated_protocol = false; - uint32_t fix_part, cnt, seed; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventByteInputDone) { - SetType state = - scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType); + GenInfo gen_info = *subghz->gen_info; - switch(state) { - case SetTypeBFTClone: - 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]; - - cnt = subghz->secure_data->cnt[0] << 8 | subghz->secure_data->cnt[1]; - - seed = subghz->secure_data->seed[0] << 24 | subghz->secure_data->seed[1] << 16 | - subghz->secure_data->seed[2] << 8 | subghz->secure_data->seed[3]; - - generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( - subghz->txrx, - "AM650", - 433920000, - fix_part & 0x0FFFFFFF, - fix_part >> 28, - cnt, - seed, - "BFT"); - - 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); - } - consumed = true; - break; - case SetTypeFaacSLH_Manual_433: - case SetTypeFaacSLH_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]; - - cnt = subghz->secure_data->cnt[0] << 16 | subghz->secure_data->cnt[1] << 8 | - subghz->secure_data->cnt[2]; - - 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 == SetTypeFaacSLH_Manual_433) { + switch(gen_info.type) { + case GenFaacSLH: generated_protocol = subghz_txrx_gen_faac_slh_protocol( subghz->txrx, - "AM650", - 433920000, - fix_part >> 4, - fix_part & 0xf, - (cnt & 0xFFFFF), - seed, - "FAAC_SLH"); - } else if(state == SetTypeFaacSLH_Manual_868) { - generated_protocol = subghz_txrx_gen_faac_slh_protocol( + gen_info.mod, + gen_info.freq, + gen_info.faac_slh.serial, + gen_info.faac_slh.btn, + gen_info.faac_slh.cnt, + gen_info.faac_slh.seed, + gen_info.faac_slh.manuf); + break; + case GenKeeloqBFT: + generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( subghz->txrx, - "AM650", - 868350000, - fix_part >> 4, - fix_part & 0xf, - (cnt & 0xFFFFF), - seed, - "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); - } - consumed = true; - break; - - default: - break; + gen_info.mod, + gen_info.freq, + gen_info.keeloq_bft.serial, + gen_info.keeloq_bft.btn, + gen_info.keeloq_bft.cnt, + gen_info.keeloq_bft.seed, + gen_info.keeloq_bft.manuf); + break; + // Not needed for these types + case GenKeeloq: + case GenAlutechAt4n: + case GenSomfyTelis: + case GenNiceFlorS: + case GenSecPlus2: + case GenPhoenixV2: + case GenData: + case GenSecPlus1: + case GenCameAtomo: + default: + furi_crash("Not implemented"); + break; } - } - // Reset Seed, Fix, Cnt, Btn in secure data after successful or unsuccessful generation - memset(subghz->secure_data->seed, 0, sizeof(subghz->secure_data->seed)); - memset(subghz->secure_data->cnt, 0, sizeof(subghz->secure_data->cnt)); - memset(subghz->secure_data->fix, 0, sizeof(subghz->secure_data->fix)); - subghz->secure_data->btn = 0x01; + consumed = true; - if(generated_protocol) { - subghz_file_name_clear(subghz); + 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); + } else { + subghz_file_name_clear(subghz); - scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); - return true; + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); + } } } return consumed; diff --git a/applications/main/subghz/scenes/subghz_scene_set_serial.c b/applications/main/subghz/scenes/subghz_scene_set_serial.c new file mode 100644 index 000000000..42d815dd7 --- /dev/null +++ b/applications/main/subghz/scenes/subghz_scene_set_serial.c @@ -0,0 +1,119 @@ +#include "../subghz_i.h" +#include "../helpers/subghz_txrx_create_protocol_key.h" + +#define TAG "SubGhzSetSerial" + +void subghz_scene_set_serial_byte_input_callback(void* context) { + SubGhz* subghz = context; + + view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone); +} + +void subghz_scene_set_serial_on_enter(void* context) { + SubGhz* subghz = context; + + uint8_t* byte_ptr = NULL; + uint8_t byte_count = 0; + + switch(subghz->gen_info->type) { + case GenFaacSLH: + byte_ptr = (uint8_t*)&subghz->gen_info->faac_slh.serial; + byte_count = sizeof(subghz->gen_info->faac_slh.serial); + break; + case GenKeeloq: + byte_ptr = (uint8_t*)&subghz->gen_info->keeloq.serial; + byte_count = sizeof(subghz->gen_info->keeloq.serial); + break; + case GenCameAtomo: + byte_ptr = (uint8_t*)&subghz->gen_info->came_atomo.serial; + byte_count = sizeof(subghz->gen_info->came_atomo.serial); + break; + case GenKeeloqBFT: + byte_ptr = (uint8_t*)&subghz->gen_info->keeloq_bft.serial; + byte_count = sizeof(subghz->gen_info->keeloq_bft.serial); + break; + case GenAlutechAt4n: + byte_ptr = (uint8_t*)&subghz->gen_info->alutech_at_4n.serial; + byte_count = sizeof(subghz->gen_info->alutech_at_4n.serial); + break; + case GenSomfyTelis: + byte_ptr = (uint8_t*)&subghz->gen_info->somfy_telis.serial; + byte_count = sizeof(subghz->gen_info->somfy_telis.serial); + break; + case GenNiceFlorS: + byte_ptr = (uint8_t*)&subghz->gen_info->nice_flor_s.serial; + byte_count = sizeof(subghz->gen_info->nice_flor_s.serial); + break; + case GenSecPlus2: + byte_ptr = (uint8_t*)&subghz->gen_info->sec_plus_2.serial; + byte_count = sizeof(subghz->gen_info->sec_plus_2.serial); + break; + case GenPhoenixV2: + byte_ptr = (uint8_t*)&subghz->gen_info->phoenix_v2.serial; + byte_count = sizeof(subghz->gen_info->phoenix_v2.serial); + break; + // Not needed for these types + case GenData: + case GenSecPlus1: + default: + furi_crash("Not implemented"); + break; + } + + furi_assert(byte_ptr); + furi_assert(byte_count > 0); + + // Setup view + ByteInput* byte_input = subghz->byte_input; + byte_input_set_header_text(byte_input, "Enter SERIAL in hex"); + byte_input_set_result_callback( + byte_input, + subghz_scene_set_serial_byte_input_callback, + NULL, + subghz, + byte_ptr, + byte_count); + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); +} + +bool subghz_scene_set_serial_on_event(void* context, SceneManagerEvent event) { + SubGhz* subghz = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubGhzCustomEventByteInputDone) { + switch(subghz->gen_info->type) { + case GenFaacSLH: + case GenKeeloq: + case GenKeeloqBFT: + case GenAlutechAt4n: + case GenSomfyTelis: + case GenNiceFlorS: + case GenSecPlus2: + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetButton); + break; + case GenCameAtomo: + case GenPhoenixV2: + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetCounter); + break; + // Not needed for these types + case GenData: + case GenSecPlus1: + default: + furi_crash("Not implemented"); + break; + } + + consumed = true; + } + } + return consumed; +} + +void subghz_scene_set_serial_on_exit(void* context) { + SubGhz* subghz = context; + + // Clear view + byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(subghz->byte_input, ""); +} diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 33177b7de..61e5148de 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -1,7 +1,8 @@ #include "../subghz_i.h" #include "../helpers/subghz_txrx_create_protocol_key.h" +#include "../helpers/subghz_gen_info.h" +#include "subghz_scene_start.h" #include -#include #define TAG "SubGhzSetType" @@ -11,9 +12,6 @@ void subghz_scene_set_type_submenu_callback(void* context, uint32_t index) { } static const char* submenu_names[SetTypeMAX] = { - [SetTypeFaacSLH_Manual_868] = "FAAC SLH [Man.] 868MHz", - [SetTypeFaacSLH_Manual_433] = "FAAC SLH [Man.] 433MHz", - [SetTypeBFTClone] = "BFT [Manual] 433MHz", [SetTypeFaacSLH_868] = "FAAC SLH 868MHz", [SetTypeFaacSLH_433] = "FAAC SLH 433MHz", [SetTypeBFTMitto] = "BFT Mitto 433MHz", @@ -104,797 +102,10 @@ void subghz_scene_set_type_on_enter(void* context) { view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdMenu); } -typedef enum { - GenData, - GenFaacSLH, - GenKeeloq, - GenCameAtomo, - GenKeeloqBFT, - GenAlutechAt4n, - GenSomfyTelis, - GenSecPlus1, - GenSecPlus2, - GenPhoenixV2, -} GenType; - -typedef struct { - GenType type; - const char* mod; - uint32_t freq; - union { - struct { - const char* name; - uint64_t key; - uint8_t bits; - uint16_t te; - } data; - struct { - uint32_t serial; - uint8_t btn; - uint8_t cnt; - uint32_t seed; - const char* manuf; - } faac_slh; - struct { - uint32_t serial; - uint8_t btn; - uint8_t cnt; - const char* manuf; - } keeloq; - struct { - uint32_t serial; - uint8_t cnt; - } came_atomo; - struct { - uint32_t serial; - uint8_t btn; - uint8_t cnt; - uint32_t seed; - const char* manuf; - } keeloq_bft; - struct { - uint32_t serial; - uint8_t btn; - uint8_t cnt; - } alutech_at_4n; - struct { - uint32_t serial; - uint8_t btn; - uint8_t cnt; - } somfy_telis; - struct { - uint32_t serial; - uint8_t btn; - uint8_t cnt; - bool nice_one; - } nice_flor_s; - struct { - uint32_t serial; - uint8_t btn; - uint32_t cnt; - } sec_plus_2; - struct { - uint32_t serial; - uint16_t cnt; - } phoenix_v2; - }; -} GenInfo; - -bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; +bool subghz_scene_set_type_generate_protocol_from_infos(SubGhz* subghz) { + GenInfo gen_info = *subghz->gen_info; bool generated_protocol = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event >= SetTypeMAX) { - return false; - } - scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneSetType, event.event); - - if(event.event == SetTypeFaacSLH_Manual_868 || event.event == SetTypeFaacSLH_Manual_433 || - event.event == SetTypeBFTClone) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFix); - return true; - } - - if (event.event == SetTypeNiceFlorS_433_92 || event.event == SetTypeNiceOne_433_92) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetButton); - return true; - } - - uint64_t key = (uint64_t)rand(); - - uint64_t gangqi_key; - subghz_txrx_gen_serial_gangqi(&gangqi_key); - - uint64_t marantec_key; - subghz_txrx_gen_key_marantec(&marantec_key); - - GenInfo gen_info = {0}; - switch(event.event) { - case SetTypePricenton433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_PRINCETON_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 400}; - break; - case SetTypePricenton315: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 315000000, - .data.name = SUBGHZ_PROTOCOL_PRINCETON_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 400}; - break; - case SetTypeNiceFlo12bit: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_NICE_FLO_NAME, - .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 - .data.bits = 12, - .data.te = 0}; - break; - case SetTypeNiceFlo24bit: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_NICE_FLO_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeCAME12bit: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_CAME_NAME, - .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 - .data.bits = 12, - .data.te = 0}; - break; - case SetTypeCAME24bit: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_CAME_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeCAME12bit868: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 868350000, - .data.name = SUBGHZ_PROTOCOL_CAME_NAME, - .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 - .data.bits = 12, - .data.te = 0}; - break; - case SetTypeCAME24bit868: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 868350000, - .data.name = SUBGHZ_PROTOCOL_CAME_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeRoger_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_ROGER_NAME, - .data.key = (key & 0xFFFF000) | 0x0000101, // button code 0x1 and (crc?) is 0x01 - .data.bits = 28, - .data.te = 0}; - break; - case SetTypeLinear_300_00: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 300000000, - .data.name = SUBGHZ_PROTOCOL_LINEAR_NAME, - .data.key = (key & 0x3FF), - .data.bits = 10, - .data.te = 0}; - break; - case SetTypeBETT_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_BETT_NAME, - .data.key = (key & 0x0000FFF0), - .data.bits = 18, - .data.te = 0}; - break; - case SetTypeCAMETwee: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_CAME_TWEE_NAME, - .data.key = 0x003FFF7200000000 | ((key & 0x0FFFFFF0) ^ 0xE0E0E0EE), // ???? - .data.bits = 54, - .data.te = 0}; - break; - case SetTypeGateTX: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_GATE_TX_NAME, // btn 0xF, 0xC, 0xA, 0x6 (?) - .data.key = subghz_protocol_blocks_reverse_key((key & 0x00F0FF00) | 0xF0040, 24), - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeGangQi_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = - SUBGHZ_PROTOCOL_GANGQI_NAME, // Add button 0xD arm and crc sum to the end - .data.key = gangqi_key, - .data.bits = 34, - .data.te = 0}; - break; - case SetTypeHollarm_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_HOLLARM_NAME, // Add button 0x2 and crc sum to the end - .data.key = (key & 0x000FFF0000) | 0xF0B0002200 | - ((((((key & 0x000FFF0000) | 0xF0B0002200) >> 32) & 0xFF) + - ((((key & 0x000FFF0000) | 0xF0B0002200) >> 24) & 0xFF) + - ((((key & 0x000FFF0000) | 0xF0B0002200) >> 16) & 0xFF) + - ((((key & 0x000FFF0000) | 0xF0B0002200) >> 8) & 0xFF)) & - 0xFF), - .data.bits = 42, - .data.te = 0}; - break; - case SetTypeReversRB2_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_REVERSRB2_NAME, // 64bits no buttons - .data.key = (key & 0x00000FFFFFFFF000) | 0xFFFFF00000000000 | 0x0000000000000A00, - .data.bits = 64, - .data.te = 0}; - break; - case SetTypeMarantec24_868: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 868350000, - .data.name = SUBGHZ_PROTOCOL_MARANTEC24_NAME, // Add button code 0x8 to the end - .data.key = (key & 0xFFFFF0) | 0x000008, - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeMarantec_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = - SUBGHZ_PROTOCOL_MARANTEC_NAME, // Button code is 0x4 and crc sum to the end - .data.key = marantec_key, - .data.bits = 49, - .data.te = 0}; - break; - case SetTypeMarantec_868: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 868350000, - .data.name = - SUBGHZ_PROTOCOL_MARANTEC_NAME, // Button code is 0x4 and crc sum to the end - .data.key = marantec_key, - .data.bits = 49, - .data.te = 0}; - break; - case SetTypeFaacSLH_433: - gen_info = (GenInfo){ - .type = GenFaacSLH, - .mod = "AM650", - .freq = 433920000, - .faac_slh.serial = ((key & 0x00FFFFF0) | 0xA0000006) >> 4, - .faac_slh.btn = 0x06, - .faac_slh.cnt = 0x02, - .faac_slh.seed = key, - .faac_slh.manuf = "FAAC_SLH"}; - break; - case SetTypeFaacSLH_868: - gen_info = (GenInfo){ - .type = GenFaacSLH, - .mod = "AM650", - .freq = 868350000, - .faac_slh.serial = ((key & 0x00FFFFF0) | 0xA0000006) >> 4, - .faac_slh.btn = 0x06, - .faac_slh.cnt = 0x02, - .faac_slh.seed = (key & 0x0FFFFFFF), - .faac_slh.manuf = "FAAC_SLH"}; - break; - case SetTypeBeninca433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFF00) | 0x00800080, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Beninca"}; - break; - case SetTypeBeninca868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 868350000, - .keeloq.serial = (key & 0x000FFF00) | 0x00800080, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Beninca"}; - break; - case SetTypeComunello433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x08, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Comunello"}; - break; - case SetTypeComunello868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 868460000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x08, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Comunello"}; - break; - case SetTypeAllmatic433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x00FFFF00) | 0x01000011, - .keeloq.btn = 0x0C, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Beninca"}; - break; - case SetTypeAllmatic868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 868350000, - .keeloq.serial = (key & 0x00FFFF00) | 0x01000011, - .keeloq.btn = 0x0C, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Beninca"}; - break; - case SetTypeCenturion433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0000FFFF), - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Centurion"}; - break; - case SetTypeMonarch433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0000FFFF), - .keeloq.btn = 0x0A, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Monarch"}; - break; - case SetTypeJollyMotors433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFFFF), - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Jolly_Motors"}; - break; - case SetTypeElmesElectronic: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x00FFFFFF) | 0x02000000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Elmes_Poland"}; - break; - case SetTypeANMotorsAT4: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFFFF) | 0x04700000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x21, - .keeloq.manuf = "AN-Motors"}; - break; - case SetTypeAprimatic: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFFFF) | 0x00600000, - .keeloq.btn = 0x08, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Aprimatic"}; - break; - case SetTypeGibidi433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Gibidi"}; - break; - case SetTypeGSN: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "GSN"}; - break; - case SetTypeIronLogic: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFF0, - .keeloq.btn = 0x04, - .keeloq.cnt = 0x05, - .keeloq.manuf = "IronLogic"}; - break; - case SetTypeStilmatic: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Stilmatic"}; - break; - case SetTypeSommer_FM_434: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "FM476", - .freq = 434420000, - .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Sommer(fsk476)"}; - break; - case SetTypeSommer_FM_868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "FM476", - .freq = 868800000, - .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Sommer(fsk476)"}; - break; - case SetTypeSommer_FM238_434: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "FM238", - .freq = 434420000, - .keeloq.serial = key & 0x0000FFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Sommer(fsk476)"}; - break; - case SetTypeSommer_FM238_868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "FM238", - .freq = 868800000, - .keeloq.serial = key & 0x0000FFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Sommer(fsk476)"}; - break; - case SetTypeDTMNeo433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x000FFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x05, - .keeloq.manuf = "DTM_Neo"}; - break; - case SetTypeCAMESpace: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x04, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Came_Space"}; - break; - case SetTypeCameAtomo433: - gen_info = (GenInfo){ - .type = GenCameAtomo, - .mod = "AM650", - .freq = 433920000, - .came_atomo.serial = (key & 0x0FFFFFFF) | 0x10000000, - .came_atomo.cnt = 0x03}; - break; - case SetTypeCameAtomo868: - gen_info = (GenInfo){ - .type = GenCameAtomo, - .mod = "AM650", - .freq = 868350000, - .came_atomo.serial = (key & 0x0FFFFFFF) | 0x10000000, - .came_atomo.cnt = 0x03}; - break; - case SetTypeBFTMitto: - gen_info = (GenInfo){ - .type = GenKeeloqBFT, - .mod = "AM650", - .freq = 433920000, - .keeloq_bft.serial = key & 0x000FFFFF, - .keeloq_bft.btn = 0x02, - .keeloq_bft.cnt = 0x02, - .keeloq_bft.seed = key & 0x000FFFFF, - .keeloq_bft.manuf = "BFT"}; - break; - case SetTypeAlutechAT4N: - gen_info = (GenInfo){ - .type = GenAlutechAt4n, - .mod = "AM650", - .freq = 433920000, - .alutech_at_4n.serial = (key & 0x000FFFFF) | 0x00100000, - .alutech_at_4n.btn = 0x44, - .alutech_at_4n.cnt = 0x03}; - break; - case SetTypeSomfyTelis: - gen_info = (GenInfo){ - .type = GenSomfyTelis, - .mod = "AM650", - .freq = 433420000, - .somfy_telis.serial = key & 0x00FFFFFF, - .somfy_telis.btn = 0x02, - .somfy_telis.cnt = 0x03}; - break; - case SetTypeMotorline433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Motorline"}; - break; - case SetTypeDoorHan_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "DoorHan"}; - break; - case SetTypeDoorHan_315_00: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 315000000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "DoorHan"}; - break; - case SetTypeNiceSmilo_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "NICE_Smilo"}; - break; - case SetTypeNiceMHouse_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x09, - .keeloq.cnt = 0x03, - .keeloq.manuf = "NICE_MHOUSE"}; - break; - case SetTypeDeaMio433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0FFFF000) | 0x00000869, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Dea_Mio"}; - break; - case SetTypeGeniusBravo433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x06, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Genius_Bravo"}; - break; - case SetTypeJCM_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "JCM_Tech"}; - break; - case SetTypeNovoferm_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0000FFFF) | 0x018F0000, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Novoferm"}; - break; - case SetTypeHormannEcoStar_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFFFF) | 0x02200000, - .keeloq.btn = 0x04, - .keeloq.cnt = 0x03, - .keeloq.manuf = "EcoStar"}; - break; - case SetTypeFAACRCXT_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0000FFFF) | 0x00100000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "FAAC_RC,XT"}; - break; - case SetTypeFAACRCXT_868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 868350000, - .keeloq.serial = (key & 0x0000FFFF) | 0x00100000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "FAAC_RC,XT"}; - break; - case SetTypeNormstahl_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0000FFFF, - .keeloq.btn = 0x04, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Normstahl"}; - break; - case SetTypeHCS101_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x000FFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "HCS101"}; - break; - case SetTypeSecPlus_v1_315_00: - gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 315000000}; - break; - case SetTypeSecPlus_v1_390_00: - gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 390000000}; - break; - case SetTypeSecPlus_v1_433_00: - gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 433920000}; - break; - case SetTypeSecPlus_v2_310_00: - gen_info = (GenInfo){ - .type = GenSecPlus2, - .mod = "AM650", - .freq = 310000000, - .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing - .sec_plus_2.btn = 0x68, - .sec_plus_2.cnt = 0xE500000}; - break; - case SetTypeSecPlus_v2_315_00: - gen_info = (GenInfo){ - .type = GenSecPlus2, - .mod = "AM650", - .freq = 315000000, - .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing - .sec_plus_2.btn = 0x68, - .sec_plus_2.cnt = 0xE500000}; - break; - case SetTypeSecPlus_v2_390_00: - gen_info = (GenInfo){ - .type = GenSecPlus2, - .mod = "AM650", - .freq = 390000000, - .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing - .sec_plus_2.btn = 0x68, - .sec_plus_2.cnt = 0xE500000}; - break; - case SetTypeSecPlus_v2_433_00: - gen_info = (GenInfo){ - .type = GenSecPlus2, - .mod = "AM650", - .freq = 433920000, - .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing - .sec_plus_2.btn = 0x68, - .sec_plus_2.cnt = 0xE500000}; - break; - case SetTypePhoenix_V2_433: - gen_info = (GenInfo){ - .type = GenPhoenixV2, - .mod = "AM650", - .freq = 433920000, - .phoenix_v2.serial = (key & 0x0FFFFFFF) | 0xB0000000, - .phoenix_v2.cnt = 0x025D}; - break; - default: - furi_crash("Not implemented"); - break; - } - - switch(gen_info.type) { + switch(gen_info.type) { case GenData: if(gen_info.data.te) { generated_protocol = subghz_txrx_gen_data_protocol_and_te( @@ -973,6 +184,16 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { gen_info.somfy_telis.btn, gen_info.somfy_telis.cnt); break; + case GenNiceFlorS: + generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.nice_flor_s.serial, + gen_info.nice_flor_s.btn, + gen_info.nice_flor_s.cnt, + gen_info.nice_flor_s.nice_one); + break; case GenSecPlus1: generated_protocol = subghz_txrx_gen_secplus_v1_protocol(subghz->txrx, gen_info.mod, gen_info.freq); @@ -997,15 +218,54 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { default: furi_crash("Not implemented"); break; - } + } - if(generated_protocol) { - subghz_file_name_clear(subghz); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); - } else { - furi_string_set( - subghz->error_str, "Function requires\nan SD card with\nfresh databases."); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); + if(generated_protocol) { + subghz_file_name_clear(subghz); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); + } else { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); + } + return generated_protocol; +} + +bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { + SubGhz* subghz = context; + bool generated_protocol = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event >= SetTypeMAX) { + return false; + } + scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneSetType, event.event); + + subghz_gen_info_reset(subghz->gen_info); + subghz_scene_set_type_fill_generation_infos(subghz->gen_info, event.event); + + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart) == SubmenuIndexAddManually) { + generated_protocol = subghz_scene_set_type_generate_protocol_from_infos(subghz); + } else if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart) == SubmenuIndexAddManuallyAdvanced) { + switch(subghz->gen_info->type) { + case GenData: // Key (u64) + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetKey); + break; + case GenSecPlus1: // None + return subghz_txrx_gen_secplus_v1_protocol(subghz->txrx, subghz->gen_info->mod, subghz->gen_info->freq); + case GenFaacSLH: // Serial (u32), Button (u8), Counter (u8), Seed (u32) + case GenKeeloq: // Serial (u32), Button (u8), Counter (u8) + case GenCameAtomo: // Serial (u32), Counter (u8) + case GenKeeloqBFT: // Serial (u32), Button (u8), Counter (u8), Seed (u32) + case GenAlutechAt4n: // Serial (u32), Button (u8), Counter (u8) + case GenSomfyTelis: // Serial (u32), Button (u8), Counter (u8) + case GenNiceFlorS: // Serial (u32), Button (u8), Counter (u8) + case GenSecPlus2: // Serial (u32), Button (u8), Counter (u32) + case GenPhoenixV2: // Serial (u32), Counter (u16) + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetSerial); + break; + } + return true; } } diff --git a/applications/main/subghz/scenes/subghz_scene_start.c b/applications/main/subghz/scenes/subghz_scene_start.c index fd59f48a4..6046b2c6d 100644 --- a/applications/main/subghz/scenes/subghz_scene_start.c +++ b/applications/main/subghz/scenes/subghz_scene_start.c @@ -1,18 +1,9 @@ #include "../subghz_i.h" +#include "subghz_scene_start.h" #include #include -enum SubmenuIndex { - SubmenuIndexRead = 10, - SubmenuIndexSaved, - SubmenuIndexAddManually, - SubmenuIndexFrequencyAnalyzer, - SubmenuIndexReadRAW, - SubmenuIndexExtSettings, - SubmenuIndexRadioSetting, -}; - void subghz_scene_start_submenu_callback(void* context, uint32_t index) { SubGhz* subghz = context; view_dispatcher_send_custom_event(subghz->view_dispatcher, index); @@ -43,7 +34,7 @@ void subghz_scene_start_on_enter(void* context) { submenu_add_item( subghz->submenu, "Add Manually [Advanced]", - SubmenuIndexAddManually, + SubmenuIndexAddManuallyAdvanced, subghz_scene_start_submenu_callback, subghz); submenu_add_item( @@ -94,6 +85,11 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManually); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType); return true; + } else if(event.event == SubmenuIndexAddManuallyAdvanced) { + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManuallyAdvanced); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType); + return true; } else if(event.event == SubmenuIndexFrequencyAnalyzer) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer); diff --git a/applications/main/subghz/scenes/subghz_scene_start.h b/applications/main/subghz/scenes/subghz_scene_start.h new file mode 100644 index 000000000..8e446f0c0 --- /dev/null +++ b/applications/main/subghz/scenes/subghz_scene_start.h @@ -0,0 +1,12 @@ +#pragma once + +enum SubmenuIndex { + SubmenuIndexRead = 10, + SubmenuIndexSaved, + SubmenuIndexAddManually, + SubmenuIndexAddManuallyAdvanced, + SubmenuIndexFrequencyAnalyzer, + SubmenuIndexReadRAW, + SubmenuIndexExtSettings, + SubmenuIndexRadioSetting, +}; diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 83e68229b..f8877551d 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -213,7 +213,7 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); - subghz->secure_data = malloc(sizeof(SecureData)); + subghz->gen_info = malloc(sizeof(GenInfo)); if(!alloc_for_tx_only) { subghz->ignore_filter = subghz->last_settings->ignore_filter; @@ -319,7 +319,7 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) { subghz_history_free(subghz->history); } - free(subghz->secure_data); + free(subghz->gen_info); //TxRx subghz_txrx_free(subghz->txrx); diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index 6160c48c3..10a2ce9f8 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -1,6 +1,7 @@ #pragma once #include "helpers/subghz_types.h" +#include "helpers/subghz_gen_info.h" #include #include "subghz.h" #include "views/receiver.h" @@ -44,13 +45,6 @@ #define SUBGHZ_RAW_THRESHOLD_MIN (-90.0f) #define SUBGHZ_MEASURE_LOADING false -typedef struct { - uint8_t fix[4]; - uint8_t cnt[4]; - uint8_t seed[4]; - uint8_t btn; -} SecureData; - struct SubGhz { Gui* gui; NotificationApp* notifications; @@ -89,7 +83,7 @@ struct SubGhz { FuriString* error_str; SubGhzLock lock; - SecureData* secure_data; + GenInfo* gen_info; SubGhzFileEncoderWorker* decode_raw_file_worker_encoder; From 6a2f0622346d384465d19c7ff423aac227b66814 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 03:43:36 +0300 Subject: [PATCH 04/14] OFW PR. 4251 CLI: Fix long delay with quick connect/disconnect by WillyJL --- applications/services/cli/cli_vcp.c | 13 +++++-------- lib/toolbox/cli/shell/cli_shell.c | 16 +++++++++++----- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/applications/services/cli/cli_vcp.c b/applications/services/cli/cli_vcp.c index 1f9c77b08..9db1bec43 100644 --- a/applications/services/cli/cli_vcp.c +++ b/applications/services/cli/cli_vcp.c @@ -218,6 +218,11 @@ static void cli_vcp_internal_event_happened(FuriEventLoopObject* object, void* c pipe_detach_from_event_loop(cli_vcp->own_pipe); pipe_free(cli_vcp->own_pipe); cli_vcp->own_pipe = NULL; + + // wait for shell to stop + cli_shell_join(cli_vcp->shell); + cli_shell_free(cli_vcp->shell); + pipe_free(cli_vcp->shell_pipe); break; } @@ -226,14 +231,6 @@ static void cli_vcp_internal_event_happened(FuriEventLoopObject* object, void* c FURI_LOG_D(TAG, "Connected"); cli_vcp->is_connected = true; - // wait for previous shell to stop - furi_check(!cli_vcp->own_pipe); - if(cli_vcp->shell) { - cli_shell_join(cli_vcp->shell); - cli_shell_free(cli_vcp->shell); - pipe_free(cli_vcp->shell_pipe); - } - // start shell thread PipeSideBundle bundle = pipe_alloc(VCP_BUF_SIZE, 1); cli_vcp->own_pipe = bundle.alices_side; diff --git a/lib/toolbox/cli/shell/cli_shell.c b/lib/toolbox/cli/shell/cli_shell.c index 7a4c7ec1f..b2648d127 100644 --- a/lib/toolbox/cli/shell/cli_shell.c +++ b/lib/toolbox/cli/shell/cli_shell.c @@ -16,7 +16,8 @@ #define TAG "CliShell" -#define ANSI_TIMEOUT_MS 10 +#define ANSI_TIMEOUT_MS 10 +#define TRANSIENT_SESSION_WINDOW_MS 100 typedef enum { CliShellComponentCompletions, @@ -415,10 +416,15 @@ static void cli_shell_deinit(CliShell* shell) { static int32_t cli_shell_thread(void* context) { CliShell* shell = context; - // Sometimes, the other side closes the pipe even before our thread is started. Although the - // rest of the code will eventually find this out if this check is removed, there's no point in - // wasting time. - if(pipe_state(shell->pipe) == PipeStateBroken) return 0; + // Sometimes, the other side (e.g. qFlipper) closes the pipe even before our thread is started. + // Although the rest of the code will eventually find this out if this check is removed, + // there's no point in wasting time. This gives qFlipper a chance to quickly close and re-open + // the session. + const size_t delay_step = 10; + for(size_t i = 0; i < TRANSIENT_SESSION_WINDOW_MS / delay_step; i++) { + furi_delay_ms(delay_step); + if(pipe_state(shell->pipe) == PipeStateBroken) return 0; + } cli_shell_init(shell); FURI_LOG_D(TAG, "Started"); From fb41c6c20c4e79838557e88bd542ad09515d6ab7 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 04:28:22 +0300 Subject: [PATCH 05/14] Input Settings: Add Vibro Trigger option by 956MB & WillyJL --- applications/services/input/input.c | 5 +- applications/services/input/input_settings.c | 21 ++++++++- applications/services/input/input_settings.h | 1 + .../input_settings_app/input_settings_app.c | 46 +++++++++++++++++-- 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/applications/services/input/input.c b/applications/services/input/input.c index c3f7c264f..a054f852a 100644 --- a/applications/services/input/input.c +++ b/applications/services/input/input.c @@ -162,13 +162,14 @@ int32_t input_srv(void* p) { event.type = pin_states[i].state ? InputTypePress : InputTypeRelease; furi_pubsub_publish(event_pubsub, &event); // vibro signal if user setup vibro touch level in Settings-Input. - if(settings->vibro_touch_level) { + if(settings->vibro_touch_level && + ((1 << event.type) & settings->vibro_touch_trigger_mask)) { //delay 1 ticks for compatibility with rgb_backlight_mod furi_delay_tick(1); furi_hal_vibro_on(true); furi_delay_tick(settings->vibro_touch_level); furi_hal_vibro_on(false); - }; + } } } diff --git a/applications/services/input/input_settings.c b/applications/services/input/input_settings.c index f1f18ba3d..1b63b62c8 100644 --- a/applications/services/input/input_settings.c +++ b/applications/services/input/input_settings.c @@ -1,16 +1,20 @@ #include "input_settings.h" #include "input_settings_filename.h" +#include "input.h" #include #include #define TAG "InputSettings" -#define INPUT_SETTINGS_VER (1) // version nnumber +#define INPUT_SETTINGS_VER (2) // version number #define INPUT_SETTINGS_PATH INT_PATH(INPUT_SETTINGS_FILE_NAME) #define INPUT_SETTINGS_MAGIC (0x29) +#define INPUT_SETTINGS_VIBRO_TOUCH_TRIGGER_MASK_DEFAULT \ + ((1 << InputTypePress) | (1 << InputTypeRelease)) + void input_settings_load(InputSettings* settings) { furi_assert(settings); @@ -22,6 +26,18 @@ void input_settings_load(InputSettings* settings) { uint8_t version; if(!saved_struct_get_metadata(INPUT_SETTINGS_PATH, NULL, &version, NULL)) break; + if(version == 1) { + struct { + uint8_t vibro_touch_level; + } v1; + if(!saved_struct_load(INPUT_SETTINGS_PATH, &v1, sizeof(v1), INPUT_SETTINGS_MAGIC, 1)) + break; + settings->vibro_touch_level = v1.vibro_touch_level; + settings->vibro_touch_trigger_mask = INPUT_SETTINGS_VIBRO_TOUCH_TRIGGER_MASK_DEFAULT; + success = true; + break; + } + // if config actual version - load it directly if(version == INPUT_SETTINGS_VER) { success = saved_struct_load( @@ -38,7 +54,8 @@ void input_settings_load(InputSettings* settings) { if(!success) { FURI_LOG_W(TAG, "Failed to load file, using defaults"); memset(settings, 0, sizeof(InputSettings)); - input_settings_save(settings); + settings->vibro_touch_trigger_mask = INPUT_SETTINGS_VIBRO_TOUCH_TRIGGER_MASK_DEFAULT; + // input_settings_save(settings); } } diff --git a/applications/services/input/input_settings.h b/applications/services/input/input_settings.h index 376e8e226..87ebca5ea 100644 --- a/applications/services/input/input_settings.h +++ b/applications/services/input/input_settings.h @@ -4,6 +4,7 @@ typedef struct { uint8_t vibro_touch_level; + uint8_t vibro_touch_trigger_mask; } InputSettings; #ifdef __cplusplus diff --git a/applications/settings/input_settings_app/input_settings_app.c b/applications/settings/input_settings_app/input_settings_app.c index 4f3e101da..035a84e79 100644 --- a/applications/settings/input_settings_app/input_settings_app.c +++ b/applications/settings/input_settings_app/input_settings_app.c @@ -3,7 +3,9 @@ #define TAG "InputSettingsApp" -#define VIBRO_TOUCH_LEVEL_COUNT 10 +#define VIBRO_TOUCH_LEVEL_COUNT 10 +#define VIBRO_TOUCH_TRIGGER_MASK_COUNT 3 + // vibro touch human readable levels const char* const vibro_touch_level_text[VIBRO_TOUCH_LEVEL_COUNT] = { "OFF", @@ -20,21 +22,45 @@ const char* const vibro_touch_level_text[VIBRO_TOUCH_LEVEL_COUNT] = { // vibro touch levels tick valies delay const uint32_t vibro_touch_level_value[VIBRO_TOUCH_LEVEL_COUNT] = {0, 13, 16, 19, 21, 24, 27, 30, 33, 36}; +// vibro touch trigger mask human readable values +const char* const vibro_touch_trigger_mask_text[VIBRO_TOUCH_TRIGGER_MASK_COUNT] = { + "Press", + "Release", + "Both", +}; +// vibro touch trigger mask values +const uint32_t vibro_touch_trigger_mask_value[VIBRO_TOUCH_TRIGGER_MASK_COUNT] = { + (1 << InputTypePress), + (1 << InputTypeRelease), + (1 << InputTypePress) | (1 << InputTypeRelease), +}; static void input_settings_vibro_touch_level_changed(VariableItem* item) { uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, vibro_touch_level_text[index]); - //change settings to selected InputSettingsApp* app = variable_item_get_context(item); app->settings->vibro_touch_level = vibro_touch_level_value[index]; - // use RECORD for acces to input service instance and set settings + // use RECORD for access to input service instance and set settings InputSettings* service_settings = furi_record_open(RECORD_INPUT_SETTINGS); service_settings->vibro_touch_level = vibro_touch_level_value[index]; furi_record_close(RECORD_INPUT_SETTINGS); } +static void input_settings_vibro_touch_trigger_mask_changed(VariableItem* item) { + uint8_t index = variable_item_get_current_value_index(item); + variable_item_set_current_value_text(item, vibro_touch_trigger_mask_text[index]); + + InputSettingsApp* app = variable_item_get_context(item); + app->settings->vibro_touch_trigger_mask = vibro_touch_trigger_mask_value[index]; + + // use RECORD for access to input service instance and set settings + InputSettings* service_settings = furi_record_open(RECORD_INPUT_SETTINGS); + service_settings->vibro_touch_trigger_mask = vibro_touch_trigger_mask_value[index]; + furi_record_close(RECORD_INPUT_SETTINGS); +} + static uint32_t input_settings_app_exit(void* context) { UNUSED(context); return VIEW_NONE; @@ -66,6 +92,20 @@ InputSettingsApp* input_settings_app_alloc(void) { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, vibro_touch_level_text[value_index]); + item = variable_item_list_add( + app->variable_item_list, + "Vibro Trigger", + VIBRO_TOUCH_TRIGGER_MASK_COUNT, + input_settings_vibro_touch_trigger_mask_changed, + app); + + value_index = value_index_uint32( + app->settings->vibro_touch_trigger_mask, + vibro_touch_trigger_mask_value, + VIBRO_TOUCH_TRIGGER_MASK_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, vibro_touch_trigger_mask_text[value_index]); + // create and setup view and view dispatcher app->view_dispatcher = view_dispatcher_alloc(); view_dispatcher_set_event_callback_context(app->view_dispatcher, app); From 3b7d837e48d6e01cb14f791f6b5234de935bb85e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 04:30:01 +0300 Subject: [PATCH 06/14] fmt --- applications/services/input/input_settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/services/input/input_settings.c b/applications/services/input/input_settings.c index 1b63b62c8..67f5ac608 100644 --- a/applications/services/input/input_settings.c +++ b/applications/services/input/input_settings.c @@ -55,7 +55,7 @@ void input_settings_load(InputSettings* settings) { FURI_LOG_W(TAG, "Failed to load file, using defaults"); memset(settings, 0, sizeof(InputSettings)); settings->vibro_touch_trigger_mask = INPUT_SETTINGS_VIBRO_TOUCH_TRIGGER_MASK_DEFAULT; - // input_settings_save(settings); + //input_settings_save(settings); } } From 59a823cbcd14a65027a5efc767790c2ac14190b1 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 04:32:54 +0300 Subject: [PATCH 07/14] BT Remote: Add Rename Option by aaronjamt & WillyJL --- .../hid_app/helpers/ble_hid_ext_profile.c | 36 ++++++++ .../hid_app/helpers/ble_hid_ext_profile.h | 14 ++++ applications/system/hid_app/hid.c | 70 +++++++++++++++- applications/system/hid_app/hid.h | 6 +- .../system/hid_app/scenes/hid_scene_config.h | 1 + .../system/hid_app/scenes/hid_scene_rename.c | 82 +++++++++++++++++++ .../system/hid_app/scenes/hid_scene_start.c | 9 ++ applications/system/hid_app/views.h | 1 + .../system/hid_app/views/hid_music_macos.h | 3 +- applications/system/hid_app/views/hid_ptt.c | 58 ++++++++++++- 10 files changed, 274 insertions(+), 6 deletions(-) create mode 100644 applications/system/hid_app/helpers/ble_hid_ext_profile.c create mode 100644 applications/system/hid_app/helpers/ble_hid_ext_profile.h create mode 100644 applications/system/hid_app/scenes/hid_scene_rename.c diff --git a/applications/system/hid_app/helpers/ble_hid_ext_profile.c b/applications/system/hid_app/helpers/ble_hid_ext_profile.c new file mode 100644 index 000000000..f1858318e --- /dev/null +++ b/applications/system/hid_app/helpers/ble_hid_ext_profile.c @@ -0,0 +1,36 @@ +#include "ble_hid_ext_profile.h" + +#include + +static FuriHalBleProfileBase* ble_profile_hid_ext_start(FuriHalBleProfileParams profile_params) { + UNUSED(profile_params); + + return ble_profile_hid->start(NULL); +} + +static void ble_profile_hid_ext_stop(FuriHalBleProfileBase* profile) { + ble_profile_hid->stop(profile); +} + +static void + ble_profile_hid_ext_get_config(GapConfig* config, FuriHalBleProfileParams profile_params) { + furi_check(config); + furi_check(profile_params); + BleProfileHidExtParams* hid_ext_profile_params = profile_params; + + // Setup config with basic profile + ble_profile_hid->get_gap_config(config, NULL); + + if(hid_ext_profile_params->name[0] != '\0') { + // Set advertise name (skip first byte which is the ADV type) + strlcpy(config->adv_name + 1, hid_ext_profile_params->name, sizeof(config->adv_name) - 1); + } +} + +static const FuriHalBleProfileTemplate profile_callbacks = { + .start = ble_profile_hid_ext_start, + .stop = ble_profile_hid_ext_stop, + .get_gap_config = ble_profile_hid_ext_get_config, +}; + +const FuriHalBleProfileTemplate* ble_profile_hid_ext = &profile_callbacks; diff --git a/applications/system/hid_app/helpers/ble_hid_ext_profile.h b/applications/system/hid_app/helpers/ble_hid_ext_profile.h new file mode 100644 index 000000000..fc0bdbb89 --- /dev/null +++ b/applications/system/hid_app/helpers/ble_hid_ext_profile.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +/** + * Optional arguments to pass along with profile template as + * FuriHalBleProfileParams for tuning profile behavior + **/ +typedef struct { + char name[FURI_HAL_BT_ADV_NAME_LENGTH]; /**< Full device name */ +} BleProfileHidExtParams; + +/** Hid Keyboard Profile descriptor */ +extern const FuriHalBleProfileTemplate* ble_profile_hid_ext; diff --git a/applications/system/hid_app/hid.c b/applications/system/hid_app/hid.c index e297e0738..00c4ee666 100644 --- a/applications/system/hid_app/hid.c +++ b/applications/system/hid_app/hid.c @@ -4,9 +4,14 @@ #include "views.h" #include #include +#include #define TAG "HidApp" +#define HID_BT_CFG_PATH APP_DATA_PATH(".bt_hid.cfg") +#define HID_BT_CFG_FILE_TYPE "Flipper BT Remote Settings File" +#define HID_BT_CFG_VERSION 1 + bool hid_custom_event_callback(void* context, uint32_t event) { furi_assert(context); Hid* app = context; @@ -33,6 +38,60 @@ void bt_hid_remove_pairing(Hid* app) { furi_hal_bt_start_advertising(); } +static void bt_hid_load_cfg(Hid* app) { + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* fff = flipper_format_file_alloc(storage); + bool loaded = false; + + FuriString* temp_str = furi_string_alloc(); + uint32_t temp_uint = 0; + + do { + if(!flipper_format_file_open_existing(fff, HID_BT_CFG_PATH)) break; + + if(!flipper_format_read_header(fff, temp_str, &temp_uint)) break; + if((strcmp(furi_string_get_cstr(temp_str), HID_BT_CFG_FILE_TYPE) != 0) || + (temp_uint != HID_BT_CFG_VERSION)) + break; + + if(flipper_format_read_string(fff, "name", temp_str)) { + strlcpy( + app->ble_hid_cfg.name, + furi_string_get_cstr(temp_str), + sizeof(app->ble_hid_cfg.name)); + } else { + flipper_format_rewind(fff); + } + + loaded = true; + } while(0); + + furi_string_free(temp_str); + + flipper_format_free(fff); + furi_record_close(RECORD_STORAGE); + + if(!loaded) { + app->ble_hid_cfg.name[0] = '\0'; + } +} + +void bt_hid_save_cfg(Hid* app) { + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* fff = flipper_format_file_alloc(storage); + + if(flipper_format_file_open_always(fff, HID_BT_CFG_PATH)) { + do { + if(!flipper_format_write_header_cstr(fff, HID_BT_CFG_FILE_TYPE, HID_BT_CFG_VERSION)) + break; + if(!flipper_format_write_string_cstr(fff, "name", app->ble_hid_cfg.name)) break; + } while(0); + } + + flipper_format_free(fff); + furi_record_close(RECORD_STORAGE); +} + static void bt_hid_connection_status_changed_callback(BtStatus status, void* context) { furi_assert(context); Hid* hid = context; @@ -89,6 +148,11 @@ Hid* hid_alloc() { app->dialog = dialog_ex_alloc(); view_dispatcher_add_view(app->view_dispatcher, HidViewDialog, dialog_ex_get_view(app->dialog)); + // Text input + app->text_input = text_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, HidViewTextInput, text_input_get_view(app->text_input)); + // Popup view app->popup = popup_alloc(); view_dispatcher_add_view(app->view_dispatcher, HidViewPopup, popup_get_view(app->popup)); @@ -177,6 +241,8 @@ void hid_free(Hid* app) { submenu_free(app->submenu); view_dispatcher_remove_view(app->view_dispatcher, HidViewDialog); dialog_ex_free(app->dialog); + view_dispatcher_remove_view(app->view_dispatcher, HidViewTextInput); + text_input_free(app->text_input); view_dispatcher_remove_view(app->view_dispatcher, HidViewPopup); popup_free(app->popup); view_dispatcher_remove_view(app->view_dispatcher, HidViewKeynote); @@ -266,7 +332,9 @@ int32_t hid_ble_app(void* p) { furi_record_close(RECORD_STORAGE); - app->ble_hid_profile = bt_profile_start(app->bt, ble_profile_hid, NULL); + bt_hid_load_cfg(app); + + app->ble_hid_profile = bt_profile_start(app->bt, ble_profile_hid_ext, &app->ble_hid_cfg); furi_check(app->ble_hid_profile); diff --git a/applications/system/hid_app/hid.h b/applications/system/hid_app/hid.h index ac565217a..e314c005c 100644 --- a/applications/system/hid_app/hid.h +++ b/applications/system/hid_app/hid.h @@ -5,7 +5,7 @@ #include #include -#include +#include "helpers/ble_hid_ext_profile.h" #include #include @@ -18,6 +18,7 @@ #include #include #include +#include #include "views/hid_keynote.h" #include "views/hid_keyboard.h" #include "views/hid_numpad.h" @@ -40,6 +41,7 @@ typedef struct Hid Hid; struct Hid { FuriHalBleProfileBase* ble_hid_profile; + BleProfileHidExtParams ble_hid_cfg; Bt* bt; Gui* gui; NotificationApp* notifications; @@ -47,6 +49,7 @@ struct Hid { SceneManager* scene_manager; Submenu* submenu; DialogEx* dialog; + TextInput* text_input; Popup* popup; HidKeynote* hid_keynote; HidKeyboard* hid_keyboard; @@ -64,6 +67,7 @@ struct Hid { }; void bt_hid_remove_pairing(Hid* app); +void bt_hid_save_cfg(Hid* app); void hid_hal_keyboard_press(Hid* instance, uint16_t event); void hid_hal_keyboard_release(Hid* instance, uint16_t event); diff --git a/applications/system/hid_app/scenes/hid_scene_config.h b/applications/system/hid_app/scenes/hid_scene_config.h index d18b15558..2064c65b1 100644 --- a/applications/system/hid_app/scenes/hid_scene_config.h +++ b/applications/system/hid_app/scenes/hid_scene_config.h @@ -1,3 +1,4 @@ ADD_SCENE(hid, start, Start) ADD_SCENE(hid, main, Main) ADD_SCENE(hid, unpair, Unpair) +ADD_SCENE(hid, rename, Rename) diff --git a/applications/system/hid_app/scenes/hid_scene_rename.c b/applications/system/hid_app/scenes/hid_scene_rename.c new file mode 100644 index 000000000..983c7d927 --- /dev/null +++ b/applications/system/hid_app/scenes/hid_scene_rename.c @@ -0,0 +1,82 @@ +#include "../hid.h" +#include "../views.h" +#include "hid_icons.h" + +enum HidSceneRenameEvent { + HidSceneRenameEventTextInput, + HidSceneRenameEventPopup, +}; + +static void hid_scene_rename_text_input_callback(void* context) { + Hid* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, HidSceneRenameEventTextInput); +} + +void hid_scene_rename_popup_callback(void* context) { + Hid* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, HidSceneRenameEventPopup); +} + +void hid_scene_rename_on_enter(void* context) { + Hid* app = context; + + // Rename text input view + text_input_reset(app->text_input); + text_input_set_result_callback( + app->text_input, + hid_scene_rename_text_input_callback, + app, + app->ble_hid_cfg.name, + sizeof(app->ble_hid_cfg.name), + true); + text_input_set_header_text(app->text_input, "Bluetooth Name"); + + // Rename success popup view + popup_set_icon(app->popup, 48, 6, &I_DolphinDone_80x58); + popup_set_header(app->popup, "Done", 14, 15, AlignLeft, AlignTop); + popup_set_timeout(app->popup, 1500); + popup_set_context(app->popup, app); + popup_set_callback(app->popup, hid_scene_rename_popup_callback); + popup_enable_timeout(app->popup); + + view_dispatcher_switch_to_view(app->view_dispatcher, HidViewTextInput); +} + +bool hid_scene_rename_on_event(void* context, SceneManagerEvent event) { + Hid* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == HidSceneRenameEventTextInput) { +#ifdef HID_TRANSPORT_BLE + furi_hal_bt_stop_advertising(); + + app->ble_hid_profile = + bt_profile_start(app->bt, ble_profile_hid_ext, &app->ble_hid_cfg); + furi_check(app->ble_hid_profile); + + furi_hal_bt_start_advertising(); +#endif + + bt_hid_save_cfg(app); + + // Show popup + view_dispatcher_switch_to_view(app->view_dispatcher, HidViewPopup); + + } else if(event.event == HidSceneRenameEventPopup) { + scene_manager_previous_scene(app->scene_manager); + } + } + + return consumed; +} + +void hid_scene_rename_on_exit(void* context) { + Hid* app = context; + + text_input_reset(app->text_input); + popup_reset(app->popup); +} diff --git a/applications/system/hid_app/scenes/hid_scene_start.c b/applications/system/hid_app/scenes/hid_scene_start.c index 61d340eec..167b967e6 100644 --- a/applications/system/hid_app/scenes/hid_scene_start.c +++ b/applications/system/hid_app/scenes/hid_scene_start.c @@ -15,6 +15,7 @@ enum HidSubmenuIndex { HidSubmenuIndexMouseJiggler, HidSubmenuIndexMouseJigglerStealth, HidSubmenuIndexPushToTalk, + HidSubmenuIndexRename, HidSubmenuIndexRemovePairing, }; @@ -81,6 +82,12 @@ void hid_scene_start_on_enter(void* context) { hid_scene_start_submenu_callback, app); #ifdef HID_TRANSPORT_BLE + submenu_add_item( + app->submenu, + "Bluetooth Remote Name", + HidSubmenuIndexRename, + hid_scene_start_submenu_callback, + app); submenu_add_item( app->submenu, "Bluetooth Unpairing", @@ -101,6 +108,8 @@ bool hid_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == HidSubmenuIndexRemovePairing) { scene_manager_next_scene(app->scene_manager, HidSceneUnpair); + } else if(event.event == HidSubmenuIndexRename) { + scene_manager_next_scene(app->scene_manager, HidSceneRename); } else { HidView view_id; diff --git a/applications/system/hid_app/views.h b/applications/system/hid_app/views.h index 606a48daf..e27d3ecf0 100644 --- a/applications/system/hid_app/views.h +++ b/applications/system/hid_app/views.h @@ -16,4 +16,5 @@ typedef enum { HidViewPushToTalkHelp, HidViewDialog, HidViewPopup, + HidViewTextInput, } HidView; diff --git a/applications/system/hid_app/views/hid_music_macos.h b/applications/system/hid_app/views/hid_music_macos.h index 9deac32eb..f185276f3 100644 --- a/applications/system/hid_app/views/hid_music_macos.h +++ b/applications/system/hid_app/views/hid_music_macos.h @@ -2,9 +2,10 @@ #include +typedef struct Hid Hid; typedef struct HidMusicMacos HidMusicMacos; -HidMusicMacos* hid_music_macos_alloc(); +HidMusicMacos* hid_music_macos_alloc(Hid* hid); void hid_music_macos_free(HidMusicMacos* hid_music_macos); diff --git a/applications/system/hid_app/views/hid_ptt.c b/applications/system/hid_app/views/hid_ptt.c index 59643abac..58599eb51 100644 --- a/applications/system/hid_app/views/hid_ptt.c +++ b/applications/system/hid_app/views/hid_ptt.c @@ -42,6 +42,7 @@ typedef struct { enum HidPushToTalkAppIndex { HidPushToTalkAppIndexDiscord, HidPushToTalkAppIndexFaceTime, + HidPushToTalkAppIndexGather, HidPushToTalkAppIndexGoogleMeet, HidPushToTalkAppIndexGoogleHangouts, HidPushToTalkAppIndexJamulus, @@ -308,7 +309,6 @@ static void hid_ptt_trigger_mute_jamulus(HidPushToTalk* hid_ptt) { } // webex - static void hid_ptt_trigger_camera_webex(HidPushToTalk* hid_ptt) { hid_hal_keyboard_press(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V); hid_hal_keyboard_release( @@ -325,6 +325,30 @@ static void hid_ptt_trigger_hand_linux_webex(HidPushToTalk* hid_ptt) { hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_R); } +// Gather +static void hid_ptt_trigger_hand_gather(HidPushToTalk* hid_ptt) { + hid_hal_keyboard_press(hid_ptt->hid, HID_KEYBOARD_H); + hid_hal_keyboard_release(hid_ptt->hid, HID_KEYBOARD_H); +} +static void hid_ptt_trigger_camera_macos_gather(HidPushToTalk* hid_ptt) { + hid_hal_keyboard_press(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V); + hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V); +} +static void hid_ptt_trigger_mute_macos_gather(HidPushToTalk* hid_ptt) { + hid_hal_keyboard_press(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_A); + hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_A); +} +static void hid_ptt_trigger_camera_linux_gather(HidPushToTalk* hid_ptt) { + hid_hal_keyboard_press(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V); + hid_hal_keyboard_release( + hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V); +} +static void hid_ptt_trigger_mute_linux_gather(HidPushToTalk* hid_ptt) { + hid_hal_keyboard_press(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_A); + hid_hal_keyboard_release( + hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_A); +} + static void hid_ptt_menu_callback( void* context, uint32_t osIndex, @@ -359,6 +383,13 @@ static void hid_ptt_menu_callback( model->callback_start_ptt = hid_ptt_trigger_cmd_shift_m; model->callback_stop_ptt = hid_ptt_trigger_cmd_shift_m; break; + case HidPushToTalkAppIndexGather: + model->callback_trigger_mute = hid_ptt_trigger_mute_macos_gather; + model->callback_trigger_camera = hid_ptt_trigger_camera_macos_gather; + model->callback_trigger_hand = hid_ptt_trigger_hand_gather; + model->callback_start_ptt = hid_ptt_trigger_mute_macos_gather; + model->callback_stop_ptt = hid_ptt_trigger_mute_macos_gather; + break; case HidPushToTalkAppIndexGoogleHangouts: model->callback_trigger_mute = hid_ptt_trigger_mute_macos_hangouts; model->callback_trigger_camera = hid_ptt_trigger_camera_macos_hangouts; @@ -434,6 +465,13 @@ static void hid_ptt_menu_callback( model->callback_start_ptt = hid_ptt_start_ptt_linux_discord; model->callback_stop_ptt = hid_ptt_stop_ptt_linux_discord; break; + case HidPushToTalkAppIndexGather: + model->callback_trigger_mute = hid_ptt_trigger_mute_linux_gather; + model->callback_trigger_camera = hid_ptt_trigger_camera_linux_gather; + model->callback_trigger_hand = hid_ptt_trigger_hand_gather; + model->callback_start_ptt = hid_ptt_trigger_mute_linux_gather; + model->callback_stop_ptt = hid_ptt_trigger_mute_linux_gather; + break; case HidPushToTalkAppIndexGoogleHangouts: model->callback_trigger_mute = hid_ptt_trigger_mute_linux_hangouts; model->callback_trigger_camera = hid_ptt_trigger_camera_linux_hangouts; @@ -873,6 +911,20 @@ HidPushToTalk* hid_ptt_alloc(Hid* hid) { HidPushToTalkAppIndexFaceTime, hid_ptt_menu_callback, hid_ptt); + ptt_menu_add_item_to_list( + hid->hid_ptt_menu, + HidPushToTalkMacOS, + "Gather", + HidPushToTalkAppIndexGather, + hid_ptt_menu_callback, + hid_ptt); + ptt_menu_add_item_to_list( + hid->hid_ptt_menu, + HidPushToTalkLinux, + "Gather", + HidPushToTalkAppIndexGather, + hid_ptt_menu_callback, + hid_ptt); ptt_menu_add_item_to_list( hid->hid_ptt_menu, HidPushToTalkMacOS, @@ -932,14 +984,14 @@ HidPushToTalk* hid_ptt_alloc(Hid* hid) { ptt_menu_add_item_to_list( hid->hid_ptt_menu, HidPushToTalkMacOS, - "Slack Hubble", + "Slack Huddle", HidPushToTalkAppIndexSlackHubble, hid_ptt_menu_callback, hid_ptt); ptt_menu_add_item_to_list( hid->hid_ptt_menu, HidPushToTalkLinux, - "Slack Hubble", + "Slack Huddle", HidPushToTalkAppIndexSlackHubble, hid_ptt_menu_callback, hid_ptt); From c189283329a150f990d5bc715ef5b9892b6bac68 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 04:37:49 +0300 Subject: [PATCH 08/14] simplify Bad USB BLE profile by aaronjamt & WillyJL --- applications/main/bad_usb/application.fam | 2 +- .../main/bad_usb/helpers/bad_usb_hid.c | 7 +- .../main/bad_usb/helpers/bad_usb_hid.h | 4 +- .../bad_usb/helpers/ble_hid_ext_profile.c | 43 ++ .../bad_usb/helpers/ble_hid_ext_profile.h | 17 + .../main/bad_usb/helpers/ble_hid_profile.c | 429 ------------------ .../main/bad_usb/helpers/ble_hid_profile.h | 109 ----- .../main/bad_usb/helpers/ble_hid_service.c | 325 ------------- .../main/bad_usb/helpers/ble_hid_service.h | 31 -- .../main/bad_usb/helpers/ducky_script.c | 2 +- .../bad_usb/scenes/bad_usb_scene_config.c | 2 +- .../main/bad_usb/views/bad_usb_view.c | 14 +- 12 files changed, 82 insertions(+), 903 deletions(-) create mode 100644 applications/main/bad_usb/helpers/ble_hid_ext_profile.c create mode 100644 applications/main/bad_usb/helpers/ble_hid_ext_profile.h delete mode 100644 applications/main/bad_usb/helpers/ble_hid_profile.c delete mode 100644 applications/main/bad_usb/helpers/ble_hid_profile.h delete mode 100644 applications/main/bad_usb/helpers/ble_hid_service.c delete mode 100644 applications/main/bad_usb/helpers/ble_hid_service.h diff --git a/applications/main/bad_usb/application.fam b/applications/main/bad_usb/application.fam index 9844e248d..8d3909fcc 100644 --- a/applications/main/bad_usb/application.fam +++ b/applications/main/bad_usb/application.fam @@ -7,7 +7,7 @@ App( icon="A_BadUsb_14", order=70, resources="resources", - fap_libs=["assets"], + fap_libs=["assets", "ble_profile"], fap_icon="icon.png", fap_category="USB", ) diff --git a/applications/main/bad_usb/helpers/bad_usb_hid.c b/applications/main/bad_usb/helpers/bad_usb_hid.c index 5ae4146e8..cab84173d 100644 --- a/applications/main/bad_usb/helpers/bad_usb_hid.c +++ b/applications/main/bad_usb/helpers/bad_usb_hid.c @@ -1,6 +1,7 @@ #include "bad_usb_hid.h" -#include "ble_hid_profile.h" +#include "ble_hid_ext_profile.h" #include +#include #include #define TAG "BadUSB HID" @@ -161,6 +162,7 @@ void hid_ble_adjust_config(BadUsbHidConfig* hid_cfg) { void* hid_ble_init(BadUsbHidConfig* hid_cfg) { BleHidInstance* ble_hid = malloc(sizeof(BleHidInstance)); ble_hid->bt = furi_record_open(RECORD_BT); + ble_hid->bt->suppress_pin_screen = true; bt_disconnect(ble_hid->bt); // Wait 2nd core to update nvm storage @@ -169,7 +171,7 @@ void* hid_ble_init(BadUsbHidConfig* hid_cfg) { bt_keys_storage_set_storage_path(ble_hid->bt, APP_DATA_PATH(HID_BT_KEYS_STORAGE_NAME)); hid_ble_adjust_config(hid_cfg); - ble_hid->profile = bt_profile_start(ble_hid->bt, ble_profile_hid, &hid_cfg->ble); + ble_hid->profile = bt_profile_start(ble_hid->bt, ble_profile_hid_ext, &hid_cfg->ble); furi_check(ble_hid->profile); furi_hal_bt_start_advertising(); @@ -191,6 +193,7 @@ void hid_ble_deinit(void* inst) { bt_keys_storage_set_default_path(ble_hid->bt); furi_check(bt_profile_restore_default(ble_hid->bt)); + ble_hid->bt->suppress_pin_screen = false; furi_record_close(RECORD_BT); free(ble_hid); } diff --git a/applications/main/bad_usb/helpers/bad_usb_hid.h b/applications/main/bad_usb/helpers/bad_usb_hid.h index 8749bdc3b..8a96ad7f3 100644 --- a/applications/main/bad_usb/helpers/bad_usb_hid.h +++ b/applications/main/bad_usb/helpers/bad_usb_hid.h @@ -7,7 +7,7 @@ extern "C" { #include #include -#include "ble_hid_profile.h" +#include "ble_hid_ext_profile.h" typedef enum { BadUsbHidInterfaceUsb, @@ -16,7 +16,7 @@ typedef enum { } BadUsbHidInterface; typedef struct { - BleProfileHidParams ble; + BleProfileHidExtParams ble; FuriHalUsbHidConfig usb; } BadUsbHidConfig; diff --git a/applications/main/bad_usb/helpers/ble_hid_ext_profile.c b/applications/main/bad_usb/helpers/ble_hid_ext_profile.c new file mode 100644 index 000000000..f77d6ba13 --- /dev/null +++ b/applications/main/bad_usb/helpers/ble_hid_ext_profile.c @@ -0,0 +1,43 @@ +#include "ble_hid_ext_profile.h" + +#include + +static FuriHalBleProfileBase* ble_profile_hid_ext_start(FuriHalBleProfileParams profile_params) { + UNUSED(profile_params); + + return ble_profile_hid->start(NULL); +} + +static void ble_profile_hid_ext_stop(FuriHalBleProfileBase* profile) { + ble_profile_hid->stop(profile); +} + +static void + ble_profile_hid_ext_get_config(GapConfig* config, FuriHalBleProfileParams profile_params) { + furi_check(config); + furi_check(profile_params); + BleProfileHidExtParams* hid_ext_profile_params = profile_params; + + // Setup config with basic profile + ble_profile_hid->get_gap_config(config, NULL); + + // Set MAC address + memcpy(config->mac_address, hid_ext_profile_params->mac, sizeof(config->mac_address)); + + // Set advertise name (skip first byte which is the ADV type) + strlcpy(config->adv_name + 1, hid_ext_profile_params->name, sizeof(config->adv_name) - 1); + + // Set bonding mode + config->bonding_mode = hid_ext_profile_params->bonding; + + // Set pairing method + config->pairing_method = hid_ext_profile_params->pairing; +} + +static const FuriHalBleProfileTemplate profile_callbacks = { + .start = ble_profile_hid_ext_start, + .stop = ble_profile_hid_ext_stop, + .get_gap_config = ble_profile_hid_ext_get_config, +}; + +const FuriHalBleProfileTemplate* ble_profile_hid_ext = &profile_callbacks; diff --git a/applications/main/bad_usb/helpers/ble_hid_ext_profile.h b/applications/main/bad_usb/helpers/ble_hid_ext_profile.h new file mode 100644 index 000000000..cc52f0ee7 --- /dev/null +++ b/applications/main/bad_usb/helpers/ble_hid_ext_profile.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +/** + * Optional arguments to pass along with profile template as + * FuriHalBleProfileParams for tuning profile behavior + **/ +typedef struct { + char name[FURI_HAL_BT_ADV_NAME_LENGTH]; /**< Full device name */ + uint8_t mac[GAP_MAC_ADDR_SIZE]; /**< Full device address */ + bool bonding; /**< Save paired devices */ + GapPairing pairing; /**< Pairing security method */ +} BleProfileHidExtParams; + +/** Hid Keyboard Profile descriptor */ +extern const FuriHalBleProfileTemplate* ble_profile_hid_ext; diff --git a/applications/main/bad_usb/helpers/ble_hid_profile.c b/applications/main/bad_usb/helpers/ble_hid_profile.c deleted file mode 100644 index a4f32159e..000000000 --- a/applications/main/bad_usb/helpers/ble_hid_profile.c +++ /dev/null @@ -1,429 +0,0 @@ -#include "ble_hid_profile.h" - -// Based on - -#include -#include -#include -#include "ble_hid_service.h" - -#include -#include -#include - -#define HID_INFO_BASE_USB_SPECIFICATION (0x0101) -#define HID_INFO_COUNTRY_CODE (0x00) -#define BLE_PROFILE_HID_INFO_FLAG_REMOTE_WAKE_MSK (0x01) -#define BLE_PROFILE_HID_INFO_FLAG_NORMALLY_CONNECTABLE_MSK (0x02) - -#define BLE_PROFILE_HID_KB_MAX_KEYS (6) -#define BLE_PROFILE_CONSUMER_MAX_KEYS (1) - -// Report ids cant be 0 -enum HidReportId { - ReportIdKeyboard = 1, - ReportIdMouse = 2, - ReportIdConsumer = 3, -}; -// Report numbers corresponded to the report id with an offset of 1 -enum HidInputNumber { - ReportNumberKeyboard = 0, - ReportNumberMouse = 1, - ReportNumberConsumer = 2, -}; - -typedef struct { - uint8_t mods; - uint8_t reserved; - uint8_t key[BLE_PROFILE_HID_KB_MAX_KEYS]; -} FURI_PACKED FuriHalBtHidKbReport; - -typedef struct { - uint8_t btn; - int8_t x; - int8_t y; - int8_t wheel; -} FURI_PACKED FuriHalBtHidMouseReport; - -typedef struct { - uint16_t key[BLE_PROFILE_CONSUMER_MAX_KEYS]; -} FURI_PACKED FuriHalBtHidConsumerReport; - -// keyboard+mouse+consumer hid report -static const uint8_t ble_profile_hid_report_map_data[] = { - // Keyboard Report - HID_USAGE_PAGE(HID_PAGE_DESKTOP), - HID_USAGE(HID_DESKTOP_KEYBOARD), - HID_COLLECTION(HID_APPLICATION_COLLECTION), - HID_REPORT_ID(ReportIdKeyboard), - HID_USAGE_PAGE(HID_DESKTOP_KEYPAD), - HID_USAGE_MINIMUM(HID_KEYBOARD_L_CTRL), - HID_USAGE_MAXIMUM(HID_KEYBOARD_R_GUI), - HID_LOGICAL_MINIMUM(0), - HID_LOGICAL_MAXIMUM(1), - HID_REPORT_SIZE(1), - HID_REPORT_COUNT(8), - HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - HID_REPORT_COUNT(1), - HID_REPORT_SIZE(8), - HID_INPUT(HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - HID_USAGE_PAGE(HID_PAGE_LED), - HID_REPORT_COUNT(8), - HID_REPORT_SIZE(1), - HID_USAGE_MINIMUM(1), - HID_USAGE_MAXIMUM(8), - HID_OUTPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - HID_REPORT_COUNT(BLE_PROFILE_HID_KB_MAX_KEYS), - HID_REPORT_SIZE(8), - HID_LOGICAL_MINIMUM(0), - HID_LOGICAL_MAXIMUM(101), - HID_USAGE_PAGE(HID_DESKTOP_KEYPAD), - HID_USAGE_MINIMUM(0), - HID_USAGE_MAXIMUM(101), - HID_INPUT(HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), - HID_END_COLLECTION, - // Mouse Report - HID_USAGE_PAGE(HID_PAGE_DESKTOP), - HID_USAGE(HID_DESKTOP_MOUSE), - HID_COLLECTION(HID_APPLICATION_COLLECTION), - HID_USAGE(HID_DESKTOP_POINTER), - HID_COLLECTION(HID_PHYSICAL_COLLECTION), - HID_REPORT_ID(ReportIdMouse), - HID_USAGE_PAGE(HID_PAGE_BUTTON), - HID_USAGE_MINIMUM(1), - HID_USAGE_MAXIMUM(3), - HID_LOGICAL_MINIMUM(0), - HID_LOGICAL_MAXIMUM(1), - HID_REPORT_COUNT(3), - HID_REPORT_SIZE(1), - HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - HID_REPORT_SIZE(1), - HID_REPORT_COUNT(5), - HID_INPUT(HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - HID_USAGE_PAGE(HID_PAGE_DESKTOP), - HID_USAGE(HID_DESKTOP_X), - HID_USAGE(HID_DESKTOP_Y), - HID_USAGE(HID_DESKTOP_WHEEL), - HID_LOGICAL_MINIMUM(-127), - HID_LOGICAL_MAXIMUM(127), - HID_REPORT_SIZE(8), - HID_REPORT_COUNT(3), - HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), - HID_END_COLLECTION, - HID_END_COLLECTION, - // Consumer Report - HID_USAGE_PAGE(HID_PAGE_CONSUMER), - HID_USAGE(HID_CONSUMER_CONTROL), - HID_COLLECTION(HID_APPLICATION_COLLECTION), - HID_REPORT_ID(ReportIdConsumer), - HID_LOGICAL_MINIMUM(0), - HID_RI_LOGICAL_MAXIMUM(16, 0x3FF), - HID_USAGE_MINIMUM(0), - HID_RI_USAGE_MAXIMUM(16, 0x3FF), - HID_REPORT_COUNT(BLE_PROFILE_CONSUMER_MAX_KEYS), - HID_REPORT_SIZE(16), - HID_INPUT(HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), - HID_END_COLLECTION, -}; - -typedef struct { - FuriHalBleProfileBase base; - - FuriHalBtHidKbReport* kb_report; - FuriHalBtHidMouseReport* mouse_report; - FuriHalBtHidConsumerReport* consumer_report; - - BleServiceBattery* battery_svc; - BleServiceDevInfo* dev_info_svc; - BleServiceHid* hid_svc; -} BleProfileHid; -_Static_assert(offsetof(BleProfileHid, base) == 0, "Wrong layout"); - -static FuriHalBleProfileBase* ble_profile_hid_start(FuriHalBleProfileParams profile_params) { - UNUSED(profile_params); - - BleProfileHid* profile = malloc(sizeof(BleProfileHid)); - - profile->base.config = ble_profile_hid; - - profile->battery_svc = ble_svc_battery_start(true); - profile->dev_info_svc = ble_svc_dev_info_start(); - profile->hid_svc = ble_svc_hid_start(); - - // Configure HID Keyboard - profile->kb_report = malloc(sizeof(FuriHalBtHidKbReport)); - profile->mouse_report = malloc(sizeof(FuriHalBtHidMouseReport)); - profile->consumer_report = malloc(sizeof(FuriHalBtHidConsumerReport)); - - // Configure Report Map characteristic - ble_svc_hid_update_report_map( - profile->hid_svc, - ble_profile_hid_report_map_data, - sizeof(ble_profile_hid_report_map_data)); - // Configure HID Information characteristic - uint8_t hid_info_val[4] = { - HID_INFO_BASE_USB_SPECIFICATION & 0x00ff, - (HID_INFO_BASE_USB_SPECIFICATION & 0xff00) >> 8, - HID_INFO_COUNTRY_CODE, - BLE_PROFILE_HID_INFO_FLAG_REMOTE_WAKE_MSK | - BLE_PROFILE_HID_INFO_FLAG_NORMALLY_CONNECTABLE_MSK, - }; - ble_svc_hid_update_info(profile->hid_svc, hid_info_val); - - return &profile->base; -} - -static void ble_profile_hid_stop(FuriHalBleProfileBase* profile) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - ble_svc_battery_stop(hid_profile->battery_svc); - ble_svc_dev_info_stop(hid_profile->dev_info_svc); - ble_svc_hid_stop(hid_profile->hid_svc); - - free(hid_profile->kb_report); - free(hid_profile->mouse_report); - free(hid_profile->consumer_report); -} - -bool ble_profile_hid_kb_press(FuriHalBleProfileBase* profile, uint16_t button) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidKbReport* kb_report = hid_profile->kb_report; - for(uint8_t i = 0; i < BLE_PROFILE_HID_KB_MAX_KEYS; i++) { - if(kb_report->key[i] == 0) { - kb_report->key[i] = button & 0xFF; - break; - } - } - kb_report->mods |= (button >> 8); - return ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberKeyboard, - (uint8_t*)kb_report, - sizeof(FuriHalBtHidKbReport)); -} - -bool ble_profile_hid_kb_release(FuriHalBleProfileBase* profile, uint16_t button) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - - FuriHalBtHidKbReport* kb_report = hid_profile->kb_report; - for(uint8_t i = 0; i < BLE_PROFILE_HID_KB_MAX_KEYS; i++) { - if(kb_report->key[i] == (button & 0xFF)) { - kb_report->key[i] = 0; - break; - } - } - kb_report->mods &= ~(button >> 8); - return ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberKeyboard, - (uint8_t*)kb_report, - sizeof(FuriHalBtHidKbReport)); -} - -bool ble_profile_hid_kb_release_all(FuriHalBleProfileBase* profile) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidKbReport* kb_report = hid_profile->kb_report; - for(uint8_t i = 0; i < BLE_PROFILE_HID_KB_MAX_KEYS; i++) { - kb_report->key[i] = 0; - } - kb_report->mods = 0; - return ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberKeyboard, - (uint8_t*)kb_report, - sizeof(FuriHalBtHidKbReport)); -} - -bool ble_profile_hid_consumer_key_press(FuriHalBleProfileBase* profile, uint16_t button) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidConsumerReport* consumer_report = hid_profile->consumer_report; - for(uint8_t i = 0; i < BLE_PROFILE_CONSUMER_MAX_KEYS; i++) { //-V1008 - if(consumer_report->key[i] == 0) { - consumer_report->key[i] = button; - break; - } - } - return ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberConsumer, - (uint8_t*)consumer_report, - sizeof(FuriHalBtHidConsumerReport)); -} - -bool ble_profile_hid_consumer_key_release(FuriHalBleProfileBase* profile, uint16_t button) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidConsumerReport* consumer_report = hid_profile->consumer_report; - for(uint8_t i = 0; i < BLE_PROFILE_CONSUMER_MAX_KEYS; i++) { //-V1008 - if(consumer_report->key[i] == button) { - consumer_report->key[i] = 0; - break; - } - } - return ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberConsumer, - (uint8_t*)consumer_report, - sizeof(FuriHalBtHidConsumerReport)); -} - -bool ble_profile_hid_consumer_key_release_all(FuriHalBleProfileBase* profile) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidConsumerReport* consumer_report = hid_profile->consumer_report; - for(uint8_t i = 0; i < BLE_PROFILE_CONSUMER_MAX_KEYS; i++) { //-V1008 - consumer_report->key[i] = 0; - } - return ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberConsumer, - (uint8_t*)consumer_report, - sizeof(FuriHalBtHidConsumerReport)); -} - -bool ble_profile_hid_mouse_move(FuriHalBleProfileBase* profile, int8_t dx, int8_t dy) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidMouseReport* mouse_report = hid_profile->mouse_report; - mouse_report->x = dx; - mouse_report->y = dy; - bool state = ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberMouse, - (uint8_t*)mouse_report, - sizeof(FuriHalBtHidMouseReport)); - mouse_report->x = 0; - mouse_report->y = 0; - return state; -} - -bool ble_profile_hid_mouse_press(FuriHalBleProfileBase* profile, uint8_t button) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidMouseReport* mouse_report = hid_profile->mouse_report; - mouse_report->btn |= button; - return ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberMouse, - (uint8_t*)mouse_report, - sizeof(FuriHalBtHidMouseReport)); -} - -bool ble_profile_hid_mouse_release(FuriHalBleProfileBase* profile, uint8_t button) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidMouseReport* mouse_report = hid_profile->mouse_report; - mouse_report->btn &= ~button; - return ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberMouse, - (uint8_t*)mouse_report, - sizeof(FuriHalBtHidMouseReport)); -} - -bool ble_profile_hid_mouse_release_all(FuriHalBleProfileBase* profile) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidMouseReport* mouse_report = hid_profile->mouse_report; - mouse_report->btn = 0; - return ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberMouse, - (uint8_t*)mouse_report, - sizeof(FuriHalBtHidMouseReport)); -} - -bool ble_profile_hid_mouse_scroll(FuriHalBleProfileBase* profile, int8_t delta) { - furi_check(profile); - furi_check(profile->config == ble_profile_hid); - - BleProfileHid* hid_profile = (BleProfileHid*)profile; - FuriHalBtHidMouseReport* mouse_report = hid_profile->mouse_report; - mouse_report->wheel = delta; - bool state = ble_svc_hid_update_input_report( - hid_profile->hid_svc, - ReportNumberMouse, - (uint8_t*)mouse_report, - sizeof(FuriHalBtHidMouseReport)); - mouse_report->wheel = 0; - return state; -} - -// AN5289: 4.7, in order to use flash controller interval must be at least 25ms + advertisement, which is 30 ms -// Since we don't use flash controller anymore interval can be lowered to 7.5ms -#define CONNECTION_INTERVAL_MIN (0x0006) -// Up to 45 ms -#define CONNECTION_INTERVAL_MAX (0x24) - -static GapConfig template_config = { - .adv_service = - { - .UUID_Type = UUID_TYPE_16, - .Service_UUID_16 = HUMAN_INTERFACE_DEVICE_SERVICE_UUID, - }, - .appearance_char = GAP_APPEARANCE_KEYBOARD, - .bonding_mode = true, - .pairing_method = GapPairingPinCodeVerifyYesNo, - .conn_param = - { - .conn_int_min = CONNECTION_INTERVAL_MIN, - .conn_int_max = CONNECTION_INTERVAL_MAX, - .slave_latency = 0, - .supervisor_timeout = 0, - }, -}; - -static void ble_profile_hid_get_config(GapConfig* config, FuriHalBleProfileParams profile_params) { - furi_check(profile_params); - BleProfileHidParams* hid_profile_params = profile_params; - - furi_check(config); - memcpy(config, &template_config, sizeof(GapConfig)); - - // Set MAC address - memcpy(config->mac_address, hid_profile_params->mac, sizeof(config->mac_address)); - - // Set advertise name - config->adv_name[0] = furi_hal_version_get_ble_local_device_name_ptr()[0]; - strlcpy(config->adv_name + 1, hid_profile_params->name, sizeof(config->adv_name) - 1); - - // Set bonding mode - config->bonding_mode = hid_profile_params->bonding; - - // Set pairing method - config->pairing_method = hid_profile_params->pairing; -} - -static const FuriHalBleProfileTemplate profile_callbacks = { - .start = ble_profile_hid_start, - .stop = ble_profile_hid_stop, - .get_gap_config = ble_profile_hid_get_config, -}; - -const FuriHalBleProfileTemplate* ble_profile_hid = &profile_callbacks; diff --git a/applications/main/bad_usb/helpers/ble_hid_profile.h b/applications/main/bad_usb/helpers/ble_hid_profile.h deleted file mode 100644 index 2302aa581..000000000 --- a/applications/main/bad_usb/helpers/ble_hid_profile.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -// Based on - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Optional arguments to pass along with profile template as - * FuriHalBleProfileParams for tuning profile behavior - **/ -typedef struct { - char name[FURI_HAL_BT_ADV_NAME_LENGTH]; /**< Full device name */ - uint8_t mac[GAP_MAC_ADDR_SIZE]; /**< Full device address */ - bool bonding; /**< Save paired devices */ - GapPairing pairing; /**< Pairing security method */ -} BleProfileHidParams; - -/** Hid Keyboard Profile descriptor */ -extern const FuriHalBleProfileTemplate* ble_profile_hid; - -/** Press keyboard button - * - * @param profile profile instance - * @param button button code from HID specification - * - * @return true on success - */ -bool ble_profile_hid_kb_press(FuriHalBleProfileBase* profile, uint16_t button); - -/** Release keyboard button - * - * @param profile profile instance - * @param button button code from HID specification - * - * @return true on success - */ -bool ble_profile_hid_kb_release(FuriHalBleProfileBase* profile, uint16_t button); - -/** Release all keyboard buttons - * - * @param profile profile instance - * @return true on success - */ -bool ble_profile_hid_kb_release_all(FuriHalBleProfileBase* profile); - -/** Set the following consumer key to pressed state and send HID report - * - * @param profile profile instance - * @param button key code - */ -bool ble_profile_hid_consumer_key_press(FuriHalBleProfileBase* profile, uint16_t button); - -/** Set the following consumer key to released state and send HID report - * - * @param profile profile instance - * @param button key code - */ -bool ble_profile_hid_consumer_key_release(FuriHalBleProfileBase* profile, uint16_t button); - -/** Set consumer key to released state and send HID report - * - * @param profile profile instance - * @param button key code - */ -bool ble_profile_hid_consumer_key_release_all(FuriHalBleProfileBase* profile); - -/** Set mouse movement and send HID report - * - * @param profile profile instance - * @param dx x coordinate delta - * @param dy y coordinate delta - */ -bool ble_profile_hid_mouse_move(FuriHalBleProfileBase* profile, int8_t dx, int8_t dy); - -/** Set mouse button to pressed state and send HID report - * - * @param profile profile instance - * @param button key code - */ -bool ble_profile_hid_mouse_press(FuriHalBleProfileBase* profile, uint8_t button); - -/** Set mouse button to released state and send HID report - * - * @param profile profile instance - * @param button key code - */ -bool ble_profile_hid_mouse_release(FuriHalBleProfileBase* profile, uint8_t button); - -/** Set mouse button to released state and send HID report - * - * @param profile profile instance - * @param button key code - */ -bool ble_profile_hid_mouse_release_all(FuriHalBleProfileBase* profile); - -/** Set mouse wheel position and send HID report - * - * @param profile profile instance - * @param delta number of scroll steps - */ -bool ble_profile_hid_mouse_scroll(FuriHalBleProfileBase* profile, int8_t delta); - -#ifdef __cplusplus -} -#endif diff --git a/applications/main/bad_usb/helpers/ble_hid_service.c b/applications/main/bad_usb/helpers/ble_hid_service.c deleted file mode 100644 index b546368dd..000000000 --- a/applications/main/bad_usb/helpers/ble_hid_service.c +++ /dev/null @@ -1,325 +0,0 @@ -#include "ble_hid_service.h" - -// Based on - -#include "app_common.h" // IWYU pragma: keep -#include -#include -#include - -#include -#include - -#define TAG "BleHid" - -#define BLE_SVC_HID_REPORT_MAP_MAX_LEN (255) -#define BLE_SVC_HID_REPORT_MAX_LEN (255) -#define BLE_SVC_HID_REPORT_REF_LEN (2) -#define BLE_SVC_HID_INFO_LEN (4) -#define BLE_SVC_HID_CONTROL_POINT_LEN (1) - -#define BLE_SVC_HID_INPUT_REPORT_COUNT (3) -#define BLE_SVC_HID_OUTPUT_REPORT_COUNT (0) -#define BLE_SVC_HID_FEATURE_REPORT_COUNT (0) -#define BLE_SVC_HID_REPORT_COUNT \ - (BLE_SVC_HID_INPUT_REPORT_COUNT + BLE_SVC_HID_OUTPUT_REPORT_COUNT + \ - BLE_SVC_HID_FEATURE_REPORT_COUNT) - -typedef enum { - HidSvcGattCharacteristicProtocolMode = 0, - HidSvcGattCharacteristicReportMap, - HidSvcGattCharacteristicInfo, - HidSvcGattCharacteristicCtrlPoint, - HidSvcGattCharacteristicCount, -} HidSvcGattCharacteristicId; - -typedef struct { - uint8_t report_idx; - uint8_t report_type; -} HidSvcReportId; - -static_assert(sizeof(HidSvcReportId) == sizeof(uint16_t), "HidSvcReportId must be 2 bytes"); - -static const Service_UUID_t ble_svc_hid_uuid = { - .Service_UUID_16 = HUMAN_INTERFACE_DEVICE_SERVICE_UUID, -}; - -static bool ble_svc_hid_char_desc_data_callback( - const void* context, - const uint8_t** data, - uint16_t* data_len) { - const HidSvcReportId* report_id = context; - *data_len = sizeof(HidSvcReportId); - if(data) { - *data = (const uint8_t*)report_id; - } - return false; -} - -typedef struct { - const void* data_ptr; - uint16_t data_len; -} HidSvcDataWrapper; - -static bool ble_svc_hid_report_data_callback( - const void* context, - const uint8_t** data, - uint16_t* data_len) { - const HidSvcDataWrapper* report_data = context; - if(data) { - *data = report_data->data_ptr; - *data_len = report_data->data_len; - } else { - *data_len = BLE_SVC_HID_REPORT_MAP_MAX_LEN; - } - return false; -} - -static const BleGattCharacteristicParams ble_svc_hid_chars[HidSvcGattCharacteristicCount] = { - [HidSvcGattCharacteristicProtocolMode] = - {.name = "Protocol Mode", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = 1, - .uuid.Char_UUID_16 = PROTOCOL_MODE_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [HidSvcGattCharacteristicReportMap] = - {.name = "Report Map", - .data_prop_type = FlipperGattCharacteristicDataCallback, - .data.callback.fn = ble_svc_hid_report_data_callback, - .data.callback.context = NULL, - .uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_VARIABLE}, - [HidSvcGattCharacteristicInfo] = - {.name = "HID Information", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = BLE_SVC_HID_INFO_LEN, - .data.fixed.ptr = NULL, - .uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, - [HidSvcGattCharacteristicCtrlPoint] = - {.name = "HID Control Point", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = BLE_SVC_HID_CONTROL_POINT_LEN, - .uuid.Char_UUID_16 = HID_CONTROL_POINT_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, - .is_variable = CHAR_VALUE_LEN_CONSTANT}, -}; - -static const BleGattCharacteristicDescriptorParams ble_svc_hid_char_descr_template = { - .uuid_type = UUID_TYPE_16, - .uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID, - .max_length = BLE_SVC_HID_REPORT_REF_LEN, - .data_callback.fn = ble_svc_hid_char_desc_data_callback, - .security_permissions = ATTR_PERMISSION_NONE, - .access_permissions = ATTR_ACCESS_READ_WRITE, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_CONSTANT, -}; - -static const BleGattCharacteristicParams ble_svc_hid_report_template = { - .name = "Report", - .data_prop_type = FlipperGattCharacteristicDataCallback, - .data.callback.fn = ble_svc_hid_report_data_callback, - .data.callback.context = NULL, - .uuid.Char_UUID_16 = REPORT_CHAR_UUID, - .uuid_type = UUID_TYPE_16, - .char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, - .security_permissions = ATTR_PERMISSION_NONE, - .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, - .is_variable = CHAR_VALUE_LEN_VARIABLE, -}; - -struct BleServiceHid { - uint16_t svc_handle; - BleGattCharacteristicInstance chars[HidSvcGattCharacteristicCount]; - BleGattCharacteristicInstance input_report_chars[BLE_SVC_HID_INPUT_REPORT_COUNT]; - BleGattCharacteristicInstance output_report_chars[BLE_SVC_HID_OUTPUT_REPORT_COUNT]; - BleGattCharacteristicInstance feature_report_chars[BLE_SVC_HID_FEATURE_REPORT_COUNT]; - GapSvcEventHandler* event_handler; -}; - -static BleEventAckStatus ble_svc_hid_event_handler(void* event, void* context) { - UNUSED(context); - - BleEventAckStatus ret = BleEventNotAck; - hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data); - evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data; - // aci_gatt_attribute_modified_event_rp0* attribute_modified; - - if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) { - if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) { - // Process modification events - ret = BleEventAckFlowEnable; - } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { - // Process notification confirmation - ret = BleEventAckFlowEnable; - } - } - return ret; -} - -BleServiceHid* ble_svc_hid_start(void) { - BleServiceHid* hid_svc = malloc(sizeof(BleServiceHid)); - - // Register event handler - hid_svc->event_handler = - ble_event_dispatcher_register_svc_handler(ble_svc_hid_event_handler, hid_svc); - /** - * Add Human Interface Device Service - */ - if(!ble_gatt_service_add( - UUID_TYPE_16, - &ble_svc_hid_uuid, - PRIMARY_SERVICE, - 2 + /* protocol mode */ - (4 * BLE_SVC_HID_INPUT_REPORT_COUNT) + (3 * BLE_SVC_HID_OUTPUT_REPORT_COUNT) + - (3 * BLE_SVC_HID_FEATURE_REPORT_COUNT) + 1 + 2 + 2 + - 2, /* Service + Report Map + HID Information + HID Control Point */ - &hid_svc->svc_handle)) { - free(hid_svc); - return NULL; - } - - // Maintain previously defined characteristic order - ble_gatt_characteristic_init( - hid_svc->svc_handle, - &ble_svc_hid_chars[HidSvcGattCharacteristicProtocolMode], - &hid_svc->chars[HidSvcGattCharacteristicProtocolMode]); - - uint8_t protocol_mode = 1; - ble_gatt_characteristic_update( - hid_svc->svc_handle, - &hid_svc->chars[HidSvcGattCharacteristicProtocolMode], - &protocol_mode); - - // reports - BleGattCharacteristicDescriptorParams ble_svc_hid_char_descr; - BleGattCharacteristicParams report_char; - HidSvcReportId report_id; - - memcpy( - &ble_svc_hid_char_descr, &ble_svc_hid_char_descr_template, sizeof(ble_svc_hid_char_descr)); - memcpy(&report_char, &ble_svc_hid_report_template, sizeof(report_char)); - - ble_svc_hid_char_descr.data_callback.context = &report_id; - report_char.descriptor_params = &ble_svc_hid_char_descr; - - typedef struct { - uint8_t report_type; - uint8_t report_count; - BleGattCharacteristicInstance* chars; - } HidSvcReportCharProps; - - HidSvcReportCharProps hid_report_chars[] = { - {0x01, BLE_SVC_HID_INPUT_REPORT_COUNT, hid_svc->input_report_chars}, - {0x02, BLE_SVC_HID_OUTPUT_REPORT_COUNT, hid_svc->output_report_chars}, - {0x03, BLE_SVC_HID_FEATURE_REPORT_COUNT, hid_svc->feature_report_chars}, - }; - - for(size_t report_type_idx = 0; report_type_idx < COUNT_OF(hid_report_chars); - report_type_idx++) { - report_id.report_type = hid_report_chars[report_type_idx].report_type; - for(size_t report_idx = 0; report_idx < hid_report_chars[report_type_idx].report_count; - report_idx++) { - report_id.report_idx = report_idx + 1; - ble_gatt_characteristic_init( - hid_svc->svc_handle, - &report_char, - &hid_report_chars[report_type_idx].chars[report_idx]); - } - } - - // Setup remaining characteristics - for(size_t i = HidSvcGattCharacteristicReportMap; i < HidSvcGattCharacteristicCount; i++) { - ble_gatt_characteristic_init( - hid_svc->svc_handle, &ble_svc_hid_chars[i], &hid_svc->chars[i]); - } - - return hid_svc; -} - -bool ble_svc_hid_update_report_map(BleServiceHid* hid_svc, const uint8_t* data, uint16_t len) { - furi_assert(data); - furi_assert(hid_svc); - - HidSvcDataWrapper report_data = { - .data_ptr = data, - .data_len = len, - }; - return ble_gatt_characteristic_update( - hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicReportMap], &report_data); -} - -bool ble_svc_hid_update_input_report( - BleServiceHid* hid_svc, - uint8_t input_report_num, - uint8_t* data, - uint16_t len) { - furi_assert(data); - furi_assert(hid_svc); - furi_assert(input_report_num < BLE_SVC_HID_INPUT_REPORT_COUNT); - - HidSvcDataWrapper report_data = { - .data_ptr = data, - .data_len = len, - }; - - return ble_gatt_characteristic_update( - hid_svc->svc_handle, &hid_svc->input_report_chars[input_report_num], &report_data); -} - -bool ble_svc_hid_update_info(BleServiceHid* hid_svc, uint8_t* data) { - furi_assert(data); - furi_assert(hid_svc); - - return ble_gatt_characteristic_update( - hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicInfo], &data); -} - -void ble_svc_hid_stop(BleServiceHid* hid_svc) { - furi_assert(hid_svc); - ble_event_dispatcher_unregister_svc_handler(hid_svc->event_handler); - // Delete characteristics - for(size_t i = 0; i < HidSvcGattCharacteristicCount; i++) { - ble_gatt_characteristic_delete(hid_svc->svc_handle, &hid_svc->chars[i]); - } - - typedef struct { - uint8_t report_count; - BleGattCharacteristicInstance* chars; - } HidSvcReportCharProps; - - HidSvcReportCharProps hid_report_chars[] = { - {BLE_SVC_HID_INPUT_REPORT_COUNT, hid_svc->input_report_chars}, - {BLE_SVC_HID_OUTPUT_REPORT_COUNT, hid_svc->output_report_chars}, - {BLE_SVC_HID_FEATURE_REPORT_COUNT, hid_svc->feature_report_chars}, - }; - - for(size_t report_type_idx = 0; report_type_idx < COUNT_OF(hid_report_chars); - report_type_idx++) { - for(size_t report_idx = 0; report_idx < hid_report_chars[report_type_idx].report_count; - report_idx++) { - ble_gatt_characteristic_delete( - hid_svc->svc_handle, &hid_report_chars[report_type_idx].chars[report_idx]); - } - } - - // Delete service - ble_gatt_service_delete(hid_svc->svc_handle); - free(hid_svc); -} diff --git a/applications/main/bad_usb/helpers/ble_hid_service.h b/applications/main/bad_usb/helpers/ble_hid_service.h deleted file mode 100644 index e1ac3b0be..000000000 --- a/applications/main/bad_usb/helpers/ble_hid_service.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -// Based on - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BleServiceHid BleServiceHid; - -BleServiceHid* ble_svc_hid_start(void); - -void ble_svc_hid_stop(BleServiceHid* service); - -bool ble_svc_hid_update_report_map(BleServiceHid* service, const uint8_t* data, uint16_t len); - -bool ble_svc_hid_update_input_report( - BleServiceHid* service, - uint8_t input_report_num, - uint8_t* data, - uint16_t len); - -// Expects data to be of length BLE_SVC_HID_INFO_LEN (4 bytes) -bool ble_svc_hid_update_info(BleServiceHid* service, uint8_t* data); - -#ifdef __cplusplus -} -#endif diff --git a/applications/main/bad_usb/helpers/ducky_script.c b/applications/main/bad_usb/helpers/ducky_script.c index 4b427b759..2c8b31e1d 100644 --- a/applications/main/bad_usb/helpers/ducky_script.c +++ b/applications/main/bad_usb/helpers/ducky_script.c @@ -257,7 +257,7 @@ static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) { } static bool ducky_set_ble_id(BadUsbScript* bad_usb, const char* line) { - BleProfileHidParams* ble_hid_cfg = &bad_usb->hid_cfg->ble; + BleProfileHidExtParams* ble_hid_cfg = &bad_usb->hid_cfg->ble; size_t line_len = strlen(line); size_t mac_len = sizeof(ble_hid_cfg->mac) * 3; // 2 hex chars + separator per byte diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_config.c b/applications/main/bad_usb/scenes/bad_usb_scene_config.c index 5c59fe6b9..adf989dfc 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_config.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_config.c @@ -84,7 +84,7 @@ static void draw_menu(BadUsbApp* bad_usb) { item, bad_usb->interface == BadUsbHidInterfaceBle ? "BLE" : "USB"); if(bad_usb->interface == BadUsbHidInterfaceBle) { - BleProfileHidParams* ble_hid_cfg = &bad_usb->script_hid_cfg.ble; + BleProfileHidExtParams* ble_hid_cfg = &bad_usb->script_hid_cfg.ble; item = variable_item_list_add( var_item_list, diff --git a/applications/main/bad_usb/views/bad_usb_view.c b/applications/main/bad_usb/views/bad_usb_view.c index 4032ea974..d6f6683ec 100644 --- a/applications/main/bad_usb/views/bad_usb_view.c +++ b/applications/main/bad_usb/views/bad_usb_view.c @@ -3,6 +3,7 @@ #include #include #include +#include #define MAX_NAME_LEN 64 @@ -19,6 +20,7 @@ typedef struct { bool pause_wait; uint8_t anim_frame; BadUsbHidInterface interface; + Bt* bt; } BadUsbModel; static void bad_usb_draw_callback(Canvas* canvas, void* _model) { @@ -34,8 +36,12 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { } else { furi_string_printf(disp_str, "(%s)", model->layout); } - uint32_t e = model->state.elapsed; - furi_string_cat_printf(disp_str, " %02lu:%02lu.%ld", e / 60 / 1000, e / 1000, e % 1000); + if(model->interface == BadUsbHidInterfaceBle && model->bt->pin_code) { + furi_string_cat_printf(disp_str, " PIN: %ld", model->bt->pin_code); + } else { + uint32_t e = model->state.elapsed; + furi_string_cat_printf(disp_str, " %02lu:%02lu.%ld", e / 60 / 1000, e / 1000, e % 1000); + } elements_string_fit_width(canvas, disp_str, 128 - 2); canvas_draw_str( canvas, 2, 8 + canvas_current_font_height(canvas), furi_string_get_cstr(disp_str)); @@ -217,11 +223,15 @@ BadUsb* bad_usb_view_alloc(void) { view_set_draw_callback(bad_usb->view, bad_usb_draw_callback); view_set_input_callback(bad_usb->view, bad_usb_input_callback); + with_view_model( + bad_usb->view, BadUsbModel * model, { model->bt = furi_record_open(RECORD_BT); }, true); + return bad_usb; } void bad_usb_view_free(BadUsb* bad_usb) { furi_assert(bad_usb); + furi_record_close(RECORD_BT); view_free(bad_usb->view); free(bad_usb); } From 3aa75341d68d3cbedf7de483d15fd320ab8fef73 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 04:39:04 +0300 Subject: [PATCH 09/14] NFC: Fix incorrect Saflok year formula by Eltrick --- applications/main/nfc/plugins/supported_cards/saflok.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/main/nfc/plugins/supported_cards/saflok.c b/applications/main/nfc/plugins/supported_cards/saflok.c index 9940b7cb1..9cab61ee5 100644 --- a/applications/main/nfc/plugins/supported_cards/saflok.c +++ b/applications/main/nfc/plugins/supported_cards/saflok.c @@ -347,8 +347,8 @@ bool saflok_parse(const NfcDevice* device, FuriString* parsed_data) { uint8_t interval_minute = decodedBA[10] & 0x3F; // Bytes 11-13: Creation date since 1980 Jan 1st - uint16_t creation_year = (((decodedBA[11] & 0xF0) >> 4) + SAFLOK_YEAR_OFFSET) | - creation_year_bits; + uint16_t creation_year = + (creation_year_bits | ((decodedBA[11] & 0xF0) >> 4)) + SAFLOK_YEAR_OFFSET; uint8_t creation_month = decodedBA[11] & 0x0F; uint8_t creation_day = (decodedBA[12] >> 3) & 0x1F; uint8_t creation_hour = ((decodedBA[12] & 0x07) << 2) | (decodedBA[13] >> 6); From 610fd68b7572cd502d385c5f84d8ad2ae02b585e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 04:59:05 +0300 Subject: [PATCH 10/14] RFID: Add additional procotols supported by EM4305 chipset by jamisonderek --- lib/lfrfid/protocols/protocol_electra.c | 3 +-- lib/lfrfid/protocols/protocol_fdx_b.c | 15 ++++++++++++ lib/lfrfid/protocols/protocol_gproxii.c | 14 +++++++++++ lib/lfrfid/protocols/protocol_jablotron.c | 13 ++++++++++ lib/lfrfid/protocols/protocol_securakey.c | 29 +++++++++++++++++++++++ 5 files changed, 72 insertions(+), 2 deletions(-) diff --git a/lib/lfrfid/protocols/protocol_electra.c b/lib/lfrfid/protocols/protocol_electra.c index 50d82c8f1..d107cd6e3 100644 --- a/lib/lfrfid/protocols/protocol_electra.c +++ b/lib/lfrfid/protocols/protocol_electra.c @@ -406,8 +406,7 @@ bool protocol_electra_write_data(ProtocolElectra* protocol, void* data) { request->t5577.block[4] = protocol->encoded_epilogue & 0xFFFFFFFF; request->t5577.blocks_to_write = 5; result = true; - } - if(request->write_type == LFRFIDWriteTypeEM4305) { + } else if(request->write_type == LFRFIDWriteTypeEM4305) { request->em4305.word[4] = (EM4x05_MODULATION_MANCHESTER | EM4x05_SET_BITRATE(64) | (8 << EM4x05_MAXBLOCK_SHIFT)); uint64_t encoded_data_reversed = 0; diff --git a/lib/lfrfid/protocols/protocol_fdx_b.c b/lib/lfrfid/protocols/protocol_fdx_b.c index 3de2b661b..df37a7e0f 100644 --- a/lib/lfrfid/protocols/protocol_fdx_b.c +++ b/lib/lfrfid/protocols/protocol_fdx_b.c @@ -369,6 +369,21 @@ bool protocol_fdx_b_write_data(ProtocolFDXB* protocol, void* data) { request->t5577.block[4] = bit_lib_get_bits_32(protocol->encoded_data, 96, 32); request->t5577.blocks_to_write = 5; result = true; + } else if(request->write_type == LFRFIDWriteTypeEM4305) { + request->em4305.word[4] = + (EM4x05_MODULATION_BIPHASE | EM4x05_SET_BITRATE(32) | (8 << EM4x05_MAXBLOCK_SHIFT)); + uint32_t encoded_data_reversed[4] = {0}; + for(uint8_t i = 0; i < 128; i++) { + encoded_data_reversed[i / 32] = + (encoded_data_reversed[i / 32] << 1) | + (bit_lib_get_bit(protocol->encoded_data, (127 - i)) & 1); + } + request->em4305.word[5] = encoded_data_reversed[3]; + request->em4305.word[6] = encoded_data_reversed[2]; + request->em4305.word[7] = encoded_data_reversed[1]; + request->em4305.word[8] = encoded_data_reversed[0]; + request->em4305.mask = 0x1F0; + result = true; } return result; } diff --git a/lib/lfrfid/protocols/protocol_gproxii.c b/lib/lfrfid/protocols/protocol_gproxii.c index 341d092e9..18d20ee75 100644 --- a/lib/lfrfid/protocols/protocol_gproxii.c +++ b/lib/lfrfid/protocols/protocol_gproxii.c @@ -287,6 +287,20 @@ bool protocol_gproxii_write_data(ProtocolGProxII* protocol, void* data) { request->t5577.block[3] = bit_lib_get_bits_32(protocol->data, 64, 32); request->t5577.blocks_to_write = 4; result = true; + } else if(request->write_type == LFRFIDWriteTypeEM4305) { + request->em4305.word[4] = + (EM4x05_MODULATION_BIPHASE | EM4x05_SET_BITRATE(64) | (7 << EM4x05_MAXBLOCK_SHIFT)); + uint32_t encoded_data_reversed[3] = {0}; + for(uint8_t i = 0; i < 96; i++) { + encoded_data_reversed[i / 32] = (encoded_data_reversed[i / 32] << 1) | + (bit_lib_get_bit(protocol->data, (95 - i)) & 1); + encoded_data_reversed[i / 32] ^= 1; // Invert to make DIPHASE/BIPHASE. + } + request->em4305.word[5] = encoded_data_reversed[2]; + request->em4305.word[6] = encoded_data_reversed[1]; + request->em4305.word[7] = encoded_data_reversed[0]; + request->em4305.mask = 0xF0; + result = true; } return result; } diff --git a/lib/lfrfid/protocols/protocol_jablotron.c b/lib/lfrfid/protocols/protocol_jablotron.c index 643bb1be6..8e3628a3b 100644 --- a/lib/lfrfid/protocols/protocol_jablotron.c +++ b/lib/lfrfid/protocols/protocol_jablotron.c @@ -182,6 +182,19 @@ bool protocol_jablotron_write_data(ProtocolJablotron* protocol, void* data) { request->t5577.block[2] = bit_lib_get_bits_32(protocol->encoded_data, 32, 32); request->t5577.blocks_to_write = 3; result = true; + } else if(request->write_type == LFRFIDWriteTypeEM4305) { + request->em4305.word[4] = + (EM4x05_MODULATION_BIPHASE | EM4x05_SET_BITRATE(64) | (6 << EM4x05_MAXBLOCK_SHIFT)); + uint32_t encoded_data_reversed[2] = {0}; + for(uint8_t i = 0; i < 64; i++) { + encoded_data_reversed[i / 32] = + (encoded_data_reversed[i / 32] << 1) | + (bit_lib_get_bit(protocol->encoded_data, (63 - i)) & 1); + } + request->em4305.word[5] = encoded_data_reversed[1]; + request->em4305.word[6] = encoded_data_reversed[0]; + request->em4305.mask = 0x70; + result = true; } return result; } diff --git a/lib/lfrfid/protocols/protocol_securakey.c b/lib/lfrfid/protocols/protocol_securakey.c index 947b68e72..9c9fb8ab1 100644 --- a/lib/lfrfid/protocols/protocol_securakey.c +++ b/lib/lfrfid/protocols/protocol_securakey.c @@ -328,6 +328,20 @@ bool protocol_securakey_write_data(ProtocolSecurakey* protocol, void* data) { request->t5577.block[2] = bit_lib_get_bits_32(protocol->RKKTH_encoded_data, 32, 32); request->t5577.blocks_to_write = 3; result = true; + } else if(request->write_type == LFRFIDWriteTypeEM4305) { + request->em4305.word[4] = + (EM4x05_MODULATION_MANCHESTER | EM4x05_SET_BITRATE(40) | // requires 330pF card + (6 << EM4x05_MAXBLOCK_SHIFT)); + uint32_t encoded_data_reversed[2] = {0}; + for(uint8_t i = 0; i < 64; i++) { + encoded_data_reversed[i / 32] = + (encoded_data_reversed[i / 32] << 1) | + (bit_lib_get_bit(protocol->RKKTH_encoded_data, (63 - i)) & 1); + } + request->em4305.word[5] = encoded_data_reversed[1]; + request->em4305.word[6] = encoded_data_reversed[0]; + request->em4305.mask = 0x70; + result = true; } } else { if(request->write_type == LFRFIDWriteTypeT5577) { @@ -340,6 +354,21 @@ bool protocol_securakey_write_data(ProtocolSecurakey* protocol, void* data) { request->t5577.block[3] = bit_lib_get_bits_32(protocol->RKKT_encoded_data, 64, 32); request->t5577.blocks_to_write = 4; result = true; + } else if(request->write_type == LFRFIDWriteTypeEM4305) { + request->em4305.word[4] = + (EM4x05_MODULATION_MANCHESTER | EM4x05_SET_BITRATE(40) | // requires 330pF card + (7 << EM4x05_MAXBLOCK_SHIFT)); + uint32_t encoded_data_reversed[3] = {0}; + for(uint8_t i = 0; i < 96; i++) { + encoded_data_reversed[i / 32] = + (encoded_data_reversed[i / 32] << 1) | + (bit_lib_get_bit(protocol->RKKT_encoded_data, (95 - i)) & 1); + } + request->em4305.word[5] = encoded_data_reversed[2]; + request->em4305.word[6] = encoded_data_reversed[1]; + request->em4305.word[7] = encoded_data_reversed[0]; + request->em4305.mask = 0xF0; + result = true; } } return result; From 7646902fdc9fda2d9080affa28240053aefe0bb3 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 05:04:02 +0300 Subject: [PATCH 11/14] JS: Expose button event type in gui/widget button callback by WillyJL --- .../examples/apps/Scripts/js_examples/gui.js | 10 +++- .../{ => js_examples}/uart_echo_8e1.js | 0 .../system/js_app/modules/js_gui/widget.c | 53 ++++++++++++++----- .../create-fz-app/template/package.json | 2 +- .../js_app/packages/fz-sdk/gui/widget.d.ts | 6 ++- documentation/js/js_gui__widget.md | 17 ++++++ documentation/js/js_serial.md | 1 + 7 files changed, 72 insertions(+), 17 deletions(-) rename applications/system/js_app/examples/apps/Scripts/{ => js_examples}/uart_echo_8e1.js (100%) diff --git a/applications/system/js_app/examples/apps/Scripts/js_examples/gui.js b/applications/system/js_app/examples/apps/Scripts/js_examples/gui.js index bc63a7ef6..9b7042848 100644 --- a/applications/system/js_app/examples/apps/Scripts/js_examples/gui.js +++ b/applications/system/js_app/examples/apps/Scripts/js_examples/gui.js @@ -62,6 +62,12 @@ let views = { }), }; +// Enable illegal filename symbols since we're not choosing filenames, gives more flexibility +// Not available in all firmwares, good idea to check if it is supported +if (doesSdkSupport(["gui-textinput-illegalsymbols"])) { + views.keyboard.set("illegalSymbols", true); +} + // demo selector eventLoop.subscribe(views.demos.chosen, function (_sub, index, gui, eventLoop, views) { if (index === 0) { @@ -131,8 +137,8 @@ eventLoop.subscribe(gui.viewDispatcher.navigation, function (_sub, _, gui, views }, gui, views, eventLoop); // go to the demo chooser screen when the right key is pressed on the widget screen -eventLoop.subscribe(views.stopwatchWidget.button, function (_sub, buttonId, gui, views) { - if (buttonId === "right") +eventLoop.subscribe(views.stopwatchWidget.button, function (_sub, buttonEvent, gui, views) { + if (buttonEvent.key === "right" && buttonEvent.type === "short") gui.viewDispatcher.switchTo(views.demos); }, gui, views); diff --git a/applications/system/js_app/examples/apps/Scripts/uart_echo_8e1.js b/applications/system/js_app/examples/apps/Scripts/js_examples/uart_echo_8e1.js similarity index 100% rename from applications/system/js_app/examples/apps/Scripts/uart_echo_8e1.js rename to applications/system/js_app/examples/apps/Scripts/js_examples/uart_echo_8e1.js diff --git a/applications/system/js_app/modules/js_gui/widget.c b/applications/system/js_app/modules/js_gui/widget.c index bb2898030..47149b4ac 100644 --- a/applications/system/js_app/modules/js_gui/widget.c +++ b/applications/system/js_app/modules/js_gui/widget.c @@ -10,6 +10,11 @@ typedef struct { #define QUEUE_LEN 2 +typedef struct { + GuiButtonType key; + InputType type; +} JsWidgetButtonEvent; + /** * @brief Parses position (X and Y) from an element declaration object */ @@ -101,8 +106,11 @@ static bool element_get_text(struct mjs* mjs, mjs_val_t element, mjs_val_t* text * @brief Widget button element callback */ static void js_widget_button_callback(GuiButtonType result, InputType type, JsWidgetCtx* context) { - UNUSED(type); - furi_check(furi_message_queue_put(context->queue, &result, 0) == FuriStatusOk); + JsWidgetButtonEvent event = { + .key = result, + .type = type, + }; + furi_check(furi_message_queue_put(context->queue, &event, 0) == FuriStatusOk); } #define DESTRUCTURE_OR_RETURN(mjs, child_obj, part, ...) \ @@ -263,25 +271,44 @@ static mjs_val_t js_widget_button_event_transformer( FuriMessageQueue* queue, JsWidgetCtx* context) { UNUSED(context); - GuiButtonType btn_type; - furi_check(furi_message_queue_get(queue, &btn_type, 0) == FuriStatusOk); - const char* btn_name; - if(btn_type == GuiButtonTypeLeft) { - btn_name = "left"; - } else if(btn_type == GuiButtonTypeCenter) { - btn_name = "center"; - } else if(btn_type == GuiButtonTypeRight) { - btn_name = "right"; + JsWidgetButtonEvent event; + furi_check(furi_message_queue_get(queue, &event, 0) == FuriStatusOk); + const char* event_key; + if(event.key == GuiButtonTypeLeft) { + event_key = "left"; + } else if(event.key == GuiButtonTypeCenter) { + event_key = "center"; + } else if(event.key == GuiButtonTypeRight) { + event_key = "right"; } else { furi_crash(); } - return mjs_mk_string(mjs, btn_name, ~0, false); + const char* event_type; + if(event.type == InputTypePress) { + event_type = "press"; + } else if(event.type == InputTypeRelease) { + event_type = "release"; + } else if(event.type == InputTypeShort) { + event_type = "short"; + } else if(event.type == InputTypeLong) { + event_type = "long"; + } else if(event.type == InputTypeRepeat) { + event_type = "repeat"; + } else { + furi_crash(); + } + mjs_val_t obj = mjs_mk_object(mjs); + JS_ASSIGN_MULTI(mjs, obj) { + JS_FIELD("key", mjs_mk_string(mjs, event_key, ~0, true)); + JS_FIELD("type", mjs_mk_string(mjs, event_type, ~0, true)); + } + return obj; } static void* js_widget_custom_make(struct mjs* mjs, Widget* widget, mjs_val_t view_obj) { UNUSED(widget); JsWidgetCtx* context = malloc(sizeof(JsWidgetCtx)); - context->queue = furi_message_queue_alloc(QUEUE_LEN, sizeof(GuiButtonType)); + context->queue = furi_message_queue_alloc(QUEUE_LEN, sizeof(JsWidgetButtonEvent)); context->contract = (JsEventLoopContract){ .magic = JsForeignMagic_JsEventLoopContract, .object_type = JsEventLoopObjectTypeQueue, diff --git a/applications/system/js_app/packages/create-fz-app/template/package.json b/applications/system/js_app/packages/create-fz-app/template/package.json index 211411c73..a7f69cf22 100644 --- a/applications/system/js_app/packages/create-fz-app/template/package.json +++ b/applications/system/js_app/packages/create-fz-app/template/package.json @@ -6,7 +6,7 @@ "start": "npm run build && node node_modules/@darkflippers/fz-sdk-ul/sdk.js upload" }, "devDependencies": { - "@darkflippers/fz-sdk-ul": "^0.1", + "@next-flip/fz-sdk-mntm": "^0.3", "typescript": "^5.6.3" } } \ No newline at end of file diff --git a/applications/system/js_app/packages/fz-sdk/gui/widget.d.ts b/applications/system/js_app/packages/fz-sdk/gui/widget.d.ts index bf4aab22b..c524c53cb 100644 --- a/applications/system/js_app/packages/fz-sdk/gui/widget.d.ts +++ b/applications/system/js_app/packages/fz-sdk/gui/widget.d.ts @@ -58,12 +58,16 @@ type Element = StringMultilineElement type Props = {}; type Child = Element; +declare class ButtonEvent { + key: "left" | "center" | "right"; + type: "press" | "release" | "short" | "long" | "repeat"; +} declare class Widget extends View { /** * Event source for buttons. Only gets fired if there's a corresponding * button element. */ - button: Contract<"left" | "center" | "right">; + button: Contract; } declare class WidgetFactory extends ViewFactory { } declare const factory: WidgetFactory; diff --git a/documentation/js/js_gui__widget.md b/documentation/js/js_gui__widget.md index 9ea3e4dfa..4c922a67c 100644 --- a/documentation/js/js_gui__widget.md +++ b/documentation/js/js_gui__widget.md @@ -35,3 +35,20 @@ Elements are objects with properties to define them, in the form `{ element: "ty | `rect` | `x` (number), `y` (number)
`w` (number), `h` (number)
`radius` (number), `fill` (boolean) | Draw a rectangle, optionally rounded and filled. | | `circle` | `x` (number), `y` (number)
`radius` (number), `fill` (boolean) | Draw a circle, optionally filled. | | `line` | `x1` (number), `y1` (number)
`x2` (number), `y2` (number) | Draw a line between 2 points. | + +## Structures + +### ButtonEvent + +Button event information structure. + +**Fields** + +- key: The key that was pressed (`"left" | "center" | "right"`) +- type: The type of the event (`"press" | "release" | "short" | "long" | "repeat"`) + +## View events + +| Item | Type | Description | +|----------|--------|-----------------------------------------------------------------------------| +| `button` | `ButtonEvent`| Fires when the user presses on one of the three possible buttons if there's a corresponding button element. Refer to the `ButtonEvent` structure above for possible values. | diff --git a/documentation/js/js_serial.md b/documentation/js/js_serial.md index d06c799ac..c45ae5f74 100644 --- a/documentation/js/js_serial.md +++ b/documentation/js/js_serial.md @@ -7,6 +7,7 @@ let serial = require("serial"); ## setup() Configure serial port. Should be called before all other methods. +Automatically disables Expansion module service to prevent interference. **Parameters** From 979e428ad8b7ed381e69d0a8239019edba903e79 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 06:01:45 +0300 Subject: [PATCH 12/14] upd changelog --- CHANGELOG.md | 66 +++++++--------------------------------------------- 1 file changed, 8 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e33b7843f..18454fba1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,65 +1,15 @@ ## Main changes - Current API: 86.0 -* SubGHz: **Roger (static 28 bit) with add manually support** (by @xMasterX & @mishamyte) -* SubGHz: **V2 Phoenix full support** (button switch, add manually, counter decrypt/encrypt) (by @xMasterX & @RocketGod-git, original code by @Skorpionm) -* SubGHz: **Keeloq: Add support for - Motorline (with add manually support), Rosh, Pecinin, Rossi, Merlin, Steelmate** (by @xMasterX & @RocketGod-git) -* SubGHz: **Nero Radio static parse** and display more data -* SubGHz: Reduce less popular freqs in default hopper preset, **make it faster** -* SubGHz: **Marantec protocol implement CRC verification display and Add manually support** (by @xMasterX & @li0ard, original code by @Skorpionm) -* SubGHz: **Keeloq: Comunello - add manually support** -* iButton: **TM01x Dallas write support** (PR #899 | by @Leptopt1los) -* SubGHz: Rename and **extend Alarms, Sensors, Cars ignore options** (Alarms: Hollarm, GangQi | Cars: Kia, Starline, ScherKhan | Sensors: Magellan, Honeywell, Honeywell WDB (doorbells), Legrand (doorbells), Feron (RGB lights)) -* SubGHz: V2 Phoenix show counter value (upd: see above, now decrypted) -* SubGHz: **Add Keeloq IronLogic (aka IL100) smart clone remote copiers support** (thanks to Vitaly for RAWs) -* SubGHz: **Fix CAME 24bit decoder** -* SubGHz: Add 462.750 MHz & 868.46 MHz to default subghz freqs list -* SubGHz: **Tune Holtek HT12x to decode Holtek only** and not conflict with came 12bit -* SubGHz: Fix Rename scene bug, that was replacing file name with random name when Rename is opened then closed then opened again -* Display: Backlight option "always on" and RGB bug removed (PR #900 | by @Dmitry422) -* NFC: Ultralight C - Attempt of authentication with default key (PR #898 | by @mishamyte) -* System: Loader - Fix misplaced ApplicationBeforeLoad events (PR #905 | by @WillyJL) -* OFW PR 4210: Infrared: Add text scroll to remote buttons (by @956MB) -* NFC: - - **NFC Type 4 support + many other improvements** (by @WillyJL) - - New Type 4 Tag (NDEF on NTAG4xx / MIFARE DESFire) protocol, full support - - New NTAG4xx (NTAG413 DNA / NTAG424 DNA) protocol, only detection and basic info support - - NDEF parsing plugin supports Type 4 Tag protocol - - Show more version info for MIFARE Plus cards - - Improve detection/verification of MIFARE DESFire and MIFARE Plus SE - - Improve navigation for MIFARE Classic Update from / Write to Initial Card - - Refactor Write code for MIFARE Ultralight/Classic in NFC app helpers - - Cleanup event handling in NFC app - - NFC app uses a bit less RAM because of previous 2 points - - Refactor NXP Native Commands to share between protocols (used by MIFARE DESFire, MIFARE Plus, NTAG4xx) - - MIFARE DESFire poller API can now switch between native and ISO7816-wrapped commands - - Expand ISO14443-4A API with listener (emulation) support for sending responses to reader (except I-block chaining) - - Exposed some APIs for apps to use that were meant to be public: - - ISO14443-3A listener (emulation) - - ISO15693-3 device (data), poller (reading), listener (emulation) - - Cleanup/reorder protocol definitions for tidyness - - Ventra ULEV1 parser (by @hazardousvoltage) - - CSC Service Works parser (by @zinongli) - - Philips Sonicare parser (by @Sil333033) - - SmartRider parser (by @jaylikesbunda) +* SubGHz: Add variant of 'Add Manually' menu with manual editing for each value (PR #909 | by @MrLego8-9) +* OFW PR 4251: CLI: Fix long delay with quick connect/disconnect (by @WillyJL) +* LFRFID: Add additional procotols supported by EM4305 chipset (by @jamisonderek) * Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev) ## Other changes -* BadUSB: Fix modifier keys with HOLD/RELEASE commands (by @WillyJL) -* Docs: Update doorhan programming instructions (by @li0ard) -* FuriHalSerial: Fix RXFNE interrupt hang, aka freezing with UART output when Expansion Modules are enabled (by @WillyJL) -* Expansion: add is_connected api (by @HaxSam & @WillyJL) -* RFID 125khz: Fix strange bug with LCD backlight going off after doing "Write" -* GUI: Added `submenu_remove_item()` to API, was needed for NFC Type 4 related changes (by @WillyJL) -* SubGHz: Fix possible frequency analyzer deadlock when holding Ok (by @WillyJL) -* RFID 125khz: Add DEZ10 representation to EM410X (by @realcatgirly) -* OFW PR 4205: fix sample durations when using external CC1101 (by @Aerosnail) -* OFW PR 4206: Stop JS PWM on exit (by @portasynthinca3) -* OFW PR 4212: Fixed inverted logic condition in subghz chat cli (by @GameLord2011) -* NFC: Fix clipper date timestamp (PR #903 | by @luu176) -* Desktop: DEBUG - fix desktop anim switch override by favourite apps -* CLI: Various fixes (by @WillyJL) -* BadUSB: Fix key combos main keys being case sensitive (by @WillyJL) -* System: log level none after update -* Docs: Some updates on subghz remotes programming +* Input Settings: Add Vibro Trigger option (by @956MB & @WillyJL) +* BT Remote: Add Rename Option (by @aaronjamt & @WillyJL) +* Simplify Bad USB BLE profile (by @aaronjamt & @WillyJL) +* NFC: Fix incorrect Saflok year formula (by @Eltrick) +* JS: Expose button event type in gui/widget button callback (by @WillyJL)

#### Known NFC post-refactor regressions list: - Mifare Mini clones reading is broken (original mini working fine) (OFW) From 9ab4fcb256ddda31d572c467e9c33623e01394a8 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 30 Jul 2025 06:03:25 +0300 Subject: [PATCH 13/14] fmt --- .../main/subghz/helpers/subghz_gen_info.c | 1408 ++++++++--------- .../main/subghz/helpers/subghz_gen_info.h | 2 +- .../subghz/scenes/subghz_scene_set_button.c | 72 +- .../subghz/scenes/subghz_scene_set_counter.c | 230 +-- .../main/subghz/scenes/subghz_scene_set_key.c | 7 +- .../subghz/scenes/subghz_scene_set_seed.c | 119 +- .../subghz/scenes/subghz_scene_set_serial.c | 122 +- .../subghz/scenes/subghz_scene_set_type.c | 225 +-- 8 files changed, 1088 insertions(+), 1097 deletions(-) diff --git a/applications/main/subghz/helpers/subghz_gen_info.c b/applications/main/subghz/helpers/subghz_gen_info.c index 00ff43abc..f6abec0c6 100644 --- a/applications/main/subghz/helpers/subghz_gen_info.c +++ b/applications/main/subghz/helpers/subghz_gen_info.c @@ -2,14 +2,13 @@ #include "../helpers/subghz_txrx_create_protocol_key.h" #include - -void subghz_gen_info_reset(GenInfo *gen_info) { +void subghz_gen_info_reset(GenInfo* gen_info) { furi_assert(gen_info); memset(gen_info, 0, sizeof(GenInfo)); } void subghz_scene_set_type_fill_generation_infos(GenInfo* infos_dest, SetType type) { - GenInfo gen_info = { 0 }; + GenInfo gen_info = {0}; uint64_t key = (uint64_t)rand(); uint64_t gangqi_key; @@ -19,707 +18,706 @@ void subghz_scene_set_type_fill_generation_infos(GenInfo* infos_dest, SetType ty subghz_txrx_gen_key_marantec(&marantec_key); switch(type) { - case SetTypePricenton433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_PRINCETON_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 400}; - break; - case SetTypePricenton315: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 315000000, - .data.name = SUBGHZ_PROTOCOL_PRINCETON_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 400}; - break; - case SetTypeNiceFlo12bit: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_NICE_FLO_NAME, - .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 - .data.bits = 12, - .data.te = 0}; - break; - case SetTypeNiceFlo24bit: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_NICE_FLO_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeCAME12bit: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_CAME_NAME, - .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 - .data.bits = 12, - .data.te = 0}; - break; - case SetTypeCAME24bit: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_CAME_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeCAME12bit868: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 868350000, - .data.name = SUBGHZ_PROTOCOL_CAME_NAME, - .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 - .data.bits = 12, - .data.te = 0}; - break; - case SetTypeCAME24bit868: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 868350000, - .data.name = SUBGHZ_PROTOCOL_CAME_NAME, - .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeRoger_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_ROGER_NAME, - .data.key = (key & 0xFFFF000) | 0x0000101, // button code 0x1 and (crc?) is 0x01 - .data.bits = 28, - .data.te = 0}; - break; - case SetTypeLinear_300_00: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 300000000, - .data.name = SUBGHZ_PROTOCOL_LINEAR_NAME, - .data.key = (key & 0x3FF), - .data.bits = 10, - .data.te = 0}; - break; - case SetTypeBETT_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_BETT_NAME, - .data.key = (key & 0x0000FFF0), - .data.bits = 18, - .data.te = 0}; - break; - case SetTypeCAMETwee: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_CAME_TWEE_NAME, - .data.key = 0x003FFF7200000000 | ((key & 0x0FFFFFF0) ^ 0xE0E0E0EE), // ???? - .data.bits = 54, - .data.te = 0}; - break; - case SetTypeGateTX: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_GATE_TX_NAME, // btn 0xF, 0xC, 0xA, 0x6 (?) - .data.key = subghz_protocol_blocks_reverse_key((key & 0x00F0FF00) | 0xF0040, 24), - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeGangQi_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = - SUBGHZ_PROTOCOL_GANGQI_NAME, // Add button 0xD arm and crc sum to the end - .data.key = gangqi_key, - .data.bits = 34, - .data.te = 0}; - break; - case SetTypeHollarm_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_HOLLARM_NAME, // Add button 0x2 and crc sum to the end - .data.key = (key & 0x000FFF0000) | 0xF0B0002200 | - ((((((key & 0x000FFF0000) | 0xF0B0002200) >> 32) & 0xFF) + - ((((key & 0x000FFF0000) | 0xF0B0002200) >> 24) & 0xFF) + - ((((key & 0x000FFF0000) | 0xF0B0002200) >> 16) & 0xFF) + - ((((key & 0x000FFF0000) | 0xF0B0002200) >> 8) & 0xFF)) & - 0xFF), - .data.bits = 42, - .data.te = 0}; - break; - case SetTypeReversRB2_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = SUBGHZ_PROTOCOL_REVERSRB2_NAME, // 64bits no buttons - .data.key = (key & 0x00000FFFFFFFF000) | 0xFFFFF00000000000 | 0x0000000000000A00, - .data.bits = 64, - .data.te = 0}; - break; - case SetTypeMarantec24_868: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 868350000, - .data.name = SUBGHZ_PROTOCOL_MARANTEC24_NAME, // Add button code 0x8 to the end - .data.key = (key & 0xFFFFF0) | 0x000008, - .data.bits = 24, - .data.te = 0}; - break; - case SetTypeMarantec_433: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 433920000, - .data.name = - SUBGHZ_PROTOCOL_MARANTEC_NAME, // Button code is 0x4 and crc sum to the end - .data.key = marantec_key, - .data.bits = 49, - .data.te = 0}; - break; - case SetTypeMarantec_868: - gen_info = (GenInfo){ - .type = GenData, - .mod = "AM650", - .freq = 868350000, - .data.name = - SUBGHZ_PROTOCOL_MARANTEC_NAME, // Button code is 0x4 and crc sum to the end - .data.key = marantec_key, - .data.bits = 49, - .data.te = 0}; - break; - case SetTypeFaacSLH_433: - gen_info = (GenInfo){ - .type = GenFaacSLH, - .mod = "AM650", - .freq = 433920000, - .faac_slh.serial = ((key & 0x00FFFFF0) | 0xA0000006) >> 4, - .faac_slh.btn = 0x06, - .faac_slh.cnt = 0x02, - .faac_slh.seed = key, - .faac_slh.manuf = "FAAC_SLH"}; - break; - case SetTypeFaacSLH_868: - gen_info = (GenInfo){ - .type = GenFaacSLH, - .mod = "AM650", - .freq = 868350000, - .faac_slh.serial = ((key & 0x00FFFFF0) | 0xA0000006) >> 4, - .faac_slh.btn = 0x06, - .faac_slh.cnt = 0x02, - .faac_slh.seed = (key & 0x0FFFFFFF), - .faac_slh.manuf = "FAAC_SLH"}; - break; - case SetTypeBeninca433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFF00) | 0x00800080, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Beninca"}; - break; - case SetTypeBeninca868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 868350000, - .keeloq.serial = (key & 0x000FFF00) | 0x00800080, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Beninca"}; - break; - case SetTypeComunello433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x08, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Comunello"}; - break; - case SetTypeComunello868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 868460000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x08, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Comunello"}; - break; - case SetTypeAllmatic433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x00FFFF00) | 0x01000011, - .keeloq.btn = 0x0C, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Beninca"}; - break; - case SetTypeAllmatic868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 868350000, - .keeloq.serial = (key & 0x00FFFF00) | 0x01000011, - .keeloq.btn = 0x0C, - .keeloq.cnt = 0x05, - .keeloq.manuf = "Beninca"}; - break; - case SetTypeCenturion433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0000FFFF), - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Centurion"}; - break; - case SetTypeMonarch433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0000FFFF), - .keeloq.btn = 0x0A, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Monarch"}; - break; - case SetTypeJollyMotors433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFFFF), - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Jolly_Motors"}; - break; - case SetTypeElmesElectronic: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x00FFFFFF) | 0x02000000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Elmes_Poland"}; - break; - case SetTypeANMotorsAT4: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFFFF) | 0x04700000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x21, - .keeloq.manuf = "AN-Motors"}; - break; - case SetTypeAprimatic: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFFFF) | 0x00600000, - .keeloq.btn = 0x08, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Aprimatic"}; - break; - case SetTypeGibidi433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Gibidi"}; - break; - case SetTypeGSN: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "GSN"}; - break; - case SetTypeIronLogic: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFF0, - .keeloq.btn = 0x04, - .keeloq.cnt = 0x05, - .keeloq.manuf = "IronLogic"}; - break; - case SetTypeStilmatic: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Stilmatic"}; - break; - case SetTypeSommer_FM_434: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "FM476", - .freq = 434420000, - .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Sommer(fsk476)"}; - break; - case SetTypeSommer_FM_868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "FM476", - .freq = 868800000, - .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Sommer(fsk476)"}; - break; - case SetTypeSommer_FM238_434: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "FM238", - .freq = 434420000, - .keeloq.serial = key & 0x0000FFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Sommer(fsk476)"}; - break; - case SetTypeSommer_FM238_868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "FM238", - .freq = 868800000, - .keeloq.serial = key & 0x0000FFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Sommer(fsk476)"}; - break; - case SetTypeDTMNeo433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x000FFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x05, - .keeloq.manuf = "DTM_Neo"}; - break; - case SetTypeCAMESpace: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x04, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Came_Space"}; - break; - case SetTypeCameAtomo433: - gen_info = (GenInfo){ - .type = GenCameAtomo, - .mod = "AM650", - .freq = 433920000, - .came_atomo.serial = (key & 0x0FFFFFFF) | 0x10000000, - .came_atomo.cnt = 0x03}; - break; - case SetTypeCameAtomo868: - gen_info = (GenInfo){ - .type = GenCameAtomo, - .mod = "AM650", - .freq = 868350000, - .came_atomo.serial = (key & 0x0FFFFFFF) | 0x10000000, - .came_atomo.cnt = 0x03}; - break; - case SetTypeBFTMitto: - gen_info = (GenInfo){ - .type = GenKeeloqBFT, - .mod = "AM650", - .freq = 433920000, - .keeloq_bft.serial = key & 0x000FFFFF, - .keeloq_bft.btn = 0x02, - .keeloq_bft.cnt = 0x02, - .keeloq_bft.seed = key & 0x000FFFFF, - .keeloq_bft.manuf = "BFT"}; - break; - case SetTypeAlutechAT4N: - gen_info = (GenInfo){ - .type = GenAlutechAt4n, - .mod = "AM650", - .freq = 433920000, - .alutech_at_4n.serial = (key & 0x000FFFFF) | 0x00100000, - .alutech_at_4n.btn = 0x44, - .alutech_at_4n.cnt = 0x03}; - break; - case SetTypeSomfyTelis: - gen_info = (GenInfo){ - .type = GenSomfyTelis, - .mod = "AM650", - .freq = 433420000, - .somfy_telis.serial = key & 0x00FFFFFF, - .somfy_telis.btn = 0x02, - .somfy_telis.cnt = 0x03}; - break; - case SetTypeMotorline433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Motorline"}; - break; - case SetTypeDoorHan_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "DoorHan"}; - break; - case SetTypeDoorHan_315_00: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 315000000, - .keeloq.serial = key & 0x0FFFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "DoorHan"}; - break; - case SetTypeNiceFlorS_433_92: - gen_info = (GenInfo){ - .type = GenNiceFlorS, - .mod = "AM650", - .freq = 433920000, - .nice_flor_s.serial = key & 0x0FFFFFFF, - .nice_flor_s.btn = 0x01, - .nice_flor_s.cnt = 0x03, - .nice_flor_s.nice_one = false}; - break; - case SetTypeNiceOne_433_92: - gen_info = (GenInfo){ - .type = GenNiceFlorS, - .mod = "AM650", - .freq = 433920000, - .nice_flor_s.serial = key & 0x0FFFFFFF, - .nice_flor_s.btn = 0x01, - .nice_flor_s.cnt = 0x03, - .nice_flor_s.nice_one = true}; - break; - case SetTypeNiceSmilo_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "NICE_Smilo"}; - break; - case SetTypeNiceMHouse_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x09, - .keeloq.cnt = 0x03, - .keeloq.manuf = "NICE_MHOUSE"}; - break; - case SetTypeDeaMio433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0FFFF000) | 0x00000869, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Dea_Mio"}; - break; - case SetTypeGeniusBravo433: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x06, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Genius_Bravo"}; - break; - case SetTypeJCM_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x00FFFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "JCM_Tech"}; - break; - case SetTypeNovoferm_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0000FFFF) | 0x018F0000, - .keeloq.btn = 0x01, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Novoferm"}; - break; - case SetTypeHormannEcoStar_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x000FFFFF) | 0x02200000, - .keeloq.btn = 0x04, - .keeloq.cnt = 0x03, - .keeloq.manuf = "EcoStar"}; - break; - case SetTypeFAACRCXT_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = (key & 0x0000FFFF) | 0x00100000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "FAAC_RC,XT"}; - break; - case SetTypeFAACRCXT_868: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 868350000, - .keeloq.serial = (key & 0x0000FFFF) | 0x00100000, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "FAAC_RC,XT"}; - break; - case SetTypeNormstahl_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x0000FFFF, - .keeloq.btn = 0x04, - .keeloq.cnt = 0x03, - .keeloq.manuf = "Normstahl"}; - break; - case SetTypeHCS101_433_92: - gen_info = (GenInfo){ - .type = GenKeeloq, - .mod = "AM650", - .freq = 433920000, - .keeloq.serial = key & 0x000FFFFF, - .keeloq.btn = 0x02, - .keeloq.cnt = 0x03, - .keeloq.manuf = "HCS101"}; - break; - case SetTypeSecPlus_v1_315_00: - gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 315000000}; - break; - case SetTypeSecPlus_v1_390_00: - gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 390000000}; - break; - case SetTypeSecPlus_v1_433_00: - gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 433920000}; - break; - case SetTypeSecPlus_v2_310_00: - gen_info = (GenInfo){ - .type = GenSecPlus2, - .mod = "AM650", - .freq = 310000000, - .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing - .sec_plus_2.btn = 0x68, - .sec_plus_2.cnt = 0xE500000}; - break; - case SetTypeSecPlus_v2_315_00: - gen_info = (GenInfo){ - .type = GenSecPlus2, - .mod = "AM650", - .freq = 315000000, - .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing - .sec_plus_2.btn = 0x68, - .sec_plus_2.cnt = 0xE500000}; - break; - case SetTypeSecPlus_v2_390_00: - gen_info = (GenInfo){ - .type = GenSecPlus2, - .mod = "AM650", - .freq = 390000000, - .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing - .sec_plus_2.btn = 0x68, - .sec_plus_2.cnt = 0xE500000}; - break; - case SetTypeSecPlus_v2_433_00: - gen_info = (GenInfo){ - .type = GenSecPlus2, - .mod = "AM650", - .freq = 433920000, - .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing - .sec_plus_2.btn = 0x68, - .sec_plus_2.cnt = 0xE500000}; - break; - case SetTypePhoenix_V2_433: - gen_info = (GenInfo){ - .type = GenPhoenixV2, - .mod = "AM650", - .freq = 433920000, - .phoenix_v2.serial = (key & 0x0FFFFFFF) | 0xB0000000, - .phoenix_v2.cnt = 0x025D}; - break; - default: - furi_crash("Not implemented"); - break; - } + case SetTypePricenton433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_PRINCETON_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 400}; + break; + case SetTypePricenton315: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 315000000, + .data.name = SUBGHZ_PROTOCOL_PRINCETON_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 400}; + break; + case SetTypeNiceFlo12bit: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_NICE_FLO_NAME, + .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 + .data.bits = 12, + .data.te = 0}; + break; + case SetTypeNiceFlo24bit: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_NICE_FLO_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeCAME12bit: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_CAME_NAME, + .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 + .data.bits = 12, + .data.te = 0}; + break; + case SetTypeCAME24bit: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_CAME_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeCAME12bit868: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 868350000, + .data.name = SUBGHZ_PROTOCOL_CAME_NAME, + .data.key = (key & 0x00000FF0) | 0x1, // btn 0x1, 0x2, 0x4 + .data.bits = 12, + .data.te = 0}; + break; + case SetTypeCAME24bit868: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 868350000, + .data.name = SUBGHZ_PROTOCOL_CAME_NAME, + .data.key = (key & 0x00FFFFF0) | 0x4, // btn 0x1, 0x2, 0x4, 0x8 + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeRoger_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_ROGER_NAME, + .data.key = (key & 0xFFFF000) | 0x0000101, // button code 0x1 and (crc?) is 0x01 + .data.bits = 28, + .data.te = 0}; + break; + case SetTypeLinear_300_00: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 300000000, + .data.name = SUBGHZ_PROTOCOL_LINEAR_NAME, + .data.key = (key & 0x3FF), + .data.bits = 10, + .data.te = 0}; + break; + case SetTypeBETT_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_BETT_NAME, + .data.key = (key & 0x0000FFF0), + .data.bits = 18, + .data.te = 0}; + break; + case SetTypeCAMETwee: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_CAME_TWEE_NAME, + .data.key = 0x003FFF7200000000 | ((key & 0x0FFFFFF0) ^ 0xE0E0E0EE), // ???? + .data.bits = 54, + .data.te = 0}; + break; + case SetTypeGateTX: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_GATE_TX_NAME, // btn 0xF, 0xC, 0xA, 0x6 (?) + .data.key = subghz_protocol_blocks_reverse_key((key & 0x00F0FF00) | 0xF0040, 24), + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeGangQi_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_GANGQI_NAME, // Add button 0xD arm and crc sum to the end + .data.key = gangqi_key, + .data.bits = 34, + .data.te = 0}; + break; + case SetTypeHollarm_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_HOLLARM_NAME, // Add button 0x2 and crc sum to the end + .data.key = (key & 0x000FFF0000) | 0xF0B0002200 | + ((((((key & 0x000FFF0000) | 0xF0B0002200) >> 32) & 0xFF) + + ((((key & 0x000FFF0000) | 0xF0B0002200) >> 24) & 0xFF) + + ((((key & 0x000FFF0000) | 0xF0B0002200) >> 16) & 0xFF) + + ((((key & 0x000FFF0000) | 0xF0B0002200) >> 8) & 0xFF)) & + 0xFF), + .data.bits = 42, + .data.te = 0}; + break; + case SetTypeReversRB2_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = SUBGHZ_PROTOCOL_REVERSRB2_NAME, // 64bits no buttons + .data.key = (key & 0x00000FFFFFFFF000) | 0xFFFFF00000000000 | 0x0000000000000A00, + .data.bits = 64, + .data.te = 0}; + break; + case SetTypeMarantec24_868: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 868350000, + .data.name = SUBGHZ_PROTOCOL_MARANTEC24_NAME, // Add button code 0x8 to the end + .data.key = (key & 0xFFFFF0) | 0x000008, + .data.bits = 24, + .data.te = 0}; + break; + case SetTypeMarantec_433: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 433920000, + .data.name = + SUBGHZ_PROTOCOL_MARANTEC_NAME, // Button code is 0x4 and crc sum to the end + .data.key = marantec_key, + .data.bits = 49, + .data.te = 0}; + break; + case SetTypeMarantec_868: + gen_info = (GenInfo){ + .type = GenData, + .mod = "AM650", + .freq = 868350000, + .data.name = + SUBGHZ_PROTOCOL_MARANTEC_NAME, // Button code is 0x4 and crc sum to the end + .data.key = marantec_key, + .data.bits = 49, + .data.te = 0}; + break; + case SetTypeFaacSLH_433: + gen_info = (GenInfo){ + .type = GenFaacSLH, + .mod = "AM650", + .freq = 433920000, + .faac_slh.serial = ((key & 0x00FFFFF0) | 0xA0000006) >> 4, + .faac_slh.btn = 0x06, + .faac_slh.cnt = 0x02, + .faac_slh.seed = key, + .faac_slh.manuf = "FAAC_SLH"}; + break; + case SetTypeFaacSLH_868: + gen_info = (GenInfo){ + .type = GenFaacSLH, + .mod = "AM650", + .freq = 868350000, + .faac_slh.serial = ((key & 0x00FFFFF0) | 0xA0000006) >> 4, + .faac_slh.btn = 0x06, + .faac_slh.cnt = 0x02, + .faac_slh.seed = (key & 0x0FFFFFFF), + .faac_slh.manuf = "FAAC_SLH"}; + break; + case SetTypeBeninca433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFF00) | 0x00800080, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Beninca"}; + break; + case SetTypeBeninca868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 868350000, + .keeloq.serial = (key & 0x000FFF00) | 0x00800080, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Beninca"}; + break; + case SetTypeComunello433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x08, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Comunello"}; + break; + case SetTypeComunello868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 868460000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x08, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Comunello"}; + break; + case SetTypeAllmatic433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x00FFFF00) | 0x01000011, + .keeloq.btn = 0x0C, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Beninca"}; + break; + case SetTypeAllmatic868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 868350000, + .keeloq.serial = (key & 0x00FFFF00) | 0x01000011, + .keeloq.btn = 0x0C, + .keeloq.cnt = 0x05, + .keeloq.manuf = "Beninca"}; + break; + case SetTypeCenturion433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0000FFFF), + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Centurion"}; + break; + case SetTypeMonarch433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0000FFFF), + .keeloq.btn = 0x0A, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Monarch"}; + break; + case SetTypeJollyMotors433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFFFF), + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Jolly_Motors"}; + break; + case SetTypeElmesElectronic: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x00FFFFFF) | 0x02000000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Elmes_Poland"}; + break; + case SetTypeANMotorsAT4: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFFFF) | 0x04700000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x21, + .keeloq.manuf = "AN-Motors"}; + break; + case SetTypeAprimatic: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFFFF) | 0x00600000, + .keeloq.btn = 0x08, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Aprimatic"}; + break; + case SetTypeGibidi433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Gibidi"}; + break; + case SetTypeGSN: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "GSN"}; + break; + case SetTypeIronLogic: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFF0, + .keeloq.btn = 0x04, + .keeloq.cnt = 0x05, + .keeloq.manuf = "IronLogic"}; + break; + case SetTypeStilmatic: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Stilmatic"}; + break; + case SetTypeSommer_FM_434: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM476", + .freq = 434420000, + .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeSommer_FM_868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM476", + .freq = 868800000, + .keeloq.serial = (key & 0x0000FFFF) | 0x01700000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeSommer_FM238_434: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM238", + .freq = 434420000, + .keeloq.serial = key & 0x0000FFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeSommer_FM238_868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "FM238", + .freq = 868800000, + .keeloq.serial = key & 0x0000FFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Sommer(fsk476)"}; + break; + case SetTypeDTMNeo433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x000FFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x05, + .keeloq.manuf = "DTM_Neo"}; + break; + case SetTypeCAMESpace: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x04, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Came_Space"}; + break; + case SetTypeCameAtomo433: + gen_info = (GenInfo){ + .type = GenCameAtomo, + .mod = "AM650", + .freq = 433920000, + .came_atomo.serial = (key & 0x0FFFFFFF) | 0x10000000, + .came_atomo.cnt = 0x03}; + break; + case SetTypeCameAtomo868: + gen_info = (GenInfo){ + .type = GenCameAtomo, + .mod = "AM650", + .freq = 868350000, + .came_atomo.serial = (key & 0x0FFFFFFF) | 0x10000000, + .came_atomo.cnt = 0x03}; + break; + case SetTypeBFTMitto: + gen_info = (GenInfo){ + .type = GenKeeloqBFT, + .mod = "AM650", + .freq = 433920000, + .keeloq_bft.serial = key & 0x000FFFFF, + .keeloq_bft.btn = 0x02, + .keeloq_bft.cnt = 0x02, + .keeloq_bft.seed = key & 0x000FFFFF, + .keeloq_bft.manuf = "BFT"}; + break; + case SetTypeAlutechAT4N: + gen_info = (GenInfo){ + .type = GenAlutechAt4n, + .mod = "AM650", + .freq = 433920000, + .alutech_at_4n.serial = (key & 0x000FFFFF) | 0x00100000, + .alutech_at_4n.btn = 0x44, + .alutech_at_4n.cnt = 0x03}; + break; + case SetTypeSomfyTelis: + gen_info = (GenInfo){ + .type = GenSomfyTelis, + .mod = "AM650", + .freq = 433420000, + .somfy_telis.serial = key & 0x00FFFFFF, + .somfy_telis.btn = 0x02, + .somfy_telis.cnt = 0x03}; + break; + case SetTypeMotorline433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Motorline"}; + break; + case SetTypeDoorHan_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "DoorHan"}; + break; + case SetTypeDoorHan_315_00: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 315000000, + .keeloq.serial = key & 0x0FFFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "DoorHan"}; + break; + case SetTypeNiceFlorS_433_92: + gen_info = (GenInfo){ + .type = GenNiceFlorS, + .mod = "AM650", + .freq = 433920000, + .nice_flor_s.serial = key & 0x0FFFFFFF, + .nice_flor_s.btn = 0x01, + .nice_flor_s.cnt = 0x03, + .nice_flor_s.nice_one = false}; + break; + case SetTypeNiceOne_433_92: + gen_info = (GenInfo){ + .type = GenNiceFlorS, + .mod = "AM650", + .freq = 433920000, + .nice_flor_s.serial = key & 0x0FFFFFFF, + .nice_flor_s.btn = 0x01, + .nice_flor_s.cnt = 0x03, + .nice_flor_s.nice_one = true}; + break; + case SetTypeNiceSmilo_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "NICE_Smilo"}; + break; + case SetTypeNiceMHouse_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x09, + .keeloq.cnt = 0x03, + .keeloq.manuf = "NICE_MHOUSE"}; + break; + case SetTypeDeaMio433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0FFFF000) | 0x00000869, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Dea_Mio"}; + break; + case SetTypeGeniusBravo433: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x06, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Genius_Bravo"}; + break; + case SetTypeJCM_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x00FFFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "JCM_Tech"}; + break; + case SetTypeNovoferm_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0000FFFF) | 0x018F0000, + .keeloq.btn = 0x01, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Novoferm"}; + break; + case SetTypeHormannEcoStar_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x000FFFFF) | 0x02200000, + .keeloq.btn = 0x04, + .keeloq.cnt = 0x03, + .keeloq.manuf = "EcoStar"}; + break; + case SetTypeFAACRCXT_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = (key & 0x0000FFFF) | 0x00100000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "FAAC_RC,XT"}; + break; + case SetTypeFAACRCXT_868: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 868350000, + .keeloq.serial = (key & 0x0000FFFF) | 0x00100000, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "FAAC_RC,XT"}; + break; + case SetTypeNormstahl_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x0000FFFF, + .keeloq.btn = 0x04, + .keeloq.cnt = 0x03, + .keeloq.manuf = "Normstahl"}; + break; + case SetTypeHCS101_433_92: + gen_info = (GenInfo){ + .type = GenKeeloq, + .mod = "AM650", + .freq = 433920000, + .keeloq.serial = key & 0x000FFFFF, + .keeloq.btn = 0x02, + .keeloq.cnt = 0x03, + .keeloq.manuf = "HCS101"}; + break; + case SetTypeSecPlus_v1_315_00: + gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 315000000}; + break; + case SetTypeSecPlus_v1_390_00: + gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 390000000}; + break; + case SetTypeSecPlus_v1_433_00: + gen_info = (GenInfo){.type = GenSecPlus1, .mod = "AM650", .freq = 433920000}; + break; + case SetTypeSecPlus_v2_310_00: + gen_info = (GenInfo){ + .type = GenSecPlus2, + .mod = "AM650", + .freq = 310000000, + .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing + .sec_plus_2.btn = 0x68, + .sec_plus_2.cnt = 0xE500000}; + break; + case SetTypeSecPlus_v2_315_00: + gen_info = (GenInfo){ + .type = GenSecPlus2, + .mod = "AM650", + .freq = 315000000, + .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing + .sec_plus_2.btn = 0x68, + .sec_plus_2.cnt = 0xE500000}; + break; + case SetTypeSecPlus_v2_390_00: + gen_info = (GenInfo){ + .type = GenSecPlus2, + .mod = "AM650", + .freq = 390000000, + .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing + .sec_plus_2.btn = 0x68, + .sec_plus_2.cnt = 0xE500000}; + break; + case SetTypeSecPlus_v2_433_00: + gen_info = (GenInfo){ + .type = GenSecPlus2, + .mod = "AM650", + .freq = 433920000, + .sec_plus_2.serial = (key & 0x7FFFF3FC), // 850LM pairing + .sec_plus_2.btn = 0x68, + .sec_plus_2.cnt = 0xE500000}; + break; + case SetTypePhoenix_V2_433: + gen_info = (GenInfo){ + .type = GenPhoenixV2, + .mod = "AM650", + .freq = 433920000, + .phoenix_v2.serial = (key & 0x0FFFFFFF) | 0xB0000000, + .phoenix_v2.cnt = 0x025D}; + break; + default: + furi_crash("Not implemented"); + break; + } *infos_dest = gen_info; } diff --git a/applications/main/subghz/helpers/subghz_gen_info.h b/applications/main/subghz/helpers/subghz_gen_info.h index 938c6d27a..003ab871a 100644 --- a/applications/main/subghz/helpers/subghz_gen_info.h +++ b/applications/main/subghz/helpers/subghz_gen_info.h @@ -79,6 +79,6 @@ typedef struct { }; } GenInfo; -void subghz_gen_info_reset(GenInfo *gen_info); +void subghz_gen_info_reset(GenInfo* gen_info); void subghz_scene_set_type_fill_generation_infos(GenInfo* infos_dest, SetType type); diff --git a/applications/main/subghz/scenes/subghz_scene_set_button.c b/applications/main/subghz/scenes/subghz_scene_set_button.c index cd5e11f47..c07b793e4 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_button.c +++ b/applications/main/subghz/scenes/subghz_scene_set_button.c @@ -16,42 +16,42 @@ void subghz_scene_set_button_on_enter(void* context) { uint8_t byte_count = 0; switch(subghz->gen_info->type) { - case GenFaacSLH: - byte_ptr = &subghz->gen_info->faac_slh.btn; - byte_count = sizeof(subghz->gen_info->faac_slh.btn); - break; - case GenKeeloq: - byte_ptr = &subghz->gen_info->keeloq.btn; - byte_count = sizeof(subghz->gen_info->keeloq.btn); - break; - case GenKeeloqBFT: - byte_ptr = &subghz->gen_info->keeloq_bft.btn; - byte_count = sizeof(subghz->gen_info->keeloq_bft.btn); - break; - case GenAlutechAt4n: - byte_ptr = &subghz->gen_info->alutech_at_4n.btn; - byte_count = sizeof(subghz->gen_info->alutech_at_4n.btn); - break; - case GenSomfyTelis: - byte_ptr = &subghz->gen_info->somfy_telis.btn; - byte_count = sizeof(subghz->gen_info->somfy_telis.btn); - break; - case GenNiceFlorS: - byte_ptr = &subghz->gen_info->nice_flor_s.btn; - byte_count = sizeof(subghz->gen_info->nice_flor_s.btn); - break; - case GenSecPlus2: - byte_ptr = &subghz->gen_info->sec_plus_2.btn; - byte_count = sizeof(subghz->gen_info->sec_plus_2.btn); - break; - // Not needed for these types - case GenPhoenixV2: - case GenData: - case GenSecPlus1: - case GenCameAtomo: - default: - furi_crash("Not implemented"); - break; + case GenFaacSLH: + byte_ptr = &subghz->gen_info->faac_slh.btn; + byte_count = sizeof(subghz->gen_info->faac_slh.btn); + break; + case GenKeeloq: + byte_ptr = &subghz->gen_info->keeloq.btn; + byte_count = sizeof(subghz->gen_info->keeloq.btn); + break; + case GenKeeloqBFT: + byte_ptr = &subghz->gen_info->keeloq_bft.btn; + byte_count = sizeof(subghz->gen_info->keeloq_bft.btn); + break; + case GenAlutechAt4n: + byte_ptr = &subghz->gen_info->alutech_at_4n.btn; + byte_count = sizeof(subghz->gen_info->alutech_at_4n.btn); + break; + case GenSomfyTelis: + byte_ptr = &subghz->gen_info->somfy_telis.btn; + byte_count = sizeof(subghz->gen_info->somfy_telis.btn); + break; + case GenNiceFlorS: + byte_ptr = &subghz->gen_info->nice_flor_s.btn; + byte_count = sizeof(subghz->gen_info->nice_flor_s.btn); + break; + case GenSecPlus2: + byte_ptr = &subghz->gen_info->sec_plus_2.btn; + byte_count = sizeof(subghz->gen_info->sec_plus_2.btn); + break; + // Not needed for these types + case GenPhoenixV2: + case GenData: + case GenSecPlus1: + case GenCameAtomo: + default: + furi_crash("Not implemented"); + break; } furi_assert(byte_ptr); diff --git a/applications/main/subghz/scenes/subghz_scene_set_counter.c b/applications/main/subghz/scenes/subghz_scene_set_counter.c index b9f241258..561c108eb 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_counter.c +++ b/applications/main/subghz/scenes/subghz_scene_set_counter.c @@ -16,48 +16,48 @@ void subghz_scene_set_counter_on_enter(void* context) { uint8_t byte_count = 0; switch(subghz->gen_info->type) { - case GenFaacSLH: - byte_ptr = &subghz->gen_info->faac_slh.cnt; - byte_count = sizeof(subghz->gen_info->faac_slh.cnt); - break; - case GenKeeloq: - byte_ptr = &subghz->gen_info->keeloq.cnt; - byte_count = sizeof(subghz->gen_info->keeloq.cnt); - break; - case GenCameAtomo: - byte_ptr = &subghz->gen_info->came_atomo.cnt; - byte_count = sizeof(subghz->gen_info->came_atomo.cnt); - break; - case GenKeeloqBFT: - byte_ptr = &subghz->gen_info->keeloq_bft.cnt; - byte_count = sizeof(subghz->gen_info->keeloq_bft.cnt); - break; - case GenAlutechAt4n: - byte_ptr = &subghz->gen_info->alutech_at_4n.cnt; - byte_count = sizeof(subghz->gen_info->alutech_at_4n.cnt); - break; - case GenSomfyTelis: - byte_ptr = &subghz->gen_info->somfy_telis.cnt; - byte_count = sizeof(subghz->gen_info->somfy_telis.cnt); - break; - case GenNiceFlorS: - byte_ptr = &subghz->gen_info->nice_flor_s.cnt; - byte_count = sizeof(subghz->gen_info->nice_flor_s.cnt); - break; - case GenSecPlus2: - byte_ptr = (uint8_t*)&subghz->gen_info->sec_plus_2.cnt; - byte_count = sizeof(subghz->gen_info->sec_plus_2.cnt); - break; - case GenPhoenixV2: - byte_ptr = (uint8_t*)&subghz->gen_info->phoenix_v2.cnt; - byte_count = sizeof(subghz->gen_info->phoenix_v2.cnt); - break; - // Not needed for these types - case GenData: - case GenSecPlus1: - default: - furi_crash("Not implemented"); - break; + case GenFaacSLH: + byte_ptr = &subghz->gen_info->faac_slh.cnt; + byte_count = sizeof(subghz->gen_info->faac_slh.cnt); + break; + case GenKeeloq: + byte_ptr = &subghz->gen_info->keeloq.cnt; + byte_count = sizeof(subghz->gen_info->keeloq.cnt); + break; + case GenCameAtomo: + byte_ptr = &subghz->gen_info->came_atomo.cnt; + byte_count = sizeof(subghz->gen_info->came_atomo.cnt); + break; + case GenKeeloqBFT: + byte_ptr = &subghz->gen_info->keeloq_bft.cnt; + byte_count = sizeof(subghz->gen_info->keeloq_bft.cnt); + break; + case GenAlutechAt4n: + byte_ptr = &subghz->gen_info->alutech_at_4n.cnt; + byte_count = sizeof(subghz->gen_info->alutech_at_4n.cnt); + break; + case GenSomfyTelis: + byte_ptr = &subghz->gen_info->somfy_telis.cnt; + byte_count = sizeof(subghz->gen_info->somfy_telis.cnt); + break; + case GenNiceFlorS: + byte_ptr = &subghz->gen_info->nice_flor_s.cnt; + byte_count = sizeof(subghz->gen_info->nice_flor_s.cnt); + break; + case GenSecPlus2: + byte_ptr = (uint8_t*)&subghz->gen_info->sec_plus_2.cnt; + byte_count = sizeof(subghz->gen_info->sec_plus_2.cnt); + break; + case GenPhoenixV2: + byte_ptr = (uint8_t*)&subghz->gen_info->phoenix_v2.cnt; + byte_count = sizeof(subghz->gen_info->phoenix_v2.cnt); + break; + // Not needed for these types + case GenData: + case GenSecPlus1: + default: + furi_crash("Not implemented"); + break; } furi_assert(byte_ptr); @@ -87,79 +87,79 @@ bool subghz_scene_set_counter_on_event(void* context, SceneManagerEvent event) { GenInfo gen_info = *subghz->gen_info; switch(gen_info.type) { - case GenFaacSLH: - case GenKeeloqBFT: - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetSeed); - return true; - case GenKeeloq: - generated_protocol = subghz_txrx_gen_keeloq_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.keeloq.serial, - gen_info.keeloq.btn, - gen_info.keeloq.cnt, - gen_info.keeloq.manuf); - break; - case GenCameAtomo: - generated_protocol = subghz_txrx_gen_came_atomo_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.came_atomo.serial, - gen_info.came_atomo.cnt); - break; - case GenAlutechAt4n: - generated_protocol = subghz_txrx_gen_alutech_at_4n_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.alutech_at_4n.serial, - gen_info.alutech_at_4n.btn, - gen_info.alutech_at_4n.cnt); - break; - case GenSomfyTelis: - generated_protocol = subghz_txrx_gen_somfy_telis_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.somfy_telis.serial, - gen_info.somfy_telis.btn, - gen_info.somfy_telis.cnt); - break; - case GenNiceFlorS: - generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.nice_flor_s.serial, - gen_info.nice_flor_s.btn, - gen_info.nice_flor_s.cnt, - gen_info.nice_flor_s.nice_one); - break; - case GenSecPlus2: - generated_protocol = subghz_txrx_gen_secplus_v2_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.sec_plus_2.serial, - gen_info.sec_plus_2.btn, - gen_info.sec_plus_2.cnt); - break; - case GenPhoenixV2: - generated_protocol = subghz_txrx_gen_phoenix_v2_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.phoenix_v2.serial, - gen_info.phoenix_v2.cnt); - break; - // Not needed for these types - case GenData: - case GenSecPlus1: - default: - furi_crash("Not implemented"); - break; + case GenFaacSLH: + case GenKeeloqBFT: + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetSeed); + return true; + case GenKeeloq: + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.keeloq.serial, + gen_info.keeloq.btn, + gen_info.keeloq.cnt, + gen_info.keeloq.manuf); + break; + case GenCameAtomo: + generated_protocol = subghz_txrx_gen_came_atomo_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.came_atomo.serial, + gen_info.came_atomo.cnt); + break; + case GenAlutechAt4n: + generated_protocol = subghz_txrx_gen_alutech_at_4n_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.alutech_at_4n.serial, + gen_info.alutech_at_4n.btn, + gen_info.alutech_at_4n.cnt); + break; + case GenSomfyTelis: + generated_protocol = subghz_txrx_gen_somfy_telis_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.somfy_telis.serial, + gen_info.somfy_telis.btn, + gen_info.somfy_telis.cnt); + break; + case GenNiceFlorS: + generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.nice_flor_s.serial, + gen_info.nice_flor_s.btn, + gen_info.nice_flor_s.cnt, + gen_info.nice_flor_s.nice_one); + break; + case GenSecPlus2: + generated_protocol = subghz_txrx_gen_secplus_v2_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.sec_plus_2.serial, + gen_info.sec_plus_2.btn, + gen_info.sec_plus_2.cnt); + break; + case GenPhoenixV2: + generated_protocol = subghz_txrx_gen_phoenix_v2_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.phoenix_v2.serial, + gen_info.phoenix_v2.cnt); + break; + // Not needed for these types + case GenData: + case GenSecPlus1: + default: + furi_crash("Not implemented"); + break; } consumed = true; diff --git a/applications/main/subghz/scenes/subghz_scene_set_key.c b/applications/main/subghz/scenes/subghz_scene_set_key.c index f9872fb11..1cb2b6b21 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_key.c +++ b/applications/main/subghz/scenes/subghz_scene_set_key.c @@ -29,12 +29,7 @@ void subghz_scene_set_key_on_enter(void* context) { ByteInput* byte_input = subghz->byte_input; byte_input_set_header_text(byte_input, "Enter KEY in hex"); byte_input_set_result_callback( - byte_input, - subghz_scene_set_key_byte_input_callback, - NULL, - subghz, - byte_ptr, - byte_count); + byte_input, subghz_scene_set_key_byte_input_callback, NULL, subghz, byte_ptr, byte_count); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); } diff --git a/applications/main/subghz/scenes/subghz_scene_set_seed.c b/applications/main/subghz/scenes/subghz_scene_set_seed.c index 408460518..d52e4b674 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_seed.c +++ b/applications/main/subghz/scenes/subghz_scene_set_seed.c @@ -16,27 +16,27 @@ void subghz_scene_set_seed_on_enter(void* context) { uint8_t byte_count = 0; switch(subghz->gen_info->type) { - case GenFaacSLH: - byte_ptr = (uint8_t*)&subghz->gen_info->faac_slh.seed; - byte_count = sizeof(subghz->gen_info->faac_slh.seed); - break; - case GenKeeloqBFT: - byte_ptr = (uint8_t*)&subghz->gen_info->keeloq_bft.seed; - byte_count = sizeof(subghz->gen_info->keeloq_bft.seed); - break; - // Not needed for these types - case GenKeeloq: - case GenAlutechAt4n: - case GenSomfyTelis: - case GenNiceFlorS: - case GenSecPlus2: - case GenPhoenixV2: - case GenData: - case GenSecPlus1: - case GenCameAtomo: - default: - furi_crash("Not implemented"); - break; + case GenFaacSLH: + byte_ptr = (uint8_t*)&subghz->gen_info->faac_slh.seed; + byte_count = sizeof(subghz->gen_info->faac_slh.seed); + break; + case GenKeeloqBFT: + byte_ptr = (uint8_t*)&subghz->gen_info->keeloq_bft.seed; + byte_count = sizeof(subghz->gen_info->keeloq_bft.seed); + break; + // Not needed for these types + case GenKeeloq: + case GenAlutechAt4n: + case GenSomfyTelis: + case GenNiceFlorS: + case GenSecPlus2: + case GenPhoenixV2: + case GenData: + case GenSecPlus1: + case GenCameAtomo: + default: + furi_crash("Not implemented"); + break; } furi_assert(byte_ptr); @@ -46,12 +46,7 @@ void subghz_scene_set_seed_on_enter(void* context) { ByteInput* byte_input = subghz->byte_input; 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, - NULL, - subghz, - byte_ptr, - byte_count); + byte_input, subghz_scene_set_seed_byte_input_callback, NULL, subghz, byte_ptr, byte_count); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); } @@ -64,41 +59,41 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { GenInfo gen_info = *subghz->gen_info; switch(gen_info.type) { - case GenFaacSLH: - generated_protocol = subghz_txrx_gen_faac_slh_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.faac_slh.serial, - gen_info.faac_slh.btn, - gen_info.faac_slh.cnt, - gen_info.faac_slh.seed, - gen_info.faac_slh.manuf); - break; - case GenKeeloqBFT: - generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.keeloq_bft.serial, - gen_info.keeloq_bft.btn, - gen_info.keeloq_bft.cnt, - gen_info.keeloq_bft.seed, - gen_info.keeloq_bft.manuf); - break; - // Not needed for these types - case GenKeeloq: - case GenAlutechAt4n: - case GenSomfyTelis: - case GenNiceFlorS: - case GenSecPlus2: - case GenPhoenixV2: - case GenData: - case GenSecPlus1: - case GenCameAtomo: - default: - furi_crash("Not implemented"); - break; + case GenFaacSLH: + generated_protocol = subghz_txrx_gen_faac_slh_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.faac_slh.serial, + gen_info.faac_slh.btn, + gen_info.faac_slh.cnt, + gen_info.faac_slh.seed, + gen_info.faac_slh.manuf); + break; + case GenKeeloqBFT: + generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.keeloq_bft.serial, + gen_info.keeloq_bft.btn, + gen_info.keeloq_bft.cnt, + gen_info.keeloq_bft.seed, + gen_info.keeloq_bft.manuf); + break; + // Not needed for these types + case GenKeeloq: + case GenAlutechAt4n: + case GenSomfyTelis: + case GenNiceFlorS: + case GenSecPlus2: + case GenPhoenixV2: + case GenData: + case GenSecPlus1: + case GenCameAtomo: + default: + furi_crash("Not implemented"); + break; } consumed = true; diff --git a/applications/main/subghz/scenes/subghz_scene_set_serial.c b/applications/main/subghz/scenes/subghz_scene_set_serial.c index 42d815dd7..2168d2df1 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_serial.c +++ b/applications/main/subghz/scenes/subghz_scene_set_serial.c @@ -16,48 +16,48 @@ void subghz_scene_set_serial_on_enter(void* context) { uint8_t byte_count = 0; switch(subghz->gen_info->type) { - case GenFaacSLH: - byte_ptr = (uint8_t*)&subghz->gen_info->faac_slh.serial; - byte_count = sizeof(subghz->gen_info->faac_slh.serial); - break; - case GenKeeloq: - byte_ptr = (uint8_t*)&subghz->gen_info->keeloq.serial; - byte_count = sizeof(subghz->gen_info->keeloq.serial); - break; - case GenCameAtomo: - byte_ptr = (uint8_t*)&subghz->gen_info->came_atomo.serial; - byte_count = sizeof(subghz->gen_info->came_atomo.serial); - break; - case GenKeeloqBFT: - byte_ptr = (uint8_t*)&subghz->gen_info->keeloq_bft.serial; - byte_count = sizeof(subghz->gen_info->keeloq_bft.serial); - break; - case GenAlutechAt4n: - byte_ptr = (uint8_t*)&subghz->gen_info->alutech_at_4n.serial; - byte_count = sizeof(subghz->gen_info->alutech_at_4n.serial); - break; - case GenSomfyTelis: - byte_ptr = (uint8_t*)&subghz->gen_info->somfy_telis.serial; - byte_count = sizeof(subghz->gen_info->somfy_telis.serial); - break; - case GenNiceFlorS: - byte_ptr = (uint8_t*)&subghz->gen_info->nice_flor_s.serial; - byte_count = sizeof(subghz->gen_info->nice_flor_s.serial); - break; - case GenSecPlus2: - byte_ptr = (uint8_t*)&subghz->gen_info->sec_plus_2.serial; - byte_count = sizeof(subghz->gen_info->sec_plus_2.serial); - break; - case GenPhoenixV2: - byte_ptr = (uint8_t*)&subghz->gen_info->phoenix_v2.serial; - byte_count = sizeof(subghz->gen_info->phoenix_v2.serial); - break; - // Not needed for these types - case GenData: - case GenSecPlus1: - default: - furi_crash("Not implemented"); - break; + case GenFaacSLH: + byte_ptr = (uint8_t*)&subghz->gen_info->faac_slh.serial; + byte_count = sizeof(subghz->gen_info->faac_slh.serial); + break; + case GenKeeloq: + byte_ptr = (uint8_t*)&subghz->gen_info->keeloq.serial; + byte_count = sizeof(subghz->gen_info->keeloq.serial); + break; + case GenCameAtomo: + byte_ptr = (uint8_t*)&subghz->gen_info->came_atomo.serial; + byte_count = sizeof(subghz->gen_info->came_atomo.serial); + break; + case GenKeeloqBFT: + byte_ptr = (uint8_t*)&subghz->gen_info->keeloq_bft.serial; + byte_count = sizeof(subghz->gen_info->keeloq_bft.serial); + break; + case GenAlutechAt4n: + byte_ptr = (uint8_t*)&subghz->gen_info->alutech_at_4n.serial; + byte_count = sizeof(subghz->gen_info->alutech_at_4n.serial); + break; + case GenSomfyTelis: + byte_ptr = (uint8_t*)&subghz->gen_info->somfy_telis.serial; + byte_count = sizeof(subghz->gen_info->somfy_telis.serial); + break; + case GenNiceFlorS: + byte_ptr = (uint8_t*)&subghz->gen_info->nice_flor_s.serial; + byte_count = sizeof(subghz->gen_info->nice_flor_s.serial); + break; + case GenSecPlus2: + byte_ptr = (uint8_t*)&subghz->gen_info->sec_plus_2.serial; + byte_count = sizeof(subghz->gen_info->sec_plus_2.serial); + break; + case GenPhoenixV2: + byte_ptr = (uint8_t*)&subghz->gen_info->phoenix_v2.serial; + byte_count = sizeof(subghz->gen_info->phoenix_v2.serial); + break; + // Not needed for these types + case GenData: + case GenSecPlus1: + default: + furi_crash("Not implemented"); + break; } furi_assert(byte_ptr); @@ -83,25 +83,25 @@ bool subghz_scene_set_serial_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventByteInputDone) { switch(subghz->gen_info->type) { - case GenFaacSLH: - case GenKeeloq: - case GenKeeloqBFT: - case GenAlutechAt4n: - case GenSomfyTelis: - case GenNiceFlorS: - case GenSecPlus2: - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetButton); - break; - case GenCameAtomo: - case GenPhoenixV2: - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetCounter); - break; - // Not needed for these types - case GenData: - case GenSecPlus1: - default: - furi_crash("Not implemented"); - break; + case GenFaacSLH: + case GenKeeloq: + case GenKeeloqBFT: + case GenAlutechAt4n: + case GenSomfyTelis: + case GenNiceFlorS: + case GenSecPlus2: + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetButton); + break; + case GenCameAtomo: + case GenPhoenixV2: + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetCounter); + break; + // Not needed for these types + case GenData: + case GenSecPlus1: + default: + furi_crash("Not implemented"); + break; } consumed = true; diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 61e5148de..446c46a83 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -106,126 +106,125 @@ bool subghz_scene_set_type_generate_protocol_from_infos(SubGhz* subghz) { GenInfo gen_info = *subghz->gen_info; bool generated_protocol = false; switch(gen_info.type) { - case GenData: - if(gen_info.data.te) { - generated_protocol = subghz_txrx_gen_data_protocol_and_te( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.data.name, - gen_info.data.key, - gen_info.data.bits, - gen_info.data.te); - } else { - generated_protocol = subghz_txrx_gen_data_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.data.name, - gen_info.data.key, - gen_info.data.bits); - } - break; - case GenFaacSLH: - generated_protocol = subghz_txrx_gen_faac_slh_protocol( + case GenData: + if(gen_info.data.te) { + generated_protocol = subghz_txrx_gen_data_protocol_and_te( subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.faac_slh.serial, - gen_info.faac_slh.btn, - gen_info.faac_slh.cnt, - gen_info.faac_slh.seed, - gen_info.faac_slh.manuf); - break; - case GenKeeloq: - generated_protocol = subghz_txrx_gen_keeloq_protocol( + gen_info.data.name, + gen_info.data.key, + gen_info.data.bits, + gen_info.data.te); + } else { + generated_protocol = subghz_txrx_gen_data_protocol( subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.keeloq.serial, - gen_info.keeloq.btn, - gen_info.keeloq.cnt, - gen_info.keeloq.manuf); - break; - case GenCameAtomo: - generated_protocol = subghz_txrx_gen_came_atomo_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.came_atomo.serial, - gen_info.came_atomo.cnt); - break; - case GenKeeloqBFT: - generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.keeloq_bft.serial, - gen_info.keeloq_bft.btn, - gen_info.keeloq_bft.cnt, - gen_info.keeloq_bft.seed, - gen_info.keeloq_bft.manuf); - break; - case GenAlutechAt4n: - generated_protocol = subghz_txrx_gen_alutech_at_4n_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.alutech_at_4n.serial, - gen_info.alutech_at_4n.btn, - gen_info.alutech_at_4n.cnt); - break; - case GenSomfyTelis: - generated_protocol = subghz_txrx_gen_somfy_telis_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.somfy_telis.serial, - gen_info.somfy_telis.btn, - gen_info.somfy_telis.cnt); - break; - case GenNiceFlorS: - generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.nice_flor_s.serial, - gen_info.nice_flor_s.btn, - gen_info.nice_flor_s.cnt, - gen_info.nice_flor_s.nice_one); - break; - case GenSecPlus1: - generated_protocol = - subghz_txrx_gen_secplus_v1_protocol(subghz->txrx, gen_info.mod, gen_info.freq); - break; - case GenSecPlus2: - generated_protocol = subghz_txrx_gen_secplus_v2_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.sec_plus_2.serial, - gen_info.sec_plus_2.btn, - gen_info.sec_plus_2.cnt); - break; - case GenPhoenixV2: - generated_protocol = subghz_txrx_gen_phoenix_v2_protocol( - subghz->txrx, - gen_info.mod, - gen_info.freq, - gen_info.phoenix_v2.serial, - gen_info.phoenix_v2.cnt); - break; - default: - furi_crash("Not implemented"); - break; + gen_info.data.name, + gen_info.data.key, + gen_info.data.bits); + } + break; + case GenFaacSLH: + generated_protocol = subghz_txrx_gen_faac_slh_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.faac_slh.serial, + gen_info.faac_slh.btn, + gen_info.faac_slh.cnt, + gen_info.faac_slh.seed, + gen_info.faac_slh.manuf); + break; + case GenKeeloq: + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.keeloq.serial, + gen_info.keeloq.btn, + gen_info.keeloq.cnt, + gen_info.keeloq.manuf); + break; + case GenCameAtomo: + generated_protocol = subghz_txrx_gen_came_atomo_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.came_atomo.serial, + gen_info.came_atomo.cnt); + break; + case GenKeeloqBFT: + generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.keeloq_bft.serial, + gen_info.keeloq_bft.btn, + gen_info.keeloq_bft.cnt, + gen_info.keeloq_bft.seed, + gen_info.keeloq_bft.manuf); + break; + case GenAlutechAt4n: + generated_protocol = subghz_txrx_gen_alutech_at_4n_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.alutech_at_4n.serial, + gen_info.alutech_at_4n.btn, + gen_info.alutech_at_4n.cnt); + break; + case GenSomfyTelis: + generated_protocol = subghz_txrx_gen_somfy_telis_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.somfy_telis.serial, + gen_info.somfy_telis.btn, + gen_info.somfy_telis.cnt); + break; + case GenNiceFlorS: + generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.nice_flor_s.serial, + gen_info.nice_flor_s.btn, + gen_info.nice_flor_s.cnt, + gen_info.nice_flor_s.nice_one); + break; + case GenSecPlus1: + generated_protocol = + subghz_txrx_gen_secplus_v1_protocol(subghz->txrx, gen_info.mod, gen_info.freq); + break; + case GenSecPlus2: + generated_protocol = subghz_txrx_gen_secplus_v2_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.sec_plus_2.serial, + gen_info.sec_plus_2.btn, + gen_info.sec_plus_2.cnt); + break; + case GenPhoenixV2: + generated_protocol = subghz_txrx_gen_phoenix_v2_protocol( + subghz->txrx, + gen_info.mod, + gen_info.freq, + gen_info.phoenix_v2.serial, + gen_info.phoenix_v2.cnt); + break; + default: + furi_crash("Not implemented"); + break; } if(generated_protocol) { subghz_file_name_clear(subghz); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); } else { - furi_string_set( - subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + furi_string_set(subghz->error_str, "Function requires\nan SD card with\nfresh databases."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } return generated_protocol; @@ -244,15 +243,19 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { subghz_gen_info_reset(subghz->gen_info); subghz_scene_set_type_fill_generation_infos(subghz->gen_info, event.event); - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart) == SubmenuIndexAddManually) { + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart) == + SubmenuIndexAddManually) { generated_protocol = subghz_scene_set_type_generate_protocol_from_infos(subghz); - } else if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart) == SubmenuIndexAddManuallyAdvanced) { + } else if( + scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart) == + SubmenuIndexAddManuallyAdvanced) { switch(subghz->gen_info->type) { case GenData: // Key (u64) scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetKey); break; case GenSecPlus1: // None - return subghz_txrx_gen_secplus_v1_protocol(subghz->txrx, subghz->gen_info->mod, subghz->gen_info->freq); + return subghz_txrx_gen_secplus_v1_protocol( + subghz->txrx, subghz->gen_info->mod, subghz->gen_info->freq); case GenFaacSLH: // Serial (u32), Button (u8), Counter (u8), Seed (u32) case GenKeeloq: // Serial (u32), Button (u8), Counter (u8) case GenCameAtomo: // Serial (u32), Counter (u8) From 2c0b7caf55f57916991a4a74c5c5bf8b16abbd85 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 31 Jul 2025 00:26:31 +0300 Subject: [PATCH 14/14] Better add manually advanced --- .../subghz/scenes/subghz_scene_set_counter.c | 26 ++++++++++++------- .../main/subghz/scenes/subghz_scene_set_key.c | 8 ++++-- .../subghz/scenes/subghz_scene_set_seed.c | 12 ++++++--- .../subghz/scenes/subghz_scene_set_serial.c | 4 +++ .../subghz/scenes/subghz_scene_set_type.c | 4 +-- 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/applications/main/subghz/scenes/subghz_scene_set_counter.c b/applications/main/subghz/scenes/subghz_scene_set_counter.c index 561c108eb..8f61c2285 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_counter.c +++ b/applications/main/subghz/scenes/subghz_scene_set_counter.c @@ -1,6 +1,8 @@ #include "../subghz_i.h" #include "../helpers/subghz_txrx_create_protocol_key.h" +#include + #define TAG "SubGhzSetCounter" void subghz_scene_set_counter_byte_input_callback(void* context) { @@ -63,6 +65,12 @@ void subghz_scene_set_counter_on_enter(void* context) { furi_assert(byte_ptr); furi_assert(byte_count > 0); + if(byte_count == 2) { + *((uint16_t*)byte_ptr) = __bswap16(*((uint16_t*)byte_ptr)); // Convert + } else if(byte_count == 4) { + *((uint32_t*)byte_ptr) = __bswap32(*((uint32_t*)byte_ptr)); // Convert + } + // Setup view ByteInput* byte_input = subghz->byte_input; byte_input_set_header_text(byte_input, "Enter COUNTER in hex"); @@ -96,7 +104,7 @@ bool subghz_scene_set_counter_on_event(void* context, SceneManagerEvent event) { subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.keeloq.serial, + __bswap32(gen_info.keeloq.serial), gen_info.keeloq.btn, gen_info.keeloq.cnt, gen_info.keeloq.manuf); @@ -106,7 +114,7 @@ bool subghz_scene_set_counter_on_event(void* context, SceneManagerEvent event) { subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.came_atomo.serial, + __bswap32(gen_info.came_atomo.serial), gen_info.came_atomo.cnt); break; case GenAlutechAt4n: @@ -114,7 +122,7 @@ bool subghz_scene_set_counter_on_event(void* context, SceneManagerEvent event) { subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.alutech_at_4n.serial, + __bswap32(gen_info.alutech_at_4n.serial), gen_info.alutech_at_4n.btn, gen_info.alutech_at_4n.cnt); break; @@ -123,7 +131,7 @@ bool subghz_scene_set_counter_on_event(void* context, SceneManagerEvent event) { subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.somfy_telis.serial, + __bswap32(gen_info.somfy_telis.serial), gen_info.somfy_telis.btn, gen_info.somfy_telis.cnt); break; @@ -132,7 +140,7 @@ bool subghz_scene_set_counter_on_event(void* context, SceneManagerEvent event) { subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.nice_flor_s.serial, + __bswap32(gen_info.nice_flor_s.serial), gen_info.nice_flor_s.btn, gen_info.nice_flor_s.cnt, gen_info.nice_flor_s.nice_one); @@ -142,17 +150,17 @@ bool subghz_scene_set_counter_on_event(void* context, SceneManagerEvent event) { subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.sec_plus_2.serial, + __bswap32(gen_info.sec_plus_2.serial), gen_info.sec_plus_2.btn, - gen_info.sec_plus_2.cnt); + __bswap32(gen_info.sec_plus_2.cnt)); break; case GenPhoenixV2: generated_protocol = subghz_txrx_gen_phoenix_v2_protocol( subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.phoenix_v2.serial, - gen_info.phoenix_v2.cnt); + __bswap32(gen_info.phoenix_v2.serial), + __bswap16(gen_info.phoenix_v2.cnt)); break; // Not needed for these types case GenData: diff --git a/applications/main/subghz/scenes/subghz_scene_set_key.c b/applications/main/subghz/scenes/subghz_scene_set_key.c index 1cb2b6b21..71c57c5f9 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_key.c +++ b/applications/main/subghz/scenes/subghz_scene_set_key.c @@ -1,6 +1,8 @@ #include "../subghz_i.h" #include "../helpers/subghz_txrx_create_protocol_key.h" +#include + #define TAG "SubGhzSetKey" void subghz_scene_set_key_byte_input_callback(void* context) { @@ -25,6 +27,8 @@ void subghz_scene_set_key_on_enter(void* context) { furi_assert(byte_ptr); furi_assert(byte_count > 0); + *((uint64_t*)byte_ptr) = __bswap64(*((uint64_t*)byte_ptr)); // Convert + // Setup view ByteInput* byte_input = subghz->byte_input; byte_input_set_header_text(byte_input, "Enter KEY in hex"); @@ -49,7 +53,7 @@ bool subghz_scene_set_key_on_event(void* context, SceneManagerEvent event) { gen_info.mod, gen_info.freq, gen_info.data.name, - gen_info.data.key, + __bswap64(gen_info.data.key), gen_info.data.bits, gen_info.data.te); } else { @@ -58,7 +62,7 @@ bool subghz_scene_set_key_on_event(void* context, SceneManagerEvent event) { gen_info.mod, gen_info.freq, gen_info.data.name, - gen_info.data.key, + __bswap64(gen_info.data.key), gen_info.data.bits); } } diff --git a/applications/main/subghz/scenes/subghz_scene_set_seed.c b/applications/main/subghz/scenes/subghz_scene_set_seed.c index d52e4b674..bebab6c27 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_seed.c +++ b/applications/main/subghz/scenes/subghz_scene_set_seed.c @@ -1,6 +1,8 @@ #include "../subghz_i.h" #include "../helpers/subghz_txrx_create_protocol_key.h" +#include + #define TAG "SubGhzSetSeed" void subghz_scene_set_seed_byte_input_callback(void* context) { @@ -42,6 +44,8 @@ void subghz_scene_set_seed_on_enter(void* context) { furi_assert(byte_ptr); furi_assert(byte_count > 0); + *((uint32_t*)byte_ptr) = __bswap32(*((uint32_t*)byte_ptr)); // Convert + // Setup view ByteInput* byte_input = subghz->byte_input; byte_input_set_header_text(byte_input, "Enter SEED in hex"); @@ -64,10 +68,10 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.faac_slh.serial, + __bswap32(gen_info.faac_slh.serial), gen_info.faac_slh.btn, gen_info.faac_slh.cnt, - gen_info.faac_slh.seed, + __bswap32(gen_info.faac_slh.seed), gen_info.faac_slh.manuf); break; case GenKeeloqBFT: @@ -75,10 +79,10 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { subghz->txrx, gen_info.mod, gen_info.freq, - gen_info.keeloq_bft.serial, + __bswap32(gen_info.keeloq_bft.serial), gen_info.keeloq_bft.btn, gen_info.keeloq_bft.cnt, - gen_info.keeloq_bft.seed, + __bswap32(gen_info.keeloq_bft.seed), gen_info.keeloq_bft.manuf); break; // Not needed for these types diff --git a/applications/main/subghz/scenes/subghz_scene_set_serial.c b/applications/main/subghz/scenes/subghz_scene_set_serial.c index 2168d2df1..6684e35a4 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_serial.c +++ b/applications/main/subghz/scenes/subghz_scene_set_serial.c @@ -1,6 +1,8 @@ #include "../subghz_i.h" #include "../helpers/subghz_txrx_create_protocol_key.h" +#include + #define TAG "SubGhzSetSerial" void subghz_scene_set_serial_byte_input_callback(void* context) { @@ -63,6 +65,8 @@ void subghz_scene_set_serial_on_enter(void* context) { furi_assert(byte_ptr); furi_assert(byte_count > 0); + *((uint32_t*)byte_ptr) = __bswap32(*((uint32_t*)byte_ptr)); // Convert + // Setup view ByteInput* byte_input = subghz->byte_input; byte_input_set_header_text(byte_input, "Enter SERIAL in hex"); diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 446c46a83..e4faead62 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -254,8 +254,8 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetKey); break; case GenSecPlus1: // None - return subghz_txrx_gen_secplus_v1_protocol( - subghz->txrx, subghz->gen_info->mod, subghz->gen_info->freq); + generated_protocol = subghz_scene_set_type_generate_protocol_from_infos(subghz); + break; case GenFaacSLH: // Serial (u32), Button (u8), Counter (u8), Seed (u32) case GenKeeloq: // Serial (u32), Button (u8), Counter (u8) case GenCameAtomo: // Serial (u32), Counter (u8)