secplus_v1.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  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_runing = 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. //optional parameter parameter
  233. flipper_format_read_uint32(
  234. flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
  235. if(!subghz_protocol_secplus_v1_encode(instance)) {
  236. break;
  237. }
  238. if(!subghz_protocol_encoder_secplus_v1_get_upload(instance)) {
  239. break;
  240. }
  241. uint8_t key_data[sizeof(uint64_t)] = {0};
  242. for(size_t i = 0; i < sizeof(uint64_t); i++) {
  243. key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF;
  244. }
  245. if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) {
  246. FURI_LOG_E(TAG, "Unable to add Key");
  247. break;
  248. }
  249. instance->encoder.is_runing = true;
  250. res = true;
  251. } while(false);
  252. return res;
  253. }
  254. void subghz_protocol_encoder_secplus_v1_stop(void* context) {
  255. SubGhzProtocolEncoderSecPlus_v1* instance = context;
  256. instance->encoder.is_runing = false;
  257. }
  258. LevelDuration subghz_protocol_encoder_secplus_v1_yield(void* context) {
  259. SubGhzProtocolEncoderSecPlus_v1* instance = context;
  260. if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) {
  261. instance->encoder.is_runing = false;
  262. return level_duration_reset();
  263. }
  264. LevelDuration ret = instance->encoder.upload[instance->encoder.front];
  265. if(++instance->encoder.front == instance->encoder.size_upload) {
  266. instance->encoder.repeat--;
  267. instance->encoder.front = 0;
  268. }
  269. return ret;
  270. }
  271. void* subghz_protocol_decoder_secplus_v1_alloc(SubGhzEnvironment* environment) {
  272. UNUSED(environment);
  273. SubGhzProtocolDecoderSecPlus_v1* instance = malloc(sizeof(SubGhzProtocolDecoderSecPlus_v1));
  274. instance->base.protocol = &subghz_protocol_secplus_v1;
  275. instance->generic.protocol_name = instance->base.protocol->name;
  276. return instance;
  277. }
  278. void subghz_protocol_decoder_secplus_v1_free(void* context) {
  279. furi_assert(context);
  280. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  281. free(instance);
  282. }
  283. void subghz_protocol_decoder_secplus_v1_reset(void* context) {
  284. furi_assert(context);
  285. // SubGhzProtocolDecoderSecPlus_v1* instance = context;
  286. // does not reset the decoder because you need to get 2 parts of the package
  287. }
  288. /**
  289. * Security+ 1.0 message decoding
  290. * @param instance SubGhzProtocolDecoderSecPlus_v1*
  291. */
  292. static void subghz_protocol_secplus_v1_decode(SubGhzProtocolDecoderSecPlus_v1* instance) {
  293. uint32_t rolling = 0;
  294. uint32_t fixed = 0;
  295. uint32_t acc = 0;
  296. uint8_t digit = 0;
  297. //decode packet 1
  298. for(uint8_t i = 1; i < 21; i += 2) {
  299. digit = instance->data_array[i];
  300. rolling = (rolling * 3) + digit;
  301. acc += digit;
  302. digit = (60 + instance->data_array[i + 1] - acc) % 3;
  303. fixed = (fixed * 3) + digit;
  304. acc += digit;
  305. }
  306. acc = 0;
  307. //decode packet 2
  308. for(uint8_t i = 22; i < 42; i += 2) {
  309. digit = instance->data_array[i];
  310. rolling = (rolling * 3) + digit;
  311. acc += digit;
  312. digit = (60 + instance->data_array[i + 1] - acc) % 3;
  313. fixed = (fixed * 3) + digit;
  314. acc += digit;
  315. }
  316. rolling = subghz_protocol_blocks_reverse_key(rolling, 32);
  317. instance->generic.data = (uint64_t)fixed << 32 | rolling;
  318. instance->generic.data_count_bit =
  319. subghz_protocol_secplus_v1_const.min_count_bit_for_found * 2;
  320. }
  321. void subghz_protocol_decoder_secplus_v1_feed(void* context, bool level, uint32_t duration) {
  322. furi_assert(context);
  323. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  324. switch(instance->decoder.parser_step) {
  325. case SecPlus_v1DecoderStepReset:
  326. if((!level) && (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 120) <
  327. subghz_protocol_secplus_v1_const.te_delta * 120)) {
  328. //Found header Security+ 1.0
  329. instance->decoder.parser_step = SecPlus_v1DecoderStepSearchStartBit;
  330. instance->decoder.decode_data = 0;
  331. instance->decoder.decode_count_bit = 0;
  332. instance->packet_accepted = 0;
  333. memset(instance->data_array, 0, sizeof(instance->data_array));
  334. }
  335. break;
  336. case SecPlus_v1DecoderStepSearchStartBit:
  337. if(level) {
  338. if(DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short) <
  339. subghz_protocol_secplus_v1_const.te_delta) {
  340. instance->base_packet_index = SECPLUS_V1_PACKET_1_INDEX_BASE;
  341. instance
  342. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  343. SECPLUS_V1_BIT_0;
  344. instance->decoder.decode_count_bit++;
  345. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  346. } else if(
  347. DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_long) <
  348. subghz_protocol_secplus_v1_const.te_delta) {
  349. instance->base_packet_index = SECPLUS_V1_PACKET_2_INDEX_BASE;
  350. instance
  351. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  352. SECPLUS_V1_BIT_2;
  353. instance->decoder.decode_count_bit++;
  354. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  355. } else {
  356. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  357. }
  358. } else {
  359. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  360. }
  361. break;
  362. case SecPlus_v1DecoderStepSaveDuration:
  363. if(!level) { //save interval
  364. if(DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 120) <
  365. subghz_protocol_secplus_v1_const.te_delta * 120) {
  366. if(instance->decoder.decode_count_bit ==
  367. subghz_protocol_secplus_v1_const.min_count_bit_for_found) {
  368. if(instance->base_packet_index == SECPLUS_V1_PACKET_1_INDEX_BASE)
  369. instance->packet_accepted |= SECPLUS_V1_PACKET_1_ACCEPTED;
  370. if(instance->base_packet_index == SECPLUS_V1_PACKET_2_INDEX_BASE)
  371. instance->packet_accepted |= SECPLUS_V1_PACKET_2_ACCEPTED;
  372. if(instance->packet_accepted ==
  373. (SECPLUS_V1_PACKET_1_ACCEPTED | SECPLUS_V1_PACKET_2_ACCEPTED)) {
  374. subghz_protocol_secplus_v1_decode(instance);
  375. if(instance->base.callback)
  376. instance->base.callback(&instance->base, instance->base.context);
  377. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  378. }
  379. }
  380. instance->decoder.parser_step = SecPlus_v1DecoderStepSearchStartBit;
  381. instance->decoder.decode_data = 0;
  382. instance->decoder.decode_count_bit = 0;
  383. } else {
  384. instance->decoder.te_last = duration;
  385. instance->decoder.parser_step = SecPlus_v1DecoderStepDecoderData;
  386. }
  387. } else {
  388. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  389. }
  390. break;
  391. case SecPlus_v1DecoderStepDecoderData:
  392. if(level && (instance->decoder.decode_count_bit <=
  393. subghz_protocol_secplus_v1_const.min_count_bit_for_found)) {
  394. if((DURATION_DIFF(
  395. instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short * 3) <
  396. subghz_protocol_secplus_v1_const.te_delta * 3) &&
  397. (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short) <
  398. subghz_protocol_secplus_v1_const.te_delta)) {
  399. instance
  400. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  401. SECPLUS_V1_BIT_0;
  402. instance->decoder.decode_count_bit++;
  403. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  404. } else if(
  405. (DURATION_DIFF(
  406. instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short * 2) <
  407. subghz_protocol_secplus_v1_const.te_delta * 2) &&
  408. (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 2) <
  409. subghz_protocol_secplus_v1_const.te_delta * 2)) {
  410. instance
  411. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  412. SECPLUS_V1_BIT_1;
  413. instance->decoder.decode_count_bit++;
  414. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  415. } else if(
  416. (DURATION_DIFF(
  417. instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short) <
  418. subghz_protocol_secplus_v1_const.te_delta) &&
  419. (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 3) <
  420. subghz_protocol_secplus_v1_const.te_delta * 3)) {
  421. instance
  422. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  423. SECPLUS_V1_BIT_2;
  424. instance->decoder.decode_count_bit++;
  425. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  426. } else {
  427. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  428. }
  429. } else {
  430. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  431. }
  432. break;
  433. }
  434. }
  435. uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context) {
  436. furi_assert(context);
  437. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  438. return subghz_protocol_blocks_get_hash_data(
  439. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  440. }
  441. bool subghz_protocol_decoder_secplus_v1_serialize(
  442. void* context,
  443. FlipperFormat* flipper_format,
  444. uint32_t frequency,
  445. FuriHalSubGhzPreset preset) {
  446. furi_assert(context);
  447. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  448. return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
  449. }
  450. bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) {
  451. furi_assert(context);
  452. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  453. return subghz_block_generic_deserialize(&instance->generic, flipper_format);
  454. }
  455. bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed) {
  456. //uint8_t id0 = (fixed / 3) % 3;
  457. uint8_t id1 = (fixed / 9) % 3;
  458. uint8_t btn = fixed % 3;
  459. do {
  460. if(id1 == 0) return false;
  461. if(!(btn == 0 || btn == 1 || btn == 2)) return false;
  462. } while(false);
  463. return true;
  464. }
  465. void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t output) {
  466. furi_assert(context);
  467. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  468. uint32_t fixed = (instance->generic.data >> 32) & 0xFFFFFFFF;
  469. instance->generic.cnt = instance->generic.data & 0xFFFFFFFF;
  470. instance->generic.btn = fixed % 3;
  471. uint8_t id0 = (fixed / 3) % 3;
  472. uint8_t id1 = (fixed / 9) % 3;
  473. uint16_t pin = 0;
  474. string_cat_printf(
  475. output,
  476. "%s %db\r\n"
  477. "Key:0x%lX%08lX\r\n"
  478. "id1:%d id0:%d",
  479. instance->generic.protocol_name,
  480. instance->generic.data_count_bit,
  481. (uint32_t)(instance->generic.data >> 32),
  482. (uint32_t)instance->generic.data,
  483. id1,
  484. id0);
  485. if(id1 == 0) {
  486. // (fixed // 3**3) % (3**7) 3^3=27 3^73=72187
  487. instance->generic.serial = (fixed / 27) % 2187;
  488. // pin = (fixed // 3**10) % (3**9) 3^10=59049 3^9=19683
  489. pin = (fixed / 59049) % 19683;
  490. if(pin <= 9999) {
  491. string_cat_printf(output, " pin:%d", pin);
  492. } else if(10000 <= pin && pin <= 11029) {
  493. string_cat_printf(output, " pin:enter");
  494. }
  495. int pin_suffix = 0;
  496. // pin_suffix = (fixed // 3**19) % 3 3^19=1162261467
  497. pin_suffix = (fixed / 1162261467) % 3;
  498. if(pin_suffix == 1) {
  499. string_cat_printf(output, " #\r\n");
  500. } else if(pin_suffix == 2) {
  501. string_cat_printf(output, " *\r\n");
  502. } else {
  503. string_cat_printf(output, "\r\n");
  504. }
  505. string_cat_printf(
  506. output,
  507. "Sn:0x%08lX\r\n"
  508. "Cnt:0x%03X\r\n"
  509. "Sw_id:0x%X\r\n",
  510. instance->generic.serial,
  511. instance->generic.cnt,
  512. instance->generic.btn);
  513. } else {
  514. //id = fixed / 27;
  515. instance->generic.serial = fixed / 27;
  516. if(instance->generic.btn == 1) {
  517. string_cat_printf(output, " Btn:left\r\n");
  518. } else if(instance->generic.btn == 0) {
  519. string_cat_printf(output, " Btn:middle\r\n");
  520. } else if(instance->generic.btn == 2) {
  521. string_cat_printf(output, " Btn:right\r\n");
  522. }
  523. string_cat_printf(
  524. output,
  525. "Sn:0x%08lX\r\n"
  526. "Cnt:0x%03X\r\n"
  527. "Sw_id:0x%X\r\n",
  528. instance->generic.serial,
  529. instance->generic.cnt,
  530. instance->generic.btn);
  531. }
  532. }