From d4cd06816cd7b1b2dee1ebef8ea8654ff778a50b Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Fri, 5 Apr 2024 05:33:43 +0100 Subject: [PATCH] JS: Add badusb layout support --- .../examples/apps/Scripts/badusb_demo.js | 8 ++- .../system/js_app/modules/js_badusb.c | 50 ++++++++++++++----- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/applications/system/js_app/examples/apps/Scripts/badusb_demo.js b/applications/system/js_app/examples/apps/Scripts/badusb_demo.js index 8605020233..be94a64d2a 100644 --- a/applications/system/js_app/examples/apps/Scripts/badusb_demo.js +++ b/applications/system/js_app/examples/apps/Scripts/badusb_demo.js @@ -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()) { diff --git a/applications/system/js_app/modules/js_badusb.c b/applications/system/js_app/modules/js_badusb.c index a380141e84..1722f66726 100644 --- a/applications/system/js_app/modules/js_badusb.c +++ b/applications/system/js_app/modules/js_badusb.c @@ -2,8 +2,11 @@ #include "../js_modules.h" #include +#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; @@ -88,7 +91,11 @@ 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; } @@ -96,6 +103,7 @@ static bool setup_parse_params(struct mjs* mjs, mjs_val_t arg, FuriHalUsbHidConf 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); @@ -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; } @@ -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, ""); @@ -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++) { @@ -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); @@ -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; @@ -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, ""); @@ -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, ""); @@ -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, ""); @@ -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 } @@ -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); }