came_twee.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. #include "came_twee.h"
  2. #include <lib/toolbox/manchester_decoder.h>
  3. #include <lib/toolbox/manchester_encoder.h>
  4. #include "../blocks/const.h"
  5. #include "../blocks/decoder.h"
  6. #include "../blocks/encoder.h"
  7. #include "../blocks/generic.h"
  8. #include "../blocks/math.h"
  9. /*
  10. * Help
  11. * https://phreakerclub.com/forum/showthread.php?t=635&highlight=came+twin
  12. *
  13. */
  14. #define TAG "SubGhzProtocolCAME_Twee"
  15. #define DIP_PATTERN "%c%c%c%c%c%c%c%c%c%c"
  16. #define CNT_TO_DIP(dip) \
  17. (dip & 0x0200 ? '1' : '0'), (dip & 0x0100 ? '1' : '0'), (dip & 0x0080 ? '1' : '0'), \
  18. (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), (dip & 0x0010 ? '1' : '0'), \
  19. (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), \
  20. (dip & 0x0001 ? '1' : '0')
  21. /**
  22. * Rainbow table Came Twee.
  23. */
  24. static const uint32_t came_twee_magic_numbers_xor[15] = {
  25. 0x0E0E0E00,
  26. 0x1D1D1D11,
  27. 0x2C2C2C22,
  28. 0x3B3B3B33,
  29. 0x4A4A4A44,
  30. 0x59595955,
  31. 0x68686866,
  32. 0x77777777,
  33. 0x86868688,
  34. 0x95959599,
  35. 0xA4A4A4AA,
  36. 0xB3B3B3BB,
  37. 0xC2C2C2CC,
  38. 0xD1D1D1DD,
  39. 0xE0E0E0EE,
  40. };
  41. static const SubGhzBlockConst subghz_protocol_came_twee_const = {
  42. .te_short = 500,
  43. .te_long = 1000,
  44. .te_delta = 250,
  45. .min_count_bit_for_found = 54,
  46. };
  47. struct SubGhzProtocolDecoderCameTwee {
  48. SubGhzProtocolDecoderBase base;
  49. SubGhzBlockDecoder decoder;
  50. SubGhzBlockGeneric generic;
  51. ManchesterState manchester_saved_state;
  52. };
  53. struct SubGhzProtocolEncoderCameTwee {
  54. SubGhzProtocolEncoderBase base;
  55. SubGhzProtocolBlockEncoder encoder;
  56. SubGhzBlockGeneric generic;
  57. };
  58. typedef enum {
  59. CameTweeDecoderStepReset = 0,
  60. CameTweeDecoderStepDecoderData,
  61. } CameTweeDecoderStep;
  62. const SubGhzProtocolDecoder subghz_protocol_came_twee_decoder = {
  63. .alloc = subghz_protocol_decoder_came_twee_alloc,
  64. .free = subghz_protocol_decoder_came_twee_free,
  65. .feed = subghz_protocol_decoder_came_twee_feed,
  66. .reset = subghz_protocol_decoder_came_twee_reset,
  67. .get_hash_data = subghz_protocol_decoder_came_twee_get_hash_data,
  68. .serialize = subghz_protocol_decoder_came_twee_serialize,
  69. .deserialize = subghz_protocol_decoder_came_twee_deserialize,
  70. .get_string = subghz_protocol_decoder_came_twee_get_string,
  71. };
  72. const SubGhzProtocolEncoder subghz_protocol_came_twee_encoder = {
  73. .alloc = subghz_protocol_encoder_came_twee_alloc,
  74. .free = subghz_protocol_encoder_came_twee_free,
  75. .deserialize = subghz_protocol_encoder_came_twee_deserialize,
  76. .stop = subghz_protocol_encoder_came_twee_stop,
  77. .yield = subghz_protocol_encoder_came_twee_yield,
  78. };
  79. const SubGhzProtocol subghz_protocol_came_twee = {
  80. .name = SUBGHZ_PROTOCOL_CAME_TWEE_NAME,
  81. .type = SubGhzProtocolTypeStatic,
  82. .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
  83. SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
  84. .decoder = &subghz_protocol_came_twee_decoder,
  85. .encoder = &subghz_protocol_came_twee_encoder,
  86. };
  87. void* subghz_protocol_encoder_came_twee_alloc(SubGhzEnvironment* environment) {
  88. UNUSED(environment);
  89. SubGhzProtocolEncoderCameTwee* instance = malloc(sizeof(SubGhzProtocolEncoderCameTwee));
  90. instance->base.protocol = &subghz_protocol_came_twee;
  91. instance->generic.protocol_name = instance->base.protocol->name;
  92. instance->encoder.repeat = 10;
  93. instance->encoder.size_upload = 1536; //max upload 92*14 = 1288 !!!!
  94. instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
  95. instance->encoder.is_running = false;
  96. return instance;
  97. }
  98. void subghz_protocol_encoder_came_twee_free(void* context) {
  99. furi_assert(context);
  100. SubGhzProtocolEncoderCameTwee* instance = context;
  101. free(instance->encoder.upload);
  102. free(instance);
  103. }
  104. static LevelDuration
  105. subghz_protocol_encoder_came_twee_add_duration_to_upload(ManchesterEncoderResult result) {
  106. LevelDuration data = {.duration = 0, .level = 0};
  107. switch(result) {
  108. case ManchesterEncoderResultShortLow:
  109. data.duration = subghz_protocol_came_twee_const.te_short;
  110. data.level = false;
  111. break;
  112. case ManchesterEncoderResultLongLow:
  113. data.duration = subghz_protocol_came_twee_const.te_long;
  114. data.level = false;
  115. break;
  116. case ManchesterEncoderResultLongHigh:
  117. data.duration = subghz_protocol_came_twee_const.te_long;
  118. data.level = true;
  119. break;
  120. case ManchesterEncoderResultShortHigh:
  121. data.duration = subghz_protocol_came_twee_const.te_short;
  122. data.level = true;
  123. break;
  124. default:
  125. furi_crash("SubGhz: ManchesterEncoderResult is incorrect.");
  126. break;
  127. }
  128. return level_duration_make(data.level, data.duration);
  129. }
  130. /**
  131. * Generating an upload from data.
  132. * @param instance Pointer to a SubGhzProtocolEncoderCameTwee instance
  133. */
  134. static void subghz_protocol_encoder_came_twee_get_upload(SubGhzProtocolEncoderCameTwee* instance) {
  135. furi_assert(instance);
  136. size_t index = 0;
  137. ManchesterEncoderState enc_state;
  138. manchester_encoder_reset(&enc_state);
  139. ManchesterEncoderResult result;
  140. uint64_t temp_parcel = 0x003FFF7200000000; //parcel mask
  141. for(int i = 14; i >= 0; i--) {
  142. temp_parcel = (temp_parcel & 0xFFFFFFFF00000000) |
  143. (instance->generic.serial ^ came_twee_magic_numbers_xor[i]);
  144. for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
  145. if(!manchester_encoder_advance(&enc_state, !bit_read(temp_parcel, i - 1), &result)) {
  146. instance->encoder.upload[index++] =
  147. subghz_protocol_encoder_came_twee_add_duration_to_upload(result);
  148. manchester_encoder_advance(&enc_state, !bit_read(temp_parcel, i - 1), &result);
  149. }
  150. instance->encoder.upload[index++] =
  151. subghz_protocol_encoder_came_twee_add_duration_to_upload(result);
  152. }
  153. instance->encoder.upload[index] = subghz_protocol_encoder_came_twee_add_duration_to_upload(
  154. manchester_encoder_finish(&enc_state));
  155. if(level_duration_get_level(instance->encoder.upload[index])) {
  156. index++;
  157. }
  158. instance->encoder.upload[index++] =
  159. level_duration_make(false, (uint32_t)subghz_protocol_came_twee_const.te_long * 51);
  160. }
  161. instance->encoder.size_upload = index;
  162. }
  163. /**
  164. * Analysis of received data
  165. * @param instance Pointer to a SubGhzBlockGeneric* instance
  166. */
  167. static void subghz_protocol_came_twee_remote_controller(SubGhzBlockGeneric* instance) {
  168. /* Came Twee 54 bit, rolling code 15 parcels with
  169. * a decreasing counter from 0xE to 0x0
  170. * with originally coded dip switches on the console 10 bit code
  171. *
  172. * 0x003FFF72E04A6FEE
  173. * 0x003FFF72D17B5EDD
  174. * 0x003FFF72C2684DCC
  175. * 0x003FFF72B3193CBB
  176. * 0x003FFF72A40E2BAA
  177. * 0x003FFF72953F1A99
  178. * 0x003FFF72862C0988
  179. * 0x003FFF7277DDF877
  180. * 0x003FFF7268C2E766
  181. * 0x003FFF7259F3D655
  182. * 0x003FFF724AE0C544
  183. * 0x003FFF723B91B433
  184. * 0x003FFF722C86A322
  185. * 0x003FFF721DB79211
  186. * 0x003FFF720EA48100
  187. *
  188. * decryption
  189. * the last 32 bits, do XOR by the desired number, divide the result by 4,
  190. * convert the first 16 bits of the resulting 32-bit number to bin and do
  191. * bit-by-bit mirroring, adding up to 10 bits
  192. *
  193. * Example
  194. * Step 1. 0x003FFF721DB79211 => 0x1DB79211
  195. * Step 4. 0x1DB79211 xor 0x1D1D1D11 => 0x00AA8F00
  196. * Step 4. 0x00AA8F00 / 4 => 0x002AA3C0
  197. * Step 5. 0x002AA3C0 => 0x002A
  198. * Step 6. 0x002A bin => b101010
  199. * Step 7. b101010 => b0101010000
  200. * Step 8. b0101010000 => (Dip) Off ON Off ON Off ON Off Off Off Off
  201. */
  202. uint8_t cnt_parcel = (uint8_t)(instance->data & 0xF);
  203. uint32_t data = (uint32_t)(instance->data & 0x0FFFFFFFF);
  204. data = (data ^ came_twee_magic_numbers_xor[cnt_parcel]);
  205. instance->serial = data;
  206. data /= 4;
  207. instance->btn = (data >> 4) & 0x0F;
  208. data >>= 16;
  209. data = (uint16_t)subghz_protocol_blocks_reverse_key(data, 16);
  210. instance->cnt = data >> 6;
  211. }
  212. SubGhzProtocolStatus
  213. subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {
  214. furi_assert(context);
  215. SubGhzProtocolEncoderCameTwee* instance = context;
  216. SubGhzProtocolStatus res = SubGhzProtocolStatusError;
  217. do {
  218. res = subghz_block_generic_deserialize_check_count_bit(
  219. &instance->generic,
  220. flipper_format,
  221. subghz_protocol_came_twee_const.min_count_bit_for_found);
  222. if(res != SubGhzProtocolStatusOk) {
  223. break;
  224. }
  225. //optional parameter parameter
  226. flipper_format_read_uint32(
  227. flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
  228. subghz_protocol_came_twee_remote_controller(&instance->generic);
  229. subghz_protocol_encoder_came_twee_get_upload(instance);
  230. instance->encoder.is_running = true;
  231. } while(false);
  232. return res;
  233. }
  234. void subghz_protocol_encoder_came_twee_stop(void* context) {
  235. SubGhzProtocolEncoderCameTwee* instance = context;
  236. instance->encoder.is_running = false;
  237. }
  238. LevelDuration subghz_protocol_encoder_came_twee_yield(void* context) {
  239. SubGhzProtocolEncoderCameTwee* instance = context;
  240. if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
  241. instance->encoder.is_running = false;
  242. return level_duration_reset();
  243. }
  244. LevelDuration ret = instance->encoder.upload[instance->encoder.front];
  245. if(++instance->encoder.front == instance->encoder.size_upload) {
  246. instance->encoder.repeat--;
  247. instance->encoder.front = 0;
  248. }
  249. return ret;
  250. }
  251. void* subghz_protocol_decoder_came_twee_alloc(SubGhzEnvironment* environment) {
  252. UNUSED(environment);
  253. SubGhzProtocolDecoderCameTwee* instance = malloc(sizeof(SubGhzProtocolDecoderCameTwee));
  254. instance->base.protocol = &subghz_protocol_came_twee;
  255. instance->generic.protocol_name = instance->base.protocol->name;
  256. return instance;
  257. }
  258. void subghz_protocol_decoder_came_twee_free(void* context) {
  259. furi_assert(context);
  260. SubGhzProtocolDecoderCameTwee* instance = context;
  261. free(instance);
  262. }
  263. void subghz_protocol_decoder_came_twee_reset(void* context) {
  264. furi_assert(context);
  265. SubGhzProtocolDecoderCameTwee* instance = context;
  266. instance->decoder.parser_step = CameTweeDecoderStepReset;
  267. manchester_advance(
  268. instance->manchester_saved_state,
  269. ManchesterEventReset,
  270. &instance->manchester_saved_state,
  271. NULL);
  272. }
  273. void subghz_protocol_decoder_came_twee_feed(void* context, bool level, uint32_t duration) {
  274. furi_assert(context);
  275. SubGhzProtocolDecoderCameTwee* instance = context;
  276. ManchesterEvent event = ManchesterEventReset;
  277. switch(instance->decoder.parser_step) {
  278. case CameTweeDecoderStepReset:
  279. if((!level) && (DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long * 51) <
  280. subghz_protocol_came_twee_const.te_delta * 20)) {
  281. //Found header CAME
  282. instance->decoder.parser_step = CameTweeDecoderStepDecoderData;
  283. instance->decoder.decode_data = 0;
  284. instance->decoder.decode_count_bit = 0;
  285. manchester_advance(
  286. instance->manchester_saved_state,
  287. ManchesterEventLongLow,
  288. &instance->manchester_saved_state,
  289. NULL);
  290. manchester_advance(
  291. instance->manchester_saved_state,
  292. ManchesterEventLongHigh,
  293. &instance->manchester_saved_state,
  294. NULL);
  295. manchester_advance(
  296. instance->manchester_saved_state,
  297. ManchesterEventShortLow,
  298. &instance->manchester_saved_state,
  299. NULL);
  300. }
  301. break;
  302. case CameTweeDecoderStepDecoderData:
  303. if(!level) {
  304. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  305. subghz_protocol_came_twee_const.te_delta) {
  306. event = ManchesterEventShortLow;
  307. } else if(
  308. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  309. subghz_protocol_came_twee_const.te_delta) {
  310. event = ManchesterEventLongLow;
  311. } else if(
  312. duration >= ((uint32_t)subghz_protocol_came_twee_const.te_long * 2 +
  313. subghz_protocol_came_twee_const.te_delta)) {
  314. if(instance->decoder.decode_count_bit ==
  315. subghz_protocol_came_twee_const.min_count_bit_for_found) {
  316. instance->generic.data = instance->decoder.decode_data;
  317. instance->generic.data_count_bit = instance->decoder.decode_count_bit;
  318. if(instance->base.callback)
  319. instance->base.callback(&instance->base, instance->base.context);
  320. }
  321. instance->decoder.decode_data = 0;
  322. instance->decoder.decode_count_bit = 0;
  323. manchester_advance(
  324. instance->manchester_saved_state,
  325. ManchesterEventLongLow,
  326. &instance->manchester_saved_state,
  327. NULL);
  328. manchester_advance(
  329. instance->manchester_saved_state,
  330. ManchesterEventLongHigh,
  331. &instance->manchester_saved_state,
  332. NULL);
  333. manchester_advance(
  334. instance->manchester_saved_state,
  335. ManchesterEventShortLow,
  336. &instance->manchester_saved_state,
  337. NULL);
  338. } else {
  339. instance->decoder.parser_step = CameTweeDecoderStepReset;
  340. }
  341. } else {
  342. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  343. subghz_protocol_came_twee_const.te_delta) {
  344. event = ManchesterEventShortHigh;
  345. } else if(
  346. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  347. subghz_protocol_came_twee_const.te_delta) {
  348. event = ManchesterEventLongHigh;
  349. } else {
  350. instance->decoder.parser_step = CameTweeDecoderStepReset;
  351. }
  352. }
  353. if(event != ManchesterEventReset) {
  354. bool data;
  355. bool data_ok = manchester_advance(
  356. instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
  357. if(data_ok) {
  358. instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data;
  359. instance->decoder.decode_count_bit++;
  360. }
  361. }
  362. break;
  363. }
  364. }
  365. uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context) {
  366. furi_assert(context);
  367. SubGhzProtocolDecoderCameTwee* instance = context;
  368. return subghz_protocol_blocks_get_hash_data(
  369. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  370. }
  371. SubGhzProtocolStatus subghz_protocol_decoder_came_twee_serialize(
  372. void* context,
  373. FlipperFormat* flipper_format,
  374. SubGhzRadioPreset* preset) {
  375. furi_assert(context);
  376. SubGhzProtocolDecoderCameTwee* instance = context;
  377. return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
  378. }
  379. SubGhzProtocolStatus
  380. subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {
  381. furi_assert(context);
  382. SubGhzProtocolDecoderCameTwee* instance = context;
  383. return subghz_block_generic_deserialize_check_count_bit(
  384. &instance->generic,
  385. flipper_format,
  386. subghz_protocol_came_twee_const.min_count_bit_for_found);
  387. }
  388. void subghz_protocol_decoder_came_twee_get_string(void* context, FuriString* output) {
  389. furi_assert(context);
  390. SubGhzProtocolDecoderCameTwee* instance = context;
  391. subghz_protocol_came_twee_remote_controller(&instance->generic);
  392. uint32_t code_found_hi = instance->generic.data >> 32;
  393. uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff;
  394. furi_string_cat_printf(
  395. output,
  396. "%s %db\r\n"
  397. "Key:0x%lX%08lX\r\n"
  398. "Btn:%X\r\n"
  399. "DIP:" DIP_PATTERN "\r\n",
  400. instance->generic.protocol_name,
  401. instance->generic.data_count_bit,
  402. code_found_hi,
  403. code_found_lo,
  404. instance->generic.btn,
  405. CNT_TO_DIP(instance->generic.cnt));
  406. }