Skip to content

Commit 1a110d7

Browse files
committed
Merge branch 'pr/167' into badUSB
2 parents f519d69 + ba34380 commit 1a110d7

33 files changed

+288
-72
lines changed

applications/archive/helpers/archive_browser.h

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ static const char* known_ext[] = {
2626
[ArchiveFileTypeLFRFID] = ".rfid",
2727
[ArchiveFileTypeInfrared] = ".ir",
2828
[ArchiveFileTypeBadUsb] = ".txt",
29+
[ArchiveFileTypeKeyboard] = ".kl",
2930
[ArchiveFileTypeU2f] = "?",
3031
[ArchiveFileTypeUpdateManifest] = ".fuf",
3132
[ArchiveFileTypeFolder] = "?",

applications/archive/helpers/archive_files.h

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ typedef enum {
1616
ArchiveFileTypeFolder,
1717
ArchiveFileTypeUnknown,
1818
ArchiveFileTypeLoading,
19+
ArchiveFileTypeKeyboard,
1920
} ArchiveFileTypeEnum;
2021

2122
typedef struct {

applications/archive/views/archive_browser_view.c

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static const Icon* ArchiveItemIcons[] = {
2929
[ArchiveFileTypeFolder] = &I_dir_10px,
3030
[ArchiveFileTypeUnknown] = &I_unknown_10px,
3131
[ArchiveFileTypeLoading] = &I_loading_10px,
32+
[ArchiveFileTypeKeyboard] = &I_keyboard_10px,
3233
};
3334

3435
void archive_browser_set_callback(

applications/bad_usb/bad_usb_app.c

+52-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
#include "bad_usb_app_i.h"
2+
#include "bad_usb_settings_filename.h"
23
#include "m-string.h"
34
#include <furi.h>
45
#include <furi_hal.h>
56
#include <storage/storage.h>
67
#include <lib/toolbox/path.h>
78

9+
#define BAD_USB_SETTINGS_PATH BAD_USB_APP_BASE_FOLDER "/" BAD_USB_SETTINGS_FILE_NAME
10+
811
static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) {
912
furi_assert(context);
1013
BadUsbApp* app = context;
@@ -23,15 +26,45 @@ static void bad_usb_app_tick_event_callback(void* context) {
2326
scene_manager_handle_tick_event(app->scene_manager);
2427
}
2528

29+
static void bad_usb_load_settings(BadUsbApp* app) {
30+
File* settings_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
31+
if(storage_file_open(settings_file, BAD_USB_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
32+
char chr;
33+
while((storage_file_read(settings_file, &chr, 1) == 1) &&
34+
!storage_file_eof(settings_file) && !isspace(chr)) {
35+
string_push_back(app->keyboard_layout, chr);
36+
}
37+
}
38+
storage_file_close(settings_file);
39+
storage_file_free(settings_file);
40+
}
41+
42+
static void bad_usb_save_settings(BadUsbApp* app) {
43+
File* settings_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
44+
if(storage_file_open(settings_file, BAD_USB_SETTINGS_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) {
45+
storage_file_write(
46+
settings_file,
47+
string_get_cstr(app->keyboard_layout),
48+
string_size(app->keyboard_layout));
49+
storage_file_write(settings_file, "\n", 1);
50+
}
51+
storage_file_close(settings_file);
52+
storage_file_free(settings_file);
53+
}
54+
2655
BadUsbApp* bad_usb_app_alloc(char* arg) {
2756
BadUsbApp* app = malloc(sizeof(BadUsbApp));
2857

29-
string_init(app->file_path);
58+
app->bad_usb_script = NULL;
3059

60+
string_init(app->file_path);
61+
string_init(app->keyboard_layout);
3162
if(arg && strlen(arg)) {
3263
string_set_str(app->file_path, arg);
3364
}
3465

66+
bad_usb_load_settings(app);
67+
3568
app->gui = furi_record_open(RECORD_GUI);
3669
app->notifications = furi_record_open(RECORD_NOTIFICATION);
3770
app->dialogs = furi_record_open(RECORD_DIALOGS);
@@ -54,6 +87,10 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
5487
view_dispatcher_add_view(
5588
app->view_dispatcher, BadUsbAppViewError, widget_get_view(app->widget));
5689

90+
app->submenu = submenu_alloc();
91+
view_dispatcher_add_view(
92+
app->view_dispatcher, BadUsbAppViewConfig, submenu_get_view(app->submenu));
93+
5794
app->bad_usb_view = bad_usb_alloc();
5895
view_dispatcher_add_view(
5996
app->view_dispatcher, BadUsbAppViewWork, bad_usb_get_view(app->bad_usb_view));
@@ -67,7 +104,7 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
67104
if(!string_empty_p(app->file_path)) {
68105
scene_manager_next_scene(app->scene_manager, BadUsbSceneWork);
69106
} else {
70-
string_set_str(app->file_path, BAD_USB_APP_PATH_FOLDER);
107+
string_set_str(app->file_path, BAD_USB_APP_PATH_SCRIPT_FOLDER);
71108
scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect);
72109
}
73110
}
@@ -78,14 +115,24 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
78115
void bad_usb_app_free(BadUsbApp* app) {
79116
furi_assert(app);
80117

118+
if(app->bad_usb_script) {
119+
bad_usb_script_close(app->bad_usb_script);
120+
app->bad_usb_script = NULL;
121+
}
122+
81123
// Views
82124
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork);
125+
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfigLayout);
83126
bad_usb_free(app->bad_usb_view);
84127

85128
// Custom Widget
86129
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewError);
87130
widget_free(app->widget);
88131

132+
// Submenu
133+
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfig);
134+
submenu_free(app->submenu);
135+
89136
// View dispatcher
90137
view_dispatcher_free(app->view_dispatcher);
91138
scene_manager_free(app->scene_manager);
@@ -95,7 +142,10 @@ void bad_usb_app_free(BadUsbApp* app) {
95142
furi_record_close(RECORD_NOTIFICATION);
96143
furi_record_close(RECORD_DIALOGS);
97144

145+
bad_usb_save_settings(app);
146+
98147
string_clear(app->file_path);
148+
string_clear(app->keyboard_layout);
99149

100150
free(app);
101151
}

applications/bad_usb/bad_usb_app_i.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
#include <gui/modules/widget.h>
1515
#include "views/bad_usb_view.h"
1616

17-
#define BAD_USB_APP_PATH_FOLDER ANY_PATH("badusb")
18-
#define BAD_USB_APP_EXTENSION ".txt"
17+
#define BAD_USB_APP_BASE_FOLDER ANY_PATH("badusb")
18+
#define BAD_USB_APP_PATH_SCRIPT_FOLDER BAD_USB_APP_BASE_FOLDER "/scripts"
19+
#define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/layouts"
20+
#define BAD_USB_APP_SCRIPT_EXTENSION ".txt"
21+
#define BAD_USB_APP_LAYOUT_EXTENSION ".kl"
1922

2023
typedef enum {
2124
BadUsbAppErrorNoFiles,
@@ -29,14 +32,18 @@ struct BadUsbApp {
2932
NotificationApp* notifications;
3033
DialogsApp* dialogs;
3134
Widget* widget;
35+
Submenu* submenu;
3236

3337
BadUsbAppError error;
3438
string_t file_path;
39+
string_t keyboard_layout;
3540
BadUsb* bad_usb_view;
3641
BadUsbScript* bad_usb_script;
3742
};
3843

3944
typedef enum {
4045
BadUsbAppViewError,
4146
BadUsbAppViewWork,
47+
BadUsbAppViewConfig,
48+
BadUsbAppViewConfigLayout,
4249
} BadUsbAppView;

applications/bad_usb/bad_usb_script.c

+42-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#define SCRIPT_STATE_END (-2)
1717
#define SCRIPT_STATE_NEXT_LINE (-3)
1818

19+
#define BADUSB_ASCII_TO_KEY(script, x) \
20+
(((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE)
21+
1922
typedef enum {
2023
WorkerEvtToggle = (1 << 0),
2124
WorkerEvtEnd = (1 << 1),
@@ -28,6 +31,7 @@ struct BadUsbScript {
2831
BadUsbState st;
2932
string_t file_path;
3033
uint32_t defdelay;
34+
uint16_t layout[128];
3135
FuriThread* thread;
3236
uint8_t file_buf[FILE_BUFFER_LEN + 1];
3337
uint8_t buf_start;
@@ -203,10 +207,10 @@ static bool ducky_altstring(const char* param) {
203207
return state;
204208
}
205209

206-
static bool ducky_string(const char* param) {
210+
static bool ducky_string(BadUsbScript* bad_usb, const char* param) {
207211
uint32_t i = 0;
208212
while(param[i] != '\0') {
209-
uint16_t keycode = HID_ASCII_TO_KEY(param[i]);
213+
uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_usb, param[i]);
210214
if(keycode != HID_KEYBOARD_NONE) {
211215
furi_hal_hid_kb_press(keycode);
212216
furi_hal_hid_kb_release(keycode);
@@ -216,7 +220,7 @@ static bool ducky_string(const char* param) {
216220
return true;
217221
}
218222

219-
static uint16_t ducky_get_keycode(const char* param, bool accept_chars) {
223+
static uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept_chars) {
220224
for(uint8_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) {
221225
uint8_t key_cmd_len = strlen(ducky_keys[i].name);
222226
if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) &&
@@ -225,7 +229,7 @@ static uint16_t ducky_get_keycode(const char* param, bool accept_chars) {
225229
}
226230
}
227231
if((accept_chars) && (strlen(param) > 0)) {
228-
return (HID_ASCII_TO_KEY(param[0]) & 0xFF);
232+
return (BADUSB_ASCII_TO_KEY(bad_usb, param[0]) & 0xFF);
229233
}
230234
return 0;
231235
}
@@ -271,7 +275,7 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
271275
} else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) {
272276
// STRING
273277
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
274-
state = ducky_string(line_tmp);
278+
state = ducky_string(bad_usb, line_tmp);
275279
return (state) ? (0) : SCRIPT_STATE_ERROR;
276280
} else if(strncmp(line_tmp, ducky_cmd_altchar, strlen(ducky_cmd_altchar)) == 0) {
277281
// ALTCHAR
@@ -294,12 +298,12 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
294298
return (state) ? (0) : SCRIPT_STATE_ERROR;
295299
} else {
296300
// Special keys + modifiers
297-
uint16_t key = ducky_get_keycode(line_tmp, false);
301+
uint16_t key = ducky_get_keycode(bad_usb, line_tmp, false);
298302
if(key == HID_KEYBOARD_NONE) return SCRIPT_STATE_ERROR;
299303
if((key & 0xFF00) != 0) {
300304
// It's a modifier key
301305
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
302-
key |= ducky_get_keycode(line_tmp, true);
306+
key |= ducky_get_keycode(bad_usb, line_tmp, true);
303307
}
304308
furi_hal_hid_kb_press(key);
305309
furi_hal_hid_kb_release(key);
@@ -585,12 +589,19 @@ static int32_t bad_usb_worker(void* context) {
585589
return 0;
586590
}
587591

592+
static void bad_usb_script_set_default_keyboard_layout(BadUsbScript* bad_usb) {
593+
furi_assert(bad_usb);
594+
memset(bad_usb->layout, HID_KEYBOARD_NONE, sizeof(bad_usb->layout));
595+
memcpy(bad_usb->layout, hid_asciimap, MIN(sizeof(hid_asciimap), sizeof(bad_usb->layout)));
596+
}
597+
588598
BadUsbScript* bad_usb_script_open(string_t file_path) {
589599
furi_assert(file_path);
590600

591601
BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript));
592602
string_init(bad_usb->file_path);
593603
string_set(bad_usb->file_path, file_path);
604+
bad_usb_script_set_default_keyboard_layout(bad_usb);
594605

595606
bad_usb->st.state = BadUsbStateInit;
596607

@@ -613,6 +624,30 @@ void bad_usb_script_close(BadUsbScript* bad_usb) {
613624
free(bad_usb);
614625
}
615626

627+
void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, string_t layout_path) {
628+
furi_assert(bad_usb);
629+
630+
if((bad_usb->st.state == BadUsbStateRunning) || (bad_usb->st.state == BadUsbStateDelay)) {
631+
// do not update keyboard layout while a script is running
632+
return;
633+
}
634+
635+
File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
636+
if(!string_empty_p(layout_path)) {
637+
if(storage_file_open(
638+
layout_file, string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
639+
uint16_t layout[128];
640+
if(storage_file_read(layout_file, layout, sizeof(layout)) == sizeof(layout)) {
641+
memcpy(bad_usb->layout, layout, sizeof(layout));
642+
}
643+
}
644+
storage_file_close(layout_file);
645+
} else {
646+
bad_usb_script_set_default_keyboard_layout(bad_usb);
647+
}
648+
storage_file_free(layout_file);
649+
}
650+
616651
void bad_usb_script_toggle(BadUsbScript* bad_usb) {
617652
furi_assert(bad_usb);
618653
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtToggle);

applications/bad_usb/bad_usb_script.h

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ BadUsbScript* bad_usb_script_open(string_t file_path);
3232

3333
void bad_usb_script_close(BadUsbScript* bad_usb);
3434

35+
void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, string_t layout_path);
36+
3537
void bad_usb_script_start(BadUsbScript* bad_usb);
3638

3739
void bad_usb_script_stop(BadUsbScript* bad_usb);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
#define BAD_USB_SETTINGS_FILE_NAME ".badusb.settings"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include "../bad_usb_app_i.h"
2+
#include "furi_hal_power.h"
3+
#include "furi_hal_usb.h"
4+
5+
enum SubmenuIndex {
6+
SubmenuIndexKeyboardLayout,
7+
};
8+
9+
void bad_usb_scene_config_submenu_callback(void* context, uint32_t index) {
10+
BadUsbApp* bad_usb = context;
11+
view_dispatcher_send_custom_event(bad_usb->view_dispatcher, index);
12+
}
13+
14+
void bad_usb_scene_config_on_enter(void* context) {
15+
BadUsbApp* bad_usb = context;
16+
Submenu* submenu = bad_usb->submenu;
17+
18+
submenu_add_item(
19+
submenu,
20+
"Keyboard layout",
21+
SubmenuIndexKeyboardLayout,
22+
bad_usb_scene_config_submenu_callback,
23+
bad_usb);
24+
25+
submenu_set_selected_item(
26+
submenu, scene_manager_get_scene_state(bad_usb->scene_manager, BadUsbSceneConfig));
27+
28+
view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewConfig);
29+
}
30+
31+
bool bad_usb_scene_config_on_event(void* context, SceneManagerEvent event) {
32+
BadUsbApp* bad_usb = context;
33+
bool consumed = false;
34+
35+
if(event.type == SceneManagerEventTypeCustom) {
36+
scene_manager_set_scene_state(bad_usb->scene_manager, BadUsbSceneConfig, event.event);
37+
consumed = true;
38+
if(event.event == SubmenuIndexKeyboardLayout) {
39+
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigLayout);
40+
} else {
41+
furi_crash("Unknown key type");
42+
}
43+
}
44+
45+
return consumed;
46+
}
47+
48+
void bad_usb_scene_config_on_exit(void* context) {
49+
BadUsbApp* bad_usb = context;
50+
Submenu* submenu = bad_usb->submenu;
51+
52+
submenu_reset(submenu);
53+
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
ADD_SCENE(bad_usb, file_select, FileSelect)
22
ADD_SCENE(bad_usb, work, Work)
33
ADD_SCENE(bad_usb, error, Error)
4+
ADD_SCENE(bad_usb, config, Config)
5+
ADD_SCENE(bad_usb, config_layout, ConfigLayout)

0 commit comments

Comments
 (0)