Re-probe for device if DeviceOn fails and 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                 return;
837         }
838
839         for (event=(struct input_event *)eventbuf;
840          event<(struct input_event *)(eventbuf+len); event++) {
841          
842                 switch (event->type) {
843                 case EV_SYN: /* 2.6.x */
844                         if (event->code != SYN_REPORT)
845                                 xf86Msg(X_ERROR, "%s: unknown EV_SYN code %d\n", local->name, event->code);
846                         break;
847                 case EV_ABS:
848                     switch (event->code) {
849                     case ABS_X:
850                         x = event->value;
851                         break;
852
853                     case ABS_Y:
854                         y = event->value;
855                         break;
856
857                     case ABS_PRESSURE:
858                         z = event->value;
859                         break;
860
861                     case ABS_MISC:
862                         break;
863
864                     }
865                     break; /* EV_ABS */
866
867                 case EV_KEY:
868                     switch (event->code) {
869                     case BTN_TOOL_PEN:
870                         prox = event->value;
871                         break;
872
873                     case BTN_TOUCH:
874                         buttons=set_bit(buttons,0,event->value);
875                         break;
876
877                     case BTN_STYLUS:
878                         buttons=set_bit(buttons,1,event->value);
879                         break;
880
881                     case BTN_STYLUS2:
882                         buttons=set_bit(buttons,2,event->value);
883                         break;
884                     }
885                     break; /* EV_KEY */
886                 default:
887                     xf86Msg(X_ERROR, "%s: unknown event type/code %d/%d\n", local->name, event->type, event->code);
888                 } /* switch event->type */
889
890                 /* Linux Kernel 2.6.x sends EV_SYN/SYN_REPORT as an event terminator,
891                  * whereas 2.4.x sends EV_ABS/ABS_MISC. We have to support both.
892                  */
893                 if (!(  (event->type == EV_SYN && event->code == SYN_REPORT) ||
894                         (event->type == EV_ABS && event->code == ABS_MISC)
895                 )) {
896                         continue;
897                 }
898
899                 if (prox)
900                 {
901                         if (!(priv->acecadOldProximity))
902                                 if (!is_core_pointer)
903                                 {
904                                         xf86PostProximityEvent(local->dev, 1, 0, 3 , x, y, z);
905                                 }
906
907
908                         xf86PostMotionEvent(local->dev, 1, 0, 3, x, y, z);
909
910                         if (priv->acecadOldButtons != buttons)
911                         {
912                                 int     delta;
913
914                                 delta = buttons ^ priv->acecadOldButtons;
915                                 while(delta)
916                                 {
917                                         int id;
918
919                                         id=ffs(delta);
920                                         delta &= ~(1 << (id-1));
921
922                                         xf86PostButtonEvent(local->dev, 1, id, (buttons&(1<<(id-1))), 0, 3, x, y,z);
923                                 }
924                         }
925                 }
926                 else
927                 {
928                         if (!is_core_pointer)
929                                 if (priv->acecadOldProximity)
930                                 {
931                                         xf86PostProximityEvent(local->dev, 0, 0, 3, x,y,z);
932                                 }
933                         priv->acecadOldProximity = 0;
934                 }
935
936                 priv->acecadOldButtons = buttons;
937                 priv->acecadOldX = x;
938                 priv->acecadOldY = y;
939                 priv->acecadOldZ = z;
940                 priv->acecadOldProximity = prox;
941         }
942         /*xf86Msg(X_INFO, "ACECAD Tablet Sortie Read Input\n");*/
943 }
944 #endif
945
946 static void
947 CloseProc (LocalDevicePtr local)
948 {
949 }
950
951 /* 
952  * The ConvertProc function may need to be tailored for your device.
953  * This function converts the device's valuator outputs to x and y coordinates
954  * to simulate mouse events.
955  */
956 static Bool
957 ConvertProc (LocalDevicePtr local,
958                          int first,
959                          int num,
960                          int v0,
961                          int v1,
962                          int v2,
963                          int v3,
964                          int v4,
965                          int v5,
966                          int *x,
967                          int *y)
968 {
969     AceCadPrivatePtr    priv = (AceCadPrivatePtr)(local->private);
970
971     *x = v0 * screenInfo.screens[0]->width / priv->acecadMaxX;
972     *y = v1 * screenInfo.screens[0]->height / priv->acecadMaxY;
973     return TRUE;
974 }
975
976
977 static Bool
978 ReverseConvertProc(             LocalDevicePtr  local,
979                         int               x,
980                         int               y,
981                         int               *valuators)
982 {
983     AceCadPrivatePtr    priv = (AceCadPrivatePtr)(local->private);
984
985     valuators[0] = x * priv->acecadMaxX / screenInfo.screens[0]->width;
986     valuators[1] = y * priv->acecadMaxY / screenInfo.screens[0]->height;
987
988     return TRUE;
989 }
990
991
992 #define WriteString(str)\
993 XisbWrite (priv->buffer, (unsigned char *)(str), strlen(str))
994
995
996 static Bool
997 QueryHardware (AceCadPrivatePtr priv)
998 {       
999         
1000         /* Reset */
1001         WriteString("z0");
1002         
1003         /* Wait */
1004         milisleep (250);
1005         
1006         /* Prompt Mode in order to not be disturbed */
1007         WriteString(ACECAD_PROMPT_MODE);
1008         
1009         /* Flush */
1010         while(XisbRead(priv->buffer)>=0);
1011         
1012         /* Ask for Config packet*/
1013         WriteString(ACECAD_CONFIG);
1014         
1015         /* Read the packet */
1016         XisbBlockDuration (priv->buffer, 1000000);
1017         NewPacket (priv);
1018
1019         /*xf86Msg(X_CONFIG, "ACECAD Tablet init envoyé \n");*/
1020
1021         if ((AceCadGetPacket (priv) == Success))
1022         {
1023                 priv->acecadMaxX = (int)priv->packet[1] + ((int)priv->packet[2] << 7);
1024                 priv->acecadMaxY = (int)priv->packet[3] + ((int)priv->packet[4] << 7);
1025                 priv->acecadMaxZ = 512;
1026                 xf86Msg(X_PROBED, "ACECAD Tablet MaxX:%d MaxY:%d\n", priv->acecadMaxX, priv->acecadMaxY);
1027         }
1028         else
1029                 return (!Success);
1030                 
1031         /*xf86Msg(X_INFO, "ACECAD Tablet query hardware fini \n");*/
1032         return (Success);
1033 }
1034
1035 #define BITS_PER_LONG (sizeof(long) * 8)
1036 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
1037 #define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
1038 #define OFF(x)  ((x)%BITS_PER_LONG)
1039 #define LONG(x) ((x)/BITS_PER_LONG)
1040
1041 #ifdef LINUX_INPUT
1042 static Bool
1043 USBQueryHardware (LocalDevicePtr local)
1044 {       
1045         AceCadPrivatePtr priv = (AceCadPrivatePtr) local->private;
1046         unsigned long   bit[EV_MAX][NBITS(KEY_MAX)];
1047         int                     i, j;
1048         int                     abs[5];
1049         char            name[256] = "Unknown";
1050
1051         ioctl(local->fd, EVIOCGNAME(sizeof(name)), name);
1052         xf86MsgVerb(X_PROBED, 4, "Kernel Input device name: \"%s\"\n", name);
1053
1054         memset(bit, 0, sizeof(bit));
1055         ioctl(local->fd, EVIOCGBIT(0, EV_MAX), bit[0]);
1056
1057     for (i = 0; i < EV_MAX; i++)
1058         if (test_bit(i, bit[0])) {
1059             ioctl(local->fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
1060             for (j = 0; j < KEY_MAX; j++) 
1061                 if (test_bit(j, bit[i])) {
1062                     if (i == EV_ABS) {
1063                         ioctl(local->fd, EVIOCGABS(j), abs);
1064                         switch (j) {
1065                         case ABS_X:
1066                                 priv->acecadMaxX = abs[2];
1067                         break;
1068                             
1069                         case ABS_Y:
1070                                 priv->acecadMaxY = abs[2];
1071                         break;
1072                             
1073                         case ABS_PRESSURE:
1074                                 priv->acecadMaxZ = abs[2];
1075                         break;
1076                         }
1077                     }
1078                 }
1079         }
1080     
1081         xf86Msg(X_PROBED, "ACECAD Tablet MaxX:%d MaxY:%d MaxZ:%d\n", priv->acecadMaxX, priv->acecadMaxY,priv->acecadMaxZ);
1082         return (Success);
1083 }
1084 #endif
1085
1086 static void
1087 NewPacket (AceCadPrivatePtr priv)
1088 {
1089     priv->packeti = 0;
1090 }
1091
1092 static Bool
1093 AceCadGetPacket (AceCadPrivatePtr priv)
1094 {
1095         int count = 0;
1096         int c = 0;
1097
1098         while((c = XisbRead(priv->buffer))>=0 )
1099         {
1100         
1101                 /* 
1102                  * fail after 500 bytes so the server doesn't hang forever if a
1103                  * device sends bad data.
1104                  */
1105                 if (count++ > 500)
1106                 {
1107                         NewPacket (priv);
1108                         return (!Success);
1109                 }
1110
1111                 if (c & PHASING_BIT)
1112                 {
1113                         NewPacket(priv);                        
1114                         
1115                         /*xf86Msg(X_CONFIG, "Push %2.2x\n",(char) c);*/
1116                         XisbBlockDuration (priv->buffer, 10000);
1117                         priv->packet[priv->packeti++] = c;
1118                         count=ACECAD_PACKET_SIZE-1;
1119                         while(count-- && (c = XisbRead(priv->buffer))>=0)
1120                                 {
1121                                 /*xf86Msg(X_INFO, "Push %2.2x\n",(char) c);*/
1122                                 priv->packet[priv->packeti++] = c;
1123                                 }
1124                         XisbBlockDuration (priv->buffer, 0);
1125                         if(c > 0)
1126                                 return (Success);
1127                 }
1128         }
1129         return (!Success);
1130 }