You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							120 lines
						
					
					
						
							2.5 KiB
						
					
					
				
			
		
		
	
	
							120 lines
						
					
					
						
							2.5 KiB
						
					
					
				| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <stdbool.h>
 | |
| #include <assert.h>
 | |
| #include <unistd.h>
 | |
| #include <fcntl.h>
 | |
| #include <dirent.h>
 | |
| #include <sys/poll.h>
 | |
| #include <linux/input.h>
 | |
| 
 | |
| #include "touch.h"
 | |
| 
 | |
| static int find_dev() {
 | |
|   int err;
 | |
| 
 | |
|   int ret = -1;
 | |
| 
 | |
|   DIR *dir = opendir("/dev/input");
 | |
|   assert(dir);
 | |
|   struct dirent* de = NULL;
 | |
|   while ((de = readdir(dir))) {
 | |
|     if (strncmp(de->d_name, "event", 5)) continue;
 | |
| 
 | |
|     int fd = openat(dirfd(dir), de->d_name, O_RDONLY);
 | |
|     assert(fd >= 0);
 | |
| 
 | |
|     unsigned char ev_bits[KEY_MAX / 8 + 1];
 | |
|     err = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(ev_bits)), ev_bits);
 | |
|     assert(err >= 0);
 | |
| 
 | |
|     const int x_key = ABS_MT_POSITION_X / 8;
 | |
|     const int y_key = ABS_MT_POSITION_Y / 8;
 | |
|     if ((ev_bits[x_key] & (ABS_MT_POSITION_X - x_key)) &&
 | |
|         (ev_bits[y_key] & (ABS_MT_POSITION_Y - y_key))) {
 | |
|       ret = fd;
 | |
|       break;
 | |
|     }
 | |
|     close(fd);
 | |
|   }
 | |
|   closedir(dir);
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| void touch_init(TouchState *s) {
 | |
|   s->fd = find_dev();
 | |
|   assert(s->fd >= 0);
 | |
| }
 | |
| 
 | |
| int touch_poll(TouchState *s, int* out_x, int* out_y, int timeout) {
 | |
|   assert(out_x && out_y);
 | |
|   bool up = false;
 | |
|   while (true) {
 | |
|     struct pollfd polls[] = {{
 | |
|       .fd = s->fd,
 | |
|       .events = POLLIN,
 | |
|     }};
 | |
|     int err = poll(polls, 1, timeout);
 | |
|     if (err < 0) {
 | |
|       return -1;
 | |
|     }
 | |
|     if (!(polls[0].revents & POLLIN)) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     struct input_event event;
 | |
|     err = read(polls[0].fd, &event, sizeof(event));
 | |
|     if (err < sizeof(event)) {
 | |
|       return -1;
 | |
|     }
 | |
| 
 | |
|     switch (event.type) {
 | |
|     case EV_ABS:
 | |
|       if (event.code == ABS_MT_POSITION_X) {
 | |
|         s->last_x = event.value;
 | |
|       } else if (event.code == ABS_MT_POSITION_Y) {
 | |
|         s->last_y = event.value;
 | |
|       } else if (event.code == ABS_MT_TRACKING_ID && event.value != -1) {
 | |
|         up = true;
 | |
|       }
 | |
|       break;
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   if (up) {
 | |
|     // adjust for flippening
 | |
|     *out_x = s->last_y;
 | |
|     *out_y = 1080 - s->last_x;
 | |
|   }
 | |
|   return up;
 | |
| }
 | |
| 
 | |
| int touch_read(TouchState *s, int* out_x, int* out_y) {
 | |
|   assert(out_x && out_y);
 | |
|   struct input_event event;
 | |
|   int err = read(s->fd, &event, sizeof(event));
 | |
|   if (err < sizeof(event)) {
 | |
|     return -1;
 | |
|   }
 | |
|   bool up = false;
 | |
|   switch (event.type) {
 | |
|   case EV_ABS:
 | |
|     if (event.code == ABS_MT_POSITION_X) {
 | |
|       s->last_x = event.value;
 | |
|     } else if (event.code == ABS_MT_POSITION_Y) {
 | |
|       s->last_y = event.value;
 | |
|     }
 | |
|     up = true;
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
|   if (up) {
 | |
|     // adjust for flippening
 | |
|     *out_x = s->last_y;
 | |
|     *out_y = 1080 - s->last_x;
 | |
|   }
 | |
|   return up;
 | |
| }
 | |
| 
 |