1// Copyright 2016 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <assert.h> 6#include <dirent.h> 7#include <errno.h> 8#include <fcntl.h> 9#include <stdbool.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <unistd.h> 14 15#include <hid/acer12.h> 16#include <hid/ft3x27.h> 17#include <hid/egalax.h> 18#include <hid/eyoyo.h> 19#include <hid/paradise.h> 20#include <hid/usages.h> 21 22#include <lib/framebuffer/framebuffer.h> 23 24#include <zircon/device/input.h> 25#include <zircon/process.h> 26#include <zircon/syscalls.h> 27#include <zircon/types.h> 28 29#define DEV_INPUT "/dev/class/input" 30#define CLEAR_BTN_SIZE 50 31#define I2C_HID_DEBUG 0 32 33enum touch_panel_type { 34 TOUCH_PANEL_UNKNOWN, 35 TOUCH_PANEL_ACER12, 36 TOUCH_PANEL_PARADISE, 37 TOUCH_PANEL_PARADISEv2, 38 TOUCH_PANEL_PARADISEv3, 39 TOUCH_PANEL_EGALAX, 40 TOUCH_PANEL_EYOYO, 41 TOUCH_PANEL_FT3X27, 42}; 43 44typedef struct display_info { 45 uint32_t width; 46 uint32_t height; 47 uint32_t stride; 48 zx_pixel_format_t format; 49} display_info_t; 50 51// Array of colors for each finger 52static uint32_t colors[] = { 53 0x00ff0000, 54 0x0000ff00, 55 0x000000ff, 56 0x00ffff00, 57 0x00ff00ff, 58 0x0000ffff, 59 0x00000000, 60 0x00f0f0f0, 61 0x00f00f00, 62 0x000ff000, 63}; 64 65static uint16_t colors16[] = { 66 0x003f, 67 0x03c0, 68 0xfc00, 69 0xe00f, 70 0xeff3, 71 0x003f, 72 0x03c0, 73 0x1c00, 74 0xe000, 75 0xe003, 76}; 77 78static bool run = false; 79 80static void acer12_touch_dump(acer12_touch_t* rpt) { 81 printf("report id: %u\n", rpt->rpt_id); 82 for (int i = 0; i < 5; i++) { 83 printf("finger %d\n", i); 84 printf(" finger_id: %u\n", rpt->fingers[i].finger_id); 85 printf(" tswitch: %u\n", acer12_finger_id_tswitch(rpt->fingers[i].finger_id)); 86 printf(" contact: %u\n", acer12_finger_id_contact(rpt->fingers[i].finger_id)); 87 printf(" width: %u\n", rpt->fingers[i].width); 88 printf(" height: %u\n", rpt->fingers[i].height); 89 printf(" x: %u\n", rpt->fingers[i].x); 90 printf(" y: %u\n", rpt->fingers[i].y); 91 } 92 printf("scan_time: %u\n", rpt->scan_time); 93 printf("contact count: %u\n", rpt->contact_count); 94} 95 96static void ft3x27_touch_dump(ft3x27_touch_t* rpt) { 97 printf("report id: %u\n", rpt->rpt_id); 98 for (int i = 0; i < 5; i++) { 99 printf("finger %d\n", i); 100 printf(" finger_id: %u\n", rpt->fingers[i].finger_id); 101 printf(" tswitch: %u\n", ft3x27_finger_id_tswitch(rpt->fingers[i].finger_id)); 102 printf(" contact: %u\n", ft3x27_finger_id_contact(rpt->fingers[i].finger_id)); 103 printf(" x: %u\n", rpt->fingers[i].x); 104 printf(" y: %u\n", rpt->fingers[i].y); 105 } 106 printf("contact count: %u\n", rpt->contact_count); 107} 108 109static void paradise_touch_dump(paradise_touch_t* rpt) { 110 printf("report id: %u\n", rpt->rpt_id); 111 printf("pad: %#02x\n", rpt->pad); 112 printf("contact count: %u\n", rpt->contact_count); 113 for (int i = 0; i < 5; i++) { 114 printf("finger %d\n", i); 115 printf(" flags: %#02x\n", rpt->fingers[i].flags); 116 printf(" tswitch: %u\n", paradise_finger_flags_tswitch(rpt->fingers[i].flags)); 117 printf(" confidence: %u\n", paradise_finger_flags_confidence(rpt->fingers[i].flags)); 118 printf(" finger_id: %u\n", rpt->fingers[i].finger_id); 119 printf(" x: %u\n", rpt->fingers[i].x); 120 printf(" y: %u\n", rpt->fingers[i].y); 121 } 122 printf("scan_time: %u\n", rpt->scan_time); 123} 124 125static void paradise_touch_v2_dump(paradise_touch_v2_t* rpt) { 126 printf("report id: %u\n", rpt->rpt_id); 127 printf("pad: %#02x\n", rpt->pad); 128 printf("contact count: %u\n", rpt->contact_count); 129 for (int i = 0; i < 5; i++) { 130 printf("finger %d\n", i); 131 printf(" flags: %#02x\n", rpt->fingers[i].flags); 132 printf(" tswitch: %u\n", paradise_finger_flags_tswitch(rpt->fingers[i].flags)); 133 printf(" confidence: %u\n", paradise_finger_flags_confidence(rpt->fingers[i].flags)); 134 printf(" finger_id: %u\n", rpt->fingers[i].finger_id); 135 printf(" width: %u\n", rpt->fingers[i].width); 136 printf(" height: %u\n", rpt->fingers[i].height); 137 printf(" x: %u\n", rpt->fingers[i].x); 138 printf(" y: %u\n", rpt->fingers[i].y); 139 } 140 printf("scan_time: %u\n", rpt->scan_time); 141} 142 143static void egalax_touch_dump(egalax_touch_t* rpt) { 144 printf("report id: %u\n", rpt->report_id); 145 printf("pad: %02x\n", egalax_pad(rpt->button_pad)); 146 printf("device supports one contact\n"); 147 printf(" finger down: %u\n", egalax_pressed_flags(rpt->button_pad)); 148 printf(" x: %u\n", rpt->x); 149 printf(" y: %u\n", rpt->y); 150} 151 152static void eyoyo_touch_dump(acer12_touch_t* rpt) { 153 printf("report id: %u\n", rpt->rpt_id); 154 for (int i = 0; i < 5; i++) { 155 printf("finger %d\n", i); 156 printf(" finger_id: %u\n", rpt->fingers[i].finger_id); 157 printf(" tswitch: %u\n", acer12_finger_id_tswitch(rpt->fingers[i].finger_id)); 158 printf(" contact: %u\n", acer12_finger_id_contact(rpt->fingers[i].finger_id)); 159 printf(" width: %u\n", rpt->fingers[i].width); 160 printf(" height: %u\n", rpt->fingers[i].height); 161 printf(" x: %u\n", rpt->fingers[i].x); 162 printf(" y: %u\n", rpt->fingers[i].y); 163 } 164 printf("scan_time: %u\n", rpt->scan_time); 165 printf("contact count: %u\n", rpt->contact_count); 166} 167 168static uint32_t scale32(uint32_t z, uint32_t screen_dim, uint32_t rpt_dim) { 169 return (z * screen_dim) / rpt_dim; 170} 171 172static void draw_points(uint32_t* pixels, uint32_t color, uint32_t x, uint32_t y, uint8_t width, uint8_t height, uint32_t fbwidth, uint32_t fbheight) { 173 uint32_t xrad = (width + 1) / 2; 174 uint32_t yrad = (height + 1) / 2; 175 176 uint32_t xmin = (xrad > x) ? 0 : x - xrad; 177 uint32_t xmax = (xrad > fbwidth - x) ? fbwidth : x + xrad; 178 uint32_t ymin = (yrad > y) ? 0 : y - yrad; 179 uint32_t ymax = (yrad > fbheight - y) ? fbheight : y + yrad; 180 181 for (uint32_t px = xmin; px < xmax; px++) { 182 for (uint32_t py = ymin; py < ymax; py++) { 183 *(pixels + py * fbwidth + px) = color; 184 } 185 } 186} 187static uint8_t is_exit(uint32_t x, uint32_t y, display_info_t* info) { 188 return (((y + CLEAR_BTN_SIZE) > info->height) && 189 (x < CLEAR_BTN_SIZE)); 190} 191 192static void draw_points16(uint32_t* pixels, uint16_t color, uint32_t x, uint32_t y, uint8_t width, uint8_t height, uint32_t fbwidth, uint32_t fbheight) { 193 194 uint16_t* pixels16 = (uint16_t*)pixels; 195 uint32_t xrad = (width + 1) / 2; 196 uint32_t yrad = (height + 1) / 2; 197 198 uint32_t xmin = (xrad > x) ? 0 : x - xrad; 199 uint32_t xmax = (xrad > fbwidth - x) ? fbwidth : x + xrad; 200 uint32_t ymin = (yrad > y) ? 0 : y - yrad; 201 uint32_t ymax = (yrad > fbheight - y) ? fbheight : y + yrad; 202 203 for (uint32_t px = xmin; px < xmax; px++) { 204 for (uint32_t py = ymin; py < ymax; py++) { 205 pixels16[py*fbwidth + px] = color; 206 } 207 } 208} 209 210static uint32_t get_color(uint8_t c) { 211 return colors[c]; 212} 213 214static uint32_t get_color16(uint8_t c) { 215 return colors16[c]; 216} 217 218static void clear_screen(void* buf, display_info_t* info) { 219 memset(buf, 0xff, ZX_PIXEL_FORMAT_BYTES(info->format) * info->stride * info->height); 220 if (ZX_PIXEL_FORMAT_BYTES(info->format) == 4) { 221 draw_points((uint32_t*)buf, 0xff00ff, info->stride - (CLEAR_BTN_SIZE / 2), 222 (CLEAR_BTN_SIZE / 2), CLEAR_BTN_SIZE, CLEAR_BTN_SIZE, info->stride, 223 info->height); 224 draw_points((uint32_t*)buf, 0x0000ff, (CLEAR_BTN_SIZE / 2), 225 info->height - (CLEAR_BTN_SIZE / 2), CLEAR_BTN_SIZE, CLEAR_BTN_SIZE, info->stride, 226 info->height); 227 } else if (ZX_PIXEL_FORMAT_BYTES(info->format) == 2) { 228 draw_points16((uint32_t*)buf, 0xf00f, info->stride - (CLEAR_BTN_SIZE / 2), 229 (CLEAR_BTN_SIZE / 2), CLEAR_BTN_SIZE, CLEAR_BTN_SIZE, info->stride, 230 info->height); 231 draw_points16((uint32_t*)buf, 0x001f, (CLEAR_BTN_SIZE / 2), 232 info->height - (CLEAR_BTN_SIZE / 2), CLEAR_BTN_SIZE, CLEAR_BTN_SIZE, info->stride, 233 info->height); 234 } 235} 236 237static void process_acer12_touchscreen_input(void* buf, size_t len, uint32_t* pixels, 238 display_info_t* info) { 239 acer12_touch_t* rpt = buf; 240 if (len < sizeof(*rpt)) { 241 printf("bad report size: %zd < %zd\n", len, sizeof(*rpt)); 242 return; 243 } 244#if I2C_HID_DEBUG 245 acer12_touch_dump(rpt); 246#endif 247 for (uint8_t c = 0; c < 5; c++) { 248 if (!acer12_finger_id_tswitch(rpt->fingers[c].finger_id % 10)) continue; 249 uint32_t x = scale32(rpt->fingers[c].x, info->width, ACER12_X_MAX); 250 uint32_t y = scale32(rpt->fingers[c].y, info->height, ACER12_Y_MAX); 251 uint32_t width = 2 * rpt->fingers[c].width; 252 uint32_t height = 2 * rpt->fingers[c].height; 253 uint32_t color = get_color(acer12_finger_id_contact(rpt->fingers[c].finger_id)); 254 draw_points(pixels, color, x, y, width, height, info->stride, info->height); 255 } 256 257 if (acer12_finger_id_tswitch(rpt->fingers[0].finger_id)) { 258 uint32_t x = scale32(rpt->fingers[0].x, info->width, ACER12_X_MAX); 259 uint32_t y = scale32(rpt->fingers[0].y, info->height, ACER12_Y_MAX); 260 if (x + CLEAR_BTN_SIZE > info->width && y < CLEAR_BTN_SIZE) { 261 clear_screen(pixels, info); 262 } 263 run = !is_exit(x, y, info); 264 } 265} 266 267 268static void process_ft3x27_touchscreen_input(void* buf, size_t len, uint32_t* pixels, 269 display_info_t* info) { 270 ft3x27_touch_t* rpt = buf; 271 if (len < sizeof(*rpt)) { 272 printf("bad report size: %zd < %zd\n", len, sizeof(*rpt)); 273 return; 274 } 275#if I2C_HID_DEBUG 276 ft3x27_touch_dump(rpt); 277#endif 278 for (uint8_t c = 0; c < 5; c++) { 279 if (!ft3x27_finger_id_tswitch(rpt->fingers[c].finger_id)) continue; 280 uint32_t x = scale32(rpt->fingers[c].x, info->width, FT3X27_X_MAX); 281 uint32_t y = scale32(rpt->fingers[c].y, info->height, FT3X27_Y_MAX); 282 uint32_t width = 10;//2 * rpt->fingers[c].width; 283 uint32_t height = 10;//2 * rpt->fingers[c].height; 284 uint16_t color = get_color16(ft3x27_finger_id_contact(rpt->fingers[c].finger_id)); 285 draw_points16(pixels, color, x, y, width, height, info->stride, info->height); 286 } 287 288 if (ft3x27_finger_id_tswitch(rpt->fingers[0].finger_id)) { 289 uint32_t x = scale32(rpt->fingers[0].x, info->width, FT3X27_X_MAX); 290 uint32_t y = scale32(rpt->fingers[0].y, info->height, FT3X27_Y_MAX); 291 if (x + CLEAR_BTN_SIZE > info->width && y < CLEAR_BTN_SIZE) { 292 clear_screen(pixels, info); 293 } 294 run = !is_exit(x, y, info); 295 } 296} 297 298static void process_egalax_touchscreen_input(void* buf, size_t len, uint32_t* pixels, 299 display_info_t* info) { 300 egalax_touch_t* rpt = buf; 301 if (len < sizeof(*rpt)) { 302 printf("bad report size: %zd < %zd\n", len, sizeof(*rpt)); 303 return; 304 } 305#if I2C_HID_DEBUG 306 egalax_touch_dump(rpt); 307#endif 308 if (!egalax_pressed_flags(rpt->button_pad)) { 309 uint32_t x = scale32(rpt->x, info->width, EGALAX_X_MAX); 310 uint32_t y = scale32(rpt->y, info->height, EGALAX_Y_MAX); 311 uint32_t width = 5; 312 uint32_t height = 5; 313 uint32_t color = get_color(1); 314 draw_points(pixels, color, x, y, width, height, info->stride, info->height); 315 } else { 316 uint32_t x = scale32(rpt->x, info->width, EGALAX_X_MAX); 317 uint32_t y = scale32(rpt->y, info->height, EGALAX_Y_MAX); 318 if (x + CLEAR_BTN_SIZE > info->width && y < CLEAR_BTN_SIZE) { 319 clear_screen(pixels, info); 320 } 321 run = !is_exit(x, y, info); 322 } 323} 324 325static void process_eyoyo_touchscreen_input(void* buf, size_t len, uint32_t* pixels, 326 display_info_t* info) { 327 eyoyo_touch_t* rpt = buf; 328 if (len < sizeof(*rpt)) { 329 printf("bad report size: %zd < %zd\n", len, sizeof(*rpt)); 330 return; 331 } 332#if I2C_HID_DEBUG 333 eyoyo_touch_dump(rpt); 334#endif 335 336 for (uint8_t c = 0; c < 10; c++) { 337 if (!eyoyo_finger_id_tswitch(rpt->fingers[c].finger_id)) continue; 338 uint32_t x = scale32(rpt->fingers[c].x, info->width, EYOYO_X_MAX); 339 uint32_t y = scale32(rpt->fingers[c].y, info->height, EYOYO_Y_MAX); 340 uint32_t width = 10; 341 uint32_t height = 10; 342 uint32_t color = get_color(eyoyo_finger_id_contact(rpt->fingers[c].finger_id)); 343 draw_points(pixels, color, x, y, width, height, info->stride, info->height); 344 } 345 346 if (eyoyo_finger_id_tswitch(rpt->fingers[0].finger_id)) { 347 uint32_t x = scale32(rpt->fingers[0].x, info->width, FT3X27_X_MAX); 348 uint32_t y = scale32(rpt->fingers[0].y, info->height, FT3X27_Y_MAX); 349 if (x + CLEAR_BTN_SIZE > info->width && y < CLEAR_BTN_SIZE) { 350 clear_screen(pixels, info); 351 } 352 run = !is_exit(x, y, info); 353 } 354} 355 356static void process_paradise_touchscreen_input(void* buf, size_t len, uint32_t* pixels, 357 display_info_t* info) { 358 paradise_touch_t* rpt = buf; 359 if (len < sizeof(*rpt)) { 360 printf("bad report size: %zd < %zd\n", len, sizeof(*rpt)); 361 return; 362 } 363#if I2C_HID_DEBUG 364 paradise_touch_dump(rpt); 365#endif 366 for (uint8_t c = 0; c < 5; c++) { 367 if (!paradise_finger_flags_tswitch(rpt->fingers[c].flags)) continue; 368 uint32_t x = scale32(rpt->fingers[c].x, info->width, PARADISE_X_MAX); 369 uint32_t y = scale32(rpt->fingers[c].y, info->height, PARADISE_Y_MAX); 370 uint32_t width = 10; 371 uint32_t height = 10; 372 uint32_t color = get_color(c); 373 draw_points(pixels, color, x, y, width, height, info->stride, info->height); 374 } 375 376 if (paradise_finger_flags_tswitch(rpt->fingers[0].flags)) { 377 uint32_t x = scale32(rpt->fingers[0].x, info->width, PARADISE_X_MAX); 378 uint32_t y = scale32(rpt->fingers[0].y, info->height, PARADISE_Y_MAX); 379 if (x + CLEAR_BTN_SIZE > info->width && y < CLEAR_BTN_SIZE) { 380 clear_screen(pixels, info); 381 } 382 run = !is_exit(x, y, info); 383 } 384} 385 386static void process_paradise_touchscreen_v2_input(void* buf, size_t len, uint32_t* pixels, 387 display_info_t* info) { 388 paradise_touch_v2_t* rpt = buf; 389 if (len < sizeof(*rpt)) { 390 printf("bad report size: %zd < %zd\n", len, sizeof(*rpt)); 391 return; 392 } 393#if I2C_HID_DEBUG 394 paradise_touch_v2_dump(rpt); 395#endif 396 for (uint8_t c = 0; c < 5; c++) { 397 if (!paradise_finger_flags_tswitch(rpt->fingers[c].flags)) continue; 398 uint32_t x = scale32(rpt->fingers[c].x, info->width, PARADISE_X_MAX); 399 uint32_t y = scale32(rpt->fingers[c].y, info->height, PARADISE_Y_MAX); 400 uint32_t width = 2 * rpt->fingers[c].width; 401 uint32_t height = 2 * rpt->fingers[c].height; 402 uint32_t color = get_color(c); 403 draw_points(pixels, color, x, y, width, height, info->stride, info->height); 404 } 405 406 if (paradise_finger_flags_tswitch(rpt->fingers[0].flags)) { 407 uint32_t x = scale32(rpt->fingers[0].x, info->width, PARADISE_X_MAX); 408 uint32_t y = scale32(rpt->fingers[0].y, info->height, PARADISE_Y_MAX); 409 if (x + CLEAR_BTN_SIZE > info->width && y < CLEAR_BTN_SIZE) { 410 clear_screen(pixels, info); 411 } 412 run = !is_exit(x, y, info); 413 } 414} 415 416static void process_acer12_stylus_input(void* buf, size_t len, uint32_t* pixels, 417 display_info_t* info) { 418 acer12_stylus_t* rpt = buf; 419 if (len < sizeof(*rpt)) { 420 printf("bad report size: %zd < %zd\n", len, sizeof(*rpt)); 421 return; 422 } 423 // Don't draw for out of range or hover with no switches. 424 if (!rpt->status || rpt->status == ACER12_STYLUS_STATUS_INRANGE) return; 425 426 uint32_t x = scale32(rpt->x, info->width, ACER12_STYLUS_X_MAX); 427 uint32_t y = scale32(rpt->y, info->height, ACER12_STYLUS_Y_MAX); 428 // Pressing the clear button requires contact (not just hover). 429 if (acer12_stylus_status_tswitch(rpt->status)) { 430 if (x + CLEAR_BTN_SIZE > info->width && y < CLEAR_BTN_SIZE) { 431 clear_screen(pixels, info); 432 return; 433 } 434 run = !is_exit(x, y, info); 435 } 436 uint32_t size, color; 437 size = acer12_stylus_status_tswitch(rpt->status) ? rpt->pressure >> 4 : 4; 438 switch (rpt->status) { 439 case 3: // in_range | tip_switch 440 color = get_color(0); 441 break; 442 case 5: // in_range | barrel_switch 443 color = get_color(1); 444 break; 445 case 7: // in_range | tip_switch | barrel_switch 446 color = get_color(4); 447 break; 448 case 9: // in_range | invert 449 color = get_color(5); 450 break; 451 case 17: // in_range | erase (== tip_switch | invert) 452 color = 0x00ffffff; 453 size = 32; // fixed size eraser 454 break; 455 default: 456 printf("unknown rpt->status=%u\n", rpt->status); 457 color = get_color(6); 458 break; 459 } 460 461 draw_points(pixels, color, x, y, size, size, info->stride, info->height); 462} 463 464int main(int argc, char* argv[]) { 465 const char* err; 466 zx_status_t status = fb_bind(true, &err); 467 if (status != ZX_OK) { 468 printf("failed to open framebuffer: %d (%s)\n", status, err); 469 return -1; 470 } 471 472 display_info_t info; 473 fb_get_config(&info.width, &info.height, &info.stride, &info.format); 474 475 zx_handle_t vmo = fb_get_single_buffer(); 476 477 printf("format = %d\n", info.format); 478 printf("width = %d\n", info.width); 479 printf("height = %d\n", info.height); 480 printf("stride = %d\n", info.stride); 481 482 size_t size = info.stride * ZX_PIXEL_FORMAT_BYTES(info.format) * info.height; 483 uintptr_t fbo; 484 status = _zx_vmar_map(zx_vmar_root_self(), 485 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 486 0, vmo, 0, size, &fbo); 487 if (status < 0) { 488 printf("couldn't map fb: %d\n", status); 489 return -1; 490 } 491 492 uint32_t* pixels32 = (uint32_t*)fbo; 493 494 clear_screen((void*)fbo, &info); 495 zx_cache_flush(pixels32, size, ZX_CACHE_FLUSH_DATA); 496 497 // Scan /dev/class/input to find the touchscreen 498 struct dirent* de; 499 DIR* dir = opendir(DEV_INPUT); 500 if (!dir) { 501 printf("failed to open %s: %d\n", DEV_INPUT, errno); 502 return -1; 503 } 504 505 ssize_t ret; 506 int touchfd = -1; 507 size_t rpt_desc_len = 0; 508 uint8_t* rpt_desc = NULL; 509 enum touch_panel_type panel = TOUCH_PANEL_UNKNOWN; 510 while ((de = readdir(dir)) != NULL) { 511 char devname[128]; 512 513 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { 514 continue; 515 } 516 517 snprintf(devname, sizeof(devname), "%s/%s", DEV_INPUT, de->d_name); 518 touchfd = open(devname, O_RDONLY); 519 if (touchfd < 0) { 520 printf("failed to open %s: %d\n", devname, errno); 521 continue; 522 } 523 524 ret = ioctl_input_get_report_desc_size(touchfd, &rpt_desc_len); 525 if (ret < 0) { 526 printf("failed to get report descriptor length for %s: %zd\n", devname, ret); 527 goto next_node; 528 } 529 530 rpt_desc = malloc(rpt_desc_len); 531 if (rpt_desc == NULL) { 532 printf("no memory!\n"); 533 exit(-1); 534 } 535 536 ret = ioctl_input_get_report_desc(touchfd, rpt_desc, rpt_desc_len); 537 if (ret < 0) { 538 printf("failed to get report descriptor for %s: %zd\n", devname, ret); 539 goto next_node; 540 } 541 542 if (is_acer12_touch_report_desc(rpt_desc, rpt_desc_len)) { 543 panel = TOUCH_PANEL_ACER12; 544 // Found the touchscreen 545 printf("touchscreen: %s\n", devname); 546 break; 547 } 548 549 if (is_paradise_touch_report_desc(rpt_desc, rpt_desc_len)) { 550 panel = TOUCH_PANEL_PARADISE; 551 // Found the touchscreen 552 printf("touchscreen: %s\n", devname); 553 break; 554 } 555 556 if (is_paradise_touch_v2_report_desc(rpt_desc, rpt_desc_len)) { 557 panel = TOUCH_PANEL_PARADISEv2; 558 // Found the touchscreen 559 printf("touchscreen: %s\n", devname); 560 break; 561 } 562 563 if (is_paradise_touch_v3_report_desc(rpt_desc, rpt_desc_len)) { 564 panel = TOUCH_PANEL_PARADISEv3; 565 // Found the touchscreen 566 printf("touchscreen: %s\n", devname); 567 break; 568 } 569 570 if (is_egalax_touchscreen_report_desc(rpt_desc, rpt_desc_len)) { 571 panel = TOUCH_PANEL_EGALAX; 572 printf("touchscreen: %s is egalax\n", devname); 573 break; 574 } 575 576 if (is_eyoyo_touch_report_desc(rpt_desc, rpt_desc_len)) { 577 panel = TOUCH_PANEL_EYOYO; 578 printf("touchscreen: %s is eyoyo\n", devname); 579 setup_eyoyo_touch(touchfd); 580 break; 581 } 582 583 if (is_ft3x27_touch_report_desc(rpt_desc, rpt_desc_len)) { 584 panel = TOUCH_PANEL_FT3X27; 585 printf("touchscreen: %s is ft3x27\n", devname); 586 break; 587 } 588 589next_node: 590 rpt_desc_len = 0; 591 592 if (rpt_desc != NULL) { 593 free(rpt_desc); 594 rpt_desc = NULL; 595 } 596 597 if (touchfd >= 0) { 598 close(touchfd); 599 touchfd = -1; 600 } 601 } 602 closedir(dir); 603 604 if (touchfd < 0) { 605 printf("could not find a touchscreen!\n"); 606 return -1; 607 } 608 assert(rpt_desc_len > 0); 609 assert(rpt_desc); 610 611 input_report_size_t max_rpt_sz = 0; 612 ret = ioctl_input_get_max_reportsize(touchfd, &max_rpt_sz); 613 if (ret < 0) { 614 printf("failed to get max report size: %zd\n", ret); 615 return -1; 616 } 617 printf("Max report size is %u\n",max_rpt_sz); 618 void* buf = malloc(max_rpt_sz); 619 if (buf == NULL) { 620 printf("no memory!\n"); 621 return -1; 622 } 623 624 run = true; 625 while (run) { 626 ssize_t r = read(touchfd, buf, max_rpt_sz); 627 if (r < 0) { 628 printf("touchscreen read error: %zd (errno=%d)\n", r, errno); 629 break; 630 } 631 if (panel == TOUCH_PANEL_ACER12) { 632 if (*(uint8_t*)buf == ACER12_RPT_ID_TOUCH) { 633 process_acer12_touchscreen_input(buf, r, pixels32, &info); 634 } else if (*(uint8_t*)buf == ACER12_RPT_ID_STYLUS) { 635 process_acer12_stylus_input(buf, r, pixels32, &info); 636 } 637 } else if (panel == TOUCH_PANEL_PARADISE) { 638 if (*(uint8_t*)buf == PARADISE_RPT_ID_TOUCH) { 639 process_paradise_touchscreen_input(buf, r, pixels32, &info); 640 } 641 } else if (panel == TOUCH_PANEL_PARADISEv2) { 642 if (*(uint8_t*)buf == PARADISE_RPT_ID_TOUCH) { 643 process_paradise_touchscreen_v2_input(buf, r, pixels32, &info); 644 } 645 } else if (panel == TOUCH_PANEL_PARADISEv3) { 646 if (*(uint8_t*)buf == PARADISE_RPT_ID_TOUCH) { 647 process_paradise_touchscreen_input(buf, r, pixels32, &info); 648 } 649 } else if (panel == TOUCH_PANEL_EGALAX) { 650 if (*(uint8_t*)buf == EGALAX_RPT_ID_TOUCH) { 651 process_egalax_touchscreen_input(buf, r, pixels32, &info); 652 } 653 } else if (panel == TOUCH_PANEL_EYOYO) { 654 if (*(uint8_t*)buf == EYOYO_RPT_ID_TOUCH) { 655 process_eyoyo_touchscreen_input(buf, r, pixels32, &info); 656 } 657 } else if (panel == TOUCH_PANEL_FT3X27) { 658 if (*(uint8_t*)buf == FT3X27_RPT_ID_TOUCH) { 659 process_ft3x27_touchscreen_input(buf, r, pixels32, &info); 660 } 661 } 662 zx_cache_flush(pixels32, size, ZX_CACHE_FLUSH_DATA); 663 } 664 memset(pixels32, 0x00, ZX_PIXEL_FORMAT_BYTES(info.format) * info.stride * info.height); 665 zx_cache_flush(pixels32, size, ZX_CACHE_FLUSH_DATA); 666 667 free(buf); 668 free(rpt_desc); 669 close(touchfd); 670 _zx_vmar_unmap(zx_vmar_root_self(), fbo, size); 671 fb_release(); 672 return 0; 673} 674