1 /*****************************************************************************
4 ** Copyright (C) 2002, 2003 - John E. Joganic
5 ** Copyright (C) 2002 - 2008 - Ping Cheng
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.
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.
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.
21 ****************************************************************************/
23 #include "wacserial.h"
34 /*****************************************************************************
35 ** Serial Tablet Object
36 *****************************************************************************/
38 typedef struct _SERIALTABLET SERIALTABLET;
39 typedef struct _SERIALSUBTYPE SERIALSUBTYPE;
40 typedef struct _SERIALDEVICE SERIALDEVICE;
41 typedef struct _SERIALVENDOR SERIALVENDOR;
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);
50 WACOMTABLET_PRIV tablet;
53 SERIALVENDOR* pVendor;
54 SERIALDEVICE* pDevice;
55 SERIALSUBTYPE* pSubType;
56 unsigned int uPacketLength;
57 int nVerMajor, nVerMinor, nVerRelease;
64 WACOMMODEL modelRequested;
67 /*****************************************************************************
68 ** Internal structures
69 *****************************************************************************/
75 unsigned int uSubType;
85 SERIALSUBTYPE* pSubTypes;
87 unsigned int uPacketLength;
98 SERIALDEVICE* pDevices;
101 /*****************************************************************************
103 *****************************************************************************/
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,
119 static int SerialParseData(WACOMTABLET_PRIV* pTablet,
120 const unsigned char* puchData, unsigned int uLength,
123 static int SerialReset(SERIALTABLET* pSerial, WACOMMODEL* pModel);
124 static int SerialConfigTTY(SERIALTABLET* pSerial);
125 static int SerialResetAtBaud(SERIALTABLET* pSerial, struct termios* pTIOS,
127 static int SerialSetDevice(SERIALTABLET* pSerial, SERIALVENDOR* pVendor,
128 SERIALDEVICE* pDevice, SERIALSUBTYPE* pSubType);
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);
136 static int SerialParseWacomV(SERIALTABLET* pSerial,
137 const unsigned char* puchData, unsigned int uLength,
139 static int SerialParseWacomIV_1_4(SERIALTABLET* pSerial,
140 const unsigned char* puchData, unsigned int uLength,
142 static int SerialParseWacomIV_1_3(SERIALTABLET* pSerial,
143 const unsigned char* puchData, unsigned int uLength,
145 static int SerialParseWacomIV_1_2(SERIALTABLET* pSerial,
146 const unsigned char* puchData, unsigned int uLength,
148 static int SerialParseTabletPC(SERIALTABLET* pSerial,
149 const unsigned char* puchData, unsigned int uLength,
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);
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, ...);
162 /*****************************************************************************
164 *****************************************************************************/
168 #define BIT(x) (1<<(x))
171 #define WACOMVALID(x) BIT(WACOMFIELD_##x)
173 #define ARTPAD_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
174 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
175 WACOMVALID(PRESSURE))
177 #define ARTPADII_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
178 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
179 WACOMVALID(PRESSURE))
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))
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))
189 #define PENPARTNER_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
190 WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
191 WACOMVALID(PRESSURE))
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))
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))
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))
207 #define TABLETPC_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(SERIAL)| \
208 WACOMVALID(PROXIMITY)|WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)| \
209 WACOMVALID(POSITION_Y)|WACOMVALID(PRESSURE))
211 #define INTUOS2_CAPS INTUOS_CAPS
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 }
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 }
228 /*****************************************************************************
230 *****************************************************************************/
232 static SERIALSUBTYPE xArtPadII[] =
234 WACOM_SUBTYPE("KT-0405-R", "Wacom ArtPadII 4x5", 1),
238 static SERIALSUBTYPE xDigitizerII[] =
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),
247 static SERIALSUBTYPE xPenPartner[] =
249 WACOM_SUBTYPE("CT-0405-R", "Wacom PenPartner", 1),
253 static SERIALSUBTYPE xGraphire[] =
255 WACOM_SUBTYPE("ET-0405-R", "Wacom Graphire", 1),
259 static SERIALSUBTYPE xIntuos[] =
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),
269 static SERIALSUBTYPE xIntuos2[] =
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),
279 static SERIALSUBTYPE xCintiq[] =
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),
292 static SERIALDEVICE xWacomDevices[] =
294 WACOM_DEVICE_P4("art", "ArtPad", WACOMDEVICE_ARTPAD,
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),
315 /* This one is reverse engineered at this point */
316 static SERIALSUBTYPE xTabletPC[] =
318 TPC_SUBTYPE("tpc", "Tablet PC Screen", 1),
322 static SERIALDEVICE xtpcDevices[] =
324 TPC_DEVICE("tpc", "TabletPC", WACOMDEVICE_TPC,
325 xTabletPC, TABLETPC_CAPS),
329 static SERIALVENDOR xWacomVendor =
330 { "wacom", "Wacom", WACOMVENDOR_WACOM, xWacomDevices };
332 static SERIALVENDOR xtpcVendor =
333 { "Wacom", "Wacom", WACOMVENDOR_TPC, xtpcDevices };
335 static SERIALVENDOR* xVendors[] =
342 /*****************************************************************************
344 *****************************************************************************/
346 static int SerialSendReset(SERIALTABLET* pSerial);
347 static int SerialSendStop(SERIALTABLET* pSerial);
348 static int SerialSendStart(SERIALTABLET* pSerial);
350 static int SerialSend(SERIALTABLET* pSerial, const char* pszData);
351 static int SerialSendRaw(SERIALTABLET* pSerial, const void* pvData,
353 static int WacomFlush(SERIALTABLET* pSerial);
354 static int SerialSendRequest(SERIALTABLET* pSerial, const char* pszRequest,
355 char* pchResponse, unsigned int uSize);
357 /*****************************************************************************
359 *****************************************************************************/
363 void (*pfnFree)(void* pv);
366 static void SerialFreeDeviceList(void* pv)
368 DEVLIST_INTERNAL* pInt = ((DEVLIST_INTERNAL*)pv) - 1;
372 int WacomGetSupportedSerialDeviceList(WACOMDEVICEREC** ppList, int* pnSize)
374 int nIndex=0, nCnt=0;
375 DEVLIST_INTERNAL* pInt;
377 SERIALVENDOR** ppVendor;
378 WACOMDEVICEREC* pRec;
380 if (!ppList || !pnSize) { errno = EINVAL; return 1; }
382 /* for each vendor, count up devices */
383 for (ppVendor=xVendors; *ppVendor; ++ppVendor)
385 /* count up devices */
386 for (pDev=(*ppVendor)->pDevices; pDev->pszName; ++pDev, ++nCnt) ;
389 /* allocate enough memory to hold internal structure and all records */
390 pInt = (DEVLIST_INTERNAL*)malloc(sizeof(DEVLIST_INTERNAL) +
391 (sizeof(WACOMDEVICEREC) * nCnt));
393 pInt->pfnFree = SerialFreeDeviceList;
394 pRec = (WACOMDEVICEREC*)(pInt + 1);
396 /* for each vendor, add devices */
397 for (ppVendor=xVendors; *ppVendor; ++ppVendor)
399 for (pDev=(*ppVendor)->pDevices; pDev->pszName; ++pDev, ++nIndex)
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;
412 assert(nIndex == nCnt);
419 unsigned int WacomGetSerialDeviceFromName(const char* pszName)
422 SERIALVENDOR** ppVendor;
424 if (!pszName) { errno = EINVAL; return 0; }
426 /* for each vendor, look for device */
427 for (ppVendor=xVendors; *ppVendor; ++ppVendor)
429 /* count up devices */
430 for (pDev=(*ppVendor)->pDevices; pDev->pszName; ++pDev)
432 if (strcasecmp(pszName,pDev->pszName) == 0)
433 return pDev->uDevice;
441 static int SerialFindModel(WACOMMODEL* pModel, SERIALVENDOR** ppVendor,
442 SERIALDEVICE** ppDevice, SERIALSUBTYPE** ppSubType)
444 SERIALVENDOR** ppPos;
448 /* device type must be specified */
450 { errno = EINVAL; return 1; }
452 /* no device specified, nothing found. */
453 if (!pModel->uDevice)
461 /* for each vendor */
462 for (ppPos=xVendors; *ppPos; ++ppPos)
465 if (!pModel->uVendor || (pModel->uVendor == (*ppPos)->uVendor))
467 /* for each device */
468 for (pDev=(*ppPos)->pDevices; pDev->pszName; ++pDev)
470 /* if device matches */
471 if (pModel->uDevice == pDev->uDevice)
473 /* no subtype specified, use it */
474 if (!pModel->uSubType)
482 /* for each subtype */
483 for (pSub=pDev->pSubTypes; pSub->pszName; ++pSub)
485 /* if subtype matches */
486 if (pModel->uSubType == pSub->uSubType)
495 /* wrong subtype? maybe try another vendor */
496 if (!pModel->uVendor) break;
498 /* otherwise, no match. */
504 /* if vendor matches, but device does not, no match. */
518 WACOMTABLET WacomOpenSerialTablet(WACOMENGINE hEngine, int fd,
521 SERIALTABLET* pSerial = NULL;
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;
540 pSerial->hEngine = hEngine;
542 pSerial->state.uValueCnt = WACOMFIELD_MAX;
544 /* remember what model was request */
546 pSerial->modelRequested = *pModel;
548 if (SerialReset(pSerial,pModel))
554 return (WACOMTABLET)pSerial;
557 static int SerialReset(SERIALTABLET* pSerial, WACOMMODEL* pModel)
559 SERIALVENDOR* pVendor = NULL;
560 SERIALDEVICE* pDevice = NULL;
561 SERIALSUBTYPE* pSubType = NULL;
563 /* If model is specified, break it down into vendor, device, and subtype */
564 if (pModel && SerialFindModel(pModel,&pVendor,&pDevice,&pSubType))
567 /* Set the tablet device */
568 if (SerialSetDevice(pSerial,pVendor,pDevice,pSubType))
571 /* configure the TTY for initial operation */
572 if (SerialConfigTTY(pSerial))
575 /* Identify the tablet */
576 if (!pSerial->pfnIdent || pSerial->pfnIdent(pSerial))
579 /* Initialize the tablet */
580 if (!pSerial->pfnInit || pSerial->pfnInit(pSerial))
584 SerialSendStart(pSerial);
589 /*****************************************************************************
590 ** Serial Tablet Functions
591 *****************************************************************************/
593 static int SerialConfigTTY(SERIALTABLET* pSerial)
596 int nBaudRate = 9600;
599 if (isatty(pSerial->fd))
601 /* set up default port parameters */
602 if (tcgetattr (pSerial->fd, &tios))
604 SerialError(pSerial,"Failed to get port params: %s",
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 */
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 */
622 if (tcsetattr (pSerial->fd, TCSANOW, &tios))
624 SerialError(pSerial,"Failed to set port params: %s",
629 /* get minumum baud rate for given device, if specified */
630 if (pSerial->pDevice)
631 nBaudRate = pSerial->pDevice->nMinBaudRate;
633 /* set 38400 baud and reset */
634 if (SerialResetAtBaud(pSerial,&tios,38400))
637 /* if valid, set 19200 baud and reset */
638 if ((nBaudRate <= 19200) && (SerialResetAtBaud(pSerial,&tios,19200)))
641 /* if valid, set 9600 baud and reset */
642 if ((nBaudRate <= 9600) && (SerialResetAtBaud(pSerial,&tios,9600)))
645 /* lower than 9600 baud? for testing, maybe */
646 if ((nBaudRate < 9600) && (SerialResetAtBaud(pSerial,&tios,nBaudRate)))
651 if (SerialSendReset(pSerial)) return 1;
655 if (SerialSendStop(pSerial) || WacomFlush(pSerial))
662 static int SerialSetDevice(SERIALTABLET* pSerial, SERIALVENDOR* pVendor,
663 SERIALDEVICE* pDevice, SERIALSUBTYPE* pSubType)
665 pSerial->pVendor = pVendor;
666 pSerial->pDevice = pDevice;
667 pSerial->pSubType = pSubType;
669 /* if we know the device, use its functions */
670 if (pSerial->pDevice)
672 pSerial->pfnIdent = pSerial->pDevice->pfnIdent;
673 if (!pSerial->pfnIdent) { errno = EPERM; return 1; }
676 pSerial->pfnIdent = SerialIdentDefault;
681 static int SerialIdentDefault(SERIALTABLET* pSerial)
683 return SerialIdentWacom(pSerial);
686 static int SerialIdentWacom(SERIALTABLET* pSerial)
689 SERIALVENDOR* pVendor = &xWacomVendor;
694 /* send wacom identification request */
695 if (SerialSendRequest(pSerial,"~#\r",chResp,sizeof(chResp)))
697 if (errno != ETIMEDOUT) return 1;
699 /* try again, sometimes the first one gets garbled */
700 if (SerialSendRequest(pSerial,"~#\r",chResp,sizeof(chResp)))
704 /* look through device table for information */
705 for (pDev=pVendor->pDevices; pDev->pszName; ++pDev)
707 for (pSub=pDev->pSubTypes; pSub && pSub->pszName; ++pSub)
709 if (strncmp(chResp,pSub->pszIdent, strlen(pSub->pszIdent)) == 0)
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;
719 /* get version number */
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)
726 pSerial->nVerRelease = 0;
727 if (sscanf(pszPos,"%d.%d",&pSerial->nVerMajor,
728 &pSerial->nVerMinor) != 2)
731 SerialError(pSerial,"bad version number: %s",pszPos);
740 SerialError(pSerial,"UNIDENTIFIED TABLET: %s",chResp);
744 static int SerialInitWacom(SERIALTABLET* pSerial)
748 /* Request tablet dimensions */
749 if (SerialSendRequest(pSerial,"~C\r",chResp,sizeof(chResp)))
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)
758 SerialError(pSerial,"Bad dimension response [%s]",chResp);
762 /* tablet specific initialization */
763 switch (pSerial->pDevice->uDevice)
765 case WACOMDEVICE_PENPARTNER:
767 SerialSend(pSerial, "PH1\r");
770 case WACOMDEVICE_INTUOS:
771 case WACOMDEVICE_INTUOS2:
772 /* multi-mode, max-rate */
773 SerialSend(pSerial, "MT1\rID1\rIT0\r");
776 if (pSerial->pDevice->nProtocol == PROTOCOL_4)
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) */
782 /* if (SerialSend(pSerial->fd, "MU1\rOC1\r~M0\r~M1\rIT0\rIN0\rSR\rZF1\r"))
786 if (pSerial->nVerMajor == 1)
788 if (pSerial->nVerMinor >= 4)
790 /* enable tilt mode */
791 if (SerialSend(pSerial,"FM1\r")) return 1;
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;
801 else if (pSerial->nVerMinor == 3)
803 pSerial->pfnParse = SerialParseWacomIV_1_3;
804 pSerial->state.values[WACOMFIELD_PRESSURE].nMax = 255;
806 else if (pSerial->nVerMinor == 2)
808 pSerial->pfnParse = SerialParseWacomIV_1_2;
809 pSerial->state.values[WACOMFIELD_PRESSURE].nMax = 255;
811 else if (pSerial->nVerMinor < 2)
813 pSerial->pfnParse = SerialParseWacomIV_1_2;
814 pSerial->state.values[WACOMFIELD_PRESSURE].nMax = 120;
818 else if (pSerial->pDevice->nProtocol == PROTOCOL_5)
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;
832 else { errno=EINVAL; return 1; }
838 static int SerialIdentTabletPC(SERIALTABLET* pSerial)
841 if ((pSerial->pVendor != &xtpcVendor) ||
842 (pSerial->pDevice == NULL)) { return EPERM; return 1; }
845 pSerial->pSubType = pSerial->pDevice->pSubTypes;
847 /* sanity check again */
848 if (pSerial->pSubType->pszName == NULL) { return EPERM; return 1; }
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;
860 static int SerialInitTabletPC(SERIALTABLET* pSerial)
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;
869 static int SerialParseWacomV(SERIALTABLET* pSerial,
870 const unsigned char* puchData, unsigned int uLength,
873 int x=0, y=0, rot=0, tiltx=0, tilty=0, wheel=0,
874 tool=WACOMTOOLTYPE_NONE, button=0, press=0, throttle=0,
878 * Supports: 1024 pressure, eraser, 2 side-switch, tilt, throttle, wheel
879 * Limitation: no tilt */
881 if (uLength != 9) { errno=EINVAL; return 1; }
884 if ((puchData[0] & 0xFC) == 0xC0)
886 int toolid = (((int)puchData[1]&0x7F) << 5) |
887 (((int)puchData[2]&0x7C) >> 2);
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));
898 case 0x812: /* Intuos2 ink pen XP-110-00A */
899 case 0x012: /* Inking pen */
900 tool = WACOMTOOLTYPE_PENCIL; break;
902 case 0x822: /* Intuos Pen GP-300E-01H */
903 case 0x852: /* Intuos2 Grip Pen XP-501E-00A */
904 case 0x842: /* added from Cheng */
906 tool = WACOMTOOLTYPE_PEN; break;
908 case 0x832: /* Intuos2 stroke pen XP-120-00A */
909 case 0x032: /* Stroke pen */
910 tool = WACOMTOOLTYPE_BRUSH; break;
912 case 0x007: /* 2D Mouse */
913 case 0x09C: /* ?? Mouse */
914 case 0x094: /* 4D Mouse */
915 tool = WACOMTOOLTYPE_MOUSE; break;
917 case 0x096: /* Lens cursor */
918 tool = WACOMTOOLTYPE_LENS; break;
923 case 0x0fa: /* Eraser */
924 tool = WACOMTOOLTYPE_ERASER; break;
926 case 0x112: /* Airbrush */
927 tool = WACOMTOOLTYPE_AIRBRUSH; break;
929 default: /* Unknown tool */
930 tool = WACOMTOOLTYPE_PEN; break;
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;
941 if ((puchData[0] & 0xFE) == 0x80)
943 pSerial->nToolID = 0;
944 memset(&pSerial->state.values, 0,
945 pSerial->state.uValueCnt * sizeof(WACOMVALUE));
946 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
950 if (((puchData[0] & 0xB8) == 0xA0) || ((puchData[0] & 0xBE) == 0xB4))
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;
964 if ((puchData[0] & 0xB8) == 0xA0)
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;
972 /* 2nd airbrush packet */
975 wheel = ((((int)puchData[5] & 0x07) << 7) |
976 ((int)puchData[6] & 0x7f));
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;
990 if (((puchData[0] & 0xBE) == 0xA8) || ((puchData[0] & 0xBE) == 0xB0))
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;
1002 if (pSerial->nToolID == 0x094)
1004 button = (((puchData[8] & 0x70) >> 1) | (puchData[8] & 0x07));
1007 else if (pSerial->nToolID == 0x096)
1009 button = puchData[8] & 0x1F;
1014 button = (puchData[8] & 0x1C) >> 2;
1015 wheel = - (puchData[8] & 1) + ((puchData[8] & 2) >> 1);
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;
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;
1035 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
1038 /* 2nd 4D mouse packet */
1039 if ((puchData[0] & 0xBE) == 0xAA)
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));
1051 if (rot < 900) rot = -rot;
1052 else rot = 1799 - rot;
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;
1064 static int SerialParseWacomIV_1_4(SERIALTABLET* pSerial,
1065 const unsigned char* puchData, unsigned int uLength,
1068 /* Wacom IV, Rom 1.4
1069 * Supports: 256 pressure, eraser, 2 side-switch, tilt */
1071 if ((uLength != 7) && (uLength != 9)) { errno=EINVAL; return 1; }
1073 if (SerialParseWacomIV_1_3(pSerial,puchData,7,pState))
1081 tiltx = puchData[7] & 0x3F;
1082 tilty = puchData[8] & 0x3F;
1083 if (puchData[7] & 0x40) tiltx -= 64;
1084 if (puchData[8] & 0x40) tilty -= 64;
1086 pSerial->state.values[WACOMFIELD_TILT_X].nValue = tiltx;
1087 pSerial->state.values[WACOMFIELD_TILT_Y].nValue = tilty;
1091 pState->values[WACOMFIELD_TILT_X].nValue = tiltx;
1092 pState->values[WACOMFIELD_TILT_Y].nValue = tilty;
1099 static int SerialParseWacomIV_1_3(SERIALTABLET* pSerial,
1100 const unsigned char* puchData, unsigned int uLength,
1103 int x=0, y=0, prox=0, tool=WACOMTOOLTYPE_NONE,
1104 button=0, press=0, stylus, eraser;
1106 /* Wacom IV, Rom 1.3 (ArtPadII)
1107 * Supports: 256 pressure, eraser, 2 side-switch
1108 * Limitation: no tilt */
1110 if (uLength != 7) { errno=EINVAL; return 1; }
1112 prox = puchData[0] & 0x40 ? 1 : 0;
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;
1122 /* if entering proximity, choose eraser or stylus2 for bit */
1123 if (pSerial->state.values[WACOMFIELD_PROXIMITY].nValue == 0)
1125 if (eraser) tool = WACOMTOOLTYPE_ERASER;
1126 else tool = WACOMTOOLTYPE_PEN;
1129 /* otherwise, keep the last tool */
1130 else tool = pSerial->state.values[WACOMFIELD_TOOLTYPE].nValue;
1132 button = (press > 10) ? BIT(WACOMBUTTON_TOUCH) : 0;
1134 /* pen has 2 side-switch, eraser has none */
1135 if (tool == WACOMTOOLTYPE_PEN)
1137 button |= (puchData[3] & 0x10) ?
1138 BIT(WACOMBUTTON_STYLUS) : 0;
1139 button |= (eraser) ? BIT(WACOMBUTTON_STYLUS2) : 0;
1144 tool = WACOMTOOLTYPE_MOUSE;
1145 button = (puchData[3] & 0x78) >> 3; /* not tested */
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);
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;
1162 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
1165 static int SerialParseWacomIV_1_2(SERIALTABLET* pSerial,
1166 const unsigned char* puchData, unsigned int uLength,
1169 int x=0, y=0, prox=0, tool=0, button=WACOMTOOLTYPE_NONE,
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 */
1176 if (uLength != 7) { errno=EINVAL; return 1; }
1178 prox = puchData[0] & 0x40 ? 1 : 0;
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);
1186 press = (puchData[6] & 0x3F) + ((puchData[6] & 0x40) ? 0 : 64);
1190 tool = WACOMTOOLTYPE_PEN;
1191 button = (press > 10) ? BIT(WACOMBUTTON_TOUCH) : 0;
1192 button |= (puchData[3] & 0x10) ? BIT(WACOMBUTTON_STYLUS) : 0;
1196 tool = WACOMTOOLTYPE_MOUSE;
1197 button = (puchData[3] & 0x78) >> 3; /* not tested */
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);
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;
1214 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
1217 static int SerialParseTabletPC(SERIALTABLET* pSerial,
1218 const unsigned char* puchData, unsigned int uLength,
1221 int x=0, y=0, prox=0, tool=WACOMTOOLTYPE_NONE,
1222 button=0, press=0, eraser;
1224 /* Tablet PC Supports: 256 pressure, eraser, 1/2 side-switch */
1226 if (uLength != 9) { errno=EINVAL; return 1; }
1228 prox = puchData[0] & 0x20 ? 1 : 0;
1231 eraser = (puchData[0] & 0x04) ? 1 : 0;
1232 press = ((puchData[6] & 0x01) << 7) | (puchData[5] & 0x7F);
1234 /* tools are distinguishable */
1235 if (eraser) tool = WACOMTOOLTYPE_ERASER;
1236 else tool = WACOMTOOLTYPE_PEN;
1238 button = (puchData[0] & 0x01) ? BIT(WACOMBUTTON_TOUCH) : 0;
1240 /* pen has side-switch(es), eraser has none */
1241 if (tool == WACOMTOOLTYPE_PEN)
1243 button |= (puchData[0] & 0x02) ?
1244 BIT(WACOMBUTTON_STYLUS) : 0;
1245 button |= (puchData[0] & 0x04) ?
1246 BIT(WACOMBUTTON_STYLUS2) : 0;
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);
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;
1265 return pState ? WacomCopyState(pState,&pSerial->state) : 0;
1270 /*****************************************************************************
1271 ** Internal Functions
1272 *****************************************************************************/
1274 static int SerialSendReset(SERIALTABLET* pSerial)
1276 SerialInfo(pSerial,"Sending reset");
1278 /* reset to Wacom II-S command set, and factory defaults */
1279 if (SerialSend(pSerial,"\r$\r")) return 1;
1280 usleep(250000); /* 250 milliseconds */
1282 /* reset tablet to Wacom IV command set */
1283 if (SerialSend(pSerial,"#\r")) return 1;
1284 usleep(75000); /* 75 milliseconds */
1289 static int SerialSendStop(SERIALTABLET* pSerial)
1291 if (SerialSend(pSerial,"\rSP\r")) return 1;
1296 static int SerialSendStart(SERIALTABLET* pSerial)
1298 return SerialSend(pSerial,"ST\r");
1301 static int SerialSend(SERIALTABLET* pSerial, const char* pszMsg)
1303 return SerialSendRaw(pSerial,pszMsg,(unsigned)strlen(pszMsg));
1306 static int SerialSendRaw(SERIALTABLET* pSerial, const void* pvData,
1310 unsigned int uCnt=0;
1311 unsigned char* puchData = (unsigned char*)pvData;
1313 while (uCnt < uSize)
1315 nXfer = write(pSerial->fd,puchData+uCnt,uSize-uCnt);
1318 SerialError(pSerial,"Failed to write to port: %s",strerror(errno));
1327 static int WacomFlush(SERIALTABLET* pSerial)
1331 struct timeval timeout;
1333 if (tcflush(pSerial->fd, TCIFLUSH) == 0)
1337 timeout.tv_usec = 0;
1342 FD_SET(pSerial->fd, &fdsRead);
1343 if (select(FD_SETSIZE,&fdsRead,NULL,NULL,&timeout) <= 0)
1345 read(pSerial->fd,&ch,sizeof(ch));
1351 static int SerialSendRequest(SERIALTABLET* pSerial, const char* pszRequest,
1352 char* pchResponse, unsigned int uSize)
1356 unsigned int uLen, uCnt;
1357 struct timeval timeout;
1359 uLen = strlen(pszRequest);
1360 if (SerialSendRaw(pSerial,pszRequest,uLen)) return 1;
1366 SerialError(pSerial,"Invalid size to SerialSendRequest: %u < %u",
1371 /* read until first header character */
1375 timeout.tv_usec = 500000;
1378 FD_SET(pSerial->fd, &fdsRead);
1379 if (select(FD_SETSIZE,&fdsRead,NULL,NULL,&timeout) <= 0)
1385 nXfer = read(pSerial->fd,pchResponse,1);
1388 SerialError(pSerial,"Truncated response header");
1391 if (*pchResponse == *pszRequest) break;
1392 SerialWarn(pSerial,"Discarding %02X", *((unsigned char*)pchResponse));
1395 /* read response header */
1396 for (uCnt=1; uCnt<uLen; uCnt+=nXfer)
1398 nXfer = read(pSerial->fd,pchResponse+uCnt,uLen-uCnt);
1401 SerialError(pSerial,"Truncated response header (2)");
1406 /* check the header */
1407 if (strncmp(pszRequest,pchResponse,uLen) != 0)
1409 SerialError(pSerial,"Incorrect response [%s,%s]",
1410 pszRequest,pchResponse);
1414 /* get the rest of the response */
1415 for (uCnt=0; uCnt<uSize; ++uCnt)
1417 nXfer = read(pSerial->fd,pchResponse+uCnt,1);
1420 SerialError(pSerial,"Failed to read response: %s",strerror(errno));
1425 if (pchResponse[uCnt] == '\r')
1427 pchResponse[uCnt] = '\0';
1433 SerialError(pSerial,"Invalid response");
1437 /*****************************************************************************
1438 ** Virtual Functions
1439 *****************************************************************************/
1441 static void SerialClose(WACOMTABLET_PRIV* pTablet)
1443 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1448 static WACOMMODEL SerialGetModel(WACOMTABLET_PRIV* pTablet)
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;
1459 static const char* SerialGetVendorName(WACOMTABLET_PRIV* pTablet)
1461 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1462 return pSerial->pVendor->pszDesc;
1465 static const char* SerialGetClassName(WACOMTABLET_PRIV* pTablet)
1470 static const char* SerialGetDeviceName(WACOMTABLET_PRIV* pTablet)
1472 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1473 return pSerial->pDevice->pszDesc;
1476 static const char* SerialGetSubTypeName(WACOMTABLET_PRIV* pTablet)
1478 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1479 return pSerial->pSubType->pszName;
1482 static const char* SerialGetModelName(WACOMTABLET_PRIV* pTablet)
1484 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1485 return pSerial->pSubType->pszDesc;
1488 static int SerialGetROMVer(WACOMTABLET_PRIV* pTablet, int* pnMajor,
1489 int* pnMinor, int* pnRelease)
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;
1499 static int SerialGetCaps(WACOMTABLET_PRIV* pTablet)
1501 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1502 return pSerial->pDevice->uCaps;
1505 static int SerialGetState(WACOMTABLET_PRIV* pTablet, WACOMSTATE* pState)
1507 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1508 return WacomCopyState(pState,&pSerial->state);
1511 static int SerialGetFD(WACOMTABLET_PRIV* pTablet)
1513 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1517 static int SerialReadRaw(WACOMTABLET_PRIV* pTablet, unsigned char* puchData,
1522 unsigned char* pPos, *pEnd;
1523 struct timeval timeout;
1524 unsigned int uCnt, uPacketLength;
1525 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1527 if (!pSerial) { errno=EBADF; return 0; }
1528 uPacketLength = pSerial->uPacketLength;
1530 /* check size of buffer */
1531 if (uSize < uPacketLength) { errno=EINVAL; return 0; }
1533 /* check for errors, reset after 3 */
1534 if (pSerial->nBitErrors > 3)
1536 pSerial->nBitErrors = 0;
1537 SerialWarn(pSerial,"Resetting tablet due to bit errors");
1538 (void)SerialReset(pSerial,&pSerial->modelRequested);
1542 timeout.tv_usec = 500000; /* 0.5 seconds for now */
1544 for (uCnt=0; uCnt<uPacketLength; uCnt+=nXfer)
1547 FD_SET(pSerial->fd, &fdsRead);
1548 if (select(FD_SETSIZE,&fdsRead,NULL,NULL,&timeout) <= 0)
1551 nXfer = read(pSerial->fd,puchData+uCnt,uPacketLength-uCnt);
1552 if (nXfer <= 0) return nXfer;
1554 /* look for high-bit */
1555 pEnd = puchData + nXfer;
1556 for (pPos=puchData; pPos<pEnd; ++pPos)
1558 if (*pPos & 0x80) break;
1561 /* not where it was expected? fix it. */
1562 if (pPos != puchData)
1564 ++pSerial->nBitErrors;
1565 SerialWarn(pSerial,"Bad high bit, discarding %d bytes",
1568 /* copy remaining bytes down, if any */
1569 memmove(puchData,pPos,(nXfer - (pPos-puchData)));
1570 nXfer -= pPos - puchData;
1574 if (uCnt < uPacketLength)
1580 return (signed)uCnt;
1583 static int SerialParseData(WACOMTABLET_PRIV* pTablet,
1584 const unsigned char* puchData, unsigned int uLength,
1588 SERIALTABLET* pSerial = (SERIALTABLET*)pTablet;
1589 if (!pSerial) { errno=EBADF; return 1; }
1591 /* check synchronization */
1592 if (!(puchData[0] & 0x80))
1594 ++pSerial->nBitErrors;
1595 SerialError(pSerial,"HIBIT FAIL");
1599 for (i=1; i<uLength; ++i)
1601 if (puchData[i] & 0x80)
1603 ++pSerial->nBitErrors;
1604 SerialError(pSerial,"LOBIT FAIL");
1605 SerialDump(pSerial,puchData,uLength);
1611 /* reset bit error count */
1612 pSerial->nBitErrors = 0;
1614 /* dispatch to parser */
1615 if (pSerial->pfnParse)
1616 return (*pSerial->pfnParse)(pSerial,puchData,uLength,pState);
1622 static int SerialResetAtBaud(SERIALTABLET* pSerial, struct termios* pTIOS,
1625 /* conver baud rate to tios macro */
1626 int baudRate = B9600;
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 */
1637 SerialInfo(pSerial,"Setting baud rate to %d",nBaud);
1639 /* change baud rate */
1640 cfsetispeed(pTIOS, baudRate);
1641 cfsetospeed(pTIOS, baudRate);
1642 if (tcsetattr (pSerial->fd, TCSANOW, pTIOS))
1645 /* send reset command */
1646 return SerialSendReset(pSerial);
1649 /*****************************************************************************
1651 *****************************************************************************/
1653 #define SERIALLOG(l) do { \
1655 va_start(a,pszFmt); \
1656 WacomLogV(pSerial->hEngine,l,pszFmt,a); \
1657 va_end(a); } while (0)
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); }
1666 static void SerialDump(SERIALTABLET* pSerial, const void* pvData, int nCnt)
1669 const unsigned char* pData = (const unsigned char*)pvData;
1671 unsigned int uAddr = 0;
1677 for (i=0; i<16; ++i)
1680 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos,
1683 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos,
1686 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos," - ");
1687 for (i=0; i<16; ++i)
1690 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos,
1691 "%c",isprint(pData[i]) ? pData[i] : '.');
1693 nPos += snprintf(chLine+nPos,sizeof(chLine)-nPos,
1697 WacomLog(pSerial->hEngine,WACOMLOGLEVEL_DEBUG,"%04X: %s",uAddr,chLine);
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); }