came_twee.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  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. bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {
  213. furi_assert(context);
  214. SubGhzProtocolEncoderCameTwee* instance = context;
  215. bool res = false;
  216. do {
  217. if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
  218. FURI_LOG_E(TAG, "Deserialize error");
  219. break;
  220. }
  221. if(instance->generic.data_count_bit !=
  222. subghz_protocol_came_twee_const.min_count_bit_for_found) {
  223. FURI_LOG_E(TAG, "Wrong number of bits in key");
  224. break;
  225. }
  226. //optional parameter parameter
  227. flipper_format_read_uint32(
  228. flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
  229. subghz_protocol_came_twee_remote_controller(&instance->generic);
  230. subghz_protocol_encoder_came_twee_get_upload(instance);
  231. instance->encoder.is_running = true;
  232. res = true;
  233. } while(false);
  234. return res;
  235. }
  236. void subghz_protocol_encoder_came_twee_stop(void* context) {
  237. SubGhzProtocolEncoderCameTwee* instance = context;
  238. instance->encoder.is_running = false;
  239. }
  240. LevelDuration subghz_protocol_encoder_came_twee_yield(void* context) {
  241. SubGhzProtocolEncoderCameTwee* instance = context;
  242. if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
  243. instance->encoder.is_running = false;
  244. return level_duration_reset();
  245. }
  246. LevelDuration ret = instance->encoder.upload[instance->encoder.front];
  247. if(++instance->encoder.front == instance->encoder.size_upload) {
  248. instance->encoder.repeat--;
  249. instance->encoder.front = 0;
  250. }
  251. return ret;
  252. }
  253. void* subghz_protocol_decoder_came_twee_alloc(SubGhzEnvironment* environment) {
  254. UNUSED(environment);
  255. SubGhzProtocolDecoderCameTwee* instance = malloc(sizeof(SubGhzProtocolDecoderCameTwee));
  256. instance->base.protocol = &subghz_protocol_came_twee;
  257. instance->generic.protocol_name = instance->base.protocol->name;
  258. return instance;
  259. }
  260. void subghz_protocol_decoder_came_twee_free(void* context) {
  261. furi_assert(context);
  262. SubGhzProtocolDecoderCameTwee* instance = context;
  263. free(instance);
  264. }
  265. void subghz_protocol_decoder_came_twee_reset(void* context) {
  266. furi_assert(context);
  267. SubGhzProtocolDecoderCameTwee* instance = context;
  268. instance->decoder.parser_step = CameTweeDecoderStepReset;
  269. manchester_advance(
  270. instance->manchester_saved_state,
  271. ManchesterEventReset,
  272. &instance->manchester_saved_state,
  273. NULL);
  274. }
  275. void subghz_protocol_decoder_came_twee_feed(void* context, bool level, uint32_t duration) {
  276. furi_assert(context);
  277. SubGhzProtocolDecoderCameTwee* instance = context;
  278. ManchesterEvent event = ManchesterEventReset;
  279. switch(instance->decoder.parser_step) {
  280. case CameTweeDecoderStepReset:
  281. if((!level) && (DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long * 51) <
  282. subghz_protocol_came_twee_const.te_delta * 20)) {
  283. //Found header CAME
  284. instance->decoder.parser_step = CameTweeDecoderStepDecoderData;
  285. instance->decoder.decode_data = 0;
  286. instance->decoder.decode_count_bit = 0;
  287. manchester_advance(
  288. instance->manchester_saved_state,
  289. ManchesterEventLongLow,
  290. &instance->manchester_saved_state,
  291. NULL);
  292. manchester_advance(
  293. instance->manchester_saved_state,
  294. ManchesterEventLongHigh,
  295. &instance->manchester_saved_state,
  296. NULL);
  297. manchester_advance(
  298. instance->manchester_saved_state,
  299. ManchesterEventShortLow,
  300. &instance->manchester_saved_state,
  301. NULL);
  302. }
  303. break;
  304. case CameTweeDecoderStepDecoderData:
  305. if(!level) {
  306. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  307. subghz_protocol_came_twee_const.te_delta) {
  308. event = ManchesterEventShortLow;
  309. } else if(
  310. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  311. subghz_protocol_came_twee_const.te_delta) {
  312. event = ManchesterEventLongLow;
  313. } else if(
  314. duration >= ((uint32_t)subghz_protocol_came_twee_const.te_long * 2 +
  315. subghz_protocol_came_twee_const.te_delta)) {
  316. if(instance->decoder.decode_count_bit ==
  317. subghz_protocol_came_twee_const.min_count_bit_for_found) {
  318. instance->generic.data = instance->decoder.decode_data;
  319. instance->generic.data_count_bit = instance->decoder.decode_count_bit;
  320. if(instance->base.callback)
  321. instance->base.callback(&instance->base, instance->base.context);
  322. }
  323. instance->decoder.decode_data = 0;
  324. instance->decoder.decode_count_bit = 0;
  325. manchester_advance(
  326. instance->manchester_saved_state,
  327. ManchesterEventLongLow,
  328. &instance->manchester_saved_state,
  329. NULL);
  330. manchester_advance(
  331. instance->manchester_saved_state,
  332. ManchesterEventLongHigh,
  333. &instance->manchester_saved_state,
  334. NULL);
  335. manchester_advance(
  336. instance->manchester_saved_state,
  337. ManchesterEventShortLow,
  338. &instance->manchester_saved_state,
  339. NULL);
  340. } else {
  341. instance->decoder.parser_step = CameTweeDecoderStepReset;
  342. }
  343. } else {
  344. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  345. subghz_protocol_came_twee_const.te_delta) {
  346. event = ManchesterEventShortHigh;
  347. } else if(
  348. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  349. subghz_protocol_came_twee_const.te_delta) {
  350. event = ManchesterEventLongHigh;
  351. } else {
  352. instance->decoder.parser_step = CameTweeDecoderStepReset;
  353. }
  354. }
  355. if(event != ManchesterEventReset) {
  356. bool data;
  357. bool data_ok = manchester_advance(
  358. instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
  359. if(data_ok) {
  360. instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data;
  361. instance->decoder.decode_count_bit++;
  362. }
  363. }
  364. break;
  365. }
  366. }
  367. uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context) {
  368. furi_assert(context);
  369. SubGhzProtocolDecoderCameTwee* instance = context;
  370. return subghz_protocol_blocks_get_hash_data(
  371. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  372. }
  373. bool subghz_protocol_decoder_came_twee_serialize(
  374. void* context,
  375. FlipperFormat* flipper_format,
  376. SubGhzRadioPreset* preset) {
  377. furi_assert(context);
  378. SubGhzProtocolDecoderCameTwee* instance = context;
  379. return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
  380. }
  381. bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {
  382. furi_assert(context);
  383. SubGhzProtocolDecoderCameTwee* instance = context;
  384. bool ret = false;
  385. do {
  386. if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
  387. break;
  388. }
  389. if(instance->generic.data_count_bit !=
  390. subghz_protocol_came_twee_const.min_count_bit_for_found) {
  391. FURI_LOG_E(TAG, "Wrong number of bits in key");
  392. break;
  393. }
  394. ret = true;
  395. } while(false);
  396. return ret;
  397. }
  398. void subghz_protocol_decoder_came_twee_get_string(void* context, FuriString* output) {
  399. furi_assert(context);
  400. SubGhzProtocolDecoderCameTwee* instance = context;
  401. subghz_protocol_came_twee_remote_controller(&instance->generic);
  402. uint32_t code_found_hi = instance->generic.data >> 32;
  403. uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff;
  404. furi_string_cat_printf(
  405. output,
  406. "%s %db\r\n"
  407. "Key:0x%lX%08lX\r\n"
  408. "Btn:%X\r\n"
  409. "DIP:" DIP_PATTERN "\r\n",
  410. instance->generic.protocol_name,
  411. instance->generic.data_count_bit,
  412. code_found_hi,
  413. code_found_lo,
  414. instance->generic.btn,
  415. CNT_TO_DIP(instance->generic.cnt));
  416. }