came_twee.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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. SubGhzProtocolEncoderCameTwee* instance = malloc(sizeof(SubGhzProtocolEncoderCameTwee));
  89. instance->base.protocol = &subghz_protocol_came_twee;
  90. instance->generic.protocol_name = instance->base.protocol->name;
  91. instance->encoder.repeat = 10;
  92. instance->encoder.size_upload = 1536; //max upload 92*14 = 1288 !!!!
  93. instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
  94. instance->encoder.is_runing = false;
  95. return instance;
  96. }
  97. void subghz_protocol_encoder_came_twee_free(void* context) {
  98. furi_assert(context);
  99. SubGhzProtocolEncoderCameTwee* instance = context;
  100. free(instance->encoder.upload);
  101. free(instance);
  102. }
  103. static LevelDuration
  104. subghz_protocol_encoder_came_twee_add_duration_to_upload(ManchesterEncoderResult result) {
  105. LevelDuration data = {.duration = 0, .level = 0};
  106. switch(result) {
  107. case ManchesterEncoderResultShortLow:
  108. data.duration = subghz_protocol_came_twee_const.te_short;
  109. data.level = false;
  110. break;
  111. case ManchesterEncoderResultLongLow:
  112. data.duration = subghz_protocol_came_twee_const.te_long;
  113. data.level = false;
  114. break;
  115. case ManchesterEncoderResultLongHigh:
  116. data.duration = subghz_protocol_came_twee_const.te_long;
  117. data.level = true;
  118. break;
  119. case ManchesterEncoderResultShortHigh:
  120. data.duration = subghz_protocol_came_twee_const.te_short;
  121. data.level = true;
  122. break;
  123. default:
  124. FURI_LOG_E(TAG, "DO CRASH HERE.");
  125. furi_crash(NULL);
  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. //optional parameter parameter
  222. flipper_format_read_uint32(
  223. flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
  224. subghz_protocol_came_twee_remote_controller(&instance->generic);
  225. subghz_protocol_encoder_came_twee_get_upload(instance);
  226. instance->encoder.is_runing = true;
  227. res = true;
  228. } while(false);
  229. return res;
  230. }
  231. void subghz_protocol_encoder_came_twee_stop(void* context) {
  232. SubGhzProtocolEncoderCameTwee* instance = context;
  233. instance->encoder.is_runing = false;
  234. }
  235. LevelDuration subghz_protocol_encoder_came_twee_yield(void* context) {
  236. SubGhzProtocolEncoderCameTwee* instance = context;
  237. if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) {
  238. instance->encoder.is_runing = false;
  239. return level_duration_reset();
  240. }
  241. LevelDuration ret = instance->encoder.upload[instance->encoder.front];
  242. if(++instance->encoder.front == instance->encoder.size_upload) {
  243. instance->encoder.repeat--;
  244. instance->encoder.front = 0;
  245. }
  246. return ret;
  247. }
  248. void* subghz_protocol_decoder_came_twee_alloc(SubGhzEnvironment* environment) {
  249. SubGhzProtocolDecoderCameTwee* instance = malloc(sizeof(SubGhzProtocolDecoderCameTwee));
  250. instance->base.protocol = &subghz_protocol_came_twee;
  251. instance->generic.protocol_name = instance->base.protocol->name;
  252. return instance;
  253. }
  254. void subghz_protocol_decoder_came_twee_free(void* context) {
  255. furi_assert(context);
  256. SubGhzProtocolDecoderCameTwee* instance = context;
  257. free(instance);
  258. }
  259. void subghz_protocol_decoder_came_twee_reset(void* context) {
  260. furi_assert(context);
  261. SubGhzProtocolDecoderCameTwee* instance = context;
  262. instance->decoder.parser_step = CameTweeDecoderStepReset;
  263. manchester_advance(
  264. instance->manchester_saved_state,
  265. ManchesterEventReset,
  266. &instance->manchester_saved_state,
  267. NULL);
  268. }
  269. void subghz_protocol_decoder_came_twee_feed(void* context, bool level, uint32_t duration) {
  270. furi_assert(context);
  271. SubGhzProtocolDecoderCameTwee* instance = context;
  272. ManchesterEvent event = ManchesterEventReset;
  273. switch(instance->decoder.parser_step) {
  274. case CameTweeDecoderStepReset:
  275. if((!level) && (DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long * 51) <
  276. subghz_protocol_came_twee_const.te_delta * 20)) {
  277. //Found header CAME
  278. instance->decoder.parser_step = CameTweeDecoderStepDecoderData;
  279. instance->decoder.decode_data = 0;
  280. instance->decoder.decode_count_bit = 0;
  281. manchester_advance(
  282. instance->manchester_saved_state,
  283. ManchesterEventLongLow,
  284. &instance->manchester_saved_state,
  285. NULL);
  286. manchester_advance(
  287. instance->manchester_saved_state,
  288. ManchesterEventLongHigh,
  289. &instance->manchester_saved_state,
  290. NULL);
  291. manchester_advance(
  292. instance->manchester_saved_state,
  293. ManchesterEventShortLow,
  294. &instance->manchester_saved_state,
  295. NULL);
  296. }
  297. break;
  298. case CameTweeDecoderStepDecoderData:
  299. if(!level) {
  300. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  301. subghz_protocol_came_twee_const.te_delta) {
  302. event = ManchesterEventShortLow;
  303. } else if(
  304. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  305. subghz_protocol_came_twee_const.te_delta) {
  306. event = ManchesterEventLongLow;
  307. } else if(
  308. duration >= (subghz_protocol_came_twee_const.te_long * 2 +
  309. subghz_protocol_came_twee_const.te_delta)) {
  310. if(instance->decoder.decode_count_bit >=
  311. subghz_protocol_came_twee_const.min_count_bit_for_found) {
  312. instance->generic.data = instance->decoder.decode_data;
  313. instance->generic.data_count_bit = instance->decoder.decode_count_bit;
  314. if(instance->base.callback)
  315. instance->base.callback(&instance->base, instance->base.context);
  316. }
  317. instance->decoder.decode_data = 0;
  318. instance->decoder.decode_count_bit = 0;
  319. manchester_advance(
  320. instance->manchester_saved_state,
  321. ManchesterEventLongLow,
  322. &instance->manchester_saved_state,
  323. NULL);
  324. manchester_advance(
  325. instance->manchester_saved_state,
  326. ManchesterEventLongHigh,
  327. &instance->manchester_saved_state,
  328. NULL);
  329. manchester_advance(
  330. instance->manchester_saved_state,
  331. ManchesterEventShortLow,
  332. &instance->manchester_saved_state,
  333. NULL);
  334. } else {
  335. instance->decoder.parser_step = CameTweeDecoderStepReset;
  336. }
  337. } else {
  338. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  339. subghz_protocol_came_twee_const.te_delta) {
  340. event = ManchesterEventShortHigh;
  341. } else if(
  342. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  343. subghz_protocol_came_twee_const.te_delta) {
  344. event = ManchesterEventLongHigh;
  345. } else {
  346. instance->decoder.parser_step = CameTweeDecoderStepReset;
  347. }
  348. }
  349. if(event != ManchesterEventReset) {
  350. bool data;
  351. bool data_ok = manchester_advance(
  352. instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
  353. if(data_ok) {
  354. instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data;
  355. instance->decoder.decode_count_bit++;
  356. }
  357. }
  358. break;
  359. }
  360. }
  361. uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context) {
  362. furi_assert(context);
  363. SubGhzProtocolDecoderCameTwee* instance = context;
  364. return subghz_protocol_blocks_get_hash_data(
  365. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  366. }
  367. bool subghz_protocol_decoder_came_twee_serialize(
  368. void* context,
  369. FlipperFormat* flipper_format,
  370. uint32_t frequency,
  371. FuriHalSubGhzPreset preset) {
  372. furi_assert(context);
  373. SubGhzProtocolDecoderCameTwee* instance = context;
  374. return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
  375. }
  376. bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {
  377. furi_assert(context);
  378. SubGhzProtocolDecoderCameTwee* instance = context;
  379. return subghz_block_generic_deserialize(&instance->generic, flipper_format);
  380. }
  381. void subghz_protocol_decoder_came_twee_get_string(void* context, string_t output) {
  382. furi_assert(context);
  383. SubGhzProtocolDecoderCameTwee* instance = context;
  384. subghz_protocol_came_twee_remote_controller(&instance->generic);
  385. uint32_t code_found_hi = instance->generic.data >> 32;
  386. uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff;
  387. string_cat_printf(
  388. output,
  389. "%s %dbit\r\n"
  390. "Key:0x%lX%08lX\r\n"
  391. "Btn:%lX\r\n"
  392. "DIP:" DIP_PATTERN "\r\n",
  393. instance->generic.protocol_name,
  394. instance->generic.data_count_bit,
  395. code_found_hi,
  396. code_found_lo,
  397. instance->generic.btn,
  398. CNT_TO_DIP(instance->generic.cnt));
  399. }