1 /*****************************************************************************
4 ** Copyright (C) 2002 - 2003 - John E. Joganic
5 ** Copyright (C) 2004 - 2005 - 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 "wactablet.h"
24 #include "wacserial.h"
36 #ifdef WCM_ENABLE_LINUXINPUT
37 #include <linux/input.h>
40 typedef void (*FREEFUNC)(void* pv);
49 WACOMDEVICEREC* pSerialList;
50 WACOMDEVICEREC* pUSBList;
52 } DEVICELIST_INTERNAL;
54 typedef struct _ENGINE_PRIV ENGINE_PRIV;
63 /*****************************************************************************
65 *****************************************************************************/
67 WACOMENGINE WacomInitEngine(void)
69 ENGINE_PRIV* pEngine = NULL;
70 pEngine = (ENGINE_PRIV*)malloc(sizeof(ENGINE_PRIV));
71 memset(pEngine,0,sizeof(*pEngine));
72 pEngine->level = WACOMLOGLEVEL_WARN;
73 return (WACOMENGINE)pEngine;
76 void WacomTermEngine(WACOMENGINE hEngine)
78 ENGINE_PRIV* pEngine = (ENGINE_PRIV*)hEngine;
84 void WacomSetLogFunc(WACOMENGINE hEngine, WACOMLOGFUNC pfnLog)
86 ENGINE_PRIV* pEngine = (ENGINE_PRIV*)hEngine;
88 pEngine->pfnLog = pfnLog;
91 void WacomSetLogLevel(WACOMENGINE hEngine, WACOMLOGLEVEL level)
93 ENGINE_PRIV* pEngine = (ENGINE_PRIV*)hEngine;
96 if (level < WACOMLOGLEVEL_CRITICAL)
97 level = WACOMLOGLEVEL_CRITICAL;
98 if (level > WACOMLOGLEVEL_TRACE)
99 level = WACOMLOGLEVEL_TRACE;
101 pEngine->level = level;
104 void WacomLogV(WACOMENGINE hEngine, WACOMLOGLEVEL level, const char* pszFmt,
108 ENGINE_PRIV* pEngine = (ENGINE_PRIV*)hEngine;
109 if (!pEngine || !pEngine->pfnLog || (pEngine->level < level)) return;
111 gettimeofday(&tv,NULL);
113 vsnprintf(pEngine->chLogBuf,sizeof(pEngine->chLogBuf),pszFmt,args);
114 pEngine->pfnLog(tv,level,pEngine->chLogBuf);
117 void WacomLog(WACOMENGINE hEngine, WACOMLOGLEVEL level, const char* pszFmt, ...)
120 va_start(args, pszFmt);
121 WacomLogV(hEngine,level,pszFmt,args);
125 static void FreeClassList(void* pv)
127 CLSLIST_INTERNAL* pInt = ((CLSLIST_INTERNAL*)pv) - 1;
131 int WacomGetSupportedClassList(WACOMCLASSREC** ppList, int* pnSize)
133 int nIndex=0, nCnt=0;
134 CLSLIST_INTERNAL* pInt;
137 if (!ppList || !pnSize) { errno = EINVAL; return 1; }
143 #ifdef WCM_ENABLE_LINUXINPUT
147 /* allocate enough memory to hold internal structure and all records */
148 pInt = (CLSLIST_INTERNAL*)malloc(sizeof(CLSLIST_INTERNAL) +
149 (sizeof(WACOMCLASSREC) * nCnt));
151 pInt->pfnFree = FreeClassList;
152 pRec = (WACOMCLASSREC*)(pInt + 1);
155 pRec[nIndex].pszName = "serial";
156 pRec[nIndex].pszDesc = "Serial TTY interface";
157 pRec[nIndex].uDeviceClass = WACOMCLASS_SERIAL;
161 #ifdef WCM_ENABLE_LINUXINPUT
162 pRec[nIndex].pszName = "usb";
163 pRec[nIndex].pszDesc = "Linux USB event interface";
164 pRec[nIndex].uDeviceClass = WACOMCLASS_USB;
168 assert(nIndex == nCnt);
174 static void FreeDeviceList(void* pv)
176 DEVICELIST_INTERNAL* pInt = ((DEVICELIST_INTERNAL*)pv) - 1;
177 WacomFreeList(pInt->pSerialList);
178 WacomFreeList(pInt->pUSBList);
182 int WacomGetSupportedDeviceList(unsigned int uDeviceClass,
183 WACOMDEVICEREC** ppList, int* pnSize)
185 int nSerialCnt=0, nUSBCnt=0, nTotalBytes;
186 WACOMDEVICEREC* pSerial=NULL, *pUSB=NULL, *pList;
187 DEVICELIST_INTERNAL* pInt;
189 if (!ppList || !pnSize) { errno = EINVAL; return 1; }
191 /* get serial list */
192 if (((!uDeviceClass) || (uDeviceClass == WACOMCLASS_SERIAL)) &&
193 WacomGetSupportedSerialDeviceList(&pSerial, &nSerialCnt)) return 1;
196 if (((!uDeviceClass) || (uDeviceClass == WACOMCLASS_USB)) &&
197 WacomGetSupportedUSBDeviceList(&pUSB, &nUSBCnt))
199 if (pSerial) WacomFreeList(pSerial);
203 /* need memory for duplicate records and list internal structure */
204 nTotalBytes = sizeof(WACOMDEVICEREC) * (nSerialCnt + nUSBCnt) +
205 sizeof(DEVICELIST_INTERNAL);
207 /* allocate memory */
208 pInt = (DEVICELIST_INTERNAL*)malloc(nTotalBytes);
210 /* copy initial list pointers */
211 pInt->pSerialList = pSerial;
212 pInt->pUSBList = pUSB;
213 pInt->pfnFree = FreeDeviceList;
216 pList = (WACOMDEVICEREC*)(pInt + 1);
218 memcpy(pList,pSerial,sizeof(WACOMDEVICEREC) * nSerialCnt);
220 memcpy(pList + nSerialCnt, pUSB, sizeof(WACOMDEVICEREC) * nUSBCnt);
223 *pnSize = nSerialCnt + nUSBCnt;
228 void WacomFreeList(void* pvList)
232 pfnFree = ((FREEFUNC*)pvList)[-1];
236 unsigned int WacomGetClassFromName(const char* pszName)
238 if (strcasecmp(pszName, "serial") == 0)
239 return WACOMCLASS_SERIAL;
240 else if (strcasecmp(pszName, "usb") == 0)
241 return WACOMCLASS_USB;
245 unsigned int WacomGetDeviceFromName(const char* pszName,
246 unsigned int uDeviceClass)
248 unsigned int uDeviceType = 0;
250 if (!uDeviceClass || (uDeviceClass == WACOMCLASS_SERIAL))
252 uDeviceType = WacomGetSerialDeviceFromName(pszName);
253 if (uDeviceType) return uDeviceType;
256 if (!uDeviceClass || (uDeviceClass == WACOMCLASS_USB))
258 uDeviceType = WacomGetUSBDeviceFromName(pszName);
259 if (uDeviceType) return uDeviceType;
266 static int WacomIsSerial(int fd)
271 static int WacomIsUSB(int fd)
273 #ifdef WCM_ENABLE_LINUXINPUT
275 if (ioctl(fd,EVIOCGID,sID) < 0) return 0;
282 WACOMTABLET WacomOpenTablet(WACOMENGINE hEngine, const char* pszDevice,
286 WACOMTABLET hTablet = NULL;
287 unsigned int uClass = pModel ? pModel->uClass : 0;
289 /* open device for read/write access */
290 fd = open(pszDevice,O_RDWR);
294 WacomLog(hEngine,WACOMLOGLEVEL_ERROR,"Failed to open %s: %s",
295 pszDevice, strerror(errno));
300 /* configure serial */
301 if ((!uClass || (uClass == WACOMCLASS_SERIAL)) && WacomIsSerial(fd))
303 hTablet = WacomOpenSerialTablet(hEngine,fd,pModel);
304 if (!hTablet) { e=errno; close(fd); errno=e; return NULL; }
308 else if ((!uClass || (uClass == WACOMCLASS_USB)) && WacomIsUSB(fd))
310 hTablet = WacomOpenUSBTablet(hEngine,fd,pModel);
311 if (!hTablet) { e=errno; close(fd); errno=e; return NULL; }
325 int WacomCopyState(WACOMSTATE* pDest, WACOMSTATE* pSrc)
328 if (!pSrc || !pDest || !pSrc->uValueCnt || !pDest->uValueCnt)
329 { errno=EINVAL; return 1; }
331 /* copy valid bits over */
332 pDest->uValid = pSrc->uValid;
334 /* determine how many values to transfer */
335 uCnt = (pDest->uValueCnt < pSrc->uValueCnt) ?
336 pDest->uValueCnt : pSrc->uValueCnt;
339 memcpy(pDest->values,pSrc->values,uCnt*sizeof(WACOMVALUE));
344 /*****************************************************************************
346 *****************************************************************************/
348 void WacomCloseTablet(WACOMTABLET hTablet)
350 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
351 if (!pTablet || !pTablet->Close) return;
352 pTablet->Close(pTablet);
355 WACOMMODEL WacomGetModel(WACOMTABLET hTablet)
357 WACOMMODEL xBadModel = { 0 };
358 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
359 if (!pTablet || !pTablet->GetModel) { errno=EBADF; return xBadModel; }
360 return pTablet->GetModel(pTablet);
363 const char* WacomGetVendorName(WACOMTABLET hTablet)
365 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
366 if (!pTablet || !pTablet->GetVendorName) { errno=EBADF; return NULL; }
367 return pTablet->GetVendorName(pTablet);
370 const char* WacomGetClassName(WACOMTABLET hTablet)
372 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
373 if (!pTablet || !pTablet->GetClassName) { errno=EBADF; return NULL; }
374 return pTablet->GetClassName(pTablet);
377 const char* WacomGetDeviceName(WACOMTABLET hTablet)
379 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
380 if (!pTablet || !pTablet->GetDeviceName) { errno=EBADF; return NULL; }
381 return pTablet->GetDeviceName(pTablet);
384 const char* WacomGetSubTypeName(WACOMTABLET hTablet)
386 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
387 if (!pTablet || !pTablet->GetSubTypeName) { errno=EBADF; return NULL; }
388 return pTablet->GetSubTypeName(pTablet);
391 const char* WacomGetModelName(WACOMTABLET hTablet)
393 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
394 if (!pTablet || !pTablet->GetModelName) { errno=EBADF; return NULL; }
395 return pTablet->GetModelName(pTablet);
398 int WacomGetROMVersion(WACOMTABLET hTablet, int* pnMajor, int* pnMinor,
401 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
402 if (!pTablet || !pTablet->GetROMVer) { errno=EBADF; return 0; }
403 return pTablet->GetROMVer(pTablet,pnMajor,pnMinor,pnRelease);
406 int WacomGetCapabilities(WACOMTABLET hTablet)
408 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
409 if (!pTablet || !pTablet->GetCaps) { errno=EBADF; return 0; }
410 return pTablet->GetCaps(pTablet);
413 int WacomGetState(WACOMTABLET hTablet, WACOMSTATE* pState)
415 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
416 if (!pTablet || !pTablet->GetState) { errno=EBADF; return 0; }
417 return pTablet->GetState(pTablet,pState);
420 int WacomGetFileDescriptor(WACOMTABLET hTablet)
422 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
423 if (!pTablet || !pTablet->GetFD) { errno=EBADF; return -1; }
424 return pTablet->GetFD(pTablet);
427 int WacomReadRaw(WACOMTABLET hTablet, unsigned char* puchData,
430 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
431 if (!pTablet || !pTablet->ReadRaw) { errno=EBADF; return 0; }
432 return pTablet->ReadRaw(pTablet,puchData,uSize);
435 int WacomParseData(WACOMTABLET hTablet, const unsigned char* puchData,
436 unsigned int uLength, WACOMSTATE* pState)
438 WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
439 if (!pTablet || !pTablet->ParseData) { errno=EBADF; return 0; }
440 return pTablet->ParseData(pTablet,puchData,uLength,pState);