1+ #include "subbrute_worker.h"
2+
3+ #include <subghz/environment.h>
4+ #include <subghz/transmitter.h>
5+ #include <flipper_format_i.h>
6+
7+ #define TAG "SubBruteWorker"
8+
9+ struct SubBruteWorker {
10+ FuriThread * thread ;
11+ volatile bool worker_running ;
12+ volatile bool worker_manual_mode ;
13+ bool is_manual_init ;
14+
15+ SubGhzEnvironment * environment ;
16+ SubGhzTransmitter * transmitter ;
17+ FlipperFormat * flipper_format ;
18+
19+ uint32_t last_time_tx_data ;
20+
21+ // Preset and frequency needed
22+ FuriHalSubGhzPreset preset ;
23+ uint32_t frequency ;
24+ string_t protocol_name ;
25+
26+ //SubBruteWorkerCallback callback;
27+ //void* context;
28+ };
29+
30+ /** Taken from subghz_tx_rx_worker.c */
31+ #define SUBBRUTE_TXRX_WORKER_BUF_SIZE 2048
32+ #define SUBBRUTE_TXRX_WORKER_MAX_TXRX_SIZE 60
33+ #define SUBBRUTE_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40
34+ #define SUBBRUTE_TX_TIMEOUT 50
35+ #define SUBBRUTE_SEND_DELAY 260
36+
37+ /**
38+ * Entrypoint for worker
39+ *
40+ * @param context SubBruteWorker*
41+ * @return 0 if ok
42+ */
43+ int32_t subbrute_worker_thread (void * context ) {
44+ furi_assert (context );
45+ SubBruteWorker * instance = (SubBruteWorker * )context ;
46+
47+ if (!instance -> worker_running ) {
48+ FURI_LOG_W (TAG , "Worker is not set to running state!" );
49+ return -1 ;
50+ }
51+ #ifdef FURI_DEBUG
52+ FURI_LOG_I (TAG , "Worker start" );
53+ #endif
54+
55+ instance -> environment = subghz_environment_alloc ();
56+ instance -> transmitter = subghz_transmitter_alloc_init (
57+ instance -> environment , string_get_cstr (instance -> protocol_name ));
58+
59+ furi_hal_subghz_reset ();
60+ furi_hal_subghz_load_preset (instance -> preset );
61+ instance -> frequency = furi_hal_subghz_set_frequency_and_path (instance -> frequency );
62+
63+ furi_hal_gpio_init (& gpio_cc1101_g0 , GpioModeOutputPushPull , GpioPullNo , GpioSpeedLow );
64+ furi_hal_gpio_write (& gpio_cc1101_g0 , true);
65+
66+ // Set ready to transmit value
67+ instance -> last_time_tx_data = furi_get_tick () - SUBBRUTE_SEND_DELAY ;
68+
69+ while (instance -> worker_running ) {
70+ // Transmit
71+ if (!furi_hal_subghz_tx ()) {
72+ FURI_LOG_E (TAG , "Cannot transmit!" );
73+ break ;
74+ }
75+ furi_delay_ms (SUBBRUTE_TX_TIMEOUT );
76+ }
77+
78+ furi_hal_subghz_set_path (FuriHalSubGhzPathIsolate );
79+ furi_hal_subghz_sleep ();
80+
81+ subghz_transmitter_free (instance -> transmitter );
82+ instance -> transmitter = NULL ;
83+ subghz_environment_free (instance -> environment );
84+ instance -> environment = NULL ;
85+
86+ #ifdef FURI_DEBUG
87+ FURI_LOG_I (TAG , "Worker stop" );
88+ #endif
89+ return 0 ;
90+ }
91+
92+ SubBruteWorker * subbrute_worker_alloc () {
93+ SubBruteWorker * instance = malloc (sizeof (SubBruteWorker ));
94+
95+ instance -> thread = furi_thread_alloc ();
96+ furi_thread_set_name (instance -> thread , "SubBruteAttackWorker" );
97+ furi_thread_set_stack_size (instance -> thread , 2048 );
98+ furi_thread_set_context (instance -> thread , instance );
99+ furi_thread_set_callback (instance -> thread , subbrute_worker_thread );
100+
101+ //instance->status = SubBruteWorkerStatusIDLE;
102+ instance -> worker_running = false;
103+ instance -> worker_manual_mode = false;
104+
105+ instance -> flipper_format = flipper_format_string_alloc ();
106+ string_init (instance -> protocol_name );
107+
108+ return instance ;
109+ }
110+
111+ void subbrute_worker_free (SubBruteWorker * instance ) {
112+ furi_assert (instance );
113+ furi_assert (!instance -> worker_running );
114+
115+ if (instance -> transmitter != NULL ) {
116+ subghz_transmitter_free (instance -> transmitter );
117+ instance -> transmitter = NULL ;
118+ }
119+
120+ if (instance -> environment != NULL ) {
121+ subghz_environment_free (instance -> environment );
122+ instance -> environment = NULL ;
123+ }
124+
125+ furi_thread_free (instance -> thread );
126+ flipper_format_free (instance -> flipper_format );
127+
128+ string_clear (instance -> protocol_name );
129+
130+ free (instance );
131+ }
132+
133+ bool subbrute_worker_start (
134+ SubBruteWorker * instance ,
135+ uint32_t frequency ,
136+ FuriHalSubGhzPreset preset ,
137+ const char * protocol_name ) {
138+ furi_assert (instance );
139+
140+ if (instance -> worker_manual_mode ) {
141+ return false;
142+ }
143+
144+ instance -> frequency = frequency ;
145+ instance -> preset = preset ;
146+
147+ string_clear (instance -> protocol_name );
148+ string_init_printf (instance -> protocol_name , "%s" , protocol_name );
149+
150+ bool res = false;
151+
152+ furi_hal_subghz_reset ();
153+ furi_hal_subghz_idle ();
154+ furi_hal_subghz_load_preset (instance -> preset );
155+
156+ furi_hal_subghz_set_frequency_and_path (instance -> frequency );
157+ furi_hal_subghz_flush_rx ();
158+
159+ if (furi_hal_subghz_is_tx_allowed (frequency )) {
160+ instance -> frequency = frequency ;
161+ res = true;
162+ }
163+ instance -> worker_running = res ;
164+
165+ #ifdef FURI_DEBUG
166+ FURI_LOG_I (TAG , "Frequency: %d" , frequency );
167+ #endif
168+ instance -> preset = preset ;
169+
170+ furi_thread_start (instance -> thread );
171+
172+ return res ;
173+ }
174+
175+ void subbrute_worker_stop (SubBruteWorker * instance ) {
176+ furi_assert (instance );
177+
178+ instance -> worker_running = false;
179+
180+ furi_thread_join (instance -> thread );
181+
182+ furi_hal_subghz_set_path (FuriHalSubGhzPathIsolate );
183+ furi_hal_subghz_sleep ();
184+ }
185+
186+ bool subbrute_worker_is_running (SubBruteWorker * instance ) {
187+ furi_assert (instance );
188+
189+ return instance -> worker_running ;
190+ }
191+
192+ bool subbrute_worker_can_transmit (SubBruteWorker * instance ) {
193+ furi_assert (instance );
194+
195+ return (furi_get_tick () - instance -> last_time_tx_data ) > SUBBRUTE_SEND_DELAY ;
196+ }
197+
198+ bool subbrute_worker_transmit (SubBruteWorker * instance , const char * payload ) {
199+ furi_assert (instance );
200+ furi_assert (instance -> worker_running );
201+
202+ if (!subbrute_worker_can_transmit (instance )) {
203+ FURI_LOG_E (TAG , "Too early to transmit" );
204+
205+ return false;
206+ }
207+ instance -> last_time_tx_data = furi_get_tick ();
208+
209+ #ifdef FURI_DEBUG
210+ //FURI_LOG_D(TAG, "payload: %s", payload);
211+ #endif
212+
213+ Stream * stream = flipper_format_get_raw_stream (instance -> flipper_format );
214+ stream_clean (stream );
215+ stream_write_cstring (stream , payload );
216+ subghz_transmitter_deserialize (instance -> transmitter , instance -> flipper_format );
217+
218+ return true;
219+ }
220+
221+ bool subbrute_worker_init_manual_transmit (
222+ SubBruteWorker * instance ,
223+ uint32_t frequency ,
224+ FuriHalSubGhzPreset preset ,
225+ const char * protocol_name ) {
226+ #ifdef FURI_DEBUG
227+ FURI_LOG_D (
228+ TAG ,
229+ "subbrute_worker_init_manual_transmit. frequency: %d, protocol: %s" ,
230+ frequency ,
231+ protocol_name );
232+ #endif
233+ if (instance -> worker_manual_mode || !subbrute_worker_can_transmit (instance )) {
234+ #ifdef FURI_DEBUG
235+ FURI_LOG_D (TAG , "cannot transmit" );
236+ #endif
237+ return false;
238+ }
239+ if (instance -> worker_running ) {
240+ #ifdef FURI_DEBUG
241+ FURI_LOG_D (TAG , "subbrute_worker_stop" );
242+ #endif
243+ subbrute_worker_stop (instance );
244+ }
245+
246+ // Not transmit at this period
247+ instance -> worker_manual_mode = true;
248+
249+ if (instance -> is_manual_init ) {
250+ FURI_LOG_E (TAG , "Trying to setup without normally shutdown prev transmit session!" );
251+ subbrute_worker_manual_transmit_stop (instance );
252+ }
253+
254+ instance -> preset = preset ;
255+ instance -> frequency = frequency ;
256+
257+ string_clear (instance -> protocol_name );
258+ string_init_printf (instance -> protocol_name , "%s" , protocol_name );
259+
260+ furi_hal_subghz_reset ();
261+ furi_hal_subghz_idle ();
262+ furi_hal_subghz_load_preset (instance -> preset );
263+
264+ furi_hal_subghz_set_frequency_and_path (instance -> frequency );
265+ furi_hal_subghz_flush_rx ();
266+
267+ if (!furi_hal_subghz_is_tx_allowed (frequency )) {
268+ FURI_LOG_E (TAG , "Frequency: %d invalid!" , frequency );
269+
270+ instance -> frequency = frequency ;
271+ instance -> worker_manual_mode = false;
272+ return false;
273+ }
274+
275+ #ifdef FURI_DEBUG
276+ FURI_LOG_I (TAG , "Frequency: %d" , frequency );
277+ #endif
278+
279+ instance -> environment = subghz_environment_alloc ();
280+ instance -> transmitter = subghz_transmitter_alloc_init (
281+ instance -> environment , string_get_cstr (instance -> protocol_name ));
282+
283+ furi_hal_subghz_reset ();
284+ furi_hal_subghz_load_preset (instance -> preset );
285+ instance -> frequency = furi_hal_subghz_set_frequency_and_path (frequency );
286+
287+ furi_hal_subghz_set_path (FuriHalSubGhzPathIsolate );
288+ furi_hal_subghz_sleep ();
289+ subghz_transmitter_free (instance -> transmitter );
290+ instance -> transmitter = NULL ;
291+
292+ instance -> worker_manual_mode = false;
293+ instance -> is_manual_init = true;
294+
295+ return true;
296+ }
297+
298+ void subbrute_worker_manual_transmit_stop (SubBruteWorker * instance ) {
299+ #ifdef FURI_DEBUG
300+ FURI_LOG_D (TAG , "subbrute_worker_manual_transmit_stop" );
301+ #endif
302+ if (!instance -> is_manual_init ) {
303+ return ;
304+ }
305+
306+ furi_hal_subghz_idle ();
307+ furi_hal_subghz_sleep ();
308+
309+ if (instance -> transmitter != NULL ) {
310+ subghz_transmitter_free (instance -> transmitter );
311+ instance -> transmitter = NULL ;
312+ }
313+ subghz_environment_free (instance -> environment );
314+ instance -> environment = NULL ;
315+
316+ instance -> is_manual_init = false;
317+ }
318+
319+ bool subbrute_worker_manual_transmit (SubBruteWorker * instance , const char * payload ) {
320+ furi_assert (instance );
321+
322+ if (instance -> worker_manual_mode || !subbrute_worker_can_transmit (instance )) {
323+ #ifdef FURI_DEBUG
324+ FURI_LOG_D (TAG , "cannot transmit" );
325+ #endif
326+ return false;
327+ }
328+ if (instance -> worker_running ) {
329+ #ifdef FURI_DEBUG
330+ FURI_LOG_D (TAG , "subbrute_worker_stop" );
331+ #endif
332+ subbrute_worker_stop (instance );
333+ }
334+ if (!instance -> is_manual_init ) {
335+ FURI_LOG_E (TAG , "Manually transmit doesn't set!" );
336+ return false;
337+ }
338+
339+ instance -> last_time_tx_data = furi_get_tick ();
340+ instance -> worker_manual_mode = true;
341+
342+ Stream * stream = flipper_format_get_raw_stream (instance -> flipper_format );
343+ stream_clean (stream );
344+ stream_write_cstring (stream , payload );
345+
346+ instance -> transmitter = subghz_transmitter_alloc_init (
347+ instance -> environment , string_get_cstr (instance -> protocol_name ));
348+ subghz_transmitter_deserialize (instance -> transmitter , instance -> flipper_format );
349+ furi_hal_subghz_reset ();
350+ furi_hal_subghz_load_preset (instance -> preset );
351+ instance -> frequency = furi_hal_subghz_set_frequency_and_path (instance -> frequency );
352+
353+ furi_hal_subghz_start_async_tx (subghz_transmitter_yield , instance -> transmitter );
354+
355+ while (!furi_hal_subghz_is_async_tx_complete ()) {
356+ furi_delay_ms (SUBBRUTE_TX_TIMEOUT );
357+ }
358+ furi_hal_subghz_stop_async_tx ();
359+
360+ furi_hal_subghz_set_path (FuriHalSubGhzPathIsolate );
361+ furi_hal_subghz_sleep ();
362+ subghz_transmitter_free (instance -> transmitter );
363+ instance -> transmitter = NULL ;
364+
365+ stream_clean (stream );
366+
367+ instance -> worker_manual_mode = false;
368+
369+ return true;
370+ }
0 commit comments