mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 04:34:43 +04:00
BadUSB: Mouse control (#4004)
* add usb hid mouse functions, add mouse functions to BadUsbHidApi * add ble mouse functionality * add hid_usb_mouse_release_all * ducky mouse command skeleton * implement mouse click functions * corrected missing semicolon * added mouse functionality * corrected mouse scroll functionality * mouse key functionality, removed mouse commands, supporting get_mouse_keycode function, added mouse buttons as Keys for HOLD function * add mouse commands * removed mouse middle click * Format sources and fix bunch of mistakes in nfc and subghz * added HID_MOUSE_NONE: added to help with better readability * added script for mouse movement test * Fix: hold and release, imrpove readability * simplified the mouse demo/test * Format sources Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -37,6 +37,31 @@ bool hid_usb_kb_release(void* inst, uint16_t button) {
|
||||
return furi_hal_hid_kb_release(button);
|
||||
}
|
||||
|
||||
bool hid_usb_mouse_press(void* inst, uint8_t button) {
|
||||
UNUSED(inst);
|
||||
return furi_hal_hid_mouse_press(button);
|
||||
}
|
||||
|
||||
bool hid_usb_mouse_release(void* inst, uint8_t button) {
|
||||
UNUSED(inst);
|
||||
return furi_hal_hid_mouse_release(button);
|
||||
}
|
||||
|
||||
bool hid_usb_mouse_scroll(void* inst, int8_t delta) {
|
||||
UNUSED(inst);
|
||||
return furi_hal_hid_mouse_scroll(delta);
|
||||
}
|
||||
|
||||
bool hid_usb_mouse_move(void* inst, int8_t dx, int8_t dy) {
|
||||
UNUSED(inst);
|
||||
return furi_hal_hid_mouse_move(dx, dy);
|
||||
}
|
||||
|
||||
bool hid_usb_mouse_release_all(void* inst) {
|
||||
UNUSED(inst);
|
||||
return furi_hal_hid_mouse_release(0);
|
||||
}
|
||||
|
||||
bool hid_usb_consumer_press(void* inst, uint16_t button) {
|
||||
UNUSED(inst);
|
||||
return furi_hal_hid_consumer_key_press(button);
|
||||
@@ -51,6 +76,7 @@ bool hid_usb_release_all(void* inst) {
|
||||
UNUSED(inst);
|
||||
bool state = furi_hal_hid_kb_release_all();
|
||||
state &= furi_hal_hid_consumer_key_release_all();
|
||||
state &= hid_usb_mouse_release_all(inst);
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -67,6 +93,10 @@ static const BadUsbHidApi hid_api_usb = {
|
||||
|
||||
.kb_press = hid_usb_kb_press,
|
||||
.kb_release = hid_usb_kb_release,
|
||||
.mouse_press = hid_usb_mouse_press,
|
||||
.mouse_release = hid_usb_mouse_release,
|
||||
.mouse_scroll = hid_usb_mouse_scroll,
|
||||
.mouse_move = hid_usb_mouse_move,
|
||||
.consumer_press = hid_usb_consumer_press,
|
||||
.consumer_release = hid_usb_consumer_release,
|
||||
.release_all = hid_usb_release_all,
|
||||
@@ -157,6 +187,27 @@ bool hid_ble_kb_release(void* inst, uint16_t button) {
|
||||
return ble_profile_hid_kb_release(ble_hid->profile, button);
|
||||
}
|
||||
|
||||
bool hid_ble_mouse_press(void* inst, uint8_t button) {
|
||||
BleHidInstance* ble_hid = inst;
|
||||
furi_assert(ble_hid);
|
||||
return ble_profile_hid_mouse_press(ble_hid->profile, button);
|
||||
}
|
||||
bool hid_ble_mouse_release(void* inst, uint8_t button) {
|
||||
BleHidInstance* ble_hid = inst;
|
||||
furi_assert(ble_hid);
|
||||
return ble_profile_hid_mouse_release(ble_hid->profile, button);
|
||||
}
|
||||
bool hid_ble_mouse_scroll(void* inst, int8_t delta) {
|
||||
BleHidInstance* ble_hid = inst;
|
||||
furi_assert(ble_hid);
|
||||
return ble_profile_hid_mouse_scroll(ble_hid->profile, delta);
|
||||
}
|
||||
bool hid_ble_mouse_move(void* inst, int8_t dx, int8_t dy) {
|
||||
BleHidInstance* ble_hid = inst;
|
||||
furi_assert(ble_hid);
|
||||
return ble_profile_hid_mouse_move(ble_hid->profile, dx, dy);
|
||||
}
|
||||
|
||||
bool hid_ble_consumer_press(void* inst, uint16_t button) {
|
||||
BleHidInstance* ble_hid = inst;
|
||||
furi_assert(ble_hid);
|
||||
@@ -174,6 +225,7 @@ bool hid_ble_release_all(void* inst) {
|
||||
furi_assert(ble_hid);
|
||||
bool state = ble_profile_hid_kb_release_all(ble_hid->profile);
|
||||
state &= ble_profile_hid_consumer_key_release_all(ble_hid->profile);
|
||||
state &= ble_profile_hid_mouse_release_all(ble_hid->profile);
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -191,6 +243,10 @@ static const BadUsbHidApi hid_api_ble = {
|
||||
|
||||
.kb_press = hid_ble_kb_press,
|
||||
.kb_release = hid_ble_kb_release,
|
||||
.mouse_press = hid_ble_mouse_press,
|
||||
.mouse_release = hid_ble_mouse_release,
|
||||
.mouse_scroll = hid_ble_mouse_scroll,
|
||||
.mouse_move = hid_ble_mouse_move,
|
||||
.consumer_press = hid_ble_consumer_press,
|
||||
.consumer_release = hid_ble_consumer_release,
|
||||
.release_all = hid_ble_release_all,
|
||||
|
||||
@@ -20,6 +20,10 @@ typedef struct {
|
||||
|
||||
bool (*kb_press)(void* inst, uint16_t button);
|
||||
bool (*kb_release)(void* inst, uint16_t button);
|
||||
bool (*mouse_press)(void* inst, uint8_t button);
|
||||
bool (*mouse_release)(void* inst, uint8_t button);
|
||||
bool (*mouse_scroll)(void* inst, int8_t delta);
|
||||
bool (*mouse_move)(void* inst, int8_t dx, int8_t dy);
|
||||
bool (*consumer_press)(void* inst, uint16_t button);
|
||||
bool (*consumer_release)(void* inst, uint16_t button);
|
||||
bool (*release_all)(void* inst);
|
||||
|
||||
@@ -193,8 +193,16 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, FuriString* line) {
|
||||
return cmd_result;
|
||||
}
|
||||
|
||||
// Mouse Keys
|
||||
uint16_t key = ducky_get_mouse_keycode_by_name(line_tmp);
|
||||
if(key != HID_MOUSE_INVALID) {
|
||||
bad_usb->hid->mouse_press(bad_usb->hid_inst, key);
|
||||
bad_usb->hid->mouse_release(bad_usb->hid_inst, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Special keys + modifiers
|
||||
uint16_t key = ducky_get_keycode(bad_usb, line_tmp, false);
|
||||
key = ducky_get_keycode(bad_usb, line_tmp, false);
|
||||
if(key == HID_KEYBOARD_NONE) {
|
||||
return ducky_error(bad_usb, "No keycode defined for %s", line_tmp);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <furi_hal.h>
|
||||
#include <lib/toolbox/strint.h>
|
||||
#include "ducky_script.h"
|
||||
#include "ducky_script_i.h"
|
||||
|
||||
@@ -124,36 +125,60 @@ static int32_t ducky_fnc_altstring(BadUsbScript* bad_usb, const char* line, int3
|
||||
|
||||
static int32_t ducky_fnc_hold(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||
UNUSED(param);
|
||||
|
||||
line = &line[ducky_get_command_len(line) + 1];
|
||||
uint16_t key = ducky_get_keycode(bad_usb, line, true);
|
||||
if(key == HID_KEYBOARD_NONE) {
|
||||
return ducky_error(bad_usb, "No keycode defined for %s", line);
|
||||
}
|
||||
bad_usb->key_hold_nb++;
|
||||
|
||||
if(bad_usb->key_hold_nb > (HID_KB_MAX_KEYS - 1)) {
|
||||
return ducky_error(bad_usb, "Too many keys are hold");
|
||||
return ducky_error(bad_usb, "Too many keys are held");
|
||||
}
|
||||
|
||||
// Handle Mouse Keys here
|
||||
uint16_t key = ducky_get_mouse_keycode_by_name(line);
|
||||
if(key != HID_MOUSE_NONE) {
|
||||
bad_usb->key_hold_nb++;
|
||||
bad_usb->hid->mouse_press(bad_usb->hid_inst, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle Keyboard keys here
|
||||
key = ducky_get_keycode(bad_usb, line, true);
|
||||
if(key != HID_KEYBOARD_NONE) {
|
||||
bad_usb->key_hold_nb++;
|
||||
bad_usb->hid->kb_press(bad_usb->hid_inst, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// keyboard and mouse were none
|
||||
return ducky_error(bad_usb, "Unknown keycode for %s", line);
|
||||
}
|
||||
|
||||
static int32_t ducky_fnc_release(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||
UNUSED(param);
|
||||
|
||||
line = &line[ducky_get_command_len(line) + 1];
|
||||
uint16_t key = ducky_get_keycode(bad_usb, line, true);
|
||||
if(key == HID_KEYBOARD_NONE) {
|
||||
return ducky_error(bad_usb, "No keycode defined for %s", line);
|
||||
}
|
||||
|
||||
if(bad_usb->key_hold_nb == 0) {
|
||||
return ducky_error(bad_usb, "No keys are hold");
|
||||
return ducky_error(bad_usb, "No keys are held");
|
||||
}
|
||||
|
||||
// Handle Mouse Keys here
|
||||
uint16_t key = ducky_get_mouse_keycode_by_name(line);
|
||||
if(key != HID_MOUSE_NONE) {
|
||||
bad_usb->key_hold_nb--;
|
||||
bad_usb->hid->mouse_release(bad_usb->hid_inst, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Handle Keyboard Keys here
|
||||
key = ducky_get_keycode(bad_usb, line, true);
|
||||
if(key != HID_KEYBOARD_NONE) {
|
||||
bad_usb->key_hold_nb--;
|
||||
bad_usb->hid->kb_release(bad_usb->hid_inst, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// keyboard and mouse were none
|
||||
return ducky_error(bad_usb, "No keycode defined for %s", line);
|
||||
}
|
||||
|
||||
static int32_t ducky_fnc_media(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||
UNUSED(param);
|
||||
|
||||
@@ -191,6 +216,43 @@ static int32_t ducky_fnc_waitforbutton(BadUsbScript* bad_usb, const char* line,
|
||||
return SCRIPT_STATE_WAIT_FOR_BTN;
|
||||
}
|
||||
|
||||
static int32_t ducky_fnc_mouse_scroll(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||
UNUSED(param);
|
||||
|
||||
line = &line[strcspn(line, " ") + 1];
|
||||
int32_t mouse_scroll_dist = 0;
|
||||
|
||||
if(strint_to_int32(line, NULL, &mouse_scroll_dist, 10) != StrintParseNoError) {
|
||||
return ducky_error(bad_usb, "Invalid Number %s", line);
|
||||
}
|
||||
|
||||
bad_usb->hid->mouse_scroll(bad_usb->hid_inst, mouse_scroll_dist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t ducky_fnc_mouse_move(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||
UNUSED(param);
|
||||
|
||||
line = &line[strcspn(line, " ") + 1];
|
||||
int32_t mouse_move_x = 0;
|
||||
int32_t mouse_move_y = 0;
|
||||
|
||||
if(strint_to_int32(line, NULL, &mouse_move_x, 10) != StrintParseNoError) {
|
||||
return ducky_error(bad_usb, "Invalid Number %s", line);
|
||||
}
|
||||
|
||||
line = &line[strcspn(line, " ") + 1];
|
||||
|
||||
if(strint_to_int32(line, NULL, &mouse_move_y, 10) != StrintParseNoError) {
|
||||
return ducky_error(bad_usb, "Invalid Number %s", line);
|
||||
}
|
||||
|
||||
bad_usb->hid->mouse_move(bad_usb->hid_inst, mouse_move_x, mouse_move_y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const DuckyCmd ducky_commands[] = {
|
||||
{"REM", NULL, -1},
|
||||
{"ID", NULL, -1},
|
||||
@@ -213,6 +275,10 @@ static const DuckyCmd ducky_commands[] = {
|
||||
{"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1},
|
||||
{"MEDIA", ducky_fnc_media, -1},
|
||||
{"GLOBE", ducky_fnc_globe, -1},
|
||||
{"MOUSEMOVE", ducky_fnc_mouse_move, -1},
|
||||
{"MOUSE_MOVE", ducky_fnc_mouse_move, -1},
|
||||
{"MOUSESCROLL", ducky_fnc_mouse_scroll, -1},
|
||||
{"MOUSE_SCROLL", ducky_fnc_mouse_scroll, -1},
|
||||
};
|
||||
|
||||
#define TAG "BadUsb"
|
||||
|
||||
@@ -18,6 +18,9 @@ extern "C" {
|
||||
|
||||
#define FILE_BUFFER_LEN 16
|
||||
|
||||
#define HID_MOUSE_INVALID 0
|
||||
#define HID_MOUSE_NONE 0
|
||||
|
||||
struct BadUsbScript {
|
||||
FuriHalUsbHidConfig hid_cfg;
|
||||
const BadUsbHidApi* hid;
|
||||
@@ -55,6 +58,8 @@ uint16_t ducky_get_keycode_by_name(const char* param);
|
||||
|
||||
uint16_t ducky_get_media_keycode_by_name(const char* param);
|
||||
|
||||
uint8_t ducky_get_mouse_keycode_by_name(const char* param);
|
||||
|
||||
bool ducky_get_number(const char* param, uint32_t* val);
|
||||
|
||||
void ducky_numlock_on(BadUsbScript* bad_usb);
|
||||
|
||||
@@ -108,6 +108,17 @@ static const DuckyKey ducky_media_keys[] = {
|
||||
{"BRIGHT_DOWN", HID_CONSUMER_BRIGHTNESS_DECREMENT},
|
||||
};
|
||||
|
||||
static const DuckyKey ducky_mouse_keys[] = {
|
||||
{"LEFTCLICK", HID_MOUSE_BTN_LEFT},
|
||||
{"LEFT_CLICK", HID_MOUSE_BTN_LEFT},
|
||||
{"RIGHTCLICK", HID_MOUSE_BTN_RIGHT},
|
||||
{"RIGHT_CLICK", HID_MOUSE_BTN_RIGHT},
|
||||
{"MIDDLECLICK", HID_MOUSE_BTN_WHEEL},
|
||||
{"MIDDLE_CLICK", HID_MOUSE_BTN_WHEEL},
|
||||
{"WHEELCLICK", HID_MOUSE_BTN_WHEEL},
|
||||
{"WHEEL_CLICK", HID_MOUSE_BTN_WHEEL},
|
||||
};
|
||||
|
||||
uint16_t ducky_get_keycode_by_name(const char* param) {
|
||||
for(size_t i = 0; i < COUNT_OF(ducky_keys); i++) {
|
||||
size_t key_cmd_len = strlen(ducky_keys[i].name);
|
||||
@@ -131,3 +142,15 @@ uint16_t ducky_get_media_keycode_by_name(const char* param) {
|
||||
|
||||
return HID_CONSUMER_UNASSIGNED;
|
||||
}
|
||||
|
||||
uint8_t ducky_get_mouse_keycode_by_name(const char* param) {
|
||||
for(size_t i = 0; i < COUNT_OF(ducky_mouse_keys); i++) {
|
||||
size_t key_cmd_len = strlen(ducky_mouse_keys[i].name);
|
||||
if((strncmp(param, ducky_mouse_keys[i].name, key_cmd_len) == 0) &&
|
||||
(ducky_is_line_end(param[key_cmd_len]))) {
|
||||
return ducky_mouse_keys[i].keycode;
|
||||
}
|
||||
}
|
||||
|
||||
return HID_MOUSE_INVALID;
|
||||
}
|
||||
|
||||
46
applications/main/bad_usb/resources/badusb/test_mouse.txt
Normal file
46
applications/main/bad_usb/resources/badusb/test_mouse.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
ID 1234:abcd Generic:USB Keyboard
|
||||
REM Declare ourselves as a generic usb keyboard
|
||||
REM You can override this to use something else
|
||||
REM Check the `lsusb` command to know your own devices IDs
|
||||
|
||||
DEFAULT_DELAY 200
|
||||
DEFAULT_STRING_DELAY 100
|
||||
|
||||
DELAY 1000
|
||||
|
||||
REM Test all mouse functions
|
||||
LEFTCLICK
|
||||
RIGHTCLICK
|
||||
MIDDLECLICK
|
||||
|
||||
DELAY 1000
|
||||
|
||||
MOUSEMOVE -10 0
|
||||
REPEAT 20
|
||||
MOUSEMOVE 0 10
|
||||
REPEAT 20
|
||||
MOUSEMOVE 10 0
|
||||
REPEAT 20
|
||||
MOUSEMOVE 0 -10
|
||||
REPEAT 20
|
||||
|
||||
DELAY 1000
|
||||
|
||||
MOUSESCROLL -50
|
||||
MOUSESCROLL 50
|
||||
|
||||
DELAY 1000
|
||||
|
||||
REM Verify Mouse hold working
|
||||
HOLD LEFTCLICK
|
||||
DELAY 2000
|
||||
RELEASE LEFTCLICK
|
||||
|
||||
DELAY 1000
|
||||
|
||||
REM Verify KB hold working
|
||||
HOLD M
|
||||
DELAY 2000
|
||||
RELEASE M
|
||||
|
||||
ENTER
|
||||
@@ -177,3 +177,18 @@ Example:
|
||||
`ID 1234:abcd Flipper Devices:Flipper Zero`
|
||||
|
||||
VID and PID are hex codes and are mandatory. Manufacturer and Product are text strings and are optional.
|
||||
|
||||
## Mouse Commands
|
||||
|
||||
Mouse movement and click commands. Mouse click commands support HOLD functionality.
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
| ------------- | -------------------------------| -------------------------------- |
|
||||
| LEFTCLICK | None | |
|
||||
| LEFT_CLICK | None | functionally same as LEFTCLICK |
|
||||
| RIGHTCLICK | None | |
|
||||
| RIGHT_CLICK | None | functionally same as RIGHTCLICK |
|
||||
| MOUSEMOVE | x y: int move mount/direction | |
|
||||
| MOUSE_MOVE | x y: int move mount/direction | functionally same as MOUSEMOVE |
|
||||
| MOUSESCROLL | delta: int scroll distance | |
|
||||
| MOUSE_SCROLL | delta: int scroll distance | functionally same as MOUSESCROLL |
|
||||
|
||||
@@ -317,6 +317,7 @@ SubGhzProtocolStatus
|
||||
res = SubGhzProtocolStatusErrorEncoderGetUpload;
|
||||
break;
|
||||
}
|
||||
|
||||
instance->encoder.is_running = true;
|
||||
|
||||
res = SubGhzProtocolStatusOk;
|
||||
|
||||
Reference in New Issue
Block a user