|
|
@ -38,7 +38,8 @@ int main(int argc, char **argv) |
|
|
|
if ((st.st_mode & S_IFMT) != S_IFCHR) |
|
|
|
if ((st.st_mode & S_IFMT) != S_IFCHR) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
int tmp_fd = openat(dirfd(dir), dp->d_name, O_RDWR | O_NONBLOCK); |
|
|
|
// blocking io
|
|
|
|
|
|
|
|
int tmp_fd = openat(dirfd(dir), dp->d_name, O_RDWR); |
|
|
|
if (tmp_fd < 0) |
|
|
|
if (tmp_fd < 0) |
|
|
|
err(1, "openat:"); |
|
|
|
err(1, "openat:"); |
|
|
|
union { |
|
|
|
union { |
|
|
@ -47,12 +48,12 @@ int main(int argc, char **argv) |
|
|
|
} vec; |
|
|
|
} vec; |
|
|
|
if (ioctl(tmp_fd, EVIOCGBIT(0, EV_MAX), vec.b) < 0) |
|
|
|
if (ioctl(tmp_fd, EVIOCGBIT(0, EV_MAX), vec.b) < 0) |
|
|
|
err(1, "ioctl:"); |
|
|
|
err(1, "ioctl:"); |
|
|
|
if (!test_bit(EV_KEY, vec.b)) |
|
|
|
if (!test_bit(EV_KEY, vec.b) || !test_bit(EV_ABS, vec.b)) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
if (ioctl(tmp_fd, EVIOCGBIT(EV_KEY, KEY_MAX), vec.k) < 0) |
|
|
|
if (ioctl(tmp_fd, EVIOCGBIT(EV_KEY, KEY_MAX), vec.k) < 0) |
|
|
|
err(1, "ioctl:"); |
|
|
|
err(1, "ioctl:"); |
|
|
|
|
|
|
|
|
|
|
|
if (test_bit(BTN_STYLUS, vec.k) && test_bit(EV_ABS, vec.k)) { |
|
|
|
if (test_bit(BTN_STYLUS, vec.k) && test_bit(BTN_TOOL_RUBBER, vec.k)) { |
|
|
|
stylus = tmp_fd; |
|
|
|
stylus = tmp_fd; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -65,28 +66,20 @@ int main(int argc, char **argv) |
|
|
|
int poll_set = epoll_create(1); |
|
|
|
int poll_set = epoll_create(1); |
|
|
|
if (poll_set < 0) |
|
|
|
if (poll_set < 0) |
|
|
|
err(1, "epoll_create:"); |
|
|
|
err(1, "epoll_create:"); |
|
|
|
struct epoll_event poll_ev = { .events = EPOLLIN | EPOLLOUT | EPOLLET }; |
|
|
|
struct epoll_event poll_ev = { .events = EPOLLIN }; |
|
|
|
if (epoll_ctl(poll_set, EPOLL_CTL_ADD, stylus, &poll_ev) < 0) |
|
|
|
if (epoll_ctl(poll_set, EPOLL_CTL_ADD, stylus, &poll_ev) < 0) |
|
|
|
err(1, "epoll_ctl:"); |
|
|
|
err(1, "epoll_ctl:"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned char button_recived = 0; |
|
|
|
|
|
|
|
struct input_event in_ev, out_ev; |
|
|
|
struct input_event in_ev, out_ev; |
|
|
|
while (epoll_wait(poll_set, &poll_ev, 1, -1) != -1) { |
|
|
|
while (epoll_wait(poll_set, &poll_ev, 1, -1) != -1) { |
|
|
|
switch (poll_ev.events) { |
|
|
|
switch (poll_ev.events) { |
|
|
|
case EPOLLIN: |
|
|
|
case EPOLLIN: |
|
|
|
if (read(stylus, &in_ev, sizeof(struct input_event)) < 0) |
|
|
|
if (read(stylus, &in_ev, sizeof(struct input_event)) < 0) |
|
|
|
err(1, "read:"); |
|
|
|
err(1, "read:"); |
|
|
|
if (in_ev.type != BTN_STYLUS) |
|
|
|
if (in_ev.code != 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; |
|
|
|
break; |
|
|
|
button_recived = 0; |
|
|
|
out_ev = in_ev; |
|
|
|
|
|
|
|
out_ev.code = BTN_TOOL_RUBBER; |
|
|
|
if (write(stylus, &out_ev, sizeof(struct input_event)) < 0) |
|
|
|
if (write(stylus, &out_ev, sizeof(struct input_event)) < 0) |
|
|
|
err(1, "write:"); |
|
|
|
err(1, "write:"); |
|
|
|
break;
|
|
|
|
break;
|
|
|
|