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