We always have config.h.
[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 #endif
67
68 /*****************************************************************************
69  *      Local Headers
70  ****************************************************************************/
71 #include "acecad.h"
72
73 /*****************************************************************************
74  *      Variables without includable headers
75  ****************************************************************************/
76
77 /*****************************************************************************
78  *      Local Variables
79  ****************************************************************************/
80
81 #undef read
82 #define read(a,b,c) xf86ReadSerial((a),(b),(c))
83
84 /* max number of input events to read in one read call */
85 #define MAX_EVENTS 50
86
87 _X_EXPORT InputDriverRec ACECAD = 
88 {
89         1,
90         "acecad",
91         NULL,
92         AceCadPreInit,
93         NULL,
94         NULL,
95         0
96 };
97
98 #ifdef XFree86LOADER
99 static XF86ModuleVersionInfo VersionRec =
100 {
101         "acecad",
102         MODULEVENDORSTRING,
103         MODINFOSTRING1,
104         MODINFOSTRING2,
105         XORG_VERSION_CURRENT,
106         PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
107         ABI_CLASS_XINPUT,
108         ABI_XINPUT_VERSION,
109         MOD_CLASS_XINPUT,
110         {0, 0, 0, 0}
111 };
112
113
114 _X_EXPORT XF86ModuleData acecadModuleData = {
115         &VersionRec,
116         SetupProc,
117         TearDownProc
118 };
119
120 /*****************************************************************************
121  *      Function Definitions
122  ****************************************************************************/
123
124 static pointer
125 SetupProc(      pointer module,
126                 pointer options,
127                 int *errmaj,
128                 int *errmin )
129 {
130         xf86AddInputDriver(&ACECAD, module, 0);
131         return module;
132 }
133
134 static void
135 TearDownProc( pointer p )
136 {
137 #if 0
138         LocalDevicePtr local = (LocalDevicePtr) p;
139         AceCadPrivatePtr priv = (AceCadPrivatePtr) local->private;
140
141         DeviceOff (local->dev);
142
143         xf86CloseSerial (local->fd);
144         XisbFree (priv->buffer);
145         xfree (priv);
146         xfree (local->name);
147         xfree (local);
148 #endif
149 }
150 #endif
151
152 static const char *default_options[] =
153 {
154         "BaudRate", "9600",
155         "StopBits", "1",
156         "DataBits", "8",
157         "Parity", "Odd",
158         "Vmin", "1",
159         "Vtime", "10",
160         "FlowControl", "Xoff",
161         NULL
162 };
163
164 #ifdef LINUX_INPUT
165 static int
166 IsUSBLine(int fd)
167 {
168     int version;
169     int err;
170
171     SYSCALL(err = ioctl(fd, EVIOCGVERSION, &version));
172     
173     if (!err) {
174         xf86Msg(X_PROBED, "Kernel Input driver version is %d.%d.%d\n",
175                version >> 16, (version >> 8) & 0xff, version & 0xff);
176         return 1;
177     } else {
178         xf86Msg(X_PROBED, "No Kernel Input driver found\n");
179         return 0;
180     }
181 }
182 #endif
183
184 static InputInfoPtr
185 AceCadPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
186 {
187         LocalDevicePtr local = xf86AllocateInput(drv, 0);
188         AceCadPrivatePtr priv = xcalloc (1, sizeof (AceCadPrivateRec));
189         int speed;
190         int msgtype;
191         char *s;
192
193         if ((!local) || (!priv))
194                 goto SetupProc_fail;
195
196         memset(priv,0,sizeof (AceCadPrivateRec));
197
198         local->name = dev->identifier;
199         local->type_name = "AceCad Tablet";
200         local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
201         local->motion_history_proc = xf86GetMotionEvents;
202         local->control_proc = NULL;
203         local->close_proc = CloseProc;
204         local->switch_mode = NULL;
205         local->conversion_proc = ConvertProc;
206         local->reverse_conversion_proc = ReverseConvertProc;
207         local->dev = NULL;
208         local->private = priv;
209         local->private_flags = 0;
210         local->conf_idev = dev;
211         local->device_control = DeviceControl;
212         /*local->always_core_feedback = 0;*/
213         
214         xf86CollectInputOptions(local, default_options, NULL);
215
216         xf86OptionListReport(local->options);
217
218         priv->acecadInc = xf86SetIntOption(local->options, "Increment", 0 );
219
220         local->fd = xf86OpenSerial (local->options);
221         if (local->fd == -1)
222         {
223                 xf86Msg(X_ERROR, "AceCad driver unable to open device\n");
224                 goto SetupProc_fail;
225         }
226         xf86ErrorFVerb( 6, "tty port opened successfully\n" );
227
228 #ifdef LINUX_INPUT
229         if(IsUSBLine(local->fd)){
230                 priv->acecadUSB=1;
231
232                 local->read_input = USBReadInput;
233
234                 if (USBQueryHardware(local) != Success)
235                 {
236                         ErrorF ("Unable to query/initialize AceCad hardware.\n");
237                         goto SetupProc_fail;
238                 }
239         } else
240 #endif
241         {
242                 priv->acecadUSB=0;
243
244                 local->read_input = ReadInput;
245                 
246                 msgtype = X_DEFAULT;
247                 if (xf86FindOptionValue(local->options, "ReportSpeed")) {
248                         msgtype = X_CONFIG;
249                         speed = xf86SetIntOption(local->options, "ReportSpeed", 85 );
250                 } else {
251                         speed = 85;
252                 }
253
254                 switch (speed)
255                 {
256                 case 120:
257                         priv->acecadReportSpeed = 'Q';
258                         break;
259                 case 85:
260                         priv->acecadReportSpeed = 'R';
261                         break;
262                 case 10:
263                         priv->acecadReportSpeed = 'S';
264                         break;
265                 case 2:
266                         priv->acecadReportSpeed = 'T';
267                         break;
268                 default:
269                         priv->acecadReportSpeed = 'R';
270                         speed = 85;
271                         xf86Msg(X_ERROR, "Acecad Tablet: ReportSpeed value %d invalid. Possible values: 120, 85, 10, 2. Defaulting to 85\n", speed);
272                         msgtype = X_DEFAULT;
273                 }
274
275                 xf86Msg(msgtype, "Acecad Tablet report %d points/s\n", speed);
276
277                 priv->buffer = XisbNew (local->fd, 200);
278
279                 /* 
280                  * Verify that hardware is attached and fuctional
281                  */
282                 if (QueryHardware(priv) != Success)
283                 {
284                         xf86Msg(X_ERROR, "Unable to query/initialize AceCad hardware.\n");
285                         goto SetupProc_fail;
286                 }
287         }
288
289         s = xf86FindOptionValue(local->options, "Mode");
290         msgtype = s ? X_CONFIG : X_DEFAULT;
291         if (s && (xf86NameCmp(s, "Relative") == 0))
292         {
293                 priv->flags = priv->flags & ~ABSOLUTE_FLAG;
294         }
295         else 
296         {
297                 priv->flags = priv->flags | ABSOLUTE_FLAG;
298         }
299
300         xf86Msg(msgtype, "Acecad Tablet is in %s mode\n", (priv->flags & ABSOLUTE_FLAG) ? "absolute" : "relative");
301         DBG (9, XisbTrace (priv->buffer, 1));
302
303         local->history_size = xf86SetIntOption(local->options , "HistorySize", 0);
304
305         xf86ProcessCommonOptions(local, local->options);
306
307         local->flags |= XI86_CONFIGURED;
308         
309         if (local->fd != -1)
310         { 
311                 RemoveEnabledDevice (local->fd);
312                 if (priv->buffer)
313                 {
314                         XisbFree(priv->buffer);
315                         priv->buffer = NULL;
316                 }
317                 xf86CloseSerial(local->fd);
318         }
319         RemoveEnabledDevice (local->fd);
320         local->fd = -1;
321         return (local);
322
323         /* 
324          * If something went wrong, cleanup and return NULL
325          */
326   SetupProc_fail:
327         if ((local) && (local->fd))
328                 xf86CloseSerial (local->fd);
329         if ((priv) && (priv->buffer))
330                 XisbFree (priv->buffer);
331         if (priv)
332                 xfree (priv);
333         return (NULL);
334 }
335
336 static Bool
337 DeviceControl (DeviceIntPtr dev, int mode)
338 {
339         Bool    RetValue;
340
341         switch (mode)
342         {
343         case DEVICE_INIT:
344                 DeviceInit (dev);
345                 RetValue = Success;
346                 break;
347         case DEVICE_ON:
348                 RetValue = DeviceOn( dev );
349                 break;
350         case DEVICE_OFF:
351                 RetValue = DeviceOff( dev );
352                 break;
353         case DEVICE_CLOSE:
354                 RetValue = DeviceClose( dev );
355                 break;
356         default:
357                 RetValue = BadValue;
358         }
359
360         return( RetValue );
361 }
362
363 static Bool
364 DeviceOn (DeviceIntPtr dev)
365 {
366         char buffer[256];
367         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
368         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
369
370         xf86Msg(X_INFO, "Acecad Tablet Device On\n");
371
372         local->fd = xf86OpenSerial(local->options);
373         if (local->fd == -1)
374         {
375                 xf86Msg(X_WARNING, "%s: cannot open input device\n", local->name);
376                 return (!Success);
377         }
378
379         
380         if (priv->acecadUSB==0){
381                 priv->buffer = XisbNew(local->fd, 200);
382                 if (!priv->buffer) 
383                         {
384                                 xf86CloseSerial(local->fd);
385                                 local->fd = -1;
386                                 return (!Success);
387                         }
388
389                 /*Rets qu'a l'envoyer a la tablette */
390                 sprintf(buffer, "%s%c%c%c%c", acecad_initstr, priv->acecadReportSpeed, ACECAD_INCREMENT, 32 + priv->acecadInc, (priv->flags & ABSOLUTE_FLAG)? ACECAD_ABSOLUTE: ACECAD_RELATIVE);
391                 XisbWrite (priv->buffer, (unsigned char *)buffer, strlen(buffer));
392         }
393         
394         xf86FlushInput(local->fd);
395         xf86AddEnabledDevice (local);
396         dev->public.on = TRUE;
397         return (Success);
398 }
399
400 static Bool
401 DeviceOff (DeviceIntPtr dev)
402 {
403         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
404         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
405
406
407         if (local->fd != -1)
408         { 
409         RemoveEnabledDevice (local->fd);
410                 if (priv->buffer)
411                 {
412                         XisbFree(priv->buffer);
413                         priv->buffer = NULL;
414                 }
415                 xf86CloseSerial(local->fd);
416         }
417
418
419         xf86RemoveEnabledDevice (local);
420         dev->public.on = FALSE;
421         return (Success);
422 }
423
424 static Bool
425 DeviceClose (DeviceIntPtr dev)
426 {
427         xf86Msg(X_INFO, "Acecad Tablet Device Close\n");
428         return (Success);
429 }
430
431 static void 
432 ControlProc(DeviceIntPtr        device,
433                    PtrCtrl      *ctrl)
434 {
435         xf86Msg(X_INFO, "Acecad Tablet Control Proc\n");
436 }
437
438 static Bool
439 DeviceInit (DeviceIntPtr dev)
440 {
441         int rx, ry;
442         LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
443         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
444         unsigned char map[] =
445         {0, 1, 2, 3};
446
447         xf86Msg(X_INFO, "Acecad Tablet Device Init\n");
448
449         /* 3 boutons */
450         if (InitButtonClassDeviceStruct (dev, 3, map) == FALSE)
451         {
452                 ErrorF ("Unable to allocate AceCad ButtonClassDeviceStruct\n");
453                 return !Success;
454         }
455
456         if (InitFocusClassDeviceStruct (dev) == FALSE)
457         {
458                 ErrorF("Unable to allocate AceCad FocusClassDeviceStruct\n");
459                 return !Success;
460         }
461
462         if (InitPtrFeedbackClassDeviceStruct(dev,
463                                              ControlProc) == FALSE) {
464                 ErrorF("unable to init ptr feedback\n");
465                 return !Success;
466         }
467
468
469         /* 3 axes */
470         if (InitValuatorClassDeviceStruct (dev, 3, xf86GetMotionEvents,
471                         local->history_size,
472                         ((priv->flags & ABSOLUTE_FLAG)? Absolute: Relative)|OutOfProximity)
473                          == FALSE)
474         {
475                 ErrorF ("Unable to allocate AceCad ValuatorClassDeviceStruct\n");
476                 return !Success;
477         }
478         else
479         {
480
481                 InitValuatorAxisStruct(dev,
482                            0,
483                            0,                   /* min val */
484                            priv->acecadMaxX,    /* max val */
485                            1000,                /* resolution */
486                            0,                   /* min_res */
487                            1000);               /* max_res */
488                 InitValuatorAxisStruct(dev,
489                            1,
490                            0,                   /* min val */
491                            priv->acecadMaxY,    /* max val */
492                            1000,                /* resolution */
493                            0,                   /* min_res */
494                            1000);               /* max_res */
495                 InitValuatorAxisStruct(dev,
496                            2,
497                            0,                   /* min val */
498                            priv->acecadMaxZ,    /* max val */
499                            1000,                /* resolution */
500                            0,                   /* min_res */
501                            1000);               /* max_res */
502
503         }
504
505         if (InitProximityClassDeviceStruct (dev) == FALSE)
506         {
507                 ErrorF ("Unable to allocate ProximityClassDeviceStruct\n");
508                 return !Success;
509         }
510
511         xf86MotionHistoryAllocate (local);
512
513
514         /* On ne peut pas calculer l'increment avant, faute d'ecran pour
515         connaitre la taille... */
516
517         if (priv->acecadInc > 95)
518                 priv->acecadInc = 95;
519         if (priv->acecadInc < 1)
520         {
521                 /* guess the best increment value given video mode */
522                 rx=priv->acecadMaxX / screenInfo.screens[0]->width;
523                 ry=priv->acecadMaxY / screenInfo.screens[0]->height;
524                 if (rx < ry)
525                         priv->acecadInc = rx;
526                 else
527                         priv->acecadInc = ry;
528                 if (priv->acecadInc < 1)
529                         priv->acecadInc = 1;
530         }
531
532         xf86Msg(X_INFO, "Acecad Tablet Increment: %d\n", priv->acecadInc);
533
534         return (Success);
535 }
536
537 static void
538 ReadInput (LocalDevicePtr local)
539 {
540         int x, y, z;
541         int prox, buttons;
542         int is_core_pointer, is_absolute;
543         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
544
545         /*xf86Msg(X_INFO, "Acecad Tablet Read Input\n");*/
546
547         is_absolute = (priv->flags & ABSOLUTE_FLAG);
548         is_core_pointer = xf86IsCorePointer(local->dev);
549
550         /* 
551          * set blocking to -1 on the first call because we know there is data to
552          * read. Xisb automatically clears it after one successful read so that
553          * succeeding reads are preceeded buy a select with a 0 timeout to prevent
554          * read from blocking indefinately.
555          */
556         XisbBlockDuration (priv->buffer, -1);
557         
558         while (AceCadGetPacket (priv) == Success)
559         {
560                 x = (int)priv->packet[1] | ((int)priv->packet[2] << 7);
561                 y = (int)priv->packet[3] | ((int)priv->packet[4] << 7);
562
563             if (!(priv->flags & ABSOLUTE_FLAG))
564                 {
565                         x = priv->packet[0] & XSIGN_BIT? x:-x;
566                         y = priv->packet[0] & YSIGN_BIT? y:-y;
567                 }
568                 else
569                 {
570                 y = priv->acecadMaxY - y ;
571                 }
572                 
573
574                 z = ((int)priv->packet[5] << 2) |
575                         (((int)priv->packet[6] & 0x01) << 1) |
576                         (((int)priv->packet[6] & 0x10) >> 4);
577
578                 buttons = ((int)priv->packet[0] & 0x07) |
579                         ((int)priv->packet[6] & 0x02 << 2);
580
581                 prox = (priv->packet[0] & PROXIMITY_BIT)? 0: 1;
582
583                 if (prox)
584                 {
585                         if (!(priv->acecadOldProximity))
586                                 if (!is_core_pointer)
587                                 {
588                                         /*xf86Msg(X_INFO, "Acecad Tablet ProxIN %d %d %d\n",x, y, z);*/
589                                         xf86PostProximityEvent(local->dev, 1, 0, 3 , x, y, z);
590                                 }
591
592                         if ((is_absolute && ((priv->acecadOldX != x) || (priv->acecadOldY != y) || (priv->acecadOldZ != z)))
593                                 || (!is_absolute && (x || y)))
594                         {
595                                 if (is_absolute || priv->acecadOldProximity)
596                                 {
597                                         /*xf86Msg(X_INFO, "Acecad Tablet Motion %d %d %d\n", x, y, z);*/
598                                         xf86PostMotionEvent(local->dev, is_absolute, 0, 3, x, y, z);
599                                 }
600                         }
601
602                         if (priv->acecadOldButtons != buttons)
603                         {
604                                 int     delta;
605
606                                 delta = buttons ^ priv->acecadOldButtons;
607                                 while(delta)
608                                 {
609                                         int id;
610
611                                         id=ffs(delta);
612                                         delta &= ~(1 << (id-1));
613
614                                         /*xf86Msg(X_INFO, "Acecad Tablet Button %d 0x%x\n",id,(buttons&(1<<(id-1))));*/
615                                         xf86PostButtonEvent(local->dev, is_absolute, id, (buttons&(1<<(id-1))), 0, 3, x, y,z);
616                                 }
617                         }
618
619                         priv->acecadOldButtons = buttons;
620                         priv->acecadOldX = x;
621                         priv->acecadOldY = y;
622                         priv->acecadOldZ = z;
623                         priv->acecadOldProximity = prox;
624                 }
625                 else
626                 {
627                         if (!is_core_pointer)
628                                 if (priv->acecadOldProximity)
629                                 {
630                                         /*xf86Msg(X_INFO, "Acecad Tablet ProxOUT %d %d %d\n",x, y, z);*/
631                                         xf86PostProximityEvent(local->dev, 0, 0, 3, x,y,z);
632                                 }
633                         priv->acecadOldProximity = 0;
634                 }
635         }
636         /*xf86Msg(X_INFO, "Acecad Tablet Sortie Read Input\n");*/
637 }
638
639 #ifdef LINUX_INPUT
640 #define set_bit(byte,nb,bit)    (bit ? byte | (1<<nb) : byte & (~(1<<nb)))
641 static void
642 USBReadInput (LocalDevicePtr local)
643 {
644         int len;
645         struct input_event * event;
646         char eventbuf[sizeof(struct input_event) * MAX_EVENTS];
647         AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private);
648         int x = priv->acecadOldX;
649         int y = priv->acecadOldY;
650         int z = priv->acecadOldZ;
651         int prox = priv->acecadOldProximity;
652         int buttons = priv->acecadOldButtons;
653         int is_core_pointer;
654
655         is_core_pointer = xf86IsCorePointer(local->dev);
656
657         SYSCALL(len = read(local->fd, eventbuf, sizeof(eventbuf)));
658
659         if (len <= 0) {
660                 ErrorF("Error reading wacom device : %s\n", strerror(errno));
661                 return;
662         }
663
664         for (event=(struct input_event *)eventbuf;
665          event<(struct input_event *)(eventbuf+len); event++) {
666          
667                 switch (event->type) {
668                 case EV_SYN: /* 2.6.x */
669                         if (event->code != SYN_REPORT)
670                                 xf86Msg(X_ERROR, "UNKNOWN EV_SYN code %d\n", event->code);
671                         break;
672                 case EV_ABS:
673                     switch (event->code) {
674                     case ABS_X:
675                         x = event->value;
676                         break;
677
678                     case ABS_Y:
679                         y = event->value;
680                         break;
681
682                     case ABS_PRESSURE:
683                         z = event->value;
684                         break;
685
686                     case ABS_MISC:
687                         break;
688
689                     }
690                     break; /* EV_ABS */
691
692                 case EV_KEY:
693                     switch (event->code) {
694                     case BTN_TOOL_PEN:
695                         prox = event->value;
696                         break;
697
698                     case BTN_TOUCH:
699                         buttons=set_bit(buttons,0,event->value);
700                         break;
701
702                     case BTN_STYLUS:
703                         buttons=set_bit(buttons,1,event->value);
704                         break;
705
706                     case BTN_STYLUS2:
707                         buttons=set_bit(buttons,2,event->value);
708                         break;
709                     }
710                     break; /* EV_KEY */
711                 default:
712                     xf86Msg(X_ERROR, "UNKNOWN event type/code %d/%d\n", event->type, event->code);
713                 } /* switch event->type */
714
715                 /* Linux Kernel 2.6.x sends EV_SYN/SYN_REPORT as an event terminator,
716                  * whereas 2.4.x sends EV_ABS/ABS_MISC. We have to support both.
717                  */
718                 if (!(  (event->type == EV_SYN && event->code == SYN_REPORT) ||
719                         (event->type == EV_ABS && event->code == ABS_MISC)
720                 )) {
721                         continue;
722                 }
723
724                 if (prox)
725                 {
726                         if (!(priv->acecadOldProximity))
727                                 if (!is_core_pointer)
728                                 {
729                                         xf86PostProximityEvent(local->dev, 1, 0, 3 , x, y, z);
730                                 }
731
732
733                         xf86PostMotionEvent(local->dev, 1, 0, 3, x, y, z);
734
735                         if (priv->acecadOldButtons != buttons)
736                         {
737                                 int     delta;
738
739                                 delta = buttons ^ priv->acecadOldButtons;
740                                 while(delta)
741                                 {
742                                         int id;
743
744                                         id=ffs(delta);
745                                         delta &= ~(1 << (id-1));
746
747                                         xf86PostButtonEvent(local->dev, 1, id, (buttons&(1<<(id-1))), 0, 3, x, y,z);
748                                 }
749                         }
750                 }
751                 else
752                 {
753                         if (!is_core_pointer)
754                                 if (priv->acecadOldProximity)
755                                 {
756                                         xf86PostProximityEvent(local->dev, 0, 0, 3, x,y,z);
757                                 }
758                         priv->acecadOldProximity = 0;
759                 }
760
761                 priv->acecadOldButtons = buttons;
762                 priv->acecadOldX = x;
763                 priv->acecadOldY = y;
764                 priv->acecadOldZ = z;
765                 priv->acecadOldProximity = prox;
766         }
767         /*xf86Msg(X_INFO, "Acecad Tablet Sortie Read Input\n");*/
768 }
769 #endif
770
771 static void
772 CloseProc (LocalDevicePtr local)
773 {
774 }
775
776 /* 
777  * The ConvertProc function may need to be tailored for your device.
778  * This function converts the device's valuator outputs to x and y coordinates
779  * to simulate mouse events.
780  */
781 static Bool
782 ConvertProc (LocalDevicePtr local,
783                          int first,
784                          int num,
785                          int v0,
786                          int v1,
787                          int v2,
788                          int v3,
789                          int v4,
790                          int v5,
791                          int *x,
792                          int *y)
793 {
794     AceCadPrivatePtr    priv = (AceCadPrivatePtr)(local->private);
795
796     *x = v0 * screenInfo.screens[0]->width / priv->acecadMaxX;
797     *y = v1 * screenInfo.screens[0]->height / priv->acecadMaxY;
798     return TRUE;
799 }
800
801
802 static Bool
803 ReverseConvertProc(             LocalDevicePtr  local,
804                         int               x,
805                         int               y,
806                         int               *valuators)
807 {
808     AceCadPrivatePtr    priv = (AceCadPrivatePtr)(local->private);
809
810     valuators[0] = x * priv->acecadMaxX / screenInfo.screens[0]->width;
811     valuators[1] = y * priv->acecadMaxY / screenInfo.screens[0]->height;
812
813     return TRUE;
814 }
815
816
817 #define WriteString(str)\
818 XisbWrite (priv->buffer, (unsigned char *)(str), strlen(str))
819
820
821 static Bool
822 QueryHardware (AceCadPrivatePtr priv)
823 {       
824         
825         /* Reset */
826         WriteString("z0");
827         
828         /* Wait */
829         milisleep (250);
830         
831         /* Prompt Mode in order to not be disturbed */
832         WriteString(ACECAD_PROMPT_MODE);
833         
834         /* Flush */
835         while(XisbRead(priv->buffer)>=0);
836         
837         /* Ask for Config packet*/
838         WriteString(ACECAD_CONFIG);
839         
840         /* Read the packet */
841         XisbBlockDuration (priv->buffer, 1000000);
842         NewPacket (priv);
843
844         /*xf86Msg(X_CONFIG, "Acecad Tablet init envoyé \n");*/
845
846         if ((AceCadGetPacket (priv) == Success))
847         {
848                 priv->acecadMaxX = (int)priv->packet[1] + ((int)priv->packet[2] << 7);
849                 priv->acecadMaxY = (int)priv->packet[3] + ((int)priv->packet[4] << 7);
850                 priv->acecadMaxZ = 512;
851                 xf86Msg(X_INFO, "Acecad Tablet MaxX:%d MaxY:%d\n",priv->acecadMaxX,priv->acecadMaxY);
852         }
853         else
854                 return (!Success);
855                 
856         /*xf86Msg(X_INFO, "Acecad Tablet query hardware fini \n");*/
857         return (Success);
858 }
859
860 #define BITS_PER_LONG (sizeof(long) * 8)
861 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
862 #define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
863 #define OFF(x)  ((x)%BITS_PER_LONG)
864 #define LONG(x) ((x)/BITS_PER_LONG)
865
866 #ifdef LINUX_INPUT
867 static Bool
868 USBQueryHardware (LocalDevicePtr local)
869 {       
870         AceCadPrivatePtr priv = (AceCadPrivatePtr) local->private;
871         unsigned long   bit[EV_MAX][NBITS(KEY_MAX)];
872         int                     i, j;
873         int                     abs[5];
874         char            name[256] = "Unknown";
875
876         ioctl(local->fd, EVIOCGNAME(sizeof(name)), name);
877         xf86Msg(X_PROBED, "Kernel Input device name: \"%s\"\n", name);
878
879         memset(bit, 0, sizeof(bit));
880         ioctl(local->fd, EVIOCGBIT(0, EV_MAX), bit[0]);
881
882     for (i = 0; i < EV_MAX; i++)
883         if (test_bit(i, bit[0])) {
884             ioctl(local->fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
885             for (j = 0; j < KEY_MAX; j++) 
886                 if (test_bit(j, bit[i])) {
887                     if (i == EV_ABS) {
888                         ioctl(local->fd, EVIOCGABS(j), abs);
889                         switch (j) {
890                         case ABS_X:
891                                 priv->acecadMaxX = abs[2];
892                         break;
893                             
894                         case ABS_Y:
895                                 priv->acecadMaxY = abs[2];
896                         break;
897                             
898                         case ABS_PRESSURE:
899                                 priv->acecadMaxZ = abs[2];
900                         break;
901                         }
902                     }
903                 }
904         }
905     
906         xf86Msg(X_PROBED, "Acecad Tablet MaxX:%d MaxY:%d MaxZ:%d\n", priv->acecadMaxX, priv->acecadMaxY,priv->acecadMaxZ);
907         return (Success);
908 }
909 #endif
910
911 static void
912 NewPacket (AceCadPrivatePtr priv)
913 {
914     priv->packeti = 0;
915 }
916
917 static Bool
918 AceCadGetPacket (AceCadPrivatePtr priv)
919 {
920         int count = 0;
921         int c = 0;
922
923         while((c = XisbRead(priv->buffer))>=0 )
924         {
925         
926                 /* 
927                  * fail after 500 bytes so the server doesn't hang forever if a
928                  * device sends bad data.
929                  */
930                 if (count++ > 500)
931                 {
932                         NewPacket (priv);
933                         return (!Success);
934                 }
935
936                 if (c & PHASING_BIT)
937                 {
938                         NewPacket(priv);                        
939                         
940                         /*xf86Msg(X_CONFIG, "Push %2.2x\n",(char) c);*/
941                         XisbBlockDuration (priv->buffer, 10000);
942                         priv->packet[priv->packeti++] = c;
943                         count=ACECAD_PACKET_SIZE-1;
944                         while(count-- && (c = XisbRead(priv->buffer))>=0)
945                                 {
946                                 /*xf86Msg(X_INFO, "Push %2.2x\n",(char) c);*/
947                                 priv->packet[priv->packeti++] = c;
948                                 }
949                         XisbBlockDuration (priv->buffer, 0);
950                         if(c > 0)
951                                 return (Success);
952                 }
953         }
954         return (!Success);
955 }