secplus_v1.c 23 KB

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