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