1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 04:34:43 +04:00

feat: add variation of 'Add Manually' menu with manual value selection for all entries

This commit is contained in:
Louis D
2025-07-23 23:24:03 +02:00
parent e6cc2852fd
commit 115734373b
17 changed files with 1445 additions and 1073 deletions

View File

@@ -65,9 +65,6 @@ typedef enum {
} SubGhzCustomEvent;
typedef enum {
SetTypeFaacSLH_Manual_868,
SetTypeFaacSLH_Manual_433,
SetTypeBFTClone,
SetTypeFaacSLH_868,
SetTypeFaacSLH_433,
SetTypeBFTMitto,

View File

@@ -0,0 +1,725 @@
#include "subghz_gen_info.h"
#include "../helpers/subghz_txrx_create_protocol_key.h"
#include <lib/subghz/protocols/protocol_items.h>
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;
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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, "");
}

View File

@@ -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, "");
}

View File

@@ -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, "");
}

View File

@@ -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, "");
}

View File

@@ -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;

View File

@@ -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, "");
}

View File

@@ -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 <lib/subghz/blocks/math.h>
#include <lib/subghz/protocols/protocol_items.h>
#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;
}
}

View File

@@ -1,18 +1,9 @@
#include "../subghz_i.h"
#include "subghz_scene_start.h"
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/raw.h>
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);

View File

@@ -0,0 +1,12 @@
#pragma once
enum SubmenuIndex {
SubmenuIndexRead = 10,
SubmenuIndexSaved,
SubmenuIndexAddManually,
SubmenuIndexAddManuallyAdvanced,
SubmenuIndexFrequencyAnalyzer,
SubmenuIndexReadRAW,
SubmenuIndexExtSettings,
SubmenuIndexRadioSetting,
};

View File

@@ -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);

View File

@@ -1,6 +1,7 @@
#pragma once
#include "helpers/subghz_types.h"
#include "helpers/subghz_gen_info.h"
#include <lib/subghz/types.h>
#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;