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