Просмотр исходного кода

BadUsb: STRINGDELAY feature, worker signal handling refactoring (#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>
n30f0x 2 лет назад
Родитель
Сommit
eaf965c66f

+ 61 - 20
applications/main/bad_usb/bad_usb_script.c

@@ -32,6 +32,7 @@ struct BadUsbScript {
     FuriString* file_path;
     uint32_t defdelay;
     uint16_t layout[128];
+    uint32_t stringdelay;
     FuriThread* thread;
     uint8_t file_buf[FILE_BUFFER_LEN + 1];
     uint8_t buf_start;
@@ -113,6 +114,8 @@ static const char ducky_cmd_delay[] = {"DELAY "};
 static const char ducky_cmd_string[] = {"STRING "};
 static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "};
 static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "};
+static const char ducky_cmd_stringdelay_1[] = {"STRINGDELAY "};
+static const char ducky_cmd_stringdelay_2[] = {"STRING_DELAY "};
 static const char ducky_cmd_repeat[] = {"REPEAT "};
 static const char ducky_cmd_sysrq[] = {"SYSRQ "};
 
@@ -211,14 +214,19 @@ static bool ducky_altstring(const char* param) {
 
 static bool ducky_string(BadUsbScript* bad_usb, const char* param) {
     uint32_t i = 0;
+
     while(param[i] != '\0') {
         uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_usb, param[i]);
         if(keycode != HID_KEYBOARD_NONE) {
             furi_hal_hid_kb_press(keycode);
             furi_hal_hid_kb_release(keycode);
+            if(bad_usb->stringdelay > 0) {
+                furi_delay_ms(bad_usb->stringdelay);
+            }
         }
         i++;
     }
+    bad_usb->stringdelay = 0;
     return true;
 }
 
@@ -277,6 +285,20 @@ static int32_t
             snprintf(error, error_len, "Invalid number %s", line_tmp);
         }
         return (state) ? (0) : SCRIPT_STATE_ERROR;
+    } else if(
+        (strncmp(line_tmp, ducky_cmd_stringdelay_1, strlen(ducky_cmd_stringdelay_1)) == 0) ||
+        (strncmp(line_tmp, ducky_cmd_stringdelay_2, strlen(ducky_cmd_stringdelay_2)) == 0)) {
+        //STRINGDELAY, finally it's here
+        line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
+        state = ducky_get_number(line_tmp, &bad_usb->stringdelay);
+        if((state) && (bad_usb->stringdelay > 0)) {
+            return state;
+        }
+        if(error != NULL) {
+            snprintf(error, error_len, "Invalid number %s", line_tmp);
+        }
+        return SCRIPT_STATE_ERROR;
+
     } else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) {
         // STRING
         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) {
         furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtDisconnect);
 }
 
+static uint32_t bad_usb_flags_get(uint32_t flags_mask, uint32_t timeout) {
+    uint32_t flags = furi_thread_flags_get();
+    furi_check((flags & FuriFlagError) == 0);
+    if(flags == 0) {
+        flags = furi_thread_flags_wait(flags_mask, FuriFlagWaitAny, timeout);
+        furi_check(((flags & FuriFlagError) == 0) || (flags == FuriFlagErrorTimeout));
+    } else {
+        uint32_t state = furi_thread_flags_clear(flags);
+        furi_check((state & FuriFlagError) == 0);
+    }
+    return flags;
+}
+
 static int32_t bad_usb_worker(void* context) {
     BadUsbScript* bad_usb = context;
 
@@ -520,11 +555,9 @@ static int32_t bad_usb_worker(void* context) {
             bad_usb->st.state = worker_state;
 
         } else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
-            uint32_t flags = furi_thread_flags_wait(
-                WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
-                FuriFlagWaitAny,
-                FuriWaitForever);
-            furi_check((flags & FuriFlagError) == 0);
+            uint32_t flags = bad_usb_flags_get(
+                WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
+
             if(flags & WorkerEvtEnd) {
                 break;
             } else if(flags & WorkerEvtConnect) {
@@ -535,11 +568,9 @@ static int32_t bad_usb_worker(void* context) {
             bad_usb->st.state = worker_state;
 
         } else if(worker_state == BadUsbStateIdle) { // State: ready to start
-            uint32_t flags = furi_thread_flags_wait(
-                WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect,
-                FuriFlagWaitAny,
-                FuriWaitForever);
-            furi_check((flags & FuriFlagError) == 0);
+            uint32_t flags = bad_usb_flags_get(
+                WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriWaitForever);
+
             if(flags & WorkerEvtEnd) {
                 break;
             } else if(flags & WorkerEvtToggle) { // Start executing script
@@ -548,6 +579,7 @@ static int32_t bad_usb_worker(void* context) {
                 bad_usb->buf_len = 0;
                 bad_usb->st.line_cur = 0;
                 bad_usb->defdelay = 0;
+                bad_usb->stringdelay = 0;
                 bad_usb->repeat_cnt = 0;
                 bad_usb->file_end = false;
                 storage_file_seek(script_file, 0, true);
@@ -558,11 +590,9 @@ static int32_t bad_usb_worker(void* context) {
             bad_usb->st.state = worker_state;
 
         } else if(worker_state == BadUsbStateWillRun) { // State: start on connection
-            uint32_t flags = furi_thread_flags_wait(
-                WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
-                FuriFlagWaitAny,
-                FuriWaitForever);
-            furi_check((flags & FuriFlagError) == 0);
+            uint32_t flags = bad_usb_flags_get(
+                WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
+
             if(flags & WorkerEvtEnd) {
                 break;
             } else if(flags & WorkerEvtConnect) { // Start executing script
@@ -571,12 +601,22 @@ static int32_t bad_usb_worker(void* context) {
                 bad_usb->buf_len = 0;
                 bad_usb->st.line_cur = 0;
                 bad_usb->defdelay = 0;
+                bad_usb->stringdelay = 0;
                 bad_usb->repeat_cnt = 0;
                 bad_usb->file_end = false;
                 storage_file_seek(script_file, 0, true);
                 // extra time for PC to recognize Flipper as keyboard
-                furi_thread_flags_wait(0, FuriFlagWaitAny, 1500);
-                worker_state = BadUsbStateRunning;
+                flags = furi_thread_flags_wait(
+                    WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtToggle,
+                    FuriFlagWaitAny | FuriFlagNoClear,
+                    1500);
+                if(flags == FuriFlagErrorTimeout) {
+                    // If nothing happened - start script execution
+                    worker_state = BadUsbStateRunning;
+                } else if(flags & WorkerEvtToggle) {
+                    worker_state = BadUsbStateIdle;
+                    furi_thread_flags_clear(WorkerEvtToggle);
+                }
             } else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
                 worker_state = BadUsbStateNotConnected;
             }
@@ -586,6 +626,7 @@ static int32_t bad_usb_worker(void* context) {
             uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
             uint32_t flags = furi_thread_flags_wait(
                 WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur);
+
             delay_val -= delay_cur;
             if(!(flags & FuriFlagError)) {
                 if(flags & WorkerEvtEnd) {
@@ -629,9 +670,9 @@ static int32_t bad_usb_worker(void* context) {
         } else if(
             (worker_state == BadUsbStateFileError) ||
             (worker_state == BadUsbStateScriptError)) { // State: error
-            uint32_t flags = furi_thread_flags_wait(
-                WorkerEvtEnd, FuriFlagWaitAny, FuriWaitForever); // Waiting for exit command
-            furi_check((flags & FuriFlagError) == 0);
+            uint32_t flags =
+                bad_usb_flags_get(WorkerEvtEnd, FuriWaitForever); // Waiting for exit command
+
             if(flags & WorkerEvtEnd) {
                 break;
             }

+ 0 - 2
applications/main/bad_usb/scenes/bad_usb_scene_file_select.c

@@ -22,7 +22,6 @@ static bool bad_usb_file_select(BadUsbApp* bad_usb) {
 void bad_usb_scene_file_select_on_enter(void* context) {
     BadUsbApp* bad_usb = context;
 
-    furi_hal_usb_disable();
     if(bad_usb->bad_usb_script) {
         bad_usb_script_close(bad_usb->bad_usb_script);
         bad_usb->bad_usb_script = NULL;
@@ -34,7 +33,6 @@ void bad_usb_scene_file_select_on_enter(void* context) {
 
         scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneWork);
     } else {
-        furi_hal_usb_enable();
         view_dispatcher_stop(bad_usb->view_dispatcher);
     }
 }

+ 8 - 0
documentation/file_formats/BadUsbScriptFormat.md

@@ -75,6 +75,14 @@ Can be combined with a special key command or a single character.
 | ------- | ----------- | ----------------- |
 | STRING  | Text string | Print text string |
 
+## String delay
+
+Delay between keypresses.
+|Command|Parameters|Notes|
+|-|-|-|
+|STRING_DELAY|Delay value in ms|Applied once to next appearing string|
+|STRINGDELAY|Delay value in ms|Same as STRING_DELAY|
+
 ## Repeat
 
 | Command | Parameters                   | Notes                   |