OSDN Git Service

Initial lollipop-x86 porting
[android-x86/device-generic-common.git] / wacom / wacserial.c
1 /*****************************************************************************
2 ** wacserial.c
3 **
4 ** Copyright (C) 2002, 2003 - John E. Joganic
5 ** Copyright (C) 2002 - 2008 - Ping Cheng
6 **
7 ** This program is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU General Public License
9 ** as published by the Free Software Foundation; either version 2
10 ** of the License, or (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 **
21 ****************************************************************************/
22
23 #include "wacserial.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <termios.h>
30 #include <ctype.h>
31 #include <unistd.h>
32 #include <assert.h>
33
34 /*****************************************************************************
35 ** Serial Tablet Object
36 *****************************************************************************/
37
38 typedef struct _SERIALTABLET SERIALTABLET;
39 typedef struct _SERIALSUBTYPE SERIALSUBTYPE;
40 typedef struct _SERIALDEVICE SERIALDEVICE;
41 typedef struct _SERIALVENDOR SERIALVENDOR;
42
43 typedef int (*IDENTFUNC)(SERIALTABLET* pSerial);
44 typedef int (*INITFUNC)(SERIALTABLET* pSerial);
45 typedef int (*PARSEFUNC)(SERIALTABLET* pSerial, const unsigned char* puchData,
46                 unsigned int uLength, WACOMSTATE* pState);
47
48 struct _SERIALTABLET
49 {
50         WACOMTABLET_PRIV tablet;
51         WACOMENGINE hEngine;
52         int fd;
53         SERIALVENDOR* pVendor;
54         SERIALDEVICE* pDevice;
55         SERIALSUBTYPE* pSubType;
56         unsigned int uPacketLength;
57         int nVerMajor, nVerMinor, nVerRelease;
58         IDENTFUNC pfnIdent;
59         INITFUNC pfnInit;
60         PARSEFUNC pfnParse;
61         int nToolID;
62         WACOMSTATE state;
63         int nBitErrors;
64         WACOMMODEL modelRequested;
65 };
66
67 /*****************************************************************************
68 ** Internal structures
69 *****************************************************************************/
70
71 struct _SERIALSUBTYPE
72 {
73         const char* pszName;
74         const char* pszDesc;
75         unsigned int uSubType;
76         const char* pszIdent;
77         INITFUNC pfnInit;
78 };
79
80 struct _SERIALDEVICE
81 {
82         const char* pszName;
83         const char* pszDesc;
84         unsigned int uDevice;
85         SERIALSUBTYPE* pSubTypes;
86         int nProtocol;
87         unsigned int uPacketLength;
88         unsigned int uCaps;
89         int nMinBaudRate;
90         IDENTFUNC pfnIdent;
91 };
92
93 struct _SERIALVENDOR
94 {
95         const char* pszName;
96         const char* pszDesc;
97         unsigned int uVendor;
98         SERIALDEVICE* pDevices;
99 };
100
101 /*****************************************************************************
102 ** Static operations
103 *****************************************************************************/
104
105 static void SerialClose(WACOMTABLET_PRIV* pTablet);
106 static WACOMMODEL SerialGetModel(WACOMTABLET_PRIV* pTablet);
107 static const char* SerialGetVendorName(WACOMTABLET_PRIV* pTablet);
108 static const char* SerialGetClassName(WACOMTABLET_PRIV* pTablet);
109 static const char* SerialGetDeviceName(WACOMTABLET_PRIV* pTablet);
110 static const char* SerialGetSubTypeName(WACOMTABLET_PRIV* pTablet);
111 static const char* SerialGetModelName(WACOMTABLET_PRIV* pTablet);
112 static int SerialGetROMVer(WACOMTABLET_PRIV* pTablet, int* pnMajor,
113                 int* pnMinor, int* pnRelease);
114 static int SerialGetCaps(WACOMTABLET_PRIV* pTablet);
115 static int SerialGetState(WACOMTABLET_PRIV* pTablet, WACOMSTATE* pState);
116 static int SerialGetFD(WACOMTABLET_PRIV* pTablet);
117 static int SerialReadRaw(WACOMTABLET_PRIV* pTablet, unsigned char* puchData,
118                 unsigned int uSize);
119 static int SerialParseData(WACOMTABLET_PRIV* pTablet,
120                 const unsigned char* puchData, unsigned int uLength,
121                 WACOMSTATE* pState);
122
123 static int SerialReset(SERIALTABLET* pSerial, WACOMMODEL* pModel);
124 static int SerialConfigTTY(SERIALTABLET* pSerial);
125 static int SerialResetAtBaud(SERIALTABLET* pSerial, struct termios* pTIOS,
126                 int nBaud);
127 static int SerialSetDevice(SERIALTABLET* pSerial, SERIALVENDOR* pVendor,
128                 SERIALDEVICE* pDevice, SERIALSUBTYPE* pSubType);
129
130 static int SerialIdentDefault(SERIALTABLET* pSerial);
131 static int SerialIdentTabletPC(SERIALTABLET* pSerial);
132 static int SerialInitTabletPC(SERIALTABLET* pSerial);
133 static int SerialIdentWacom(SERIALTABLET* pSerial);
134 static int SerialInitWacom(SERIALTABLET* pSerial);
135
136 static int SerialParseWacomV(SERIALTABLET* pSerial,
137                 const unsigned char* puchData, unsigned int uLength,
138                 WACOMSTATE* pState);
139 static int SerialParseWacomIV_1_4(SERIALTABLET* pSerial,
140                 const unsigned char* puchData, unsigned int uLength,
141                 WACOMSTATE* pState);
142 static int SerialParseWacomIV_1_3(SERIALTABLET* pSerial,
143                 const unsigned char* puchData, unsigned int uLength,
144                 WACOMSTATE* pState);
145 static int SerialParseWacomIV_1_2(SERIALTABLET* pSerial,
146                 const unsigned char* puchData, unsigned int uLength,
147                 WACOMSTATE* pState);
148 static int SerialParseTabletPC(SERIALTABLET* pSerial,
149                 const unsigned char* puchData, unsigned int uLength,
150                 WACOMSTATE* pState);
151
152 static void SerialError(SERIALTABLET* pSerial, const char* pszFmt, ...);
153 static void SerialWarn(SERIALTABLET* pSerial, const char* pszFmt, ...);
154 static void SerialInfo(SERIALTABLET* pSerial, const char* pszFmt, ...);
155 static void SerialDump(SERIALTABLET* pSerial, const void* pvData, int nCnt);
156 /* NOT USED, YET
157 static void SerialCritical(SERIALTABLET* pSerial, const char* pszFmt, ...);
158 static void SerialDebug(SERIALTABLET* pSerial, const char* pszFmt, ...);
159 static void SerialTrace(SERIALTABLET* pSerial, const char* pszFmt, ...);
160 */
161
162 /*****************************************************************************
163 ** Defines
164 *****************************************************************************/
165
166 #ifndef BIT
167 #undef BIT
168 #define BIT(x) (1<<(x))
169 #endif
170
171 #define WACOMVALID(x) BIT(WACOMFIELD_##x)
172
173 #define ARTPAD_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
174                 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
175                 WACOMVALID(PRESSURE))
176
177 #define ARTPADII_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
178                 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
179                 WACOMVALID(PRESSURE))
180
181 #define DIGITIZER_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
182                 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
183                 WACOMVALID(PRESSURE)|WACOMVALID(TILT_X)|WACOMVALID(TILT_Y))
184
185 #define DIGITIZERII_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
186                 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
187                 WACOMVALID(PRESSURE)|WACOMVALID(TILT_X)|WACOMVALID(TILT_Y))
188
189 #define PENPARTNER_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
190                 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
191                 WACOMVALID(PRESSURE))
192
193 #define GRAPHIRE_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
194                 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
195                 WACOMVALID(PRESSURE)|WACOMVALID(TILT_X)|WACOMVALID(TILT_Y))
196
197 #define CINTIQ_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
198                 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
199                 WACOMVALID(PRESSURE)|WACOMVALID(TILT_X)|WACOMVALID(TILT_Y))
200
201 #define INTUOS_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(SERIAL)| \
202                 WACOMVALID(PROXIMITY)|WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)| \
203                 WACOMVALID(POSITION_Y)|WACOMVALID(ROTATION_Z)|WACOMVALID(DISTANCE)| \
204                 WACOMVALID(PRESSURE)|WACOMVALID(TILT_X)|WACOMVALID(TILT_Y)| \
205                 WACOMVALID(ABSWHEEL)|WACOMVALID(RELWHEEL)|WACOMVALID(THROTTLE))
206
207 #define TABLETPC_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(SERIAL)| \
208                 WACOMVALID(PROXIMITY)|WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)| \
209                 WACOMVALID(POSITION_Y)|WACOMVALID(PRESSURE))
210
211 #define INTUOS2_CAPS INTUOS_CAPS
212
213 #define PROTOCOL_4 4
214 #define PROTOCOL_5 5
215
216 #define WACOM_SUBTYPE(id,d,s) \
217         { id, d, s, id, SerialInitWacom }
218 #define TPC_SUBTYPE(id,d,s) \
219         { id, d, s, id, SerialInitTabletPC }
220
221 #define WACOM_DEVICE_P4(n,d,i,s,c) \
222         { n, d, i, s, PROTOCOL_4, 7, c, 9600, SerialIdentWacom }
223 #define WACOM_DEVICE_P5(n,d,i,s,c) \
224         { n, d, i, s, PROTOCOL_5, 9, c, 9600, SerialIdentWacom }
225 #define TPC_DEVICE(n,d,i,s,c) \
226         { n, d, i, s, 0, 9, c, 19200, SerialIdentTabletPC }
227
228 /*****************************************************************************
229 ** Globals
230 *****************************************************************************/
231
232         static SERIALSUBTYPE xArtPadII[] =
233         {
234                 WACOM_SUBTYPE("KT-0405-R", "Wacom ArtPadII 4x5", 1),
235                 { NULL }
236         };
237
238         static SERIALSUBTYPE xDigitizerII[] =
239         {
240                 WACOM_SUBTYPE("UD-0608-R", "Wacom DigitizerII 6x8",   1),
241                 WACOM_SUBTYPE("UD-1212-R", "Wacom DigitizerII 12x12", 2),
242                 WACOM_SUBTYPE("UD-1218-R", "Wacom DigitizerII 12x18", 3),
243                 WACOM_SUBTYPE("UD-1825-R", "Wacom DigitizerII 18x25", 4),
244                 { NULL }
245         };
246
247         static SERIALSUBTYPE xPenPartner[] =
248         {
249                 WACOM_SUBTYPE("CT-0405-R", "Wacom PenPartner", 1),
250                 { NULL }
251         };
252
253         static SERIALSUBTYPE xGraphire[] =
254         {
255                 WACOM_SUBTYPE("ET-0405-R", "Wacom Graphire", 1),
256                 { NULL }
257         };
258
259         static SERIALSUBTYPE xIntuos[] =
260         {
261                 WACOM_SUBTYPE("GD-0405-R", "Wacom Intuos 4x5",   1),
262                 WACOM_SUBTYPE("GD-0608-R", "Wacom Intuos 6x8",   2),
263                 WACOM_SUBTYPE("GD-0912-R", "Wacom Intuos 9x12",  3),
264                 WACOM_SUBTYPE("GD-1212-R", "Wacom Intuos 12x12", 4),
265                 WACOM_SUBTYPE("GD-1218-R", "Wacom Intuos 12x18", 5),
266                 { NULL }
267         };
268
269         static SERIALSUBTYPE xIntuos2[] =
270         {
271                 WACOM_SUBTYPE("XD-0405-R", "Wacom Intuos2 4x5",   1),
272                 WACOM_SUBTYPE("XD-0608-R", "Wacom Intuos2 6x8",   2),
273                 WACOM_SUBTYPE("XD-0912-R", "Wacom Intuos2 9x12",  3),
274                 WACOM_SUBTYPE("XD-1212-R", "Wacom Intuos2 12x12", 4),
275                 WACOM_SUBTYPE("XD-1218-R", "Wacom Intuos2 12x18", 5),
276                 { NULL }
277         };
278
279         static SERIALSUBTYPE xCintiq[] =
280         {
281                 WACOM_SUBTYPE("PL-250", "Wacom PL-250",     1),
282                 WACOM_SUBTYPE("PL-270", "Wacom PL-270",     2),
283                 WACOM_SUBTYPE("PL-400", "Wacom PL-400",     3),
284                 WACOM_SUBTYPE("PL-500", "Wacom PL-500",     4),
285                 WACOM_SUBTYPE("PL-550", "Wacom PL-550",     5),
286                 WACOM_SUBTYPE("PL-600", "Wacom PL-600",     6),
287                 WACOM_SUBTYPE("PL-600SX", "Wacom PL-600SX", 7),
288                 WACOM_SUBTYPE("PL-800", "Wacom PL-800",     8),
289                 { NULL }
290         };
291
292         static SERIALDEVICE xWacomDevices[] =
293         {
294                 WACOM_DEVICE_P4("art", "ArtPad", WACOMDEVICE_ARTPAD,
295                                 NULL, ARTPAD_CAPS),
296                 WACOM_DEVICE_P4("art2", "ArtPadII", WACOMDEVICE_ARTPADII,
297                                 xArtPadII, ARTPADII_CAPS),
298                 WACOM_DEVICE_P4("dig", "Digitizer", WACOMDEVICE_DIGITIZER,
299                                 NULL, DIGITIZERII_CAPS),
300                 WACOM_DEVICE_P4("dig2", "Digitizer II", WACOMDEVICE_DIGITIZERII,
301                                 xDigitizerII, DIGITIZERII_CAPS),
302                 WACOM_DEVICE_P4("pp", "PenPartner", WACOMDEVICE_PENPARTNER,
303                                 xPenPartner, PENPARTNER_CAPS),
304                 WACOM_DEVICE_P4("gr", "Graphire", WACOMDEVICE_GRAPHIRE,
305                                 xGraphire, GRAPHIRE_CAPS),
306                 WACOM_DEVICE_P4("pl", "Cintiq (PL)", WACOMDEVICE_CINTIQ,
307                                 xCintiq, CINTIQ_CAPS),
308                 WACOM_DEVICE_P5("int", "Intuos", WACOMDEVICE_INTUOS,
309                                 xIntuos, INTUOS_CAPS),
310                 WACOM_DEVICE_P5("int2", "Intuos2", WACOMDEVICE_INTUOS2,
311                                 xIntuos2, INTUOS2_CAPS),
312                 { NULL }
313         };
314
315         /* This one is reverse engineered at this point */
316         static SERIALSUBTYPE xTabletPC[] =
317         {
318                 TPC_SUBTYPE("tpc", "Tablet PC Screen", 1),
319                 { NULL }
320         };
321
322         static SERIALDEVICE xtpcDevices[] =
323         {
324                 TPC_DEVICE("tpc", "TabletPC", WACOMDEVICE_TPC,
325                                 xTabletPC, TABLETPC_CAPS),
326                 { NULL }
327         };
328
329         static SERIALVENDOR xWacomVendor =
330         { "wacom", "Wacom", WACOMVENDOR_WACOM, xWacomDevices };
331
332         static SERIALVENDOR xtpcVendor =
333         { "Wacom", "Wacom", WACOMVENDOR_TPC, xtpcDevices };
334
335         static SERIALVENDOR* xVendors[] =
336         {
337                 &xWacomVendor,
338                 &xtpcVendor,
339                 NULL
340         };
341
342 /*****************************************************************************
343 ** Static Prototypes
344 *****************************************************************************/
345
346 static int SerialSendReset(SERIALTABLET* pSerial);
347 static int SerialSendStop(SERIALTABLET* pSerial);
348 static int SerialSendStart(SERIALTABLET* pSerial);
349
350 static int SerialSend(SERIALTABLET* pSerial, const char* pszData);
351 static int SerialSendRaw(SERIALTABLET* pSerial, const void* pvData,
352                 unsigned int uSize);
353 static int WacomFlush(SERIALTABLET* pSerial);
354 static int SerialSendRequest(SERIALTABLET* pSerial, const char* pszRequest,
355                 char* pchResponse, unsigned int uSize);
356
357 /*****************************************************************************
358 ** Public Functions
359 *****************************************************************************/
360
361 typedef struct
362 {
363         void (*pfnFree)(void* pv);
364 } DEVLIST_INTERNAL;
365
366 static void SerialFreeDeviceList(void* pv)
367 {
368         DEVLIST_INTERNAL* pInt = ((DEVLIST_INTERNAL*)pv) - 1;
369         free(pInt);
370 }
371
372 int WacomGetSupportedSerialDeviceList(WACOMDEVICEREC** ppList, int* pnSize)
373 {
374         int nIndex=0, nCnt=0;
375         DEVLIST_INTERNAL* pInt;
376         SERIALDEVICE* pDev;
377         SERIALVENDOR** ppVendor;
378         WACOMDEVICEREC* pRec;
379
380         if (!ppList || !pnSize) { errno = EINVAL; return 1; }
381
382         /* for each vendor, count up devices */
383         for (ppVendor=xVendors; *ppVendor; ++ppVendor)
384         {
385                 /* count up devices */
386                 for (pDev=(*ppVendor)->pDevices; pDev->pszName; ++pDev, ++nCnt) ;
387         }
388
389         /* allocate enough memory to hold internal structure and all records */
390         pInt = (DEVLIST_INTERNAL*)malloc(sizeof(DEVLIST_INTERNAL) +
391                                         (sizeof(WACOMDEVICEREC) * nCnt));
392
393         pInt->pfnFree = SerialFreeDeviceList;
394         pRec = (WACOMDEVICEREC*)(pInt + 1);
395
396         /* for each vendor, add devices */
397         for (ppVendor=xVendors; *ppVendor; ++ppVendor)
398         {
399                 for (pDev=(*ppVendor)->pDevices; pDev->pszName; ++pDev, ++nIndex)
400                 {
401                         pRec[nIndex].pszName = pDev->pszName;
402                         pRec[nIndex].pszDesc = pDev->pszDesc;
403                         pRec[nIndex].pszVendorName = (*ppVendor)->pszName;
404                         pRec[nIndex].pszVendorDesc = (*ppVendor)->pszDesc;
405                         pRec[nIndex].pszClass = "serial";
406                         pRec[nIndex].model.uClass = WACOMCLASS_SERIAL;
407                         pRec[nIndex].model.uVendor = (*ppVendor)->uVendor;
408                         pRec[nIndex].model.uDevice = pDev->uDevice;
409                         pRec[nIndex].model.uSubType = 0;
410                 }
411         }
412         assert(nIndex == nCnt);
413
414         *ppList = pRec;
415         *pnSize = nCnt;
416         return 0;
417 }
418
419 unsigned int WacomGetSerialDeviceFromName(const char* pszName)
420 {
421         SERIALDEVICE* pDev;
422         SERIALVENDOR** ppVendor;
423
424         if (!pszName) { errno = EINVAL; return 0; }
425
426         /* for each vendor, look for device */
427         for (ppVendor=xVendors; *ppVendor; ++ppVendor)
428         {
429                 /* count up devices */
430                 for (pDev=(*ppVendor)->pDevices; pDev->pszName; ++pDev)
431                 {
432                         if (strcasecmp(pszName,pDev->pszName) == 0)
433                                 return pDev->uDevice;
434                 }
435         }
436
437         errno = ENOENT;
438         return 0;
439 }
440
441 static int SerialFindModel(WACOMMODEL* pModel, SERIALVENDOR** ppVendor,
442                 SERIALDEVICE** ppDevice, SERIALSUBTYPE** ppSubType)
443 {
444         SERIALVENDOR** ppPos;
445         SERIALDEVICE* pDev;
446         SERIALSUBTYPE* pSub;
447
448         /* device type must be specified */
449         if (!pModel)
450                 { errno = EINVAL; return 1; }
451
452         /* no device specified, nothing found. */
453         if (!pModel->uDevice)
454         {
455                 *ppVendor = NULL;
456                 *ppDevice = NULL;
457                 *ppSubType = NULL;
458                 return 0;
459         }
460
461         /* for each vendor */
462         for (ppPos=xVendors; *ppPos; ++ppPos)
463         {
464                 /* check vendor */
465                 if (!pModel->uVendor || (pModel->uVendor == (*ppPos)->uVendor))
466                 {
467                         /* for each device */
468                         for (pDev=(*ppPos)->pDevices; pDev->pszName; ++pDev)
469                         {
470                                 /* if device matches */
471                                 if (pModel->uDevice == pDev->uDevice)
472                                 {
473                                         /* no subtype specified, use it */
474                                         if (!pModel->uSubType)
475                                         {
476                                                 *ppVendor = *ppPos;
477                                                 *ppDevice = pDev;
478                                                 *ppSubType = NULL;
479                                                 return 0;
480                                         }
481
482                                         /* for each subtype */
483                                         for (pSub=pDev->pSubTypes; pSub->pszName; ++pSub)
484                                         {
485                                                 /* if subtype matches */
486                                                 if (pModel->uSubType == pSub->uSubType)
487                                                 {
488                                                         *ppVendor = *ppPos;
489                                                         *ppDevice = pDev;
490                                                         *ppSubType = pSub;
491                                                         return 0;
492                                                 }
493                                         }
494
495                                         /* wrong subtype? maybe try another vendor */
496                                         if (!pModel->uVendor) break;
497
498                                         /* otherwise, no match. */
499                                         errno = ENOENT;
500                                         return 1;
501                                 }
502                         } /* next device */
503
504                         /* if vendor matches, but device does not, no match. */
505                         if (pModel->uVendor)
506                         {
507                                 errno = ENOENT;
508                                 return 1;
509                         }
510                 }
511         } /* next vendor */
512
513         /* no match */
514         errno = ENOENT;
515         return 1;
516 }
517
518 WACOMTABLET WacomOpenSerialTablet(WACOMENGINE hEngine, int fd,
519         WACOMMODEL* pModel)
520 {
521         SERIALTABLET* pSerial = NULL;
522
523         /* Allocate tablet */
524         pSerial = (SERIALTABLET*)malloc(sizeof(SERIALTABLET));
525         memset(pSerial,0,sizeof(*pSerial));
526         pSerial->tablet.Close = SerialClose;
527         pSerial->tablet.GetModel = SerialGetModel;
528         pSerial->tablet.GetVendorName = SerialGetVendorName;
529         pSerial->tablet.GetClassName = SerialGetClassName;
530         pSerial->tablet.GetDeviceName = SerialGetDeviceName;
531         pSerial->tablet.GetSubTypeName = SerialGetSubTypeName;
532         pSerial->tablet.GetModelName = SerialGetModelName;
533         pSerial->tablet.GetROMVer = SerialGetROMVer;
534         pSerial->tablet.GetCaps = SerialGetCaps;
535         pSerial->tablet.GetState = SerialGetState;
536         pSerial->tablet.GetFD = SerialGetFD;
537         pSerial->tablet.ReadRaw = SerialReadRaw;
538         pSerial->tablet.ParseData = SerialParseData;
539
540         pSerial->hEngine = hEngine;
541         pSerial->fd = fd;
542         pSerial->state.uValueCnt = WACOMFIELD_MAX;
543
544         /* remember what model was request */
545         if (pModel)
546                 pSerial->modelRequested = *pModel;
547
548         if (SerialReset(pSerial,pModel))
549         {
550                 free(pSerial);
551                 return NULL;
552         }
553
554         return (WACOMTABLET)pSerial;
555 }
556
557 static int SerialReset(SERIALTABLET* pSerial, WACOMMODEL* pModel)
558 {
559         SERIALVENDOR* pVendor = NULL;
560         SERIALDEVICE* pDevice = NULL;
561         SERIALSUBTYPE* pSubType = NULL;
562
563         /* If model is specified, break it down into vendor, device, and subtype */
564         if (pModel && SerialFindModel(pModel,&pVendor,&pDevice,&pSubType))
565                 return 1;
566
567         /* Set the tablet device */
568         if (SerialSetDevice(pSerial,pVendor,pDevice,pSubType))
569                 return 1;
570
571         /* configure the TTY for initial operation */
572         if (SerialConfigTTY(pSerial))
573                 return 1;
574
575         /* Identify the tablet */
576         if (!pSerial->pfnIdent || pSerial->pfnIdent(pSerial))
577                 return 1;
578
579         /* Initialize the tablet */
580         if (!pSerial->pfnInit || pSerial->pfnInit(pSerial))
581                 return 1;
582
583         /* Send start */
584         SerialSendStart(pSerial);
585
586         return 0;
587 }
588
589 /*****************************************************************************
590 ** Serial Tablet Functions
591 *****************************************************************************/
592
593 static int SerialConfigTTY(SERIALTABLET* pSerial)
594 {
595         struct termios tios;
596         int nBaudRate = 9600;
597
598         /* configure tty */
599         if (isatty(pSerial->fd))
600         {
601                 /* set up default port parameters */
602                 if (tcgetattr (pSerial->fd, &tios))
603                 {
604                         SerialError(pSerial,"Failed to get port params: %s",
605                                         strerror(errno));
606                         return 1;
607                 }
608
609                 tios.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
610                 tios.c_oflag &= ~OPOST;
611                 tios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
612                 tios.c_cflag &= ~(CSIZE|PARENB);
613                 tios.c_cflag |= CS8|CLOCAL;
614                 tios.c_cflag &= ~(CSTOPB); /* 1 stop bit */
615                 tios.c_cflag &= ~(CSIZE); /* 8 data bits */
616                 tios.c_cflag |= CS8;
617         tios.c_cflag &= ~(PARENB); /* no parity */
618                 tios.c_iflag |= IXOFF;          /* flow control XOff */
619                 tios.c_cc[VMIN] = 1;            /* vmin value */
620                 tios.c_cc[VTIME] = 0;           /* vtime value */
621
622                 if (tcsetattr (pSerial->fd, TCSANOW, &tios))
623                 {
624                         SerialError(pSerial,"Failed to set port params: %s",
625                                         strerror(errno));
626                         return 1;
627                 }
628
629                 /* get minumum baud rate for given device, if specified */
630                 if (pSerial->pDevice)
631                         nBaudRate = pSerial->pDevice->nMinBaudRate;
632
633                 /* set 38400 baud and reset */
634                 if (SerialResetAtBaud(pSerial,&tios,38400))
635                         return 1;
636
637                 /* if valid, set 19200 baud and reset */
638                 if ((nBaudRate <= 19200) && (SerialResetAtBaud(pSerial,&tios,19200)))
639                         return 1;
640
641                 /* if valid, set 9600 baud and reset */
642                 if ((nBaudRate <= 9600) && (SerialResetAtBaud(pSerial,&tios,9600)))
643                         return 1;
644
645                 /* lower than 9600 baud? for testing, maybe */
646                 if ((nBaudRate < 9600) && (SerialResetAtBaud(pSerial,&tios,nBaudRate)))
647                         return 1;
648         }
649         else /* not tty */
650         {
651                 if (SerialSendReset(pSerial)) return 1;
652         }
653
654         /* Send stop */
655         if (SerialSendStop(pSerial) || WacomFlush(pSerial))
656                 return 1;
657
658         return 0;
659 }
660
661
662 static int SerialSetDevice(SERIALTABLET* pSerial, SERIALVENDOR* pVendor,
663                 SERIALDEVICE* pDevice, SERIALSUBTYPE* pSubType)
664 {
665         pSerial->pVendor = pVendor;
666         pSerial->pDevice = pDevice;
667         pSerial->pSubType = pSubType;
668
669         /* if we know the device, use its functions */
670         if (pSerial->pDevice)
671         {
672                 pSerial->pfnIdent = pSerial->pDevice->pfnIdent;
673                 if (!pSerial->pfnIdent) { errno = EPERM; return 1; }
674         }
675         else
676                 pSerial->pfnIdent = SerialIdentDefault;
677
678         return 0;
679 }
680
681 static int SerialIdentDefault(SERIALTABLET* pSerial)
682 {
683         return SerialIdentWacom(pSerial);
684 }
685
686 static int SerialIdentWacom(SERIALTABLET* pSerial)
687 {
688         char* pszPos;
689         SERIALVENDOR* pVendor = &xWacomVendor;
690         SERIALDEVICE* pDev;
691         SERIALSUBTYPE* pSub;
692         char chResp[64];
693
694         /* send wacom identification request */
695         if (SerialSendRequest(pSerial,"~#\r",chResp,sizeof(chResp)))
696         {
697                 if (errno != ETIMEDOUT) return 1;
698
699                 /* try again, sometimes the first one gets garbled */
700                 if (SerialSendRequest(pSerial,"~#\r",chResp,sizeof(chResp)))
701                         return 1;
702         }
703
704         /* look through device table for information */
705         for (pDev=pVendor->pDevices; pDev->pszName; ++pDev)
706         {
707                 for (pSub=pDev->pSubTypes; pSub && pSub->pszName; ++pSub)
708                 {
709                         if (strncmp(chResp,pSub->pszIdent, strlen(pSub->pszIdent)) == 0)
710                         {
711                                 pSerial->pVendor = pVendor;
712                                 pSerial->pDevice = pDev;
713                                 pSerial->pSubType = pSub;
714                                 pSerial->state.uValid = pDev->uCaps;
715                                 pSerial->uPacketLength = pDev->uPacketLength;
716                                 pSerial->pfnInit = pSub->pfnInit ?
717                                                 pSub->pfnInit : SerialInitWacom;
718
719                                 /* get version number */
720                                 pszPos = chResp;
721                                 while (*pszPos) ++pszPos;
722                                 while ((pszPos > chResp) && (pszPos[-1] != 'V')) --pszPos;
723                                 if (sscanf(pszPos,"%d.%d-%d",&pSerial->nVerMajor,
724                                                 &pSerial->nVerMinor,&pSerial->nVerRelease) != 3)
725                                 {
726                                         pSerial->nVerRelease = 0;
727                                         if (sscanf(pszPos,"%d.%d",&pSerial->nVerMajor,
728                                                 &pSerial->nVerMinor) != 2)
729                                         {
730                                                 errno = EINVAL;
731                                                 SerialError(pSerial,"bad version number: %s",pszPos);
732                                                 return 1;
733                                         }
734                                 }
735                                 return 0;
736                         }
737                 }
738         }
739
740         SerialError(pSerial,"UNIDENTIFIED TABLET: %s",chResp);
741         return 1;
742 }
743
744 static int SerialInitWacom(SERIALTABLET* pSerial)
745 {
746         char chResp[32];
747
748         /* Request tablet dimensions */
749         if (SerialSendRequest(pSerial,"~C\r",chResp,sizeof(chResp)))
750                 return 1;
751
752         /* parse position range */
753         if (sscanf(chResp,"%d,%d",
754                         &pSerial->state.values[WACOMFIELD_POSITION_X].nMax,
755                         &pSerial->state.values[WACOMFIELD_POSITION_Y].nMax) != 2)
756         {
757                 errno=EINVAL;
758                 SerialError(pSerial,"Bad dimension response [%s]",chResp);
759                 return 1;
760         }
761
762         /* tablet specific initialization */
763         switch (pSerial->pDevice->uDevice)
764         {
765                 case WACOMDEVICE_PENPARTNER:
766                         /* pressure mode */
767                         SerialSend(pSerial, "PH1\r");
768                         break;
769
770                 case WACOMDEVICE_INTUOS:
771                 case WACOMDEVICE_INTUOS2:
772                         /* multi-mode, max-rate */
773                         SerialSend(pSerial, "MT1\rID1\rIT0\r");
774         }
775
776         if (pSerial->pDevice->nProtocol == PROTOCOL_4)
777         {
778                 /* multi-mode (MU), upper-origin (OC), all-macro (M0),
779                  * no-macro1 (M1), max-rate (IT), no-inc (IN),
780                  * stream-mode (SR), Z-filter (ZF) */
781
782 /*              if (SerialSend(pSerial->fd, "MU1\rOC1\r~M0\r~M1\rIT0\rIN0\rSR\rZF1\r"))
783                         return 1;
784                         */
785
786                 if (pSerial->nVerMajor == 1)
787                 {
788                         if (pSerial->nVerMinor >= 4)
789                         {
790                                 /* enable tilt mode */
791                                 if (SerialSend(pSerial,"FM1\r")) return 1;
792
793                                 pSerial->pfnParse = SerialParseWacomIV_1_4;
794                                 pSerial->uPacketLength = 9;
795                                 pSerial->state.values[WACOMFIELD_PRESSURE].nMax = 255;
796                                 pSerial->state.values[WACOMFIELD_TILT_X].nMin = -64;
797                                 pSerial->state.values[WACOMFIELD_TILT_X].nMax = 63;
798                                 pSerial->state.values[WACOMFIELD_TILT_Y].nMin = -64;
799                                 pSerial->state.values[WACOMFIELD_TILT_Y].nMax = 63;
800                         }
801                         else if (pSerial->nVerMinor == 3)
802                         {
803                                 pSerial->pfnParse = SerialParseWacomIV_1_3;
804                                 pSerial->state.values[WACOMFIELD_PRESSURE].nMax = 255;
805                         }
806                         else if (pSerial->nVerMinor == 2)
807                         {
808                                 pSerial->pfnParse = SerialParseWacomIV_1_2;
809                                 pSerial->state.values[WACOMFIELD_PRESSURE].nMax = 255;
810                         }
811                         else if (pSerial->nVerMinor < 2)
812                         {
813                                 pSerial->pfnParse = SerialParseWacomIV_1_2;
814                                 pSerial->state.values[WACOMFIELD_PRESSURE].nMax = 120;
815                         }
816                 }
817         }
818         else if (pSerial->pDevice->nProtocol == PROTOCOL_5)
819         {
820                 pSerial->pfnParse = SerialParseWacomV;
821                 pSerial->state.values[WACOMFIELD_PRESSURE].nMax = 1023;
822                 pSerial->state.values[WACOMFIELD_ABSWHEEL].nMax = 1023;
823                 pSerial->state.values[WACOMFIELD_ROTATION_Z].nMin = -900;
824                 pSerial->state.values[WACOMFIELD_ROTATION_Z].nMax = 899;
825                 pSerial->state.values[WACOMFIELD_THROTTLE].nMin = -1023;
826                 pSerial->state.values[WACOMFIELD_THROTTLE].nMax = 1023;
827                 pSerial->state.values[WACOMFIELD_TILT_X].nMin = -64;
828                 pSerial->state.values[WACOMFIELD_TILT_X].nMax = 63;
829                 pSerial->state.values[WACOMFIELD_TILT_Y].nMin = -64;
830                 pSerial->state.values[WACOMFIELD_TILT_Y].nMax = 63;
831         }
832         else { errno=EINVAL; return 1; }
833
834         return 0;
835 }
836
837
838 static int SerialIdentTabletPC(SERIALTABLET* pSerial)
839 {
840         /* sanity check */
841         if ((pSerial->pVendor != &xtpcVendor) ||
842                 (pSerial->pDevice == NULL)) { return EPERM; return 1; }
843
844         /* use first one */
845         pSerial->pSubType = pSerial->pDevice->pSubTypes;
846
847         /* sanity check again */
848         if (pSerial->pSubType->pszName == NULL) { return EPERM; return 1; }
849
850         pSerial->state.uValid = pSerial->pDevice->uCaps;
851         pSerial->uPacketLength = pSerial->pDevice->uPacketLength;
852         pSerial->pfnInit = pSerial->pSubType->pfnInit;
853         pSerial->nVerMajor = 0;
854         pSerial->nVerMinor = 0;
855         pSerial->nVerRelease = 0;
856
857         return 0;
858 }
859
860 static int SerialInitTabletPC(SERIALTABLET* pSerial)
861 {
862         pSerial->pfnParse = SerialParseTabletPC;
863         pSerial->state.values[WACOMFIELD_POSITION_X].nMax = 0x6000;
864         pSerial->state.values[WACOMFIELD_POSITION_Y].nMax = 0x4800;
865         pSerial->state.values[WACOMFIELD_PRESSURE].nMax = 255;
866         return 0;
867 }
868
869 static int SerialParseWacomV(SERIALTABLET* pSerial,
870                 const unsigned char* puchData, unsigned int uLength,
871                 WACOMSTATE* pState)
872 {
873         int x=0, y=0, rot=0, tiltx=0, tilty=0, wheel=0,
874                         tool=WACOMTOOLTYPE_NONE, button=0, press=0, throttle=0,
875                         nButtonValue;
876
877         /* Wacom V
878          * Supports: 1024 pressure, eraser, 2 side-switch, tilt, throttle, wheel
879          * Limitation: no tilt */
880
881         if (uLength != 9) { errno=EINVAL; return 1; }
882
883         /* in */
884         if ((puchData[0] & 0xFC) == 0xC0)
885         {
886                 int toolid = (((int)puchData[1]&0x7F) << 5) |
887                                 (((int)puchData[2]&0x7C) >> 2);
888
889                 int serial = ((((int)puchData[2] & 0x03) << 30) |
890                         (((int)puchData[3] & 0x7f) << 23) |
891                           (((int)puchData[4] & 0x7f) << 16) |
892                           (((int)puchData[5] & 0x7f) << 9) |
893                         (((int)puchData[6] & 0x7f) << 2) |
894                   (((int)puchData[7] & 0x60) >> 5));
895
896                 switch (toolid)
897                 {
898                         case 0x812: /* Intuos2 ink pen XP-110-00A */
899                         case 0x012: /* Inking pen */
900                                 tool = WACOMTOOLTYPE_PENCIL; break;
901
902                         case 0x822: /* Intuos Pen GP-300E-01H */
903                         case 0x852: /* Intuos2 Grip Pen XP-501E-00A */
904                         case 0x842: /* added from Cheng */
905                         case 0x022:
906                                 tool = WACOMTOOLTYPE_PEN; break;
907
908                         case 0x832: /* Intuos2 stroke pen XP-120-00A */
909                         case 0x032: /* Stroke pen */
910                                 tool = WACOMTOOLTYPE_BRUSH; break;
911
912                         case 0x007: /* 2D Mouse */
913                         case 0x09C: /* ?? Mouse */
914                         case 0x094: /* 4D Mouse */
915                                 tool = WACOMTOOLTYPE_MOUSE; break;
916
917                         case 0x096: /* Lens cursor */
918                                 tool = WACOMTOOLTYPE_LENS; break;
919
920                         case 0x82a:
921                         case 0x85a:
922                         case 0x91a:
923                         case 0x0fa: /* Eraser */
924                                 tool = WACOMTOOLTYPE_ERASER; break;
925
926                         case 0x112: /* Airbrush */
927                                 tool = WACOMTOOLTYPE_AIRBRUSH; break;
928
929                         default: /* Unknown tool */
930                                 tool = WACOMTOOLTYPE_PEN; break;
931                 }
932
933                 pSerial->nToolID = toolid;
934                 pSerial->state.values[WACOMFIELD_PROXIMITY].nValue = 1;
935                 pSerial->state.values[WACOMFIELD_SERIAL].nValue = serial;
936                 pSerial->state.values[WACOMFIELD_TOOLTYPE].nValue = tool;
937                 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
938         }
939
940         /* out */
941         if ((puchData[0] & 0xFE) == 0x80)
942         {
943                 pSerial->nToolID = 0;
944                 memset(&pSerial->state.values, 0,
945                                 pSerial->state.uValueCnt * sizeof(WACOMVALUE));
946                 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
947         }
948
949         /* pen data */
950         if (((puchData[0] & 0xB8) == 0xA0) || ((puchData[0] & 0xBE) == 0xB4))
951         {
952                 x = ((((int)puchData[1] & 0x7f) << 9) |
953                                 (((int)puchData[2] & 0x7f) << 2) |
954                                 (((int)puchData[3] & 0x60) >> 5));
955                 y = ((((int)puchData[3] & 0x1f) << 11) |
956                                 (((int)puchData[4] & 0x7f) << 4) |
957                                 (((int)puchData[5] & 0x78) >> 3));
958                 tiltx = (puchData[7] & 0x3F);
959                 tilty = (puchData[8] & 0x3F);
960                 if (puchData[7] & 0x40) tiltx -= 0x40;
961                 if (puchData[8] & 0x40) tilty -= 0x40;
962
963                 /* pen packet */
964                 if ((puchData[0] & 0xB8) == 0xA0)
965                 {
966                         press = ((((int)puchData[5] & 0x07) << 7) | ((int)puchData[6] & 0x7f));
967                         button = (press > 10) ? BIT(WACOMBUTTON_TOUCH) : 0;
968                         button |= (puchData[0] & 0x02) ? BIT(WACOMBUTTON_STYLUS) : 0;
969                         button |= (puchData[0] & 0x04) ? BIT(WACOMBUTTON_STYLUS2) : 0;
970                 }
971
972                 /* 2nd airbrush packet */
973                 else
974                 {
975                         wheel = ((((int)puchData[5] & 0x07) << 7) |
976                                         ((int)puchData[6] & 0x7f));
977                 }
978
979                 pSerial->state.values[WACOMFIELD_POSITION_X].nValue = x;
980                 pSerial->state.values[WACOMFIELD_POSITION_Y].nValue = y;
981                 pSerial->state.values[WACOMFIELD_TILT_X].nValue = tiltx;
982                 pSerial->state.values[WACOMFIELD_TILT_Y].nValue = tilty;
983                 pSerial->state.values[WACOMFIELD_PRESSURE].nValue = press;
984                 pSerial->state.values[WACOMFIELD_BUTTONS].nValue = button;
985                 pSerial->state.values[WACOMFIELD_ABSWHEEL].nValue = wheel;
986                 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
987         }
988
989         /* mouse packet */
990         if (((puchData[0] & 0xBE) == 0xA8) || ((puchData[0] & 0xBE) == 0xB0))
991         {
992                 x = ((((int)puchData[1] & 0x7f) << 9) |
993                                 (((int)puchData[2] & 0x7f) << 2) |
994                                 (((int)puchData[3] & 0x60) >> 5));
995                 y = ((((int)puchData[3] & 0x1f) << 11) |
996                                 (((int)puchData[4] & 0x7f) << 4) |
997                                 (((int)puchData[5] & 0x78) >> 3));
998                 throttle = ((((int)puchData[5] & 0x07) << 7) | (puchData[6] & 0x7f));
999                 if (puchData[8] & 0x08) throttle = -throttle;
1000
1001                 /* 4D mouse */
1002                 if (pSerial->nToolID == 0x094)
1003                 {
1004                         button = (((puchData[8] & 0x70) >> 1) | (puchData[8] & 0x07));
1005                 }
1006                 /* lens cursor */
1007                 else if (pSerial->nToolID == 0x096)
1008                 {
1009                         button = puchData[8] & 0x1F;
1010                 }
1011                 /* 2D mouse */
1012                 else
1013                 {
1014                         button = (puchData[8] & 0x1C) >> 2;
1015                         wheel = - (puchData[8] & 1) + ((puchData[8] & 2) >> 1);
1016                 }
1017
1018                 pSerial->state.values[WACOMFIELD_POSITION_X].nValue = x;
1019                 pSerial->state.values[WACOMFIELD_POSITION_Y].nValue = y;
1020                 pSerial->state.values[WACOMFIELD_RELWHEEL].nValue = wheel;
1021                 pSerial->state.values[WACOMFIELD_THROTTLE].nValue = throttle;
1022
1023                 /* button values */
1024                 nButtonValue = pSerial->state.values[WACOMFIELD_BUTTONS].nValue &
1025                                 ~(BIT(WACOMBUTTON_LEFT) |
1026                                 BIT(WACOMBUTTON_RIGHT) | BIT(WACOMBUTTON_MIDDLE) |
1027                                 BIT(WACOMBUTTON_EXTRA) | BIT(WACOMBUTTON_SIDE));
1028                 if (button & 1) nButtonValue |= BIT(WACOMBUTTON_LEFT);
1029                 if (button & 2) nButtonValue |= BIT(WACOMBUTTON_MIDDLE);
1030                 if (button & 4) nButtonValue |= BIT(WACOMBUTTON_RIGHT);
1031                 if (button & 8) nButtonValue |= BIT(WACOMBUTTON_EXTRA);
1032                 if (button & 16) nButtonValue |= BIT(WACOMBUTTON_SIDE);
1033                 pSerial->state.values[WACOMFIELD_BUTTONS].nValue = nButtonValue;
1034
1035                 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
1036         }
1037
1038         /* 2nd 4D mouse packet */
1039         if ((puchData[0] & 0xBE) == 0xAA)
1040         {
1041                 x = ((((int)puchData[1] & 0x7f) << 9) |
1042                                 (((int)puchData[2] & 0x7f) << 2) |
1043                                 (((int)puchData[3] & 0x60) >> 5));
1044                 y = ((((int)puchData[3] & 0x1f) << 11) |
1045                                 (((int)puchData[4] & 0x7f) << 4) |
1046                                 (((int)puchData[5] & 0x78) >> 3));
1047                 rot = ((((int)puchData[6] & 0x0f) << 7) |
1048                                 ((int)puchData[7] & 0x7f));
1049
1050                 /* FIX ROT */
1051                 if (rot < 900) rot = -rot;
1052                 else rot = 1799 - rot;
1053
1054                 pSerial->state.values[WACOMFIELD_POSITION_X].nValue = x;
1055                 pSerial->state.values[WACOMFIELD_POSITION_Y].nValue = y;
1056                 pSerial->state.values[WACOMFIELD_ROTATION_Z].nValue = rot;
1057                 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
1058         }
1059
1060         errno = EINVAL;
1061         return 1;
1062 }
1063
1064 static int SerialParseWacomIV_1_4(SERIALTABLET* pSerial,
1065                 const unsigned char* puchData, unsigned int uLength,
1066                 WACOMSTATE* pState)
1067 {
1068         /* Wacom IV, Rom 1.4
1069          * Supports: 256 pressure, eraser, 2 side-switch, tilt */
1070
1071         if ((uLength != 7) && (uLength != 9)) { errno=EINVAL; return 1; }
1072
1073         if (SerialParseWacomIV_1_3(pSerial,puchData,7,pState))
1074                 return 1;
1075
1076         /* tilt mode */
1077         if (uLength == 9)
1078         {
1079                 int tiltx, tilty;
1080
1081                 tiltx = puchData[7] & 0x3F;
1082                 tilty = puchData[8] & 0x3F;
1083                 if (puchData[7] & 0x40) tiltx -= 64;
1084                 if (puchData[8] & 0x40) tilty -= 64;
1085
1086                 pSerial->state.values[WACOMFIELD_TILT_X].nValue = tiltx;
1087                 pSerial->state.values[WACOMFIELD_TILT_Y].nValue = tilty;
1088
1089                 if (pState)
1090                 {
1091                         pState->values[WACOMFIELD_TILT_X].nValue = tiltx;
1092                         pState->values[WACOMFIELD_TILT_Y].nValue = tilty;
1093                 }
1094         }
1095
1096         return 0;
1097 }
1098
1099 static int SerialParseWacomIV_1_3(SERIALTABLET* pSerial,
1100                 const unsigned char* puchData, unsigned int uLength,
1101                 WACOMSTATE* pState)
1102 {
1103         int x=0, y=0, prox=0, tool=WACOMTOOLTYPE_NONE,
1104                         button=0, press=0, stylus, eraser;
1105
1106         /* Wacom IV, Rom 1.3 (ArtPadII)
1107          * Supports: 256 pressure, eraser, 2 side-switch
1108          * Limitation: no tilt */
1109
1110         if (uLength != 7) { errno=EINVAL; return 1; }
1111
1112         prox = puchData[0] & 0x40 ? 1 : 0;
1113         if (prox)
1114         {
1115                 stylus = puchData[0] & 0x20 ? 1 : 0;
1116                 press = (puchData[6] & 0x3F) << 1 | ((puchData[3] & 0x4) >> 2);
1117                 press |= (puchData[6] & 0x40) ? 0 : 0x80;
1118                 eraser = (puchData[3] & 0x20) ? 1 : 0;
1119
1120                 if (stylus)
1121                 {
1122                         /* if entering proximity, choose eraser or stylus2 for bit */
1123                         if (pSerial->state.values[WACOMFIELD_PROXIMITY].nValue == 0)
1124                         {
1125                                 if (eraser) tool = WACOMTOOLTYPE_ERASER;
1126                                 else tool = WACOMTOOLTYPE_PEN;
1127                         }
1128
1129                         /* otherwise, keep the last tool */
1130                         else tool = pSerial->state.values[WACOMFIELD_TOOLTYPE].nValue;
1131
1132                         button = (press > 10) ? BIT(WACOMBUTTON_TOUCH) : 0;
1133
1134                         /* pen has 2 side-switch, eraser has none */
1135                         if (tool == WACOMTOOLTYPE_PEN)
1136                         {
1137                                 button |= (puchData[3] & 0x10) ?
1138                                                 BIT(WACOMBUTTON_STYLUS) : 0;
1139                                 button |= (eraser) ? BIT(WACOMBUTTON_STYLUS2) : 0;
1140                         }
1141                 }
1142                 else
1143                 {
1144                         tool = WACOMTOOLTYPE_MOUSE;
1145                         button = (puchData[3] & 0x78) >> 3; /* not tested */
1146                 }
1147
1148                 x = puchData[2] | ((int)puchData[1] << 7) |
1149                                 (((int)puchData[0] & 0x3) << 14);
1150                 y = puchData[5] | ((int)puchData[4] << 7) |
1151                                 (((int)puchData[3] & 0x3) << 14);
1152         }
1153
1154         /* set valid fields */
1155         pSerial->state.values[WACOMFIELD_PROXIMITY].nValue = prox;
1156         pSerial->state.values[WACOMFIELD_TOOLTYPE].nValue = tool;
1157         pSerial->state.values[WACOMFIELD_POSITION_X].nValue = x;
1158         pSerial->state.values[WACOMFIELD_POSITION_Y].nValue = y;
1159         pSerial->state.values[WACOMFIELD_PRESSURE].nValue = press;
1160         pSerial->state.values[WACOMFIELD_BUTTONS].nValue = button;
1161
1162         return pState ? WacomCopyState(pState,&pSerial->state) : 0;
1163 }
1164
1165 static int SerialParseWacomIV_1_2(SERIALTABLET* pSerial,
1166                 const unsigned char* puchData, unsigned int uLength,
1167                 WACOMSTATE* pState)
1168 {
1169         int x=0, y=0, prox=0, tool=0, button=WACOMTOOLTYPE_NONE,
1170                         press=0, stylus;
1171
1172         /* Wacom IV, Rom 1.2, 1.1, and 1.0
1173          * Supports: 256 pressure (120 for 1.1 and 1.0), multi-mode
1174          * Limitation: no stylus2, no tilt, no eraser */
1175
1176         if (uLength != 7) { errno=EINVAL; return 1; }
1177
1178         prox = puchData[0] & 0x40 ? 1 : 0;
1179         if (prox)
1180         {
1181                 stylus = puchData[0] & 0x20 ? 1 : 0;
1182                 if (pSerial->nVerMinor == 2)
1183                         press = ((puchData[6] & 0x3F) << 1) | ((puchData[3] & 0x4) >> 2) |
1184                                         ((puchData[6] & 0x40) ? 0 : 0x80);
1185                 else
1186                         press = (puchData[6] & 0x3F) + ((puchData[6] & 0x40) ? 0 : 64);
1187
1188                 if (stylus)
1189                 {
1190                         tool = WACOMTOOLTYPE_PEN;
1191                         button = (press > 10) ? BIT(WACOMBUTTON_TOUCH) : 0;
1192                         button |= (puchData[3] & 0x10) ? BIT(WACOMBUTTON_STYLUS) : 0;
1193                 }
1194                 else
1195                 {
1196                         tool = WACOMTOOLTYPE_MOUSE;
1197                         button = (puchData[3] & 0x78) >> 3; /* not tested */
1198                 }
1199
1200                 x = puchData[2] | ((int)puchData[1] << 7) |
1201                                 (((int)puchData[0] & 0x3) << 14);
1202                 y = puchData[5] | ((int)puchData[4] << 7) |
1203                                 (((int)puchData[3] & 0x3) << 14);
1204         }
1205
1206         /* set valid fields */
1207         pSerial->state.values[WACOMFIELD_PROXIMITY].nValue = prox;
1208         pSerial->state.values[WACOMFIELD_TOOLTYPE].nValue = tool;
1209         pSerial->state.values[WACOMFIELD_POSITION_X].nValue = x;
1210         pSerial->state.values[WACOMFIELD_POSITION_Y].nValue = y;
1211         pSerial->state.values[WACOMFIELD_PRESSURE].nValue = press;
1212         pSerial->state.values[WACOMFIELD_BUTTONS].nValue = button;
1213
1214         return pState ? WacomCopyState(pState,&pSerial->state) : 0;
1215 }
1216
1217 static int SerialParseTabletPC(SERIALTABLET* pSerial,
1218                 const unsigned char* puchData, unsigned int uLength,
1219                 WACOMSTATE* pState)
1220 {
1221         int x=0, y=0, prox=0, tool=WACOMTOOLTYPE_NONE,
1222                         button=0, press=0, eraser;
1223
1224         /* Tablet PC Supports: 256 pressure, eraser, 1/2 side-switch */
1225
1226         if (uLength != 9) { errno=EINVAL; return 1; }
1227
1228         prox = puchData[0] & 0x20 ? 1 : 0;
1229         if (prox)
1230         {
1231                 eraser = (puchData[0] & 0x04) ? 1 : 0;
1232                 press = ((puchData[6] & 0x01) << 7) | (puchData[5] & 0x7F);
1233
1234                 /* tools are distinguishable */
1235                 if (eraser) tool = WACOMTOOLTYPE_ERASER;
1236                 else tool = WACOMTOOLTYPE_PEN;
1237
1238                 button = (puchData[0] & 0x01) ? BIT(WACOMBUTTON_TOUCH) : 0;
1239
1240                 /* pen has side-switch(es), eraser has none */
1241                 if (tool == WACOMTOOLTYPE_PEN)
1242                 {
1243                         button |= (puchData[0] & 0x02) ?
1244                                         BIT(WACOMBUTTON_STYLUS) : 0;
1245                         button |= (puchData[0] & 0x04) ?
1246                                         BIT(WACOMBUTTON_STYLUS2) : 0;
1247                 }
1248
1249                 x = (((int)puchData[6] & 0x60) >> 5) |
1250                         ((int)puchData[2] << 2) |
1251                         ((int)puchData[1] << 9);
1252                 y = (((int)puchData[6] & 0x18) >> 3) |
1253                         ((int)puchData[4] << 2) |
1254                         ((int)puchData[3] << 9);
1255         }
1256
1257         /* set valid fields */
1258         pSerial->state.values[WACOMFIELD_PROXIMITY].nValue = prox;
1259         pSerial->state.values[WACOMFIELD_TOOLTYPE].nValue = tool;
1260         pSerial->state.values[WACOMFIELD_POSITION_X].nValue = x;
1261         pSerial->state.values[WACOMFIELD_POSITION_Y].nValue = y;
1262         pSerial->state.values[WACOMFIELD_PRESSURE].nValue = press;
1263         pSerial->state.values[WACOMFIELD_BUTTONS].nValue = button;
1264
1265         return pState ? WacomCopyState(pState,&pSerial->state) : 0;
1266 }
1267
1268
1269
1270 /*****************************************************************************
1271 ** Internal Functions
1272 *****************************************************************************/
1273
1274 static int SerialSendReset(SERIALTABLET* pSerial)
1275 {
1276         SerialInfo(pSerial,"Sending reset");
1277
1278         /* reset to Wacom II-S command set, and factory defaults */
1279         if (SerialSend(pSerial,"\r$\r")) return 1;
1280         usleep(250000); /* 250 milliseconds */
1281
1282         /* reset tablet to Wacom IV command set */
1283         if (SerialSend(pSerial,"#\r")) return 1;
1284         usleep(75000); /* 75 milliseconds */
1285
1286         return 0;
1287 }
1288
1289 static int SerialSendStop(SERIALTABLET* pSerial)
1290 {
1291         if (SerialSend(pSerial,"\rSP\r")) return 1;
1292         usleep(100000);
1293         return 0;
1294 }
1295
1296 static int SerialSendStart(SERIALTABLET* pSerial)
1297 {
1298         return SerialSend(pSerial,"ST\r");
1299 }
1300
1301 static int SerialSend(SERIALTABLET* pSerial, const char* pszMsg)
1302 {
1303         return SerialSendRaw(pSerial,pszMsg,(unsigned)strlen(pszMsg));
1304 }
1305
1306 static int SerialSendRaw(SERIALTABLET* pSerial, const void* pvData,
1307                 unsigned int uSize)
1308 {
1309         int nXfer;
1310         unsigned int uCnt=0;
1311         unsigned char* puchData = (unsigned char*)pvData;
1312
1313         while (uCnt < uSize)
1314         {
1315                 nXfer = write(pSerial->fd,puchData+uCnt,uSize-uCnt);
1316                 if (nXfer <= 0)
1317                 {
1318                         SerialError(pSerial,"Failed to write to port: %s",strerror(errno));
1319                         return 1;
1320                 }
1321                 uCnt += nXfer;
1322         }
1323
1324         return 0;
1325 }
1326
1327 static int WacomFlush(SERIALTABLET* pSerial)
1328 {
1329         char ch[16];
1330         fd_set fdsRead;
1331         struct timeval timeout;
1332
1333         if (tcflush(pSerial->fd, TCIFLUSH) == 0)
1334                 return 0;
1335
1336         timeout.tv_sec = 0;
1337         timeout.tv_usec = 0;
1338
1339         while (1)
1340         {
1341                 FD_ZERO(&fdsRead);
1342                 FD_SET(pSerial->fd, &fdsRead);
1343                 if (select(FD_SETSIZE,&fdsRead,NULL,NULL,&timeout) <= 0)
1344                         break;
1345                 read(pSerial->fd,&ch,sizeof(ch));
1346         }
1347
1348         return 0;
1349 }
1350
1351 static int SerialSendRequest(SERIALTABLET* pSerial, const char* pszRequest,
1352                 char* pchResponse, unsigned int uSize)
1353 {
1354         int nXfer;
1355         fd_set fdsRead;
1356         unsigned int uLen, uCnt;
1357         struct timeval timeout;
1358
1359         uLen = strlen(pszRequest);
1360         if (SerialSendRaw(pSerial,pszRequest,uLen)) return 1;
1361         --uLen;
1362
1363         if (uSize < uLen)
1364         {
1365                 errno=EINVAL;
1366                 SerialError(pSerial,"Invalid size to SerialSendRequest: %u < %u",
1367                                 uSize,uLen);
1368                 return 1;
1369         }
1370
1371         /* read until first header character */
1372         while (1)
1373         {
1374                 timeout.tv_sec = 0;
1375                 timeout.tv_usec = 500000;
1376
1377                 FD_ZERO(&fdsRead);
1378                 FD_SET(pSerial->fd, &fdsRead);
1379                 if (select(FD_SETSIZE,&fdsRead,NULL,NULL,&timeout) <= 0)
1380                 {
1381                         errno = ETIMEDOUT;
1382                         return 1;
1383                 }
1384
1385                 nXfer = read(pSerial->fd,pchResponse,1);
1386                 if (nXfer <= 0)
1387                 {
1388                         SerialError(pSerial,"Truncated response header");
1389                         return 1;
1390                 }
1391                 if (*pchResponse == *pszRequest) break;
1392                 SerialWarn(pSerial,"Discarding %02X", *((unsigned char*)pchResponse));
1393         }
1394
1395         /* read response header */
1396         for (uCnt=1; uCnt<uLen; uCnt+=nXfer)
1397         {
1398                 nXfer = read(pSerial->fd,pchResponse+uCnt,uLen-uCnt);
1399                 if (nXfer <= 0)
1400                 {
1401                         SerialError(pSerial,"Truncated response header (2)");
1402                         return 1;
1403                 }
1404         }
1405
1406         /* check the header */
1407         if (strncmp(pszRequest,pchResponse,uLen) != 0)
1408         {
1409                 SerialError(pSerial,"Incorrect response [%s,%s]",
1410                                 pszRequest,pchResponse);
1411                 return 1;
1412         }
1413
1414         /* get the rest of the response */
1415         for (uCnt=0; uCnt<uSize; ++uCnt)
1416         {
1417                 nXfer = read(pSerial->fd,pchResponse+uCnt,1);
1418                 if (nXfer <= 0)
1419                 {
1420                         SerialError(pSerial,"Failed to read response: %s",strerror(errno));
1421                         return 1;
1422                 }
1423
1424                 /* stop on CR */
1425                 if (pchResponse[uCnt] == '\r')
1426                 {
1427                         pchResponse[uCnt] = '\0';
1428                         return 0;
1429                 }
1430         }
1431
1432         errno = EINVAL;
1433         SerialError(pSerial,"Invalid response");
1434         return 1;
1435 }
1436
1437 /*****************************************************************************
1438 ** Virtual Functions
1439 *****************************************************************************/
1440
1441 static void SerialClose(WACOMTABLET_PRIV* pTablet)
1442 {
1443         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1444         close(pSerial->fd);
1445         free(pSerial);
1446 }
1447
1448 static WACOMMODEL SerialGetModel(WACOMTABLET_PRIV* pTablet)
1449 {
1450         WACOMMODEL model = { 0 };
1451         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1452         model.uClass = WACOMCLASS_SERIAL;
1453         model.uVendor = pSerial->pVendor->uVendor;
1454         model.uDevice = pSerial->pDevice->uDevice;
1455         model.uSubType = pSerial->pSubType->uSubType;
1456         return model;
1457 }
1458
1459 static const char* SerialGetVendorName(WACOMTABLET_PRIV* pTablet)
1460 {
1461         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1462         return pSerial->pVendor->pszDesc;
1463 }
1464
1465 static const char* SerialGetClassName(WACOMTABLET_PRIV* pTablet)
1466 {
1467         return "Serial";
1468 }
1469
1470 static const char* SerialGetDeviceName(WACOMTABLET_PRIV* pTablet)
1471 {
1472         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1473         return pSerial->pDevice->pszDesc;
1474 }
1475
1476 static const char* SerialGetSubTypeName(WACOMTABLET_PRIV* pTablet)
1477 {
1478         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1479         return pSerial->pSubType->pszName;
1480 }
1481
1482 static const char* SerialGetModelName(WACOMTABLET_PRIV* pTablet)
1483 {
1484         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1485         return pSerial->pSubType->pszDesc;
1486 }
1487
1488 static int SerialGetROMVer(WACOMTABLET_PRIV* pTablet, int* pnMajor,
1489                 int* pnMinor, int* pnRelease)
1490 {
1491         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1492         if (!pnMajor) { errno=EINVAL; return 1; }
1493         *pnMajor = pSerial->nVerMajor;
1494         if (pnMinor) *pnMinor = pSerial->nVerMinor;
1495         if (pnRelease) *pnRelease = pSerial->nVerRelease;
1496         return 0;
1497 }
1498
1499 static int SerialGetCaps(WACOMTABLET_PRIV* pTablet)
1500 {
1501         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1502         return pSerial->pDevice->uCaps;
1503 }
1504
1505 static int SerialGetState(WACOMTABLET_PRIV* pTablet, WACOMSTATE* pState)
1506 {
1507         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1508         return WacomCopyState(pState,&pSerial->state);
1509 }
1510
1511 static int SerialGetFD(WACOMTABLET_PRIV* pTablet)
1512 {
1513         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1514         return pSerial->fd;
1515 }
1516
1517 static int SerialReadRaw(WACOMTABLET_PRIV* pTablet, unsigned char* puchData,
1518                 unsigned int uSize)
1519 {
1520         int nXfer;
1521         fd_set fdsRead;
1522         unsigned char* pPos, *pEnd;
1523         struct timeval timeout;
1524         unsigned int uCnt, uPacketLength;
1525         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1526
1527         if (!pSerial) { errno=EBADF; return 0; }
1528         uPacketLength = pSerial->uPacketLength;
1529
1530         /* check size of buffer */
1531         if (uSize < uPacketLength) { errno=EINVAL; return 0; }
1532
1533         /* check for errors, reset after 3 */
1534         if (pSerial->nBitErrors > 3)
1535         {
1536                 pSerial->nBitErrors = 0;
1537                 SerialWarn(pSerial,"Resetting tablet due to bit errors");
1538                 (void)SerialReset(pSerial,&pSerial->modelRequested);
1539         }
1540
1541         timeout.tv_sec = 0;
1542         timeout.tv_usec = 500000; /* 0.5 seconds for now */
1543
1544         for (uCnt=0; uCnt<uPacketLength; uCnt+=nXfer)
1545         {
1546                 FD_ZERO(&fdsRead);
1547                 FD_SET(pSerial->fd, &fdsRead);
1548                 if (select(FD_SETSIZE,&fdsRead,NULL,NULL,&timeout) <= 0)
1549                         break;
1550
1551                 nXfer = read(pSerial->fd,puchData+uCnt,uPacketLength-uCnt);
1552                 if (nXfer <= 0) return nXfer;
1553
1554                 /* look for high-bit */
1555                 pEnd = puchData + nXfer;
1556                 for (pPos=puchData; pPos<pEnd; ++pPos)
1557                 {
1558                         if (*pPos & 0x80) break;
1559                 }
1560
1561                 /* not where it was expected? fix it. */
1562                 if (pPos != puchData)
1563                 {
1564                         ++pSerial->nBitErrors;
1565                         SerialWarn(pSerial,"Bad high bit, discarding %d bytes",
1566                                 pPos - puchData);
1567
1568                         /* copy remaining bytes down, if any */
1569                         memmove(puchData,pPos,(nXfer - (pPos-puchData)));
1570                         nXfer -= pPos - puchData;
1571                 }
1572         }
1573
1574         if (uCnt < uPacketLength)
1575         {
1576                 errno = ETIMEDOUT;
1577                 return -1;
1578         }
1579
1580         return (signed)uCnt;
1581 }
1582
1583 static int SerialParseData(WACOMTABLET_PRIV* pTablet,
1584                 const unsigned char* puchData, unsigned int uLength,
1585                 WACOMSTATE* pState)
1586 {
1587         int i;
1588         SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1589         if (!pSerial) { errno=EBADF; return 1; }
1590
1591         /* check synchronization */
1592         if (!(puchData[0] & 0x80))
1593         {
1594                 ++pSerial->nBitErrors;
1595                 SerialError(pSerial,"HIBIT FAIL");
1596                 errno=EINVAL;
1597                 return 1;
1598         }
1599         for (i=1; i<uLength; ++i)
1600         {
1601                 if (puchData[i] & 0x80)
1602                 {
1603                         ++pSerial->nBitErrors;
1604                         SerialError(pSerial,"LOBIT FAIL");
1605                         SerialDump(pSerial,puchData,uLength);
1606                         errno=EINVAL;
1607                         return 1;
1608                 }
1609         }
1610
1611         /* reset bit error count */
1612         pSerial->nBitErrors = 0;
1613
1614         /* dispatch to parser */
1615         if (pSerial->pfnParse)
1616                 return (*pSerial->pfnParse)(pSerial,puchData,uLength,pState);
1617
1618         errno=EINVAL;
1619         return 1;
1620 }
1621
1622 static int SerialResetAtBaud(SERIALTABLET* pSerial, struct termios* pTIOS,
1623                 int nBaud)
1624 {
1625         /* conver baud rate to tios macro */
1626         int baudRate = B9600;
1627         switch (nBaud)
1628         {
1629                 case 38400: baudRate = B38400; break;
1630                 case 19200: baudRate = B19200; break;
1631                 case 9600: baudRate = B9600; break;
1632                 case 4800: baudRate = B4800; break; /* for testing, maybe */
1633                 case 2400: baudRate = B2400; break; /* for testing, maybe */
1634                 case 1200: baudRate = B1200; break; /* for testing, maybe */
1635         }
1636
1637         SerialInfo(pSerial,"Setting baud rate to %d",nBaud);
1638
1639         /* change baud rate */
1640         cfsetispeed(pTIOS, baudRate);
1641         cfsetospeed(pTIOS, baudRate);
1642         if (tcsetattr (pSerial->fd, TCSANOW, pTIOS))
1643                 return 1;
1644
1645         /* send reset command */
1646         return SerialSendReset(pSerial);
1647 }
1648
1649 /*****************************************************************************
1650 ** Log Functions
1651 *****************************************************************************/
1652
1653 #define SERIALLOG(l) do { \
1654         va_list a; \
1655         va_start(a,pszFmt); \
1656         WacomLogV(pSerial->hEngine,l,pszFmt,a); \
1657         va_end(a); } while (0)
1658
1659 static void SerialError(SERIALTABLET* pSerial, const char* pszFmt, ...)
1660         { SERIALLOG(WACOMLOGLEVEL_ERROR); }
1661 static void SerialWarn(SERIALTABLET* pSerial, const char* pszFmt, ...)
1662         { SERIALLOG(WACOMLOGLEVEL_WARN); }
1663 static void SerialInfo(SERIALTABLET* pSerial, const char* pszFmt, ...)
1664         { SERIALLOG(WACOMLOGLEVEL_INFO); }
1665
1666 static void SerialDump(SERIALTABLET* pSerial, const void* pvData, int nCnt)
1667 {
1668         int i;
1669         const unsigned char* pData = (const unsigned char*)pvData;
1670         char chLine[80];
1671         unsigned int uAddr = 0;
1672         int nPos = 0;
1673
1674         while (nCnt > 0)
1675         {
1676                 nPos = 0;
1677                 for (i=0; i<16; ++i)
1678                 {
1679                         if (i < nCnt)
1680                                 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos,
1681                                                 "%02X",pData[i]);
1682                         else
1683                                 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos,
1684                                                 "  ");
1685                 }
1686                 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos," - ");
1687                 for (i=0; i<16; ++i)
1688                 {
1689                         if (i < nCnt)
1690                                 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos,
1691                                                 "%c",isprint(pData[i]) ? pData[i] : '.');
1692                         else
1693                                 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos,
1694                                                 " ");
1695                 }
1696
1697                 WacomLog(pSerial->hEngine,WACOMLOGLEVEL_DEBUG,"%04X: %s",uAddr,chLine);
1698                 uAddr += 16;
1699                 nCnt -= 16;
1700                 pData += 16;
1701         }
1702 }
1703
1704 /* NOT USED, YET
1705 static void SerialCritical(SERIALTABLET* pSerial, const char* pszFmt, ...)
1706         { SERIALLOG(WACOMLOGLEVEL_CRITICAL); }
1707 static void SerialDebug(SERIALTABLET* pSerial, const char* pszFmt, ...)
1708         { SERIALLOG(WACOMLOGLEVEL_DEBUG); }
1709 static void SerialTrace(SERIALTABLET* pSerial, const char* pszFmt, ...)
1710         { SERIALLOG(WACOMLOGLEVEL_TRACE); }
1711 */