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