Skip to content

Commit 9cffa3e

Browse files
n30f0xskotopesnminaylov
authored andcommitted
BadUsb: STRINGDELAY feature, worker signal handling refactoring (flipperdevices#2269)
* BadUsb: Added stringdelay feature * BadUsb: added stringdelay feature, fixed delay * BadUsb: fix cursed delay structure * BadUsb: long delay check added * BadUsb: long delay distribution * furi_delay_ms(0) edgecase fix, add documentation entry * additional documentation entry * BadUsb: get rid of bad logic, fixed documentation * BadUSB script: fix events handling * Delay value fix * Script execution fix Co-authored-by: あく <alleteam@gmail.com> Co-authored-by: nminaylov <nm29719@gmail.com>
1 parent 1d97a6a commit 9cffa3e

File tree

3 files changed

+69
-22
lines changed

3 files changed

+69
-22
lines changed

applications/main/bad_usb/bad_usb_script.c

+61-20
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct BadUsbScript {
3232
FuriString* file_path;
3333
uint32_t defdelay;
3434
uint16_t layout[128];
35+
uint32_t stringdelay;
3536
FuriThread* thread;
3637
uint8_t file_buf[FILE_BUFFER_LEN + 1];
3738
uint8_t buf_start;
@@ -113,6 +114,8 @@ static const char ducky_cmd_delay[] = {"DELAY "};
113114
static const char ducky_cmd_string[] = {"STRING "};
114115
static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "};
115116
static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "};
117+
static const char ducky_cmd_stringdelay_1[] = {"STRINGDELAY "};
118+
static const char ducky_cmd_stringdelay_2[] = {"STRING_DELAY "};
116119
static const char ducky_cmd_repeat[] = {"REPEAT "};
117120
static const char ducky_cmd_sysrq[] = {"SYSRQ "};
118121

@@ -211,14 +214,19 @@ static bool ducky_altstring(const char* param) {
211214

212215
static bool ducky_string(BadUsbScript* bad_usb, const char* param) {
213216
uint32_t i = 0;
217+
214218
while(param[i] != '\0') {
215219
uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_usb, param[i]);
216220
if(keycode != HID_KEYBOARD_NONE) {
217221
furi_hal_hid_kb_press(keycode);
218222
furi_hal_hid_kb_release(keycode);
223+
if(bad_usb->stringdelay > 0) {
224+
furi_delay_ms(bad_usb->stringdelay);
225+
}
219226
}
220227
i++;
221228
}
229+
bad_usb->stringdelay = 0;
222230
return true;
223231
}
224232

@@ -277,6 +285,20 @@ static int32_t
277285
snprintf(error, error_len, "Invalid number %s", line_tmp);
278286
}
279287
return (state) ? (0) : SCRIPT_STATE_ERROR;
288+
} else if(
289+
(strncmp(line_tmp, ducky_cmd_stringdelay_1, strlen(ducky_cmd_stringdelay_1)) == 0) ||
290+
(strncmp(line_tmp, ducky_cmd_stringdelay_2, strlen(ducky_cmd_stringdelay_2)) == 0)) {
291+
//STRINGDELAY, finally it's here
292+
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
293+
state = ducky_get_number(line_tmp, &bad_usb->stringdelay);
294+
if((state) && (bad_usb->stringdelay > 0)) {
295+
return state;
296+
}
297+
if(error != NULL) {
298+
snprintf(error, error_len, "Invalid number %s", line_tmp);
299+
}
300+
return SCRIPT_STATE_ERROR;
301+
280302
} else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) {
281303
// STRING
282304
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
@@ -484,6 +506,19 @@ static void bad_usb_hid_state_callback(bool state, void* context) {
484506
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtDisconnect);
485507
}
486508

509+
static uint32_t bad_usb_flags_get(uint32_t flags_mask, uint32_t timeout) {
510+
uint32_t flags = furi_thread_flags_get();
511+
furi_check((flags & FuriFlagError) == 0);
512+
if(flags == 0) {
513+
flags = furi_thread_flags_wait(flags_mask, FuriFlagWaitAny, timeout);
514+
furi_check(((flags & FuriFlagError) == 0) || (flags == FuriFlagErrorTimeout));
515+
} else {
516+
uint32_t state = furi_thread_flags_clear(flags);
517+
furi_check((state & FuriFlagError) == 0);
518+
}
519+
return flags;
520+
}
521+
487522
static int32_t bad_usb_worker(void* context) {
488523
BadUsbScript* bad_usb = context;
489524

@@ -520,11 +555,9 @@ static int32_t bad_usb_worker(void* context) {
520555
bad_usb->st.state = worker_state;
521556

522557
} else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
523-
uint32_t flags = furi_thread_flags_wait(
524-
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
525-
FuriFlagWaitAny,
526-
FuriWaitForever);
527-
furi_check((flags & FuriFlagError) == 0);
558+
uint32_t flags = bad_usb_flags_get(
559+
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
560+
528561
if(flags & WorkerEvtEnd) {
529562
break;
530563
} else if(flags & WorkerEvtConnect) {
@@ -535,11 +568,9 @@ static int32_t bad_usb_worker(void* context) {
535568
bad_usb->st.state = worker_state;
536569

537570
} else if(worker_state == BadUsbStateIdle) { // State: ready to start
538-
uint32_t flags = furi_thread_flags_wait(
539-
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect,
540-
FuriFlagWaitAny,
541-
FuriWaitForever);
542-
furi_check((flags & FuriFlagError) == 0);
571+
uint32_t flags = bad_usb_flags_get(
572+
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriWaitForever);
573+
543574
if(flags & WorkerEvtEnd) {
544575
break;
545576
} else if(flags & WorkerEvtToggle) { // Start executing script
@@ -548,6 +579,7 @@ static int32_t bad_usb_worker(void* context) {
548579
bad_usb->buf_len = 0;
549580
bad_usb->st.line_cur = 0;
550581
bad_usb->defdelay = 0;
582+
bad_usb->stringdelay = 0;
551583
bad_usb->repeat_cnt = 0;
552584
bad_usb->file_end = false;
553585
storage_file_seek(script_file, 0, true);
@@ -558,11 +590,9 @@ static int32_t bad_usb_worker(void* context) {
558590
bad_usb->st.state = worker_state;
559591

560592
} else if(worker_state == BadUsbStateWillRun) { // State: start on connection
561-
uint32_t flags = furi_thread_flags_wait(
562-
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
563-
FuriFlagWaitAny,
564-
FuriWaitForever);
565-
furi_check((flags & FuriFlagError) == 0);
593+
uint32_t flags = bad_usb_flags_get(
594+
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
595+
566596
if(flags & WorkerEvtEnd) {
567597
break;
568598
} else if(flags & WorkerEvtConnect) { // Start executing script
@@ -571,12 +601,22 @@ static int32_t bad_usb_worker(void* context) {
571601
bad_usb->buf_len = 0;
572602
bad_usb->st.line_cur = 0;
573603
bad_usb->defdelay = 0;
604+
bad_usb->stringdelay = 0;
574605
bad_usb->repeat_cnt = 0;
575606
bad_usb->file_end = false;
576607
storage_file_seek(script_file, 0, true);
577608
// extra time for PC to recognize Flipper as keyboard
578-
furi_thread_flags_wait(0, FuriFlagWaitAny, 1500);
579-
worker_state = BadUsbStateRunning;
609+
flags = furi_thread_flags_wait(
610+
WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtToggle,
611+
FuriFlagWaitAny | FuriFlagNoClear,
612+
1500);
613+
if(flags == FuriFlagErrorTimeout) {
614+
// If nothing happened - start script execution
615+
worker_state = BadUsbStateRunning;
616+
} else if(flags & WorkerEvtToggle) {
617+
worker_state = BadUsbStateIdle;
618+
furi_thread_flags_clear(WorkerEvtToggle);
619+
}
580620
} else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
581621
worker_state = BadUsbStateNotConnected;
582622
}
@@ -586,6 +626,7 @@ static int32_t bad_usb_worker(void* context) {
586626
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
587627
uint32_t flags = furi_thread_flags_wait(
588628
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur);
629+
589630
delay_val -= delay_cur;
590631
if(!(flags & FuriFlagError)) {
591632
if(flags & WorkerEvtEnd) {
@@ -629,9 +670,9 @@ static int32_t bad_usb_worker(void* context) {
629670
} else if(
630671
(worker_state == BadUsbStateFileError) ||
631672
(worker_state == BadUsbStateScriptError)) { // State: error
632-
uint32_t flags = furi_thread_flags_wait(
633-
WorkerEvtEnd, FuriFlagWaitAny, FuriWaitForever); // Waiting for exit command
634-
furi_check((flags & FuriFlagError) == 0);
673+
uint32_t flags =
674+
bad_usb_flags_get(WorkerEvtEnd, FuriWaitForever); // Waiting for exit command
675+
635676
if(flags & WorkerEvtEnd) {
636677
break;
637678
}

applications/main/bad_usb/scenes/bad_usb_scene_file_select.c

-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ static bool bad_usb_file_select(BadUsbApp* bad_usb) {
2222
void bad_usb_scene_file_select_on_enter(void* context) {
2323
BadUsbApp* bad_usb = context;
2424

25-
furi_hal_usb_disable();
2625
if(bad_usb->bad_usb_script) {
2726
bad_usb_script_close(bad_usb->bad_usb_script);
2827
bad_usb->bad_usb_script = NULL;
@@ -34,7 +33,6 @@ void bad_usb_scene_file_select_on_enter(void* context) {
3433

3534
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneWork);
3635
} else {
37-
furi_hal_usb_enable();
3836
view_dispatcher_stop(bad_usb->view_dispatcher);
3937
}
4038
}

documentation/file_formats/BadUsbScriptFormat.md

+8
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ Can be combined with a special key command or a single character.
7575
| ------- | ----------- | ----------------- |
7676
| STRING | Text string | Print text string |
7777

78+
## String delay
79+
80+
Delay between keypresses.
81+
|Command|Parameters|Notes|
82+
|-|-|-|
83+
|STRING_DELAY|Delay value in ms|Applied once to next appearing string|
84+
|STRINGDELAY|Delay value in ms|Same as STRING_DELAY|
85+
7886
## Repeat
7987

8088
| Command | Parameters | Notes |

0 commit comments

Comments
 (0)