|
|
@@ -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;
|
|
|
}
|