Skip to content

Instantly share code, notes, and snippets.

@Noble-Mushtak
Last active August 5, 2019 15:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Noble-Mushtak/6aadb2df6756e53b21e2421fe29165d6 to your computer and use it in GitHub Desktop.
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
//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;
}
//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