[FL-1610] SubGhz: scene based application, PT save and replay (#630)
* SubGhz: scene based application * SubGhz: encoder/decoder separation, DMA streaming, update app and cli. * SubGhz: 2 stage async tx complete, minor cleanup * SubGhz: 2 stage async tx complete, FIX state pin end transmit * SubGhz: Pricenton, receive TE signal * SubGhz: Pricenton, add save data, add load data * SubGhz: Add Read scene, Fix pricenton save, load funtion * SubGhz: Add Read, Receiver, SaveName scene * SubGhz: Read and Save (pricenton) * SubGhz: add Load scence * SubGhz: Fix select file scene, add load scene, add transmitter view, add send tx pricenton * SubGhz: Fix pricenton encoder, fix transmitter send * SubGhz: modified Pricenton Encoder (added guard time at the beginning), modified CC1101 config, code refactoring * SubGhz: Fix pricenton encoder defalut TE * Archive: Fix path and name SubGhz * Archive: Fix name app SubGhz * GubGhz: Came: add Save, Load key * GubGhz: GateTX: add Save, Load key * GubGhz: NeroSketch: add Save, Load key * Github: better linters triggers * SubGhz: adding fast loading keys Archive -> Run in app * GubGhz: KeeLog: add Save, Load key, key generation from the serial number of the meter and the button * SubGhz: format sources and fix compilation * FuriHal: add subghz configuration description for AGC section * SubGhz: save only protocols that can be saved. Cleanup. * Github: lint on pull requests Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
@@ -16,19 +16,26 @@
|
||||
#include <furi.h>
|
||||
#include <m-string.h>
|
||||
|
||||
typedef enum {
|
||||
SubGhzProtocolTypeCame,
|
||||
SubGhzProtocolTypeKeeloq,
|
||||
SubGhzProtocolTypeNiceFlo,
|
||||
SubGhzProtocolTypeNiceFlorS,
|
||||
SubGhzProtocolTypePrinceton,
|
||||
SubGhzProtocolTypeGateTX,
|
||||
SubGhzProtocolTypeIDo,
|
||||
SubGhzProtocolTypeFaacSLH,
|
||||
SubGhzProtocolTypeNeroSketch,
|
||||
SubGhzProtocolTypeStarLine,
|
||||
|
||||
SubGhzProtocolTypeMax,
|
||||
} SubGhzProtocolType;
|
||||
|
||||
|
||||
struct SubGhzProtocol {
|
||||
SubGhzKeystore* keystore;
|
||||
|
||||
SubGhzProtocolCame* came;
|
||||
SubGhzProtocolKeeloq* keeloq;
|
||||
SubGhzProtocolNiceFlo* nice_flo;
|
||||
SubGhzProtocolNiceFlorS* nice_flor_s;
|
||||
SubGhzProtocolPrinceton* princeton;
|
||||
SubGhzProtocolGateTX* gate_tx;
|
||||
SubGhzProtocolIDo* ido;
|
||||
SubGhzProtocolFaacSLH* faac_slh;
|
||||
SubGhzProtocolNeroSketch* nero_sketch;
|
||||
SubGhzProtocolStarLine* star_line;
|
||||
SubGhzProtocolCommon* protocols[SubGhzProtocolTypeMax];
|
||||
|
||||
SubGhzProtocolTextCallback text_callback;
|
||||
void* text_callback_context;
|
||||
@@ -62,16 +69,16 @@ SubGhzProtocol* subghz_protocol_alloc() {
|
||||
|
||||
instance->keystore = subghz_keystore_alloc();
|
||||
|
||||
instance->came = subghz_protocol_came_alloc();
|
||||
instance->keeloq = subghz_protocol_keeloq_alloc(instance->keystore);
|
||||
instance->princeton = subghz_protocol_princeton_alloc();
|
||||
instance->nice_flo = subghz_protocol_nice_flo_alloc();
|
||||
instance->nice_flor_s = subghz_protocol_nice_flor_s_alloc();
|
||||
instance->gate_tx = subghz_protocol_gate_tx_alloc();
|
||||
instance->ido = subghz_protocol_ido_alloc();
|
||||
instance->faac_slh = subghz_protocol_faac_slh_alloc();
|
||||
instance->nero_sketch = subghz_protocol_nero_sketch_alloc();
|
||||
instance->star_line = subghz_protocol_star_line_alloc(instance->keystore);
|
||||
instance->protocols[SubGhzProtocolTypeCame] =(SubGhzProtocolCommon*)subghz_protocol_came_alloc();
|
||||
instance->protocols[SubGhzProtocolTypeKeeloq] = (SubGhzProtocolCommon*)subghz_protocol_keeloq_alloc(instance->keystore);
|
||||
instance->protocols[SubGhzProtocolTypePrinceton] = (SubGhzProtocolCommon*)subghz_decoder_princeton_alloc();
|
||||
instance->protocols[SubGhzProtocolTypeNiceFlo] = (SubGhzProtocolCommon*)subghz_protocol_nice_flo_alloc();
|
||||
instance->protocols[SubGhzProtocolTypeNiceFlorS] = (SubGhzProtocolCommon*)subghz_protocol_nice_flor_s_alloc();
|
||||
instance->protocols[SubGhzProtocolTypeGateTX] = (SubGhzProtocolCommon*)subghz_protocol_gate_tx_alloc();
|
||||
instance->protocols[SubGhzProtocolTypeIDo] = (SubGhzProtocolCommon*)subghz_protocol_ido_alloc();
|
||||
instance->protocols[SubGhzProtocolTypeFaacSLH] = (SubGhzProtocolCommon*)subghz_protocol_faac_slh_alloc();
|
||||
instance->protocols[SubGhzProtocolTypeNeroSketch] = (SubGhzProtocolCommon*)subghz_protocol_nero_sketch_alloc();
|
||||
instance->protocols[SubGhzProtocolTypeStarLine] = (SubGhzProtocolCommon*)subghz_protocol_star_line_alloc(instance->keystore);
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -79,35 +86,41 @@ SubGhzProtocol* subghz_protocol_alloc() {
|
||||
void subghz_protocol_free(SubGhzProtocol* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
subghz_protocol_came_free(instance->came);
|
||||
subghz_protocol_keeloq_free(instance->keeloq);
|
||||
subghz_protocol_princeton_free(instance->princeton);
|
||||
subghz_protocol_nice_flo_free(instance->nice_flo);
|
||||
subghz_protocol_nice_flor_s_free(instance->nice_flor_s);
|
||||
subghz_protocol_gate_tx_free(instance->gate_tx);
|
||||
subghz_protocol_ido_free(instance->ido);
|
||||
subghz_protocol_faac_slh_free(instance->faac_slh);
|
||||
subghz_protocol_nero_sketch_free(instance->nero_sketch);
|
||||
subghz_protocol_star_line_free(instance->star_line);
|
||||
subghz_protocol_came_free((SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame]);
|
||||
subghz_protocol_keeloq_free((SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq]);
|
||||
subghz_decoder_princeton_free((SubGhzDecoderPrinceton*)instance->protocols[SubGhzProtocolTypePrinceton]);
|
||||
subghz_protocol_nice_flo_free((SubGhzProtocolNiceFlo*)instance->protocols[SubGhzProtocolTypeNiceFlo]);
|
||||
subghz_protocol_nice_flor_s_free((SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS]);
|
||||
subghz_protocol_gate_tx_free((SubGhzProtocolGateTX*)instance->protocols[SubGhzProtocolTypeGateTX]);
|
||||
subghz_protocol_ido_free((SubGhzProtocolIDo*)instance->protocols[SubGhzProtocolTypeIDo]);
|
||||
subghz_protocol_faac_slh_free((SubGhzProtocolFaacSLH*)instance->protocols[SubGhzProtocolTypeFaacSLH]);
|
||||
subghz_protocol_nero_sketch_free((SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]);
|
||||
subghz_protocol_star_line_free((SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]);
|
||||
|
||||
subghz_keystore_free(instance->keystore);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
SubGhzProtocolCommon* subghz_protocol_get_by_name(SubGhzProtocol* instance, const char* name) {
|
||||
SubGhzProtocolCommon* result = NULL;
|
||||
|
||||
for(size_t i = 0; i < SubGhzProtocolTypeMax; i++) {
|
||||
if(strcmp(instance->protocols[i]->name, name) == 0) {
|
||||
result = instance->protocols[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void subghz_protocol_enable_dump_text(SubGhzProtocol* instance, SubGhzProtocolTextCallback callback, void* context) {
|
||||
furi_assert(instance);
|
||||
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->came, subghz_protocol_text_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->keeloq, subghz_protocol_text_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->princeton, subghz_protocol_text_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flo, subghz_protocol_text_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flor_s, subghz_protocol_text_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->gate_tx, subghz_protocol_text_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->ido, subghz_protocol_text_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->faac_slh, subghz_protocol_text_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nero_sketch, subghz_protocol_text_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->star_line, subghz_protocol_text_rx_callback, instance);
|
||||
for(size_t i = 0; i < SubGhzProtocolTypeMax; i++) {
|
||||
subghz_protocol_common_set_callback(instance->protocols[i], subghz_protocol_text_rx_callback, instance);
|
||||
}
|
||||
|
||||
instance->text_callback = callback;
|
||||
instance->text_callback_context = context;
|
||||
@@ -116,24 +129,18 @@ void subghz_protocol_enable_dump_text(SubGhzProtocol* instance, SubGhzProtocolTe
|
||||
void subghz_protocol_enable_dump(SubGhzProtocol* instance, SubGhzProtocolCommonCallbackDump callback, void* context) {
|
||||
furi_assert(instance);
|
||||
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->came, subghz_protocol_parser_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->keeloq, subghz_protocol_parser_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->princeton, subghz_protocol_parser_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flo, subghz_protocol_parser_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flor_s, subghz_protocol_parser_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->gate_tx, subghz_protocol_parser_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->ido, subghz_protocol_parser_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->faac_slh, subghz_protocol_parser_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nero_sketch, subghz_protocol_parser_rx_callback, instance);
|
||||
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->star_line, subghz_protocol_parser_rx_callback, instance);
|
||||
|
||||
for(size_t i = 0; i < SubGhzProtocolTypeMax; i++) {
|
||||
subghz_protocol_common_set_callback(instance->protocols[i], subghz_protocol_parser_rx_callback, instance);
|
||||
}
|
||||
|
||||
instance->parser_callback = callback;
|
||||
instance->parser_callback_context = context;
|
||||
}
|
||||
|
||||
|
||||
void subghz_protocol_load_nice_flor_s_file(SubGhzProtocol* instance, const char* file_name) {
|
||||
subghz_protocol_nice_flor_s_name_file(instance->nice_flor_s, file_name);
|
||||
// subghz_protocol_nice_flor_s_name_file(instance->nice_flor_s, file_name);
|
||||
subghz_protocol_nice_flor_s_name_file((SubGhzProtocolNiceFlorS*) instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name);
|
||||
}
|
||||
|
||||
void subghz_protocol_load_keeloq_file(SubGhzProtocol* instance, const char* file_name) {
|
||||
@@ -141,27 +148,29 @@ void subghz_protocol_load_keeloq_file(SubGhzProtocol* instance, const char* file
|
||||
}
|
||||
|
||||
void subghz_protocol_reset(SubGhzProtocol* instance) {
|
||||
subghz_protocol_came_reset(instance->came);
|
||||
subghz_protocol_keeloq_reset(instance->keeloq);
|
||||
subghz_protocol_princeton_reset(instance->princeton);
|
||||
subghz_protocol_nice_flo_reset(instance->nice_flo);
|
||||
subghz_protocol_nice_flor_s_reset(instance->nice_flor_s);
|
||||
subghz_protocol_gate_tx_reset(instance->gate_tx);
|
||||
subghz_protocol_ido_reset(instance->ido);
|
||||
subghz_protocol_faac_slh_reset(instance->faac_slh);
|
||||
subghz_protocol_nero_sketch_reset(instance->nero_sketch);
|
||||
subghz_protocol_star_line_reset(instance->star_line);
|
||||
|
||||
subghz_protocol_came_reset((SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame]);
|
||||
subghz_protocol_keeloq_reset((SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq]);
|
||||
subghz_decoder_princeton_reset((SubGhzDecoderPrinceton*)instance->protocols[SubGhzProtocolTypePrinceton]);
|
||||
subghz_protocol_nice_flo_reset((SubGhzProtocolNiceFlo*)instance->protocols[SubGhzProtocolTypeNiceFlo]);
|
||||
subghz_protocol_nice_flor_s_reset((SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS]);
|
||||
subghz_protocol_gate_tx_reset((SubGhzProtocolGateTX*)instance->protocols[SubGhzProtocolTypeGateTX]);
|
||||
subghz_protocol_ido_reset((SubGhzProtocolIDo*)instance->protocols[SubGhzProtocolTypeIDo]);
|
||||
subghz_protocol_faac_slh_reset((SubGhzProtocolFaacSLH*)instance->protocols[SubGhzProtocolTypeFaacSLH]);
|
||||
subghz_protocol_nero_sketch_reset((SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]);
|
||||
subghz_protocol_star_line_reset((SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]);
|
||||
}
|
||||
|
||||
void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration) {
|
||||
subghz_protocol_came_parse(instance->came, level, duration);
|
||||
subghz_protocol_keeloq_parse(instance->keeloq, level, duration);
|
||||
subghz_protocol_princeton_parse(instance->princeton, level, duration);
|
||||
subghz_protocol_nice_flo_parse(instance->nice_flo, level, duration);
|
||||
subghz_protocol_nice_flor_s_parse(instance->nice_flor_s, level, duration);
|
||||
subghz_protocol_gate_tx_parse(instance->gate_tx, level, duration);
|
||||
subghz_protocol_ido_parse(instance->ido, level, duration);
|
||||
subghz_protocol_faac_slh_parse(instance->faac_slh, level, duration);
|
||||
subghz_protocol_nero_sketch_parse(instance->nero_sketch, level, duration);
|
||||
subghz_protocol_star_line_parse(instance->star_line, level, duration);
|
||||
|
||||
subghz_protocol_came_parse((SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame], level, duration);
|
||||
subghz_protocol_keeloq_parse((SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq], level, duration);
|
||||
subghz_decoder_princeton_parse((SubGhzDecoderPrinceton*)instance->protocols[SubGhzProtocolTypePrinceton], level, duration);
|
||||
subghz_protocol_nice_flo_parse((SubGhzProtocolNiceFlo*)instance->protocols[SubGhzProtocolTypeNiceFlo], level, duration);
|
||||
subghz_protocol_nice_flor_s_parse((SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], level, duration);
|
||||
subghz_protocol_gate_tx_parse((SubGhzProtocolGateTX*)instance->protocols[SubGhzProtocolTypeGateTX], level, duration);
|
||||
subghz_protocol_ido_parse((SubGhzProtocolIDo*)instance->protocols[SubGhzProtocolTypeIDo], level, duration);
|
||||
subghz_protocol_faac_slh_parse((SubGhzProtocolFaacSLH*)instance->protocols[SubGhzProtocolTypeFaacSLH], level, duration);
|
||||
subghz_protocol_nero_sketch_parse((SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch], level, duration);
|
||||
subghz_protocol_star_line_parse((SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine], level, duration);
|
||||
}
|
||||
|
@@ -19,6 +19,14 @@ SubGhzProtocol* subghz_protocol_alloc();
|
||||
*/
|
||||
void subghz_protocol_free(SubGhzProtocol* instance);
|
||||
|
||||
/** Get protocol by name
|
||||
*
|
||||
* @param instance - SubGhzProtocol instance
|
||||
* @param name - name protocol
|
||||
* @param SubGhzProtocolCommon
|
||||
*/
|
||||
SubGhzProtocolCommon* subghz_protocol_get_by_name(SubGhzProtocol* instance, const char* name);
|
||||
|
||||
/** Outputting data text from all parsers
|
||||
*
|
||||
* @param instance - SubGhzProtocol instance
|
||||
|
@@ -19,6 +19,11 @@ SubGhzProtocolCame* subghz_protocol_came_alloc() {
|
||||
instance->common.te_shot = 320;
|
||||
instance->common.te_long = 640;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_came_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_came_to_save_str;
|
||||
instance->common.to_load_protocol=
|
||||
(SubGhzProtocolCommonLoad)subghz_protocol_came_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -99,6 +104,10 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32
|
||||
|
||||
instance->common.serial = 0x0;
|
||||
instance->common.btn = 0x0;
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
|
||||
if (instance->common.callback)
|
||||
instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
@@ -129,3 +138,75 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output) {
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %d Bit\r\n"
|
||||
" KEY:0x%lX%08lX\r\n"
|
||||
" YEK:0x%lX%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo
|
||||
);
|
||||
}
|
||||
|
||||
void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_protocol_came_to_load_protocol(FileWorker* file_worker, SubGhzProtocolCame* instance){
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
@@ -36,3 +36,13 @@ void subghz_protocol_came_reset(SubGhzProtocolCame* instance);
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output);
|
||||
|
||||
void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output);
|
||||
bool subghz_protocol_came_to_load_protocol(FileWorker* file_worker, SubGhzProtocolCame* instance);
|
||||
|
@@ -3,37 +3,50 @@
|
||||
#include <m-string.h>
|
||||
#include <furi-hal.h>
|
||||
#include <stdint.h>
|
||||
#include "file-worker.h"
|
||||
|
||||
#define bit_read(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bit_set(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define bit_clear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
|
||||
|
||||
#define SUBGHZ_TX_PIN_HIGTH()
|
||||
#define SUBGHZ_TX_PIN_LOW()
|
||||
#define SUBGHZ_TX_PIN_HIGTH()
|
||||
#define SUBGHZ_TX_PIN_LOW()
|
||||
#define DURATION_DIFF(x, y) ((x < y) ? (y - x) : (x - y))
|
||||
|
||||
//#define SUBGHZ_APP_PATH_FOLDER "/ext/subghz/saved"
|
||||
#define SUBGHZ_APP_FOLDER "/any/subghz"
|
||||
#define SUBGHZ_APP_PATH_FOLDER "/any/subghz/saved"
|
||||
#define SUBGHZ_APP_EXTENSION ".sub"
|
||||
|
||||
typedef struct SubGhzProtocolCommon SubGhzProtocolCommon;
|
||||
|
||||
typedef void (*SubGhzProtocolCommonCallback)(SubGhzProtocolCommon* parser, void* context);
|
||||
|
||||
typedef void (*SubGhzProtocolCommonToStr)(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
//Save
|
||||
typedef void (*SubGhzProtocolCommonGetStrSave)(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
//Load
|
||||
typedef bool (*SubGhzProtocolCommonLoad)(FileWorker* file_worker, SubGhzProtocolCommon* instance);
|
||||
|
||||
struct SubGhzProtocolCommon {
|
||||
const char* name;
|
||||
uint16_t te_long;
|
||||
uint16_t te_shot;
|
||||
uint16_t te_delta;
|
||||
uint64_t code_found;
|
||||
uint64_t code_last_found;
|
||||
uint8_t code_count_bit;
|
||||
uint8_t code_min_count_bit_for_found;
|
||||
uint8_t parser_step;
|
||||
uint32_t te_last;
|
||||
uint8_t header_count;
|
||||
uint16_t cnt;
|
||||
uint32_t serial;
|
||||
uint8_t btn;
|
||||
uint16_t te_long;
|
||||
uint16_t te_shot;
|
||||
uint16_t te_delta;
|
||||
uint8_t code_count_bit;
|
||||
uint8_t code_last_count_bit;
|
||||
uint64_t code_found;
|
||||
uint64_t code_last_found;
|
||||
uint8_t code_min_count_bit_for_found;
|
||||
uint8_t parser_step;
|
||||
uint32_t te_last;
|
||||
uint8_t header_count;
|
||||
uint16_t cnt;
|
||||
uint32_t serial;
|
||||
uint8_t btn;
|
||||
|
||||
/* Standard Callback for on rx complete event */
|
||||
SubGhzProtocolCommonCallback callback;
|
||||
@@ -41,15 +54,18 @@ struct SubGhzProtocolCommon {
|
||||
|
||||
/* Dump To String */
|
||||
SubGhzProtocolCommonToStr to_string;
|
||||
/* Get string to save */
|
||||
SubGhzProtocolCommonGetStrSave to_save_string;
|
||||
/*Load protocol by file*/
|
||||
SubGhzProtocolCommonLoad to_load_protocol;
|
||||
};
|
||||
|
||||
|
||||
/** Add data bit to code_found
|
||||
*
|
||||
* @param common - SubGhzProtocolCommon common
|
||||
* @param bit - add bit
|
||||
*/
|
||||
void subghz_protocol_common_add_bit(SubGhzProtocolCommon *common, uint8_t bit);
|
||||
void subghz_protocol_common_add_bit(SubGhzProtocolCommon* common, uint8_t bit);
|
||||
|
||||
/** Checking that the duration is included in the interval
|
||||
*
|
||||
@@ -58,7 +74,10 @@ void subghz_protocol_common_add_bit(SubGhzProtocolCommon *common, uint8_t bit);
|
||||
* @param duration_check duration checked
|
||||
* @return true on success
|
||||
*/
|
||||
bool subghz_protocol_common_check_interval(SubGhzProtocolCommon *common, uint32_t duration, uint16_t duration_check);
|
||||
bool subghz_protocol_common_check_interval(
|
||||
SubGhzProtocolCommon* common,
|
||||
uint32_t duration,
|
||||
uint16_t duration_check);
|
||||
|
||||
/** Bit-by-bit data mirroring
|
||||
*
|
||||
@@ -68,14 +87,16 @@ bool subghz_protocol_common_check_interval(SubGhzProtocolCommon *common, uint32_
|
||||
*/
|
||||
uint64_t subghz_protocol_common_reverse_key(uint64_t key, uint8_t count_bit);
|
||||
|
||||
|
||||
/** Callback protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCommon* instance
|
||||
* @param callback
|
||||
* @param context
|
||||
*/
|
||||
void subghz_protocol_common_set_callback(SubGhzProtocolCommon* instance, SubGhzProtocolCommonCallback callback, void* context);
|
||||
void subghz_protocol_common_set_callback(
|
||||
SubGhzProtocolCommon* instance,
|
||||
SubGhzProtocolCommonCallback callback,
|
||||
void* context);
|
||||
|
||||
/** outputting information from the parser
|
||||
*
|
||||
@@ -83,4 +104,3 @@ void subghz_protocol_common_set_callback(SubGhzProtocolCommon* instance, SubGhzP
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
|
@@ -14,6 +14,10 @@ SubGhzProtocolGateTX* subghz_protocol_gate_tx_alloc(void) {
|
||||
instance->common.te_long = 700;
|
||||
instance->common.te_delta = 100;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_gate_tx_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_gate_tx_to_save_str;
|
||||
instance->common.to_load_protocol=
|
||||
(SubGhzProtocolCommonLoad)subghz_protocol_gate_tx_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -68,13 +72,10 @@ void subghz_protocol_gate_tx_reset(SubGhzProtocolGateTX* instance) {
|
||||
* @param instance SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_gate_tx_check_remote_controller(SubGhzProtocolGateTX* instance) {
|
||||
uint32_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit);
|
||||
uint32_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
instance->common.serial = (code_found_reverse & 0xFF) << 12 | ((code_found_reverse >>8) & 0xFF) << 4 | ((code_found_reverse >>20) & 0x0F) ;
|
||||
instance->common.btn = ((code_found_reverse >> 16) & 0x0F);
|
||||
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, uint32_t duration) {
|
||||
@@ -103,7 +104,11 @@ void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, u
|
||||
if (duration >= (instance->common.te_shot * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = 1;
|
||||
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
@@ -135,20 +140,64 @@ void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, u
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output) {
|
||||
|
||||
// uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit);
|
||||
// uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
// uint32_t code_hop = (code_found_reverse >>32) & 0xFFFFFFFF;
|
||||
|
||||
//uint32_t rev_hi =
|
||||
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
string_cat_printf(output,
|
||||
"Protocol %s, %d Bit\r\n"
|
||||
"%s, %d Bit\r\n"
|
||||
" KEY:%06lX\r\n"
|
||||
" SN:%05lX BTN:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_count_bit,
|
||||
(uint32_t)(instance->common.code_found & 0xFFFFFF),
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0xFFFFFF),
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
instance->common.btn
|
||||
);
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_protocol_gate_tx_to_load_protocol(FileWorker* file_worker, SubGhzProtocolGateTX* instance){
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
@@ -42,4 +42,7 @@ void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, u
|
||||
* @param instance - SubGhzProtocolFaacSLH* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output);
|
||||
void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output);
|
||||
|
||||
void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output);
|
||||
bool subghz_protocol_gate_tx_to_load_protocol(FileWorker* file_worker, SubGhzProtocolGateTX* instance);
|
||||
|
@@ -24,6 +24,10 @@ SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore) {
|
||||
instance->common.te_long = 800;
|
||||
instance->common.te_delta = 140;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_keeloq_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_keeloq_to_save_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoad)subghz_protocol_keeloq_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -40,86 +44,97 @@ void subghz_protocol_keeloq_free(SubGhzProtocolKeeloq* instance) {
|
||||
* @param hop hop encrypted part of the parcel
|
||||
* @return true on successful search
|
||||
*/
|
||||
uint8_t subghz_protocol_keeloq_check_remote_controller_selector(SubGhzProtocolKeeloq* instance, uint32_t fix , uint32_t hop) {
|
||||
uint16_t end_serial = (uint16_t)(fix&0x3FF);
|
||||
uint8_t btn = (uint8_t)(fix>>28);
|
||||
uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
|
||||
SubGhzProtocolKeeloq* instance,
|
||||
uint32_t fix,
|
||||
uint32_t hop) {
|
||||
uint16_t end_serial = (uint16_t)(fix & 0x3FF);
|
||||
uint8_t btn = (uint8_t)(fix >> 28);
|
||||
uint32_t decrypt = 0;
|
||||
uint64_t man_normal_learning;
|
||||
|
||||
for
|
||||
M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) {
|
||||
switch (manufacture_code->type){
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt>>28 == btn) && ((((uint16_t)(decrypt>>16)) & 0x3FF) == end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
switch(manufacture_code->type) {
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if( (decrypt>>28 ==btn)&& ((((uint16_t)(decrypt>>16))&0x3FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
// Simple Learning
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if( (decrypt>>28 ==btn) && ((((uint16_t)(decrypt>>16))&0x3FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
uint64_t man_rev=0;
|
||||
uint64_t man_rev_byte=0;
|
||||
for(uint8_t i=0; i<64; i+=8){
|
||||
man_rev_byte=(uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56-i);
|
||||
}
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, man_rev);
|
||||
if( (decrypt>>28 ==btn) && ((((uint16_t)(decrypt>>16))&0x3FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt= decrypt&0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
//###########################
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if( (decrypt>>28 ==btn)&& ((((uint16_t)(decrypt>>16))&0x3FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt= decrypt&0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
man_rev=0;
|
||||
man_rev_byte=0;
|
||||
for(uint8_t i=0; i<64; i+=8){
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56-i);
|
||||
}
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if( (decrypt>>28 ==btn) && ((((uint16_t)(decrypt>>16))&0x3FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt= decrypt&0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
// Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
uint64_t man_rev = 0;
|
||||
uint64_t man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
//###########################
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
man_rev = 0;
|
||||
man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
instance->manufacture_name = "Unknown";
|
||||
instance->common.cnt=0;
|
||||
instance->common.cnt = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -129,22 +144,23 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(SubGhzProtocolKe
|
||||
* @param instance SubGhzProtocolKeeloq instance
|
||||
*/
|
||||
void subghz_protocol_keeloq_check_remote_controller(SubGhzProtocolKeeloq* instance) {
|
||||
uint64_t key = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit);
|
||||
uint64_t key = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t key_fix = key >> 32;
|
||||
uint32_t key_hop = key & 0x00000000ffffffff;
|
||||
// Check key AN-Motors
|
||||
if((key_hop >> 24) == ((key_hop>>16)&0x00ff) && (key_fix>>28) ==((key_hop>>12)&0x0f) && (key_hop & 0xFFF ) == 0x404){
|
||||
if((key_hop >> 24) == ((key_hop >> 16) & 0x00ff) &&
|
||||
(key_fix >> 28) == ((key_hop >> 12) & 0x0f) && (key_hop & 0xFFF) == 0x404) {
|
||||
instance->manufacture_name = "AN-Motors";
|
||||
instance->common.cnt = key_hop>>16;
|
||||
} else if((key_hop & 0xFFF) == (0x000) && (key_fix>>28) ==((key_hop>>12)&0x0f) ){
|
||||
instance->common.cnt = key_hop >> 16;
|
||||
} else if((key_hop & 0xFFF) == (0x000) && (key_fix >> 28) == ((key_hop >> 12) & 0x0f)) {
|
||||
instance->manufacture_name = "HCS101";
|
||||
instance->common.cnt = key_hop>>16;
|
||||
instance->common.cnt = key_hop >> 16;
|
||||
} else {
|
||||
subghz_protocol_keeloq_check_remote_controller_selector(instance, key_fix, key_hop);
|
||||
}
|
||||
instance ->common.serial= key_fix&0x0FFFFFFF;
|
||||
instance->common.serial = key_fix & 0x0FFFFFFF;
|
||||
instance->common.btn = key_fix >> 28;
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
@@ -153,7 +169,7 @@ void subghz_protocol_keeloq_check_remote_controller(SubGhzProtocolKeeloq* instan
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_keeloq_send_bit(SubGhzProtocolKeeloq* instance, uint8_t bit) {
|
||||
if (bit) {
|
||||
if(bit) {
|
||||
// send bit 1
|
||||
SUBGHZ_TX_PIN_HIGTH();
|
||||
delay_us(instance->common.te_shot);
|
||||
@@ -168,10 +184,14 @@ void subghz_protocol_keeloq_send_bit(SubGhzProtocolKeeloq* instance, uint8_t bit
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, uint64_t key, uint8_t bit, uint8_t repeat) {
|
||||
while (repeat--) {
|
||||
void subghz_protocol_keeloq_send_key(
|
||||
SubGhzProtocolKeeloq* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
// Send header
|
||||
for (uint8_t i = 11; i > 0; i--) {
|
||||
for(uint8_t i = 11; i > 0; i--) {
|
||||
SUBGHZ_TX_PIN_HIGTH();
|
||||
delay_us(instance->common.te_shot);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
@@ -179,7 +199,7 @@ void subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, uint64_t ke
|
||||
}
|
||||
delay_us(instance->common.te_shot * 9); //+1 up Send header
|
||||
|
||||
for (uint8_t i = bit; i > 0; i--) {
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_keeloq_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
// +send 2 status bit
|
||||
@@ -187,7 +207,7 @@ void subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, uint64_t ke
|
||||
subghz_protocol_keeloq_send_bit(instance, 0);
|
||||
// send end
|
||||
subghz_protocol_keeloq_send_bit(instance, 0);
|
||||
delay_us(instance->common.te_shot * 2); //+2 interval END SEND
|
||||
delay_us(instance->common.te_shot * 2); //+2 interval END SEND
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,9 +216,10 @@ void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance) {
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration) {
|
||||
switch (instance->common.parser_step) {
|
||||
switch(instance->common.parser_step) {
|
||||
case 0:
|
||||
if ((level) && DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta) {
|
||||
if((level) &&
|
||||
DURATION_DIFF(duration, instance->common.te_shot) < instance->common.te_delta) {
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.header_count++;
|
||||
} else {
|
||||
@@ -207,11 +228,14 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui
|
||||
|
||||
break;
|
||||
case 1:
|
||||
if ((!level) && (DURATION_DIFF(duration, instance->common.te_shot ) < instance->common.te_delta)) {
|
||||
if((!level) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_shot) < instance->common.te_delta)) {
|
||||
instance->common.parser_step = 0;
|
||||
break;
|
||||
}
|
||||
if ((instance->common.header_count > 2) && ( DURATION_DIFF(duration, instance->common.te_shot * 10)< instance->common.te_delta * 10)) {
|
||||
if((instance->common.header_count > 2) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_shot * 10) <
|
||||
instance->common.te_delta * 10)) {
|
||||
// Found header
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.code_found = 0;
|
||||
@@ -222,35 +246,45 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (level) {
|
||||
if(level) {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (!level) {
|
||||
if (duration >= (instance->common.te_shot * 2 + instance->common.te_delta)) {
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_shot * 2 + instance->common.te_delta)) {
|
||||
// Found end TX
|
||||
instance->common.parser_step = 0;
|
||||
if (instance->common.code_count_bit >= instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found != instance->common.code_found ){
|
||||
subghz_protocol_keeloq_check_remote_controller(instance);
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found != instance->common.code_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
} else if ((DURATION_DIFF(instance->common.te_last, instance->common.te_shot) < instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
if (instance->common.code_count_bit < instance->common.code_min_count_bit_for_found) {
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_shot) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
if(instance->common.code_count_bit <
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
}
|
||||
instance->common.parser_step = 2;
|
||||
} else if ((DURATION_DIFF(instance->common.te_last, instance->common.te_long) < instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_shot) < instance->common.te_delta)) {
|
||||
if (instance->common.code_count_bit < instance->common.code_min_count_bit_for_found) {
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_shot) < instance->common.te_delta)) {
|
||||
if(instance->common.code_count_bit <
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
}
|
||||
instance->common.parser_step = 2;
|
||||
@@ -267,29 +301,152 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output) {
|
||||
uint32_t code_found_hi = instance->common.code_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_found & 0x00000000ffffffff;
|
||||
subghz_protocol_keeloq_check_remote_controller(instance);
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse>>32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse&0x00000000ffffffff;
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Protocol %s, %d Bit\r\n"
|
||||
"%s, %d Bit\r\n"
|
||||
"KEY:0x%lX%lX\r\n"
|
||||
"FIX:%08lX MF:%s \r\n"
|
||||
"HOP:%08lX \r\n"
|
||||
"SN:%07lX CNT:%04X B:%02lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_count_bit,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
instance->manufacture_name,
|
||||
code_found_reverse_lo,
|
||||
instance->common.serial,
|
||||
instance->common.cnt,
|
||||
instance->common.btn
|
||||
);
|
||||
instance->common.cnt,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
uint64_t subghz_protocol_keeloq_gen_key(SubGhzProtocolKeeloq* instance) {
|
||||
uint32_t fix = instance->common.btn << 28 | instance->common.serial;
|
||||
uint32_t decrypt = instance->common.btn << 28 | (instance->common.serial & 0x3FF) << 16 |
|
||||
instance->common.cnt;
|
||||
uint32_t hop = 0;
|
||||
uint64_t man_normal_learning = 0;
|
||||
int res = 0;
|
||||
|
||||
for
|
||||
M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) {
|
||||
res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name);
|
||||
if(res == 0) {
|
||||
switch(manufacture_code->type) {
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
hop = subghz_protocol_keeloq_common_encrypt(decrypt, manufacture_code->key);
|
||||
break;
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
//Simple Learning
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
hop = subghz_protocol_keeloq_common_encrypt(decrypt, man_normal_learning);
|
||||
break;
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
hop = 0; //todo
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint64_t yek = (uint64_t)fix << 32 | hop;
|
||||
return subghz_protocol_common_reverse_key(yek, instance->common.code_last_count_bit);
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Manufacture_name: %s\n"
|
||||
"Serial: %08lX\n"
|
||||
"Cnt: %04lX\n"
|
||||
"Btn: %01lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
instance->manufacture_name,
|
||||
instance->common.serial,
|
||||
instance->common.cnt,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
bool subghz_protocol_keeloq_to_load_protocol(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolKeeloq* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
string_t temp_name_man;
|
||||
string_init(temp_name_man);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse name protocol from 3st line
|
||||
if(!file_worker_read_until(file_worker, temp_name_man, '\n')) {
|
||||
break;
|
||||
}
|
||||
// strlen("Manufacture_name: ") = 18
|
||||
string_right(temp_name_man, 18);
|
||||
instance->manufacture_name = string_get_cstr(temp_name_man);
|
||||
|
||||
// Read and parse key data from 4nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_param = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Serial: %08lX\n", &temp_param);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.serial = temp_param;
|
||||
|
||||
// Read and parse key data from 5nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Cnt: %04lX\n", &temp_param);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.cnt = (uint16_t)temp_param;
|
||||
|
||||
// Read and parse key data from 5nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Btn: %01lX\n", &temp_param);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.btn = (uint8_t)temp_param;
|
||||
|
||||
instance->common.code_last_found = subghz_protocol_keeloq_gen_key(instance);
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
string_clear(temp_name_man);
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
@@ -45,3 +45,6 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output);
|
||||
|
||||
void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output);
|
||||
bool subghz_protocol_keeloq_to_load_protocol(FileWorker* file_worker, SubGhzProtocolKeeloq* instance);
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include "subghz_protocol_common.h"
|
||||
#include "file-worker.h"
|
||||
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
|
@@ -14,6 +14,10 @@ SubGhzProtocolNeroSketch* subghz_protocol_nero_sketch_alloc(void) {
|
||||
instance->common.te_long = 660;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nero_sketch_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_nero_sketch_to_save_str;
|
||||
instance->common.to_load_protocol=
|
||||
(SubGhzProtocolCommonLoad)subghz_protocol_nero_sketch_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -80,18 +84,18 @@ void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance) {
|
||||
*
|
||||
* @param instance SubGhzProtocolNeroSketch instance
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_check_remote_controller(SubGhzProtocolNeroSketch* instance) {
|
||||
//пока не понятно с серийником, но код статический
|
||||
// uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit);
|
||||
// uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
// //uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF;
|
||||
// void subghz_protocol_nero_sketch_check_remote_controller(SubGhzProtocolNeroSketch* instance) {
|
||||
// //пока не понятно с серийником, но код статический
|
||||
// // uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit);
|
||||
// // uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
// // //uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF;
|
||||
|
||||
// instance->common.serial = code_fix & 0xFFFFFFF;
|
||||
// instance->common.btn = (code_fix >> 28) & 0x0F;
|
||||
// // instance->common.serial = code_fix & 0xFFFFFFF;
|
||||
// // instance->common.btn = (code_fix >> 28) & 0x0F;
|
||||
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
// //if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool level, uint32_t duration) {
|
||||
switch (instance->common.parser_step) {
|
||||
@@ -140,7 +144,11 @@ void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool
|
||||
//Found stop bit
|
||||
instance->common.parser_step = 0;
|
||||
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
|
||||
subghz_protocol_nero_sketch_check_remote_controller(instance);
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
@@ -176,25 +184,77 @@ void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool
|
||||
|
||||
void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output) {
|
||||
|
||||
uint32_t code_found_hi = instance->common.code_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_found & 0x00000000ffffffff;
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse>>32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse&0x00000000ffffffff;
|
||||
|
||||
//uint32_t rev_hi =
|
||||
|
||||
string_cat_printf(output,
|
||||
"Protocol %s, %d Bit\r\n"
|
||||
"%s, %d Bit\r\n"
|
||||
" KEY:0x%lX%08lX\r\n"
|
||||
" YEK:0x%lX%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_count_bit,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo
|
||||
);
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output) {
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX%08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo
|
||||
);
|
||||
}
|
||||
|
||||
bool subghz_protocol_nero_sketch_to_load_protocol(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance){
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key_hi = 0;
|
||||
uint32_t temp_key_lo = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX%08lX\n", &temp_key_hi, &temp_key_lo);
|
||||
if(res != 2) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key_hi<<32 | temp_key_lo;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
@@ -49,3 +49,6 @@ void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output);
|
||||
|
||||
void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output);
|
||||
bool subghz_protocol_nero_sketch_to_load_protocol(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance);
|
||||
|
@@ -1,39 +1,120 @@
|
||||
#include "subghz_protocol_princeton.h"
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://phreakerclub.com/447
|
||||
*
|
||||
*/
|
||||
|
||||
struct SubGhzProtocolPrinceton {
|
||||
SubGhzProtocolCommon common;
|
||||
#define SUBGHZ_PT_SHORT 450
|
||||
#define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
|
||||
#define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
|
||||
|
||||
struct SubGhzEncoderPrinceton {
|
||||
uint32_t key;
|
||||
uint16_t te;
|
||||
size_t repeat;
|
||||
size_t front;
|
||||
};
|
||||
|
||||
SubGhzProtocolPrinceton* subghz_protocol_princeton_alloc(void) {
|
||||
SubGhzProtocolPrinceton* instance = furi_alloc(sizeof(SubGhzProtocolPrinceton));
|
||||
struct SubGhzDecoderPrinceton {
|
||||
SubGhzProtocolCommon common;
|
||||
uint16_t te;
|
||||
};
|
||||
|
||||
instance->common.name = "Princeton";
|
||||
instance->common.code_min_count_bit_for_found = 24;
|
||||
instance->common.te_shot = 450;//150;
|
||||
instance->common.te_long = 1350;//450;
|
||||
instance->common.te_delta = 200;//50;
|
||||
SubGhzEncoderPrinceton* subghz_encoder_princeton_alloc() {
|
||||
SubGhzEncoderPrinceton* instance = furi_alloc(sizeof(SubGhzEncoderPrinceton));
|
||||
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_princeton_free(SubGhzProtocolPrinceton* instance) {
|
||||
void subghz_encoder_princeton_free(SubGhzEncoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
void subghz_encoder_princeton_set_te(SubGhzEncoderPrinceton* instance, void* decoder){
|
||||
SubGhzDecoderPrinceton* pricenton = decoder;
|
||||
if((pricenton->te) !=0){
|
||||
instance->te = pricenton->te;
|
||||
}else{
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void subghz_encoder_princeton_reset(SubGhzEncoderPrinceton* instance, uint32_t key, size_t repeat) {
|
||||
furi_assert(instance);
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
instance->key = key;
|
||||
instance->repeat = repeat;
|
||||
instance->front = 48;
|
||||
}
|
||||
|
||||
size_t subghz_encoder_princeton_get_repeat_left(SubGhzEncoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->repeat;
|
||||
}
|
||||
|
||||
LevelDuration subghz_encoder_princeton_yield(void* context) {
|
||||
SubGhzEncoderPrinceton* instance = context;
|
||||
if(instance->repeat == 0) return level_duration_reset();
|
||||
|
||||
size_t bit = instance->front / 2;
|
||||
bool level = !(instance->front % 2);
|
||||
|
||||
LevelDuration ret;
|
||||
if(bit < 24) {
|
||||
uint8_t byte = bit / 8;
|
||||
uint8_t bit_in_byte = bit % 8;
|
||||
bool value = (((uint8_t*)&instance->key)[2 - byte] >> (7 - bit_in_byte)) & 1;
|
||||
if(value) {
|
||||
ret = level_duration_make(level, level ? instance->te * 3 : instance->te);
|
||||
} else {
|
||||
ret = level_duration_make(level, level ? instance->te : instance->te * 3);
|
||||
}
|
||||
} else {
|
||||
ret = level_duration_make(level, level ? instance->te : instance->te * 30);
|
||||
}
|
||||
|
||||
instance->front++;
|
||||
if(instance->front == 50) {
|
||||
instance->repeat--;
|
||||
instance->front = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc(void) {
|
||||
SubGhzDecoderPrinceton* instance = furi_alloc(sizeof(SubGhzDecoderPrinceton));
|
||||
|
||||
instance->common.name = "Princeton";
|
||||
instance->common.code_min_count_bit_for_found = 24;
|
||||
instance->common.te_shot = 450; //150;
|
||||
instance->common.te_long = 1350; //450;
|
||||
instance->common.te_delta = 200; //50;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_decoder_princeton_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_decoder_princeton_to_save_str;
|
||||
instance->common.to_load_protocol=
|
||||
(SubGhzProtocolCommonLoad)subghz_decoder_princeton_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
*
|
||||
* @param instance - SubGhzProtocolPrinceton instance
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_princeton_send_bit(SubGhzProtocolPrinceton* instance, uint8_t bit) {
|
||||
if (bit) {
|
||||
void subghz_decoder_princeton_send_bit(SubGhzDecoderPrinceton* instance, uint8_t bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long);
|
||||
@@ -48,29 +129,36 @@ void subghz_protocol_princeton_send_bit(SubGhzProtocolPrinceton* instance, uint8
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_princeton_send_key(SubGhzProtocolPrinceton* instance, uint64_t key, uint8_t bit,uint8_t repeat) {
|
||||
while (repeat--) {
|
||||
void subghz_decoder_princeton_send_key(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
//Send start bit
|
||||
subghz_protocol_princeton_send_bit(instance, 1);
|
||||
subghz_decoder_princeton_send_bit(instance, 1);
|
||||
//Send header
|
||||
delay_us(instance->common.te_shot * 33); //+2 interval v bit 1
|
||||
//Send key data
|
||||
for (uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_princeton_send_bit(instance, bit_read(key, i - 1));
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_decoder_princeton_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_princeton_reset(SubGhzProtocolPrinceton* instance) {
|
||||
void subghz_decoder_princeton_reset(SubGhzDecoderPrinceton* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
}
|
||||
|
||||
void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, bool level, uint32_t duration) {
|
||||
switch (instance->common.parser_step) {
|
||||
void subghz_decoder_princeton_parse(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case 0:
|
||||
if ((!level)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_shot * 36) < instance->common.te_delta * 36)) {
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_shot * 36) <
|
||||
instance->common.te_delta * 36)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.code_found = 0;
|
||||
@@ -81,33 +169,49 @@ void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, bool lev
|
||||
break;
|
||||
case 1:
|
||||
//save duration
|
||||
if (level) {
|
||||
if(level) {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 2;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!level) {
|
||||
if (duration >= (instance->common.te_shot * 10 + instance->common.te_delta)) {
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_shot * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = 1;
|
||||
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found == instance->common.code_found) {
|
||||
//instance->te = (instance->te+instance->common.te_last)/2; //Option 1 TE averaging
|
||||
if(instance->te > instance->common.te_last)
|
||||
instance->te = instance->common.te_last; //Option 2 TE averaging
|
||||
} else {
|
||||
instance->te = instance->common.te_last;
|
||||
}
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
instance->common.serial = instance->common.code_found >> 4;
|
||||
instance->common.btn = (uint8_t)instance->common.code_found & 0x00000F;
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot)< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_long)< instance->common.te_delta*3)) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_shot) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 1;
|
||||
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta*3)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_shot)< instance->common.te_delta)) {
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_shot) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 1;
|
||||
} else {
|
||||
@@ -119,3 +223,92 @@ void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, bool lev
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output) {
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %d Bit te %dus\r\n"
|
||||
" KEY:0x%lX%08lX\r\n"
|
||||
" YEK:0x%lX%08lX\r\n"
|
||||
" SN:0x%05lX BTN:%02X\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
instance->te,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo,
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Te: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
instance->te,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_decoder_princeton_to_load_protocol(FileWorker* file_worker, SubGhzDecoderPrinceton* instance){
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse te data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Te: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->te = (uint16_t)data;
|
||||
|
||||
// Read and parse key data from 4nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
instance->common.serial = instance->common.code_last_found >> 4;
|
||||
instance->common.btn = (uint8_t)instance->common.code_last_found & 0x00000F;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
@@ -2,38 +2,90 @@
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolPrinceton SubGhzProtocolPrinceton;
|
||||
|
||||
/** Allocate SubGhzProtocolPrinceton
|
||||
*
|
||||
* @return SubGhzProtocolPrinceton*
|
||||
/** SubGhzEncoderPrinceton anonymous type */
|
||||
typedef struct SubGhzEncoderPrinceton SubGhzEncoderPrinceton;
|
||||
|
||||
/** Allocate SubGhzEncoderPrinceton
|
||||
* @return pointer to SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
SubGhzProtocolPrinceton* subghz_protocol_princeton_alloc();
|
||||
SubGhzEncoderPrinceton* subghz_encoder_princeton_alloc();
|
||||
|
||||
/** Free SubGhzProtocolPrinceton
|
||||
/** Free SubGhzEncoderPrinceton instance
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
void subghz_encoder_princeton_free(SubGhzEncoderPrinceton* instance);
|
||||
|
||||
|
||||
/** Reset encoder with new params
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @param key - 24bit key
|
||||
* @param repeat - how many times to repeat
|
||||
*/
|
||||
void subghz_encoder_princeton_reset(SubGhzEncoderPrinceton* instance, uint32_t key, size_t repeat);
|
||||
|
||||
/** Get repeat count left
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @return repeat count left
|
||||
*/
|
||||
size_t subghz_encoder_princeton_get_repeat_left(SubGhzEncoderPrinceton* instance);
|
||||
|
||||
/** Get level duration
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @return level duration
|
||||
*/
|
||||
LevelDuration subghz_encoder_princeton_yield(void* context);
|
||||
|
||||
|
||||
/** SubGhzDecoderPrinceton anonymous type */
|
||||
typedef struct SubGhzDecoderPrinceton SubGhzDecoderPrinceton;
|
||||
|
||||
|
||||
void subghz_encoder_princeton_set_te(
|
||||
SubGhzEncoderPrinceton* instance,
|
||||
void* decoder);
|
||||
|
||||
/** Allocate SubGhzDecoderPrinceton
|
||||
*
|
||||
* @return SubGhzDecoderPrinceton*
|
||||
*/
|
||||
SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc();
|
||||
|
||||
/** Free SubGhzDecoderPrinceton
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_princeton_free(SubGhzProtocolPrinceton* instance);
|
||||
void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance);
|
||||
|
||||
/** Sends the key on the air
|
||||
*
|
||||
* @param instance - SubGhzProtocolPrinceton instance
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param key - key send
|
||||
* @param bit - count bit key
|
||||
* @param repeat - repeat send key
|
||||
*/
|
||||
void subghz_protocol_princeton_send_key(SubGhzProtocolPrinceton* instance, uint64_t key, uint8_t bit, uint8_t repeat);
|
||||
void subghz_decoder_princeton_send_key(SubGhzDecoderPrinceton* instance, uint64_t key, uint8_t bit, uint8_t repeat);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolPrinceton instance
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
*/
|
||||
void subghz_protocol_princeton_reset(SubGhzProtocolPrinceton* instance);
|
||||
void subghz_decoder_princeton_reset(SubGhzDecoderPrinceton* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolPrinceton instance
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, bool level, uint32_t duration);
|
||||
void subghz_decoder_princeton_parse(SubGhzDecoderPrinceton* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output);
|
||||
|
||||
void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output);
|
||||
bool subghz_decoder_princeton_to_load_protocol(FileWorker* file_worker, SubGhzDecoderPrinceton* instance);
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user