commit
8082251bef
@ -0,0 +1 @@ |
|||||||
|
btor |
@ -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
|
@ -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