Skip to content

Commit

Permalink
js add badusb layout support
Browse files Browse the repository at this point in the history
by Willy-JL
  • Loading branch information
xMasterX committed Apr 5, 2024
1 parent 22cf19d commit 6e4d32b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ let notify = require("notification");
let flipper = require("flipper");
let dialog = require("dialog");

badusb.setup({ vid: 0xAAAA, pid: 0xBBBB, mfr_name: "Flipper", prod_name: "Zero" });
badusb.setup({
vid: 0xAAAA,
pid: 0xBBBB,
mfr_name: "Flipper",
prod_name: "Zero",
layout_path: "/ext/badusb/assets/layouts/en-US.kl"
});
dialog.message("BadUSB demo", "Press OK to start");

if (badusb.isConnected()) {
Expand Down
50 changes: 37 additions & 13 deletions applications/system/js_app/modules/js_badusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
#include "../js_modules.h"
#include <furi_hal.h>

#define ASCII_TO_KEY(layout, x) (((uint8_t)x < 128) ? (layout[(uint8_t)x]) : HID_KEYBOARD_NONE)

typedef struct {
FuriHalUsbHidConfig* hid_cfg;
uint16_t layout[128];
FuriHalUsbInterface* usb_if_prev;
uint8_t key_hold_cnt;
} JsBadusbInst;
Expand Down Expand Up @@ -88,14 +91,19 @@ static void js_badusb_quit_free(JsBadusbInst* badusb) {
}
}

static bool setup_parse_params(struct mjs* mjs, mjs_val_t arg, FuriHalUsbHidConfig* hid_cfg) {
static bool setup_parse_params(
JsBadusbInst* badusb,
struct mjs* mjs,
mjs_val_t arg,
FuriHalUsbHidConfig* hid_cfg) {
if(!mjs_is_object(arg)) {
return false;
}
mjs_val_t vid_obj = mjs_get(mjs, arg, "vid", ~0);
mjs_val_t pid_obj = mjs_get(mjs, arg, "pid", ~0);
mjs_val_t mfr_obj = mjs_get(mjs, arg, "mfr_name", ~0);
mjs_val_t prod_obj = mjs_get(mjs, arg, "prod_name", ~0);
mjs_val_t layout_obj = mjs_get(mjs, arg, "layout_path", ~0);

if(mjs_is_number(vid_obj) && mjs_is_number(pid_obj)) {
hid_cfg->vid = mjs_get_int32(mjs, vid_obj);
Expand All @@ -122,6 +130,22 @@ static bool setup_parse_params(struct mjs* mjs, mjs_val_t arg, FuriHalUsbHidConf
strlcpy(hid_cfg->product, str_temp, sizeof(hid_cfg->product));
}

if(mjs_is_string(layout_obj)) {
size_t str_len = 0;
const char* str_temp = mjs_get_string(mjs, &layout_obj, &str_len);
File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
size_t size = sizeof(badusb->layout);

if((str_len == 0) || (str_temp == NULL) ||
!storage_file_open(file, str_temp, FSAM_READ, FSOM_OPEN_EXISTING) ||
storage_file_read(file, badusb->layout, size) != size) {
memcpy(badusb->layout, hid_asciimap, MIN(sizeof(hid_asciimap), size));
}

storage_file_free(file);
furi_record_close(RECORD_STORAGE);
}

return true;
}

Expand All @@ -144,7 +168,7 @@ static void js_badusb_setup(struct mjs* mjs) {
} else if(num_args == 1) {
badusb->hid_cfg = malloc(sizeof(FuriHalUsbHidConfig));
// Parse argument object
args_correct = setup_parse_params(mjs, mjs_arg(mjs, 0), badusb->hid_cfg);
args_correct = setup_parse_params(badusb, mjs, mjs_arg(mjs, 0), badusb->hid_cfg);
}
if(!args_correct) {
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
Expand Down Expand Up @@ -191,9 +215,9 @@ static void js_badusb_is_connected(struct mjs* mjs) {
mjs_return(mjs, mjs_mk_boolean(mjs, is_connected));
}

uint16_t get_keycode_by_name(const char* key_name, size_t name_len) {
uint16_t get_keycode_by_name(JsBadusbInst* badusb, const char* key_name, size_t name_len) {
if(name_len == 1) { // Single char
return (HID_ASCII_TO_KEY(key_name[0]));
return (ASCII_TO_KEY(badusb->layout, key_name[0]));
}

for(size_t i = 0; i < COUNT_OF(key_codes); i++) {
Expand All @@ -210,7 +234,7 @@ uint16_t get_keycode_by_name(const char* key_name, size_t name_len) {
return HID_KEYBOARD_NONE;
}

static bool parse_keycode(struct mjs* mjs, size_t nargs, uint16_t* keycode) {
static bool parse_keycode(JsBadusbInst* badusb, struct mjs* mjs, size_t nargs, uint16_t* keycode) {
uint16_t key_tmp = 0;
for(size_t i = 0; i < nargs; i++) {
mjs_val_t arg = mjs_arg(mjs, i);
Expand All @@ -221,7 +245,7 @@ static bool parse_keycode(struct mjs* mjs, size_t nargs, uint16_t* keycode) {
// String error
return false;
}
uint16_t str_key = get_keycode_by_name(key_name, name_len);
uint16_t str_key = get_keycode_by_name(badusb, key_name, name_len);
if(str_key == HID_KEYBOARD_NONE) {
// Unknown key code
return false;
Expand Down Expand Up @@ -259,7 +283,7 @@ static void js_badusb_press(struct mjs* mjs) {
uint16_t keycode = HID_KEYBOARD_NONE;
size_t num_args = mjs_nargs(mjs);
if(num_args > 0) {
args_correct = parse_keycode(mjs, num_args, &keycode);
args_correct = parse_keycode(badusb, mjs, num_args, &keycode);
}
if(!args_correct) {
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
Expand All @@ -285,7 +309,7 @@ static void js_badusb_hold(struct mjs* mjs) {
uint16_t keycode = HID_KEYBOARD_NONE;
size_t num_args = mjs_nargs(mjs);
if(num_args > 0) {
args_correct = parse_keycode(mjs, num_args, &keycode);
args_correct = parse_keycode(badusb, mjs, num_args, &keycode);
}
if(!args_correct) {
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
Expand Down Expand Up @@ -324,7 +348,7 @@ static void js_badusb_release(struct mjs* mjs) {
mjs_return(mjs, MJS_UNDEFINED);
return;
} else {
args_correct = parse_keycode(mjs, num_args, &keycode);
args_correct = parse_keycode(badusb, mjs, num_args, &keycode);
}
if(!args_correct) {
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
Expand All @@ -347,14 +371,14 @@ static void ducky_numlock_on() {
}

// Simulate pressing a character using ALT+Numpad ASCII code
static void ducky_altchar(const char* ascii_code) {
static void ducky_altchar(JsBadusbInst* badusb, const char* ascii_code) {
// Hold the ALT key
furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT);

// Press the corresponding numpad key for each digit of the ASCII code
for(size_t i = 0; ascii_code[i] != '\0'; i++) {
char digitChar[5] = {'N', 'U', 'M', ascii_code[i], '\0'}; // Construct the numpad key name
uint16_t numpad_keycode = get_keycode_by_name(digitChar, strlen(digitChar));
uint16_t numpad_keycode = get_keycode_by_name(badusb, digitChar, strlen(digitChar));
if(numpad_keycode == HID_KEYBOARD_NONE) {
continue; // Skip if keycode not found
}
Expand Down Expand Up @@ -420,9 +444,9 @@ static void badusb_print(struct mjs* mjs, bool ln, bool alt) {
// Convert character to ascii numeric value
char ascii_str[4];
snprintf(ascii_str, sizeof(ascii_str), "%u", (uint8_t)text_str[i]);
ducky_altchar(ascii_str);
ducky_altchar(badusb, ascii_str);
} else {
uint16_t keycode = HID_ASCII_TO_KEY(text_str[i]);
uint16_t keycode = ASCII_TO_KEY(badusb->layout, text_str[i]);
furi_hal_hid_kb_press(keycode);
furi_hal_hid_kb_release(keycode);
}
Expand Down

0 comments on commit 6e4d32b

Please sign in to comment.