1 /*
2 * Copyright 1995-2002 by Frederic Lepied, France. <Lepied@XFree86.org>
3 * Copyright 2002-2010 by Ping Cheng, Wacom. <pingc@wacom.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 * This driver is currently able to handle USB Wacom IV and V, serial ISDV4,
22 * and bluetooth protocols.
23 *
24 * Wacom V protocol work done by Raph Levien <raph@gtk.org> and
25 * Frédéric Lepied <lepied@xfree86.org>.
26 *
27 * Modified for Linux USB by MATSUMURA Namihiko,
28 * Daniel Egger, Germany. <egger@suse.de>,
29 * Frederic Lepied <lepied@xfree86.org>,
30 * Brion Vibber <brion@pobox.com>,
31 * Aaron Optimizer Digulla <digulla@hepe.com>,
32 * Jonathan Layes <jonathan@layes.com>,
33 * John Joganic <jej@j-arkadia.com>,
34 * Magnus Vigerlöf <Magnus.Vigerlof@ipbo.se>,
35 * Peter Hutterer <peter.hutterer@redhat.com>.
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45
46 #include "xf86Wacom.h"
47 #include <xf86_OSproc.h>
48 #include <exevents.h> /* Needed for InitValuator/Proximity stuff */
49
50 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
51 #include <xserver-properties.h>
52 #include <X11/extensions/XKB.h>
53 #include <xkbsrv.h>
54 #else
55 #define XIGetKnownProperty(prop) 0
56 #endif
57
58 #ifndef XI86_SERVER_FD
59 #define XI86_SERVER_FD 0x20
60 #endif
61
62 static int wcmDevOpen(DeviceIntPtr pWcm);
63 static int wcmReady(InputInfoPtr pInfo);
64 static void wcmDevReadInput(InputInfoPtr pInfo);
65 static void wcmDevControlProc(DeviceIntPtr device, PtrCtrl* ctrl);
66 int wcmDevChangeControl(InputInfoPtr pInfo, xDeviceCtl * control);
67 static void wcmDevClose(InputInfoPtr pInfo);
68 static int wcmDevProc(DeviceIntPtr pWcm, int what);
69
70 WacomModule gWacomModule =
71 {
72 NULL, /* input driver pointer */
73
74 /* device procedures */
75 wcmDevOpen,
76 wcmDevReadInput,
77 wcmDevControlProc,
78 wcmDevChangeControl,
79 wcmDevClose,
80 wcmDevProc,
81 wcmDevSwitchMode,
82 };
83
wcmKbdLedCallback(DeviceIntPtr di,LedCtrl * lcp)84 static void wcmKbdLedCallback(DeviceIntPtr di, LedCtrl * lcp)
85 {
86 }
87
wcmKbdCtrlCallback(DeviceIntPtr di,KeybdCtrl * ctrl)88 static void wcmKbdCtrlCallback(DeviceIntPtr di, KeybdCtrl* ctrl)
89 {
90 }
91
92 /*****************************************************************************
93 * wcmInitialToolSize --
94 * Initialize logical size and resolution for individual tool.
95 ****************************************************************************/
96
97 TEST_NON_STATIC void
wcmInitialToolSize(InputInfoPtr pInfo)98 wcmInitialToolSize(InputInfoPtr pInfo)
99 {
100 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
101 WacomCommonPtr common = priv->common;
102
103 /* assign max and resolution here since we don't get them during
104 * the configuration stage */
105 if (IsTouch(priv))
106 {
107 priv->maxX = common->wcmMaxTouchX;
108 priv->maxY = common->wcmMaxTouchY;
109 priv->resolX = common->wcmTouchResolX;
110 priv->resolY = common->wcmTouchResolY;
111 }
112 else
113 {
114 priv->minX = common->wcmMinX;
115 priv->minY = common->wcmMinY;
116 priv->maxX = common->wcmMaxX;
117 priv->maxY = common->wcmMaxY;
118 priv->resolX = common->wcmResolX;
119 priv->resolY = common->wcmResolY;
120 }
121
122 if (!priv->topX)
123 priv->topX = priv->minX;
124 if (!priv->topY)
125 priv->topY = priv->minY;
126 if (!priv->bottomX)
127 priv->bottomX = priv->maxX;
128 if (!priv->bottomY)
129 priv->bottomY = priv->maxY;
130
131 return;
132 }
133
wcmInitAxis(DeviceIntPtr dev,int axis,Atom label,int min,int max,int res,int min_res,int max_res,int mode)134 static void wcmInitAxis(DeviceIntPtr dev, int axis, Atom label, int min, int max, int res, int min_res, int max_res, int mode) {
135 InitValuatorAxisStruct(dev, axis,
136 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
137 label,
138 #endif
139 min, max, res, min_res, max_res
140 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
141 ,mode
142 #endif
143 );
144 }
145
146 /**
147 * Initialize the device axes with their proper attributes.
148 *
149 * For each axis on the device, we need to provide X with its attributes
150 * so that its values can be interpreted properly. To support older X
151 * servers without axis labels, each axis index has a de-facto meaning.
152 * Any de-facto defined axis index left unused is initialized with default
153 * attributes.
154 */
wcmInitAxes(DeviceIntPtr pWcm)155 static int wcmInitAxes(DeviceIntPtr pWcm)
156 {
157 InputInfoPtr pInfo = (InputInfoPtr)pWcm->public.devicePrivate;
158 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
159 WacomCommonPtr common = priv->common;
160
161 Atom label;
162 int index;
163 int min, max, min_res, max_res, res;
164 int mode;
165
166 /* first valuator: x */
167 index = 0;
168 label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
169 min = priv->topX;
170 max = priv->bottomX;
171 min_res = 0;
172 max_res = priv->resolX;
173 res = priv->resolX;
174 mode = Absolute;
175
176 wcmInitAxis(pInfo->dev, index, label, min, max, res, min_res, max_res, mode);
177
178
179 /* second valuator: y */
180 index = 1;
181 label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
182 min = priv->topY;
183 max = priv->bottomY;
184 min_res = 0;
185 max_res = priv->resolY;
186 res = priv->resolY;
187 mode = Absolute;
188
189 wcmInitAxis(pInfo->dev, index, label, min, max, res, min_res, max_res, mode);
190
191
192 /* third valuator: pressure */
193 index = 2;
194 label = None;
195 mode = Absolute;
196 min_res = max_res = res = 1;
197 min = 0;
198 max = 1;
199
200 if (!IsPad(priv))
201 {
202 label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
203 max = priv->maxCurve;
204 }
205
206 wcmInitAxis(pInfo->dev, index, label, min, max, res, min_res, max_res, mode);
207
208
209 /* fourth valuator: tilt-x, cursor:z-rotation, pad:strip-x */
210 index = 3;
211 label = None;
212 mode = Absolute;
213 min_res = max_res = res = 1;
214 min = 0;
215 max = 1;
216
217 if (IsPen(priv))
218 {
219 label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X),
220 min_res = max_res = res = round(TILT_RES);
221 min = TILT_MIN;
222 max = TILT_MAX;
223 }
224 else if (IsCursor(priv))
225 {
226 label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_RZ);
227 min = MIN_ROTATION;
228 max = MIN_ROTATION + MAX_ROTATION_RANGE - 1;
229 }
230 else if (IsPad(priv) && TabletHasFeature(common, WCM_STRIP))
231 { /* XXX: what is this axis label? */
232 max = common->wcmMaxStripX;
233 }
234
235 wcmInitAxis(pInfo->dev, index, label, min, max, res, min_res, max_res, mode);
236
237
238 /* fifth valuator: tilt-y, cursor:throttle, pad:strip-y */
239 index = 4;
240 label = None;
241 mode = Absolute;
242 min_res = max_res = res = 1;
243 min = 0;
244 max = 1;
245
246 if (IsPen(priv))
247 {
248 label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y);
249 min_res = max_res = res = round(TILT_RES);
250 min = TILT_MIN;
251 max = TILT_MAX;
252 }
253 else if (IsCursor(priv))
254 {
255 label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_THROTTLE);
256 min = -1023;
257 max = 1023;
258 }
259 else if (IsPad(priv) && TabletHasFeature(common, WCM_STRIP))
260 { /* XXX: what is this axis label? */
261 max = common->wcmMaxStripY;
262 }
263
264 wcmInitAxis(pInfo->dev, index, label, min, max, res, min_res, max_res, mode);
265
266
267 /* sixth valuator: airbrush: abs-wheel, artpen: rotation, pad:abs-wheel */
268 index = 5;
269 label = None;
270 mode = Absolute;
271 min_res = max_res = res = 1;
272 min = 0;
273 max = 1;
274
275 if (IsStylus(priv))
276 {
277 label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_WHEEL);
278 max = MAX_ROTATION_RANGE + MIN_ROTATION - 1;
279 min = MIN_ROTATION;
280 }
281 else if ((TabletHasFeature(common, WCM_RING)) && IsPad(priv))
282 {
283 /* Touch ring */
284 label = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_WHEEL);
285 min = common->wcmMinRing;
286 max = common->wcmMaxRing;
287 }
288
289 wcmInitAxis(pInfo->dev, index, label, min, max, res, min_res, max_res, mode);
290
291
292 /* seventh valuator: abswheel2 */
293 if ((TabletHasFeature(common, WCM_DUALRING)) && IsPad(priv))
294 {
295 /* XXX: what is this axis label? */
296 index = 6;
297 label = None;
298 mode = Absolute;
299 min_res = max_res = res = 1;
300
301 min = common->wcmMinRing;
302 max = common->wcmMaxRing;
303
304 wcmInitAxis(pInfo->dev, index, label, min, max, res, min_res, max_res, mode);
305 }
306
307 return TRUE;
308 }
309
310 /*****************************************************************************
311 * wcmDevInit --
312 * Set up the device's buttons, axes and keys
313 ****************************************************************************/
314
wcmDevInit(DeviceIntPtr pWcm)315 static int wcmDevInit(DeviceIntPtr pWcm)
316 {
317 InputInfoPtr pInfo = (InputInfoPtr)pWcm->public.devicePrivate;
318 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
319 WacomCommonPtr common = priv->common;
320 unsigned char butmap[WCM_MAX_BUTTONS+1];
321 int nbaxes, nbbuttons, nbkeys;
322 int loop;
323 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
324 Atom btn_labels[WCM_MAX_BUTTONS] = {0};
325 Atom axis_labels[MAX_VALUATORS] = {0};
326 #endif
327
328 /* Detect tablet configuration, if possible */
329 if (priv->common->wcmModel->DetectConfig)
330 priv->common->wcmModel->DetectConfig (pInfo);
331
332 nbaxes = priv->naxes; /* X, Y, Pressure, Tilt-X, Tilt-Y, Wheel */
333 nbbuttons = priv->nbuttons; /* Use actual number of buttons, if possible */
334
335 if (IsPad(priv) && TabletHasFeature(priv->common, WCM_DUALRING))
336 nbaxes = priv->naxes = nbaxes + 1; /* ABS wheel 2 */
337
338 /* if more than 3 buttons, offset by the four scroll buttons,
339 * otherwise, alloc 7 buttons for scroll wheel. */
340 nbbuttons = min(max(nbbuttons + 4, 7), WCM_MAX_BUTTONS);
341 nbkeys = nbbuttons; /* Same number of keys since any button may be
342 * configured as an either mouse button or key */
343
344 DBG(10, priv,
345 "(%s) %d buttons, %d keys, %d axes\n",
346 pInfo->type_name,
347 nbbuttons, nbkeys, nbaxes);
348
349 for(loop=1; loop<=nbbuttons; loop++)
350 butmap[loop] = loop;
351
352 /* FIXME: button labels would be nice */
353 if (InitButtonClassDeviceStruct(pInfo->dev, nbbuttons,
354 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
355 btn_labels,
356 #endif
357 butmap) == FALSE)
358 {
359 xf86Msg(X_ERROR, "%s: unable to allocate Button class device\n", pInfo->name);
360 return FALSE;
361 }
362
363 if (InitFocusClassDeviceStruct(pInfo->dev) == FALSE)
364 {
365 xf86Msg(X_ERROR, "%s: unable to init Focus class device\n", pInfo->name);
366 return FALSE;
367 }
368
369 if (InitPtrFeedbackClassDeviceStruct(pInfo->dev,
370 wcmDevControlProc) == FALSE)
371 {
372 xf86Msg(X_ERROR, "%s: unable to init ptr feedback\n", pInfo->name);
373 return FALSE;
374 }
375
376 if (InitProximityClassDeviceStruct(pInfo->dev) == FALSE)
377 {
378 xf86Msg(X_ERROR, "%s: unable to init proximity class device\n", pInfo->name);
379 return FALSE;
380 }
381
382 if (!nbaxes || nbaxes > 7)
383 nbaxes = priv->naxes = 7;
384
385 /* axis_labels is just zeros, we set up each valuator with the
386 * correct property later */
387 if (InitValuatorClassDeviceStruct(pInfo->dev, nbaxes,
388 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
389 axis_labels,
390 #endif
391 GetMotionHistorySize(),
392 (is_absolute(pInfo) ? Absolute : Relative) | OutOfProximity) == FALSE)
393 {
394 xf86Msg(X_ERROR, "%s: unable to allocate Valuator class device\n", pInfo->name);
395 return FALSE;
396 }
397
398
399 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
400 if (!InitKeyboardDeviceStruct(pInfo->dev, NULL, NULL, wcmKbdCtrlCallback)) {
401 xf86Msg(X_ERROR, "%s: unable to init kbd device struct\n", pInfo->name);
402 return FALSE;
403 }
404 #endif
405 if(InitLedFeedbackClassDeviceStruct (pInfo->dev, wcmKbdLedCallback) == FALSE) {
406 xf86Msg(X_ERROR, "%s: unable to init led feedback device struct\n", pInfo->name);
407 return FALSE;
408 }
409
410 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 16
411 if (IsTouch(priv)) {
412 if (!InitTouchClassDeviceStruct(pInfo->dev, common->wcmMaxContacts,
413 TabletHasFeature(common, WCM_LCD) ? XIDirectTouch : XIDependentTouch,
414 2))
415 {
416 xf86Msg(X_ERROR, "Unable to init touch class device struct!\n");
417 return FALSE;
418 }
419 priv->common->touch_mask = valuator_mask_new(2);
420 }
421 #endif
422
423 if (!IsPad(priv))
424 {
425 wcmInitialToolSize(pInfo);
426 }
427
428 if (!wcmInitAxes(pWcm))
429 return FALSE;
430
431 InitWcmDeviceProperties(pInfo);
432 XIRegisterPropertyHandler(pInfo->dev, wcmSetProperty, wcmGetProperty, wcmDeleteProperty);
433
434 return TRUE;
435 }
436
wcmIsWacomDevice(char * fname)437 Bool wcmIsWacomDevice (char* fname)
438 {
439 int fd = -1;
440 struct input_id id;
441
442 SYSCALL(fd = open(fname, O_RDONLY));
443 if (fd < 0)
444 return FALSE;
445
446 if (ioctl(fd, EVIOCGID, &id) < 0)
447 {
448 SYSCALL(close(fd));
449 return FALSE;
450 }
451
452 SYSCALL(close(fd));
453
454 switch(id.vendor)
455 {
456 case WACOM_VENDOR_ID:
457 case WALTOP_VENDOR_ID:
458 case HANWANG_VENDOR_ID:
459 case LENOVO_VENDOR_ID:
460 return TRUE;
461 default:
462 break;
463 }
464 return FALSE;
465 }
466
467 /*****************************************************************************
468 * wcmEventAutoDevProbe -- Probe for right input device
469 ****************************************************************************/
470 #define DEV_INPUT_EVENT "/dev/input/event%d"
471 #define EVDEV_MINORS 32
wcmEventAutoDevProbe(InputInfoPtr pInfo)472 char *wcmEventAutoDevProbe (InputInfoPtr pInfo)
473 {
474 /* We are trying to find the right eventX device */
475 int i = 0, wait = 0;
476 const int max_wait = 2000;
477
478 /* If device is not available after Resume, wait some ms */
479 while (wait <= max_wait)
480 {
481 for (i = 0; i < EVDEV_MINORS; i++)
482 {
483 char fname[64];
484 Bool is_wacom;
485
486 sprintf(fname, DEV_INPUT_EVENT, i);
487 is_wacom = wcmIsWacomDevice(fname);
488 if (is_wacom)
489 {
490 xf86Msg(X_PROBED, "%s: probed device is %s (waited %d msec)\n",
491 pInfo->name, fname, wait);
492 xf86ReplaceStrOption(pInfo->options, "Device", fname);
493
494 /* this assumes there is only one Wacom device on the system */
495 return xf86CheckStrOption(pInfo->options, "Device", NULL);
496 }
497 }
498 wait += 100;
499 xf86Msg(X_ERROR, "%s: waiting 100 msec (total %dms) for device to become ready\n", pInfo->name, wait);
500 usleep(100*1000);
501 }
502 xf86Msg(X_ERROR, "%s: no Wacom event device found (checked %d nodes, waited %d msec)\n",
503 pInfo->name, i + 1, wait);
504 xf86Msg(X_ERROR, "%s: unable to probe device\n", pInfo->name);
505 return NULL;
506 }
507
508 /*****************************************************************************
509 * wcmOpen --
510 ****************************************************************************/
511
wcmOpen(InputInfoPtr pInfo)512 Bool wcmOpen(InputInfoPtr pInfo)
513 {
514 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
515 WacomCommonPtr common = priv->common;
516
517 DBG(1, priv, "opening device file\n");
518
519 pInfo->fd = xf86OpenSerial(pInfo->options);
520 if (pInfo->fd < 0)
521 {
522 xf86Msg(X_ERROR, "%s: Error opening %s (%s)\n", pInfo->name,
523 common->device_path, strerror(errno));
524 return !Success;
525 }
526
527 return Success;
528 }
529
530 /*****************************************************************************
531 * wcmClose --
532 ****************************************************************************/
533
wcmClose(InputInfoPtr pInfo)534 void wcmClose(InputInfoPtr pInfo)
535 {
536 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
537
538 DBG(1, priv, "closing device file\n");
539
540 if (pInfo->fd > -1 && !(pInfo->flags & XI86_SERVER_FD)) {
541 xf86CloseSerial(pInfo->fd);
542 pInfo->fd = -1;
543 }
544 }
545
546 /*****************************************************************************
547 * wcmDevOpen --
548 * Open the physical device and init information structs.
549 ****************************************************************************/
550
wcmDevOpen(DeviceIntPtr pWcm)551 static int wcmDevOpen(DeviceIntPtr pWcm)
552 {
553 InputInfoPtr pInfo = (InputInfoPtr)pWcm->public.devicePrivate;
554 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
555 WacomCommonPtr common = priv->common;
556 WacomModelPtr model = common->wcmModel;
557 struct stat st;
558
559 DBG(10, priv, "\n");
560
561 /* If fd management is done by the server, skip common fd handling */
562 if (pInfo->flags & XI86_SERVER_FD)
563 goto got_fd;
564
565 /* open file, if not already open */
566 if (common->fd_refs == 0)
567 {
568 if ((wcmOpen (pInfo) != Success) || !common->device_path)
569 {
570 DBG(1, priv, "Failed to open device (fd=%d)\n", pInfo->fd);
571 wcmClose(pInfo);
572 return FALSE;
573 }
574
575 if (fstat(pInfo->fd, &st) == -1)
576 {
577 /* can not access major/minor */
578 DBG(1, priv, "stat failed (%s).\n", strerror(errno));
579
580 /* older systems don't support the required ioctl.
581 * So, we have to let it pass */
582 common->min_maj = 0;
583 }
584 else
585 common->min_maj = st.st_rdev;
586 common->fd = pInfo->fd;
587 common->fd_refs = 1;
588 }
589
590 /* Grab the common descriptor, if it's available */
591 if (pInfo->fd < 0)
592 {
593 pInfo->fd = common->fd;
594 common->fd_refs++;
595 }
596
597 got_fd:
598 /* start the tablet data */
599 if (model->Start && (model->Start(pInfo) != Success))
600 return !Success;
601
602 return TRUE;
603 }
604
wcmReady(InputInfoPtr pInfo)605 static int wcmReady(InputInfoPtr pInfo)
606 {
607 #ifdef DEBUG
608 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
609 #endif
610 int n = xf86WaitForInput(pInfo->fd, 0);
611 DBG(10, priv, "%d numbers of data\n", n);
612
613 if (n >= 0) return n ? 1 : 0;
614 xf86Msg(X_ERROR, "%s: select error: %s\n", pInfo->name, strerror(errno));
615 return 0;
616 }
617
618 /*****************************************************************************
619 * wcmDevReadInput --
620 * Read the device on IO signal
621 ****************************************************************************/
622
wcmDevReadInput(InputInfoPtr pInfo)623 static void wcmDevReadInput(InputInfoPtr pInfo)
624 {
625 int loop=0;
626 #define MAX_READ_LOOPS 10
627
628 /* move data until we exhaust the device */
629 for (loop=0; loop < MAX_READ_LOOPS; ++loop)
630 {
631 /* verify that there is still data in pipe */
632 if (!wcmReady(pInfo)) break;
633
634 /* dispatch */
635 if (!wcmReadPacket(pInfo))
636 break;
637 }
638
639 #ifdef DEBUG
640 /* report how well we're doing */
641 if (loop > 0)
642 {
643 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
644
645 if (loop >= MAX_READ_LOOPS)
646 DBG(1, priv, "Can't keep up!!!\n");
647 else
648 DBG(10, priv, "Read (%d)\n",loop);
649 }
650 #endif
651 }
652
wcmReadPacket(InputInfoPtr pInfo)653 Bool wcmReadPacket(InputInfoPtr pInfo)
654 {
655 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
656 WacomCommonPtr common = priv->common;
657 int len, pos, cnt, remaining;
658
659 DBG(10, common, "fd=%d\n", pInfo->fd);
660
661 remaining = sizeof(common->buffer) - common->bufpos;
662
663 DBG(1, common, "pos=%d remaining=%d\n", common->bufpos, remaining);
664
665 /* fill buffer with as much data as we can handle */
666 len = xf86ReadSerial(pInfo->fd,
667 common->buffer + common->bufpos, remaining);
668
669 if (len <= 0)
670 {
671 /* BSD specific code. */
672 /* Hotplug code does not send remove dev notify because
673 * opened cuse dev cant be removed. */
674 if (priv->isParent && errno == EINVAL) {
675 WacomDevicePtr other;
676 for (other = common->wcmDevices; other; other = other->next) {
677 xf86Msg(X_INFO, "%s: removing automatically added device.\n",
678 other->pInfo->name);
679 DeleteInputDeviceRequest(other->pInfo->dev);
680 }
681 } else
682 /* for all other errors, hope that the hotplugging code will
683 * remove the device */
684 if (errno != EAGAIN && errno != EINTR)
685 LogMessageVerbSigSafe(X_ERROR, 0,
686 "%s: Error reading wacom device : %s\n", pInfo->name, strerror(errno));
687 if (errno == ENODEV)
688 xf86RemoveEnabledDevice(pInfo);
689
690 return FALSE;
691 }
692
693 /* account for new data */
694 common->bufpos += len;
695 DBG(10, common, "buffer has %d bytes\n", common->bufpos);
696
697 len = common->bufpos;
698 pos = 0;
699
700 while (len > 0)
701 {
702 /* parse packet */
703 cnt = common->wcmModel->Parse(pInfo, common->buffer + pos, len);
704 if (cnt <= 0)
705 {
706 if (cnt < 0)
707 DBG(1, common, "Misbehaving parser returned %d\n",cnt);
708 break;
709 }
710 pos += cnt;
711 len -= cnt;
712 }
713
714 /* if half a packet remains, move it down */
715 if (len)
716 {
717 DBG(7, common, "MOVE %d bytes\n", common->bufpos - pos);
718 memmove(common->buffer,common->buffer+pos, len);
719 }
720
721 common->bufpos = len;
722
723 return TRUE;
724 }
725
wcmDevChangeControl(InputInfoPtr pInfo,xDeviceCtl * control)726 int wcmDevChangeControl(InputInfoPtr pInfo, xDeviceCtl * control)
727 {
728 #ifdef DEBUG
729 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
730 DBG(3, priv, "\n");
731 #endif
732 return Success;
733 }
734
735 /*****************************************************************************
736 * wcmDevControlProc --
737 ****************************************************************************/
738
wcmDevControlProc(DeviceIntPtr device,PtrCtrl * ctrl)739 static void wcmDevControlProc(DeviceIntPtr device, PtrCtrl* ctrl)
740 {
741 #ifdef DEBUG
742 InputInfoPtr pInfo = (InputInfoPtr)device->public.devicePrivate;
743 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
744
745 DBG(4, priv, "called\n");
746 #endif
747 return;
748 }
749
750 /*****************************************************************************
751 * wcmDevClose --
752 ****************************************************************************/
753
wcmDevClose(InputInfoPtr pInfo)754 static void wcmDevClose(InputInfoPtr pInfo)
755 {
756 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
757 WacomCommonPtr common = priv->common;
758
759 /* If fd management is done by the server, skip common fd handling */
760 if (pInfo->flags & XI86_SERVER_FD)
761 return;
762
763 DBG(4, priv, "Wacom number of open devices = %d\n", common->fd_refs);
764
765 if (pInfo->fd >= 0)
766 {
767 if (!--common->fd_refs)
768 wcmClose(pInfo);
769 pInfo->fd = -1;
770 }
771 }
772
wcmEnableDisableTool(DeviceIntPtr dev,Bool enable)773 static void wcmEnableDisableTool(DeviceIntPtr dev, Bool enable)
774 {
775 InputInfoPtr pInfo = dev->public.devicePrivate;
776 WacomDevicePtr priv = pInfo->private;
777 WacomToolPtr tool = priv->tool;
778
779 tool->enabled = enable;
780 }
781
wcmEnableTool(DeviceIntPtr dev)782 static void wcmEnableTool(DeviceIntPtr dev)
783 {
784 wcmEnableDisableTool(dev, TRUE);
785 }
wcmDisableTool(DeviceIntPtr dev)786 static void wcmDisableTool(DeviceIntPtr dev)
787 {
788 wcmEnableDisableTool(dev, FALSE);
789 }
790
791 /**
792 * Unlink the touch tool from the pen of the same device
793 */
wcmUnlinkTouchAndPen(InputInfoPtr pInfo)794 static void wcmUnlinkTouchAndPen(InputInfoPtr pInfo)
795 {
796 WacomDevicePtr priv = pInfo->private;
797 WacomCommonPtr common = priv->common;
798 InputInfoPtr device = xf86FirstLocalDevice();
799 WacomCommonPtr tmpcommon = NULL;
800 WacomDevicePtr tmppriv = NULL;
801 Bool touch_device = FALSE;
802
803 if (!TabletHasFeature(common, WCM_PENTOUCH))
804 return;
805
806 /* Lookup to find the associated pen and touch */
807 for (; device != NULL; device = device->next)
808 {
809 if (!strcmp(device->drv->driverName, "wacom"))
810 {
811 tmppriv = (WacomDevicePtr) device->private;
812 tmpcommon = tmppriv->common;
813 touch_device = (common->wcmTouchDevice ||
814 tmpcommon->wcmTouchDevice);
815
816 /* skip the same tool or unlinked devices */
817 if ((tmppriv == priv) || !touch_device)
818 continue;
819
820 if (tmpcommon->tablet_id == common->tablet_id)
821 {
822 common->wcmTouchDevice = NULL;
823 tmpcommon->wcmTouchDevice = NULL;
824 common->tablet_type &= ~WCM_PENTOUCH;
825 tmpcommon->tablet_type &= ~WCM_PENTOUCH;
826 return;
827 }
828 }
829 }
830 }
831
832 /*****************************************************************************
833 * wcmDevProc --
834 * Handle the initialization, etc. of a wacom tablet. Called by the server
835 * once with DEVICE_INIT when the device becomes available, then
836 * DEVICE_ON/DEVICE_OFF possibly multiple times as the device is enabled
837 * and disabled. DEVICE_CLOSE is called before removal of the device.
838 ****************************************************************************/
839
wcmDevProc(DeviceIntPtr pWcm,int what)840 static int wcmDevProc(DeviceIntPtr pWcm, int what)
841 {
842 InputInfoPtr pInfo = (InputInfoPtr)pWcm->public.devicePrivate;
843 WacomDevicePtr priv = (WacomDevicePtr)pInfo->private;
844 Status rc = !Success;
845
846 DBG(2, priv, "BEGIN dev=%p priv=%p "
847 "type=%s flags=%d fd=%d what=%s\n",
848 (void *)pWcm, (void *)priv,
849 pInfo->type_name,
850 priv->flags, pInfo ? pInfo->fd : -1,
851 (what == DEVICE_INIT) ? "INIT" :
852 (what == DEVICE_OFF) ? "OFF" :
853 (what == DEVICE_ON) ? "ON" :
854 (what == DEVICE_CLOSE) ? "CLOSE" : "???");
855
856 switch (what)
857 {
858 case DEVICE_INIT:
859 if (!wcmDevInit(pWcm))
860 goto out;
861 break;
862
863 case DEVICE_ON:
864 if (!wcmDevOpen(pWcm))
865 goto out;
866 wcmEnableTool(pWcm);
867 xf86AddEnabledDevice(pInfo);
868 pWcm->public.on = TRUE;
869 break;
870
871 case DEVICE_OFF:
872 TimerCancel(priv->tap_timer);
873 TimerCancel(priv->serial_timer);
874 TimerCancel(priv->touch_timer);
875 wcmDisableTool(pWcm);
876 wcmUnlinkTouchAndPen(pInfo);
877 if (pInfo->fd >= 0)
878 {
879 xf86RemoveEnabledDevice(pInfo);
880 wcmDevClose(pInfo);
881 }
882 pWcm->public.on = FALSE;
883 break;
884 case DEVICE_CLOSE:
885 break;
886 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) * 100 + GET_ABI_MINOR(ABI_XINPUT_VERSION) >= 1901
887 case DEVICE_ABORT:
888 break;
889 #endif
890 default:
891 xf86Msg(X_ERROR, "%s: invalid mode=%d. This is an X server bug.\n",
892 pInfo->name, what);
893 goto out;
894 } /* end switch */
895
896 rc = Success;
897
898 out:
899 if (rc != Success)
900 DBG(1, priv, "Failed during %d\n", what);
901 return rc;
902 }
903
904 /* vim: set noexpandtab tabstop=8 shiftwidth=8: */
905