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_settings_filename.h" | ||||
| #include <furi.h> | ||||
| #include <furi_hal.h> | ||||
| #include <storage/storage.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) { | ||||
|     furi_assert(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); | ||||
| } | ||||
| 
 | ||||
| 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* 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)) { | ||||
|         furi_string_set(app->file_path, arg); | ||||
|     } | ||||
| 
 | ||||
|     bad_usb_load_settings(app); | ||||
| 
 | ||||
|     app->gui = furi_record_open(RECORD_GUI); | ||||
|     app->notifications = furi_record_open(RECORD_NOTIFICATION); | ||||
|     app->dialogs = furi_record_open(RECORD_DIALOGS); | ||||
| @ -53,6 +103,10 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { | ||||
|     view_dispatcher_add_view( | ||||
|         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(); | ||||
|     view_dispatcher_add_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); | ||||
|     } else { | ||||
|         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); | ||||
|         } 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); | ||||
|         } | ||||
|     } | ||||
| @ -77,6 +133,11 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { | ||||
| void bad_usb_app_free(BadUsbApp* app) { | ||||
|     furi_assert(app); | ||||
| 
 | ||||
|     if(app->bad_usb_script) { | ||||
|         bad_usb_script_close(app->bad_usb_script); | ||||
|         app->bad_usb_script = NULL; | ||||
|     } | ||||
| 
 | ||||
|     // Views
 | ||||
|     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); | ||||
|     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); | ||||
|     widget_free(app->widget); | ||||
| 
 | ||||
|     // Submenu
 | ||||
|     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfig); | ||||
|     submenu_free(app->submenu); | ||||
| 
 | ||||
|     // View dispatcher
 | ||||
|     view_dispatcher_free(app->view_dispatcher); | ||||
|     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_DIALOGS); | ||||
| 
 | ||||
|     bad_usb_save_settings(app); | ||||
| 
 | ||||
|     furi_string_free(app->file_path); | ||||
|     furi_string_free(app->keyboard_layout); | ||||
| 
 | ||||
|     free(app); | ||||
| } | ||||
|  | ||||
| @ -15,8 +15,10 @@ | ||||
| #include <gui/modules/widget.h> | ||||
| #include "views/bad_usb_view.h" | ||||
| 
 | ||||
| #define BAD_USB_APP_PATH_FOLDER ANY_PATH("badusb") | ||||
| #define BAD_USB_APP_EXTENSION ".txt" | ||||
| #define BAD_USB_APP_BASE_FOLDER ANY_PATH("badusb") | ||||
| #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 { | ||||
|     BadUsbAppErrorNoFiles, | ||||
| @ -30,9 +32,11 @@ struct BadUsbApp { | ||||
|     NotificationApp* notifications; | ||||
|     DialogsApp* dialogs; | ||||
|     Widget* widget; | ||||
|     Submenu* submenu; | ||||
| 
 | ||||
|     BadUsbAppError error; | ||||
|     FuriString* file_path; | ||||
|     FuriString* keyboard_layout; | ||||
|     BadUsb* bad_usb_view; | ||||
|     BadUsbScript* bad_usb_script; | ||||
| }; | ||||
| @ -40,4 +44,5 @@ struct BadUsbApp { | ||||
| typedef enum { | ||||
|     BadUsbAppViewError, | ||||
|     BadUsbAppViewWork, | ||||
|     BadUsbAppViewConfig, | ||||
| } BadUsbAppView; | ||||
| @ -16,6 +16,9 @@ | ||||
| #define SCRIPT_STATE_END (-2) | ||||
| #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 { | ||||
|     WorkerEvtToggle = (1 << 0), | ||||
|     WorkerEvtEnd = (1 << 1), | ||||
| @ -28,6 +31,7 @@ struct BadUsbScript { | ||||
|     BadUsbState st; | ||||
|     FuriString* file_path; | ||||
|     uint32_t defdelay; | ||||
|     uint16_t layout[128]; | ||||
|     FuriThread* thread; | ||||
|     uint8_t file_buf[FILE_BUFFER_LEN + 1]; | ||||
|     uint8_t buf_start; | ||||
| @ -205,10 +209,10 @@ static bool ducky_altstring(const char* param) { | ||||
|     return state; | ||||
| } | ||||
| 
 | ||||
| static bool ducky_string(const char* param) { | ||||
| static bool ducky_string(BadUsbScript* bad_usb, const char* param) { | ||||
|     uint32_t 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) { | ||||
|             furi_hal_hid_kb_press(keycode); | ||||
|             furi_hal_hid_kb_release(keycode); | ||||
| @ -218,7 +222,7 @@ static bool ducky_string(const char* param) { | ||||
|     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++) { | ||||
|         size_t key_cmd_len = strlen(ducky_keys[i].name); | ||||
|         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)) { | ||||
|         return (HID_ASCII_TO_KEY(param[0]) & 0xFF); | ||||
|         return (BADUSB_ASCII_TO_KEY(bad_usb, param[0]) & 0xFF); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| @ -276,7 +280,7 @@ static int32_t | ||||
|     } else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) { | ||||
|         // STRING
 | ||||
|         line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; | ||||
|         state = ducky_string(line_tmp); | ||||
|         state = ducky_string(bad_usb, line_tmp); | ||||
|         if(!state && error != NULL) { | ||||
|             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) { | ||||
|         // SYSRQ
 | ||||
|         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); | ||||
|         furi_hal_hid_kb_release_all(); | ||||
|         return (0); | ||||
|     } else { | ||||
|         // 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(error != NULL) { | ||||
|                 snprintf(error, error_len, "No keycode defined for %s", line_tmp); | ||||
| @ -329,7 +333,7 @@ static int32_t | ||||
|         if((key & 0xFF00) != 0) { | ||||
|             // It's a modifier key
 | ||||
|             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_release(key); | ||||
| @ -650,12 +654,19 @@ static int32_t bad_usb_worker(void* context) { | ||||
|     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) { | ||||
|     furi_assert(file_path); | ||||
| 
 | ||||
|     BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); | ||||
|     bad_usb->file_path = furi_string_alloc(); | ||||
|     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.error[0] = '\0'; | ||||
| @ -674,6 +685,30 @@ void bad_usb_script_close(BadUsbScript* 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) { | ||||
|     furi_assert(bad_usb); | ||||
|     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_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layout_path); | ||||
| 
 | ||||
| void bad_usb_script_start(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, work, Work) | ||||
| 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); | ||||
| 
 | ||||
|     DialogsFileBrowserOptions browser_options; | ||||
|     dialog_file_browser_set_basic_options(&browser_options, BAD_USB_APP_EXTENSION, &I_badusb_10px); | ||||
|     browser_options.base_path = BAD_USB_APP_PATH_FOLDER; | ||||
|     dialog_file_browser_set_basic_options( | ||||
|         &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
 | ||||
|     bool res = dialog_file_browser_show( | ||||
| @ -21,12 +23,18 @@ void bad_usb_scene_file_select_on_enter(void* context) { | ||||
|     BadUsbApp* bad_usb = context; | ||||
| 
 | ||||
|     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)) { | ||||
|         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); | ||||
|     } else { | ||||
|         furi_hal_usb_enable(); | ||||
|         //scene_manager_previous_scene(bad_usb->scene_manager);
 | ||||
|         view_dispatcher_stop(bad_usb->view_dispatcher); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -4,10 +4,10 @@ | ||||
| #include <furi_hal.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); | ||||
|     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) { | ||||
| @ -15,8 +15,13 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == InputKeyLeft) { | ||||
|             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) { | ||||
|         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; | ||||
|     file_name = furi_string_alloc(); | ||||
| 
 | ||||
|     path_extract_filename(app->file_path, file_name, true); | ||||
|     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); | ||||
| 
 | ||||
|     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_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); | ||||
| } | ||||
| 
 | ||||
| void bad_usb_scene_work_on_exit(void* context) { | ||||
|     BadUsbApp* app = context; | ||||
|     bad_usb_script_close(app->bad_usb_script); | ||||
|     UNUSED(context); | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| #include "bad_usb_view.h" | ||||
| #include "../bad_usb_script.h" | ||||
| #include <toolbox/path.h> | ||||
| #include <gui/elements.h> | ||||
| #include <assets_icons.h> | ||||
| 
 | ||||
| @ -7,12 +8,13 @@ | ||||
| 
 | ||||
| struct BadUsb { | ||||
|     View* view; | ||||
|     BadUsbOkCallback callback; | ||||
|     BadUsbButtonCallback callback; | ||||
|     void* context; | ||||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
|     char file_name[MAX_NAME_LEN]; | ||||
|     char layout[MAX_NAME_LEN]; | ||||
|     BadUsbState state; | ||||
|     uint8_t anim_frame; | ||||
| } BadUsbModel; | ||||
| @ -25,9 +27,23 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { | ||||
|     elements_string_fit_width(canvas, disp_str, 128 - 2); | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
|     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); | ||||
| 
 | ||||
|     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) || | ||||
|        (model->state.state == BadUsbStateNotConnected)) { | ||||
| @ -38,23 +54,28 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { | ||||
|         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) { | ||||
|         canvas_draw_icon(canvas, 4, 22, &I_Clock_18x18); | ||||
|         canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); | ||||
|         canvas_set_font(canvas, FontPrimary); | ||||
|         canvas_draw_str_aligned(canvas, 127, 27, AlignRight, AlignBottom, "Connect"); | ||||
|         canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "to USB"); | ||||
|         canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect"); | ||||
|         canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to USB"); | ||||
|     } 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_draw_str_aligned(canvas, 127, 27, AlignRight, AlignBottom, "Will run"); | ||||
|         canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "on connect"); | ||||
|         canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run"); | ||||
|         canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect"); | ||||
|     } 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_draw_str_aligned(canvas, 127, 27, AlignRight, AlignBottom, "File"); | ||||
|         canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "ERROR"); | ||||
|         canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "File"); | ||||
|         canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "ERROR"); | ||||
|     } 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_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:"); | ||||
|         canvas_set_font(canvas, FontSecondary); | ||||
| @ -64,49 +85,49 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { | ||||
|         furi_string_reset(disp_str); | ||||
|         canvas_draw_str_aligned(canvas, 127, 56, AlignRight, AlignBottom, model->state.error); | ||||
|     } 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_draw_str_aligned(canvas, 114, 36, AlignRight, AlignBottom, "0"); | ||||
|         canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); | ||||
|         canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "0"); | ||||
|         canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); | ||||
|     } else if(model->state.state == BadUsbStateRunning) { | ||||
|         if(model->anim_frame == 0) { | ||||
|             canvas_draw_icon(canvas, 4, 19, &I_EviSmile1_18x21); | ||||
|             canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21); | ||||
|         } else { | ||||
|             canvas_draw_icon(canvas, 4, 19, &I_EviSmile2_18x21); | ||||
|             canvas_draw_icon(canvas, 4, 23, &I_EviSmile2_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, 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); | ||||
|         canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); | ||||
|         canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); | ||||
|     } 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_draw_str_aligned(canvas, 114, 36, AlignRight, AlignBottom, "100"); | ||||
|         canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "100"); | ||||
|         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) { | ||||
|         if(model->anim_frame == 0) { | ||||
|             canvas_draw_icon(canvas, 4, 19, &I_EviWaiting1_18x21); | ||||
|             canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21); | ||||
|         } else { | ||||
|             canvas_draw_icon(canvas, 4, 19, &I_EviWaiting2_18x21); | ||||
|             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, 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); | ||||
|         canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); | ||||
|         canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); | ||||
|         canvas_set_font(canvas, FontSecondary); | ||||
|         furi_string_printf(disp_str, "delay %lus", model->state.delay_remain); | ||||
|         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); | ||||
|     } else { | ||||
|         canvas_draw_icon(canvas, 4, 22, &I_Clock_18x18); | ||||
|         canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); | ||||
|     } | ||||
| 
 | ||||
|     furi_string_free(disp_str); | ||||
| @ -118,10 +139,10 @@ static bool bad_usb_input_callback(InputEvent* event, void* context) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == InputTypeShort) { | ||||
|         if(event->key == InputKeyOk) { | ||||
|         if((event->key == InputKeyLeft) || (event->key == InputKeyOk)) { | ||||
|             consumed = true; | ||||
|             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; | ||||
| } | ||||
| 
 | ||||
| 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(callback); | ||||
|     with_view_model( | ||||
| @ -174,6 +195,14 @@ void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) { | ||||
|         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) { | ||||
|     furi_assert(st); | ||||
|     with_view_model( | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| #include "../bad_usb_script.h" | ||||
| 
 | ||||
| typedef struct BadUsb BadUsb; | ||||
| typedef void (*BadUsbOkCallback)(InputType type, void* context); | ||||
| typedef void (*BadUsbButtonCallback)(InputKey key, void* context); | ||||
| 
 | ||||
| BadUsb* bad_usb_alloc(); | ||||
| 
 | ||||
| @ -12,8 +12,10 @@ void bad_usb_free(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_layout(BadUsb* bad_usb, const char* layout); | ||||
| 
 | ||||
| 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