Re-probe on device not found on input if auto-dev is active.
[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)
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         xf86Msg(X_INFO, "%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                 xf86Msg(X_WARNING, "%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         }
282     } else
283         xf86MsgVerb(X_WARNING, 4, "%s: libsysfs not found\n", local->name);
284
285 #endif
286
287     if (!ace_name)
288         ace_name = ace_name_default;
289
290     xf86Msg(X_INFO, "%s: probing event devices for Acecad tablets\n", local->name);
291     for (i = 0; ; i++) {
292         int fd = -1;
293         Bool is_acecad;
294
295         np = SET_EVENT_NUM(fname, i);
296         if (np < 0 || np >= EV_DEV_NAME_MAXLEN) {
297                 xf86Msg(X_WARNING, "%s: too many devices, giving up %d", local->name, i);
298                 break;
299         }
300         SYSCALL(fd = open(fname, O_RDONLY));
301         if (fd < 0) {
302             if (errno == ENOENT) {
303                 if (++noent_cnt >= max_skip)
304                     break;
305                 else
306                     continue;
307             } else {
308                 continue;
309             }
310         }
311         noent_cnt = 0;
312         have_evdev = TRUE;
313         is_acecad = fd_query_acecad(fd, ace_name);
314         SYSCALL(close(fd));
315         if (is_acecad) {
316             xf86Msg(X_PROBED, "%s auto-dev sets device to %s\n",
317                     local->name, fname);
318             xf86ReplaceStrOption(local->options, "Device", fname);
319             return TRUE;
320         }
321     }
322     xf86Msg(X_ERROR, "%s: no Acecad event device found (checked %d nodes, no device name started with '%s')\n",
323            local->name, i + 1, ace_name);
324     if (i <= max_skip)
325         xf86Msg(X_ERROR, "%s: The /dev/input/event* device nodes seem to be missing\n",
326                local->name);
327     if (i > max_skip && !have_evdev)
328         xf86Msg(X_ERROR, "%s: The evdev kernel module seems to be missing\n", local->name);
329     return FALSE;
330 }
331
332 #endif
333
334 static InputInfoPtr
335 AceCadPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
336 {
337         LocalDevicePtr local = xf86AllocateInput(drv, 0);
338         AceCadPrivatePtr priv = xcalloc (1, sizeof (AceCadPrivateRec));
339         int speed;
340         int msgtype;
341         char *s;
342
343         if ((!local) || (!priv))
344                 goto SetupProc_fail;
345
346         memset(priv,0,sizeof (AceCadPrivateRec));
347
348         local->name = dev->identifier;
349         local->type_name = "ACECAD Tablet";
350         local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
351         local->motion_history_proc = xf86GetMotionEvents;
352         local->control_proc = NULL;
353         local->close_proc = CloseProc;
354         local->switch_mode = NULL;
355         local->conversion_proc = ConvertProc;
356         local->reverse_conversion_proc = ReverseConvertProc;
357         local->dev = NULL;
358         local->private = priv;
359         local->private_flags = 0;
360         local->conf_idev = dev;
361         local->device_control = DeviceControl;
362         /*local->always_core_feedback = 0;*/
363         
364         xf86CollectInputOptions(local, default_options, NULL);
365
366         xf86OptionListReport(local->options);
367
368         priv->acecadInc = xf86SetIntOption(local->options, "Increment", 0 );
369         priv->acecadAutoDev = FALSE;
370
371         s = xf86FindOptionValue(local->options, "Device");
372         if (!s || (s && (xf86NameCmp(s, "auto-dev") == 0))) {
373 #ifdef LINUX_INPUT
374                 priv->acecadAutoDev = TRUE;
375                 if (!AceCadAutoDevProbe(local))
376                 {
377                         xf86Msg(X_ERROR, "%s: unable to find device\n", local->name);
378                         goto SetupProc_fail;
379                 }
380 #else
381                 xf86Msg(X_NOT_IMPLEMENTED, "%s: device autodetection not implemented, sorry\n", local->name);
382                 goto SetupProc_fail;
383 #endif
384         }
385
386         local->fd = xf86OpenSerial (local->options);
387         if (local->fd == -1)
388         {
389                 xf86Msg(X_ERROR, "%s: unable to open device\n", local->name);
390                 goto SetupProc_fail;
391         }
392         xf86ErrorFVerb( 6, "tty port opened successfully\n" );
393
394 #ifdef LINUX_INPUT
395         if(IsUSBLine(local->fd)){
396                 priv->acecadUSB=1;
397
398                 local->read_input = USBReadInput;
399
400                 if (USBQueryHardware(local) != Success)
401                 {
402                         xf86Msg(X_ERROR, "%s: unable to query/initialize hardware (not an %s?).\n", local->name, local->type_name);
403                         goto SetupProc_fail;
404                 }
405         } else
406 #endif
407         {
408                 priv->acecadUSB=0;
409
410                 local->read_input = ReadInput;
411                 
412                 msgtype = X_DEFAULT;
413                 if (xf86FindOptionValue(local->options, "ReportSpeed")) {
414                         msgtype = X_CONFIG;
415                         speed = xf86SetIntOption(local->options, "ReportSpeed", 85 );
416                 } else {
417                         speed = 85;
418                 }
419
420                 switch (speed)
421                 {
422                 case 120:
423                         priv->acecadReportSpeed = 'Q';
424                         break;
425                 case 85:
426                         priv->acecadReportSpeed = 'R';
427                         break;
428                 case 10:
429                         priv->acecadReportSpeed = 'S';
430                         break;
431                 case 2:
432                         priv->acecadReportSpeed = 'T';
433                         break;
434                 default:
435                         priv->acecadReportSpeed = 'R';
436                         speed = 85;
437                         xf86Msg(X_ERROR, "%s: ReportSpeed value %d invalid. Possible values: 120, 85, 10, 2. Defaulting to 85\n", local->name, speed);
438                         msgtype = X_DEFAULT;
439                 }
440
441                 xf86Msg(msgtype, "%s report %d points/s\n", local->name, speed);
442
443                 priv->buffer = XisbNew (local->fd, 200);
444
445                 /* 
446                  * Verify that hardware is attached and fuctional
447                  */
448                 if (QueryHardware(priv) != Success)
449                 {
450                         xf86Msg(X_ERROR, "%s: unable to query/initialize hardware (not an %s?).\n", local->name, local->type_name);
451                         goto SetupProc_fail;
452                 }
453         }
454
455         s = xf86FindOptionValue(local->options, "Mode");
456         msgtype = s ? X_CONFIG : X_DEFAULT;
457         if (s && (xf86NameCmp(s, "Relative") == 0))
458         {
459                 priv->flags = priv->flags & ~ABSOLUTE_FLAG;
460         }
461         else 
462         {
463                 priv->flags = priv->flags | ABSOLUTE_FLAG;
464         }
465
466         xf86Msg(msgtype, "%s is in %s mode\n", local->name, (priv->flags & ABSOLUTE_FLAG) ? "absolute" : "relative");
467         DBG (9, XisbTrace (priv->buffer, 1));
468
469         local->history_size = xf86SetIntOption(local->options , "HistorySize", 0);
470
471         xf86ProcessCommonOptions(local, local->options);
472
473         local->flags |= XI86_CONFIGURED;
474         
475         if (local->fd != -1)
476         { 
477                 RemoveEnabledDevice (local->fd);
478                 if (priv->buffer)
479                 {
480                         XisbFree(priv->buffer);
481                         priv->buffer = NULL;
482                 }
483                 xf86CloseSerial(local->fd);
484         }
485         RemoveEnabledDevice (local->fd);
486         local->fd = -1;
487         return (local);
488
489         /* 
490          * If something went wrong, cleanup and return NULL
491          */
492   SetupProc_fail:
493         if ((local) && (local->fd))
494                 xf86CloseSerial (local->fd);
495         if ((priv) && (priv->buffer))
496                 XisbFree (priv->buffer);
497         if (priv)
498                 xfree (priv);
499         return (NULL);
500 }
501
502 static Bool
503 DeviceControl (DeviceIntPtr dev, int mode)
504 {
505         Bool    RetValue;
506
507         switch (mode)
508         {
509         case DEVICE_INIT:
510                 DeviceInit (dev);
511                 RetValue = Success;
512                 break;
513         case DEVICE_ON:
514                 RetValue = DeviceOn( dev );
515                 break;
516         case DEVICE_OFF:
517                 RetValue = DeviceOff( dev );
518                 break;
519         case DEVICE_CLOSE:
520                 RetValue = DeviceClose( dev );
521                 break;
522         default:
523                 RetValue = BadValue;
524         }
525
526         return( RetValue );
527 }
528
529 static Bool
530 DeviceOn (DeviceIntPtr dev)
531 {
532         char buffer[256];
533         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
534         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
535
536         xf86MsgVerb(X_INFO, 4, "%s Device On\n", local->name);
537
538         local->fd = xf86OpenSerial(local->options);
539         if (local->fd == -1)
540         {
541                 xf86Msg(X_WARNING, "%s: cannot open input device %s\n", local->name, xf86FindOptionValue(local->options, "Device"));
542 #ifdef LINUX_INPUT
543                 if (priv->acecadAutoDev && AceCadAutoDevProbe(local))
544                         local->fd = xf86OpenSerial(local->options);
545                 if (local->fd == -1)
546 #endif
547                 return (!Success);
548         }
549
550         
551         if (priv->acecadUSB==0){
552                 priv->buffer = XisbNew(local->fd, 200);
553                 if (!priv->buffer) 
554                         {
555                                 xf86CloseSerial(local->fd);
556                                 local->fd = -1;
557                                 return (!Success);
558                         }
559
560                 /*Rets qu'a l'envoyer a la tablette */
561                 sprintf(buffer, "%s%c%c%c%c", acecad_initstr, priv->acecadReportSpeed, ACECAD_INCREMENT, 32 + priv->acecadInc, (priv->flags & ABSOLUTE_FLAG)? ACECAD_ABSOLUTE: ACECAD_RELATIVE);
562                 XisbWrite (priv->buffer, (unsigned char *)buffer, strlen(buffer));
563         }
564         
565         xf86FlushInput(local->fd);
566         xf86AddEnabledDevice (local);
567         dev->public.on = TRUE;
568         return (Success);
569 }
570
571 static Bool
572 DeviceOff (DeviceIntPtr dev)
573 {
574         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
575         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
576
577         xf86MsgVerb(X_INFO, 4, "%s Device Off\n", local->name);
578
579         if (local->fd != -1)
580         { 
581         RemoveEnabledDevice (local->fd);
582                 if (priv->buffer)
583                 {
584                         XisbFree(priv->buffer);
585                         priv->buffer = NULL;
586                 }
587                 xf86CloseSerial(local->fd);
588         }
589
590
591         xf86RemoveEnabledDevice (local);
592         dev->public.on = FALSE;
593         return (Success);
594 }
595
596 static Bool
597 DeviceClose (DeviceIntPtr dev)
598 {
599         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
600
601         xf86MsgVerb(X_INFO, 4, "%s Device Close\n", local->name);
602
603         return (Success);
604 }
605
606 static void 
607 ControlProc(DeviceIntPtr dev, PtrCtrl *ctrl)
608 {
609         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
610
611         xf86MsgVerb(X_INFO, 4, "%s Control Proc\n", local->name);
612 }
613
614 static Bool
615 DeviceInit (DeviceIntPtr dev)
616 {
617         int rx, ry;
618         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
619         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
620         unsigned char map[] =
621         {0, 1, 2, 3};
622
623         xf86MsgVerb(X_INFO, 4, "%s Init\n", local->name);
624
625         /* 3 boutons */
626         if (InitButtonClassDeviceStruct (dev, 3, map) == FALSE)
627         {
628                 xf86Msg(X_ERROR, "%s: unable to allocate ButtonClassDeviceStruct\n", local->name);
629                 return !Success;
630         }
631
632         if (InitFocusClassDeviceStruct (dev) == FALSE)
633         {
634                 xf86Msg(X_ERROR, "%s: unable to allocate FocusClassDeviceStruct\n", local->name);
635                 return !Success;
636         }
637
638         if (InitPtrFeedbackClassDeviceStruct(dev, ControlProc) == FALSE) {
639                 xf86Msg(X_ERROR, "%s: unable to init ptr feedback\n", local->name);
640                 return !Success;
641         }
642
643
644         /* 3 axes */
645         if (InitValuatorClassDeviceStruct (dev, 3, xf86GetMotionEvents,
646                         local->history_size,
647                         ((priv->flags & ABSOLUTE_FLAG)? Absolute: Relative)|OutOfProximity)
648                          == FALSE)
649         {
650                 xf86Msg(X_ERROR, "%s: unable to allocate ValuatorClassDeviceStruct\n", local->name);
651                 return !Success;
652         }
653         else
654         {
655
656                 InitValuatorAxisStruct(dev,
657                            0,
658                            0,                   /* min val */
659                            priv->acecadMaxX,    /* max val */
660                            1000,                /* resolution */
661                            0,                   /* min_res */
662                            1000);               /* max_res */
663                 InitValuatorAxisStruct(dev,
664                            1,
665                            0,                   /* min val */
666                            priv->acecadMaxY,    /* max val */
667                            1000,                /* resolution */
668                            0,                   /* min_res */
669                            1000);               /* max_res */
670                 InitValuatorAxisStruct(dev,
671                            2,
672                            0,                   /* min val */
673                            priv->acecadMaxZ,    /* max val */
674                            1000,                /* resolution */
675                            0,                   /* min_res */
676                            1000);               /* max_res */
677
678         }
679
680         if (InitProximityClassDeviceStruct (dev) == FALSE)
681         {
682                 xf86Msg(X_ERROR, "%s: unable to allocate ProximityClassDeviceStruct\n", local->name);
683                 return !Success;
684         }
685
686         xf86MotionHistoryAllocate (local);
687
688
689         /* On ne peut pas calculer l'increment avant, faute d'ecran pour
690         connaitre la taille... */
691
692         if (priv->acecadInc > 95)
693                 priv->acecadInc = 95;
694         if (priv->acecadInc < 1)
695         {
696                 /* guess the best increment value given video mode */
697                 rx=priv->acecadMaxX / screenInfo.screens[0]->width;
698                 ry=priv->acecadMaxY / screenInfo.screens[0]->height;
699                 if (rx < ry)
700                         priv->acecadInc = rx;
701                 else
702                         priv->acecadInc = ry;
703                 if (priv->acecadInc < 1)
704                         priv->acecadInc = 1;
705         }
706
707         xf86Msg(X_INFO, "%s Increment: %d\n", local->name, priv->acecadInc);
708
709         return (Success);
710 }
711
712 static void
713 ReadInput (LocalDevicePtr local)
714 {
715         int x, y, z;
716         int prox, buttons;
717         int is_core_pointer, is_absolute;
718         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
719
720         /*xf86Msg(X_INFO, "ACECAD Tablet Read Input\n");*/
721
722         is_absolute = (priv->flags & ABSOLUTE_FLAG);
723         is_core_pointer = xf86IsCorePointer(local->dev);
724
725         /* 
726          * set blocking to -1 on the first call because we know there is data to
727          * read. Xisb automatically clears it after one successful read so that
728          * succeeding reads are preceeded buy a select with a 0 timeout to prevent
729          * read from blocking indefinately.
730          */
731         XisbBlockDuration (priv->buffer, -1);
732         
733         while (AceCadGetPacket (priv) == Success)
734         {
735                 x = (int)priv->packet[1] | ((int)priv->packet[2] << 7);
736                 y = (int)priv->packet[3] | ((int)priv->packet[4] << 7);
737
738             if (!(priv->flags & ABSOLUTE_FLAG))
739                 {
740                         x = priv->packet[0] & XSIGN_BIT? x:-x;
741                         y = priv->packet[0] & YSIGN_BIT? y:-y;
742                 }
743                 else
744                 {
745                 y = priv->acecadMaxY - y ;
746                 }
747                 
748
749                 z = ((int)priv->packet[5] << 2) |
750                         (((int)priv->packet[6] & 0x01) << 1) |
751                         (((int)priv->packet[6] & 0x10) >> 4);
752
753                 buttons = ((int)priv->packet[0] & 0x07) |
754                         ((int)priv->packet[6] & 0x02 << 2);
755
756                 prox = (priv->packet[0] & PROXIMITY_BIT)? 0: 1;
757
758                 if (prox)
759                 {
760                         if (!(priv->acecadOldProximity))
761                                 if (!is_core_pointer)
762                                 {
763                                         /*xf86Msg(X_INFO, "ACECAD Tablet ProxIN %d %d %d\n",x, y, z);*/
764                                         xf86PostProximityEvent(local->dev, 1, 0, 3 , x, y, z);
765                                 }
766
767                         if ((is_absolute && ((priv->acecadOldX != x) || (priv->acecadOldY != y) || (priv->acecadOldZ != z)))
768                                 || (!is_absolute && (x || y)))
769                         {
770                                 if (is_absolute || priv->acecadOldProximity)
771                                 {
772                                         /*xf86Msg(X_INFO, "ACECAD Tablet Motion %d %d %d\n", x, y, z);*/
773                                         xf86PostMotionEvent(local->dev, is_absolute, 0, 3, x, y, z);
774                                 }
775                         }
776
777                         if (priv->acecadOldButtons != buttons)
778                         {
779                                 int     delta;
780
781                                 delta = buttons ^ priv->acecadOldButtons;
782                                 while(delta)
783                                 {
784                                         int id;
785
786                                         id=ffs(delta);
787                                         delta &= ~(1 << (id-1));
788
789                                         /*xf86Msg(X_INFO, "ACECAD Tablet Button %d 0x%x\n",id,(buttons&(1<<(id-1))));*/
790                                         xf86PostButtonEvent(local->dev, is_absolute, id, (buttons&(1<<(id-1))), 0, 3, x, y,z);
791                                 }
792                         }
793
794                         priv->acecadOldButtons = buttons;
795                         priv->acecadOldX = x;
796                         priv->acecadOldY = y;
797                         priv->acecadOldZ = z;
798                         priv->acecadOldProximity = prox;
799                 }
800                 else
801                 {
802                         if (!is_core_pointer)
803                                 if (priv->acecadOldProximity)
804                                 {
805                                         /*xf86Msg(X_INFO, "ACECAD Tablet ProxOUT %d %d %d\n",x, y, z);*/
806                                         xf86PostProximityEvent(local->dev, 0, 0, 3, x,y,z);
807                                 }
808                         priv->acecadOldProximity = 0;
809                 }
810         }
811         /*xf86Msg(X_INFO, "ACECAD Tablet Sortie Read Input\n");*/
812 }
813
814 #ifdef LINUX_INPUT
815 #define set_bit(byte,nb,bit)    (bit ? byte | (1<<nb) : byte & (~(1<<nb)))
816 static void
817 USBReadInput (LocalDevicePtr local)
818 {
819         int len;
820         struct input_event * event;
821         char eventbuf[sizeof(struct input_event) * MAX_EVENTS];
822         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
823         int x = priv->acecadOldX;
824         int y = priv->acecadOldY;
825         int z = priv->acecadOldZ;
826         int prox = priv->acecadOldProximity;
827         int buttons = priv->acecadOldButtons;
828         int is_core_pointer;
829
830         is_core_pointer = xf86IsCorePointer(local->dev);
831
832         SYSCALL(len = read(local->fd, eventbuf, sizeof(eventbuf)));
833
834         if (len <= 0) {
835                 xf86Msg(X_ERROR, "%s: error reading device: %s\n", local->name, strerror(errno));
836                 if ((errno == ENODEV) && priv->acecadAutoDev && AceCadAutoDevProbe(local)) {
837                         DeviceOff(local->dev);
838                         DeviceOn(local->dev);
839                 }
840                 return;
841         }
842
843         for (event=(struct input_event *)eventbuf;
844          event<(struct input_event *)(eventbuf+len); event++) {
845          
846                 switch (event->type) {
847                 case EV_SYN: /* 2.6.x */
848                         if (event->code != SYN_REPORT)
849                                 xf86Msg(X_ERROR, "%s: unknown EV_SYN code %d\n", local->name, event->code);
850                         break;
851                 case EV_ABS:
852                     switch (event->code) {
853                     case ABS_X:
854                         x = event->value;
855                         break;
856
857                     case ABS_Y:
858                         y = event->value;
859                         break;
860
861                     case ABS_PRESSURE:
862                         z = event->value;
863                         break;
864
865                     case ABS_MISC:
866                         break;
867
868                     }
869                     break; /* EV_ABS */
870
871                 case EV_KEY:
872                     switch (event->code) {
873                     case BTN_TOOL_PEN:
874                         prox = event->value;
875                         break;
876
877                     case BTN_TOUCH:
878                         buttons=set_bit(buttons,0,event->value);
879                         break;
880
881                     case BTN_STYLUS:
882                         buttons=set_bit(buttons,1,event->value);
883                         break;
884
885                     case BTN_STYLUS2:
886                         buttons=set_bit(buttons,2,event->value);
887                         break;
888                     }
889                     break; /* EV_KEY */
890                 default:
891                     xf86Msg(X_ERROR, "%s: unknown event type/code %d/%d\n", local->name, event->type, event->code);
892                 } /* switch event->type */
893
894                 /* Linux Kernel 2.6.x sends EV_SYN/SYN_REPORT as an event terminator,
895                  * whereas 2.4.x sends EV_ABS/ABS_MISC. We have to support both.
896                  */
897                 if (!(  (event->type == EV_SYN && event->code == SYN_REPORT) ||
898                         (event->type == EV_ABS && event->code == ABS_MISC)
899                 )) {
900                         continue;
901                 }
902
903                 if (prox)
904                 {
905                         if (!(priv->acecadOldProximity))
906                                 if (!is_core_pointer)
907                                 {
908                                         xf86PostProximityEvent(local->dev, 1, 0, 3 , x, y, z);
909                                 }
910
911
912                         xf86PostMotionEvent(local->dev, 1, 0, 3, x, y, z);
913
914                         if (priv->acecadOldButtons != buttons)
915                         {
916                                 int     delta;
917
918                                 delta = buttons ^ priv->acecadOldButtons;
919                                 while(delta)
920                                 {
921                                         int id;
922
923                                         id=ffs(delta);
924                                         delta &= ~(1 << (id-1));
925
926                                         xf86PostButtonEvent(local->dev, 1, id, (buttons&(1<<(id-1))), 0, 3, x, y,z);
927                                 }
928                         }
929                 }
930                 else
931                 {
932                         if (!is_core_pointer)
933                                 if (priv->acecadOldProximity)
934                                 {
935                                         xf86PostProximityEvent(local->dev, 0, 0, 3, x,y,z);
936                                 }
937                         priv->acecadOldProximity = 0;
938                 }
939
940                 priv->acecadOldButtons = buttons;
941                 priv->acecadOldX = x;
942                 priv->acecadOldY = y;
943                 priv->acecadOldZ = z;
944                 priv->acecadOldProximity = prox;
945         }
946         /*xf86Msg(X_INFO, "ACECAD Tablet Sortie Read Input\n");*/
947 }
948 #endif
949
950 static void
951 CloseProc (LocalDevicePtr local)
952 {
953 }
954
955 /* 
956  * The ConvertProc function may need to be tailored for your device.
957  * This function converts the device's valuator outputs to x and y coordinates
958  * to simulate mouse events.
959  */
960 static Bool
961 ConvertProc (LocalDevicePtr local,
962                          int first,
963                          int num,
964                          int v0,
965                          int v1,
966                          int v2,
967                          int v3,
968                          int v4,
969                          int v5,
970                          int *x,
971                          int *y)
972 {
973     AceCadPrivatePtr    priv = (AceCadPrivatePtr)(local->private);
974
975     *x = v0 * screenInfo.screens[0]->width / priv->acecadMaxX;
976     *y = v1 * screenInfo.screens[0]->height / priv->acecadMaxY;
977     return TRUE;
978 }
979
980
981 static Bool
982 ReverseConvertProc(             LocalDevicePtr  local,
983                         int               x,
984                         int               y,
985                         int               *valuators)
986 {
987     AceCadPrivatePtr    priv = (AceCadPrivatePtr)(local->private);
988
989     valuators[0] = x * priv->acecadMaxX / screenInfo.screens[0]->width;
990     valuators[1] = y * priv->acecadMaxY / screenInfo.screens[0]->height;
991
992     return TRUE;
993 }
994
995
996 #define WriteString(str)\
997 XisbWrite (priv->buffer, (unsigned char *)(str), strlen(str))
998
999
1000 static Bool
1001 QueryHardware (AceCadPrivatePtr priv)
1002 {       
1003         
1004         /* Reset */
1005         WriteString("z0");
1006         
1007         /* Wait */
1008         milisleep (250);
1009         
1010         /* Prompt Mode in order to not be disturbed */
1011         WriteString(ACECAD_PROMPT_MODE);
1012         
1013         /* Flush */
1014         while(XisbRead(priv->buffer)>=0);
1015         
1016         /* Ask for Config packet*/
1017         WriteString(ACECAD_CONFIG);
1018         
1019         /* Read the packet */
1020         XisbBlockDuration (priv->buffer, 1000000);
1021         NewPacket (priv);
1022
1023         /*xf86Msg(X_CONFIG, "ACECAD Tablet init envoyé \n");*/
1024
1025         if ((AceCadGetPacket (priv) == Success))
1026         {
1027                 priv->acecadMaxX = (int)priv->packet[1] + ((int)priv->packet[2] << 7);
1028                 priv->acecadMaxY = (int)priv->packet[3] + ((int)priv->packet[4] << 7);
1029                 priv->acecadMaxZ = 512;
1030                 xf86Msg(X_PROBED, "ACECAD Tablet MaxX:%d MaxY:%d\n", priv->acecadMaxX, priv->acecadMaxY);
1031         }
1032         else
1033                 return (!Success);
1034                 
1035         /*xf86Msg(X_INFO, "ACECAD Tablet query hardware fini \n");*/
1036         return (Success);
1037 }
1038
1039 #define BITS_PER_LONG (sizeof(long) * 8)
1040 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
1041 #define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
1042 #define OFF(x)  ((x)%BITS_PER_LONG)
1043 #define LONG(x) ((x)/BITS_PER_LONG)
1044
1045 #ifdef LINUX_INPUT
1046 static Bool
1047 USBQueryHardware (LocalDevicePtr local)
1048 {       
1049         AceCadPrivatePtr priv = (AceCadPrivatePtr) local->private;
1050         unsigned long   bit[EV_MAX][NBITS(KEY_MAX)];
1051         int                     i, j;
1052         int                     abs[5];
1053         char            name[256] = "Unknown";
1054
1055         ioctl(local->fd, EVIOCGNAME(sizeof(name)), name);
1056         xf86MsgVerb(X_PROBED, 4, "Kernel Input device name: \"%s\"\n", name);
1057
1058         memset(bit, 0, sizeof(bit));
1059         ioctl(local->fd, EVIOCGBIT(0, EV_MAX), bit[0]);
1060
1061     for (i = 0; i < EV_MAX; i++)
1062         if (test_bit(i, bit[0])) {
1063             ioctl(local->fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
1064             for (j = 0; j < KEY_MAX; j++) 
1065                 if (test_bit(j, bit[i])) {
1066                     if (i == EV_ABS) {
1067                         ioctl(local->fd, EVIOCGABS(j), abs);
1068                         switch (j) {
1069                         case ABS_X:
1070                                 priv->acecadMaxX = abs[2];
1071                         break;
1072                             
1073                         case ABS_Y:
1074                                 priv->acecadMaxY = abs[2];
1075                         break;
1076                             
1077                         case ABS_PRESSURE:
1078                                 priv->acecadMaxZ = abs[2];
1079                         break;
1080                         }
1081                     }
1082                 }
1083         }
1084     
1085         xf86Msg(X_PROBED, "ACECAD Tablet MaxX:%d MaxY:%d MaxZ:%d\n", priv->acecadMaxX, priv->acecadMaxY,priv->acecadMaxZ);
1086         return (Success);
1087 }
1088 #endif
1089
1090 static void
1091 NewPacket (AceCadPrivatePtr priv)
1092 {
1093     priv->packeti = 0;
1094 }
1095
1096 static Bool
1097 AceCadGetPacket (AceCadPrivatePtr priv)
1098 {
1099         int count = 0;
1100         int c = 0;
1101
1102         while((c = XisbRead(priv->buffer))>=0 )
1103         {
1104         
1105                 /* 
1106                  * fail after 500 bytes so the server doesn't hang forever if a
1107                  * device sends bad data.
1108                  */
1109                 if (count++ > 500)
1110                 {
1111                         NewPacket (priv);
1112                         return (!Success);
1113                 }
1114
1115                 if (c & PHASING_BIT)
1116                 {
1117                         NewPacket(priv);                        
1118                         
1119                         /*xf86Msg(X_CONFIG, "Push %2.2x\n",(char) c);*/
1120                         XisbBlockDuration (priv->buffer, 10000);
1121                         priv->packet[priv->packeti++] = c;
1122                         count=ACECAD_PACKET_SIZE-1;
1123                         while(count-- && (c = XisbRead(priv->buffer))>=0)
1124                                 {
1125                                 /*xf86Msg(X_INFO, "Push %2.2x\n",(char) c);*/
1126                                 priv->packet[priv->packeti++] = c;
1127                                 }
1128                         XisbBlockDuration (priv->buffer, 0);
1129                         if(c > 0)
1130                                 return (Success);
1131                 }
1132         }
1133         return (!Success);
1134 }