Skip to content

Commit

Permalink
BadUSB: script execution pause (#2700)
Browse files Browse the repository at this point in the history
Co-authored-by: あく <[email protected]>
  • Loading branch information
nminaylov and skotopes authored May 29, 2023
1 parent f9390e0 commit 66961da
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 46 deletions.
96 changes: 71 additions & 25 deletions applications/main/bad_usb/helpers/ducky_script.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
(((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE)

typedef enum {
WorkerEvtToggle = (1 << 0),
WorkerEvtEnd = (1 << 1),
WorkerEvtConnect = (1 << 2),
WorkerEvtDisconnect = (1 << 3),
WorkerEvtStartStop = (1 << 0),
WorkerEvtPauseResume = (1 << 1),
WorkerEvtEnd = (1 << 2),
WorkerEvtConnect = (1 << 3),
WorkerEvtDisconnect = (1 << 4),
} WorkerEvtFlags;

static const char ducky_cmd_id[] = {"ID"};
Expand Down Expand Up @@ -372,6 +373,7 @@ static int32_t bad_usb_worker(void* context) {
BadUsbScript* bad_usb = context;

BadUsbWorkerState worker_state = BadUsbStateInit;
BadUsbWorkerState pause_state = BadUsbStateRunning;
int32_t delay_val = 0;

FURI_LOG_I(WORKER_TAG, "Init");
Expand Down Expand Up @@ -406,24 +408,24 @@ static int32_t bad_usb_worker(void* context) {

} else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtStartStop, FuriWaitForever);

if(flags & WorkerEvtEnd) {
break;
} else if(flags & WorkerEvtConnect) {
worker_state = BadUsbStateIdle; // Ready to run
} else if(flags & WorkerEvtToggle) {
} else if(flags & WorkerEvtStartStop) {
worker_state = BadUsbStateWillRun; // Will run when USB is connected
}
bad_usb->st.state = worker_state;

} else if(worker_state == BadUsbStateIdle) { // State: ready to start
uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriWaitForever);
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtDisconnect, FuriWaitForever);

if(flags & WorkerEvtEnd) {
break;
} else if(flags & WorkerEvtToggle) { // Start executing script
} else if(flags & WorkerEvtStartStop) { // Start executing script
DOLPHIN_DEED(DolphinDeedBadUsbPlayScript);
delay_val = 0;
bad_usb->buf_len = 0;
Expand All @@ -442,7 +444,7 @@ static int32_t bad_usb_worker(void* context) {

} else if(worker_state == BadUsbStateWillRun) { // State: start on connection
uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtStartStop, FuriWaitForever);

if(flags & WorkerEvtEnd) {
break;
Expand All @@ -458,36 +460,41 @@ static int32_t bad_usb_worker(void* context) {
storage_file_seek(script_file, 0, true);
// extra time for PC to recognize Flipper as keyboard
flags = furi_thread_flags_wait(
WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtToggle,
WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtStartStop,
FuriFlagWaitAny | FuriFlagNoClear,
1500);
if(flags == (unsigned)FuriFlagErrorTimeout) {
// If nothing happened - start script execution
worker_state = BadUsbStateRunning;
} else if(flags & WorkerEvtToggle) {
} else if(flags & WorkerEvtStartStop) {
worker_state = BadUsbStateIdle;
furi_thread_flags_clear(WorkerEvtToggle);
furi_thread_flags_clear(WorkerEvtStartStop);
}
} else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
} else if(flags & WorkerEvtStartStop) { // Cancel scheduled execution
worker_state = BadUsbStateNotConnected;
}
bad_usb->st.state = worker_state;

} else if(worker_state == BadUsbStateRunning) { // State: running
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
uint32_t flags = furi_thread_flags_wait(
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur);
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
FuriFlagWaitAny,
delay_cur);

delay_val -= delay_cur;
if(!(flags & FuriFlagError)) {
if(flags & WorkerEvtEnd) {
break;
} else if(flags & WorkerEvtToggle) {
} else if(flags & WorkerEvtStartStop) {
worker_state = BadUsbStateIdle; // Stop executing script
furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtDisconnect) {
worker_state = BadUsbStateNotConnected; // USB disconnected
furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtPauseResume) {
pause_state = BadUsbStateRunning;
worker_state = BadUsbStatePaused; // Pause
}
bad_usb->st.state = worker_state;
continue;
Expand Down Expand Up @@ -526,13 +533,13 @@ static int32_t bad_usb_worker(void* context) {
furi_check((flags & FuriFlagError) == 0);
}
} else if(worker_state == BadUsbStateWaitForBtn) { // State: Wait for button Press
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
uint32_t flags = furi_thread_flags_wait(
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur);
uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
FuriWaitForever);
if(!(flags & FuriFlagError)) {
if(flags & WorkerEvtEnd) {
break;
} else if(flags & WorkerEvtToggle) {
} else if(flags & WorkerEvtStartStop) {
delay_val = 0;
worker_state = BadUsbStateRunning;
} else if(flags & WorkerEvtDisconnect) {
Expand All @@ -542,21 +549,55 @@ static int32_t bad_usb_worker(void* context) {
bad_usb->st.state = worker_state;
continue;
}
} else if(worker_state == BadUsbStatePaused) { // State: Paused
uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
FuriWaitForever);
if(!(flags & FuriFlagError)) {
if(flags & WorkerEvtEnd) {
break;
} else if(flags & WorkerEvtStartStop) {
worker_state = BadUsbStateIdle; // Stop executing script
bad_usb->st.state = worker_state;
furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtDisconnect) {
worker_state = BadUsbStateNotConnected; // USB disconnected
bad_usb->st.state = worker_state;
furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtPauseResume) {
if(pause_state == BadUsbStateRunning) {
if(delay_val > 0) {
bad_usb->st.state = BadUsbStateDelay;
bad_usb->st.delay_remain = delay_val / 1000;
} else {
bad_usb->st.state = BadUsbStateRunning;
delay_val = 0;
}
worker_state = BadUsbStateRunning; // Resume
} else if(pause_state == BadUsbStateStringDelay) {
bad_usb->st.state = BadUsbStateRunning;
worker_state = BadUsbStateStringDelay; // Resume
}
}
continue;
}
} else if(worker_state == BadUsbStateStringDelay) { // State: print string with delays
uint32_t flags = furi_thread_flags_wait(
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect,
FuriFlagWaitAny,
uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
bad_usb->stringdelay);

if(!(flags & FuriFlagError)) {
if(flags & WorkerEvtEnd) {
break;
} else if(flags & WorkerEvtToggle) {
} else if(flags & WorkerEvtStartStop) {
worker_state = BadUsbStateIdle; // Stop executing script
furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtDisconnect) {
worker_state = BadUsbStateNotConnected; // USB disconnected
furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtPauseResume) {
pause_state = BadUsbStateStringDelay;
worker_state = BadUsbStatePaused; // Pause
}
bad_usb->st.state = worker_state;
continue;
Expand Down Expand Up @@ -651,9 +692,14 @@ void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layou
storage_file_free(layout_file);
}

void bad_usb_script_toggle(BadUsbScript* bad_usb) {
void bad_usb_script_start_stop(BadUsbScript* bad_usb) {
furi_assert(bad_usb);
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtStartStop);
}

void bad_usb_script_pause_resume(BadUsbScript* bad_usb) {
furi_assert(bad_usb);
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtToggle);
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtPauseResume);
}

BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb) {
Expand Down
5 changes: 4 additions & 1 deletion applications/main/bad_usb/helpers/ducky_script.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ typedef enum {
BadUsbStateDelay,
BadUsbStateStringDelay,
BadUsbStateWaitForBtn,
BadUsbStatePaused,
BadUsbStateDone,
BadUsbStateScriptError,
BadUsbStateFileError,
Expand All @@ -42,7 +43,9 @@ void bad_usb_script_start(BadUsbScript* bad_usb);

void bad_usb_script_stop(BadUsbScript* bad_usb);

void bad_usb_script_toggle(BadUsbScript* bad_usb);
void bad_usb_script_start_stop(BadUsbScript* bad_usb);

void bad_usb_script_pause_resume(BadUsbScript* bad_usb);

BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb);

Expand Down
5 changes: 4 additions & 1 deletion applications/main/bad_usb/scenes/bad_usb_scene_work.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) {
}
consumed = true;
} else if(event.event == InputKeyOk) {
bad_usb_script_toggle(app->bad_usb_script);
bad_usb_script_start_stop(app->bad_usb_script);
consumed = true;
} else if(event.event == InputKeyRight) {
bad_usb_script_pause_resume(app->bad_usb_script);
consumed = true;
}
} else if(event.type == SceneManagerEventTypeTick) {
Expand Down
Loading

0 comments on commit 66961da

Please sign in to comment.