il terzo il tipo di configurazione (0=VBand con tasti parentesi quadre, 1=Google con tasti . e / ed infine 3=VBand con tasti CTRL-LEFT e CTRL-RIGHT)
#include <linux/uinput.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>
#include <signal.h>
volatile sig_atomic_t running = 1;
void signal_handler(int sig) {
running = 0;
}
void send_key(int ufd, int keycode) {
struct input_event ev;
memset(&ev, 0, sizeof(ev));
// Key press
ev.type = EV_KEY;
ev.code = keycode;
ev.value = 1;
write(ufd, &ev, sizeof(ev));
// Sync
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
write(ufd, &ev, sizeof(ev));
// Key release
ev.type = EV_KEY;
ev.code = keycode;
ev.value = 0;
write(ufd, &ev, sizeof(ev));
// Sync
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
write(ufd, &ev, sizeof(ev));
}
int main(int argc, char *argv[]) {
if (argc < 4) {
printf("Usage: %s /dev/input/eventX <delay_ms> <mode>\n", argv[0]);
printf("\nModes:\n");
printf(" 0: LEFT='[' RIGHT=']' (VBand)\n");
printf(" 1: LEFT='.' RIGHT='/' (Learn Morse Google)\n");
printf(" 2: LEFT=CTRL_LEFT RIGHT=CTRL_RIGHT (VBand2)\n");
printf("\nExample: %s /dev/input/event4 100 0\n", argv[0]);
return 1;
}
const char *mouse_dev = argv[1];
int delay_ms = atoi(argv[2]);
int mode = atoi(argv[3]);
if (delay_ms <= 0) {
printf("Error: delay must be positive\n");
return 1;
}
if (mode < 0 || mode > 2) {
printf("Error: mode must be 0, 1, or 2\n");
return 1;
}
// Define key mappings based on mode
int left_key, right_key;
const char *left_label, *right_label;
switch (mode) {
case 0:
left_key = KEY_LEFTBRACE;
right_key = KEY_RIGHTBRACE;
left_label = "'['";
right_label = "']'";
break;
case 1:
left_key = KEY_DOT;
right_key = KEY_SLASH;
left_label = "'.'";
right_label = "'/'";
break;
case 2:
left_key = KEY_LEFTCTRL;
right_key = KEY_RIGHTCTRL;
left_label = "CTRL_LEFT";
right_label = "CTRL_RIGHT";
break;
}
// Open mouse device
int mfd = open(mouse_dev, O_RDONLY | O_NONBLOCK);
if (mfd < 0) {
perror("Mouse open");
return 1;
}
// GRAB EXCLUSIVE ACCESS
if (ioctl(mfd, EVIOCGRAB, 1) < 0) {
perror("Cannot grab mouse device");
close(mfd);
return 1;
}
printf("Mouse device grabbed successfully\n");
// Open uinput
int ufd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if (ufd < 0) {
perror("uinput open");
ioctl(mfd, EVIOCGRAB, 0);
close(mfd);
return 1;
}
// Setup virtual keyboard - register all possible keys
ioctl(ufd, UI_SET_EVBIT, EV_KEY);
ioctl(ufd, UI_SET_KEYBIT, KEY_DOT);
ioctl(ufd, UI_SET_KEYBIT, KEY_COMMA);
ioctl(ufd, UI_SET_KEYBIT, KEY_SLASH);
ioctl(ufd, UI_SET_KEYBIT, KEY_LEFTBRACE);
ioctl(ufd, UI_SET_KEYBIT, KEY_RIGHTBRACE);
ioctl(ufd, UI_SET_KEYBIT, KEY_LEFTCTRL);
ioctl(ufd, UI_SET_KEYBIT, KEY_RIGHTCTRL);
struct uinput_setup usetup;
memset(&usetup, 0, sizeof(usetup));
snprintf(usetup.name, UINPUT_MAX_NAME_SIZE, "mouse2key-mode%d", mode);
usetup.id.bustype = BUS_USB;
usetup.id.vendor = 0x1;
usetup.id.product = 0x1;
usetup.id.version = 1;
ioctl(ufd, UI_DEV_SETUP, &usetup);
ioctl(ufd, UI_DEV_CREATE);
// Setup signal handler
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
printf("Mode %d selected - Delay: %dms\n", mode, delay_ms);
printf(" Hold LEFT button = send %s repeatedly\n", left_label);
printf(" Hold RIGHT button = send %s repeatedly\n", right_label);
printf("Press Ctrl+C to exit\n\n");
struct input_event ev;
fd_set readfds;
struct timeval timeout;
int left_pressed = 0;
int right_pressed = 0;
while (running) {
// Setup select with timeout
FD_ZERO(&readfds);
FD_SET(mfd, &readfds);
int ret;
// Only use timeout if a button is held
if (left_pressed || right_pressed) {
// Send keystroke(s) immediately
if (left_pressed) {
send_key(ufd, left_key);
//if (mode < 2) printf(".");
fflush(stdout);
}
if (right_pressed) {
send_key(ufd, right_key);
//if (mode < 2) printf(",");
fflush(stdout);
}
// NOW wait for the delay
timeout.tv_sec = delay_ms / 1000;
timeout.tv_usec = (delay_ms % 1000) * 1000;
ret = select(mfd + 1, &readfds, NULL, NULL, &timeout);
if (ret < 0) {
perror("select");
break;
}
} else {
// No button held, just wait for events (blocking)
ret = select(mfd + 1, &readfds, NULL, NULL, NULL);
if (ret < 0) {
perror("select");
break;
}
}
// Check for mouse events
if (FD_ISSET(mfd, &readfds)) {
while (read(mfd, &ev, sizeof(ev)) > 0) {
if (ev.type == EV_KEY) {
if (ev.code == BTN_LEFT) {
if (ev.value == 1) {
// Left button pressed
left_pressed = 1;
//printf("\n[LEFT pressed - sending %s]\n", left_label);
} else if (ev.value == 0) {
// Left button released
left_pressed = 0;
//printf("\n[LEFT released]\n");
}
} else if (ev.code == BTN_RIGHT) {
if (ev.value == 1) {
// Right button pressed
right_pressed = 1;
//printf("\n[RIGHT pressed - sending %s]\n", right_label);
} else if (ev.value == 0) {
// Right button released
right_pressed = 0;
//printf("\n[RIGHT released]\n");
}
}
}
}
}
}
// Cleanup
printf("\nCleaning up...\n");
ioctl(ufd, UI_DEV_DESTROY);
ioctl(mfd, EVIOCGRAB, 0);
close(ufd);
close(mfd);
return 0;
}