secplus_v1.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. #include "secplus_v1.h"
  2. #include "../blocks/const.h"
  3. #include "../blocks/decoder.h"
  4. #include "../blocks/encoder.h"
  5. #include "../blocks/generic.h"
  6. #include "../blocks/math.h"
  7. /*
  8. * Help
  9. * https://github.com/argilo/secplus
  10. * https://github.com/merbanan/rtl_433/blob/master/src/devices/secplus_v1.c
  11. */
  12. #define TAG "SubGhzProtocoSecPlus_v1"
  13. #define SECPLUS_V1_BIT_ERR -1 //0b0000
  14. #define SECPLUS_V1_BIT_0 0 //0b0001
  15. #define SECPLUS_V1_BIT_1 1 //0b0011
  16. #define SECPLUS_V1_BIT_2 2 //0b0111
  17. #define SECPLUS_V1_PACKET_1_HEADER 0x00
  18. #define SECPLUS_V1_PACKET_2_HEADER 0x02
  19. #define SECPLUS_V1_PACKET_1_INDEX_BASE 0
  20. #define SECPLUS_V1_PACKET_2_INDEX_BASE 21
  21. #define SECPLUS_V1_PACKET_1_ACCEPTED (1 << 0)
  22. #define SECPLUS_V1_PACKET_2_ACCEPTED (1 << 1)
  23. static const SubGhzBlockConst subghz_protocol_secplus_v1_const = {
  24. .te_short = 500,
  25. .te_long = 1500,
  26. .te_delta = 100,
  27. .min_count_bit_for_found = 21,
  28. };
  29. struct SubGhzProtocolDecoderSecPlus_v1 {
  30. SubGhzProtocolDecoderBase base;
  31. SubGhzBlockDecoder decoder;
  32. SubGhzBlockGeneric generic;
  33. uint8_t packet_accepted;
  34. uint8_t base_packet_index;
  35. uint8_t data_array[44];
  36. };
  37. struct SubGhzProtocolEncoderSecPlus_v1 {
  38. SubGhzProtocolEncoderBase base;
  39. SubGhzProtocolBlockEncoder encoder;
  40. SubGhzBlockGeneric generic;
  41. uint8_t data_array[44];
  42. };
  43. typedef enum {
  44. SecPlus_v1DecoderStepReset = 0,
  45. SecPlus_v1DecoderStepSearchStartBit,
  46. SecPlus_v1DecoderStepSaveDuration,
  47. SecPlus_v1DecoderStepDecoderData,
  48. } SecPlus_v1DecoderStep;
  49. const SubGhzProtocolDecoder subghz_protocol_secplus_v1_decoder = {
  50. .alloc = subghz_protocol_decoder_secplus_v1_alloc,
  51. .free = subghz_protocol_decoder_secplus_v1_free,
  52. .feed = subghz_protocol_decoder_secplus_v1_feed,
  53. .reset = subghz_protocol_decoder_secplus_v1_reset,
  54. .get_hash_data = subghz_protocol_decoder_secplus_v1_get_hash_data,
  55. .serialize = subghz_protocol_decoder_secplus_v1_serialize,
  56. .deserialize = subghz_protocol_decoder_secplus_v1_deserialize,
  57. .get_string = subghz_protocol_decoder_secplus_v1_get_string,
  58. };
  59. const SubGhzProtocolEncoder subghz_protocol_secplus_v1_encoder = {
  60. .alloc = subghz_protocol_encoder_secplus_v1_alloc,
  61. .free = subghz_protocol_encoder_secplus_v1_free,
  62. .deserialize = subghz_protocol_encoder_secplus_v1_deserialize,
  63. .stop = subghz_protocol_encoder_secplus_v1_stop,
  64. .yield = subghz_protocol_encoder_secplus_v1_yield,
  65. };
  66. const SubGhzProtocol subghz_protocol_secplus_v1 = {
  67. .name = SUBGHZ_PROTOCOL_SECPLUS_V1_NAME,
  68. .type = SubGhzProtocolTypeDynamic,
  69. .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
  70. SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Send,
  71. .decoder = &subghz_protocol_secplus_v1_decoder,
  72. .encoder = &subghz_protocol_secplus_v1_encoder,
  73. };
  74. void* subghz_protocol_encoder_secplus_v1_alloc(SubGhzEnvironment* environment) {
  75. UNUSED(environment);
  76. SubGhzProtocolEncoderSecPlus_v1* instance = malloc(sizeof(SubGhzProtocolEncoderSecPlus_v1));
  77. instance->base.protocol = &subghz_protocol_secplus_v1;
  78. instance->generic.protocol_name = instance->base.protocol->name;
  79. instance->encoder.repeat = 10;
  80. instance->encoder.size_upload = 128;
  81. instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
  82. instance->encoder.is_running = false;
  83. return instance;
  84. }
  85. void subghz_protocol_encoder_secplus_v1_free(void* context) {
  86. furi_assert(context);
  87. SubGhzProtocolEncoderSecPlus_v1* instance = context;
  88. free(instance->encoder.upload);
  89. free(instance);
  90. }
  91. /**
  92. * Generating an upload from data.
  93. * @param instance Pointer to a SubGhzProtocolEncoderSecPlus_v1 instance
  94. * @return true On success
  95. */
  96. static bool
  97. subghz_protocol_encoder_secplus_v1_get_upload(SubGhzProtocolEncoderSecPlus_v1* instance) {
  98. furi_assert(instance);
  99. size_t index = 0;
  100. size_t size_upload = (instance->generic.data_count_bit * 2);
  101. if(size_upload > instance->encoder.size_upload) {
  102. FURI_LOG_E(TAG, "Encoder size upload exceeds allocated encoder buffer.");
  103. return false;
  104. } else {
  105. instance->encoder.size_upload = size_upload;
  106. }
  107. //Send header packet 1
  108. instance->encoder.upload[index++] = level_duration_make(
  109. false, (uint32_t)subghz_protocol_secplus_v1_const.te_short * (116 + 3));
  110. instance->encoder.upload[index++] =
  111. level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short);
  112. //Send data packet 1
  113. for(uint8_t i = SECPLUS_V1_PACKET_1_INDEX_BASE + 1; i < SECPLUS_V1_PACKET_1_INDEX_BASE + 21;
  114. i++) {
  115. switch(instance->data_array[i]) {
  116. case SECPLUS_V1_BIT_0:
  117. instance->encoder.upload[index++] = level_duration_make(
  118. false, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 3);
  119. instance->encoder.upload[index++] =
  120. level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short);
  121. break;
  122. case SECPLUS_V1_BIT_1:
  123. instance->encoder.upload[index++] = level_duration_make(
  124. false, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 2);
  125. instance->encoder.upload[index++] =
  126. level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 2);
  127. break;
  128. case SECPLUS_V1_BIT_2:
  129. instance->encoder.upload[index++] =
  130. level_duration_make(false, (uint32_t)subghz_protocol_secplus_v1_const.te_short);
  131. instance->encoder.upload[index++] =
  132. level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 3);
  133. break;
  134. default:
  135. FURI_LOG_E(TAG, "Encoder error, wrong bit type");
  136. return false;
  137. break;
  138. }
  139. }
  140. //Send header packet 2
  141. instance->encoder.upload[index++] =
  142. level_duration_make(false, (uint32_t)subghz_protocol_secplus_v1_const.te_short * (116));
  143. instance->encoder.upload[index++] =
  144. level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 3);
  145. //Send data packet 2
  146. for(uint8_t i = SECPLUS_V1_PACKET_2_INDEX_BASE + 1; i < SECPLUS_V1_PACKET_2_INDEX_BASE + 21;
  147. i++) {
  148. switch(instance->data_array[i]) {
  149. case SECPLUS_V1_BIT_0:
  150. instance->encoder.upload[index++] = level_duration_make(
  151. false, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 3);
  152. instance->encoder.upload[index++] =
  153. level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short);
  154. break;
  155. case SECPLUS_V1_BIT_1:
  156. instance->encoder.upload[index++] = level_duration_make(
  157. false, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 2);
  158. instance->encoder.upload[index++] =
  159. level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 2);
  160. break;
  161. case SECPLUS_V1_BIT_2:
  162. instance->encoder.upload[index++] =
  163. level_duration_make(false, (uint32_t)subghz_protocol_secplus_v1_const.te_short);
  164. instance->encoder.upload[index++] =
  165. level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 3);
  166. break;
  167. default:
  168. FURI_LOG_E(TAG, "Encoder error, wrong bit type.");
  169. return false;
  170. break;
  171. }
  172. }
  173. return true;
  174. }
  175. /**
  176. * Security+ 1.0 message encoding
  177. * @param instance SubGhzProtocolEncoderSecPlus_v1*
  178. */
  179. static bool subghz_protocol_secplus_v1_encode(SubGhzProtocolEncoderSecPlus_v1* instance) {
  180. uint32_t fixed = (instance->generic.data >> 32) & 0xFFFFFFFF;
  181. uint32_t rolling = instance->generic.data & 0xFFFFFFFF;
  182. uint8_t rolling_array[20] = {0};
  183. uint8_t fixed_array[20] = {0};
  184. uint32_t acc = 0;
  185. //increment the counter
  186. rolling += 2;
  187. //update data
  188. instance->generic.data &= 0xFFFFFFFF00000000;
  189. instance->generic.data |= rolling;
  190. if(rolling > 0xFFFFFFFF) {
  191. rolling = 0xE6000000;
  192. }
  193. if(fixed > 0xCFD41B90) {
  194. FURI_LOG_E("TAG", "Encode wrong fixed data");
  195. return false;
  196. }
  197. rolling = subghz_protocol_blocks_reverse_key(rolling, 32);
  198. for(int i = 19; i > -1; i--) {
  199. rolling_array[i] = rolling % 3;
  200. rolling /= 3;
  201. fixed_array[i] = fixed % 3;
  202. fixed /= 3;
  203. }
  204. instance->data_array[SECPLUS_V1_PACKET_1_INDEX_BASE] = SECPLUS_V1_PACKET_1_HEADER;
  205. instance->data_array[SECPLUS_V1_PACKET_2_INDEX_BASE] = SECPLUS_V1_PACKET_2_HEADER;
  206. //encode packet 1
  207. for(uint8_t i = 1; i < 11; i++) {
  208. acc += rolling_array[i - 1];
  209. instance->data_array[i * 2 - 1] = rolling_array[i - 1];
  210. acc += fixed_array[i - 1];
  211. instance->data_array[i * 2] = acc % 3;
  212. }
  213. acc = 0;
  214. //encode packet 2
  215. for(uint8_t i = 11; i < 21; i++) {
  216. acc += rolling_array[i - 1];
  217. instance->data_array[i * 2] = rolling_array[i - 1];
  218. acc += fixed_array[i - 1];
  219. instance->data_array[i * 2 + 1] = acc % 3;
  220. }
  221. return true;
  222. }
  223. bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) {
  224. furi_assert(context);
  225. SubGhzProtocolEncoderSecPlus_v1* instance = context;
  226. bool res = false;
  227. do {
  228. if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
  229. FURI_LOG_E(TAG, "Deserialize error");
  230. break;
  231. }
  232. if(instance->generic.data_count_bit !=
  233. 2 * subghz_protocol_secplus_v1_const.min_count_bit_for_found) {
  234. FURI_LOG_E(TAG, "Wrong number of bits in key");
  235. break;
  236. }
  237. //optional parameter parameter
  238. flipper_format_read_uint32(
  239. flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
  240. if(!subghz_protocol_secplus_v1_encode(instance)) {
  241. break;
  242. }
  243. if(!subghz_protocol_encoder_secplus_v1_get_upload(instance)) {
  244. break;
  245. }
  246. uint8_t key_data[sizeof(uint64_t)] = {0};
  247. for(size_t i = 0; i < sizeof(uint64_t); i++) {
  248. key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF;
  249. }
  250. if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) {
  251. FURI_LOG_E(TAG, "Unable to add Key");
  252. break;
  253. }
  254. instance->encoder.is_running = true;
  255. res = true;
  256. } while(false);
  257. return res;
  258. }
  259. void subghz_protocol_encoder_secplus_v1_stop(void* context) {
  260. SubGhzProtocolEncoderSecPlus_v1* instance = context;
  261. instance->encoder.is_running = false;
  262. }
  263. LevelDuration subghz_protocol_encoder_secplus_v1_yield(void* context) {
  264. SubGhzProtocolEncoderSecPlus_v1* instance = context;
  265. if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
  266. instance->encoder.is_running = false;
  267. return level_duration_reset();
  268. }
  269. LevelDuration ret = instance->encoder.upload[instance->encoder.front];
  270. if(++instance->encoder.front == instance->encoder.size_upload) {
  271. instance->encoder.repeat--;
  272. instance->encoder.front = 0;
  273. }
  274. return ret;
  275. }
  276. void* subghz_protocol_decoder_secplus_v1_alloc(SubGhzEnvironment* environment) {
  277. UNUSED(environment);
  278. SubGhzProtocolDecoderSecPlus_v1* instance = malloc(sizeof(SubGhzProtocolDecoderSecPlus_v1));
  279. instance->base.protocol = &subghz_protocol_secplus_v1;
  280. instance->generic.protocol_name = instance->base.protocol->name;
  281. return instance;
  282. }
  283. void subghz_protocol_decoder_secplus_v1_free(void* context) {
  284. furi_assert(context);
  285. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  286. free(instance);
  287. }
  288. void subghz_protocol_decoder_secplus_v1_reset(void* context) {
  289. furi_assert(context);
  290. // SubGhzProtocolDecoderSecPlus_v1* instance = context;
  291. // does not reset the decoder because you need to get 2 parts of the package
  292. }
  293. /**
  294. * Security+ 1.0 message decoding
  295. * @param instance SubGhzProtocolDecoderSecPlus_v1*
  296. */
  297. static void subghz_protocol_secplus_v1_decode(SubGhzProtocolDecoderSecPlus_v1* instance) {
  298. uint32_t rolling = 0;
  299. uint32_t fixed = 0;
  300. uint32_t acc = 0;
  301. uint8_t digit = 0;
  302. //decode packet 1
  303. for(uint8_t i = 1; i < 21; i += 2) {
  304. digit = instance->data_array[i];
  305. rolling = (rolling * 3) + digit;
  306. acc += digit;
  307. digit = (60 + instance->data_array[i + 1] - acc) % 3;
  308. fixed = (fixed * 3) + digit;
  309. acc += digit;
  310. }
  311. acc = 0;
  312. //decode packet 2
  313. for(uint8_t i = 22; i < 42; i += 2) {
  314. digit = instance->data_array[i];
  315. rolling = (rolling * 3) + digit;
  316. acc += digit;
  317. digit = (60 + instance->data_array[i + 1] - acc) % 3;
  318. fixed = (fixed * 3) + digit;
  319. acc += digit;
  320. }
  321. rolling = subghz_protocol_blocks_reverse_key(rolling, 32);
  322. instance->generic.data = (uint64_t)fixed << 32 | rolling;
  323. instance->generic.data_count_bit =
  324. subghz_protocol_secplus_v1_const.min_count_bit_for_found * 2;
  325. }
  326. void subghz_protocol_decoder_secplus_v1_feed(void* context, bool level, uint32_t duration) {
  327. furi_assert(context);
  328. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  329. switch(instance->decoder.parser_step) {
  330. case SecPlus_v1DecoderStepReset:
  331. if((!level) && (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 120) <
  332. subghz_protocol_secplus_v1_const.te_delta * 120)) {
  333. //Found header Security+ 1.0
  334. instance->decoder.parser_step = SecPlus_v1DecoderStepSearchStartBit;
  335. instance->decoder.decode_data = 0;
  336. instance->decoder.decode_count_bit = 0;
  337. instance->packet_accepted = 0;
  338. memset(instance->data_array, 0, sizeof(instance->data_array));
  339. }
  340. break;
  341. case SecPlus_v1DecoderStepSearchStartBit:
  342. if(level) {
  343. if(DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short) <
  344. subghz_protocol_secplus_v1_const.te_delta) {
  345. instance->base_packet_index = SECPLUS_V1_PACKET_1_INDEX_BASE;
  346. instance
  347. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  348. SECPLUS_V1_BIT_0;
  349. instance->decoder.decode_count_bit++;
  350. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  351. } else if(
  352. DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_long) <
  353. subghz_protocol_secplus_v1_const.te_delta) {
  354. instance->base_packet_index = SECPLUS_V1_PACKET_2_INDEX_BASE;
  355. instance
  356. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  357. SECPLUS_V1_BIT_2;
  358. instance->decoder.decode_count_bit++;
  359. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  360. } else {
  361. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  362. }
  363. } else {
  364. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  365. }
  366. break;
  367. case SecPlus_v1DecoderStepSaveDuration:
  368. if(!level) { //save interval
  369. if(DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 120) <
  370. subghz_protocol_secplus_v1_const.te_delta * 120) {
  371. if(instance->decoder.decode_count_bit ==
  372. subghz_protocol_secplus_v1_const.min_count_bit_for_found) {
  373. if(instance->base_packet_index == SECPLUS_V1_PACKET_1_INDEX_BASE)
  374. instance->packet_accepted |= SECPLUS_V1_PACKET_1_ACCEPTED;
  375. if(instance->base_packet_index == SECPLUS_V1_PACKET_2_INDEX_BASE)
  376. instance->packet_accepted |= SECPLUS_V1_PACKET_2_ACCEPTED;
  377. if(instance->packet_accepted ==
  378. (SECPLUS_V1_PACKET_1_ACCEPTED | SECPLUS_V1_PACKET_2_ACCEPTED)) {
  379. subghz_protocol_secplus_v1_decode(instance);
  380. if(instance->base.callback)
  381. instance->base.callback(&instance->base, instance->base.context);
  382. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  383. }
  384. }
  385. instance->decoder.parser_step = SecPlus_v1DecoderStepSearchStartBit;
  386. instance->decoder.decode_data = 0;
  387. instance->decoder.decode_count_bit = 0;
  388. } else {
  389. instance->decoder.te_last = duration;
  390. instance->decoder.parser_step = SecPlus_v1DecoderStepDecoderData;
  391. }
  392. } else {
  393. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  394. }
  395. break;
  396. case SecPlus_v1DecoderStepDecoderData:
  397. if(level && (instance->decoder.decode_count_bit <=
  398. subghz_protocol_secplus_v1_const.min_count_bit_for_found)) {
  399. if((DURATION_DIFF(
  400. instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short * 3) <
  401. subghz_protocol_secplus_v1_const.te_delta * 3) &&
  402. (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short) <
  403. subghz_protocol_secplus_v1_const.te_delta)) {
  404. instance
  405. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  406. SECPLUS_V1_BIT_0;
  407. instance->decoder.decode_count_bit++;
  408. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  409. } else if(
  410. (DURATION_DIFF(
  411. instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short * 2) <
  412. subghz_protocol_secplus_v1_const.te_delta * 2) &&
  413. (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 2) <
  414. subghz_protocol_secplus_v1_const.te_delta * 2)) {
  415. instance
  416. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  417. SECPLUS_V1_BIT_1;
  418. instance->decoder.decode_count_bit++;
  419. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  420. } else if(
  421. (DURATION_DIFF(
  422. instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short) <
  423. subghz_protocol_secplus_v1_const.te_delta) &&
  424. (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 3) <
  425. subghz_protocol_secplus_v1_const.te_delta * 3)) {
  426. instance
  427. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  428. SECPLUS_V1_BIT_2;
  429. instance->decoder.decode_count_bit++;
  430. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  431. } else {
  432. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  433. }
  434. } else {
  435. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  436. }
  437. break;
  438. }
  439. }
  440. uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context) {
  441. furi_assert(context);
  442. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  443. return subghz_protocol_blocks_get_hash_data(
  444. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  445. }
  446. bool subghz_protocol_decoder_secplus_v1_serialize(
  447. void* context,
  448. FlipperFormat* flipper_format,
  449. SubGhzPresetDefinition* preset) {
  450. furi_assert(context);
  451. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  452. return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
  453. }
  454. bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) {
  455. furi_assert(context);
  456. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  457. bool ret = false;
  458. do {
  459. if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
  460. break;
  461. }
  462. if(instance->generic.data_count_bit !=
  463. 2 * subghz_protocol_secplus_v1_const.min_count_bit_for_found) {
  464. FURI_LOG_E(TAG, "Wrong number of bits in key");
  465. break;
  466. }
  467. ret = true;
  468. } while(false);
  469. return ret;
  470. }
  471. bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed) {
  472. //uint8_t id0 = (fixed / 3) % 3;
  473. uint8_t id1 = (fixed / 9) % 3;
  474. uint8_t btn = fixed % 3;
  475. do {
  476. if(id1 == 0) return false;
  477. if(!(btn == 0 || btn == 1 || btn == 2)) return false;
  478. } while(false);
  479. return true;
  480. }
  481. void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t output) {
  482. furi_assert(context);
  483. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  484. uint32_t fixed = (instance->generic.data >> 32) & 0xFFFFFFFF;
  485. instance->generic.cnt = instance->generic.data & 0xFFFFFFFF;
  486. instance->generic.btn = fixed % 3;
  487. uint8_t id0 = (fixed / 3) % 3;
  488. uint8_t id1 = (fixed / 9) % 3;
  489. uint16_t pin = 0;
  490. string_cat_printf(
  491. output,
  492. "%s %db\r\n"
  493. "Key:0x%lX%08lX\r\n"
  494. "id1:%d id0:%d",
  495. instance->generic.protocol_name,
  496. instance->generic.data_count_bit,
  497. (uint32_t)(instance->generic.data >> 32),
  498. (uint32_t)instance->generic.data,
  499. id1,
  500. id0);
  501. if(id1 == 0) {
  502. // (fixed // 3**3) % (3**7) 3^3=27 3^73=72187
  503. instance->generic.serial = (fixed / 27) % 2187;
  504. // pin = (fixed // 3**10) % (3**9) 3^10=59049 3^9=19683
  505. pin = (fixed / 59049) % 19683;
  506. if(pin <= 9999) {
  507. string_cat_printf(output, " pin:%d", pin);
  508. } else if(10000 <= pin && pin <= 11029) {
  509. string_cat_printf(output, " pin:enter");
  510. }
  511. int pin_suffix = 0;
  512. // pin_suffix = (fixed // 3**19) % 3 3^19=1162261467
  513. pin_suffix = (fixed / 1162261467) % 3;
  514. if(pin_suffix == 1) {
  515. string_cat_printf(output, " #\r\n");
  516. } else if(pin_suffix == 2) {
  517. string_cat_printf(output, " *\r\n");
  518. } else {
  519. string_cat_printf(output, "\r\n");
  520. }
  521. string_cat_printf(
  522. output,
  523. "Sn:0x%08lX\r\n"
  524. "Cnt:0x%03X\r\n"
  525. "Sw_id:0x%X\r\n",
  526. instance->generic.serial,
  527. instance->generic.cnt,
  528. instance->generic.btn);
  529. } else {
  530. //id = fixed / 27;
  531. instance->generic.serial = fixed / 27;
  532. if(instance->generic.btn == 1) {
  533. string_cat_printf(output, " Btn:left\r\n");
  534. } else if(instance->generic.btn == 0) {
  535. string_cat_printf(output, " Btn:middle\r\n");
  536. } else if(instance->generic.btn == 2) {
  537. string_cat_printf(output, " Btn:right\r\n");
  538. }
  539. string_cat_printf(
  540. output,
  541. "Sn:0x%08lX\r\n"
  542. "Cnt:0x%03X\r\n"
  543. "Sw_id:0x%X\r\n",
  544. instance->generic.serial,
  545. instance->generic.cnt,
  546. instance->generic.btn);
  547. }
  548. }