initial commit
This commit is contained in:
commit
8082251bef
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
btor
|
10
Makefile
Normal file
10
Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
.POSIX:
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -Werror -Wextra -pedantic -std=c11
|
||||
|
||||
btor: btor.c
|
||||
${CC} ${LDFLAGS} ${CFLAGS} btor.c -o btor
|
||||
|
||||
clean:
|
||||
rm -f btor
|
99
btor.c
Normal file
99
btor.c
Normal file
@ -0,0 +1,99 @@
|
||||
#define _POSIX_C_SOURCE 200809l
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <err.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define test_bit(yalv, abs_b) ((((char *)abs_b)[yalv/8] & (1<<yalv%8)) > 0)
|
||||
|
||||
#define EVDEV_ROOT "/dev/input/"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
DIR *dir = opendir(EVDEV_ROOT);
|
||||
if (!dir)
|
||||
err(1, "opendir:");
|
||||
struct dirent *dp;
|
||||
struct stat st = {0};
|
||||
int stylus = -1;
|
||||
|
||||
while ((dp = readdir(dir)) != NULL) {
|
||||
if (fstatat(dirfd(dir), dp->d_name, &st, 0) == -1)
|
||||
err(1, "fstatat:");
|
||||
if ((st.st_mode & S_IFMT) != S_IFCHR)
|
||||
continue;
|
||||
|
||||
int tmp_fd = openat(dirfd(dir), dp->d_name, O_RDWR | O_NONBLOCK);
|
||||
if (tmp_fd < 0)
|
||||
err(1, "openat:");
|
||||
union {
|
||||
char b[EV_MAX];
|
||||
char k[KEY_MAX];
|
||||
} vec;
|
||||
if (ioctl(tmp_fd, EVIOCGBIT(0, EV_MAX), vec.b) < 0)
|
||||
err(1, "ioctl:");
|
||||
if (!test_bit(EV_KEY, vec.b))
|
||||
continue;
|
||||
if (ioctl(tmp_fd, EVIOCGBIT(EV_KEY, KEY_MAX), vec.k) < 0)
|
||||
err(1, "ioctl:");
|
||||
|
||||
if (test_bit(BTN_STYLUS, vec.k) && test_bit(EV_ABS, vec.k)) {
|
||||
stylus = tmp_fd;
|
||||
break;
|
||||
}
|
||||
close(tmp_fd);
|
||||
}
|
||||
closedir(dir);
|
||||
if (stylus == -1)
|
||||
err(1, "no stylus input found");
|
||||
|
||||
int poll_set = epoll_create(1);
|
||||
if (poll_set < 0)
|
||||
err(1, "epoll_create:");
|
||||
struct epoll_event poll_ev = { .events = EPOLLIN | EPOLLOUT | EPOLLET };
|
||||
if (epoll_ctl(poll_set, EPOLL_CTL_ADD, stylus, &poll_ev) < 0)
|
||||
err(1, "epoll_ctl:");
|
||||
|
||||
|
||||
unsigned char button_recived = 0;
|
||||
struct input_event in_ev, out_ev;
|
||||
while (epoll_wait(poll_set, &poll_ev, 1, -1) != -1) {
|
||||
switch (poll_ev.events) {
|
||||
case EPOLLIN:
|
||||
if (read(stylus, &in_ev, sizeof(struct input_event)) < 0)
|
||||
err(1, "read:");
|
||||
if (in_ev.type != BTN_STYLUS)
|
||||
break;
|
||||
out_ev.type = BTN_TOOL_RUBBER;
|
||||
out_ev.value = in_ev.value;
|
||||
button_recived = 1;
|
||||
break;
|
||||
case EPOLLOUT:
|
||||
if (!button_recived)
|
||||
break;
|
||||
button_recived = 0;
|
||||
if (write(stylus, &out_ev, sizeof(struct input_event)) < 0)
|
||||
err(1, "write:");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user