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