mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 12:42:30 +04:00
js add badusb layout support
by Willy-JL
This commit is contained in:
@@ -3,7 +3,13 @@ let notify = require("notification");
|
|||||||
let flipper = require("flipper");
|
let flipper = require("flipper");
|
||||||
let dialog = require("dialog");
|
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");
|
dialog.message("BadUSB demo", "Press OK to start");
|
||||||
|
|
||||||
if (badusb.isConnected()) {
|
if (badusb.isConnected()) {
|
||||||
|
|||||||
@@ -2,8 +2,11 @@
|
|||||||
#include "../js_modules.h"
|
#include "../js_modules.h"
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
#define ASCII_TO_KEY(layout, x) (((uint8_t)x < 128) ? (layout[(uint8_t)x]) : HID_KEYBOARD_NONE)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FuriHalUsbHidConfig* hid_cfg;
|
FuriHalUsbHidConfig* hid_cfg;
|
||||||
|
uint16_t layout[128];
|
||||||
FuriHalUsbInterface* usb_if_prev;
|
FuriHalUsbInterface* usb_if_prev;
|
||||||
uint8_t key_hold_cnt;
|
uint8_t key_hold_cnt;
|
||||||
} JsBadusbInst;
|
} 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)) {
|
if(!mjs_is_object(arg)) {
|
||||||
return false;
|
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 pid_obj = mjs_get(mjs, arg, "pid", ~0);
|
||||||
mjs_val_t mfr_obj = mjs_get(mjs, arg, "mfr_name", ~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 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)) {
|
if(mjs_is_number(vid_obj) && mjs_is_number(pid_obj)) {
|
||||||
hid_cfg->vid = mjs_get_int32(mjs, vid_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));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +168,7 @@ static void js_badusb_setup(struct mjs* mjs) {
|
|||||||
} else if(num_args == 1) {
|
} else if(num_args == 1) {
|
||||||
badusb->hid_cfg = malloc(sizeof(FuriHalUsbHidConfig));
|
badusb->hid_cfg = malloc(sizeof(FuriHalUsbHidConfig));
|
||||||
// Parse argument object
|
// 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) {
|
if(!args_correct) {
|
||||||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
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));
|
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
|
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++) {
|
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;
|
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;
|
uint16_t key_tmp = 0;
|
||||||
for(size_t i = 0; i < nargs; i++) {
|
for(size_t i = 0; i < nargs; i++) {
|
||||||
mjs_val_t arg = mjs_arg(mjs, 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
|
// String error
|
||||||
return false;
|
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) {
|
if(str_key == HID_KEYBOARD_NONE) {
|
||||||
// Unknown key code
|
// Unknown key code
|
||||||
return false;
|
return false;
|
||||||
@@ -259,7 +283,7 @@ static void js_badusb_press(struct mjs* mjs) {
|
|||||||
uint16_t keycode = HID_KEYBOARD_NONE;
|
uint16_t keycode = HID_KEYBOARD_NONE;
|
||||||
size_t num_args = mjs_nargs(mjs);
|
size_t num_args = mjs_nargs(mjs);
|
||||||
if(num_args > 0) {
|
if(num_args > 0) {
|
||||||
args_correct = parse_keycode(mjs, num_args, &keycode);
|
args_correct = parse_keycode(badusb, mjs, num_args, &keycode);
|
||||||
}
|
}
|
||||||
if(!args_correct) {
|
if(!args_correct) {
|
||||||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
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;
|
uint16_t keycode = HID_KEYBOARD_NONE;
|
||||||
size_t num_args = mjs_nargs(mjs);
|
size_t num_args = mjs_nargs(mjs);
|
||||||
if(num_args > 0) {
|
if(num_args > 0) {
|
||||||
args_correct = parse_keycode(mjs, num_args, &keycode);
|
args_correct = parse_keycode(badusb, mjs, num_args, &keycode);
|
||||||
}
|
}
|
||||||
if(!args_correct) {
|
if(!args_correct) {
|
||||||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
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);
|
mjs_return(mjs, MJS_UNDEFINED);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
args_correct = parse_keycode(mjs, num_args, &keycode);
|
args_correct = parse_keycode(badusb, mjs, num_args, &keycode);
|
||||||
}
|
}
|
||||||
if(!args_correct) {
|
if(!args_correct) {
|
||||||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
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
|
// 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
|
// Hold the ALT key
|
||||||
furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT);
|
furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT);
|
||||||
|
|
||||||
// Press the corresponding numpad key for each digit of the ASCII code
|
// Press the corresponding numpad key for each digit of the ASCII code
|
||||||
for(size_t i = 0; ascii_code[i] != '\0'; i++) {
|
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
|
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) {
|
if(numpad_keycode == HID_KEYBOARD_NONE) {
|
||||||
continue; // Skip if keycode not found
|
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
|
// Convert character to ascii numeric value
|
||||||
char ascii_str[4];
|
char ascii_str[4];
|
||||||
snprintf(ascii_str, sizeof(ascii_str), "%u", (uint8_t)text_str[i]);
|
snprintf(ascii_str, sizeof(ascii_str), "%u", (uint8_t)text_str[i]);
|
||||||
ducky_altchar(ascii_str);
|
ducky_altchar(badusb, ascii_str);
|
||||||
} else {
|
} 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_press(keycode);
|
||||||
furi_hal_hid_kb_release(keycode);
|
furi_hal_hid_kb_release(keycode);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user