secplus_v1.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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. };
  42. typedef enum {
  43. SecPlus_v1DecoderStepReset = 0,
  44. SecPlus_v1DecoderStepSearchStartBit,
  45. SecPlus_v1DecoderStepSaveDuration,
  46. SecPlus_v1DecoderStepDecoderData,
  47. } SecPlus_v1DecoderStep;
  48. const SubGhzProtocolDecoder subghz_protocol_secplus_v1_decoder = {
  49. .alloc = subghz_protocol_decoder_secplus_v1_alloc,
  50. .free = subghz_protocol_decoder_secplus_v1_free,
  51. .feed = subghz_protocol_decoder_secplus_v1_feed,
  52. .reset = subghz_protocol_decoder_secplus_v1_reset,
  53. .get_hash_data = subghz_protocol_decoder_secplus_v1_get_hash_data,
  54. .serialize = subghz_protocol_decoder_secplus_v1_serialize,
  55. .deserialize = subghz_protocol_decoder_secplus_v1_deserialize,
  56. .get_string = subghz_protocol_decoder_secplus_v1_get_string,
  57. };
  58. const SubGhzProtocolEncoder subghz_protocol_secplus_v1_encoder = {
  59. .alloc = NULL,
  60. .free = NULL,
  61. .deserialize = NULL,
  62. .stop = NULL,
  63. .yield = NULL,
  64. };
  65. const SubGhzProtocol subghz_protocol_secplus_v1 = {
  66. .name = SUBGHZ_PROTOCOL_SECPLUS_V1_NAME,
  67. .type = SubGhzProtocolTypeDynamic,
  68. .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
  69. .decoder = &subghz_protocol_secplus_v1_decoder,
  70. .encoder = &subghz_protocol_secplus_v1_encoder,
  71. };
  72. void* subghz_protocol_decoder_secplus_v1_alloc(SubGhzEnvironment* environment) {
  73. SubGhzProtocolDecoderSecPlus_v1* instance = malloc(sizeof(SubGhzProtocolDecoderSecPlus_v1));
  74. instance->base.protocol = &subghz_protocol_secplus_v1;
  75. instance->generic.protocol_name = instance->base.protocol->name;
  76. return instance;
  77. }
  78. void subghz_protocol_decoder_secplus_v1_free(void* context) {
  79. furi_assert(context);
  80. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  81. free(instance);
  82. }
  83. void subghz_protocol_decoder_secplus_v1_reset(void* context) {
  84. furi_assert(context);
  85. // SubGhzProtocolDecoderSecPlus_v1* instance = context;
  86. // does not reset the decoder because you need to get 2 parts of the package
  87. }
  88. /**
  89. * Security+ 1.0 half-message decoding
  90. * @param instance SubGhzProtocolDecoderSecPlus_v1*
  91. */
  92. static void subghz_protocol_secplus_v1_decode(SubGhzProtocolDecoderSecPlus_v1* instance) {
  93. uint32_t rolling = 0;
  94. uint32_t fixed = 0;
  95. uint32_t acc = 0;
  96. uint8_t digit = 0;
  97. //decode packet 1
  98. for(uint8_t i = 1; i < 21; i += 2) {
  99. digit = instance->data_array[i];
  100. rolling = (rolling * 3) + digit;
  101. acc += digit;
  102. digit = (60 + instance->data_array[i + 1] - acc) % 3;
  103. fixed = (fixed * 3) + digit;
  104. acc += digit;
  105. }
  106. acc = 0;
  107. //decode packet 2
  108. for(uint8_t i = 22; i < 42; i += 2) {
  109. digit = instance->data_array[i];
  110. rolling = (rolling * 3) + digit;
  111. acc += digit;
  112. digit = (60 + instance->data_array[i + 1] - acc) % 3;
  113. fixed = (fixed * 3) + digit;
  114. acc += digit;
  115. }
  116. rolling = subghz_protocol_blocks_reverse_key(rolling, 32);
  117. instance->generic.data = (uint64_t)fixed << 32 | rolling;
  118. instance->generic.data_count_bit =
  119. subghz_protocol_secplus_v1_const.min_count_bit_for_found * 2;
  120. }
  121. void subghz_protocol_decoder_secplus_v1_feed(void* context, bool level, uint32_t duration) {
  122. furi_assert(context);
  123. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  124. switch(instance->decoder.parser_step) {
  125. case SecPlus_v1DecoderStepReset:
  126. if((!level) && (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 120) <
  127. subghz_protocol_secplus_v1_const.te_delta * 120)) {
  128. //Found header Security+ 1.0
  129. instance->decoder.parser_step = SecPlus_v1DecoderStepSearchStartBit;
  130. instance->decoder.decode_data = 0;
  131. instance->decoder.decode_count_bit = 0;
  132. instance->packet_accepted = 0;
  133. memset(instance->data_array, 0, sizeof(instance->data_array));
  134. }
  135. break;
  136. case SecPlus_v1DecoderStepSearchStartBit:
  137. if(level) {
  138. if(DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short) <
  139. subghz_protocol_secplus_v1_const.te_delta) {
  140. instance->base_packet_index = SECPLUS_V1_PACKET_1_INDEX_BASE;
  141. instance
  142. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  143. SECPLUS_V1_BIT_0;
  144. instance->decoder.decode_count_bit++;
  145. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  146. } else if(
  147. DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_long) <
  148. subghz_protocol_secplus_v1_const.te_delta) {
  149. instance->base_packet_index = SECPLUS_V1_PACKET_2_INDEX_BASE;
  150. instance
  151. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  152. SECPLUS_V1_BIT_2;
  153. instance->decoder.decode_count_bit++;
  154. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  155. } else {
  156. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  157. }
  158. } else {
  159. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  160. }
  161. break;
  162. case SecPlus_v1DecoderStepSaveDuration:
  163. if(!level) { //save interval
  164. if(DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 120) <
  165. subghz_protocol_secplus_v1_const.te_delta * 120) {
  166. if(instance->decoder.decode_count_bit ==
  167. subghz_protocol_secplus_v1_const.min_count_bit_for_found) {
  168. if(instance->base_packet_index == SECPLUS_V1_PACKET_1_INDEX_BASE)
  169. instance->packet_accepted |= SECPLUS_V1_PACKET_1_ACCEPTED;
  170. if(instance->base_packet_index == SECPLUS_V1_PACKET_2_INDEX_BASE)
  171. instance->packet_accepted |= SECPLUS_V1_PACKET_2_ACCEPTED;
  172. if(instance->packet_accepted ==
  173. (SECPLUS_V1_PACKET_1_ACCEPTED | SECPLUS_V1_PACKET_2_ACCEPTED)) {
  174. subghz_protocol_secplus_v1_decode(instance);
  175. if(instance->base.callback)
  176. instance->base.callback(&instance->base, instance->base.context);
  177. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  178. }
  179. }
  180. instance->decoder.parser_step = SecPlus_v1DecoderStepSearchStartBit;
  181. instance->decoder.decode_data = 0;
  182. instance->decoder.decode_count_bit = 0;
  183. } else {
  184. instance->decoder.te_last = duration;
  185. instance->decoder.parser_step = SecPlus_v1DecoderStepDecoderData;
  186. }
  187. } else {
  188. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  189. }
  190. break;
  191. case SecPlus_v1DecoderStepDecoderData:
  192. if(level && (instance->decoder.decode_count_bit <=
  193. subghz_protocol_secplus_v1_const.min_count_bit_for_found)) {
  194. if((DURATION_DIFF(
  195. instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short * 3) <
  196. subghz_protocol_secplus_v1_const.te_delta * 3) &&
  197. (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short) <
  198. subghz_protocol_secplus_v1_const.te_delta)) {
  199. instance
  200. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  201. SECPLUS_V1_BIT_0;
  202. instance->decoder.decode_count_bit++;
  203. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  204. } else if(
  205. (DURATION_DIFF(
  206. instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short * 2) <
  207. subghz_protocol_secplus_v1_const.te_delta * 2) &&
  208. (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 2) <
  209. subghz_protocol_secplus_v1_const.te_delta * 2)) {
  210. instance
  211. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  212. SECPLUS_V1_BIT_1;
  213. instance->decoder.decode_count_bit++;
  214. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  215. } else if(
  216. (DURATION_DIFF(
  217. instance->decoder.te_last, subghz_protocol_secplus_v1_const.te_short) <
  218. subghz_protocol_secplus_v1_const.te_delta) &&
  219. (DURATION_DIFF(duration, subghz_protocol_secplus_v1_const.te_short * 3) <
  220. subghz_protocol_secplus_v1_const.te_delta * 3)) {
  221. instance
  222. ->data_array[instance->decoder.decode_count_bit + instance->base_packet_index] =
  223. SECPLUS_V1_BIT_2;
  224. instance->decoder.decode_count_bit++;
  225. instance->decoder.parser_step = SecPlus_v1DecoderStepSaveDuration;
  226. } else {
  227. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  228. }
  229. } else {
  230. instance->decoder.parser_step = SecPlus_v1DecoderStepReset;
  231. }
  232. break;
  233. }
  234. }
  235. uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context) {
  236. furi_assert(context);
  237. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  238. return subghz_protocol_blocks_get_hash_data(
  239. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  240. }
  241. bool subghz_protocol_decoder_secplus_v1_serialize(
  242. void* context,
  243. FlipperFormat* flipper_format,
  244. uint32_t frequency,
  245. FuriHalSubGhzPreset preset) {
  246. furi_assert(context);
  247. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  248. return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
  249. }
  250. bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) {
  251. furi_assert(context);
  252. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  253. return subghz_block_generic_deserialize(&instance->generic, flipper_format);
  254. }
  255. void subghz_protocol_decoder_secplus_v1_get_string(void* context, string_t output) {
  256. furi_assert(context);
  257. SubGhzProtocolDecoderSecPlus_v1* instance = context;
  258. uint32_t fixed = (instance->generic.data >> 32) & 0xFFFFFFFF;
  259. instance->generic.cnt = instance->generic.data & 0xFFFFFFFF;
  260. instance->generic.btn = fixed % 3;
  261. uint8_t id0 = (fixed / 3) % 3;
  262. uint8_t id1 = (fixed / 9) % 3;
  263. uint16_t pin = 0;
  264. string_cat_printf(
  265. output,
  266. "%s %db\r\n"
  267. "Key:0x%lX%08lX\r\n"
  268. "id1:%d id0:%d",
  269. instance->generic.protocol_name,
  270. instance->generic.data_count_bit,
  271. (uint32_t)(instance->generic.data >> 32),
  272. (uint32_t)instance->generic.data,
  273. id1,
  274. id0);
  275. if(id1 == 0) {
  276. // (fixed // 3**3) % (3**7) 3^3=27 3^73=72187
  277. instance->generic.serial = (fixed / 27) % 2187;
  278. // pin = (fixed // 3**10) % (3**9) 3^10=59049 3^9=19683
  279. pin = (fixed / 59049) % 19683;
  280. if(0 <= pin && pin <= 9999) {
  281. string_cat_printf(output, " pin:%d", pin);
  282. } else if(10000 <= pin && pin <= 11029) {
  283. string_cat_printf(output, " pin:enter");
  284. }
  285. int pin_suffix = 0;
  286. // pin_suffix = (fixed // 3**19) % 3 3^19=1162261467
  287. pin_suffix = (fixed / 1162261467) % 3;
  288. if(pin_suffix == 1) {
  289. string_cat_printf(output, " #\r\n");
  290. } else if(pin_suffix == 2) {
  291. string_cat_printf(output, " *\r\n");
  292. } else {
  293. string_cat_printf(output, "\r\n");
  294. }
  295. string_cat_printf(
  296. output,
  297. "Sn:0x%08lX\r\n"
  298. "Cnt:0x%03X\r\n"
  299. "Sw_id:0x%X\r\n",
  300. instance->generic.serial,
  301. instance->generic.cnt,
  302. instance->generic.btn);
  303. } else {
  304. //id = fixed / 27;
  305. instance->generic.serial = fixed / 27;
  306. if(instance->generic.btn == 1) {
  307. string_cat_printf(output, " Btn:left\r\n");
  308. } else if(instance->generic.btn == 0) {
  309. string_cat_printf(output, " Btn:middle\r\n");
  310. } else if(instance->generic.btn == 2) {
  311. string_cat_printf(output, " Btn:right\r\n");
  312. }
  313. string_cat_printf(
  314. output,
  315. "Sn:0x%08lX\r\n"
  316. "Cnt:0x%03X\r\n"
  317. "Sw_id:0x%X\r\n",
  318. instance->generic.serial,
  319. instance->generic.cnt,
  320. instance->generic.btn);
  321. }
  322. }