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