Skip to content

Instantly share code, notes, and snippets.

@CyberShadow
Last active December 21, 2018 01:01
Show Gist options
  • Save CyberShadow/ae30a8d9f86c170c2451c3dd7edb649c to your computer and use it in GitHub Desktop.
Save CyberShadow/ae30a8d9f86c170c2451c3dd7edb649c to your computer and use it in GitHub Desktop.
uinput-filter-mouse - program to filter and rewrite uinput events
/uinput-filter-mouse
/config.h
#define UPSTREAM_UINPUT_DEVICE "/dev/input/by-id/usb-Logitech_G700_Laser_Mouse_37ADAF750037-event-mouse"
uinput-filter-mouse: Makefile uinput-filter-mouse.c config.h
gcc -o $@ $@.c
config.h:
@echo "Copy and edit \`config.h.sample' to \`config.h' first."
@exit 1
install:
install uinput-filter-mouse /usr/local/bin/
install -m 644 uinput-filter-mouse.service /etc/systemd/system
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include "config.h"
#define die(str, args...) do { \
perror(str); \
exit(EXIT_FAILURE); \
} while(0)
int
main(int argc, char* argv[])
{
int fdo, fdi;
struct uinput_user_dev uidev;
struct input_event ev;
int i;
//if(argc != 2) die("error: specify input device");
fdo = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if(fdo < 0) die("error: open");
//fdi = open(argv[1], O_RDONLY);
fdi = open(UPSTREAM_UINPUT_DEVICE, O_RDONLY);
if(fdi < 0) die("error: open");
if(ioctl(fdi, EVIOCGRAB, 1) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_SYN) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_KEY) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_REL) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_MSC) < 0) die("error: ioctl");
for(i = 0; i < KEY_MAX; ++i)
if(ioctl(fdo, UI_SET_KEYBIT, i) < 0) die("error: ioctl");
for(i = 0; i < REL_MAX; ++i)
if(ioctl(fdo, UI_SET_RELBIT, i) < 0) die("error: ioctl");
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "my-uinput-filter");
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x1;
uidev.id.product = 0x1;
uidev.id.version = 1;
if(write(fdo, &uidev, sizeof(uidev)) < 0) die("error: write");
if(ioctl(fdo, UI_DEV_CREATE) < 0) die("error: ioctl");
while(1)
{
if(read(fdi, &ev, sizeof(struct input_event)) < 0)
die("error: read");
//printf("Got event! type=%d code=%d value=%d\n", ev.type, ev.code, ev.value);
//ev.time.tv_sec = 0;
//ev.time.tv_usec = 0;
if (ev.type == EV_KEY)
{
int key = ev.code;
if (key == BTN_EXTRA || key == BTN_SIDE)
{
ev.code = KEY_LEFTMETA;
if(write(fdo, &ev, sizeof(struct input_event)) < 0)
die("error: write");
if (key == BTN_EXTRA)
ev.code = BTN_LEFT;
if (key == BTN_SIDE)
ev.code = BTN_RIGHT;
if(write(fdo, &ev, sizeof(struct input_event)) < 0)
die("error: write");
}
}
if(write(fdo, &ev, sizeof(struct input_event)) < 0)
die("error: write");
}
if(ioctl(fdo, UI_DEV_DESTROY) < 0) die("error: ioctl");
close(fdi);
close(fdo);
return 0;
}
[Unit]
Description=uinput mouse filter
[Service]
ExecStart=/usr/local/bin/uinput-filter-mouse
Restart=always
[Install]
WantedBy=default.target
@aksel
Copy link

aksel commented Jul 16, 2018

I haven't seen your reply until now

Gist stuff doesn't trigger a notification, apparently

But yeah, that was what I wanted to do.

0x118 -> KEY_LEFTMETA + BTN_LEFT (for moving floating)
KEY_LEFTMETA + 0x118 -> KEY_LEFTMETA + BTN_RIGHT (for resizing)

I have since gotten a new mouse, that has an extra button that I have bound to resizing. But for future reference, how
would I have achieved the other thing?

@aksel
Copy link

aksel commented Jul 17, 2018

Hahaha, how to contact you... Maybe a ping @CyberShadow will work?

@CyberShadow
Copy link
Author

Gist stuff doesn't trigger a notification, apparently

It seems to be a long-standing omission: isaacs/github#21

These's apparently a third-party service: https://giscus.co/

But for future reference, how
would I have achieved the other thing?

Your code looks correct... I don't know why it wouldn't work.

I would try debugging it with more logging in the program, and looking at what ends up in xev.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment