Last active
August 5, 2019 15:05
-
-
Save Noble-Mushtak/6aadb2df6756e53b21e2421fe29165d6 to your computer and use it in GitHub Desktop.
Emulates Mouse Keys and uses 0/period on numpad to slow/speed up mouse movements
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Based off https://gist.github.com/matthewaveryusa/a721aad80ae89a5c69f7c964fa20fec1 and https://www.kernel.org/doc/html/latest/input/uinput.html | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <time.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <stdbool.h> | |
#include <syslog.h> | |
#include <linux/uinput.h> | |
//#define SAFE_MODE | |
static inline bool isNumericValue(int key_code) { | |
if (key_code == KEY_KP1) return true; | |
if (key_code == KEY_KP2) return true; | |
if (key_code == KEY_KP3) return true; | |
if (key_code == KEY_KP4) return true; | |
if (key_code == KEY_KP5) return true; | |
if (key_code == KEY_KP6) return true; | |
if (key_code == KEY_KP7) return true; | |
if (key_code == KEY_KP8) return true; | |
if (key_code == KEY_KP9) return true; | |
return false; | |
} | |
typedef struct { | |
int x, y; | |
} Vector2D; | |
static inline Vector2D getMouseMovement(int key_code, int MAGNITUDE) { | |
Vector2D mouseMovement; | |
mouseMovement.x = mouseMovement.y = 0; | |
if ((key_code == KEY_KP1) || (key_code == KEY_KP4) || (key_code == KEY_KP7)) mouseMovement.x = -MAGNITUDE; | |
if ((key_code == KEY_KP1) || (key_code == KEY_KP2) || (key_code == KEY_KP3)) mouseMovement.y = MAGNITUDE; | |
if ((key_code == KEY_KP3) || (key_code == KEY_KP6) || (key_code == KEY_KP9)) mouseMovement.x = MAGNITUDE; | |
if ((key_code == KEY_KP7) || (key_code == KEY_KP8) || (key_code == KEY_KP9)) mouseMovement.y = -MAGNITUDE; | |
return mouseMovement; | |
} | |
int main(int argc, char* argv[]){ | |
const int DIV_ON_NUMPAD = KEY_KPSLASH; | |
const int MUL_ON_NUMPAD = KEY_KPASTERISK; | |
const int SUB_ON_NUMPAD = KEY_KPMINUS; | |
const int FIVE_ON_NUMPAD = KEY_KP5; | |
const int ZERO_ON_NUMPAD = KEY_KP0; | |
const int PERIOD_ON_NUMPAD = KEY_KPDOT; | |
const int VERY_SLOW_MAGNITUDE = 1; | |
const int SLOW_MAGNITUDE = 15; | |
const int MEDIUM_MAGNITUDE = 10; | |
const int FAST_MAGNITUDE = 30; | |
//This stores the type of button click we want to emulate: | |
int cur_button = BTN_LEFT; | |
//This stores the magnitude of the mouse movement we want to emulate when the user presses the button for a short period of time: | |
int desired_slow_magnitude = SLOW_MAGNITUDE; | |
//This stores the magnitude of the mouse movement we want to emulate when the user is pressing the button down for a long period of time: | |
int desired_fast_magnitude = MEDIUM_MAGNITUDE; | |
enum { NUM_CODES = 18 }; | |
//This array represents the key codes for typing "stopthemousethingy": | |
int stop_codes[NUM_CODES] = {31, 20, 24, 25, 20, 35, 18, 50, 24, 22, 31, 18, 20, 35, 23, 49, 34, 21}; | |
//This array holds the last 18 keys the user has pressed: | |
int cur_codes[NUM_CODES]; | |
memset(cur_codes, 0, sizeof(cur_codes)); | |
//This holds our current position in the cur_codes queue: | |
int cur_offset = 0; | |
struct uinput_setup usetup; | |
//Setup and create fake mouse device: | |
int fake_mouse_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); | |
ioctl(fake_mouse_fd, UI_SET_EVBIT, EV_KEY); | |
ioctl(fake_mouse_fd, UI_SET_EVBIT, EV_REP); | |
ioctl(fake_mouse_fd, UI_SET_EVBIT, EV_SYN); | |
ioctl(fake_mouse_fd, UI_SET_EVBIT, EV_REL); | |
ioctl(fake_mouse_fd, UI_SET_RELBIT, REL_X); | |
ioctl(fake_mouse_fd, UI_SET_RELBIT, REL_Y); | |
ioctl(fake_mouse_fd, UI_SET_KEYBIT, BTN_LEFT); | |
ioctl(fake_mouse_fd, UI_SET_KEYBIT, BTN_MIDDLE); | |
ioctl(fake_mouse_fd, UI_SET_KEYBIT, BTN_RIGHT); | |
memset(&usetup, 0, sizeof(usetup)); | |
usetup.id.bustype = BUS_USB; | |
usetup.id.vendor = 0x20; | |
usetup.id.product = 0x01; | |
strcpy(usetup.name, "Fake mouse device"); | |
ioctl(fake_mouse_fd, UI_DEV_SETUP, &usetup); | |
ioctl(fake_mouse_fd, UI_DEV_CREATE); | |
//Setup and create fake keyboard device: | |
int fake_keyboard_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); | |
ioctl(fake_keyboard_fd, UI_SET_EVBIT, EV_KEY); | |
ioctl(fake_keyboard_fd, UI_SET_EVBIT, EV_REP); | |
ioctl(fake_keyboard_fd, UI_SET_EVBIT, EV_SYN); | |
for (int i = KEY_RESERVED; i <= KEY_UNKNOWN; i++) ioctl(fake_keyboard_fd, UI_SET_KEYBIT, i); | |
memset(&usetup, 0, sizeof(usetup)); | |
usetup.id.bustype = BUS_USB; | |
usetup.id.vendor = 0x20; | |
usetup.id.product = 0x02; | |
strcpy(usetup.name, "Fake keyboard device"); | |
ioctl(fake_keyboard_fd, UI_DEV_SETUP, &usetup); | |
ioctl(fake_keyboard_fd, UI_DEV_CREATE); | |
//Without this sleep command, the keyboard gets stuck on the Enter key for some reason. | |
sleep(1); | |
int keyboard_fd = -1, mouse_fd = -1, fd; | |
char filename[256]; | |
char keyboard_name[256] = "Unknown", mouse_name[256] = "Unknown"; | |
//n represents the file number we are testing: | |
int n; | |
int keyboard_n, mouse_n; | |
for (n = 0; n < 32; n++) { | |
//Try to open this event file: | |
sprintf(filename, "/dev/input/event%d", n); | |
fd = open(filename, O_RDONLY | O_NONBLOCK); | |
//If opening the device failed, close the file descriptor and continue searching: | |
if (fd < 0) { | |
close(fd); | |
continue; | |
} | |
//This is the real keyboard if both the EV_KEY and EV_REP bits are set: | |
uint8_t bit[256]; | |
ioctl(fd, EVIOCGBIT(0, EV_MAX), bit); | |
if ((keyboard_fd == -1) && ((bit[EV_KEY/8] >> (EV_KEY % 8)) & 1) && ((bit[EV_REP/8] >> (EV_REP % 8)) & 1)) { | |
keyboard_fd = fd, keyboard_n = n; | |
//Print out the keyboard name: | |
int rcode = ioctl(keyboard_fd, EVIOCGNAME(sizeof(keyboard_name)), keyboard_name); | |
syslog(LOG_NOTICE, "Reading From : %s \n", keyboard_name); | |
//Try to get exclusive access to the keyboard: | |
rcode = ioctl(keyboard_fd, EVIOCGRAB, 1); | |
syslog(LOG_NOTICE, "Getting exclusive access to keyboard: %s\n", (rcode == 0) ? "SUCCESS" : "FAILURE"); | |
} | |
/* | |
//This is the real mouse if EV_REL bit is set | |
else if ((mouse_fd == -1) && ((bit[EV_REL/8] >> (EV_REL % 8)) & 1)) { | |
mouse_fd = fd, mouse_n = n; | |
//Print out the mouse name: | |
int rcode = ioctl(mouse_fd, EVIOCGNAME(sizeof(mouse_name)), mouse_name); | |
syslog(LOG_NOTICE, "Reading From: %s\n", mouse_name); | |
//Try to get exclusive access to the mouse: | |
//rcode = ioctl(mouse_fd, EVIOCGRAB, 1); | |
//syslog(LOG_NOTICE, "Getting exclusive access to mouse: %s\n", (rcode == 0) ? "SUCCESS" : "FAILURE"); | |
} | |
*/ | |
else { | |
//Close the file descriptor if this is not the keyboard or mouse: | |
close(fd); | |
} | |
} | |
//Exit if keyboard was not found: | |
if ((keyboard_fd == -1) /*|| (mouse_fd == -1)*/) exit(1); | |
//Used to mock click event: | |
struct input_event fake_mouse_click; | |
fake_mouse_click.type = EV_KEY; | |
//Used to mock mouse movement: | |
struct input_event fake_mouse_movementX; | |
fake_mouse_movementX.type = EV_REL; | |
fake_mouse_movementX.code = REL_X; | |
struct input_event fake_mouse_movementY; | |
fake_mouse_movementY.type = EV_REL; | |
fake_mouse_movementY.code = REL_Y; | |
//Used to mock SYN_REPORT event: | |
struct input_event syn_report; | |
syn_report.type = EV_SYN; | |
syn_report.code = SYN_REPORT; | |
syn_report.value = 0; | |
//Used to store event from keyboard: | |
struct input_event event; | |
#ifdef SAFE_MODE | |
int end = time(NULL)+20; | |
while (time(NULL) < end) { | |
#else | |
while (true) { | |
#endif | |
//Read an event from the keyboard: | |
if (read(keyboard_fd, &event, sizeof(event)) != -1) { | |
if (event.code == FIVE_ON_NUMPAD) { | |
//Click the appropriate button when user pressed 5 on numpad: | |
fake_mouse_click.code = cur_button; | |
//Press the mouse button down if the user pressed the key down, press the mouse button up if the user pressed the key up | |
fake_mouse_click.value = event.value; | |
//Update time and send the click: | |
gettimeofday(&(fake_mouse_click.time), NULL); | |
if (write(fake_mouse_fd, &fake_mouse_click, sizeof(fake_mouse_click)) < sizeof(fake_mouse_click)) perror("send click error"); | |
//Update time and send the SYN_REPORT: | |
gettimeofday(&(syn_report.time), NULL); | |
if (write(fake_mouse_fd, &syn_report, sizeof(syn_report)) < sizeof(syn_report)) perror("syn report error"); | |
} else if (event.code == DIV_ON_NUMPAD) { | |
//Change selected button to left button when user hits divide symbol on numpad: | |
cur_button = BTN_LEFT; | |
} else if (event.code == MUL_ON_NUMPAD) { | |
//Change selected button to middle button when user hits multiply symbol on numpad: | |
cur_button = BTN_MIDDLE; | |
} else if (event.code == SUB_ON_NUMPAD) { | |
//Change selected button to right button when user hits subtract symbol on numpad: | |
cur_button = BTN_RIGHT; | |
} else if (event.code == ZERO_ON_NUMPAD){ | |
//FAST_MAGNITUDE if they pressed zero, MEDIUM_MAGNITUDE if they stopped pressing zero | |
desired_fast_magnitude = (event.value == 0) ? MEDIUM_MAGNITUDE : FAST_MAGNITUDE; | |
} else if (event.code == PERIOD_ON_NUMPAD) { | |
//VERY_SLOW_MAGNITUDE if they pressed period, SLOW_MAGNITUDE if they stopped pressing period | |
desired_slow_magnitude = (event.value == 0) ? SLOW_MAGNITUDE : VERY_SLOW_MAGNITUDE; | |
} else if (isNumericValue(event.code)) { | |
//Don't move the mouse if the user is just stopped pressing the key: | |
if (event.value == 0) continue; | |
//Get the desired movement, with the magnitude being slow if they press down for a short time and fast if they continue pressing down: | |
Vector2D desiredMovement = getMouseMovement(event.code, (event.value == 2) ? desired_fast_magnitude : desired_slow_magnitude); | |
//printf("%d %d %d\n", event.value, desiredMovement.x, desiredMovement.y); | |
//Send the mouseX and mouseY movement events: | |
fake_mouse_movementX.value = desiredMovement.x; | |
gettimeofday(&(fake_mouse_movementX.time), NULL); | |
if (write(fake_mouse_fd, &fake_mouse_movementX, sizeof(fake_mouse_movementX)) < sizeof(fake_mouse_movementX)) perror("passthrough error"); | |
fake_mouse_movementY.value = desiredMovement.y; | |
gettimeofday(&(fake_mouse_movementY.time), NULL); | |
if (write(fake_mouse_fd, &fake_mouse_movementY, sizeof(fake_mouse_movementY)) < sizeof(fake_mouse_movementY)) perror("passthrough error"); | |
//Update time and send the SYN_REPORT: | |
gettimeofday(&(syn_report.time), NULL); | |
if (write(fake_mouse_fd, &syn_report, sizeof(syn_report)) < sizeof(syn_report)) perror("syn report error"); | |
} else { | |
//For all other key events, just pass it through to the keyboard: | |
if (write(fake_keyboard_fd, &event, sizeof(event)) < sizeof(event)) perror("passthrough error"); | |
//If this is a keydown, add this to the queue of cur_codes: | |
if ((event.type == 1) && (event.value == 1)) { | |
cur_codes[cur_offset] = event.code; | |
cur_offset += 1; | |
if (cur_offset >= NUM_CODES) cur_offset -= NUM_CODES; | |
int i; | |
for (i = 0; i < NUM_CODES; i++) { | |
if (cur_codes[(i+cur_offset) % NUM_CODES] != stop_codes[i]) break; | |
} | |
if (i == NUM_CODES) break; | |
} | |
} | |
} | |
//Allow userspace time to process the above events: | |
usleep(10000); | |
} | |
#ifdef SAFE_MODE | |
for (int i = 0; i < NUM_CODES; i++) printf("%d%s", cur_codes[(i+cur_offset) % NUM_CODES], (i+1 == NUM_CODES) ? "\n" : ", "); | |
#endif | |
syslog(LOG_NOTICE, "Exiting mouse click simulator"); | |
//Give userspace time to read events before destroying devices: | |
sleep(1); | |
//Destroy mock devices made up for /dev/uinput | |
ioctl(fake_mouse_fd, UI_DEV_DESTROY); | |
close(fake_mouse_fd); | |
ioctl(fake_keyboard_fd, UI_DEV_DESTROY); | |
close(fake_keyboard_fd); | |
//Close keyboard | |
ioctl(keyboard_fd, EVIOCGRAB, 0); | |
close(keyboard_fd); | |
/*//Close mouse | |
ioctl(mouse_fd, EVIOCGRAB, 0); | |
close(mouse_fd);*/ | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Based off https://gist.github.com/matthewaveryusa/a721aad80ae89a5c69f7c964fa20fec1 | |
//Uses old uinput version (before uinput version 5) | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <time.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <stdbool.h> | |
#include <syslog.h> | |
#include <linux/input.h> | |
#include <linux/uinput.h> | |
//#define SAFE_MODE | |
static inline bool isNumericValue(int key_code) { | |
if (key_code == KEY_KP1) return true; | |
if (key_code == KEY_KP2) return true; | |
if (key_code == KEY_KP3) return true; | |
if (key_code == KEY_KP4) return true; | |
if (key_code == KEY_KP5) return true; | |
if (key_code == KEY_KP6) return true; | |
if (key_code == KEY_KP7) return true; | |
if (key_code == KEY_KP8) return true; | |
if (key_code == KEY_KP9) return true; | |
return false; | |
} | |
typedef struct { | |
int x, y; | |
} Vector2D; | |
static inline Vector2D getMouseMovement(int key_code, int MAGNITUDE) { | |
Vector2D mouseMovement; | |
mouseMovement.x = mouseMovement.y = 0; | |
if ((key_code == KEY_KP1) || (key_code == KEY_KP4) || (key_code == KEY_KP7)) mouseMovement.x = -MAGNITUDE; | |
if ((key_code == KEY_KP1) || (key_code == KEY_KP2) || (key_code == KEY_KP3)) mouseMovement.y = MAGNITUDE; | |
if ((key_code == KEY_KP3) || (key_code == KEY_KP6) || (key_code == KEY_KP9)) mouseMovement.x = MAGNITUDE; | |
if ((key_code == KEY_KP7) || (key_code == KEY_KP8) || (key_code == KEY_KP9)) mouseMovement.y = -MAGNITUDE; | |
return mouseMovement; | |
} | |
int main(int argc, char* argv[]){ | |
const int DIV_ON_NUMPAD = KEY_KPSLASH; | |
const int MUL_ON_NUMPAD = KEY_KPASTERISK; | |
const int SUB_ON_NUMPAD = KEY_KPMINUS; | |
const int FIVE_ON_NUMPAD = KEY_KP5; | |
const int ZERO_ON_NUMPAD = KEY_KP0; | |
const int PERIOD_ON_NUMPAD = KEY_KPDOT; | |
const int VERY_SLOW_MAGNITUDE = 1; | |
const int SLOW_MAGNITUDE = 15; | |
const int MEDIUM_MAGNITUDE = 10; | |
const int FAST_MAGNITUDE = 30; | |
//This stores the type of button click we want to emulate: | |
int cur_button = BTN_LEFT; | |
//This stores the magnitude of the mouse movement we want to emulate when the user presses the button for a short period of time: | |
int desired_slow_magnitude = SLOW_MAGNITUDE; | |
//This stores the magnitude of the mouse movement we want to emulate when the user is pressing the button down for a long period of time: | |
int desired_fast_magnitude = MEDIUM_MAGNITUDE; | |
enum { NUM_CODES = 18 }; | |
//This array represents the key codes for typing "stopthemousethingy": | |
int stop_codes[NUM_CODES] = {31, 20, 24, 25, 20, 35, 18, 50, 24, 22, 31, 18, 20, 35, 23, 49, 34, 21}; | |
//This array holds the last 18 keys the user has pressed: | |
int cur_codes[NUM_CODES]; | |
memset(cur_codes, 0, sizeof(cur_codes)); | |
//This holds our current position in the cur_codes queue: | |
int cur_offset = 0; | |
struct uinput_user_dev usetup; | |
//Setup and create fake mouse device: | |
int fake_mouse_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); | |
memset(&usetup, 0, sizeof(usetup)); | |
usetup.id.bustype = BUS_USB; | |
usetup.id.vendor = 0x20; | |
usetup.id.product = 0x01; | |
strcpy(usetup.name, "Fake mouse device"); | |
write(fake_mouse_fd, &usetup, sizeof(usetup)); | |
ioctl(fake_mouse_fd, UI_SET_EVBIT, EV_KEY); | |
ioctl(fake_mouse_fd, UI_SET_EVBIT, EV_REP); | |
ioctl(fake_mouse_fd, UI_SET_EVBIT, EV_SYN); | |
ioctl(fake_mouse_fd, UI_SET_EVBIT, EV_REL); | |
ioctl(fake_mouse_fd, UI_SET_RELBIT, REL_X); | |
ioctl(fake_mouse_fd, UI_SET_RELBIT, REL_Y); | |
ioctl(fake_mouse_fd, UI_SET_KEYBIT, BTN_LEFT); | |
ioctl(fake_mouse_fd, UI_SET_KEYBIT, BTN_MIDDLE); | |
ioctl(fake_mouse_fd, UI_SET_KEYBIT, BTN_RIGHT); | |
ioctl(fake_mouse_fd, UI_DEV_CREATE, NULL); | |
//Setup and create fake keyboard device: | |
int fake_keyboard_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); | |
memset(&usetup, 0, sizeof(usetup)); | |
usetup.id.bustype = BUS_USB; | |
usetup.id.vendor = 0x20; | |
usetup.id.product = 0x02; | |
strcpy(usetup.name, "Fake keyboard device"); | |
write(fake_keyboard_fd, &usetup, sizeof(usetup)); | |
ioctl(fake_keyboard_fd, UI_SET_EVBIT, EV_KEY); | |
ioctl(fake_keyboard_fd, UI_SET_EVBIT, EV_REP); | |
ioctl(fake_keyboard_fd, UI_SET_EVBIT, EV_SYN); | |
for (int i = KEY_RESERVED; i <= KEY_UNKNOWN; i++) ioctl(fake_keyboard_fd, UI_SET_KEYBIT, i); | |
ioctl(fake_keyboard_fd, UI_DEV_CREATE, NULL); | |
//Without this sleep command, the keyboard gets stuck on the Enter key for some reason. | |
sleep(1); | |
int keyboard_fd = -1, mouse_fd = -1, fd; | |
char filename[256]; | |
char keyboard_name[256] = "Unknown", mouse_name[256] = "Unknown"; | |
//n represents the file number we are testing: | |
int n; | |
int keyboard_n, mouse_n; | |
for (n = 0; n < 32; n++) { | |
//Try to open this event file: | |
sprintf(filename, "/dev/input/event%d", n); | |
fd = open(filename, O_RDONLY | O_NONBLOCK); | |
//If opening the device failed, close the file descriptor and continue searching: | |
if (fd < 0) { | |
close(fd); | |
continue; | |
} | |
//This is the real keyboard if both the EV_KEY and EV_REP bits are set: | |
uint8_t bit[256]; | |
ioctl(fd, EVIOCGBIT(0, EV_MAX), bit); | |
if ((keyboard_fd == -1) && ((bit[EV_KEY/8] >> (EV_KEY % 8)) & 1) && ((bit[EV_REP/8] >> (EV_REP % 8)) & 1)) { | |
keyboard_fd = fd, keyboard_n = n; | |
//Print out the keyboard name: | |
int rcode = ioctl(keyboard_fd, EVIOCGNAME(sizeof(keyboard_name)), keyboard_name); | |
syslog(LOG_NOTICE, "Reading From : %s \n", keyboard_name); | |
//Try to get exclusive access to the keyboard: | |
rcode = ioctl(keyboard_fd, EVIOCGRAB, 1); | |
syslog(LOG_NOTICE, "Getting exclusive access to keyboard: %s\n", (rcode == 0) ? "SUCCESS" : "FAILURE"); | |
} | |
/* | |
//This is the real mouse if EV_REL bit is set | |
else if ((mouse_fd == -1) && ((bit[EV_REL/8] >> (EV_REL % 8)) & 1)) { | |
mouse_fd = fd, mouse_n = n; | |
//Print out the mouse name: | |
int rcode = ioctl(mouse_fd, EVIOCGNAME(sizeof(mouse_name)), mouse_name); | |
syslog(LOG_NOTICE, "Reading From: %s\n", mouse_name); | |
//Try to get exclusive access to the mouse: | |
//rcode = ioctl(mouse_fd, EVIOCGRAB, 1); | |
//syslog(LOG_NOTICE, "Getting exclusive access to mouse: %s\n", (rcode == 0) ? "SUCCESS" : "FAILURE"); | |
} | |
*/ | |
else { | |
//Close the file descriptor if this is not the keyboard or mouse: | |
close(fd); | |
} | |
} | |
//Exit if keyboard was not found: | |
if ((keyboard_fd == -1) /*|| (mouse_fd == -1)*/) exit(1); | |
//Used to mock click event: | |
struct input_event fake_mouse_click; | |
fake_mouse_click.type = EV_KEY; | |
//Used to mock mouse movement: | |
struct input_event fake_mouse_movementX; | |
fake_mouse_movementX.type = EV_REL; | |
fake_mouse_movementX.code = REL_X; | |
struct input_event fake_mouse_movementY; | |
fake_mouse_movementY.type = EV_REL; | |
fake_mouse_movementY.code = REL_Y; | |
//Used to mock SYN_REPORT event: | |
struct input_event syn_report; | |
syn_report.type = EV_SYN; | |
syn_report.code = SYN_REPORT; | |
syn_report.value = 0; | |
//Used to store event from keyboard: | |
struct input_event event; | |
#ifdef SAFE_MODE | |
int end = time(NULL)+20; | |
while (time(NULL) < end) { | |
#else | |
while (true) { | |
#endif | |
//Read an event from the keyboard: | |
if (read(keyboard_fd, &event, sizeof(event)) != -1) { | |
if (event.code == FIVE_ON_NUMPAD) { | |
//Click the appropriate button when user pressed 5 on numpad: | |
fake_mouse_click.code = cur_button; | |
//Press the mouse button down if the user pressed the key down, press the mouse button up if the user pressed the key up | |
fake_mouse_click.value = event.value; | |
//Update time and send the click: | |
gettimeofday(&(fake_mouse_click.time), NULL); | |
if (write(fake_mouse_fd, &fake_mouse_click, sizeof(fake_mouse_click)) < sizeof(fake_mouse_click)) perror("send click error"); | |
//Update time and send the SYN_REPORT: | |
gettimeofday(&(syn_report.time), NULL); | |
if (write(fake_mouse_fd, &syn_report, sizeof(syn_report)) < sizeof(syn_report)) perror("syn report error"); | |
} else if (event.code == DIV_ON_NUMPAD) { | |
//Change selected button to left button when user hits divide symbol on numpad: | |
cur_button = BTN_LEFT; | |
} else if (event.code == MUL_ON_NUMPAD) { | |
//Change selected button to middle button when user hits multiply symbol on numpad: | |
cur_button = BTN_MIDDLE; | |
} else if (event.code == SUB_ON_NUMPAD) { | |
//Change selected button to right button when user hits subtract symbol on numpad: | |
cur_button = BTN_RIGHT; | |
} else if (event.code == ZERO_ON_NUMPAD){ | |
//FAST_MAGNITUDE if they pressed zero, MEDIUM_MAGNITUDE if they stopped pressing zero | |
desired_fast_magnitude = (event.value == 0) ? MEDIUM_MAGNITUDE : FAST_MAGNITUDE; | |
} else if (event.code == PERIOD_ON_NUMPAD) { | |
//VERY_SLOW_MAGNITUDE if they pressed period, SLOW_MAGNITUDE if they stopped pressing period | |
desired_slow_magnitude = (event.value == 0) ? SLOW_MAGNITUDE : VERY_SLOW_MAGNITUDE; | |
} else if (isNumericValue(event.code)) { | |
//Don't move the mouse if the user is just stopped pressing the key: | |
if (event.value == 0) continue; | |
//Get the desired movement, with the magnitude being slow if they press down for a short time and fast if they continue pressing down: | |
Vector2D desiredMovement = getMouseMovement(event.code, (event.value == 2) ? desired_fast_magnitude : desired_slow_magnitude); | |
//printf("%d %d %d\n", event.value, desiredMovement.x, desiredMovement.y); | |
//Send the mouseX and mouseY movement events: | |
fake_mouse_movementX.value = desiredMovement.x; | |
gettimeofday(&(fake_mouse_movementX.time), NULL); | |
if (write(fake_mouse_fd, &fake_mouse_movementX, sizeof(fake_mouse_movementX)) < sizeof(fake_mouse_movementX)) perror("passthrough error"); | |
fake_mouse_movementY.value = desiredMovement.y; | |
gettimeofday(&(fake_mouse_movementY.time), NULL); | |
if (write(fake_mouse_fd, &fake_mouse_movementY, sizeof(fake_mouse_movementY)) < sizeof(fake_mouse_movementY)) perror("passthrough error"); | |
//Update time and send the SYN_REPORT: | |
gettimeofday(&(syn_report.time), NULL); | |
if (write(fake_mouse_fd, &syn_report, sizeof(syn_report)) < sizeof(syn_report)) perror("syn report error"); | |
} else { | |
//For all other key events, just pass it through to the keyboard: | |
if (write(fake_keyboard_fd, &event, sizeof(event)) < sizeof(event)) perror("passthrough error"); | |
//If this is a keydown, add this to the queue of cur_codes: | |
if ((event.type == 1) && (event.value == 1)) { | |
cur_codes[cur_offset] = event.code; | |
cur_offset += 1; | |
if (cur_offset >= NUM_CODES) cur_offset -= NUM_CODES; | |
int i; | |
for (i = 0; i < NUM_CODES; i++) { | |
if (cur_codes[(i+cur_offset) % NUM_CODES] != stop_codes[i]) break; | |
} | |
if (i == NUM_CODES) break; | |
} | |
} | |
} | |
//Allow userspace time to process the above events: | |
usleep(10000); | |
} | |
#ifdef SAFE_MODE | |
for (int i = 0; i < NUM_CODES; i++) printf("%d%s", cur_codes[(i+cur_offset) % NUM_CODES], (i+1 == NUM_CODES) ? "\n" : ", "); | |
#endif | |
syslog(LOG_NOTICE, "Exiting mouse click simulator"); | |
//Destroy mock devices made up for /dev/uinput | |
ioctl(fake_mouse_fd, UI_DEV_DESTROY); | |
close(fake_mouse_fd); | |
ioctl(fake_keyboard_fd, UI_DEV_DESTROY); | |
close(fake_keyboard_fd); | |
//Close keyboard | |
ioctl(keyboard_fd, EVIOCGRAB, 0); | |
close(keyboard_fd); | |
/*//Close mouse | |
ioctl(mouse_fd, EVIOCGRAB, 0); | |
close(mouse_fd);*/ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment