BadUSB: script execution pause (#2700)

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
Nikolay Minaylov 2023-05-29 12:21:18 +03:00 committed by GitHub
parent f9390e0cbd
commit 66961dab06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 142 additions and 46 deletions

View File

@ -16,10 +16,11 @@
(((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE) (((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE)
typedef enum { typedef enum {
WorkerEvtToggle = (1 << 0), WorkerEvtStartStop = (1 << 0),
WorkerEvtEnd = (1 << 1), WorkerEvtPauseResume = (1 << 1),
WorkerEvtConnect = (1 << 2), WorkerEvtEnd = (1 << 2),
WorkerEvtDisconnect = (1 << 3), WorkerEvtConnect = (1 << 3),
WorkerEvtDisconnect = (1 << 4),
} WorkerEvtFlags; } WorkerEvtFlags;
static const char ducky_cmd_id[] = {"ID"}; static const char ducky_cmd_id[] = {"ID"};
@ -372,6 +373,7 @@ static int32_t bad_usb_worker(void* context) {
BadUsbScript* bad_usb = context; BadUsbScript* bad_usb = context;
BadUsbWorkerState worker_state = BadUsbStateInit; BadUsbWorkerState worker_state = BadUsbStateInit;
BadUsbWorkerState pause_state = BadUsbStateRunning;
int32_t delay_val = 0; int32_t delay_val = 0;
FURI_LOG_I(WORKER_TAG, "Init"); FURI_LOG_I(WORKER_TAG, "Init");
@ -406,24 +408,24 @@ static int32_t bad_usb_worker(void* context) {
} else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected } else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
uint32_t flags = bad_usb_flags_get( uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever); WorkerEvtEnd | WorkerEvtConnect | WorkerEvtStartStop, FuriWaitForever);
if(flags & WorkerEvtEnd) { if(flags & WorkerEvtEnd) {
break; break;
} else if(flags & WorkerEvtConnect) { } else if(flags & WorkerEvtConnect) {
worker_state = BadUsbStateIdle; // Ready to run worker_state = BadUsbStateIdle; // Ready to run
} else if(flags & WorkerEvtToggle) { } else if(flags & WorkerEvtStartStop) {
worker_state = BadUsbStateWillRun; // Will run when USB is connected worker_state = BadUsbStateWillRun; // Will run when USB is connected
} }
bad_usb->st.state = worker_state; bad_usb->st.state = worker_state;
} else if(worker_state == BadUsbStateIdle) { // State: ready to start } else if(worker_state == BadUsbStateIdle) { // State: ready to start
uint32_t flags = bad_usb_flags_get( uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriWaitForever); WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtDisconnect, FuriWaitForever);
if(flags & WorkerEvtEnd) { if(flags & WorkerEvtEnd) {
break; break;
} else if(flags & WorkerEvtToggle) { // Start executing script } else if(flags & WorkerEvtStartStop) { // Start executing script
DOLPHIN_DEED(DolphinDeedBadUsbPlayScript); DOLPHIN_DEED(DolphinDeedBadUsbPlayScript);
delay_val = 0; delay_val = 0;
bad_usb->buf_len = 0; bad_usb->buf_len = 0;
@ -442,7 +444,7 @@ static int32_t bad_usb_worker(void* context) {
} else if(worker_state == BadUsbStateWillRun) { // State: start on connection } else if(worker_state == BadUsbStateWillRun) { // State: start on connection
uint32_t flags = bad_usb_flags_get( uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever); WorkerEvtEnd | WorkerEvtConnect | WorkerEvtStartStop, FuriWaitForever);
if(flags & WorkerEvtEnd) { if(flags & WorkerEvtEnd) {
break; break;
@ -458,17 +460,17 @@ static int32_t bad_usb_worker(void* context) {
storage_file_seek(script_file, 0, true); storage_file_seek(script_file, 0, true);
// extra time for PC to recognize Flipper as keyboard // extra time for PC to recognize Flipper as keyboard
flags = furi_thread_flags_wait( flags = furi_thread_flags_wait(
WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtToggle, WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtStartStop,
FuriFlagWaitAny | FuriFlagNoClear, FuriFlagWaitAny | FuriFlagNoClear,
1500); 1500);
if(flags == (unsigned)FuriFlagErrorTimeout) { if(flags == (unsigned)FuriFlagErrorTimeout) {
// If nothing happened - start script execution // If nothing happened - start script execution
worker_state = BadUsbStateRunning; worker_state = BadUsbStateRunning;
} else if(flags & WorkerEvtToggle) { } else if(flags & WorkerEvtStartStop) {
worker_state = BadUsbStateIdle; 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; worker_state = BadUsbStateNotConnected;
} }
bad_usb->st.state = worker_state; bad_usb->st.state = worker_state;
@ -476,18 +478,23 @@ static int32_t bad_usb_worker(void* context) {
} else if(worker_state == BadUsbStateRunning) { // State: running } else if(worker_state == BadUsbStateRunning) { // State: running
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val); uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
uint32_t flags = furi_thread_flags_wait( uint32_t flags = furi_thread_flags_wait(
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur); WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
FuriFlagWaitAny,
delay_cur);
delay_val -= delay_cur; delay_val -= delay_cur;
if(!(flags & FuriFlagError)) { if(!(flags & FuriFlagError)) {
if(flags & WorkerEvtEnd) { if(flags & WorkerEvtEnd) {
break; break;
} else if(flags & WorkerEvtToggle) { } else if(flags & WorkerEvtStartStop) {
worker_state = BadUsbStateIdle; // Stop executing script worker_state = BadUsbStateIdle; // Stop executing script
furi_hal_hid_kb_release_all(); furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtDisconnect) { } else if(flags & WorkerEvtDisconnect) {
worker_state = BadUsbStateNotConnected; // USB disconnected worker_state = BadUsbStateNotConnected; // USB disconnected
furi_hal_hid_kb_release_all(); furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtPauseResume) {
pause_state = BadUsbStateRunning;
worker_state = BadUsbStatePaused; // Pause
} }
bad_usb->st.state = worker_state; bad_usb->st.state = worker_state;
continue; continue;
@ -526,13 +533,13 @@ static int32_t bad_usb_worker(void* context) {
furi_check((flags & FuriFlagError) == 0); furi_check((flags & FuriFlagError) == 0);
} }
} else if(worker_state == BadUsbStateWaitForBtn) { // State: Wait for button Press } else if(worker_state == BadUsbStateWaitForBtn) { // State: Wait for button Press
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val); uint32_t flags = bad_usb_flags_get(
uint32_t flags = furi_thread_flags_wait( WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur); FuriWaitForever);
if(!(flags & FuriFlagError)) { if(!(flags & FuriFlagError)) {
if(flags & WorkerEvtEnd) { if(flags & WorkerEvtEnd) {
break; break;
} else if(flags & WorkerEvtToggle) { } else if(flags & WorkerEvtStartStop) {
delay_val = 0; delay_val = 0;
worker_state = BadUsbStateRunning; worker_state = BadUsbStateRunning;
} else if(flags & WorkerEvtDisconnect) { } else if(flags & WorkerEvtDisconnect) {
@ -542,21 +549,55 @@ static int32_t bad_usb_worker(void* context) {
bad_usb->st.state = worker_state; bad_usb->st.state = worker_state;
continue; 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 } else if(worker_state == BadUsbStateStringDelay) { // State: print string with delays
uint32_t flags = furi_thread_flags_wait( uint32_t flags = bad_usb_flags_get(
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
FuriFlagWaitAny,
bad_usb->stringdelay); bad_usb->stringdelay);
if(!(flags & FuriFlagError)) { if(!(flags & FuriFlagError)) {
if(flags & WorkerEvtEnd) { if(flags & WorkerEvtEnd) {
break; break;
} else if(flags & WorkerEvtToggle) { } else if(flags & WorkerEvtStartStop) {
worker_state = BadUsbStateIdle; // Stop executing script worker_state = BadUsbStateIdle; // Stop executing script
furi_hal_hid_kb_release_all(); furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtDisconnect) { } else if(flags & WorkerEvtDisconnect) {
worker_state = BadUsbStateNotConnected; // USB disconnected worker_state = BadUsbStateNotConnected; // USB disconnected
furi_hal_hid_kb_release_all(); furi_hal_hid_kb_release_all();
} else if(flags & WorkerEvtPauseResume) {
pause_state = BadUsbStateStringDelay;
worker_state = BadUsbStatePaused; // Pause
} }
bad_usb->st.state = worker_state; bad_usb->st.state = worker_state;
continue; continue;
@ -651,9 +692,14 @@ void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layou
storage_file_free(layout_file); 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_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), 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), WorkerEvtPauseResume);
} }
BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb) { BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb) {

View File

@ -16,6 +16,7 @@ typedef enum {
BadUsbStateDelay, BadUsbStateDelay,
BadUsbStateStringDelay, BadUsbStateStringDelay,
BadUsbStateWaitForBtn, BadUsbStateWaitForBtn,
BadUsbStatePaused,
BadUsbStateDone, BadUsbStateDone,
BadUsbStateScriptError, BadUsbStateScriptError,
BadUsbStateFileError, BadUsbStateFileError,
@ -42,7 +43,9 @@ void bad_usb_script_start(BadUsbScript* bad_usb);
void bad_usb_script_stop(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); BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb);

View File

@ -21,7 +21,10 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) {
} }
consumed = true; consumed = true;
} else if(event.event == InputKeyOk) { } 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; consumed = true;
} }
} else if(event.type == SceneManagerEventTypeTick) { } else if(event.type == SceneManagerEventTypeTick) {

View File

@ -16,6 +16,7 @@ typedef struct {
char file_name[MAX_NAME_LEN]; char file_name[MAX_NAME_LEN];
char layout[MAX_NAME_LEN]; char layout[MAX_NAME_LEN];
BadUsbState state; BadUsbState state;
bool pause_wait;
uint8_t anim_frame; uint8_t anim_frame;
} BadUsbModel; } BadUsbModel;
@ -31,11 +32,7 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
if(strlen(model->layout) == 0) { if(strlen(model->layout) == 0) {
furi_string_set(disp_str, "(default)"); furi_string_set(disp_str, "(default)");
} else { } else {
furi_string_reset(disp_str); furi_string_printf(disp_str, "(%s)", model->layout);
furi_string_push_back(disp_str, '(');
for(size_t i = 0; i < strlen(model->layout); i++)
furi_string_push_back(disp_str, model->layout[i]);
furi_string_push_back(disp_str, ')');
} }
elements_string_fit_width(canvas, disp_str, 128 - 2); elements_string_fit_width(canvas, disp_str, 128 - 2);
canvas_draw_str( canvas_draw_str(
@ -45,34 +42,42 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_icon(canvas, 22, 24, &I_UsbTree_48x22); canvas_draw_icon(canvas, 22, 24, &I_UsbTree_48x22);
if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone) || BadUsbWorkerState state = model->state.state;
(model->state.state == BadUsbStateNotConnected)) {
if((state == BadUsbStateIdle) || (state == BadUsbStateDone) ||
(state == BadUsbStateNotConnected)) {
elements_button_center(canvas, "Run"); elements_button_center(canvas, "Run");
elements_button_left(canvas, "Config"); elements_button_left(canvas, "Config");
} else if((model->state.state == BadUsbStateRunning) || (model->state.state == BadUsbStateDelay)) { } else if((state == BadUsbStateRunning) || (state == BadUsbStateDelay)) {
elements_button_center(canvas, "Stop"); elements_button_center(canvas, "Stop");
} else if(model->state.state == BadUsbStateWaitForBtn) { if(!model->pause_wait) {
elements_button_right(canvas, "Pause");
}
} else if(state == BadUsbStatePaused) {
elements_button_center(canvas, "End");
elements_button_right(canvas, "Resume");
} else if(state == BadUsbStateWaitForBtn) {
elements_button_center(canvas, "Press to continue"); elements_button_center(canvas, "Press to continue");
} else if(model->state.state == BadUsbStateWillRun) { } else if(state == BadUsbStateWillRun) {
elements_button_center(canvas, "Cancel"); elements_button_center(canvas, "Cancel");
} }
if(model->state.state == BadUsbStateNotConnected) { if(state == BadUsbStateNotConnected) {
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect"); canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect");
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to USB"); canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to USB");
} else if(model->state.state == BadUsbStateWillRun) { } else if(state == BadUsbStateWillRun) {
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run"); canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run");
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect"); canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect");
} else if(model->state.state == BadUsbStateFileError) { } else if(state == BadUsbStateFileError) {
canvas_draw_icon(canvas, 4, 26, &I_Error_18x18); canvas_draw_icon(canvas, 4, 26, &I_Error_18x18);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "File"); canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "File");
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "ERROR"); canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "ERROR");
} else if(model->state.state == BadUsbStateScriptError) { } else if(state == BadUsbStateScriptError) {
canvas_draw_icon(canvas, 4, 26, &I_Error_18x18); canvas_draw_icon(canvas, 4, 26, &I_Error_18x18);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:"); canvas_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:");
@ -87,12 +92,12 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_str_aligned( canvas_draw_str_aligned(
canvas, 127, 56, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); canvas, 127, 56, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
furi_string_reset(disp_str); furi_string_reset(disp_str);
} else if(model->state.state == BadUsbStateIdle) { } else if(state == BadUsbStateIdle) {
canvas_draw_icon(canvas, 4, 26, &I_Smile_18x18); canvas_draw_icon(canvas, 4, 26, &I_Smile_18x18);
canvas_set_font(canvas, FontBigNumbers); canvas_set_font(canvas, FontBigNumbers);
canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "0"); canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "0");
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
} else if(model->state.state == BadUsbStateRunning) { } else if(state == BadUsbStateRunning) {
if(model->anim_frame == 0) { if(model->anim_frame == 0) {
canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21); canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21);
} else { } else {
@ -105,13 +110,13 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
furi_string_reset(disp_str); furi_string_reset(disp_str);
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
} else if(model->state.state == BadUsbStateDone) { } else if(state == BadUsbStateDone) {
canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21); canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21);
canvas_set_font(canvas, FontBigNumbers); canvas_set_font(canvas, FontBigNumbers);
canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "100"); canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "100");
furi_string_reset(disp_str); furi_string_reset(disp_str);
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
} else if(model->state.state == BadUsbStateDelay) { } else if(state == BadUsbStateDelay) {
if(model->anim_frame == 0) { if(model->anim_frame == 0) {
canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21); canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21);
} else { } else {
@ -129,6 +134,22 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_str_aligned( canvas_draw_str_aligned(
canvas, 127, 50, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); canvas, 127, 50, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
furi_string_reset(disp_str); furi_string_reset(disp_str);
} else if((state == BadUsbStatePaused) || (state == BadUsbStateWaitForBtn)) {
if(model->anim_frame == 0) {
canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21);
} else {
canvas_draw_icon(canvas, 4, 23, &I_EviWaiting2_18x21);
}
canvas_set_font(canvas, FontBigNumbers);
furi_string_printf(
disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb);
canvas_draw_str_aligned(
canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
furi_string_reset(disp_str);
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 127, 50, AlignRight, AlignBottom, "Paused");
furi_string_reset(disp_str);
} else { } else {
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
} }
@ -142,7 +163,27 @@ static bool bad_usb_input_callback(InputEvent* event, void* context) {
bool consumed = false; bool consumed = false;
if(event->type == InputTypeShort) { if(event->type == InputTypeShort) {
if((event->key == InputKeyLeft) || (event->key == InputKeyOk)) { if(event->key == InputKeyLeft) {
consumed = true;
furi_assert(bad_usb->callback);
bad_usb->callback(event->key, bad_usb->context);
} else if(event->key == InputKeyOk) {
with_view_model(
bad_usb->view, BadUsbModel * model, { model->pause_wait = false; }, true);
consumed = true;
furi_assert(bad_usb->callback);
bad_usb->callback(event->key, bad_usb->context);
} else if(event->key == InputKeyRight) {
with_view_model(
bad_usb->view,
BadUsbModel * model,
{
if((model->state.state == BadUsbStateRunning) ||
(model->state.state == BadUsbStateDelay)) {
model->pause_wait = true;
}
},
true);
consumed = true; consumed = true;
furi_assert(bad_usb->callback); furi_assert(bad_usb->callback);
bad_usb->callback(event->key, bad_usb->context); bad_usb->callback(event->key, bad_usb->context);
@ -215,6 +256,9 @@ void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) {
{ {
memcpy(&(model->state), st, sizeof(BadUsbState)); memcpy(&(model->state), st, sizeof(BadUsbState));
model->anim_frame ^= 1; model->anim_frame ^= 1;
if(model->state.state == BadUsbStatePaused) {
model->pause_wait = false;
}
}, },
true); true);
} }