subbrute_worker.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. #include "subbrute_worker_private.h"
  2. #include <string.h>
  3. #include <toolbox/stream/stream.h>
  4. #include <flipper_format.h>
  5. #include <flipper_format_i.h>
  6. #define TAG "SubBruteWorker"
  7. #define SUBBRUTE_TX_TIMEOUT 5
  8. #define SUBBRUTE_MANUAL_TRANSMIT_INTERVAL 400
  9. SubBruteWorker* subbrute_worker_alloc() {
  10. SubBruteWorker* instance = malloc(sizeof(SubBruteWorker));
  11. instance->state = SubBruteWorkerStateIDLE;
  12. instance->step = 0;
  13. instance->worker_running = false;
  14. instance->initiated = false;
  15. instance->last_time_tx_data = 0;
  16. instance->load_index = 0;
  17. instance->thread = furi_thread_alloc();
  18. furi_thread_set_name(instance->thread, "SubBruteAttackWorker");
  19. furi_thread_set_stack_size(instance->thread, 2048);
  20. furi_thread_set_context(instance->thread, instance);
  21. furi_thread_set_callback(instance->thread, subbrute_worker_thread);
  22. instance->context = NULL;
  23. instance->callback = NULL;
  24. instance->decoder_result = NULL;
  25. instance->transmitter = NULL;
  26. instance->environment = subghz_environment_alloc();
  27. instance->transmit_mode = false;
  28. return instance;
  29. }
  30. void subbrute_worker_free(SubBruteWorker* instance) {
  31. furi_assert(instance);
  32. // I don't know how to free this
  33. instance->decoder_result = NULL;
  34. if(instance->transmitter != NULL) {
  35. subghz_transmitter_free(instance->transmitter);
  36. instance->transmitter = NULL;
  37. }
  38. subghz_environment_free(instance->environment);
  39. instance->environment = NULL;
  40. furi_thread_free(instance->thread);
  41. free(instance);
  42. }
  43. uint64_t subbrute_worker_get_step(SubBruteWorker* instance) {
  44. return instance->step;
  45. }
  46. bool subbrute_worker_set_step(SubBruteWorker* instance, uint64_t step) {
  47. furi_assert(instance);
  48. if(!subbrute_worker_can_manual_transmit(instance)) {
  49. FURI_LOG_W(TAG, "Cannot set step during running mode");
  50. return false;
  51. }
  52. instance->step = step;
  53. return true;
  54. }
  55. bool subbrute_worker_init_default_attack(
  56. SubBruteWorker* instance,
  57. SubBruteAttacks attack_type,
  58. uint64_t step,
  59. const SubBruteProtocol* protocol) {
  60. furi_assert(instance);
  61. if(instance->worker_running) {
  62. FURI_LOG_W(TAG, "Init Worker when it's running");
  63. subbrute_worker_stop(instance);
  64. }
  65. instance->attack = attack_type;
  66. instance->frequency = protocol->frequency;
  67. instance->preset = protocol->preset;
  68. instance->file = protocol->file;
  69. instance->step = step;
  70. instance->bits = protocol->bits;
  71. instance->te = protocol->te;
  72. instance->repeat = protocol->repeat;
  73. instance->load_index = 0;
  74. instance->file_key = NULL;
  75. instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
  76. instance->initiated = true;
  77. instance->state = SubBruteWorkerStateReady;
  78. subbrute_worker_send_callback(instance);
  79. #ifdef FURI_DEBUG
  80. FURI_LOG_I(
  81. TAG,
  82. "subbrute_worker_init_default_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld",
  83. subbrute_protocol_name(instance->attack),
  84. instance->bits,
  85. subbrute_protocol_preset(instance->preset),
  86. subbrute_protocol_file(instance->file),
  87. instance->te,
  88. instance->repeat,
  89. instance->max_value);
  90. #endif
  91. return true;
  92. }
  93. bool subbrute_worker_init_file_attack(
  94. SubBruteWorker* instance,
  95. uint64_t step,
  96. uint8_t load_index,
  97. const char* file_key,
  98. SubBruteProtocol* protocol) {
  99. furi_assert(instance);
  100. if(instance->worker_running) {
  101. FURI_LOG_W(TAG, "Init Worker when it's running");
  102. subbrute_worker_stop(instance);
  103. }
  104. instance->attack = SubBruteAttackLoadFile;
  105. instance->frequency = protocol->frequency;
  106. instance->preset = protocol->preset;
  107. instance->file = protocol->file;
  108. instance->step = step;
  109. instance->bits = protocol->bits;
  110. instance->te = protocol->te;
  111. instance->load_index = load_index;
  112. instance->repeat = protocol->repeat;
  113. instance->file_key = file_key;
  114. instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
  115. instance->initiated = true;
  116. instance->state = SubBruteWorkerStateReady;
  117. subbrute_worker_send_callback(instance);
  118. #ifdef FURI_DEBUG
  119. FURI_LOG_I(
  120. TAG,
  121. "subbrute_worker_init_file_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld",
  122. subbrute_protocol_name(instance->attack),
  123. instance->bits,
  124. subbrute_protocol_preset(instance->preset),
  125. subbrute_protocol_file(instance->file),
  126. instance->te,
  127. instance->repeat,
  128. instance->max_value);
  129. #endif
  130. return true;
  131. }
  132. bool subbrute_worker_start(SubBruteWorker* instance) {
  133. furi_assert(instance);
  134. if(!instance->initiated) {
  135. FURI_LOG_W(TAG, "Worker not init!");
  136. return false;
  137. }
  138. if(instance->worker_running) {
  139. FURI_LOG_W(TAG, "Worker is already running!");
  140. return false;
  141. }
  142. if(instance->state != SubBruteWorkerStateReady &&
  143. instance->state != SubBruteWorkerStateFinished) {
  144. FURI_LOG_W(TAG, "Worker cannot start, invalid device state: %d", instance->state);
  145. return false;
  146. }
  147. instance->worker_running = true;
  148. furi_thread_start(instance->thread);
  149. return true;
  150. }
  151. void subbrute_worker_stop(SubBruteWorker* instance) {
  152. furi_assert(instance);
  153. if (!instance->worker_running) {
  154. return;
  155. }
  156. instance->worker_running = false;
  157. furi_thread_join(instance->thread);
  158. furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
  159. furi_hal_subghz_sleep();
  160. }
  161. bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t step) {
  162. furi_assert(instance);
  163. if(!instance->initiated) {
  164. FURI_LOG_W(TAG, "Worker not init!");
  165. return false;
  166. }
  167. if(instance->worker_running) {
  168. FURI_LOG_W(TAG, "Worker in running state!");
  169. return false;
  170. }
  171. if(instance->state != SubBruteWorkerStateReady &&
  172. instance->state != SubBruteWorkerStateFinished) {
  173. FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
  174. return false;
  175. }
  176. uint32_t ticks = furi_get_tick();
  177. if((ticks - instance->last_time_tx_data) < SUBBRUTE_MANUAL_TRANSMIT_INTERVAL) {
  178. #if FURI_DEBUG
  179. FURI_LOG_D(TAG, "Need to wait, current: %ld", ticks - instance->last_time_tx_data);
  180. #endif
  181. return false;
  182. }
  183. instance->last_time_tx_data = ticks;
  184. instance->step = step;
  185. bool result;
  186. instance->protocol_name = subbrute_protocol_file(instance->file);
  187. FlipperFormat* flipper_format = flipper_format_string_alloc();
  188. Stream* stream = flipper_format_get_raw_stream(flipper_format);
  189. stream_clean(stream);
  190. if(instance->attack == SubBruteAttackLoadFile) {
  191. subbrute_protocol_file_payload(
  192. stream,
  193. step,
  194. instance->bits,
  195. instance->te,
  196. instance->repeat,
  197. instance->load_index,
  198. instance->file_key);
  199. } else {
  200. subbrute_protocol_default_payload(
  201. stream, step, instance->bits, instance->te, instance->repeat);
  202. }
  203. // size_t written = stream_write_string(stream, payload);
  204. // if(written <= 0) {
  205. // FURI_LOG_W(TAG, "Error creating packet! EXIT");
  206. // result = false;
  207. // } else {
  208. subbrute_worker_subghz_transmit(instance, flipper_format);
  209. result = true;
  210. #if FURI_DEBUG
  211. FURI_LOG_D(TAG, "Manual transmit done");
  212. #endif
  213. // }
  214. flipper_format_free(flipper_format);
  215. // furi_string_free(payload);
  216. return result;
  217. }
  218. bool subbrute_worker_is_running(SubBruteWorker* instance) {
  219. return instance->worker_running;
  220. }
  221. bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance) {
  222. furi_assert(instance);
  223. if(!instance->initiated) {
  224. FURI_LOG_W(TAG, "Worker not init!");
  225. return false;
  226. }
  227. return !instance->worker_running && instance->state != SubBruteWorkerStateIDLE &&
  228. instance->state != SubBruteWorkerStateTx &&
  229. ((furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_MANUAL_TRANSMIT_INTERVAL);
  230. }
  231. void subbrute_worker_set_callback(
  232. SubBruteWorker* instance,
  233. SubBruteWorkerCallback callback,
  234. void* context) {
  235. furi_assert(instance);
  236. instance->callback = callback;
  237. instance->context = context;
  238. }
  239. void subbrute_worker_subghz_transmit(SubBruteWorker* instance, FlipperFormat* flipper_format) {
  240. while(instance->transmit_mode) {
  241. furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
  242. }
  243. instance->transmit_mode = true;
  244. if(instance->transmitter != NULL) {
  245. subghz_transmitter_free(instance->transmitter);
  246. instance->transmitter = NULL;
  247. }
  248. instance->transmitter =
  249. subghz_transmitter_alloc_init(instance->environment, instance->protocol_name);
  250. subghz_transmitter_deserialize(instance->transmitter, flipper_format);
  251. furi_hal_subghz_reset();
  252. furi_hal_subghz_load_preset(instance->preset);
  253. furi_hal_subghz_set_frequency_and_path(instance->frequency);
  254. furi_hal_subghz_start_async_tx(subghz_transmitter_yield, instance->transmitter);
  255. while(!furi_hal_subghz_is_async_tx_complete()) {
  256. furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
  257. }
  258. furi_hal_subghz_stop_async_tx();
  259. furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
  260. furi_hal_subghz_sleep();
  261. subghz_transmitter_free(instance->transmitter);
  262. instance->transmitter = NULL;
  263. instance->transmit_mode = false;
  264. }
  265. void subbrute_worker_send_callback(SubBruteWorker* instance) {
  266. if(instance->callback != NULL) {
  267. instance->callback(instance->context, instance->state);
  268. }
  269. }
  270. /**
  271. * Entrypoint for worker
  272. *
  273. * @param context SubBruteWorker*
  274. * @return 0 if ok
  275. */
  276. int32_t subbrute_worker_thread(void* context) {
  277. furi_assert(context);
  278. SubBruteWorker* instance = (SubBruteWorker*)context;
  279. if(!instance->worker_running) {
  280. FURI_LOG_W(TAG, "Worker is not set to running state!");
  281. return -1;
  282. }
  283. if(instance->state != SubBruteWorkerStateReady &&
  284. instance->state != SubBruteWorkerStateFinished) {
  285. FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
  286. return -2;
  287. }
  288. #ifdef FURI_DEBUG
  289. FURI_LOG_I(TAG, "Worker start");
  290. #endif
  291. SubBruteWorkerState local_state = instance->state = SubBruteWorkerStateTx;
  292. subbrute_worker_send_callback(instance);
  293. instance->protocol_name = subbrute_protocol_file(instance->file);
  294. FlipperFormat* flipper_format = flipper_format_string_alloc();
  295. Stream* stream = flipper_format_get_raw_stream(flipper_format);
  296. while(instance->worker_running) {
  297. stream_clean(stream);
  298. if(instance->attack == SubBruteAttackLoadFile) {
  299. subbrute_protocol_file_payload(
  300. stream,
  301. instance->step,
  302. instance->bits,
  303. instance->te,
  304. instance->repeat,
  305. instance->load_index,
  306. instance->file_key);
  307. } else {
  308. subbrute_protocol_default_payload(
  309. stream, instance->step, instance->bits, instance->te, instance->repeat);
  310. }
  311. #ifdef FURI_DEBUG
  312. //FURI_LOG_I(TAG, "Payload: %s", furi_string_get_cstr(payload));
  313. //furi_delay_ms(SUBBRUTE_MANUAL_TRANSMIT_INTERVAL / 4);
  314. #endif
  315. // size_t written = stream_write_stream_write_string(stream, payload);
  316. // if(written <= 0) {
  317. // FURI_LOG_W(TAG, "Error creating packet! BREAK");
  318. // instance->worker_running = false;
  319. // local_state = SubBruteWorkerStateIDLE;
  320. // furi_string_free(payload);
  321. // break;
  322. // }
  323. subbrute_worker_subghz_transmit(instance, flipper_format);
  324. if(instance->step + 1 > instance->max_value) {
  325. #ifdef FURI_DEBUG
  326. FURI_LOG_I(TAG, "Worker finished to end");
  327. #endif
  328. local_state = SubBruteWorkerStateFinished;
  329. // furi_string_free(payload);
  330. break;
  331. }
  332. instance->step++;
  333. // furi_string_free(payload);
  334. furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
  335. }
  336. flipper_format_free(flipper_format);
  337. instance->worker_running = false; // Because we have error states
  338. instance->state = local_state == SubBruteWorkerStateTx ? SubBruteWorkerStateReady :
  339. local_state;
  340. subbrute_worker_send_callback(instance);
  341. #ifdef FURI_DEBUG
  342. FURI_LOG_I(TAG, "Worker stop");
  343. #endif
  344. return 0;
  345. }