De-spammify AceCadAutoDevProbe().
[xorg/acecad] / src / acecad.c
1 /* 
2  * Copyright (c) 2001 Edouard TISSERANT <tissered@esstin.u-nancy.fr>
3  * Parts inspired from Shane Watts <shane@bofh.asn.au> XFree86 3 Acecad Driver
4  * Thanks to Emily, from AceCad, For giving me documents.
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  *
25  */
26 /* $XFree86: xc/programs/Xserver/hw/xfree86/input/acecad/acecad.c,v 1.4 2003/10/30 00:40:45 dawes Exp $ */
27
28 #include "config.h"
29
30 #define _ACECAD_C_
31 /*****************************************************************************
32  *      Standard Headers
33  ****************************************************************************/
34
35 #ifdef LINUX_INPUT
36 #include <asm/types.h>
37 #include <linux/input.h>
38 #ifndef EV_SYN
39 #define EV_SYN EV_RST
40 #define SYN_REPORT 0
41 #endif
42 #ifdef BUS_PCI
43 #undef BUS_PCI
44 #endif
45 #ifdef BUS_ISA
46 #undef BUS_ISA
47 #endif
48 #endif
49
50 #include <misc.h>
51 #include <xf86.h>
52 #ifndef NEED_XF86_TYPES
53 #define NEED_XF86_TYPES
54 #endif
55 #include <xf86_OSproc.h>
56 #include <xisb.h>
57 #include <xf86Xinput.h>
58 #include <exevents.h>
59 #include <xf86Module.h>
60
61 #include <string.h>
62 #include <stdio.h>
63
64 #ifdef LINUX_INPUT
65 #include <errno.h>
66 #include <fcntl.h>
67 #ifdef LINUX_SYSFS
68 #include <sysfs/libsysfs.h>
69 #include <dlfcn.h>
70 #endif
71 #endif
72
73 /*****************************************************************************
74  *      Local Headers
75  ****************************************************************************/
76 #include "acecad.h"
77
78 /*****************************************************************************
79  *      Variables without includable headers
80  ****************************************************************************/
81
82 /*****************************************************************************
83  *      Local Variables
84  ****************************************************************************/
85
86 #undef read
87 #define read(a,b,c) xf86ReadSerial((a),(b),(c))
88
89 /* max number of input events to read in one read call */
90 #define MAX_EVENTS 50
91
92 _X_EXPORT InputDriverRec ACECAD = 
93 {
94         1,
95         "acecad",
96         NULL,
97         AceCadPreInit,
98         NULL,
99         NULL,
100         0
101 };
102
103 #ifdef XFree86LOADER
104 static XF86ModuleVersionInfo VersionRec =
105 {
106         "acecad",
107         MODULEVENDORSTRING,
108         MODINFOSTRING1,
109         MODINFOSTRING2,
110         XORG_VERSION_CURRENT,
111         PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
112         ABI_CLASS_XINPUT,
113         ABI_XINPUT_VERSION,
114         MOD_CLASS_XINPUT,
115         {0, 0, 0, 0}
116 };
117
118
119 _X_EXPORT XF86ModuleData acecadModuleData = {
120         &VersionRec,
121         SetupProc,
122         TearDownProc
123 };
124
125 /*****************************************************************************
126  *      Function Definitions
127  ****************************************************************************/
128
129 static pointer
130 SetupProc(      pointer module,
131                 pointer options,
132                 int *errmaj,
133                 int *errmin )
134 {
135         xf86AddInputDriver(&ACECAD, module, 0);
136         return module;
137 }
138
139 static void
140 TearDownProc( pointer p )
141 {
142 #if 0
143         LocalDevicePtr local = (LocalDevicePtr) p;
144         AceCadPrivatePtr priv = (AceCadPrivatePtr) local->private;
145
146         DeviceOff (local->dev);
147
148         xf86CloseSerial (local->fd);
149         XisbFree (priv->buffer);
150         xfree (priv);
151         xfree (local->name);
152         xfree (local);
153 #endif
154 }
155 #endif
156
157 static const char *default_options[] =
158 {
159         "BaudRate", "9600",
160         "StopBits", "1",
161         "DataBits", "8",
162         "Parity", "Odd",
163         "Vmin", "1",
164         "Vtime", "10",
165         "FlowControl", "Xoff",
166         NULL
167 };
168
169 #ifdef LINUX_INPUT
170 static int
171 IsUSBLine(int fd)
172 {
173     int version;
174     int err;
175
176     SYSCALL(err = ioctl(fd, EVIOCGVERSION, &version));
177     
178     if (!err) {
179         xf86MsgVerb(X_PROBED, 4, "Kernel Input driver version is %d.%d.%d\n",
180                version >> 16, (version >> 8) & 0xff, version & 0xff);
181         return 1;
182     } else {
183         xf86MsgVerb(X_PROBED, 4, "No Kernel Input driver found\n");
184         return 0;
185     }
186 }
187
188 /* Heavily inspired by synpatics/eventcomm.c */
189
190 #define DEV_INPUT_EVENT "/dev/input/event"
191 #define EV_DEV_NAME_MAXLEN 64
192 #define SET_EVENT_NUM(str, num) \
193     snprintf(str, EV_DEV_NAME_MAXLEN, "%s%d", DEV_INPUT_EVENT, num)
194
195 static Bool
196 fd_query_acecad(int fd, char *ace_name) {
197         char name[256] = "Unknown";
198         int cmp_at = strlen(ace_name);
199         if (cmp_at > 256)
200                 cmp_at = 256;
201         ioctl(fd, EVIOCGNAME(sizeof(name)), name);
202         name[cmp_at] = '\0';
203         if (xf86NameCmp(name, ace_name) == 0)
204                 return TRUE;
205         return FALSE;
206 }
207
208 static char ace_name_default[7] = "acecad";
209
210 #ifdef LINUX_SYSFS
211 static char usb_bus_name[4] = "usb";
212 static char acecad_driver_name[11] = "usb_acecad";
213 #endif
214
215 static Bool
216 AceCadAutoDevProbe(LocalDevicePtr local, int verb)
217 {
218     /* We are trying to find the right eventX device */
219     int i = 0;
220     Bool have_evdev = FALSE;
221     int noent_cnt = 0;
222     const int max_skip = 10;
223     char *ace_name = xf86FindOptionValue(local->options, "Name");
224     char fname[EV_DEV_NAME_MAXLEN];
225     int np;
226
227 #ifdef LINUX_SYSFS
228     struct sysfs_bus *usb_bus = NULL;
229     struct sysfs_driver *acecad_driver = NULL;
230     struct sysfs_device *candidate = NULL;
231     char *link = NULL;
232     struct dlist *devs = NULL;
233     struct dlist *links = NULL;
234     unsigned int major = 0, minor = 0;
235     void *libsysfs = NULL;
236
237     if (libsysfs = dlopen("libsysfs.so", RTLD_NOW | RTLD_GLOBAL)) {
238         xf86MsgVerb(X_INFO, verb, "%s: querying sysfs for Acecad tablets\n", local->name);
239         usb_bus = sysfs_open_bus(usb_bus_name);
240         if (usb_bus) {
241             xf86MsgVerb(X_PROBED, 4, "%s: usb bus opened\n", local->name);
242             acecad_driver = sysfs_get_bus_driver(usb_bus, acecad_driver_name);
243             if (acecad_driver) {
244                 xf86MsgVerb(X_PROBED, 4, "%s: usb_acecad driver opened\n", local->name);
245                 devs = sysfs_get_driver_devices(acecad_driver);
246                 if (devs) {
247                     xf86MsgVerb(X_PROBED, 4, "%s: usb_acecad devices retrieved\n", local->name);
248                     dlist_for_each_data(devs, candidate, struct sysfs_device) {
249                         xf86MsgVerb(X_PROBED, 4, "%s: device %s at %s\n", local->name, candidate->name, candidate->path);
250                         links = sysfs_open_link_list(candidate->path);
251                         dlist_for_each_data(links, link, char) {
252                             if (sscanf(link, "input:event%d", &i) == 1) {
253                                 xf86MsgVerb(X_PROBED, 4, "%s: device %s at %s: %s\n", local->name, candidate->name, candidate->path, link);
254                                 break;
255                             }
256                         }
257                         sysfs_close_list(links);
258                         if (i > 0) /* We found something */
259                             break;
260                     }
261                 } else
262                     xf86MsgVerb(X_WARNING, 4, "%s: no usb_acecad devices found\n", local->name);
263             } else
264                 xf86MsgVerb(X_WARNING, 4, "%s: usb_acecad driver not found\n", local->name);
265         } else
266             xf86MsgVerb(X_WARNING, 4, "%s: usb bus not found\n", local->name);
267         sysfs_close_bus(usb_bus);
268         dlclose(libsysfs);
269
270         if (i > 0) {
271             /* We found something */
272             np = SET_EVENT_NUM(fname, i);
273             if (np < 0 || np >= EV_DEV_NAME_MAXLEN) {
274                 xf86MsgVerb(X_WARNING, verb, "%s: unable to manage event device %d", local->name, i);
275             } else {
276                 xf86Msg(X_PROBED, "%s auto-dev sets device to %s\n",
277                         local->name, fname);
278                 xf86ReplaceStrOption(local->options, "Device", fname);
279                 return TRUE;
280             }
281         } else
282             xf86MsgVerb(X_WARNING, verb, "%s: no Acecad devices found via sysfs", local->name);
283     } else
284         xf86MsgVerb(X_WARNING, 4, "%s: libsysfs not found\n", local->name);
285
286 #endif
287
288     if (!ace_name)
289         ace_name = ace_name_default;
290
291     xf86MsgVerb(X_INFO, verb, "%s: probing event devices for Acecad tablets\n", local->name);
292     for (i = 0; ; i++) {
293         int fd = -1;
294         Bool is_acecad;
295
296         np = SET_EVENT_NUM(fname, i);
297         if (np < 0 || np >= EV_DEV_NAME_MAXLEN) {
298                 xf86MsgVerb(X_WARNING, verb, "%s: too many devices, giving up %d", local->name, i);
299                 break;
300         }
301         SYSCALL(fd = open(fname, O_RDONLY));
302         if (fd < 0) {
303             if (errno == ENOENT) {
304                 if (++noent_cnt >= max_skip)
305                     break;
306                 else
307                     continue;
308             } else {
309                 continue;
310             }
311         }
312         noent_cnt = 0;
313         have_evdev = TRUE;
314         is_acecad = fd_query_acecad(fd, ace_name);
315         SYSCALL(close(fd));
316         if (is_acecad) {
317             xf86Msg(X_PROBED, "%s auto-dev sets device to %s\n",
318                     local->name, fname);
319             xf86ReplaceStrOption(local->options, "Device", fname);
320             return TRUE;
321         }
322     }
323     xf86MsgVerb(X_WARNING, verb, "%s: no Acecad event device found (checked %d nodes, no device name started with '%s')\n",
324            local->name, i + 1, ace_name);
325     if (i <= max_skip)
326         xf86MsgVerb(X_WARNING, verb, "%s: The /dev/input/event* device nodes seem to be missing\n",
327                local->name);
328     if (i > max_skip && !have_evdev)
329         xf86MsgVerb(X_WARNING, verb, "%s: The evdev kernel module seems to be missing\n", local->name);
330     return FALSE;
331 }
332
333 #endif
334
335 static InputInfoPtr
336 AceCadPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
337 {
338         LocalDevicePtr local = xf86AllocateInput(drv, 0);
339         AceCadPrivatePtr priv = xcalloc (1, sizeof (AceCadPrivateRec));
340         int speed;
341         int msgtype;
342         char *s;
343
344         if ((!local) || (!priv))
345                 goto SetupProc_fail;
346
347         memset(priv,0,sizeof (AceCadPrivateRec));
348
349         local->name = dev->identifier;
350         local->type_name = "ACECAD Tablet";
351         local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
352         local->motion_history_proc = xf86GetMotionEvents;
353         local->control_proc = NULL;
354         local->close_proc = CloseProc;
355         local->switch_mode = NULL;
356         local->conversion_proc = ConvertProc;
357         local->reverse_conversion_proc = ReverseConvertProc;
358         local->dev = NULL;
359         local->private = priv;
360         local->private_flags = 0;
361         local->conf_idev = dev;
362         local->device_control = DeviceControl;
363         /*local->always_core_feedback = 0;*/
364         
365         xf86CollectInputOptions(local, default_options, NULL);
366
367         xf86OptionListReport(local->options);
368
369         priv->acecadInc = xf86SetIntOption(local->options, "Increment", 0 );
370         priv->acecadAutoDev = FALSE;
371
372         s = xf86FindOptionValue(local->options, "Device");
373         if (!s || (s && (xf86NameCmp(s, "auto-dev") == 0))) {
374 #ifdef LINUX_INPUT
375                 priv->acecadAutoDev = TRUE;
376                 if (!AceCadAutoDevProbe(local, 0))
377                 {
378                         xf86Msg(X_ERROR, "%s: unable to find device\n", local->name);
379                         goto SetupProc_fail;
380                 }
381 #else
382                 xf86Msg(X_NOT_IMPLEMENTED, "%s: device autodetection not implemented, sorry\n", local->name);
383                 goto SetupProc_fail;
384 #endif
385         }
386
387         local->fd = xf86OpenSerial (local->options);
388         if (local->fd == -1)
389         {
390                 xf86Msg(X_ERROR, "%s: unable to open device\n", local->name);
391                 goto SetupProc_fail;
392         }
393         xf86ErrorFVerb( 6, "tty port opened successfully\n" );
394
395 #ifdef LINUX_INPUT
396         if(IsUSBLine(local->fd)){
397                 priv->acecadUSB=1;
398
399                 local->read_input = USBReadInput;
400
401                 if (USBQueryHardware(local) != Success)
402                 {
403                         xf86Msg(X_ERROR, "%s: unable to query/initialize hardware (not an %s?).\n", local->name, local->type_name);
404                         goto SetupProc_fail;
405                 }
406         } else
407 #endif
408         {
409                 priv->acecadUSB=0;
410
411                 local->read_input = ReadInput;
412                 
413                 msgtype = X_DEFAULT;
414                 if (xf86FindOptionValue(local->options, "ReportSpeed")) {
415                         msgtype = X_CONFIG;
416                         speed = xf86SetIntOption(local->options, "ReportSpeed", 85 );
417                 } else {
418                         speed = 85;
419                 }
420
421                 switch (speed)
422                 {
423                 case 120:
424                         priv->acecadReportSpeed = 'Q';
425                         break;
426                 case 85:
427                         priv->acecadReportSpeed = 'R';
428                         break;
429                 case 10:
430                         priv->acecadReportSpeed = 'S';
431                         break;
432                 case 2:
433                         priv->acecadReportSpeed = 'T';
434                         break;
435                 default:
436                         priv->acecadReportSpeed = 'R';
437                         speed = 85;
438                         xf86Msg(X_ERROR, "%s: ReportSpeed value %d invalid. Possible values: 120, 85, 10, 2. Defaulting to 85\n", local->name, speed);
439                         msgtype = X_DEFAULT;
440                 }
441
442                 xf86Msg(msgtype, "%s report %d points/s\n", local->name, speed);
443
444                 priv->buffer = XisbNew (local->fd, 200);
445
446                 /* 
447                  * Verify that hardware is attached and fuctional
448                  */
449                 if (QueryHardware(priv) != Success)
450                 {
451                         xf86Msg(X_ERROR, "%s: unable to query/initialize hardware (not an %s?).\n", local->name, local->type_name);
452                         goto SetupProc_fail;
453                 }
454         }
455
456         s = xf86FindOptionValue(local->options, "Mode");
457         msgtype = s ? X_CONFIG : X_DEFAULT;
458         if (s && (xf86NameCmp(s, "Relative") == 0))
459         {
460                 priv->flags = priv->flags & ~ABSOLUTE_FLAG;
461         }
462         else 
463         {
464                 priv->flags = priv->flags | ABSOLUTE_FLAG;
465         }
466
467         xf86Msg(msgtype, "%s is in %s mode\n", local->name, (priv->flags & ABSOLUTE_FLAG) ? "absolute" : "relative");
468         DBG (9, XisbTrace (priv->buffer, 1));
469
470         local->history_size = xf86SetIntOption(local->options , "HistorySize", 0);
471
472         xf86ProcessCommonOptions(local, local->options);
473
474         local->flags |= XI86_CONFIGURED;
475         
476         if (local->fd != -1)
477         { 
478                 RemoveEnabledDevice (local->fd);
479                 if (priv->buffer)
480                 {
481                         XisbFree(priv->buffer);
482                         priv->buffer = NULL;
483                 }
484                 xf86CloseSerial(local->fd);
485         }
486         RemoveEnabledDevice (local->fd);
487         local->fd = -1;
488         return (local);
489
490         /* 
491          * If something went wrong, cleanup and return NULL
492          */
493   SetupProc_fail:
494         if ((local) && (local->fd))
495                 xf86CloseSerial (local->fd);
496         if ((priv) && (priv->buffer))
497                 XisbFree (priv->buffer);
498         if (priv)
499                 xfree (priv);
500         return (NULL);
501 }
502
503 static Bool
504 DeviceControl (DeviceIntPtr dev, int mode)
505 {
506         Bool    RetValue;
507
508         switch (mode)
509         {
510         case DEVICE_INIT:
511                 DeviceInit (dev);
512                 RetValue = Success;
513                 break;
514         case DEVICE_ON:
515                 RetValue = DeviceOn( dev );
516                 break;
517         case DEVICE_OFF:
518                 RetValue = DeviceOff( dev );
519                 break;
520         case DEVICE_CLOSE:
521                 RetValue = DeviceClose( dev );
522                 break;
523         default:
524                 RetValue = BadValue;
525         }
526
527         return( RetValue );
528 }
529
530 static Bool
531 DeviceOn (DeviceIntPtr dev)
532 {
533         char buffer[256];
534         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
535         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
536
537         xf86MsgVerb(X_INFO, 4, "%s Device On\n", local->name);
538
539         local->fd = xf86OpenSerial(local->options);
540         if (local->fd == -1)
541         {
542                 xf86Msg(X_WARNING, "%s: cannot open input device %s\n", local->name, xf86FindOptionValue(local->options, "Device"));
543 #ifdef LINUX_INPUT
544                 if (priv->acecadAutoDev && AceCadAutoDevProbe(local, 4))
545                         local->fd = xf86OpenSerial(local->options);
546                 if (local->fd == -1)
547 #endif
548                 return (!Success);
549         }
550
551         
552         if (priv->acecadUSB==0){
553                 priv->buffer = XisbNew(local->fd, 200);
554                 if (!priv->buffer) 
555                         {
556                                 xf86CloseSerial(local->fd);
557                                 local->fd = -1;
558                                 return (!Success);
559                         }
560
561                 /*Rets qu'a l'envoyer a la tablette */
562                 sprintf(buffer, "%s%c%c%c%c", acecad_initstr, priv->acecadReportSpeed, ACECAD_INCREMENT, 32 + priv->acecadInc, (priv->flags & ABSOLUTE_FLAG)? ACECAD_ABSOLUTE: ACECAD_RELATIVE);
563                 XisbWrite (priv->buffer, (unsigned char *)buffer, strlen(buffer));
564         }
565         
566         xf86FlushInput(local->fd);
567         xf86AddEnabledDevice (local);
568         dev->public.on = TRUE;
569         return (Success);
570 }
571
572 static Bool
573 DeviceOff (DeviceIntPtr dev)
574 {
575         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
576         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
577
578         xf86MsgVerb(X_INFO, 4, "%s Device Off\n", local->name);
579
580         if (local->fd != -1)
581         { 
582         RemoveEnabledDevice (local->fd);
583                 if (priv->buffer)
584                 {
585                         XisbFree(priv->buffer);
586                         priv->buffer = NULL;
587                 }
588                 xf86CloseSerial(local->fd);
589         }
590
591
592         xf86RemoveEnabledDevice (local);
593         dev->public.on = FALSE;
594         return (Success);
595 }
596
597 static Bool
598 DeviceClose (DeviceIntPtr dev)
599 {
600         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
601
602         xf86MsgVerb(X_INFO, 4, "%s Device Close\n", local->name);
603
604         return (Success);
605 }
606
607 static void 
608 ControlProc(DeviceIntPtr dev, PtrCtrl *ctrl)
609 {
610         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
611
612         xf86MsgVerb(X_INFO, 4, "%s Control Proc\n", local->name);
613 }
614
615 static Bool
616 DeviceInit (DeviceIntPtr dev)
617 {
618         int rx, ry;
619         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
620         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
621         unsigned char map[] =
622         {0, 1, 2, 3};
623
624         xf86MsgVerb(X_INFO, 4, "%s Init\n", local->name);
625
626         /* 3 boutons */
627         if (InitButtonClassDeviceStruct (dev, 3, map) == FALSE)
628         {
629                 xf86Msg(X_ERROR, "%s: unable to allocate ButtonClassDeviceStruct\n", local->name);
630                 return !Success;
631         }
632
633         if (InitFocusClassDeviceStruct (dev) == FALSE)
634         {
635                 xf86Msg(X_ERROR, "%s: unable to allocate FocusClassDeviceStruct\n", local->name);
636                 return !Success;
637         }
638
639         if (InitPtrFeedbackClassDeviceStruct(dev, ControlProc) == FALSE) {
640                 xf86Msg(X_ERROR, "%s: unable to init ptr feedback\n", local->name);
641                 return !Success;
642         }
643
644
645         /* 3 axes */
646         if (InitValuatorClassDeviceStruct (dev, 3, xf86GetMotionEvents,
647                         local->history_size,
648                         ((priv->flags & ABSOLUTE_FLAG)? Absolute: Relative)|OutOfProximity)
649                          == FALSE)
650         {
651                 xf86Msg(X_ERROR, "%s: unable to allocate ValuatorClassDeviceStruct\n", local->name);
652                 return !Success;
653         }
654         else
655         {
656
657                 InitValuatorAxisStruct(dev,
658                            0,
659                            0,                   /* min val */
660                            priv->acecadMaxX,    /* max val */
661                            1000,                /* resolution */
662                            0,                   /* min_res */
663                            1000);               /* max_res */
664                 InitValuatorAxisStruct(dev,
665                            1,
666                            0,                   /* min val */
667                            priv->acecadMaxY,    /* max val */
668                            1000,                /* resolution */
669                            0,                   /* min_res */
670                            1000);               /* max_res */
671                 InitValuatorAxisStruct(dev,
672                            2,
673                            0,                   /* min val */
674                            priv->acecadMaxZ,    /* max val */
675                            1000,                /* resolution */
676                            0,                   /* min_res */
677                            1000);               /* max_res */
678
679         }
680
681         if (InitProximityClassDeviceStruct (dev) == FALSE)
682         {
683                 xf86Msg(X_ERROR, "%s: unable to allocate ProximityClassDeviceStruct\n", local->name);
684                 return !Success;
685         }
686
687         xf86MotionHistoryAllocate (local);
688
689
690         /* On ne peut pas calculer l'increment avant, faute d'ecran pour
691         connaitre la taille... */
692
693         if (priv->acecadInc > 95)
694                 priv->acecadInc = 95;
695         if (priv->acecadInc < 1)
696         {
697                 /* guess the best increment value given video mode */
698                 rx=priv->acecadMaxX / screenInfo.screens[0]->width;
699                 ry=priv->acecadMaxY / screenInfo.screens[0]->height;
700                 if (rx < ry)
701                         priv->acecadInc = rx;
702                 else
703                         priv->acecadInc = ry;
704                 if (priv->acecadInc < 1)
705                         priv->acecadInc = 1;
706         }
707
708         xf86Msg(X_INFO, "%s Increment: %d\n", local->name, priv->acecadInc);
709
710         return (Success);
711 }
712
713 static void
714 ReadInput (LocalDevicePtr local)
715 {
716         int x, y, z;
717         int prox, buttons;
718         int is_core_pointer, is_absolute;
719         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
720
721         /*xf86Msg(X_INFO, "ACECAD Tablet Read Input\n");*/
722
723         is_absolute = (priv->flags & ABSOLUTE_FLAG);
724         is_core_pointer = xf86IsCorePointer(local->dev);
725
726         /* 
727          * set blocking to -1 on the first call because we know there is data to
728          * read. Xisb automatically clears it after one successful read so that
729          * succeeding reads are preceeded buy a select with a 0 timeout to prevent
730          * read from blocking indefinately.
731          */
732         XisbBlockDuration (priv->buffer, -1);
733         
734         while (AceCadGetPacket (priv) == Success)
735         {
736                 x = (int)priv->packet[1] | ((int)priv->packet[2] << 7);
737                 y = (int)priv->packet[3] | ((int)priv->packet[4] << 7);
738
739             if (!(priv->flags & ABSOLUTE_FLAG))
740                 {
741                         x = priv->packet[0] & XSIGN_BIT? x:-x;
742                         y = priv->packet[0] & YSIGN_BIT? y:-y;
743                 }
744                 else
745                 {
746                 y = priv->acecadMaxY - y ;
747                 }
748                 
749
750                 z = ((int)priv->packet[5] << 2) |
751                         (((int)priv->packet[6] & 0x01) << 1) |
752                         (((int)priv->packet[6] & 0x10) >> 4);
753
754                 buttons = ((int)priv->packet[0] & 0x07) |
755                         ((int)priv->packet[6] & 0x02 << 2);
756
757                 prox = (priv->packet[0] & PROXIMITY_BIT)? 0: 1;
758
759                 if (prox)
760                 {
761                         if (!(priv->acecadOldProximity))
762                                 if (!is_core_pointer)
763                                 {
764                                         /*xf86Msg(X_INFO, "ACECAD Tablet ProxIN %d %d %d\n",x, y, z);*/
765                                         xf86PostProximityEvent(local->dev, 1, 0, 3 , x, y, z);
766                                 }
767
768                         if ((is_absolute && ((priv->acecadOldX != x) || (priv->acecadOldY != y) || (priv->acecadOldZ != z)))
769                                 || (!is_absolute && (x || y)))
770                         {
771                                 if (is_absolute || priv->acecadOldProximity)
772                                 {
773                                         /*xf86Msg(X_INFO, "ACECAD Tablet Motion %d %d %d\n", x, y, z);*/
774                                         xf86PostMotionEvent(local->dev, is_absolute, 0, 3, x, y, z);
775                                 }
776                         }
777
778                         if (priv->acecadOldButtons != buttons)
779                         {
780                                 int     delta;
781
782                                 delta = buttons ^ priv->acecadOldButtons;
783                                 while(delta)
784                                 {
785                                         int id;
786
787                                         id=ffs(delta);
788                                         delta &= ~(1 << (id-1));
789
790                                         /*xf86Msg(X_INFO, "ACECAD Tablet Button %d 0x%x\n",id,(buttons&(1<<(id-1))));*/
791                                         xf86PostButtonEvent(local->dev, is_absolute, id, (buttons&(1<<(id-1))), 0, 3, x, y,z);
792                                 }
793                         }
794
795                         priv->acecadOldButtons = buttons;
796                         priv->acecadOldX = x;
797                         priv->acecadOldY = y;
798                         priv->acecadOldZ = z;
799                         priv->acecadOldProximity = prox;
800                 }
801                 else
802                 {
803                         if (!is_core_pointer)
804                                 if (priv->acecadOldProximity)
805                                 {
806                                         /*xf86Msg(X_INFO, "ACECAD Tablet ProxOUT %d %d %d\n",x, y, z);*/
807                                         xf86PostProximityEvent(local->dev, 0, 0, 3, x,y,z);
808                                 }
809                         priv->acecadOldProximity = 0;
810                 }
811         }
812         /*xf86Msg(X_INFO, "ACECAD Tablet Sortie Read Input\n");*/
813 }
814
815 #ifdef LINUX_INPUT
816 #define set_bit(byte,nb,bit)    (bit ? byte | (1<<nb) : byte & (~(1<<nb)))
817 static void
818 USBReadInput (LocalDevicePtr local)
819 {
820         int len;
821         struct input_event * event;
822         char eventbuf[sizeof(struct input_event) * MAX_EVENTS];
823         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
824         int x = priv->acecadOldX;
825         int y = priv->acecadOldY;
826         int z = priv->acecadOldZ;
827         int prox = priv->acecadOldProximity;
828         int buttons = priv->acecadOldButtons;
829         int is_core_pointer;
830
831         is_core_pointer = xf86IsCorePointer(local->dev);
832
833         SYSCALL(len = read(local->fd, eventbuf, sizeof(eventbuf)));
834
835         if (len <= 0) {
836                 xf86Msg(X_ERROR, "%s: error reading device: %s\n", local->name, strerror(errno));
837                 if ((errno == ENODEV) && priv->acecadAutoDev && AceCadAutoDevProbe(local, 4)) {
838                         DeviceOff(local->dev);
839                         DeviceOn(local->dev);
840                 }
841                 return;
842         }
843
844         for (event=(struct input_event *)eventbuf;
845          event<(struct input_event *)(eventbuf+len); event++) {
846          
847                 switch (event->type) {
848                 case EV_SYN: /* 2.6.x */
849                         if (event->code != SYN_REPORT)
850                                 xf86Msg(X_ERROR, "%s: unknown EV_SYN code %d\n", local->name, event->code);
851                         break;
852                 case EV_ABS:
853                     switch (event->code) {
854                     case ABS_X:
855                         x = event->value;
856                         break;
857
858                     case ABS_Y:
859                         y = event->value;
860                         break;
861
862                     case ABS_PRESSURE:
863                         z = event->value;
864                         break;
865
866                     case ABS_MISC:
867                         break;
868
869                     }
870                     break; /* EV_ABS */
871
872                 case EV_KEY:
873                     switch (event->code) {
874                     case BTN_TOOL_PEN:
875                         prox = event->value;
876                         break;
877
878                     case BTN_TOUCH:
879                         buttons=set_bit(buttons,0,event->value);
880                         break;
881
882                     case BTN_STYLUS:
883                         buttons=set_bit(buttons,1,event->value);
884                         break;
885
886                     case BTN_STYLUS2:
887                         buttons=set_bit(buttons,2,event->value);
888                         break;
889                     }
890                     break; /* EV_KEY */
891                 default:
892                     xf86Msg(X_ERROR, "%s: unknown event type/code %d/%d\n", local->name, event->type, event->code);
893                 } /* switch event->type */
894
895                 /* Linux Kernel 2.6.x sends EV_SYN/SYN_REPORT as an event terminator,
896                  * whereas 2.4.x sends EV_ABS/ABS_MISC. We have to support both.
897                  */
898                 if (!(  (event->type == EV_SYN && event->code == SYN_REPORT) ||
899                         (event->type == EV_ABS && event->code == ABS_MISC)
900                 )) {
901                         continue;
902                 }
903
904                 if (prox)
905                 {
906                         if (!(priv->acecadOldProximity))
907                                 if (!is_core_pointer)
908                                 {
909                                         xf86PostProximityEvent(local->dev, 1, 0, 3 , x, y, z);
910                                 }
911
912
913                         xf86PostMotionEvent(local->dev, 1, 0, 3, x, y, z);
914
915                         if (priv->acecadOldButtons != buttons)
916                         {
917                                 int     delta;
918
919                                 delta = buttons ^ priv->acecadOldButtons;
920                                 while(delta)
921                                 {
922                                         int id;
923
924                                         id=ffs(delta);
925                                         delta &= ~(1 << (id-1));
926
927                                         xf86PostButtonEvent(local->dev, 1, id, (buttons&(1<<(id-1))), 0, 3, x, y,z);
928                                 }
929                         }
930                 }
931                 else
932                 {
933                         if (!is_core_pointer)
934                                 if (priv->acecadOldProximity)
935                                 {
936                                         xf86PostProximityEvent(local->dev, 0, 0, 3, x,y,z);
937                                 }
938                         priv->acecadOldProximity = 0;
939                 }
940
941                 priv->acecadOldButtons = buttons;
942                 priv->acecadOldX = x;
943                 priv->acecadOldY = y;
944                 priv->acecadOldZ = z;
945                 priv->acecadOldProximity = prox;
946         }
947         /*xf86Msg(X_INFO, "ACECAD Tablet Sortie Read Input\n");*/
948 }
949 #endif
950
951 static void
952 CloseProc (LocalDevicePtr local)
953 {
954 }
955
956 /* 
957  * The ConvertProc function may need to be tailored for your device.
958  * This function converts the device's valuator outputs to x and y coordinates
959  * to simulate mouse events.
960  */
961 static Bool
962 ConvertProc (LocalDevicePtr local,
963                          int first,
964                          int num,
965                          int v0,
966                          int v1,
967                          int v2,
968                          int v3,
969                          int v4,
970                          int v5,
971                          int *x,
972                          int *y)
973 {
974     AceCadPrivatePtr    priv = (AceCadPrivatePtr)(local->private);
975
976     *x = v0 * screenInfo.screens[0]->width / priv->acecadMaxX;
977     *y = v1 * screenInfo.screens[0]->height / priv->acecadMaxY;
978     return TRUE;
979 }
980
981
982 static Bool
983 ReverseConvertProc(             LocalDevicePtr  local,
984                         int               x,
985                         int               y,
986                         int               *valuators)
987 {
988     AceCadPrivatePtr    priv = (AceCadPrivatePtr)(local->private);
989
990     valuators[0] = x * priv->acecadMaxX / screenInfo.screens[0]->width;
991     valuators[1] = y * priv->acecadMaxY / screenInfo.screens[0]->height;
992
993     return TRUE;
994 }
995
996
997 #define WriteString(str)\
998 XisbWrite (priv->buffer, (unsigned char *)(str), strlen(str))
999
1000
1001 static Bool
1002 QueryHardware (AceCadPrivatePtr priv)
1003 {       
1004         
1005         /* Reset */
1006         WriteString("z0");
1007         
1008         /* Wait */
1009         milisleep (250);
1010         
1011         /* Prompt Mode in order to not be disturbed */
1012         WriteString(ACECAD_PROMPT_MODE);
1013         
1014         /* Flush */
1015         while(XisbRead(priv->buffer)>=0);
1016         
1017         /* Ask for Config packet*/
1018         WriteString(ACECAD_CONFIG);
1019         
1020         /* Read the packet */
1021         XisbBlockDuration (priv->buffer, 1000000);
1022         NewPacket (priv);
1023
1024         /*xf86Msg(X_CONFIG, "ACECAD Tablet init envoyé \n");*/
1025
1026         if ((AceCadGetPacket (priv) == Success))
1027         {
1028                 priv->acecadMaxX = (int)priv->packet[1] + ((int)priv->packet[2] << 7);
1029                 priv->acecadMaxY = (int)priv->packet[3] + ((int)priv->packet[4] << 7);
1030                 priv->acecadMaxZ = 512;
1031                 xf86Msg(X_PROBED, "ACECAD Tablet MaxX:%d MaxY:%d\n", priv->acecadMaxX, priv->acecadMaxY);
1032         }
1033         else
1034                 return (!Success);
1035                 
1036         /*xf86Msg(X_INFO, "ACECAD Tablet query hardware fini \n");*/
1037         return (Success);
1038 }
1039
1040 #define BITS_PER_LONG (sizeof(long) * 8)
1041 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
1042 #define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
1043 #define OFF(x)  ((x)%BITS_PER_LONG)
1044 #define LONG(x) ((x)/BITS_PER_LONG)
1045
1046 #ifdef LINUX_INPUT
1047 static Bool
1048 USBQueryHardware (LocalDevicePtr local)
1049 {       
1050         AceCadPrivatePtr priv = (AceCadPrivatePtr) local->private;
1051         unsigned long   bit[EV_MAX][NBITS(KEY_MAX)];
1052         int                     i, j;
1053         int                     abs[5];
1054         char            name[256] = "Unknown";
1055
1056         ioctl(local->fd, EVIOCGNAME(sizeof(name)), name);
1057         xf86MsgVerb(X_PROBED, 4, "Kernel Input device name: \"%s\"\n", name);
1058
1059         memset(bit, 0, sizeof(bit));
1060         ioctl(local->fd, EVIOCGBIT(0, EV_MAX), bit[0]);
1061
1062     for (i = 0; i < EV_MAX; i++)
1063         if (test_bit(i, bit[0])) {
1064             ioctl(local->fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
1065             for (j = 0; j < KEY_MAX; j++) 
1066                 if (test_bit(j, bit[i])) {
1067                     if (i == EV_ABS) {
1068                         ioctl(local->fd, EVIOCGABS(j), abs);
1069                         switch (j) {
1070                         case ABS_X:
1071                                 priv->acecadMaxX = abs[2];
1072                         break;
1073                             
1074                         case ABS_Y:
1075                                 priv->acecadMaxY = abs[2];
1076                         break;
1077                             
1078                         case ABS_PRESSURE:
1079                                 priv->acecadMaxZ = abs[2];
1080                         break;
1081                         }
1082                     }
1083                 }
1084         }
1085     
1086         xf86Msg(X_PROBED, "ACECAD Tablet MaxX:%d MaxY:%d MaxZ:%d\n", priv->acecadMaxX, priv->acecadMaxY,priv->acecadMaxZ);
1087         return (Success);
1088 }
1089 #endif
1090
1091 static void
1092 NewPacket (AceCadPrivatePtr priv)
1093 {
1094     priv->packeti = 0;
1095 }
1096
1097 static Bool
1098 AceCadGetPacket (AceCadPrivatePtr priv)
1099 {
1100         int count = 0;
1101         int c = 0;
1102
1103         while((c = XisbRead(priv->buffer))>=0 )
1104         {
1105         
1106                 /* 
1107                  * fail after 500 bytes so the server doesn't hang forever if a
1108                  * device sends bad data.
1109                  */
1110                 if (count++ > 500)
1111                 {
1112                         NewPacket (priv);
1113                         return (!Success);
1114                 }
1115
1116                 if (c & PHASING_BIT)
1117                 {
1118                         NewPacket(priv);                        
1119                         
1120                         /*xf86Msg(X_CONFIG, "Push %2.2x\n",(char) c);*/
1121                         XisbBlockDuration (priv->buffer, 10000);
1122                         priv->packet[priv->packeti++] = c;
1123                         count=ACECAD_PACKET_SIZE-1;
1124                         while(count-- && (c = XisbRead(priv->buffer))>=0)
1125                                 {
1126                                 /*xf86Msg(X_INFO, "Push %2.2x\n",(char) c);*/
1127                                 priv->packet[priv->packeti++] = c;
1128                                 }
1129                         XisbBlockDuration (priv->buffer, 0);
1130                         if(c > 0)
1131                                 return (Success);
1132                 }
1133         }
1134         return (!Success);
1135 }