@@ -100,15 +100,23 @@ static uint32_t subghz_protocol_keeloq_check_remote_controller(
100100 SubGhzKeystore * keystore ,
101101 const char * * manufacture_name );
102102
103+ /**
104+ * Defines the button value for the current btn_id
105+ * Basic set | 0x1 | 0x2 | 0x4 | 0x8 | 0xA or Special Learning Code |
106+ * @param last_btn_code Candidate for the last button
107+ * @return Button code
108+ */
109+ static uint8_t subghz_protocol_keeloq_get_btn_code (uint8_t last_btn_code );
110+
103111void * subghz_protocol_encoder_keeloq_alloc (SubGhzEnvironment * environment ) {
104112 SubGhzProtocolEncoderKeeloq * instance = malloc (sizeof (SubGhzProtocolEncoderKeeloq ));
105113
106114 instance -> base .protocol = & subghz_protocol_keeloq ;
107115 instance -> generic .protocol_name = instance -> base .protocol -> name ;
108116 instance -> keystore = subghz_environment_get_keystore (environment );
109117
110- instance -> encoder .repeat = 100 ;
111- instance -> encoder .size_upload = 256 ;
118+ instance -> encoder .repeat = 3 ;
119+ instance -> encoder .size_upload = 1100 ;
112120 instance -> encoder .upload = malloc (instance -> encoder .size_upload * sizeof (LevelDuration ));
113121 instance -> encoder .is_running = false;
114122
@@ -134,7 +142,57 @@ void subghz_protocol_encoder_keeloq_free(void* context) {
134142static bool subghz_protocol_keeloq_gen_data (
135143 SubGhzProtocolEncoderKeeloq * instance ,
136144 uint8_t btn ,
137- bool counter_up ) {
145+ bool counter_up ,
146+ bool skip_btn_check ) {
147+ // No mf name set? -> set to ""
148+ if (instance -> manufacture_name == 0x0 ) {
149+ instance -> manufacture_name = "" ;
150+ }
151+ // add gendata part
152+ ProgMode prog_mode = subghz_custom_btn_get_prog_mode ();
153+ if (!skip_btn_check && (keeloq_counter_mode != 7 )) {
154+ // Save original button
155+ if (subghz_custom_btn_get_original () == 0 ) {
156+ subghz_custom_btn_set_original (btn );
157+ }
158+
159+ // Prog mode checks and extra fixage of MF Names
160+ if (prog_mode == PROG_MODE_KEELOQ_BFT ) {
161+ instance -> manufacture_name = "BFT" ;
162+ } else if (prog_mode == PROG_MODE_KEELOQ_APRIMATIC ) {
163+ instance -> manufacture_name = "Aprimatic" ;
164+ } else if (prog_mode == PROG_MODE_KEELOQ_DEA_MIO ) {
165+ instance -> manufacture_name = "Dea_Mio" ;
166+ }
167+ // Custom button (programming mode button) for BFT, Aprimatic, Dea_Mio
168+ uint8_t klq_last_custom_btn = 0xA ;
169+ if ((strcmp (instance -> manufacture_name , "BFT" ) == 0 ) ||
170+ (strcmp (instance -> manufacture_name , "Aprimatic" ) == 0 ) ||
171+ (strcmp (instance -> manufacture_name , "Dea_Mio" ) == 0 ) ||
172+ (strcmp (instance -> manufacture_name , "NICE_MHOUSE" ) == 0 )) {
173+ klq_last_custom_btn = 0xF ;
174+ } else if (
175+ (strcmp (instance -> manufacture_name , "FAAC_RC,XT" ) == 0 ) ||
176+ (strcmp (instance -> manufacture_name , "Monarch" ) == 0 ) ||
177+ (strcmp (instance -> manufacture_name , "NICE_Smilo" ) == 0 )) {
178+ klq_last_custom_btn = 0xB ;
179+ } else if (
180+ (strcmp (instance -> manufacture_name , "Novoferm" ) == 0 ) ||
181+ (strcmp (instance -> manufacture_name , "Stilmatic" ) == 0 )) {
182+ klq_last_custom_btn = 0x9 ;
183+ } else if (
184+ (strcmp (instance -> manufacture_name , "EcoStar" ) == 0 ) ||
185+ (strcmp (instance -> manufacture_name , "Sommer" ) == 0 )) {
186+ klq_last_custom_btn = 0x6 ;
187+ } else if ((strcmp (instance -> manufacture_name , "AN-Motors" ) == 0 )) {
188+ klq_last_custom_btn = 0xC ;
189+ } else if ((strcmp (instance -> manufacture_name , "Cardin_S449" ) == 0 )) {
190+ klq_last_custom_btn = 0xD ;
191+ }
192+
193+ btn = subghz_protocol_keeloq_get_btn_code (klq_last_custom_btn );
194+ }
195+ // end gendata part
138196 // override button if we change it with signal settings button editor
139197 if (subghz_block_generic_global_button_override_get (& btn ))
140198 FURI_LOG_D (TAG , "Button sucessfully changed to 0x%X" , btn );
@@ -150,7 +208,6 @@ static bool subghz_protocol_keeloq_gen_data(
150208 }
151209
152210 // programming mode on / off conditions
153- ProgMode prog_mode = subghz_custom_btn_get_prog_mode ();
154211 if (strcmp (instance -> manufacture_name , "BFT" ) == 0 ) {
155212 // BFT programming mode on / off conditions
156213 if (btn == 0xF ) {
@@ -259,8 +316,16 @@ static bool subghz_protocol_keeloq_gen_data(
259316 } else {
260317 instance -> generic .cnt = 0xFFFF ;
261318 }
262- } else {
319+ } else if ( keeloq_counter_mode == 6 ) {
263320 // Mode 6 - Freeze counter
321+ } else {
322+ // Mode 7 - Make 12 signals in row with mode 2
323+ // + 0x3333 each time
324+ if ((instance -> generic .cnt + 0x3333 ) > 0xFFFF ) {
325+ instance -> generic .cnt = 0 ;
326+ } else {
327+ instance -> generic .cnt += 0x3333 ;
328+ }
264329 }
265330 }
266331 if (prog_mode == PROG_MODE_OFF ) {
@@ -437,7 +502,7 @@ bool subghz_protocol_keeloq_create_data(
437502 instance -> generic .cnt = cnt ;
438503 instance -> manufacture_name = manufacture_name ;
439504 instance -> generic .data_count_bit = 64 ;
440- if (subghz_protocol_keeloq_gen_data (instance , btn , false)) {
505+ if (subghz_protocol_keeloq_gen_data (instance , btn , false, true )) {
441506 return (
442507 subghz_block_generic_serialize (& instance -> generic , flipper_format , preset ) ==
443508 SubGhzProtocolStatusOk );
@@ -463,96 +528,30 @@ bool subghz_protocol_keeloq_bft_create_data(
463528 instance -> manufacture_name = manufacture_name ;
464529 instance -> generic .data_count_bit = 64 ;
465530 // hehehehe
466- if (subghz_protocol_keeloq_gen_data (instance , btn , false)) {
531+ if (subghz_protocol_keeloq_gen_data (instance , btn , false, true )) {
467532 return (
468533 subghz_block_generic_serialize (& instance -> generic , flipper_format , preset ) ==
469534 SubGhzProtocolStatusOk );
470535 }
471536 return false;
472537}
473538
474- /**
475- * Defines the button value for the current btn_id
476- * Basic set | 0x1 | 0x2 | 0x4 | 0x8 | 0xA or Special Learning Code |
477- * @param last_btn_code Candidate for the last button
478- * @return Button code
479- */
480- static uint8_t subghz_protocol_keeloq_get_btn_code (uint8_t last_btn_code );
481-
482- /**
483- * Generating an upload from data.
484- * @param instance Pointer to a SubGhzProtocolEncoderKeeloq instance
485- * @return true On success
486- */
487- static bool
488- subghz_protocol_encoder_keeloq_get_upload (SubGhzProtocolEncoderKeeloq * instance , uint8_t btn ) {
539+ static size_t subghz_protocol_encoder_keeloq_encode_to_timings (
540+ SubGhzProtocolEncoderKeeloq * instance ,
541+ uint8_t btn ,
542+ bool counter_up ,
543+ size_t index ) {
489544 furi_assert (instance );
490-
491- // Save original button
492- if (subghz_custom_btn_get_original () == 0 ) {
493- subghz_custom_btn_set_original (btn );
494- }
495-
496- // No mf name set? -> set to ""
497- if (instance -> manufacture_name == 0x0 ) {
498- instance -> manufacture_name = "" ;
499- }
500- // Prog mode checks and extra fixage of MF Names
501- ProgMode prog_mode = subghz_custom_btn_get_prog_mode ();
502- if (prog_mode == PROG_MODE_KEELOQ_BFT ) {
503- instance -> manufacture_name = "BFT" ;
504- } else if (prog_mode == PROG_MODE_KEELOQ_APRIMATIC ) {
505- instance -> manufacture_name = "Aprimatic" ;
506- } else if (prog_mode == PROG_MODE_KEELOQ_DEA_MIO ) {
507- instance -> manufacture_name = "Dea_Mio" ;
508- }
509- // Custom button (programming mode button) for BFT, Aprimatic, Dea_Mio
510- uint8_t klq_last_custom_btn = 0xA ;
511- if ((strcmp (instance -> manufacture_name , "BFT" ) == 0 ) ||
512- (strcmp (instance -> manufacture_name , "Aprimatic" ) == 0 ) ||
513- (strcmp (instance -> manufacture_name , "Dea_Mio" ) == 0 ) ||
514- (strcmp (instance -> manufacture_name , "NICE_MHOUSE" ) == 0 )) {
515- klq_last_custom_btn = 0xF ;
516- } else if (
517- (strcmp (instance -> manufacture_name , "FAAC_RC,XT" ) == 0 ) ||
518- (strcmp (instance -> manufacture_name , "Monarch" ) == 0 ) ||
519- (strcmp (instance -> manufacture_name , "NICE_Smilo" ) == 0 )) {
520- klq_last_custom_btn = 0xB ;
521- } else if (
522- (strcmp (instance -> manufacture_name , "Novoferm" ) == 0 ) ||
523- (strcmp (instance -> manufacture_name , "Stilmatic" ) == 0 )) {
524- klq_last_custom_btn = 0x9 ;
525- } else if (
526- (strcmp (instance -> manufacture_name , "EcoStar" ) == 0 ) ||
527- (strcmp (instance -> manufacture_name , "Sommer" ) == 0 )) {
528- klq_last_custom_btn = 0x6 ;
529- } else if ((strcmp (instance -> manufacture_name , "AN-Motors" ) == 0 )) {
530- klq_last_custom_btn = 0xC ;
531- } else if ((strcmp (instance -> manufacture_name , "Cardin_S449" ) == 0 )) {
532- klq_last_custom_btn = 0xD ;
533- }
534-
535- uint32_t gap_duration = subghz_protocol_keeloq_const .te_short * 40 ;
536- if ((strcmp (instance -> manufacture_name , "Sommer" ) == 0 )) {
537- gap_duration = subghz_protocol_keeloq_const .te_short * 29 ;
538- }
539-
540- btn = subghz_protocol_keeloq_get_btn_code (klq_last_custom_btn );
541-
542545 // Generate new key
543- if (subghz_protocol_keeloq_gen_data (instance , btn , true )) {
546+ if (subghz_protocol_keeloq_gen_data (instance , btn , counter_up , false )) {
544547 // OK
545548 } else {
546549 return false;
547550 }
548551
549- size_t index = 0 ;
550- size_t size_upload = 11 * 2 + 2 + (instance -> generic .data_count_bit * 2 ) + 4 ;
551- if (size_upload > instance -> encoder .size_upload ) {
552- FURI_LOG_E (TAG , "Size upload exceeds allocated encoder buffer." );
553- return false;
554- } else {
555- instance -> encoder .size_upload = size_upload ;
552+ uint32_t gap_duration = subghz_protocol_keeloq_const .te_short * 40 ;
553+ if ((strcmp (instance -> manufacture_name , "Sommer" ) == 0 )) {
554+ gap_duration = subghz_protocol_keeloq_const .te_short * 29 ;
556555 }
557556
558557 //Send header
@@ -593,6 +592,52 @@ static bool
593592 level_duration_make (true, (uint32_t )subghz_protocol_keeloq_const .te_short );
594593 instance -> encoder .upload [index ++ ] = level_duration_make (false, gap_duration );
595594
595+ return index ;
596+ }
597+
598+ /**
599+ * Generating an upload from data.
600+ * @param instance Pointer to a SubGhzProtocolEncoderKeeloq instance
601+ * @return true On success
602+ */
603+ static bool
604+ subghz_protocol_encoder_keeloq_get_upload (SubGhzProtocolEncoderKeeloq * instance , uint8_t btn ) {
605+ furi_assert (instance );
606+
607+ instance -> encoder .size_upload = 0 ;
608+ size_t upindex = 0 ;
609+
610+ if (keeloq_counter_mode == 7 ) {
611+ uint16_t temp_cnt = instance -> generic .cnt ;
612+ instance -> encoder .repeat = 1 ;
613+ for (uint8_t i = 7 ; i > 0 ; i -- ) {
614+ if (i == 3 ) {
615+ instance -> generic .cnt = 0x0000 ;
616+ upindex = subghz_protocol_encoder_keeloq_encode_to_timings (
617+ instance , (uint8_t )0x00 , false, upindex );
618+ continue ;
619+ } else if (i == 2 ) {
620+ instance -> generic .cnt = temp_cnt ;
621+ upindex = subghz_protocol_encoder_keeloq_encode_to_timings (
622+ instance , btn , false, upindex );
623+ continue ;
624+ } else if (i == 1 ) {
625+ instance -> generic .cnt = temp_cnt + 1 ;
626+ upindex = subghz_protocol_encoder_keeloq_encode_to_timings (
627+ instance , btn , false, upindex );
628+ continue ;
629+ }
630+ upindex = subghz_protocol_encoder_keeloq_encode_to_timings (
631+ instance , (uint8_t )0x00 , true, upindex );
632+ }
633+ instance -> encoder .size_upload = upindex ;
634+ return true;
635+ } else {
636+ instance -> encoder .repeat = 3 ;
637+ instance -> encoder .size_upload =
638+ subghz_protocol_encoder_keeloq_encode_to_timings (instance , btn , true, upindex );
639+ }
640+
596641 return true;
597642}
598643
@@ -719,7 +764,7 @@ LevelDuration subghz_protocol_encoder_keeloq_yield(void* context) {
719764 LevelDuration ret = instance -> encoder .upload [instance -> encoder .front ];
720765
721766 if (++ instance -> encoder .front == instance -> encoder .size_upload ) {
722- instance -> encoder .repeat -- ;
767+ if (! subghz_block_generic_global . endless_tx ) instance -> encoder .repeat -- ;
723768 instance -> encoder .front = 0 ;
724769 }
725770
@@ -1366,7 +1411,8 @@ static uint8_t subghz_protocol_keeloq_get_btn_code(uint8_t last_btn_code) {
13661411
13671412 // Set custom button
13681413 // Basic set | 0x1 | 0x2 | 0x4 | 0x8 | 0xA or Special Learning Code |
1369- if ((custom_btn_id == SUBGHZ_CUSTOM_BTN_OK ) && (original_btn_code != 0 )) {
1414+ if ((custom_btn_id == SUBGHZ_CUSTOM_BTN_OK ) && (original_btn_code != 0 ) &&
1415+ (keeloq_counter_mode != 7 )) {
13701416 // Restore original button code
13711417 btn = original_btn_code ;
13721418 } else if (custom_btn_id == SUBGHZ_CUSTOM_BTN_UP ) {
0 commit comments