came_twee.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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_runing = 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_LOG_E(TAG, "DO CRASH HERE.");
  126. furi_crash(NULL);
  127. break;
  128. }
  129. return level_duration_make(data.level, data.duration);
  130. }
  131. /**
  132. * Generating an upload from data.
  133. * @param instance Pointer to a SubGhzProtocolEncoderCameTwee instance
  134. */
  135. static void subghz_protocol_encoder_came_twee_get_upload(SubGhzProtocolEncoderCameTwee* instance) {
  136. furi_assert(instance);
  137. size_t index = 0;
  138. ManchesterEncoderState enc_state;
  139. manchester_encoder_reset(&enc_state);
  140. ManchesterEncoderResult result;
  141. uint64_t temp_parcel = 0x003FFF7200000000; //parcel mask
  142. for(int i = 14; i >= 0; i--) {
  143. temp_parcel = (temp_parcel & 0xFFFFFFFF00000000) |
  144. (instance->generic.serial ^ came_twee_magic_numbers_xor[i]);
  145. for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
  146. if(!manchester_encoder_advance(&enc_state, !bit_read(temp_parcel, i - 1), &result)) {
  147. instance->encoder.upload[index++] =
  148. subghz_protocol_encoder_came_twee_add_duration_to_upload(result);
  149. manchester_encoder_advance(&enc_state, !bit_read(temp_parcel, i - 1), &result);
  150. }
  151. instance->encoder.upload[index++] =
  152. subghz_protocol_encoder_came_twee_add_duration_to_upload(result);
  153. }
  154. instance->encoder.upload[index] = subghz_protocol_encoder_came_twee_add_duration_to_upload(
  155. manchester_encoder_finish(&enc_state));
  156. if(level_duration_get_level(instance->encoder.upload[index])) {
  157. index++;
  158. }
  159. instance->encoder.upload[index++] =
  160. level_duration_make(false, (uint32_t)subghz_protocol_came_twee_const.te_long * 51);
  161. }
  162. instance->encoder.size_upload = index;
  163. }
  164. /**
  165. * Analysis of received data
  166. * @param instance Pointer to a SubGhzBlockGeneric* instance
  167. */
  168. static void subghz_protocol_came_twee_remote_controller(SubGhzBlockGeneric* instance) {
  169. /* Came Twee 54 bit, rolling code 15 parcels with
  170. * a decreasing counter from 0xE to 0x0
  171. * with originally coded dip switches on the console 10 bit code
  172. *
  173. * 0x003FFF72E04A6FEE
  174. * 0x003FFF72D17B5EDD
  175. * 0x003FFF72C2684DCC
  176. * 0x003FFF72B3193CBB
  177. * 0x003FFF72A40E2BAA
  178. * 0x003FFF72953F1A99
  179. * 0x003FFF72862C0988
  180. * 0x003FFF7277DDF877
  181. * 0x003FFF7268C2E766
  182. * 0x003FFF7259F3D655
  183. * 0x003FFF724AE0C544
  184. * 0x003FFF723B91B433
  185. * 0x003FFF722C86A322
  186. * 0x003FFF721DB79211
  187. * 0x003FFF720EA48100
  188. *
  189. * decryption
  190. * the last 32 bits, do XOR by the desired number, divide the result by 4,
  191. * convert the first 16 bits of the resulting 32-bit number to bin and do
  192. * bit-by-bit mirroring, adding up to 10 bits
  193. *
  194. * Example
  195. * Step 1. 0x003FFF721DB79211 => 0x1DB79211
  196. * Step 4. 0x1DB79211 xor 0x1D1D1D11 => 0x00AA8F00
  197. * Step 4. 0x00AA8F00 / 4 => 0x002AA3C0
  198. * Step 5. 0x002AA3C0 => 0x002A
  199. * Step 6. 0x002A bin => b101010
  200. * Step 7. b101010 => b0101010000
  201. * Step 8. b0101010000 => (Dip) Off ON Off ON Off ON Off Off Off Off
  202. */
  203. uint8_t cnt_parcel = (uint8_t)(instance->data & 0xF);
  204. uint32_t data = (uint32_t)(instance->data & 0x0FFFFFFFF);
  205. data = (data ^ came_twee_magic_numbers_xor[cnt_parcel]);
  206. instance->serial = data;
  207. data /= 4;
  208. instance->btn = (data >> 4) & 0x0F;
  209. data >>= 16;
  210. data = (uint16_t)subghz_protocol_blocks_reverse_key(data, 16);
  211. instance->cnt = data >> 6;
  212. }
  213. bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {
  214. furi_assert(context);
  215. SubGhzProtocolEncoderCameTwee* instance = context;
  216. bool res = false;
  217. do {
  218. if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
  219. FURI_LOG_E(TAG, "Deserialize error");
  220. break;
  221. }
  222. //optional parameter parameter
  223. flipper_format_read_uint32(
  224. flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
  225. subghz_protocol_came_twee_remote_controller(&instance->generic);
  226. subghz_protocol_encoder_came_twee_get_upload(instance);
  227. instance->encoder.is_runing = true;
  228. res = true;
  229. } while(false);
  230. return res;
  231. }
  232. void subghz_protocol_encoder_came_twee_stop(void* context) {
  233. SubGhzProtocolEncoderCameTwee* instance = context;
  234. instance->encoder.is_runing = false;
  235. }
  236. LevelDuration subghz_protocol_encoder_came_twee_yield(void* context) {
  237. SubGhzProtocolEncoderCameTwee* instance = context;
  238. if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) {
  239. instance->encoder.is_runing = false;
  240. return level_duration_reset();
  241. }
  242. LevelDuration ret = instance->encoder.upload[instance->encoder.front];
  243. if(++instance->encoder.front == instance->encoder.size_upload) {
  244. instance->encoder.repeat--;
  245. instance->encoder.front = 0;
  246. }
  247. return ret;
  248. }
  249. void* subghz_protocol_decoder_came_twee_alloc(SubGhzEnvironment* environment) {
  250. UNUSED(environment);
  251. SubGhzProtocolDecoderCameTwee* instance = malloc(sizeof(SubGhzProtocolDecoderCameTwee));
  252. instance->base.protocol = &subghz_protocol_came_twee;
  253. instance->generic.protocol_name = instance->base.protocol->name;
  254. return instance;
  255. }
  256. void subghz_protocol_decoder_came_twee_free(void* context) {
  257. furi_assert(context);
  258. SubGhzProtocolDecoderCameTwee* instance = context;
  259. free(instance);
  260. }
  261. void subghz_protocol_decoder_came_twee_reset(void* context) {
  262. furi_assert(context);
  263. SubGhzProtocolDecoderCameTwee* instance = context;
  264. instance->decoder.parser_step = CameTweeDecoderStepReset;
  265. manchester_advance(
  266. instance->manchester_saved_state,
  267. ManchesterEventReset,
  268. &instance->manchester_saved_state,
  269. NULL);
  270. }
  271. void subghz_protocol_decoder_came_twee_feed(void* context, bool level, uint32_t duration) {
  272. furi_assert(context);
  273. SubGhzProtocolDecoderCameTwee* instance = context;
  274. ManchesterEvent event = ManchesterEventReset;
  275. switch(instance->decoder.parser_step) {
  276. case CameTweeDecoderStepReset:
  277. if((!level) && (DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long * 51) <
  278. subghz_protocol_came_twee_const.te_delta * 20)) {
  279. //Found header CAME
  280. instance->decoder.parser_step = CameTweeDecoderStepDecoderData;
  281. instance->decoder.decode_data = 0;
  282. instance->decoder.decode_count_bit = 0;
  283. manchester_advance(
  284. instance->manchester_saved_state,
  285. ManchesterEventLongLow,
  286. &instance->manchester_saved_state,
  287. NULL);
  288. manchester_advance(
  289. instance->manchester_saved_state,
  290. ManchesterEventLongHigh,
  291. &instance->manchester_saved_state,
  292. NULL);
  293. manchester_advance(
  294. instance->manchester_saved_state,
  295. ManchesterEventShortLow,
  296. &instance->manchester_saved_state,
  297. NULL);
  298. }
  299. break;
  300. case CameTweeDecoderStepDecoderData:
  301. if(!level) {
  302. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  303. subghz_protocol_came_twee_const.te_delta) {
  304. event = ManchesterEventShortLow;
  305. } else if(
  306. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  307. subghz_protocol_came_twee_const.te_delta) {
  308. event = ManchesterEventLongLow;
  309. } else if(
  310. duration >= ((uint32_t)subghz_protocol_came_twee_const.te_long * 2 +
  311. subghz_protocol_came_twee_const.te_delta)) {
  312. if(instance->decoder.decode_count_bit >=
  313. subghz_protocol_came_twee_const.min_count_bit_for_found) {
  314. instance->generic.data = instance->decoder.decode_data;
  315. instance->generic.data_count_bit = instance->decoder.decode_count_bit;
  316. if(instance->base.callback)
  317. instance->base.callback(&instance->base, instance->base.context);
  318. }
  319. instance->decoder.decode_data = 0;
  320. instance->decoder.decode_count_bit = 0;
  321. manchester_advance(
  322. instance->manchester_saved_state,
  323. ManchesterEventLongLow,
  324. &instance->manchester_saved_state,
  325. NULL);
  326. manchester_advance(
  327. instance->manchester_saved_state,
  328. ManchesterEventLongHigh,
  329. &instance->manchester_saved_state,
  330. NULL);
  331. manchester_advance(
  332. instance->manchester_saved_state,
  333. ManchesterEventShortLow,
  334. &instance->manchester_saved_state,
  335. NULL);
  336. } else {
  337. instance->decoder.parser_step = CameTweeDecoderStepReset;
  338. }
  339. } else {
  340. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  341. subghz_protocol_came_twee_const.te_delta) {
  342. event = ManchesterEventShortHigh;
  343. } else if(
  344. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  345. subghz_protocol_came_twee_const.te_delta) {
  346. event = ManchesterEventLongHigh;
  347. } else {
  348. instance->decoder.parser_step = CameTweeDecoderStepReset;
  349. }
  350. }
  351. if(event != ManchesterEventReset) {
  352. bool data;
  353. bool data_ok = manchester_advance(
  354. instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
  355. if(data_ok) {
  356. instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data;
  357. instance->decoder.decode_count_bit++;
  358. }
  359. }
  360. break;
  361. }
  362. }
  363. uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context) {
  364. furi_assert(context);
  365. SubGhzProtocolDecoderCameTwee* instance = context;
  366. return subghz_protocol_blocks_get_hash_data(
  367. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  368. }
  369. bool subghz_protocol_decoder_came_twee_serialize(
  370. void* context,
  371. FlipperFormat* flipper_format,
  372. uint32_t frequency,
  373. FuriHalSubGhzPreset preset) {
  374. furi_assert(context);
  375. SubGhzProtocolDecoderCameTwee* instance = context;
  376. return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
  377. }
  378. bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {
  379. furi_assert(context);
  380. SubGhzProtocolDecoderCameTwee* instance = context;
  381. return subghz_block_generic_deserialize(&instance->generic, flipper_format);
  382. }
  383. void subghz_protocol_decoder_came_twee_get_string(void* context, string_t output) {
  384. furi_assert(context);
  385. SubGhzProtocolDecoderCameTwee* instance = context;
  386. subghz_protocol_came_twee_remote_controller(&instance->generic);
  387. uint32_t code_found_hi = instance->generic.data >> 32;
  388. uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff;
  389. string_cat_printf(
  390. output,
  391. "%s %dbit\r\n"
  392. "Key:0x%lX%08lX\r\n"
  393. "Btn:%lX\r\n"
  394. "DIP:" DIP_PATTERN "\r\n",
  395. instance->generic.protocol_name,
  396. instance->generic.data_count_bit,
  397. code_found_hi,
  398. code_found_lo,
  399. instance->generic.btn,
  400. CNT_TO_DIP(instance->generic.cnt));
  401. }