OSDN Git Service

init: Fix sensors never detected when not available at first boot
[android-x86/device-generic-common.git] / wacom / wactablet.c
1 /*****************************************************************************
2 ** wactablet.c
3 **
4 ** Copyright (C) 2002 - 2003 - John E. Joganic
5 ** Copyright (C) 2004 - 2005 - 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 "wactablet.h"
24 #include "wacserial.h"
25 #include "wacusb.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <memory.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <assert.h>
34 #include <stdarg.h>
35
36 #ifdef WCM_ENABLE_LINUXINPUT
37 #include <linux/input.h>
38 #endif
39
40 typedef void (*FREEFUNC)(void* pv);
41
42 typedef struct
43 {
44         FREEFUNC pfnFree;
45 } CLSLIST_INTERNAL;
46
47 typedef struct
48 {
49         WACOMDEVICEREC* pSerialList;
50         WACOMDEVICEREC* pUSBList;
51         FREEFUNC pfnFree;
52 } DEVICELIST_INTERNAL;
53
54 typedef struct _ENGINE_PRIV ENGINE_PRIV;
55
56 struct _ENGINE_PRIV
57 {
58         WACOMLOGFUNC pfnLog;
59         WACOMLOGLEVEL level;
60         char chLogBuf[1024];
61 };
62
63 /*****************************************************************************
64 ** Implementation
65 *****************************************************************************/
66
67 WACOMENGINE WacomInitEngine(void)
68 {
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;
74 }
75
76 void WacomTermEngine(WACOMENGINE hEngine)
77 {
78         ENGINE_PRIV* pEngine = (ENGINE_PRIV*)hEngine;
79         if (!pEngine) return;
80
81         free(pEngine);
82 }
83
84 void WacomSetLogFunc(WACOMENGINE hEngine, WACOMLOGFUNC pfnLog)
85 {
86         ENGINE_PRIV* pEngine = (ENGINE_PRIV*)hEngine;
87         if (!pEngine) return;
88         pEngine->pfnLog = pfnLog;
89 }
90
91 void WacomSetLogLevel(WACOMENGINE hEngine, WACOMLOGLEVEL level)
92 {
93         ENGINE_PRIV* pEngine = (ENGINE_PRIV*)hEngine;
94         if (!pEngine) return;
95
96         if (level < WACOMLOGLEVEL_CRITICAL)
97                 level = WACOMLOGLEVEL_CRITICAL;
98         if (level > WACOMLOGLEVEL_TRACE)
99                 level = WACOMLOGLEVEL_TRACE;
100
101         pEngine->level = level;
102 }
103
104 void WacomLogV(WACOMENGINE hEngine, WACOMLOGLEVEL level, const char* pszFmt,
105         va_list args)
106 {
107         struct timeval tv;
108         ENGINE_PRIV* pEngine = (ENGINE_PRIV*)hEngine;
109         if (!pEngine || !pEngine->pfnLog || (pEngine->level < level)) return;
110
111         gettimeofday(&tv,NULL);
112
113         vsnprintf(pEngine->chLogBuf,sizeof(pEngine->chLogBuf),pszFmt,args);
114         pEngine->pfnLog(tv,level,pEngine->chLogBuf);
115 }
116
117 void WacomLog(WACOMENGINE hEngine, WACOMLOGLEVEL level, const char* pszFmt, ...)
118 {
119         va_list args;
120         va_start(args, pszFmt);
121         WacomLogV(hEngine,level,pszFmt,args);
122         va_end(args);
123 }
124
125 static void FreeClassList(void* pv)
126 {
127         CLSLIST_INTERNAL* pInt = ((CLSLIST_INTERNAL*)pv) - 1;
128         free(pInt);
129 }
130
131 int WacomGetSupportedClassList(WACOMCLASSREC** ppList, int* pnSize)
132 {
133         int nIndex=0, nCnt=0;
134         CLSLIST_INTERNAL* pInt;
135         WACOMCLASSREC* pRec;
136
137         if (!ppList || !pnSize) { errno = EINVAL; return 1; }
138
139         /* serial */
140         ++nCnt;
141
142         /* USB */
143         #ifdef WCM_ENABLE_LINUXINPUT
144         ++nCnt;
145         #endif
146
147         /* allocate enough memory to hold internal structure and all records */
148         pInt = (CLSLIST_INTERNAL*)malloc(sizeof(CLSLIST_INTERNAL) +
149                                         (sizeof(WACOMCLASSREC) * nCnt));
150
151         pInt->pfnFree = FreeClassList;
152         pRec = (WACOMCLASSREC*)(pInt + 1);
153
154         /* serial */
155         pRec[nIndex].pszName = "serial";
156         pRec[nIndex].pszDesc = "Serial TTY interface";
157         pRec[nIndex].uDeviceClass = WACOMCLASS_SERIAL;
158         ++nIndex;
159
160         /* USB */
161         #ifdef WCM_ENABLE_LINUXINPUT
162         pRec[nIndex].pszName = "usb";
163         pRec[nIndex].pszDesc = "Linux USB event interface";
164         pRec[nIndex].uDeviceClass = WACOMCLASS_USB;
165         ++nIndex;
166         #endif
167
168         assert(nIndex == nCnt);
169         *ppList = pRec;
170         *pnSize = nCnt;
171         return 0;
172 }
173
174 static void FreeDeviceList(void* pv)
175 {
176         DEVICELIST_INTERNAL* pInt = ((DEVICELIST_INTERNAL*)pv) - 1;
177         WacomFreeList(pInt->pSerialList);
178         WacomFreeList(pInt->pUSBList);
179         free(pInt);
180 }
181
182 int WacomGetSupportedDeviceList(unsigned int uDeviceClass,
183                 WACOMDEVICEREC** ppList, int* pnSize)
184 {
185         int nSerialCnt=0, nUSBCnt=0, nTotalBytes;
186         WACOMDEVICEREC* pSerial=NULL, *pUSB=NULL, *pList;
187         DEVICELIST_INTERNAL* pInt;
188
189         if (!ppList || !pnSize) { errno = EINVAL; return 1; }
190
191         /* get serial list */
192         if (((!uDeviceClass) || (uDeviceClass == WACOMCLASS_SERIAL)) &&
193                 WacomGetSupportedSerialDeviceList(&pSerial, &nSerialCnt)) return 1;
194
195         /* get usb list */
196         if (((!uDeviceClass) || (uDeviceClass == WACOMCLASS_USB)) &&
197                 WacomGetSupportedUSBDeviceList(&pUSB, &nUSBCnt))
198         {
199                 if (pSerial) WacomFreeList(pSerial);
200                 return 1;
201         }
202
203         /* need memory for duplicate records and list internal structure */
204         nTotalBytes = sizeof(WACOMDEVICEREC) * (nSerialCnt + nUSBCnt) +
205                         sizeof(DEVICELIST_INTERNAL);
206
207         /* allocate memory */
208         pInt = (DEVICELIST_INTERNAL*)malloc(nTotalBytes);
209
210         /* copy initial list pointers */
211         pInt->pSerialList = pSerial;
212         pInt->pUSBList = pUSB;
213         pInt->pfnFree = FreeDeviceList;
214
215         /* copy records */
216         pList = (WACOMDEVICEREC*)(pInt + 1);
217         if (pSerial)
218                 memcpy(pList,pSerial,sizeof(WACOMDEVICEREC) * nSerialCnt);
219         if (pUSB)
220                 memcpy(pList + nSerialCnt, pUSB, sizeof(WACOMDEVICEREC) * nUSBCnt);
221
222         *ppList = pList;
223         *pnSize = nSerialCnt + nUSBCnt;
224
225         return 0;
226 }
227
228 void WacomFreeList(void* pvList)
229 {
230         FREEFUNC pfnFree;
231         if (!pvList) return;
232         pfnFree = ((FREEFUNC*)pvList)[-1];
233         (*pfnFree)(pvList);
234 }
235
236 unsigned int WacomGetClassFromName(const char* pszName)
237 {
238         if (strcasecmp(pszName, "serial") == 0)
239                 return WACOMCLASS_SERIAL;
240         else if (strcasecmp(pszName, "usb") == 0)
241                 return WACOMCLASS_USB;
242         return 0;
243 }
244
245 unsigned int WacomGetDeviceFromName(const char* pszName,
246                 unsigned int uDeviceClass)
247 {
248         unsigned int uDeviceType = 0;
249
250         if (!uDeviceClass || (uDeviceClass == WACOMCLASS_SERIAL))
251         {
252                 uDeviceType = WacomGetSerialDeviceFromName(pszName);
253                 if (uDeviceType) return uDeviceType;
254         }
255
256         if (!uDeviceClass || (uDeviceClass == WACOMCLASS_USB))
257         {
258                 uDeviceType = WacomGetUSBDeviceFromName(pszName);
259                 if (uDeviceType) return uDeviceType;
260         }
261
262         errno = ENOENT;
263         return 0;
264 }
265
266 static int WacomIsSerial(int fd)
267 {
268         return isatty(fd);
269 }
270
271 static int WacomIsUSB(int fd)
272 {
273 #ifdef WCM_ENABLE_LINUXINPUT
274         short sID[4];
275         if (ioctl(fd,EVIOCGID,sID) < 0) return 0;
276         return 1;
277 #else
278         return 0;
279 #endif
280 }
281
282 WACOMTABLET WacomOpenTablet(WACOMENGINE hEngine, const char* pszDevice,
283         WACOMMODEL* pModel)
284 {
285         int fd, e;
286         WACOMTABLET hTablet = NULL;
287         unsigned int uClass = pModel ? pModel->uClass : 0;
288
289         /* open device for read/write access */
290         fd = open(pszDevice,O_RDWR);
291         if (fd < 0)
292         {
293                 e = errno;
294                 WacomLog(hEngine,WACOMLOGLEVEL_ERROR,"Failed to open %s: %s",
295                         pszDevice, strerror(errno));
296                 errno = e;
297                 return NULL;
298         }
299
300         /* configure serial */
301         if ((!uClass || (uClass == WACOMCLASS_SERIAL)) && WacomIsSerial(fd))
302         {
303                 hTablet = WacomOpenSerialTablet(hEngine,fd,pModel);
304                 if (!hTablet) { e=errno; close(fd); errno=e; return NULL; }
305         }
306
307         /* configure usb */
308         else if ((!uClass || (uClass == WACOMCLASS_USB)) && WacomIsUSB(fd))
309         {
310                 hTablet = WacomOpenUSBTablet(hEngine,fd,pModel);
311                 if (!hTablet) { e=errno; close(fd); errno=e; return NULL; }
312         }
313
314         /* give up */
315         else
316         {
317                 close(fd);
318                 errno = EINVAL;
319                 return NULL;
320         }
321
322         return hTablet;
323 }
324
325 int WacomCopyState(WACOMSTATE* pDest, WACOMSTATE* pSrc)
326 {
327         unsigned int uCnt;
328         if (!pSrc || !pDest || !pSrc->uValueCnt || !pDest->uValueCnt)
329                 { errno=EINVAL; return 1; }
330
331         /* copy valid bits over */
332         pDest->uValid = pSrc->uValid;
333
334         /* determine how many values to transfer */
335         uCnt = (pDest->uValueCnt < pSrc->uValueCnt) ?
336                         pDest->uValueCnt : pSrc->uValueCnt;
337
338         /* copy them over */
339         memcpy(pDest->values,pSrc->values,uCnt*sizeof(WACOMVALUE));
340
341         return 0;
342 }
343
344 /*****************************************************************************
345 ** Virtual Functions
346 *****************************************************************************/
347
348 void WacomCloseTablet(WACOMTABLET hTablet)
349 {
350         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
351         if (!pTablet || !pTablet->Close) return;
352         pTablet->Close(pTablet);
353 }
354
355 WACOMMODEL WacomGetModel(WACOMTABLET hTablet)
356 {
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);
361 }
362
363 const char* WacomGetVendorName(WACOMTABLET hTablet)
364 {
365         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
366         if (!pTablet || !pTablet->GetVendorName) { errno=EBADF; return NULL; }
367         return pTablet->GetVendorName(pTablet);
368 }
369
370 const char* WacomGetClassName(WACOMTABLET hTablet)
371 {
372         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
373         if (!pTablet || !pTablet->GetClassName) { errno=EBADF; return NULL; }
374         return pTablet->GetClassName(pTablet);
375 }
376
377 const char* WacomGetDeviceName(WACOMTABLET hTablet)
378 {
379         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
380         if (!pTablet || !pTablet->GetDeviceName) { errno=EBADF; return NULL; }
381         return pTablet->GetDeviceName(pTablet);
382 }
383
384 const char* WacomGetSubTypeName(WACOMTABLET hTablet)
385 {
386         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
387         if (!pTablet || !pTablet->GetSubTypeName) { errno=EBADF; return NULL; }
388         return pTablet->GetSubTypeName(pTablet);
389 }
390
391 const char* WacomGetModelName(WACOMTABLET hTablet)
392 {
393         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
394         if (!pTablet || !pTablet->GetModelName) { errno=EBADF; return NULL; }
395         return pTablet->GetModelName(pTablet);
396 }
397
398 int WacomGetROMVersion(WACOMTABLET hTablet, int* pnMajor, int* pnMinor,
399                 int* pnRelease)
400 {
401         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
402         if (!pTablet || !pTablet->GetROMVer) { errno=EBADF; return 0; }
403         return pTablet->GetROMVer(pTablet,pnMajor,pnMinor,pnRelease);
404 }
405
406 int WacomGetCapabilities(WACOMTABLET hTablet)
407 {
408         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
409         if (!pTablet || !pTablet->GetCaps) { errno=EBADF; return 0; }
410         return pTablet->GetCaps(pTablet);
411 }
412
413 int WacomGetState(WACOMTABLET hTablet, WACOMSTATE* pState)
414 {
415         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
416         if (!pTablet || !pTablet->GetState) { errno=EBADF; return 0; }
417         return pTablet->GetState(pTablet,pState);
418 }
419
420 int WacomGetFileDescriptor(WACOMTABLET hTablet)
421 {
422         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
423         if (!pTablet || !pTablet->GetFD) { errno=EBADF; return -1; }
424         return pTablet->GetFD(pTablet);
425 }
426
427 int WacomReadRaw(WACOMTABLET hTablet, unsigned char* puchData,
428                 unsigned int uSize)
429 {
430         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
431         if (!pTablet || !pTablet->ReadRaw) { errno=EBADF; return 0; }
432         return pTablet->ReadRaw(pTablet,puchData,uSize);
433 }
434
435 int WacomParseData(WACOMTABLET hTablet, const unsigned char* puchData,
436                 unsigned int uLength, WACOMSTATE* pState)
437 {
438         WACOMTABLET_PRIV* pTablet = (WACOMTABLET_PRIV*)hTablet;
439         if (!pTablet || !pTablet->ParseData) { errno=EBADF; return 0; }
440         return pTablet->ParseData(pTablet,puchData,uLength,pState);
441 }