1/* 2 * Copyright 1995, 1999 by Patrick Lecoanet, France. <lecoanet@cena.dgac.fr> 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Patrick Lecoanet not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Patrick Lecoanet makes no 11 * representations about the suitability of this software for any purpose. It 12 * is provided "as is" without express or implied warranty. 13 * 14 * PATRICK LECOANET DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL PATRICK LECOANET BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 */ 23 24/* 25 ******************************************************************************* 26 ******************************************************************************* 27 * 28 * This driver is able to deal with Elographics SmartSet serial controllers. 29 * It uses only a subset of the functions provided through the protocol. 30 * 31 * SUPPORT FOR E281-2310 and compatible controllers added with help of: 32 * 1996/01/17 Juergen P. Meier (jpm@mailserv.rz.fh-muenchen.de) and 33 * 1998/03/25 G.Felkel@edelmann.de 34 * 35 * The E281-2310 is a somewhat lobotomized 2210. 36 * It does not support the c,g,h,k,l,p,q,s and t commands. 37 * Especially the P command, which is used to check the baud rate. 38 * The E281-2310 however semms to use always 9600bps, 8bit, 1stop 39 * no parity, Hardwarehandshake (RTS-CTS) (which are the drivers 40 * default values) 41 * 42 ******************************************************************************* 43 ******************************************************************************* 44 */ 45 46#ifdef HAVE_CONFIG_H 47#include "config.h" 48#endif 49 50#include "xorgVersion.h" 51 52 53#include "misc.h" 54#include "xf86.h" 55#include "xf86_OSproc.h" 56#include "xf86Xinput.h" 57#include "exevents.h" 58 59#include "xf86Module.h" 60 61/** 62 * models to be treated specially. 63 */ 64#define MODEL_UNKNOWN -1 65#define MODEL_SUNIT_D 1 66 67typedef struct { 68 int type; 69 const char *name; 70} Model; 71 72static Model SupportedModels[] = 73{ 74 {MODEL_SUNIT_D, "Sunit dSeries"}, /* sunit dSeries models don't reply to queries */ 75 {MODEL_UNKNOWN, NULL} 76}; 77/* 78 *************************************************************************** 79 * 80 * Default constants. 81 * 82 *************************************************************************** 83 */ 84#define ELO_MAX_TRIALS 3 /* Number of timeouts waiting for a */ 85 /* pending reply. */ 86#define ELO_MAX_WAIT 100000 /* Max wait time for a reply (microsec) */ 87#define ELO_UNTOUCH_DELAY 5 /* 100 ms */ 88#define ELO_REPORT_DELAY 1 /* 40 ms or 25 motion reports/s */ 89#define ELO_LINK_SPEED B9600 /* 9600 Bauds */ 90#define ELO_PORT "/dev/ttyS1" 91 92#define DEFAULT_MAX_X 3000 93#define DEFAULT_MIN_X 600 94#define DEFAULT_MAX_Y 3000 95#define DEFAULT_MIN_Y 600 96 97 98/* 99 *************************************************************************** 100 * 101 * Protocol constants. 102 * 103 *************************************************************************** 104 */ 105#define ELO_PACKET_SIZE 10 106#define ELO_UNFRAMED_SIZE 8 107 108#define ELO_SYNC_BYTE 'U' /* Sync byte. First of a packet. */ 109#define ELO_TOUCH 'T' /* Report of touchs and motions. Not * 110 * used by 2310. */ 111#define ELO_OWNER 'O' /* Report vendor name. */ 112#define ELO_ID 'I' /* Report of type and features. */ 113#define ELO_MODE 'M' /* Set current operating mode. */ 114#define ELO_PARAMETER 'P' /* Set the serial parameters. */ 115#define ELO_REPORT 'B' /* Set touch reports timings. */ 116#define ELO_ACK 'A' /* Acknowledge packet */ 117 118#define ELO_INIT_CHECKSUM 0xAA /* Initial value of checksum. */ 119 120#define ELO_PRESS 0x01 /* Flags in ELO_TOUCH status byte */ 121#define ELO_STREAM 0x02 122#define ELO_RELEASE 0x04 123 124#define ELO_TOUCH_MODE 0x01 /* Flags in ELO_MODE command */ 125#define ELO_STREAM_MODE 0x02 126#define ELO_UNTOUCH_MODE 0x04 127#define ELO_RANGE_CHECK_MODE 0x40 128#define ELO_TRIM_MODE 0x02 129#define ELO_CALIB_MODE 0x04 130#define ELO_SCALING_MODE 0x08 131#define ELO_TRACKING_MODE 0x40 132 133#define ELO_SERIAL_SPEED 0x06 /* Flags for high speed serial (19200) */ 134#define ELO_SERIAL_MASK 0xF8 135 136#define ELO_SERIAL_IO '0' /* Indicator byte for PARAMETER command */ 137 138 139/* 140 *************************************************************************** 141 * 142 * Useful macros. 143 * 144 *************************************************************************** 145 */ 146#define WORD_ASSEMBLY(byte1, byte2) (((byte2) << 8) | (byte1)) 147#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) 148 149/* This one is handy, thanx Fred ! */ 150#ifdef DBG 151#undef DBG 152#endif 153#ifdef DEBUG 154#undef DEBUG 155#endif 156 157static int debug_level = 0; 158#define DEBUG 1 159#if DEBUG 160#define DBG(lvl, f) {if ((lvl) <= debug_level) f;} 161#else 162#define DBG(lvl, f) 163#endif 164 165#undef SYSCALL 166#undef read 167#undef write 168#undef close 169#define SYSCALL(call) call 170#define read(fd, ptr, num) xf86ReadSerial(fd, ptr, num) 171#define write(fd, ptr, num) xf86WriteSerial(fd, ptr, num) 172#define close(fd) xf86CloseSerial(fd) 173 174 175/* 176 *************************************************************************** 177 * 178 * Device private records. 179 * 180 *************************************************************************** 181 */ 182typedef struct _EloPrivateRec { 183 char *input_dev; /* The touchscreen input tty */ 184 int min_x; /* Minimum x reported by calibration */ 185 int max_x; /* Maximum x */ 186 int min_y; /* Minimum y reported by calibration */ 187 int max_y; /* Maximum y */ 188 int untouch_delay; /* Delay before reporting an untouch (in ms) */ 189 int report_delay; /* Delay between touch report packets */ 190 int screen_no; /* Screen associated with the device */ 191 int screen_width; /* Width of the associated X screen */ 192 int screen_height; /* Height of the screen */ 193 Bool inited; /* The controller has already been configured ? */ 194 Bool is_a_2310; /* Set if the smartset is a 2310. */ 195 int checksum; /* Current checksum of data in assembly buffer */ 196 int packet_buf_p; /* Assembly buffer pointer */ 197 int swap_axes; /* Swap X an Y axes if != 0 */ 198 unsigned char packet_buf[ELO_PACKET_SIZE]; /* Assembly buffer */ 199 int model; /* one of MODEL_... */ 200 Bool no_framing; /* Whether packets are framed */ 201 202} EloPrivateRec, *EloPrivatePtr; 203 204/* 205 *************************************************************************** 206 * 207 * xf86EloGetPacket -- 208 * Read a packet from the port. Try to synchronize with start of 209 * packet and compute checksum. 210 * The packet structure read by this function is as follow: 211 * Byte 0 : ELO_SYNC_BYTE 212 * Byte 1 213 * ... 214 * Byte 8 : packet data 215 * Byte 9 : checksum of bytes 0 to 8 216 * 217 * This function returns if a valid packet has been assembled in 218 * buffer or if no more data is available. 219 * 220 * Returns Success if a packet is successfully assembled including 221 * testing checksum. If a packet checksum is incorrect, it is discarded. 222 * Bytes preceding the ELO_SYNC_BYTE are also discarded. 223 * Returns !Success if out of data while reading. The start of the 224 * partially assembled packet is left in buffer, buffer_p and 225 * checksum reflect the current state of assembly. 226 * 227 *************************************************************************** 228 */ 229static Bool 230xf86EloGetPacket(unsigned char *buffer, 231 int *buffer_p, 232 int *checksum, 233 int fd) 234{ 235 int num_bytes; 236 Bool ok; 237 238 DBG(4, ErrorF("Entering xf86EloGetPacket with checksum == %d and buffer_p == %d\n", 239 *checksum, *buffer_p)); 240 241 /* 242 * Try to read enough bytes to fill up the packet buffer. 243 */ 244 DBG(4, ErrorF("buffer_p is %d, Trying to read %d bytes from link\n", 245 *buffer_p, ELO_PACKET_SIZE - *buffer_p)); 246 SYSCALL(num_bytes = read(fd, 247 (char *) (buffer + *buffer_p), 248 ELO_PACKET_SIZE - *buffer_p)); 249 250 /* 251 * Okay, give up. 252 */ 253 if (num_bytes < 0) { 254 ErrorF("System error while reading from Elographics touchscreen."); 255 return !Success; 256 } 257 DBG(4, ErrorF("Read %d bytes\n", num_bytes)); 258 259 while (num_bytes) { 260 /* 261 * Sync with the start of a packet. 262 */ 263 if ((*buffer_p == 0) && (buffer[0] != ELO_SYNC_BYTE)) { 264 /* 265 * No match, shift data one byte toward the start of the buffer. 266 */ 267 ErrorF("Elographics: Dropping one byte in an attempt to synchronize: '%c' 0x%X\n", 268 buffer[0], buffer[0]); 269 memmove(&buffer[0], &buffer[1], num_bytes-1); 270 } 271 else { 272 /* 273 * Compute checksum in assembly buffer. 274 */ 275 if (*buffer_p < ELO_PACKET_SIZE-1) { 276 *checksum = *checksum + buffer[*buffer_p]; 277 *checksum = *checksum % 256; 278 DBG(4, ErrorF(" 0x%X-->0x%X ", buffer[*buffer_p], *checksum)); 279 } 280 (*buffer_p)++; 281 } 282 num_bytes--; 283 } 284 285 if (*buffer_p == ELO_PACKET_SIZE) { 286 /* 287 * Got a packet, validate checksum and reset state. 288 */ 289 ok = (*checksum == buffer[ELO_PACKET_SIZE-1]); 290 DBG(3, ErrorF("Expecting checksum %d, got %d\n", *checksum, buffer[ELO_PACKET_SIZE-1])); 291 *checksum = ELO_INIT_CHECKSUM; 292 *buffer_p = 0; 293 294 if (!ok) { 295 ErrorF("Checksum error on Elographics touchscreen link\n"); 296 return !Success; 297 } 298 299 /* 300 * Valid packet received report it. 301 */ 302 return Success; 303 } 304 else { 305 return !Success; 306 } 307} 308 309/* 310 *************************************************************************** 311 * 312 * xf86EloGetUnframedPacket -- 313 * Read an unframed packet from the port 314 * The packet structure read by this function is as follow: 315 * Byte 0 : ELO_TOUCH 316 * Byte 1 317 * ... 318 * Byte 8 : packet data 319 * 320 * This function returns if a valid packet has been assembled in 321 * buffer or if no more data is available. 322 * 323 * 324 *************************************************************************** 325 */ 326static Bool 327xf86EloGetUnframedPacket(unsigned char *buffer, 328 int fd) 329{ 330 int num_bytes; 331 Bool ok; 332 333 SYSCALL(num_bytes = read(fd, 334 (char *) (buffer), 335 ELO_UNFRAMED_SIZE)); 336 337 /* 338 * Okay, give up. 339 */ 340 if (num_bytes != ELO_UNFRAMED_SIZE) { 341 ErrorF("System error while reading from Elographics touchscreen."); 342 return !Success; 343 } 344 DBG(4, ErrorF("Read %d bytes\n", num_bytes)); 345 346 return Success; 347} 348 349/* 350 *************************************************************************** 351 * 352 * xf86EloReadInput -- 353 * Read all pending report packets from the touchscreen and enqueue 354 * them. 355 * If a packet is not fully received it is deferred until the next 356 * call to the function. 357 * Packets recognized by this function comply with the format: 358 * 359 * Byte 1 : ELO_TOUCH 360 * Byte 2 : Packet type 361 * Bit 2 : Pen Up (Release) 362 * Bit 1 : Position (Stream) 363 * Bit 0 : Pen Down (Press) 364 * Byte 3 : X coordinate (lower bits) 365 * Byte 4 : X coordinate (upper bits) 366 * Byte 5 : Y coordinate (lower bits) 367 * Byte 6 : Y coordinate (upper bits) 368 * Byte 7 : Z coordinate (lower bits) 369 * Byte 8 : Z coordinates (upper bits) 370 * 371 * 372 *************************************************************************** 373 */ 374static void 375xf86EloReadInput(InputInfoPtr pInfo) 376{ 377 EloPrivatePtr priv = (EloPrivatePtr)(pInfo->private); 378 int cur_x, cur_y; 379 int state; 380 381 DBG(4, ErrorF("Entering ReadInput\n")); 382 383 /* 384 * Read bytes until there's no data left. We may have more or less than 385 * one packet worth of data in the OS buffer. 386 */ 387 do { 388 if (priv->no_framing) { 389 if(xf86EloGetUnframedPacket(&priv->packet_buf[1], 390 pInfo->fd) != Success) 391 continue; 392 } else { 393 if(xf86EloGetPacket(priv->packet_buf, 394 &priv->packet_buf_p, 395 &priv->checksum, 396 pInfo->fd) != Success) 397 continue; 398 } 399 /* 400 * Process only ELO_TOUCHs here. 401 */ 402 if (priv->packet_buf[1] == ELO_TOUCH) { 403 /* 404 * First stick together the various pieces. 405 */ 406 cur_x = WORD_ASSEMBLY(priv->packet_buf[3], priv->packet_buf[4]); 407 cur_y = WORD_ASSEMBLY(priv->packet_buf[5], priv->packet_buf[6]); 408 state = priv->packet_buf[2] & 0x07; 409 410 DBG(5, ErrorF("ELO got: x(%d), y(%d), %s\n", 411 cur_x, cur_y, 412 (state == ELO_PRESS) ? "Press" : 413 ((state == ELO_RELEASE) ? "Release" : "Stream"))); 414 415 if (priv->min_y > priv->max_y) { 416 /* inverted y axis */ 417 cur_y = priv->max_y - cur_y + priv->min_y; 418 } 419 420 if (priv->min_x > priv->max_x) { 421 /* inverted x axis */ 422 cur_x = priv->max_x - cur_x + priv->min_x; 423 } 424 425 426 /* 427 * Send events. 428 * 429 * We *must* generate a motion before a button change if pointer 430 * location has changed as DIX assumes this. This is why we always 431 * emit a motion, regardless of the kind of packet processed. 432 */ 433 xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, cur_x, cur_y); 434 435 /* 436 * Emit a button press or release. 437 */ 438 if (state == ELO_PRESS || state == ELO_RELEASE) { 439 xf86PostButtonEvent(pInfo->dev, TRUE, 1, state == ELO_PRESS, 0, 2, cur_x, cur_y); 440 } 441 442 DBG(3, ErrorF("TouchScreen: x(%d), y(%d), %s\n", 443 cur_x, cur_y, 444 (state == ELO_PRESS) ? "Press" : ((state == ELO_RELEASE) ? "Release" : "Stream"))); 445 } 446 } 447 while (xf86WaitForInput(pInfo->fd, 0) > 0); /* don't wait, just check */ 448} 449 450 451/* 452 *************************************************************************** 453 * 454 * xf86EloSendPacket -- 455 * Emit an height bytes packet to the controller. 456 * The function expects a valid buffer containing the 457 * command to be sent to the controller. It fills it with the 458 * leading sync character an the trailing checksum byte. 459 * 460 *************************************************************************** 461 */ 462static Bool 463xf86EloSendPacket(unsigned char *packet, 464 int fd) 465{ 466 int i, result; 467 int sum = ELO_INIT_CHECKSUM; 468 469 packet[0] = ELO_SYNC_BYTE; 470 for (i = 0; i < ELO_PACKET_SIZE-1; i++) { 471 sum += packet[i]; 472 sum &= 0xFF; 473 } 474 packet[ELO_PACKET_SIZE-1] = sum; 475 476 DBG(4, ErrorF("Sending packet : 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X \n", 477 packet[0], packet[1], packet[2], packet[3], packet[4], 478 packet[5], packet[6], packet[7], packet[8], packet[9])); 479 SYSCALL(result = write(fd, packet, ELO_PACKET_SIZE)); 480 if (result != ELO_PACKET_SIZE) { 481 DBG(5, ErrorF("System error while sending to Elographics touchscreen.\n")); 482 return !Success; 483 } 484 else { 485 return Success; 486 } 487} 488 489 490/* 491 *************************************************************************** 492 * 493 * xf86EloWaitReply -- 494 * It is assumed that the reply will be in the few next bytes 495 * read and will be available very soon after the query post. if 496 * these two asumptions are not met, there are chances that the server 497 * will be stuck for a while. 498 * The reply type need to match parameter 'type'. 499 * The reply is left in reply. The function returns Success if the 500 * reply is valid and !Success otherwise. 501 * 502 *************************************************************************** 503 */ 504 505static Bool 506xf86EloWaitReply(unsigned char type, 507 unsigned char *reply, 508 int fd) 509{ 510 Bool ok; 511 int i, result; 512 int reply_p = 0; 513 int sum = ELO_INIT_CHECKSUM; 514 515 DBG(4, ErrorF("Waiting a '%c' reply\n", type)); 516 i = ELO_MAX_TRIALS; 517 do { 518 ok = !Success; 519 520 /* 521 * Wait half a second for the reply. The fuse counts down each 522 * timeout and each wrong packet. 523 */ 524 DBG(4, ErrorF("Waiting %d ms for data from port\n", ELO_MAX_WAIT / 1000)); 525 result = xf86WaitForInput(fd, ELO_MAX_WAIT); 526 if (result > 0) { 527 ok = xf86EloGetPacket(reply, &reply_p, &sum, fd); 528 /* 529 * Do not report an error on a 'P' query as the controller 530 * might be a 2310. 531 */ 532 if (ok == Success && reply[1] != type && type != ELO_PARAMETER) { 533 DBG(3, ErrorF("Wrong reply received\n")); 534 ok = !Success; 535 } 536 } 537 else { 538 DBG(3, ErrorF("No answer from link : %d\n", result)); 539 } 540 541 if (result == 0) { 542 i--; 543 } 544 } while(ok != Success && i); 545 546 return ok; 547} 548 549 550/* 551 *************************************************************************** 552 * 553 * xf86EloWaitAck -- 554 * Wait for an acknowledge from the controller. Returns Success if 555 * acknowledge received and reported no errors. 556 * 557 *************************************************************************** 558 */ 559static Bool 560xf86EloWaitAck(int fd) 561{ 562 unsigned char packet[ELO_PACKET_SIZE]; 563 int i, nb_errors; 564 565 if (xf86EloWaitReply(ELO_ACK, packet, fd) == Success) { 566 for (i = 0, nb_errors = 0; i < 4; i++) { 567 if (packet[2 + i] != '0') { 568 nb_errors++; 569 } 570 } 571 if (nb_errors != 0) { 572 DBG(2, ErrorF("Elographics acknowledge packet reports %d errors\n", 573 nb_errors)); 574 } 575 return Success; 576 /* return (nb_errors < 4) ? Success : !Success;*/ 577 } 578 else { 579 return !Success; 580 } 581} 582 583 584/* 585 *************************************************************************** 586 * 587 * xf86EloSendQuery -- 588 * Emit a query to the controller and blocks until the reply and 589 * the acknowledge are read. 590 * 591 * The reply is left in reply. The function returns Success if the 592 * reply is valid and !Success otherwise. 593 * 594 *************************************************************************** 595 */ 596static Bool 597xf86EloSendQuery(unsigned char *request, 598 unsigned char *reply, 599 int fd) 600{ 601 Bool ok; 602 603 if (xf86EloSendPacket(request, fd) == Success) { 604 ok = xf86EloWaitReply(toupper(request[1]), reply, fd); 605 if (ok == Success) { 606 ok = xf86EloWaitAck(fd); 607 } 608 return ok; 609 } 610 else { 611 return !Success; 612 } 613} 614 615 616/* 617 *************************************************************************** 618 * 619 * xf86EloSendControl -- 620 * Emit a control command to the controller and wait for acknowledge. 621 * 622 * Returns Success if acknowledge received and reported no error. 623 * 624 *************************************************************************** 625 */ 626static Bool 627xf86EloSendControl(unsigned char *control, 628 int fd) 629{ 630 if (xf86EloSendPacket(control, fd) == Success) { 631 return xf86EloWaitAck(fd); 632 } 633 else { 634 return !Success; 635 } 636} 637 638 639/* 640 *************************************************************************** 641 * 642 * xf86EloPrintIdent -- 643 * Print type of touchscreen and features on controller board. 644 * 645 *************************************************************************** 646 */ 647static void 648xf86EloPrintIdent(unsigned char *packet, 649 EloPrivatePtr priv) 650{ 651 xf86Msg(X_PROBED, "Elographics touchscreen is a "); 652 switch(packet[2]) { 653 case '0': 654 xf86Msg(X_NONE, "AccuTouch"); 655 break; 656 case '1': 657 xf86Msg(X_NONE, "DuraTouch"); 658 break; 659 case '2': 660 xf86Msg(X_NONE, "Intellitouch"); 661 break; 662 } 663 xf86Msg(X_NONE, ", connected through a "); 664 switch(packet[3]) { 665 case '0': 666 xf86Msg(X_NONE, "serial link.\n"); 667 break; 668 case '1': 669 xf86Msg(X_NONE, "PC-Bus port.\n"); 670 break; 671 case '2': 672 xf86Msg(X_NONE, "Micro Channel port.\n"); 673 break; 674 } 675 xf86Msg(X_PROBED, "The controller is a model "); 676 if (packet[8] & 1) { 677 if (priv->is_a_2310) { 678 xf86Msg(X_NONE, "E281-2310"); 679 } 680 else { 681 xf86Msg(X_NONE, "E271-2210"); 682 } 683 } 684 else { 685 xf86Msg(X_NONE, "E271-2200"); 686 } 687 xf86Msg(X_NONE, ", firmware revision %d.%d.\n", packet[6], packet[5]); 688 689 if (packet[4]) { 690 xf86Msg(X_PROBED, " Additional features:\n"); 691 if (packet[4] & 0x10) { 692 xf86Msg(X_PROBED, " External A/D converter\n"); 693 } 694 if (packet[4] & 0x20) { 695 xf86Msg(X_PROBED, " 32Ko RAM\n"); 696 } 697 if (packet[4] & 0x40) { 698 xf86Msg(X_PROBED, " RAM onboard\n"); 699 } 700 if (packet[4] & 0x80) { 701 xf86Msg(X_PROBED, " Z axis active\n"); 702 } 703 xf86Msg(X_NONE, "\n"); 704 } 705} 706 707 708/* 709 *************************************************************************** 710 * 711 * xf86EloPtrControl -- 712 * 713 *************************************************************************** 714 */ 715 716static void 717xf86EloPtrControl(DeviceIntPtr dev, 718 PtrCtrl *ctrl) 719{ 720} 721 722 723 724/* 725 *************************************************************************** 726 * 727 * xf86EloControl -- 728 * 729 *************************************************************************** 730 */ 731static Bool 732xf86EloControl(DeviceIntPtr dev, 733 int mode) 734{ 735 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 736 EloPrivatePtr priv = (EloPrivatePtr)(pInfo->private); 737 unsigned char map[] = { 0, 1 }; 738 unsigned char req[ELO_PACKET_SIZE]; 739 unsigned char reply[ELO_PACKET_SIZE]; 740 Atom btn_label; 741 Atom axis_labels[2] = { 0, 0 }; 742 int x0, x1, y0, y1; 743 744 switch(mode) { 745 746 case DEVICE_INIT: 747 { 748 DBG(2, ErrorF("Elographics touchscreen init...\n")); 749 750 if (priv->screen_no >= screenInfo.numScreens || 751 priv->screen_no < 0) { 752 priv->screen_no = 0; 753 } 754 priv->screen_width = screenInfo.screens[priv->screen_no]->width; 755 priv->screen_height = screenInfo.screens[priv->screen_no]->height; 756 757 /* 758 * Device reports button press for up to 1 button. 759 */ 760 if (InitButtonClassDeviceStruct(dev, 1, &btn_label, map) == FALSE) { 761 ErrorF("Unable to allocate Elographics touchscreen ButtonClassDeviceStruct\n"); 762 return !Success; 763 } 764 765 if (InitFocusClassDeviceStruct(dev) == FALSE) { 766 ErrorF("Unable to allocate Elographics touchscreen FocusClassDeviceStruct\n"); 767 return !Success; 768 } 769 if (InitPtrFeedbackClassDeviceStruct(dev, xf86EloPtrControl) == FALSE) { 770 ErrorF("unable to init ptr feedback\n"); 771 return !Success; 772 } 773 /* 774 * Device reports motions on 2 axes in absolute coordinates. 775 * Axes min and max values are reported in raw coordinates. 776 * Resolution is computed roughly by the difference between 777 * max and min values scaled from the approximate size of the 778 * screen to fit one meter. 779 */ 780 if (InitValuatorClassDeviceStruct(dev, 2, axis_labels, 781 GetMotionHistorySize(), Absolute) == FALSE) { 782 ErrorF("Unable to allocate Elographics touchscreen ValuatorClassDeviceStruct\n"); 783 return !Success; 784 } 785 else { 786 787 /* Correct the coordinates for possibly inverted axis. 788 Leave priv->variables untouched so we can check for 789 inversion on incoming events. 790 */ 791 y0 = min(priv->min_y, priv->max_y); 792 y1 = max(priv->min_y, priv->max_y); 793 x0 = min(priv->min_x, priv->max_x); 794 x1 = max(priv->min_x, priv->max_x); 795 796 /* I will map coordinates myself */ 797 InitValuatorAxisStruct(dev, 0, 798 axis_labels[0], 799 x0, x1, 800 9500, 801 0 /* min_res */, 802 9500 /* max_res */, 803 Absolute); 804 InitValuatorAxisStruct(dev, 1, 805 axis_labels[1], 806 y0, y1, 807 10500, 808 0 /* min_res */, 809 10500 /* max_res */, 810 Absolute); 811 } 812 813 if (InitFocusClassDeviceStruct(dev) == FALSE) { 814 ErrorF("Unable to allocate Elographics touchscreen FocusClassDeviceStruct\n"); 815 } 816 817 /* 818 * Allocate the motion events buffer. 819 */ 820 xf86MotionHistoryAllocate(pInfo); 821 822 823 DBG(2, ErrorF("Done.\n")); 824 return Success; 825 } 826 827 case DEVICE_ON: 828 DBG(2, ErrorF("Elographics touchscreen on...\n")); 829 830 if (pInfo->fd < 0) { 831 832 DBG(2, ErrorF("Elographics touchscreen opening : %s\n", priv->input_dev)); 833 pInfo->fd = xf86OpenSerial(pInfo->options); 834 if (pInfo->fd < 0) { 835 ErrorF("Unable to open Elographics touchscreen device"); 836 return !Success; 837 } 838 839 if (priv->model != MODEL_SUNIT_D) 840 { 841 /* 842 * Try to see if the link is at the specified rate and 843 * ask the controller to report various infos. 844 */ 845 memset(req, 0, ELO_PACKET_SIZE); 846 req[1] = tolower(ELO_PARAMETER); 847 if (xf86EloSendQuery(req, reply, pInfo->fd) != Success) { 848 priv->is_a_2310 = 1; 849 ErrorF("Not at the specified rate or model 2310, will continue\n"); 850 } 851 852 /* 853 * Ask the controller to report various infos. 854 */ 855 memset(req, 0, ELO_PACKET_SIZE); 856 req[1] = tolower(ELO_ID); 857 if (xf86EloSendQuery(req, reply, pInfo->fd) == Success) { 858 xf86EloPrintIdent(reply, priv); 859 } 860 else { 861 DBG(2, ErrorF("Unable to ask Elographics touchscreen identification... Maybe it's GeneralTouch touchscreen...\n")); 862 } 863 864 /* 865 * Set the operating mode: Stream, no scaling, no calibration, 866 * no range checking, no trim, tracking enabled. 867 */ 868 memset(req, 0, ELO_PACKET_SIZE); 869 req[1] = ELO_MODE; 870 req[3] = ELO_TOUCH_MODE | ELO_STREAM_MODE | ELO_UNTOUCH_MODE; 871 req[4] = ELO_TRACKING_MODE; 872 if (xf86EloSendControl(req, pInfo->fd) != Success) { 873 DBG(2, ErrorF("Unable to change Elographics touchscreen operating mode... Maybe it's GeneralTouch touchscreen...\n")); 874 } 875 876 /* 877 * Set the touch reports timings from configuration data. 878 */ 879 memset(req, 0, ELO_PACKET_SIZE); 880 req[1] = ELO_REPORT; 881 req[2] = priv->untouch_delay; 882 req[3] = priv->report_delay; 883 if (xf86EloSendControl(req, pInfo->fd) != Success) { 884 DBG(2, ErrorF("Unable to change Elographics touchscreen reports timings... Maybe it's GeneralTouch touchscreen...\n")); 885 } 886 } 887 xf86AddEnabledDevice(pInfo); 888 dev->public.on = TRUE; 889 } 890 891 DBG(2, ErrorF("Done\n")); 892 return Success; 893 894 /* 895 * Deactivate the device. After this, the device will not emit 896 * events until a subsequent DEVICE_ON. Thus, we can momentarily 897 * close the port. 898 */ 899 case DEVICE_OFF: 900 DBG(2, ErrorF("Elographics touchscreen off...\n")); 901 dev->public.on = FALSE; 902 if (pInfo->fd >= 0) { 903 xf86RemoveEnabledDevice(pInfo); 904 } 905 SYSCALL(close(pInfo->fd)); 906 pInfo->fd = -1; 907 DBG(2, ErrorF("Done\n")); 908 return Success; 909 910 /* 911 * Final close before server exit. This is used during server shutdown. 912 * Close the port and free all the resources. 913 */ 914 case DEVICE_CLOSE: 915 DBG(2, ErrorF("Elographics touchscreen close...\n")); 916 dev->public.on = FALSE; 917 if (pInfo->fd >= 0) { 918 xf86RemoveEnabledDevice(pInfo); 919 } 920 SYSCALL(close(pInfo->fd)); 921 pInfo->fd = -1; 922 DBG(2, ErrorF("Done\n")); 923 return Success; 924 925#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) * 100 + GET_ABI_MINOR(ABI_XINPUT_VERSION) >= 1901 926 case DEVICE_ABORT: 927 return Success; 928#endif 929 930 default: 931 ErrorF("unsupported mode=%d\n", mode); 932 return BadValue; 933 } 934} 935 936/* 937 *************************************************************************** 938 * 939 * xf86EloAllocate -- 940 * 941 *************************************************************************** 942 */ 943static int 944xf86EloAllocate(InputDriverPtr drv, InputInfoPtr pInfo) 945{ 946 EloPrivatePtr priv; 947 948 priv = malloc(sizeof(EloPrivateRec)); 949 if (!priv) 950 return BadAlloc; 951 952 priv->input_dev = strdup(ELO_PORT); 953 priv->min_x = 0; 954 priv->max_x = 3000; 955 priv->min_y = 0; 956 priv->max_y = 3000; 957 priv->untouch_delay = ELO_UNTOUCH_DELAY; 958 priv->report_delay = ELO_REPORT_DELAY; 959 priv->screen_no = 0; 960 priv->screen_width = -1; 961 priv->screen_height = -1; 962 priv->inited = 0; 963 priv->is_a_2310 = 0; 964 priv->checksum = ELO_INIT_CHECKSUM; 965 priv->packet_buf_p = 0; 966 priv->swap_axes = 0; 967 priv->no_framing = 0; 968 pInfo->device_control = xf86EloControl; 969 pInfo->read_input = xf86EloReadInput; 970 pInfo->control_proc = NULL; 971 pInfo->switch_mode = NULL; 972 pInfo->private = priv; 973 pInfo->type_name = XI_TOUCHSCREEN; 974 975 return Success; 976} 977 978 979static void 980xf86EloUninit(InputDriverPtr drv, 981 InputInfoPtr pInfo, 982 int flags) 983{ 984 EloPrivatePtr priv = (EloPrivatePtr) pInfo->private; 985 986 free(priv->input_dev); 987 free(priv); 988 pInfo->private = NULL; 989 xf86DeleteInput(pInfo, 0); 990} 991 992static 993#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 18 994const 995#endif 996char *default_options[] = { 997 "BaudRate", "9600", 998 "StopBits", "1", 999 "DataBits", "8", 1000 "Parity", "None", 1001 "FlowControl", "None", 1002 NULL 1003}; 1004 1005static int 1006xf86EloInit(InputDriverPtr drv, 1007 InputInfoPtr pInfo, 1008 int flags) 1009{ 1010 EloPrivatePtr priv=NULL; 1011 const char *str; 1012 int portrait = 0; 1013 int height, width; 1014 char *opt_model; 1015 Model* model; 1016 int rc; 1017 1018 1019 rc = xf86EloAllocate(drv, pInfo); 1020 if (rc != Success) 1021 return rc; 1022 1023 priv = pInfo->private; 1024 1025 str = xf86SetStrOption(pInfo->options, "Device", NULL); 1026 if (!str) { 1027 xf86Msg(X_ERROR, "%s: No Device specified in Elographics module config.\n", 1028 pInfo->name); 1029 return BadValue; 1030 } else { 1031 pInfo->fd = xf86OpenSerial(pInfo->options); 1032 if (pInfo->fd < 0) { 1033 xf86Msg(X_ERROR, "%s: Unable to open Elographics touchscreen device %s", pInfo->name, str); 1034 return BadValue; 1035 } 1036 xf86CloseSerial(pInfo->fd); 1037 pInfo->fd = -1; 1038 } 1039 1040 priv->input_dev = strdup(str); 1041 1042 opt_model = xf86SetStrOption(pInfo->options, "Model", NULL); 1043 model = SupportedModels; 1044 priv->model = MODEL_UNKNOWN; 1045 while(model->type != MODEL_UNKNOWN && opt_model) 1046 { 1047 if (!strcmp(model->name, opt_model)) 1048 { 1049 priv->model = model->type; 1050 break; 1051 } 1052 model++; 1053 } 1054 1055 priv->screen_no = xf86SetIntOption(pInfo->options, "ScreenNo", 0); 1056 xf86Msg(X_CONFIG, "Elographics associated screen: %d\n", priv->screen_no); 1057 priv->untouch_delay = xf86SetIntOption(pInfo->options, "UntouchDelay", ELO_UNTOUCH_DELAY); 1058 xf86Msg(X_CONFIG, "Elographics untouch delay: %d ms\n", priv->untouch_delay*10); 1059 priv->report_delay = xf86SetIntOption(pInfo->options, "ReportDelay", ELO_REPORT_DELAY); 1060 xf86Msg(X_CONFIG, "Elographics report delay: %d ms\n", priv->report_delay*10); 1061 priv->max_x = xf86SetIntOption(pInfo->options, "MaxX", 3000); 1062 xf86Msg(X_CONFIG, "Elographics maximum x position: %d\n", priv->max_x); 1063 priv->min_x = xf86SetIntOption(pInfo->options, "MinX", 0); 1064 xf86Msg(X_CONFIG, "Elographics minimum x position: %d\n", priv->min_x); 1065 priv->max_y = xf86SetIntOption(pInfo->options, "MaxY", 3000); 1066 xf86Msg(X_CONFIG, "Elographics maximum y position: %d\n", priv->max_y); 1067 priv->min_y = xf86SetIntOption(pInfo->options, "MinY", 0); 1068 xf86Msg(X_CONFIG, "Elographics minimum y position: %d\n", priv->min_y); 1069 priv->swap_axes = xf86SetBoolOption(pInfo->options, "SwapXY", 0); 1070 if (priv->swap_axes) { 1071 xf86Msg(X_CONFIG, "Elographics device will work with X and Y axes swapped\n"); 1072 } 1073 priv->no_framing = xf86SetIntOption(pInfo->options, "NoFraming", 0); 1074 xf86Msg(X_CONFIG, "Elographics no framing: %d\n", priv->no_framing); 1075 debug_level = xf86SetIntOption(pInfo->options, "DebugLevel", 0); 1076 if (debug_level) { 1077#if DEBUG 1078 xf86Msg(X_CONFIG, "Elographics debug level sets to %d\n", debug_level); 1079#else 1080 xf86Msg(X_INFO, "Elographics debug not available\n"); 1081#endif 1082 } 1083 str = xf86SetStrOption(pInfo->options, "PortraitMode", "Landscape"); 1084 if (strcmp(str, "Portrait") == 0) { 1085 portrait = 1; 1086 } 1087 else if (strcmp(str, "PortraitCCW") == 0) { 1088 portrait = -1; 1089 } 1090 else if (strcmp(str, "Landscape") != 0) { 1091 xf86Msg(X_ERROR, "Elographics portrait mode should be: Portrait, Landscape or PortraitCCW"); 1092 str = "Landscape"; 1093 } 1094 xf86Msg(X_CONFIG, "Elographics device will work in %s mode\n", str); 1095 1096 width = priv->max_x - priv->min_x; 1097 height = priv->max_y - priv->min_y; 1098 if (width == 0) { 1099 xf86Msg(X_ERROR, "Elographics: Cannot configure touchscreen with width 0\n"); 1100 return BadValue; 1101 } 1102 else if (width < 0) { 1103 xf86Msg(X_INFO, "Elographics: reverse x mode (minimum x position >= maximum x position)\n"); 1104 } 1105 if (height == 0) { 1106 xf86Msg(X_ERROR, "Elographics: Cannot configure touchscreen with height 0\n"); 1107 return BadValue; 1108 } 1109 else if (height < 0) { 1110 xf86Msg(X_INFO, "Elographics: reverse y mode (minimum y position >= maximum y position)\n"); 1111 } 1112 1113 if (portrait == 1) { 1114 /* 1115 * Portrait Clockwise: reverse Y axis and exchange X and Y. 1116 */ 1117 int tmp; 1118 tmp = priv->min_y; 1119 priv->min_y = priv->max_y; 1120 priv->max_y = tmp; 1121 priv->swap_axes = (priv->swap_axes==0) ? 1 : 0; 1122 } 1123 else if (portrait == -1) { 1124 /* 1125 * Portrait Counter Clockwise: reverse X axis and exchange X and Y. 1126 */ 1127 int tmp; 1128 tmp = priv->min_x; 1129 priv->min_x = priv->max_x; 1130 priv->max_x = tmp; 1131 priv->swap_axes = (priv->swap_axes==0) ? 1 : 0; 1132 } 1133 1134 return Success; 1135} 1136 1137_X_EXPORT InputDriverRec ELOGRAPHICS = { 1138 1, /* driver version */ 1139 "elographics", /* driver name */ 1140 NULL, /* identify */ 1141 xf86EloInit, /* pre-init */ 1142 xf86EloUninit, /* un-init */ 1143 NULL, /* module */ 1144 default_options 1145}; 1146 1147static pointer 1148Plug(pointer module, 1149 pointer options, 1150 int *errmaj, 1151 int *errmin) 1152{ 1153 xf86AddInputDriver(&ELOGRAPHICS, module, 0); 1154 1155 return module; 1156} 1157 1158static void 1159Unplug(pointer p) 1160{ 1161 DBG(1, ErrorF("EloUnplug\n")); 1162} 1163 1164static XF86ModuleVersionInfo version_rec = { 1165 "elographics", 1166 MODULEVENDORSTRING, 1167 MODINFOSTRING1, 1168 MODINFOSTRING2, 1169 XORG_VERSION_CURRENT, 1170 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, 1171 ABI_CLASS_XINPUT, 1172 ABI_XINPUT_VERSION, 1173 MOD_CLASS_XINPUT, 1174 { 0, 0, 0, 0 } 1175}; 1176 1177/* 1178 * This is the entry point in the module. The name 1179 * is setup after the pattern <module_name>ModuleData. 1180 * Do not change it. 1181 */ 1182_X_EXPORT XF86ModuleData elographicsModuleData = { &version_rec, Plug, Unplug }; 1183 1184