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

Merge pull request #909 from MrLego8-9/feature/subghz-nice-custom-buttons

[SubGHz] Add variant of 'Add Manually' menu with manual editing for each value
This commit is contained in:
MMX
2025-07-30 06:01:15 +03:00
committed by GitHub
17 changed files with 1486 additions and 1043 deletions

View File

@@ -65,9 +65,6 @@ typedef enum {
} SubGhzCustomEvent; } SubGhzCustomEvent;
typedef enum { typedef enum {
SetTypeFaacSLH_Manual_868,
SetTypeFaacSLH_Manual_433,
SetTypeBFTClone,
SetTypeFaacSLH_868, SetTypeFaacSLH_868,
SetTypeFaacSLH_433, SetTypeFaacSLH_433,
SetTypeBFTMitto, 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,8 +12,10 @@ ADD_SCENE(subghz, saved_menu, SavedMenu)
ADD_SCENE(subghz, delete, Delete) ADD_SCENE(subghz, delete, Delete)
ADD_SCENE(subghz, delete_success, DeleteSuccess) ADD_SCENE(subghz, delete_success, DeleteSuccess)
ADD_SCENE(subghz, set_type, SetType) ADD_SCENE(subghz, set_type, SetType)
ADD_SCENE(subghz, set_fix, SetFix) ADD_SCENE(subghz, set_key, SetKey)
ADD_SCENE(subghz, set_cnt, SetCnt) ADD_SCENE(subghz, set_serial, SetSerial)
ADD_SCENE(subghz, set_button, SetButton)
ADD_SCENE(subghz, set_counter, SetCounter)
ADD_SCENE(subghz, set_seed, SetSeed) ADD_SCENE(subghz, set_seed, SetSeed)
ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer)
ADD_SCENE(subghz, radio_settings, ExtModuleSettings) 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); 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( scene_manager_previous_scene(subghz->scene_manager);
subghz->scene_manager, SubGhzSceneSetType);
} else {
scene_manager_previous_scene(subghz->scene_manager);
}
return true; return true;
} else if(event.type == SceneManagerEventTypeCustom) { } else if(event.type == SceneManagerEventTypeCustom) {

View File

@@ -0,0 +1,111 @@
#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;
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;
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,
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;
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, SubGhzSceneSetCounter);
break;
// Not needed for these types
case GenCameAtomo:
case GenPhoenixV2:
case GenData:
case GenSecPlus1:
default:
furi_crash("Not implemented");
break;
}
consumed = 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, "");
}

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) { void subghz_scene_set_seed_on_enter(void* context) {
SubGhz* subghz = 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 // Setup view
ByteInput* byte_input = subghz->byte_input; ByteInput* byte_input = subghz->byte_input;
byte_input_set_header_text(byte_input, "Enter SEED in hex"); byte_input_set_header_text(byte_input, "Enter SEED in hex");
@@ -20,8 +50,8 @@ void subghz_scene_set_seed_on_enter(void* context) {
subghz_scene_set_seed_byte_input_callback, subghz_scene_set_seed_byte_input_callback,
NULL, NULL,
subghz, subghz,
subghz->secure_data->seed, byte_ptr,
4); byte_count);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
} }
@@ -29,97 +59,61 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context; SubGhz* subghz = context;
bool consumed = false; bool consumed = false;
bool generated_protocol = false; bool generated_protocol = false;
uint32_t fix_part, cnt, seed;
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventByteInputDone) { if(event.event == SubGhzCustomEventByteInputDone) {
SetType state = GenInfo gen_info = *subghz->gen_info;
scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType);
switch(state) { switch(gen_info.type) {
case SetTypeBFTClone: case GenFaacSLH:
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) {
generated_protocol = subghz_txrx_gen_faac_slh_protocol( generated_protocol = subghz_txrx_gen_faac_slh_protocol(
subghz->txrx, subghz->txrx,
"AM650", gen_info.mod,
433920000, gen_info.freq,
fix_part >> 4, gen_info.faac_slh.serial,
fix_part & 0xf, gen_info.faac_slh.btn,
(cnt & 0xFFFFF), gen_info.faac_slh.cnt,
seed, gen_info.faac_slh.seed,
"FAAC_SLH"); gen_info.faac_slh.manuf);
} else if(state == SetTypeFaacSLH_Manual_868) { break;
generated_protocol = subghz_txrx_gen_faac_slh_protocol( case GenKeeloqBFT:
generated_protocol = subghz_txrx_gen_keeloq_bft_protocol(
subghz->txrx, subghz->txrx,
"AM650", gen_info.mod,
868350000, gen_info.freq,
fix_part >> 4, gen_info.keeloq_bft.serial,
fix_part & 0xf, gen_info.keeloq_bft.btn,
(cnt & 0xFFFFF), gen_info.keeloq_bft.cnt,
seed, gen_info.keeloq_bft.seed,
"FAAC_SLH"); gen_info.keeloq_bft.manuf);
} break;
// Not needed for these types
if(!generated_protocol) { case GenKeeloq:
furi_string_set( case GenAlutechAt4n:
subghz->error_str, "Function requires\nan SD card with\nfresh databases."); case GenSomfyTelis:
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); case GenNiceFlorS:
} case GenSecPlus2:
consumed = true; case GenPhoenixV2:
break; case GenData:
case GenSecPlus1:
default: case GenCameAtomo:
break; default:
furi_crash("Not implemented");
break;
} }
}
// Reset Seed, Fix, Cnt in secure data after successful or unsuccessful generation consumed = true;
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));
if(generated_protocol) { if(!generated_protocol) {
subghz_file_name_clear(subghz); 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( scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet); subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
return true; }
} }
} }
return consumed; 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 "../subghz_i.h"
#include "../helpers/subghz_txrx_create_protocol_key.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/blocks/math.h>
#include <lib/subghz/protocols/protocol_items.h>
#define TAG "SubGhzSetType" #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] = { 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_868] = "FAAC SLH 868MHz",
[SetTypeFaacSLH_433] = "FAAC SLH 433MHz", [SetTypeFaacSLH_433] = "FAAC SLH 433MHz",
[SetTypeBFTMitto] = "BFT Mitto 433MHz", [SetTypeBFTMitto] = "BFT Mitto 433MHz",
@@ -104,813 +102,10 @@ void subghz_scene_set_type_on_enter(void* context) {
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdMenu); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdMenu);
} }
typedef enum { bool subghz_scene_set_type_generate_protocol_from_infos(SubGhz* subghz) {
GenData, GenInfo gen_info = *subghz->gen_info;
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;
bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool generated_protocol = false; bool generated_protocol = false;
switch(gen_info.type) {
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;
}
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 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;
}
switch(gen_info.type) {
case GenData: case GenData:
if(gen_info.data.te) { if(gen_info.data.te) {
generated_protocol = subghz_txrx_gen_data_protocol_and_te( generated_protocol = subghz_txrx_gen_data_protocol_and_te(
@@ -1023,15 +218,54 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
default: default:
furi_crash("Not implemented"); furi_crash("Not implemented");
break; break;
} }
if(generated_protocol) { if(generated_protocol) {
subghz_file_name_clear(subghz); subghz_file_name_clear(subghz);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
} else { } else {
furi_string_set( furi_string_set(
subghz->error_str, "Function requires\nan SD card with\nfresh databases."); subghz->error_str, "Function requires\nan SD card with\nfresh databases.");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); 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_i.h"
#include "subghz_scene_start.h"
#include <dolphin/dolphin.h> #include <dolphin/dolphin.h>
#include <lib/subghz/protocols/raw.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) { void subghz_scene_start_submenu_callback(void* context, uint32_t index) {
SubGhz* subghz = context; SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, index); view_dispatcher_send_custom_event(subghz->view_dispatcher, index);
@@ -40,6 +31,12 @@ void subghz_scene_start_on_enter(void* context) {
SubmenuIndexAddManually, SubmenuIndexAddManually,
subghz_scene_start_submenu_callback, subghz_scene_start_submenu_callback,
subghz); subghz);
submenu_add_item(
subghz->submenu,
"Add Manually [Advanced]",
SubmenuIndexAddManuallyAdvanced,
subghz_scene_start_submenu_callback,
subghz);
submenu_add_item( submenu_add_item(
subghz->submenu, subghz->submenu,
"Frequency Analyzer", "Frequency Analyzer",
@@ -88,6 +85,11 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManually); subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManually);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType);
return true; 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) { } else if(event.event == SubmenuIndexFrequencyAnalyzer) {
scene_manager_set_scene_state( scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer); 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_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE);
subghz->secure_data = malloc(sizeof(SecureData)); subghz->gen_info = malloc(sizeof(GenInfo));
if(!alloc_for_tx_only) { if(!alloc_for_tx_only) {
subghz->ignore_filter = subghz->last_settings->ignore_filter; 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); subghz_history_free(subghz->history);
} }
free(subghz->secure_data); free(subghz->gen_info);
//TxRx //TxRx
subghz_txrx_free(subghz->txrx); subghz_txrx_free(subghz->txrx);

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "helpers/subghz_types.h" #include "helpers/subghz_types.h"
#include "helpers/subghz_gen_info.h"
#include <lib/subghz/types.h> #include <lib/subghz/types.h>
#include "subghz.h" #include "subghz.h"
#include "views/receiver.h" #include "views/receiver.h"
@@ -44,12 +45,6 @@
#define SUBGHZ_RAW_THRESHOLD_MIN (-90.0f) #define SUBGHZ_RAW_THRESHOLD_MIN (-90.0f)
#define SUBGHZ_MEASURE_LOADING false #define SUBGHZ_MEASURE_LOADING false
typedef struct {
uint8_t fix[4];
uint8_t cnt[4];
uint8_t seed[4];
} SecureData;
struct SubGhz { struct SubGhz {
Gui* gui; Gui* gui;
NotificationApp* notifications; NotificationApp* notifications;
@@ -88,7 +83,7 @@ struct SubGhz {
FuriString* error_str; FuriString* error_str;
SubGhzLock lock; SubGhzLock lock;
SecureData* secure_data; GenInfo* gen_info;
SubGhzFileEncoderWorker* decode_raw_file_worker_encoder; SubGhzFileEncoderWorker* decode_raw_file_worker_encoder;