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