• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <cstdio>
2 #include <unistd.h>
3 #include <algorithm>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <cstring>
8 
9 #include <libevdev/libevdev.h>
10 #include <libevdev/libevdev-uinput.h>
11 
12 #include <kms++/kms++.h>
13 #include <kms++util/kms++util.h>
14 
15 using namespace std;
16 using namespace kms;
17 
18 static const char* usage_str =
19 	"Usage: kmstouch [OPTION]...\n\n"
20 	"Simple touchscreen tester\n\n"
21 	"Options:\n"
22 	"      --input=DEVICE        DEVICE is the path to input device to open\n"
23 	"      --device=DEVICE       DEVICE is the path to DRM card to open\n"
24 	"  -c, --connector=CONN      CONN is <connector>\n"
25 	"\n";
26 
usage()27 static void usage()
28 {
29 	puts(usage_str);
30 }
31 
32 static bool s_print_ev = false;
33 
34 static vector<pair<int32_t, int32_t>> s_coords;
35 
36 // axis -> min,max
37 static map<int, pair<int32_t, int32_t>> s_abs_map;
38 // axis -> value
39 static map<int, int32_t> s_abs_vals;
40 
print_abs_bits(struct libevdev * dev,int axis)41 static void print_abs_bits(struct libevdev* dev, int axis)
42 {
43 	const struct input_absinfo* abs;
44 
45 	if (!libevdev_has_event_code(dev, EV_ABS, axis))
46 		return;
47 
48 	abs = libevdev_get_abs_info(dev, axis);
49 
50 	printf("	Value	%6d\n", abs->value);
51 	printf("	Min	%6d\n", abs->minimum);
52 	printf("	Max	%6d\n", abs->maximum);
53 	if (abs->fuzz)
54 		printf("	Fuzz	%6d\n", abs->fuzz);
55 	if (abs->flat)
56 		printf("	Flat	%6d\n", abs->flat);
57 	if (abs->resolution)
58 		printf("	Resolution	%6d\n", abs->resolution);
59 }
60 
print_code_bits(struct libevdev * dev,unsigned int type,unsigned int max)61 static void print_code_bits(struct libevdev* dev, unsigned int type, unsigned int max)
62 {
63 	for (uint32_t i = 0; i <= max; i++) {
64 		if (!libevdev_has_event_code(dev, type, i))
65 			continue;
66 
67 		printf("    Event code %i (%s)\n", i, libevdev_event_code_get_name(type, i));
68 		if (type == EV_ABS)
69 			print_abs_bits(dev, i);
70 	}
71 }
72 
print_bits(struct libevdev * dev)73 static void print_bits(struct libevdev* dev)
74 {
75 	printf("Supported events:\n");
76 
77 	for (uint32_t i = 0; i <= EV_MAX; i++) {
78 		if (!libevdev_has_event_type(dev, i))
79 			continue;
80 
81 		printf("  Event type %d (%s)\n", i, libevdev_event_type_get_name(i));
82 
83 		switch (i) {
84 		case EV_KEY:
85 			print_code_bits(dev, EV_KEY, KEY_MAX);
86 			break;
87 		case EV_REL:
88 			print_code_bits(dev, EV_REL, REL_MAX);
89 			break;
90 		case EV_ABS:
91 			print_code_bits(dev, EV_ABS, ABS_MAX);
92 			break;
93 		case EV_LED:
94 			print_code_bits(dev, EV_LED, LED_MAX);
95 			break;
96 		}
97 	}
98 }
99 
collect_current(struct libevdev * dev)100 static void collect_current(struct libevdev* dev)
101 {
102 	for (uint32_t i = 0; i <= ABS_MAX; i++) {
103 		if (!libevdev_has_event_code(dev, EV_ABS, i))
104 			continue;
105 
106 		const struct input_absinfo* abs;
107 
108 		abs = libevdev_get_abs_info(dev, i);
109 
110 		s_abs_vals[i] = abs->value;
111 		s_abs_map[i] = make_pair(abs->minimum, abs->maximum);
112 	}
113 }
114 
print_props(struct libevdev * dev)115 static void print_props(struct libevdev* dev)
116 {
117 	printf("Properties:\n");
118 
119 	for (uint32_t i = 0; i <= INPUT_PROP_MAX; i++) {
120 		if (!libevdev_has_property(dev, i))
121 			continue;
122 
123 		printf("  Property type %d (%s)\n", i, libevdev_property_get_name(i));
124 	}
125 }
126 
handle_event(struct input_event & ev,DumbFramebuffer * fb)127 static void handle_event(struct input_event& ev, DumbFramebuffer* fb)
128 {
129 	static vector<pair<uint16_t, int32_t>> s_event_vec;
130 
131 	if (s_print_ev)
132 		printf("%-6s %20s %6d\n",
133 		       libevdev_event_type_get_name(ev.type),
134 		       libevdev_event_code_get_name(ev.type, ev.code),
135 		       ev.value);
136 
137 	switch (ev.type) {
138 	case EV_ABS:
139 		s_event_vec.emplace_back(ev.code, ev.value);
140 		break;
141 
142 	case EV_KEY:
143 		s_event_vec.emplace_back(ev.code, ev.value);
144 		break;
145 
146 	case EV_SYN:
147 		switch (ev.code) {
148 		case SYN_REPORT: {
149 			int32_t min_x = s_abs_map[ABS_X].first;
150 			int32_t max_x = s_abs_map[ABS_X].second;
151 
152 			int32_t min_y = s_abs_map[ABS_Y].first;
153 			int32_t max_y = s_abs_map[ABS_Y].second;
154 
155 			for (const auto& p : s_event_vec) {
156 				switch (p.first) {
157 				case ABS_X:
158 				case ABS_Y:
159 					s_abs_vals[p.first] = p.second;
160 					break;
161 				default:
162 					break;
163 				}
164 			}
165 
166 			int32_t abs_x = s_abs_vals[ABS_X];
167 			int32_t abs_y = s_abs_vals[ABS_Y];
168 
169 			int32_t x = (abs_x - min_x) * (fb->width() - 1) / (max_x - min_x);
170 			int32_t y = (abs_y - min_y) * (fb->height() - 1) / (max_y - min_y);
171 
172 			printf("%d, %d -> %d, %d\n", abs_x, abs_y, x, y);
173 
174 			draw_rgb_pixel(*fb, x, y, RGB(255, 255, 255));
175 
176 			s_event_vec.clear();
177 
178 			if (s_print_ev)
179 				printf("----\n");
180 			break;
181 		}
182 
183 		default:
184 			EXIT("Unhandled syn event code %u\n", ev.code);
185 			break;
186 		}
187 
188 		break;
189 
190 	default:
191 		EXIT("Unhandled event type %u\n", ev.type);
192 		break;
193 	}
194 }
195 
main(int argc,char ** argv)196 int main(int argc, char** argv)
197 {
198 	string drm_dev_path = "/dev/dri/card0";
199 	string input_dev_path = "/dev/input/event0";
200 	string conn_name;
201 
202 	OptionSet optionset = {
203 		Option("i|input=", [&input_dev_path](string s) {
204 			input_dev_path = s;
205 		}),
206 		Option("|device=", [&drm_dev_path](string s) {
207 			drm_dev_path = s;
208 		}),
209 		Option("c|connector=", [&conn_name](string s) {
210 			conn_name = s;
211 		}),
212 		Option("h|help", []() {
213 			usage();
214 			exit(-1);
215 		}),
216 	};
217 
218 	optionset.parse(argc, argv);
219 
220 	if (optionset.params().size() > 0) {
221 		usage();
222 		exit(-1);
223 	}
224 
225 	struct libevdev* dev = nullptr;
226 
227 	int fd = open(input_dev_path.c_str(), O_RDONLY | O_NONBLOCK);
228 	FAIL_IF(fd < 0, "Failed to open input device %s: %s\n", input_dev_path.c_str(), strerror(errno));
229 	int rc = libevdev_new_from_fd(fd, &dev);
230 	FAIL_IF(rc < 0, "Failed to init libevdev (%s)\n", strerror(-rc));
231 
232 	printf("Input device name: \"%s\"\n", libevdev_get_name(dev));
233 	printf("Input device ID: bus %#x vendor %#x product %#x\n",
234 	       libevdev_get_id_bustype(dev),
235 	       libevdev_get_id_vendor(dev),
236 	       libevdev_get_id_product(dev));
237 
238 	if (!libevdev_has_event_type(dev, EV_ABS) ||
239 	    !libevdev_has_event_code(dev, EV_KEY, BTN_TOUCH)) {
240 		printf("This device does not look like a mouse\n");
241 		exit(1);
242 	}
243 
244 	print_bits(dev);
245 	print_props(dev);
246 
247 	collect_current(dev);
248 
249 	Card card(drm_dev_path);
250 	ResourceManager resman(card);
251 
252 	auto pixfmt = PixelFormat::XRGB8888;
253 
254 	Connector* conn = resman.reserve_connector(conn_name);
255 	Crtc* crtc = resman.reserve_crtc(conn);
256 	Plane* plane = resman.reserve_overlay_plane(crtc, pixfmt);
257 
258 	Videomode mode = conn->get_default_mode();
259 
260 	uint32_t w = mode.hdisplay;
261 	uint32_t h = mode.vdisplay;
262 
263 	auto fb = new DumbFramebuffer(card, w, h, pixfmt);
264 
265 	AtomicReq req(card);
266 
267 	req.add(plane, "CRTC_ID", crtc->id());
268 	req.add(plane, "FB_ID", fb->id());
269 
270 	req.add(plane, "CRTC_X", 0);
271 	req.add(plane, "CRTC_Y", 0);
272 	req.add(plane, "CRTC_W", w);
273 	req.add(plane, "CRTC_H", h);
274 
275 	req.add(plane, "SRC_X", 0);
276 	req.add(plane, "SRC_Y", 0);
277 	req.add(plane, "SRC_W", w << 16);
278 	req.add(plane, "SRC_H", h << 16);
279 
280 	int r = req.commit_sync();
281 	FAIL_IF(r, "initial plane setup failed");
282 
283 	do {
284 		struct input_event ev {
285 		};
286 		rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
287 		if (rc == 0)
288 			handle_event(ev, fb);
289 
290 	} while (rc == 1 || rc == 0 || rc == -EAGAIN);
291 
292 	delete fb;
293 }
294