Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions applications/archive/helpers/archive_browser.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ static const char* known_ext[] = {
[ArchiveFileTypeLFRFID] = ".rfid",
[ArchiveFileTypeInfrared] = ".ir",
[ArchiveFileTypeBadUsb] = ".txt",
[ArchiveFileTypeKeyboard] = ".kl",
[ArchiveFileTypeU2f] = "?",
[ArchiveFileTypeUpdateManifest] = ".fuf",
[ArchiveFileTypeFolder] = "?",
Expand Down
1 change: 1 addition & 0 deletions applications/archive/helpers/archive_files.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ typedef enum {
ArchiveFileTypeFolder,
ArchiveFileTypeUnknown,
ArchiveFileTypeLoading,
ArchiveFileTypeKeyboard,
} ArchiveFileTypeEnum;

typedef struct {
Expand Down
1 change: 1 addition & 0 deletions applications/archive/views/archive_browser_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ static const Icon* ArchiveItemIcons[] = {
[ArchiveFileTypeFolder] = &I_dir_10px,
[ArchiveFileTypeUnknown] = &I_unknown_10px,
[ArchiveFileTypeLoading] = &I_loading_10px,
[ArchiveFileTypeKeyboard] = &I_keyboard_10px,
};

void archive_browser_set_callback(
Expand Down
54 changes: 52 additions & 2 deletions applications/bad_usb/bad_usb_app.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#include "bad_usb_app_i.h"
#include "bad_usb_settings_filename.h"
#include "m-string.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;
Expand All @@ -23,15 +26,45 @@ 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)) {
string_push_back(app->keyboard_layout, chr);
}
}
storage_file_close(settings_file);
storage_file_free(settings_file);
}

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,
string_get_cstr(app->keyboard_layout),
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));

string_init(app->file_path);
app->bad_usb_script = NULL;

string_init(app->file_path);
string_init(app->keyboard_layout);
if(arg && strlen(arg)) {
string_set_str(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);
Expand All @@ -54,6 +87,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));
Expand All @@ -67,7 +104,7 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
if(!string_empty_p(app->file_path)) {
scene_manager_next_scene(app->scene_manager, BadUsbSceneWork);
} else {
string_set_str(app->file_path, BAD_USB_APP_PATH_FOLDER);
string_set_str(app->file_path, BAD_USB_APP_PATH_SCRIPT_FOLDER);
scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect);
}
}
Expand All @@ -78,14 +115,24 @@ 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);
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfigLayout);
bad_usb_free(app->bad_usb_view);

// Custom Widget
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);
Expand All @@ -95,7 +142,10 @@ void bad_usb_app_free(BadUsbApp* app) {
furi_record_close(RECORD_NOTIFICATION);
furi_record_close(RECORD_DIALOGS);

bad_usb_save_settings(app);

string_clear(app->file_path);
string_clear(app->keyboard_layout);

free(app);
}
Expand Down
11 changes: 9 additions & 2 deletions applications/bad_usb/bad_usb_app_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
#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_SCRIPT_FOLDER BAD_USB_APP_BASE_FOLDER "/scripts"
#define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/layouts"
#define BAD_USB_APP_SCRIPT_EXTENSION ".txt"
#define BAD_USB_APP_LAYOUT_EXTENSION ".kl"

typedef enum {
BadUsbAppErrorNoFiles,
Expand All @@ -29,14 +32,18 @@ struct BadUsbApp {
NotificationApp* notifications;
DialogsApp* dialogs;
Widget* widget;
Submenu* submenu;

BadUsbAppError error;
string_t file_path;
string_t keyboard_layout;
BadUsb* bad_usb_view;
BadUsbScript* bad_usb_script;
};

typedef enum {
BadUsbAppViewError,
BadUsbAppViewWork,
BadUsbAppViewConfig,
BadUsbAppViewConfigLayout,
} BadUsbAppView;
49 changes: 42 additions & 7 deletions applications/bad_usb/bad_usb_script.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -28,6 +31,7 @@ struct BadUsbScript {
BadUsbState st;
string_t file_path;
uint32_t defdelay;
uint16_t layout[128];
FuriThread* thread;
uint8_t file_buf[FILE_BUFFER_LEN + 1];
uint8_t buf_start;
Expand Down Expand Up @@ -203,10 +207,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);
Expand All @@ -216,7 +220,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(uint8_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) {
uint8_t key_cmd_len = strlen(ducky_keys[i].name);
if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) &&
Expand All @@ -225,7 +229,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;
}
Expand Down Expand Up @@ -271,7 +275,7 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
} 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);
return (state) ? (0) : SCRIPT_STATE_ERROR;
} else if(strncmp(line_tmp, ducky_cmd_altchar, strlen(ducky_cmd_altchar)) == 0) {
// ALTCHAR
Expand All @@ -294,12 +298,12 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
return (state) ? (0) : SCRIPT_STATE_ERROR;
} 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) return SCRIPT_STATE_ERROR;
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);
Expand Down Expand Up @@ -585,12 +589,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(string_t file_path) {
furi_assert(file_path);

BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript));
string_init(bad_usb->file_path);
string_set(bad_usb->file_path, file_path);
bad_usb_script_set_default_keyboard_layout(bad_usb);

bad_usb->st.state = BadUsbStateInit;

Expand All @@ -613,6 +624,30 @@ void bad_usb_script_close(BadUsbScript* bad_usb) {
free(bad_usb);
}

void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, string_t 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(!string_empty_p(layout_path)) {
if(storage_file_open(
layout_file, 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);
Expand Down
2 changes: 2 additions & 0 deletions applications/bad_usb/bad_usb_script.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ BadUsbScript* bad_usb_script_open(string_t file_path);

void bad_usb_script_close(BadUsbScript* bad_usb);

void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, string_t layout_path);

void bad_usb_script_start(BadUsbScript* bad_usb);

void bad_usb_script_stop(BadUsbScript* bad_usb);
Expand Down
3 changes: 3 additions & 0 deletions applications/bad_usb/bad_usb_settings_filename.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

#define BAD_USB_SETTINGS_FILE_NAME ".badusb.settings"
53 changes: 53 additions & 0 deletions applications/bad_usb/scenes/bad_usb_scene_config.c
Original file line number Diff line number Diff line change
@@ -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);
}
2 changes: 2 additions & 0 deletions applications/bad_usb/scenes/bad_usb_scene_config.h
Original file line number Diff line number Diff line change
@@ -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)
Loading