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>
This commit is contained in:
		
							parent
							
								
									e999c35749
								
							
						
					
					
						commit
						eaf965c66f
					
				| @ -32,6 +32,7 @@ struct BadUsbScript { | |||||||
|     FuriString* file_path; |     FuriString* file_path; | ||||||
|     uint32_t defdelay; |     uint32_t defdelay; | ||||||
|     uint16_t layout[128]; |     uint16_t layout[128]; | ||||||
|  |     uint32_t stringdelay; | ||||||
|     FuriThread* thread; |     FuriThread* thread; | ||||||
|     uint8_t file_buf[FILE_BUFFER_LEN + 1]; |     uint8_t file_buf[FILE_BUFFER_LEN + 1]; | ||||||
|     uint8_t buf_start; |     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_string[] = {"STRING "}; | ||||||
| static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "}; | static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "}; | ||||||
| static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "}; | 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_repeat[] = {"REPEAT "}; | ||||||
| static const char ducky_cmd_sysrq[] = {"SYSRQ "}; | 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) { | static bool ducky_string(BadUsbScript* bad_usb, const char* param) { | ||||||
|     uint32_t i = 0; |     uint32_t i = 0; | ||||||
|  | 
 | ||||||
|     while(param[i] != '\0') { |     while(param[i] != '\0') { | ||||||
|         uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_usb, param[i]); |         uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_usb, param[i]); | ||||||
|         if(keycode != HID_KEYBOARD_NONE) { |         if(keycode != HID_KEYBOARD_NONE) { | ||||||
|             furi_hal_hid_kb_press(keycode); |             furi_hal_hid_kb_press(keycode); | ||||||
|             furi_hal_hid_kb_release(keycode); |             furi_hal_hid_kb_release(keycode); | ||||||
|  |             if(bad_usb->stringdelay > 0) { | ||||||
|  |                 furi_delay_ms(bad_usb->stringdelay); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         i++; |         i++; | ||||||
|     } |     } | ||||||
|  |     bad_usb->stringdelay = 0; | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -277,6 +285,20 @@ static int32_t | |||||||
|             snprintf(error, error_len, "Invalid number %s", line_tmp); |             snprintf(error, error_len, "Invalid number %s", line_tmp); | ||||||
|         } |         } | ||||||
|         return (state) ? (0) : SCRIPT_STATE_ERROR; |         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) { |     } else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) { | ||||||
|         // STRING
 |         // STRING
 | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |         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); |         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) { | static int32_t bad_usb_worker(void* context) { | ||||||
|     BadUsbScript* bad_usb = context; |     BadUsbScript* bad_usb = context; | ||||||
| 
 | 
 | ||||||
| @ -520,11 +555,9 @@ static int32_t bad_usb_worker(void* context) { | |||||||
|             bad_usb->st.state = worker_state; |             bad_usb->st.state = worker_state; | ||||||
| 
 | 
 | ||||||
|         } else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
 |         } else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
 | ||||||
|             uint32_t flags = furi_thread_flags_wait( |             uint32_t flags = bad_usb_flags_get( | ||||||
|                 WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, |                 WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever); | ||||||
|                 FuriFlagWaitAny, | 
 | ||||||
|                 FuriWaitForever); |  | ||||||
|             furi_check((flags & FuriFlagError) == 0); |  | ||||||
|             if(flags & WorkerEvtEnd) { |             if(flags & WorkerEvtEnd) { | ||||||
|                 break; |                 break; | ||||||
|             } else if(flags & WorkerEvtConnect) { |             } else if(flags & WorkerEvtConnect) { | ||||||
| @ -535,11 +568,9 @@ static int32_t bad_usb_worker(void* context) { | |||||||
|             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 = furi_thread_flags_wait( |             uint32_t flags = bad_usb_flags_get( | ||||||
|                 WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, |                 WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriWaitForever); | ||||||
|                 FuriFlagWaitAny, | 
 | ||||||
|                 FuriWaitForever); |  | ||||||
|             furi_check((flags & FuriFlagError) == 0); |  | ||||||
|             if(flags & WorkerEvtEnd) { |             if(flags & WorkerEvtEnd) { | ||||||
|                 break; |                 break; | ||||||
|             } else if(flags & WorkerEvtToggle) { // Start executing script
 |             } 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->buf_len = 0; | ||||||
|                 bad_usb->st.line_cur = 0; |                 bad_usb->st.line_cur = 0; | ||||||
|                 bad_usb->defdelay = 0; |                 bad_usb->defdelay = 0; | ||||||
|  |                 bad_usb->stringdelay = 0; | ||||||
|                 bad_usb->repeat_cnt = 0; |                 bad_usb->repeat_cnt = 0; | ||||||
|                 bad_usb->file_end = false; |                 bad_usb->file_end = false; | ||||||
|                 storage_file_seek(script_file, 0, true); |                 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; |             bad_usb->st.state = worker_state; | ||||||
| 
 | 
 | ||||||
|         } else if(worker_state == BadUsbStateWillRun) { // State: start on connection
 |         } else if(worker_state == BadUsbStateWillRun) { // State: start on connection
 | ||||||
|             uint32_t flags = furi_thread_flags_wait( |             uint32_t flags = bad_usb_flags_get( | ||||||
|                 WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, |                 WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever); | ||||||
|                 FuriFlagWaitAny, | 
 | ||||||
|                 FuriWaitForever); |  | ||||||
|             furi_check((flags & FuriFlagError) == 0); |  | ||||||
|             if(flags & WorkerEvtEnd) { |             if(flags & WorkerEvtEnd) { | ||||||
|                 break; |                 break; | ||||||
|             } else if(flags & WorkerEvtConnect) { // Start executing script
 |             } 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->buf_len = 0; | ||||||
|                 bad_usb->st.line_cur = 0; |                 bad_usb->st.line_cur = 0; | ||||||
|                 bad_usb->defdelay = 0; |                 bad_usb->defdelay = 0; | ||||||
|  |                 bad_usb->stringdelay = 0; | ||||||
|                 bad_usb->repeat_cnt = 0; |                 bad_usb->repeat_cnt = 0; | ||||||
|                 bad_usb->file_end = false; |                 bad_usb->file_end = false; | ||||||
|                 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
 | ||||||
|                 furi_thread_flags_wait(0, FuriFlagWaitAny, 1500); |                 flags = furi_thread_flags_wait( | ||||||
|                 worker_state = BadUsbStateRunning; |                     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
 |             } else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
 | ||||||
|                 worker_state = BadUsbStateNotConnected; |                 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); |             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 | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur); | ||||||
|  | 
 | ||||||
|             delay_val -= delay_cur; |             delay_val -= delay_cur; | ||||||
|             if(!(flags & FuriFlagError)) { |             if(!(flags & FuriFlagError)) { | ||||||
|                 if(flags & WorkerEvtEnd) { |                 if(flags & WorkerEvtEnd) { | ||||||
| @ -629,9 +670,9 @@ static int32_t bad_usb_worker(void* context) { | |||||||
|         } else if( |         } else if( | ||||||
|             (worker_state == BadUsbStateFileError) || |             (worker_state == BadUsbStateFileError) || | ||||||
|             (worker_state == BadUsbStateScriptError)) { // State: error
 |             (worker_state == BadUsbStateScriptError)) { // State: error
 | ||||||
|             uint32_t flags = furi_thread_flags_wait( |             uint32_t flags = | ||||||
|                 WorkerEvtEnd, FuriFlagWaitAny, FuriWaitForever); // Waiting for exit command
 |                 bad_usb_flags_get(WorkerEvtEnd, FuriWaitForever); // Waiting for exit command
 | ||||||
|             furi_check((flags & FuriFlagError) == 0); | 
 | ||||||
|             if(flags & WorkerEvtEnd) { |             if(flags & WorkerEvtEnd) { | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -22,7 +22,6 @@ static bool bad_usb_file_select(BadUsbApp* bad_usb) { | |||||||
| void bad_usb_scene_file_select_on_enter(void* context) { | void bad_usb_scene_file_select_on_enter(void* context) { | ||||||
|     BadUsbApp* bad_usb = context; |     BadUsbApp* bad_usb = context; | ||||||
| 
 | 
 | ||||||
|     furi_hal_usb_disable(); |  | ||||||
|     if(bad_usb->bad_usb_script) { |     if(bad_usb->bad_usb_script) { | ||||||
|         bad_usb_script_close(bad_usb->bad_usb_script); |         bad_usb_script_close(bad_usb->bad_usb_script); | ||||||
|         bad_usb->bad_usb_script = NULL; |         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); |         scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneWork); | ||||||
|     } else { |     } else { | ||||||
|         furi_hal_usb_enable(); |  | ||||||
|         view_dispatcher_stop(bad_usb->view_dispatcher); |         view_dispatcher_stop(bad_usb->view_dispatcher); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -75,6 +75,14 @@ Can be combined with a special key command or a single character. | |||||||
| | ------- | ----------- | ----------------- | | | ------- | ----------- | ----------------- | | ||||||
| | STRING  | Text string | Print text string | | | 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 | ## Repeat | ||||||
| 
 | 
 | ||||||
| | Command | Parameters                   | Notes                   | | | Command | Parameters                   | Notes                   | | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 n30f0x
						n30f0x