BadUSB: Keyboard Layouts (#2256)
* BadUSB: Keyboard Layouts * Apply requested changes pt1 * Add layout file check when we loading config Co-authored-by: Nikolay Minaylov <nm29719@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									99253a0e28
								
							
						
					
					
						commit
						b1f581239b
					
				| @ -1,9 +1,12 @@ | |||||||
| #include "bad_usb_app_i.h" | #include "bad_usb_app_i.h" | ||||||
|  | #include "bad_usb_settings_filename.h" | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| #include <storage/storage.h> | #include <storage/storage.h> | ||||||
| #include <lib/toolbox/path.h> | #include <lib/toolbox/path.h> | ||||||
| 
 | 
 | ||||||
|  | #define BAD_USB_SETTINGS_PATH BAD_USB_APP_BASE_FOLDER "/" BAD_USB_SETTINGS_FILE_NAME | ||||||
|  | 
 | ||||||
| static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) { | static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     BadUsbApp* app = context; |     BadUsbApp* app = context; | ||||||
| @ -22,15 +25,62 @@ static void bad_usb_app_tick_event_callback(void* context) { | |||||||
|     scene_manager_handle_tick_event(app->scene_manager); |     scene_manager_handle_tick_event(app->scene_manager); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void bad_usb_load_settings(BadUsbApp* app) { | ||||||
|  |     File* settings_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); | ||||||
|  |     if(storage_file_open(settings_file, BAD_USB_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { | ||||||
|  |         char chr; | ||||||
|  |         while((storage_file_read(settings_file, &chr, 1) == 1) && | ||||||
|  |               !storage_file_eof(settings_file) && !isspace(chr)) { | ||||||
|  |             furi_string_push_back(app->keyboard_layout, chr); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         furi_string_reset(app->keyboard_layout); | ||||||
|  |     } | ||||||
|  |     storage_file_close(settings_file); | ||||||
|  |     storage_file_free(settings_file); | ||||||
|  | 
 | ||||||
|  |     if(!furi_string_empty(app->keyboard_layout)) { | ||||||
|  |         Storage* fs_api = furi_record_open(RECORD_STORAGE); | ||||||
|  |         FileInfo layout_file_info; | ||||||
|  |         FS_Error file_check_err = storage_common_stat( | ||||||
|  |             fs_api, furi_string_get_cstr(app->keyboard_layout), &layout_file_info); | ||||||
|  |         furi_record_close(RECORD_STORAGE); | ||||||
|  |         if(file_check_err != FSE_OK) { | ||||||
|  |             furi_string_reset(app->keyboard_layout); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         if(layout_file_info.size != 256) { | ||||||
|  |             furi_string_reset(app->keyboard_layout); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void bad_usb_save_settings(BadUsbApp* app) { | ||||||
|  |     File* settings_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); | ||||||
|  |     if(storage_file_open(settings_file, BAD_USB_SETTINGS_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) { | ||||||
|  |         storage_file_write( | ||||||
|  |             settings_file, | ||||||
|  |             furi_string_get_cstr(app->keyboard_layout), | ||||||
|  |             furi_string_size(app->keyboard_layout)); | ||||||
|  |         storage_file_write(settings_file, "\n", 1); | ||||||
|  |     } | ||||||
|  |     storage_file_close(settings_file); | ||||||
|  |     storage_file_free(settings_file); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BadUsbApp* bad_usb_app_alloc(char* arg) { | BadUsbApp* bad_usb_app_alloc(char* arg) { | ||||||
|     BadUsbApp* app = malloc(sizeof(BadUsbApp)); |     BadUsbApp* app = malloc(sizeof(BadUsbApp)); | ||||||
| 
 | 
 | ||||||
|     app->file_path = furi_string_alloc(); |     app->bad_usb_script = NULL; | ||||||
| 
 | 
 | ||||||
|  |     app->file_path = furi_string_alloc(); | ||||||
|  |     app->keyboard_layout = furi_string_alloc(); | ||||||
|     if(arg && strlen(arg)) { |     if(arg && strlen(arg)) { | ||||||
|         furi_string_set(app->file_path, arg); |         furi_string_set(app->file_path, arg); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     bad_usb_load_settings(app); | ||||||
|  | 
 | ||||||
|     app->gui = furi_record_open(RECORD_GUI); |     app->gui = furi_record_open(RECORD_GUI); | ||||||
|     app->notifications = furi_record_open(RECORD_NOTIFICATION); |     app->notifications = furi_record_open(RECORD_NOTIFICATION); | ||||||
|     app->dialogs = furi_record_open(RECORD_DIALOGS); |     app->dialogs = furi_record_open(RECORD_DIALOGS); | ||||||
| @ -53,6 +103,10 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { | |||||||
|     view_dispatcher_add_view( |     view_dispatcher_add_view( | ||||||
|         app->view_dispatcher, BadUsbAppViewError, widget_get_view(app->widget)); |         app->view_dispatcher, BadUsbAppViewError, widget_get_view(app->widget)); | ||||||
| 
 | 
 | ||||||
|  |     app->submenu = submenu_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         app->view_dispatcher, BadUsbAppViewConfig, submenu_get_view(app->submenu)); | ||||||
|  | 
 | ||||||
|     app->bad_usb_view = bad_usb_alloc(); |     app->bad_usb_view = bad_usb_alloc(); | ||||||
|     view_dispatcher_add_view( |     view_dispatcher_add_view( | ||||||
|         app->view_dispatcher, BadUsbAppViewWork, bad_usb_get_view(app->bad_usb_view)); |         app->view_dispatcher, BadUsbAppViewWork, bad_usb_get_view(app->bad_usb_view)); | ||||||
| @ -64,9 +118,11 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { | |||||||
|         scene_manager_next_scene(app->scene_manager, BadUsbSceneError); |         scene_manager_next_scene(app->scene_manager, BadUsbSceneError); | ||||||
|     } else { |     } else { | ||||||
|         if(!furi_string_empty(app->file_path)) { |         if(!furi_string_empty(app->file_path)) { | ||||||
|  |             app->bad_usb_script = bad_usb_script_open(app->file_path); | ||||||
|  |             bad_usb_script_set_keyboard_layout(app->bad_usb_script, app->keyboard_layout); | ||||||
|             scene_manager_next_scene(app->scene_manager, BadUsbSceneWork); |             scene_manager_next_scene(app->scene_manager, BadUsbSceneWork); | ||||||
|         } else { |         } else { | ||||||
|             furi_string_set(app->file_path, BAD_USB_APP_PATH_FOLDER); |             furi_string_set(app->file_path, BAD_USB_APP_BASE_FOLDER); | ||||||
|             scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); |             scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -77,6 +133,11 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { | |||||||
| void bad_usb_app_free(BadUsbApp* app) { | void bad_usb_app_free(BadUsbApp* app) { | ||||||
|     furi_assert(app); |     furi_assert(app); | ||||||
| 
 | 
 | ||||||
|  |     if(app->bad_usb_script) { | ||||||
|  |         bad_usb_script_close(app->bad_usb_script); | ||||||
|  |         app->bad_usb_script = NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // Views
 |     // Views
 | ||||||
|     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); |     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); | ||||||
|     bad_usb_free(app->bad_usb_view); |     bad_usb_free(app->bad_usb_view); | ||||||
| @ -85,6 +146,10 @@ void bad_usb_app_free(BadUsbApp* app) { | |||||||
|     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewError); |     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewError); | ||||||
|     widget_free(app->widget); |     widget_free(app->widget); | ||||||
| 
 | 
 | ||||||
|  |     // Submenu
 | ||||||
|  |     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfig); | ||||||
|  |     submenu_free(app->submenu); | ||||||
|  | 
 | ||||||
|     // View dispatcher
 |     // View dispatcher
 | ||||||
|     view_dispatcher_free(app->view_dispatcher); |     view_dispatcher_free(app->view_dispatcher); | ||||||
|     scene_manager_free(app->scene_manager); |     scene_manager_free(app->scene_manager); | ||||||
| @ -94,7 +159,10 @@ void bad_usb_app_free(BadUsbApp* app) { | |||||||
|     furi_record_close(RECORD_NOTIFICATION); |     furi_record_close(RECORD_NOTIFICATION); | ||||||
|     furi_record_close(RECORD_DIALOGS); |     furi_record_close(RECORD_DIALOGS); | ||||||
| 
 | 
 | ||||||
|  |     bad_usb_save_settings(app); | ||||||
|  | 
 | ||||||
|     furi_string_free(app->file_path); |     furi_string_free(app->file_path); | ||||||
|  |     furi_string_free(app->keyboard_layout); | ||||||
| 
 | 
 | ||||||
|     free(app); |     free(app); | ||||||
| } | } | ||||||
|  | |||||||
| @ -15,8 +15,10 @@ | |||||||
| #include <gui/modules/widget.h> | #include <gui/modules/widget.h> | ||||||
| #include "views/bad_usb_view.h" | #include "views/bad_usb_view.h" | ||||||
| 
 | 
 | ||||||
| #define BAD_USB_APP_PATH_FOLDER ANY_PATH("badusb") | #define BAD_USB_APP_BASE_FOLDER ANY_PATH("badusb") | ||||||
| #define BAD_USB_APP_EXTENSION ".txt" | #define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/assets/layouts" | ||||||
|  | #define BAD_USB_APP_SCRIPT_EXTENSION ".txt" | ||||||
|  | #define BAD_USB_APP_LAYOUT_EXTENSION ".kl" | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     BadUsbAppErrorNoFiles, |     BadUsbAppErrorNoFiles, | ||||||
| @ -30,9 +32,11 @@ struct BadUsbApp { | |||||||
|     NotificationApp* notifications; |     NotificationApp* notifications; | ||||||
|     DialogsApp* dialogs; |     DialogsApp* dialogs; | ||||||
|     Widget* widget; |     Widget* widget; | ||||||
|  |     Submenu* submenu; | ||||||
| 
 | 
 | ||||||
|     BadUsbAppError error; |     BadUsbAppError error; | ||||||
|     FuriString* file_path; |     FuriString* file_path; | ||||||
|  |     FuriString* keyboard_layout; | ||||||
|     BadUsb* bad_usb_view; |     BadUsb* bad_usb_view; | ||||||
|     BadUsbScript* bad_usb_script; |     BadUsbScript* bad_usb_script; | ||||||
| }; | }; | ||||||
| @ -40,4 +44,5 @@ struct BadUsbApp { | |||||||
| typedef enum { | typedef enum { | ||||||
|     BadUsbAppViewError, |     BadUsbAppViewError, | ||||||
|     BadUsbAppViewWork, |     BadUsbAppViewWork, | ||||||
|  |     BadUsbAppViewConfig, | ||||||
| } BadUsbAppView; | } BadUsbAppView; | ||||||
| @ -16,6 +16,9 @@ | |||||||
| #define SCRIPT_STATE_END (-2) | #define SCRIPT_STATE_END (-2) | ||||||
| #define SCRIPT_STATE_NEXT_LINE (-3) | #define SCRIPT_STATE_NEXT_LINE (-3) | ||||||
| 
 | 
 | ||||||
|  | #define BADUSB_ASCII_TO_KEY(script, x) \ | ||||||
|  |     (((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE) | ||||||
|  | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     WorkerEvtToggle = (1 << 0), |     WorkerEvtToggle = (1 << 0), | ||||||
|     WorkerEvtEnd = (1 << 1), |     WorkerEvtEnd = (1 << 1), | ||||||
| @ -28,6 +31,7 @@ struct BadUsbScript { | |||||||
|     BadUsbState st; |     BadUsbState st; | ||||||
|     FuriString* file_path; |     FuriString* file_path; | ||||||
|     uint32_t defdelay; |     uint32_t defdelay; | ||||||
|  |     uint16_t layout[128]; | ||||||
|     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; | ||||||
| @ -205,10 +209,10 @@ static bool ducky_altstring(const char* param) { | |||||||
|     return state; |     return state; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool ducky_string(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 = HID_ASCII_TO_KEY(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); | ||||||
| @ -218,7 +222,7 @@ static bool ducky_string(const char* param) { | |||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint16_t ducky_get_keycode(const char* param, bool accept_chars) { | static uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept_chars) { | ||||||
|     for(size_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) { |     for(size_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) { | ||||||
|         size_t key_cmd_len = strlen(ducky_keys[i].name); |         size_t key_cmd_len = strlen(ducky_keys[i].name); | ||||||
|         if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) && |         if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) && | ||||||
| @ -227,7 +231,7 @@ static uint16_t ducky_get_keycode(const char* param, bool accept_chars) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if((accept_chars) && (strlen(param) > 0)) { |     if((accept_chars) && (strlen(param) > 0)) { | ||||||
|         return (HID_ASCII_TO_KEY(param[0]) & 0xFF); |         return (BADUSB_ASCII_TO_KEY(bad_usb, param[0]) & 0xFF); | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| @ -276,7 +280,7 @@ static int32_t | |||||||
|     } 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]; | ||||||
|         state = ducky_string(line_tmp); |         state = ducky_string(bad_usb, line_tmp); | ||||||
|         if(!state && error != NULL) { |         if(!state && error != NULL) { | ||||||
|             snprintf(error, error_len, "Invalid string %s", line_tmp); |             snprintf(error, error_len, "Invalid string %s", line_tmp); | ||||||
|         } |         } | ||||||
| @ -312,14 +316,14 @@ static int32_t | |||||||
|     } else if(strncmp(line_tmp, ducky_cmd_sysrq, strlen(ducky_cmd_sysrq)) == 0) { |     } else if(strncmp(line_tmp, ducky_cmd_sysrq, strlen(ducky_cmd_sysrq)) == 0) { | ||||||
|         // SYSRQ
 |         // SYSRQ
 | ||||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|         uint16_t key = ducky_get_keycode(line_tmp, true); |         uint16_t key = ducky_get_keycode(bad_usb, line_tmp, true); | ||||||
|         furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN); |         furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN); | ||||||
|         furi_hal_hid_kb_press(key); |         furi_hal_hid_kb_press(key); | ||||||
|         furi_hal_hid_kb_release_all(); |         furi_hal_hid_kb_release_all(); | ||||||
|         return (0); |         return (0); | ||||||
|     } else { |     } else { | ||||||
|         // Special keys + modifiers
 |         // Special keys + modifiers
 | ||||||
|         uint16_t key = ducky_get_keycode(line_tmp, false); |         uint16_t key = ducky_get_keycode(bad_usb, line_tmp, false); | ||||||
|         if(key == HID_KEYBOARD_NONE) { |         if(key == HID_KEYBOARD_NONE) { | ||||||
|             if(error != NULL) { |             if(error != NULL) { | ||||||
|                 snprintf(error, error_len, "No keycode defined for %s", line_tmp); |                 snprintf(error, error_len, "No keycode defined for %s", line_tmp); | ||||||
| @ -329,7 +333,7 @@ static int32_t | |||||||
|         if((key & 0xFF00) != 0) { |         if((key & 0xFF00) != 0) { | ||||||
|             // It's a modifier key
 |             // It's a modifier key
 | ||||||
|             line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; |             line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||||
|             key |= ducky_get_keycode(line_tmp, true); |             key |= ducky_get_keycode(bad_usb, line_tmp, true); | ||||||
|         } |         } | ||||||
|         furi_hal_hid_kb_press(key); |         furi_hal_hid_kb_press(key); | ||||||
|         furi_hal_hid_kb_release(key); |         furi_hal_hid_kb_release(key); | ||||||
| @ -650,12 +654,19 @@ static int32_t bad_usb_worker(void* context) { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void bad_usb_script_set_default_keyboard_layout(BadUsbScript* bad_usb) { | ||||||
|  |     furi_assert(bad_usb); | ||||||
|  |     memset(bad_usb->layout, HID_KEYBOARD_NONE, sizeof(bad_usb->layout)); | ||||||
|  |     memcpy(bad_usb->layout, hid_asciimap, MIN(sizeof(hid_asciimap), sizeof(bad_usb->layout))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BadUsbScript* bad_usb_script_open(FuriString* file_path) { | BadUsbScript* bad_usb_script_open(FuriString* file_path) { | ||||||
|     furi_assert(file_path); |     furi_assert(file_path); | ||||||
| 
 | 
 | ||||||
|     BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); |     BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); | ||||||
|     bad_usb->file_path = furi_string_alloc(); |     bad_usb->file_path = furi_string_alloc(); | ||||||
|     furi_string_set(bad_usb->file_path, file_path); |     furi_string_set(bad_usb->file_path, file_path); | ||||||
|  |     bad_usb_script_set_default_keyboard_layout(bad_usb); | ||||||
| 
 | 
 | ||||||
|     bad_usb->st.state = BadUsbStateInit; |     bad_usb->st.state = BadUsbStateInit; | ||||||
|     bad_usb->st.error[0] = '\0'; |     bad_usb->st.error[0] = '\0'; | ||||||
| @ -674,6 +685,30 @@ void bad_usb_script_close(BadUsbScript* bad_usb) { | |||||||
|     free(bad_usb); |     free(bad_usb); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layout_path) { | ||||||
|  |     furi_assert(bad_usb); | ||||||
|  | 
 | ||||||
|  |     if((bad_usb->st.state == BadUsbStateRunning) || (bad_usb->st.state == BadUsbStateDelay)) { | ||||||
|  |         // do not update keyboard layout while a script is running
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); | ||||||
|  |     if(!furi_string_empty(layout_path)) { | ||||||
|  |         if(storage_file_open( | ||||||
|  |                layout_file, furi_string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) { | ||||||
|  |             uint16_t layout[128]; | ||||||
|  |             if(storage_file_read(layout_file, layout, sizeof(layout)) == sizeof(layout)) { | ||||||
|  |                 memcpy(bad_usb->layout, layout, sizeof(layout)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         storage_file_close(layout_file); | ||||||
|  |     } else { | ||||||
|  |         bad_usb_script_set_default_keyboard_layout(bad_usb); | ||||||
|  |     } | ||||||
|  |     storage_file_free(layout_file); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void bad_usb_script_toggle(BadUsbScript* bad_usb) { | void bad_usb_script_toggle(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), WorkerEvtToggle); | ||||||
|  | |||||||
| @ -33,6 +33,8 @@ BadUsbScript* bad_usb_script_open(FuriString* file_path); | |||||||
| 
 | 
 | ||||||
| void bad_usb_script_close(BadUsbScript* bad_usb); | void bad_usb_script_close(BadUsbScript* bad_usb); | ||||||
| 
 | 
 | ||||||
|  | void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layout_path); | ||||||
|  | 
 | ||||||
| void bad_usb_script_start(BadUsbScript* bad_usb); | void bad_usb_script_start(BadUsbScript* bad_usb); | ||||||
| 
 | 
 | ||||||
| void bad_usb_script_stop(BadUsbScript* bad_usb); | void bad_usb_script_stop(BadUsbScript* bad_usb); | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								applications/main/bad_usb/bad_usb_settings_filename.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								applications/main/bad_usb/bad_usb_settings_filename.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #define BAD_USB_SETTINGS_FILE_NAME ".badusb.settings" | ||||||
							
								
								
									
										53
									
								
								applications/main/bad_usb/scenes/bad_usb_scene_config.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								applications/main/bad_usb/scenes/bad_usb_scene_config.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | #include "../bad_usb_app_i.h" | ||||||
|  | #include "furi_hal_power.h" | ||||||
|  | #include "furi_hal_usb.h" | ||||||
|  | 
 | ||||||
|  | enum SubmenuIndex { | ||||||
|  |     SubmenuIndexKeyboardLayout, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void bad_usb_scene_config_submenu_callback(void* context, uint32_t index) { | ||||||
|  |     BadUsbApp* bad_usb = context; | ||||||
|  |     view_dispatcher_send_custom_event(bad_usb->view_dispatcher, index); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void bad_usb_scene_config_on_enter(void* context) { | ||||||
|  |     BadUsbApp* bad_usb = context; | ||||||
|  |     Submenu* submenu = bad_usb->submenu; | ||||||
|  | 
 | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Keyboard layout", | ||||||
|  |         SubmenuIndexKeyboardLayout, | ||||||
|  |         bad_usb_scene_config_submenu_callback, | ||||||
|  |         bad_usb); | ||||||
|  | 
 | ||||||
|  |     submenu_set_selected_item( | ||||||
|  |         submenu, scene_manager_get_scene_state(bad_usb->scene_manager, BadUsbSceneConfig)); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewConfig); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool bad_usb_scene_config_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     BadUsbApp* bad_usb = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         scene_manager_set_scene_state(bad_usb->scene_manager, BadUsbSceneConfig, event.event); | ||||||
|  |         consumed = true; | ||||||
|  |         if(event.event == SubmenuIndexKeyboardLayout) { | ||||||
|  |             scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigLayout); | ||||||
|  |         } else { | ||||||
|  |             furi_crash("Unknown key type"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void bad_usb_scene_config_on_exit(void* context) { | ||||||
|  |     BadUsbApp* bad_usb = context; | ||||||
|  |     Submenu* submenu = bad_usb->submenu; | ||||||
|  | 
 | ||||||
|  |     submenu_reset(submenu); | ||||||
|  | } | ||||||
| @ -1,3 +1,5 @@ | |||||||
| ADD_SCENE(bad_usb, file_select, FileSelect) | ADD_SCENE(bad_usb, file_select, FileSelect) | ||||||
| ADD_SCENE(bad_usb, work, Work) | ADD_SCENE(bad_usb, work, Work) | ||||||
| ADD_SCENE(bad_usb, error, Error) | ADD_SCENE(bad_usb, error, Error) | ||||||
|  | ADD_SCENE(bad_usb, config, Config) | ||||||
|  | ADD_SCENE(bad_usb, config_layout, ConfigLayout) | ||||||
|  | |||||||
| @ -0,0 +1,50 @@ | |||||||
|  | #include "../bad_usb_app_i.h" | ||||||
|  | #include "furi_hal_power.h" | ||||||
|  | #include "furi_hal_usb.h" | ||||||
|  | #include <storage/storage.h> | ||||||
|  | 
 | ||||||
|  | static bool bad_usb_layout_select(BadUsbApp* bad_usb) { | ||||||
|  |     furi_assert(bad_usb); | ||||||
|  | 
 | ||||||
|  |     FuriString* predefined_path; | ||||||
|  |     predefined_path = furi_string_alloc(); | ||||||
|  |     if(!furi_string_empty(bad_usb->keyboard_layout)) { | ||||||
|  |         furi_string_set(predefined_path, bad_usb->keyboard_layout); | ||||||
|  |     } else { | ||||||
|  |         furi_string_set(predefined_path, BAD_USB_APP_PATH_LAYOUT_FOLDER); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     DialogsFileBrowserOptions browser_options; | ||||||
|  |     dialog_file_browser_set_basic_options( | ||||||
|  |         &browser_options, BAD_USB_APP_LAYOUT_EXTENSION, &I_keyboard_10px); | ||||||
|  |     browser_options.base_path = BAD_USB_APP_PATH_LAYOUT_FOLDER; | ||||||
|  |     browser_options.skip_assets = false; | ||||||
|  | 
 | ||||||
|  |     // Input events and views are managed by file_browser
 | ||||||
|  |     bool res = dialog_file_browser_show( | ||||||
|  |         bad_usb->dialogs, bad_usb->keyboard_layout, predefined_path, &browser_options); | ||||||
|  | 
 | ||||||
|  |     furi_string_free(predefined_path); | ||||||
|  |     return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void bad_usb_scene_config_layout_on_enter(void* context) { | ||||||
|  |     BadUsbApp* bad_usb = context; | ||||||
|  | 
 | ||||||
|  |     if(bad_usb_layout_select(bad_usb)) { | ||||||
|  |         bad_usb_script_set_keyboard_layout(bad_usb->bad_usb_script, bad_usb->keyboard_layout); | ||||||
|  |     } | ||||||
|  |     scene_manager_previous_scene(bad_usb->scene_manager); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool bad_usb_scene_config_layout_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     UNUSED(context); | ||||||
|  |     UNUSED(event); | ||||||
|  |     // BadUsbApp* bad_usb = context;
 | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void bad_usb_scene_config_layout_on_exit(void* context) { | ||||||
|  |     UNUSED(context); | ||||||
|  |     // BadUsbApp* bad_usb = context;
 | ||||||
|  | } | ||||||
| @ -7,8 +7,10 @@ static bool bad_usb_file_select(BadUsbApp* bad_usb) { | |||||||
|     furi_assert(bad_usb); |     furi_assert(bad_usb); | ||||||
| 
 | 
 | ||||||
|     DialogsFileBrowserOptions browser_options; |     DialogsFileBrowserOptions browser_options; | ||||||
|     dialog_file_browser_set_basic_options(&browser_options, BAD_USB_APP_EXTENSION, &I_badusb_10px); |     dialog_file_browser_set_basic_options( | ||||||
|     browser_options.base_path = BAD_USB_APP_PATH_FOLDER; |         &browser_options, BAD_USB_APP_SCRIPT_EXTENSION, &I_badusb_10px); | ||||||
|  |     browser_options.base_path = BAD_USB_APP_BASE_FOLDER; | ||||||
|  |     browser_options.skip_assets = true; | ||||||
| 
 | 
 | ||||||
|     // Input events and views are managed by file_browser
 |     // Input events and views are managed by file_browser
 | ||||||
|     bool res = dialog_file_browser_show( |     bool res = dialog_file_browser_show( | ||||||
| @ -21,12 +23,18 @@ void bad_usb_scene_file_select_on_enter(void* context) { | |||||||
|     BadUsbApp* bad_usb = context; |     BadUsbApp* bad_usb = context; | ||||||
| 
 | 
 | ||||||
|     furi_hal_usb_disable(); |     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; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if(bad_usb_file_select(bad_usb)) { |     if(bad_usb_file_select(bad_usb)) { | ||||||
|  |         bad_usb->bad_usb_script = bad_usb_script_open(bad_usb->file_path); | ||||||
|  |         bad_usb_script_set_keyboard_layout(bad_usb->bad_usb_script, bad_usb->keyboard_layout); | ||||||
|  | 
 | ||||||
|         scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneWork); |         scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneWork); | ||||||
|     } else { |     } else { | ||||||
|         furi_hal_usb_enable(); |         furi_hal_usb_enable(); | ||||||
|         //scene_manager_previous_scene(bad_usb->scene_manager);
 |  | ||||||
|         view_dispatcher_stop(bad_usb->view_dispatcher); |         view_dispatcher_stop(bad_usb->view_dispatcher); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,10 +4,10 @@ | |||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| #include "toolbox/path.h" | #include "toolbox/path.h" | ||||||
| 
 | 
 | ||||||
| void bad_usb_scene_work_ok_callback(InputType type, void* context) { | void bad_usb_scene_work_button_callback(InputKey key, void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     BadUsbApp* app = context; |     BadUsbApp* app = context; | ||||||
|     view_dispatcher_send_custom_event(app->view_dispatcher, type); |     view_dispatcher_send_custom_event(app->view_dispatcher, key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) { | bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) { | ||||||
| @ -15,8 +15,13 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) { | |||||||
|     bool consumed = false; |     bool consumed = false; | ||||||
| 
 | 
 | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         bad_usb_script_toggle(app->bad_usb_script); |         if(event.event == InputKeyLeft) { | ||||||
|         consumed = true; |             scene_manager_next_scene(app->scene_manager, BadUsbSceneConfig); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == InputKeyOk) { | ||||||
|  |             bad_usb_script_toggle(app->bad_usb_script); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|     } else if(event.type == SceneManagerEventTypeTick) { |     } else if(event.type == SceneManagerEventTypeTick) { | ||||||
|         bad_usb_set_state(app->bad_usb_view, bad_usb_script_get_state(app->bad_usb_script)); |         bad_usb_set_state(app->bad_usb_view, bad_usb_script_get_state(app->bad_usb_script)); | ||||||
|     } |     } | ||||||
| @ -28,20 +33,22 @@ void bad_usb_scene_work_on_enter(void* context) { | |||||||
| 
 | 
 | ||||||
|     FuriString* file_name; |     FuriString* file_name; | ||||||
|     file_name = furi_string_alloc(); |     file_name = furi_string_alloc(); | ||||||
| 
 |  | ||||||
|     path_extract_filename(app->file_path, file_name, true); |     path_extract_filename(app->file_path, file_name, true); | ||||||
|     bad_usb_set_file_name(app->bad_usb_view, furi_string_get_cstr(file_name)); |     bad_usb_set_file_name(app->bad_usb_view, furi_string_get_cstr(file_name)); | ||||||
|     app->bad_usb_script = bad_usb_script_open(app->file_path); |  | ||||||
| 
 |  | ||||||
|     furi_string_free(file_name); |     furi_string_free(file_name); | ||||||
| 
 | 
 | ||||||
|  |     FuriString* layout; | ||||||
|  |     layout = furi_string_alloc(); | ||||||
|  |     path_extract_filename(app->keyboard_layout, layout, true); | ||||||
|  |     bad_usb_set_layout(app->bad_usb_view, furi_string_get_cstr(layout)); | ||||||
|  |     furi_string_free(layout); | ||||||
|  | 
 | ||||||
|     bad_usb_set_state(app->bad_usb_view, bad_usb_script_get_state(app->bad_usb_script)); |     bad_usb_set_state(app->bad_usb_view, bad_usb_script_get_state(app->bad_usb_script)); | ||||||
| 
 | 
 | ||||||
|     bad_usb_set_ok_callback(app->bad_usb_view, bad_usb_scene_work_ok_callback, app); |     bad_usb_set_button_callback(app->bad_usb_view, bad_usb_scene_work_button_callback, app); | ||||||
|     view_dispatcher_switch_to_view(app->view_dispatcher, BadUsbAppViewWork); |     view_dispatcher_switch_to_view(app->view_dispatcher, BadUsbAppViewWork); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void bad_usb_scene_work_on_exit(void* context) { | void bad_usb_scene_work_on_exit(void* context) { | ||||||
|     BadUsbApp* app = context; |     UNUSED(context); | ||||||
|     bad_usb_script_close(app->bad_usb_script); |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| #include "bad_usb_view.h" | #include "bad_usb_view.h" | ||||||
| #include "../bad_usb_script.h" | #include "../bad_usb_script.h" | ||||||
|  | #include <toolbox/path.h> | ||||||
| #include <gui/elements.h> | #include <gui/elements.h> | ||||||
| #include <assets_icons.h> | #include <assets_icons.h> | ||||||
| 
 | 
 | ||||||
| @ -7,12 +8,13 @@ | |||||||
| 
 | 
 | ||||||
| struct BadUsb { | struct BadUsb { | ||||||
|     View* view; |     View* view; | ||||||
|     BadUsbOkCallback callback; |     BadUsbButtonCallback callback; | ||||||
|     void* context; |     void* context; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     char file_name[MAX_NAME_LEN]; |     char file_name[MAX_NAME_LEN]; | ||||||
|  |     char layout[MAX_NAME_LEN]; | ||||||
|     BadUsbState state; |     BadUsbState state; | ||||||
|     uint8_t anim_frame; |     uint8_t anim_frame; | ||||||
| } BadUsbModel; | } BadUsbModel; | ||||||
| @ -25,9 +27,23 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { | |||||||
|     elements_string_fit_width(canvas, disp_str, 128 - 2); |     elements_string_fit_width(canvas, disp_str, 128 - 2); | ||||||
|     canvas_set_font(canvas, FontSecondary); |     canvas_set_font(canvas, FontSecondary); | ||||||
|     canvas_draw_str(canvas, 2, 8, furi_string_get_cstr(disp_str)); |     canvas_draw_str(canvas, 2, 8, furi_string_get_cstr(disp_str)); | ||||||
|  | 
 | ||||||
|  |     if(strlen(model->layout) == 0) { | ||||||
|  |         furi_string_set(disp_str, "(default)"); | ||||||
|  |     } else { | ||||||
|  |         furi_string_reset(disp_str); | ||||||
|  |         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); | ||||||
|  |     canvas_draw_str( | ||||||
|  |         canvas, 2, 8 + canvas_current_font_height(canvas), furi_string_get_cstr(disp_str)); | ||||||
|  | 
 | ||||||
|     furi_string_reset(disp_str); |     furi_string_reset(disp_str); | ||||||
| 
 | 
 | ||||||
|     canvas_draw_icon(canvas, 22, 20, &I_UsbTree_48x22); |     canvas_draw_icon(canvas, 22, 24, &I_UsbTree_48x22); | ||||||
| 
 | 
 | ||||||
|     if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone) || |     if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone) || | ||||||
|        (model->state.state == BadUsbStateNotConnected)) { |        (model->state.state == BadUsbStateNotConnected)) { | ||||||
| @ -38,23 +54,28 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { | |||||||
|         elements_button_center(canvas, "Cancel"); |         elements_button_center(canvas, "Cancel"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if((model->state.state == BadUsbStateNotConnected) || | ||||||
|  |        (model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone)) { | ||||||
|  |         elements_button_left(canvas, "Config"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if(model->state.state == BadUsbStateNotConnected) { |     if(model->state.state == BadUsbStateNotConnected) { | ||||||
|         canvas_draw_icon(canvas, 4, 22, &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, 27, AlignRight, AlignBottom, "Connect"); |         canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect"); | ||||||
|         canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "to USB"); |         canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to USB"); | ||||||
|     } else if(model->state.state == BadUsbStateWillRun) { |     } else if(model->state.state == BadUsbStateWillRun) { | ||||||
|         canvas_draw_icon(canvas, 4, 22, &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, 27, AlignRight, AlignBottom, "Will run"); |         canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run"); | ||||||
|         canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "on connect"); |         canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect"); | ||||||
|     } else if(model->state.state == BadUsbStateFileError) { |     } else if(model->state.state == BadUsbStateFileError) { | ||||||
|         canvas_draw_icon(canvas, 4, 22, &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, 27, AlignRight, AlignBottom, "File"); |         canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "File"); | ||||||
|         canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "ERROR"); |         canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "ERROR"); | ||||||
|     } else if(model->state.state == BadUsbStateScriptError) { |     } else if(model->state.state == BadUsbStateScriptError) { | ||||||
|         canvas_draw_icon(canvas, 4, 22, &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:"); | ||||||
|         canvas_set_font(canvas, FontSecondary); |         canvas_set_font(canvas, FontSecondary); | ||||||
| @ -64,49 +85,49 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { | |||||||
|         furi_string_reset(disp_str); |         furi_string_reset(disp_str); | ||||||
|         canvas_draw_str_aligned(canvas, 127, 56, AlignRight, AlignBottom, model->state.error); |         canvas_draw_str_aligned(canvas, 127, 56, AlignRight, AlignBottom, model->state.error); | ||||||
|     } else if(model->state.state == BadUsbStateIdle) { |     } else if(model->state.state == BadUsbStateIdle) { | ||||||
|         canvas_draw_icon(canvas, 4, 22, &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, 36, AlignRight, AlignBottom, "0"); |         canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "0"); | ||||||
|         canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); |         canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); | ||||||
|     } else if(model->state.state == BadUsbStateRunning) { |     } else if(model->state.state == BadUsbStateRunning) { | ||||||
|         if(model->anim_frame == 0) { |         if(model->anim_frame == 0) { | ||||||
|             canvas_draw_icon(canvas, 4, 19, &I_EviSmile1_18x21); |             canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21); | ||||||
|         } else { |         } else { | ||||||
|             canvas_draw_icon(canvas, 4, 19, &I_EviSmile2_18x21); |             canvas_draw_icon(canvas, 4, 23, &I_EviSmile2_18x21); | ||||||
|         } |         } | ||||||
|         canvas_set_font(canvas, FontBigNumbers); |         canvas_set_font(canvas, FontBigNumbers); | ||||||
|         furi_string_printf( |         furi_string_printf( | ||||||
|             disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); |             disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); | ||||||
|         canvas_draw_str_aligned( |         canvas_draw_str_aligned( | ||||||
|             canvas, 114, 36, 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, 22, &I_Percent_10x14); |         canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); | ||||||
|     } else if(model->state.state == BadUsbStateDone) { |     } else if(model->state.state == BadUsbStateDone) { | ||||||
|         canvas_draw_icon(canvas, 4, 19, &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, 36, 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, 22, &I_Percent_10x14); |         canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); | ||||||
|     } else if(model->state.state == BadUsbStateDelay) { |     } else if(model->state.state == BadUsbStateDelay) { | ||||||
|         if(model->anim_frame == 0) { |         if(model->anim_frame == 0) { | ||||||
|             canvas_draw_icon(canvas, 4, 19, &I_EviWaiting1_18x21); |             canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21); | ||||||
|         } else { |         } else { | ||||||
|             canvas_draw_icon(canvas, 4, 19, &I_EviWaiting2_18x21); |             canvas_draw_icon(canvas, 4, 23, &I_EviWaiting2_18x21); | ||||||
|         } |         } | ||||||
|         canvas_set_font(canvas, FontBigNumbers); |         canvas_set_font(canvas, FontBigNumbers); | ||||||
|         furi_string_printf( |         furi_string_printf( | ||||||
|             disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); |             disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); | ||||||
|         canvas_draw_str_aligned( |         canvas_draw_str_aligned( | ||||||
|             canvas, 114, 36, 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, 22, &I_Percent_10x14); |         canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); | ||||||
|         canvas_set_font(canvas, FontSecondary); |         canvas_set_font(canvas, FontSecondary); | ||||||
|         furi_string_printf(disp_str, "delay %lus", model->state.delay_remain); |         furi_string_printf(disp_str, "delay %lus", model->state.delay_remain); | ||||||
|         canvas_draw_str_aligned( |         canvas_draw_str_aligned( | ||||||
|             canvas, 127, 46, 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 { |     } else { | ||||||
|         canvas_draw_icon(canvas, 4, 22, &I_Clock_18x18); |         canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_string_free(disp_str); |     furi_string_free(disp_str); | ||||||
| @ -118,10 +139,10 @@ 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 == InputKeyOk) { |         if((event->key == InputKeyLeft) || (event->key == InputKeyOk)) { | ||||||
|             consumed = true; |             consumed = true; | ||||||
|             furi_assert(bad_usb->callback); |             furi_assert(bad_usb->callback); | ||||||
|             bad_usb->callback(InputTypeShort, bad_usb->context); |             bad_usb->callback(event->key, bad_usb->context); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -151,7 +172,7 @@ View* bad_usb_get_view(BadUsb* bad_usb) { | |||||||
|     return bad_usb->view; |     return bad_usb->view; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* context) { | void bad_usb_set_button_callback(BadUsb* bad_usb, BadUsbButtonCallback callback, void* context) { | ||||||
|     furi_assert(bad_usb); |     furi_assert(bad_usb); | ||||||
|     furi_assert(callback); |     furi_assert(callback); | ||||||
|     with_view_model( |     with_view_model( | ||||||
| @ -174,6 +195,14 @@ void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) { | |||||||
|         true); |         true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void bad_usb_set_layout(BadUsb* bad_usb, const char* layout) { | ||||||
|  |     furi_assert(layout); | ||||||
|  |     with_view_model( | ||||||
|  |         bad_usb->view, | ||||||
|  |         BadUsbModel * model, | ||||||
|  |         { strlcpy(model->layout, layout, MAX_NAME_LEN); }, | ||||||
|  |         true); | ||||||
|  | } | ||||||
| void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) { | void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) { | ||||||
|     furi_assert(st); |     furi_assert(st); | ||||||
|     with_view_model( |     with_view_model( | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
| #include "../bad_usb_script.h" | #include "../bad_usb_script.h" | ||||||
| 
 | 
 | ||||||
| typedef struct BadUsb BadUsb; | typedef struct BadUsb BadUsb; | ||||||
| typedef void (*BadUsbOkCallback)(InputType type, void* context); | typedef void (*BadUsbButtonCallback)(InputKey key, void* context); | ||||||
| 
 | 
 | ||||||
| BadUsb* bad_usb_alloc(); | BadUsb* bad_usb_alloc(); | ||||||
| 
 | 
 | ||||||
| @ -12,8 +12,10 @@ void bad_usb_free(BadUsb* bad_usb); | |||||||
| 
 | 
 | ||||||
| View* bad_usb_get_view(BadUsb* bad_usb); | View* bad_usb_get_view(BadUsb* bad_usb); | ||||||
| 
 | 
 | ||||||
| void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* context); | void bad_usb_set_button_callback(BadUsb* bad_usb, BadUsbButtonCallback callback, void* context); | ||||||
| 
 | 
 | ||||||
| void bad_usb_set_file_name(BadUsb* bad_usb, const char* name); | void bad_usb_set_file_name(BadUsb* bad_usb, const char* name); | ||||||
| 
 | 
 | ||||||
|  | void bad_usb_set_layout(BadUsb* bad_usb, const char* layout); | ||||||
|  | 
 | ||||||
| void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st); | void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st); | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Archive/keyboard_10px.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Archive/keyboard_10px.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 147 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/ba-BA.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/ba-BA.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/cz_CS.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/cz_CS.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/da-DA.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/da-DA.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/de-CH.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/de-CH.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/de-DE.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/de-DE.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/dvorak.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/dvorak.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/en-UK.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/en-UK.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/en-US.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/en-US.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/es-ES.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/es-ES.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/fr-BE.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/fr-BE.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/fr-CH.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/fr-CH.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/fr-FR.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/fr-FR.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/hr-HR.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/hr-HR.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/hu-HU.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/hu-HU.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/it-IT.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/it-IT.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/nb-NO.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/nb-NO.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/nl-NL.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/nl-NL.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/pt-BR.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/pt-BR.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/pt-PT.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/pt-PT.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/si-SI.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/si-SI.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/sk-SK.kl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/sk-SK.kl
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/sv-SE.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/sv-SE.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/tr-TR.kl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/resources/badusb/assets/layouts/tr-TR.kl
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 MX
						MX