1
2 /*
3 * Copyright (c) 1999-2003 by The XFree86 Project, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Except as contained in this notice, the name of the copyright holder(s)
24 * and author(s) shall not be used in advertising or otherwise to promote
25 * the sale, use or other dealings in this Software without prior written
26 * authorization from the copyright holder(s) and author(s).
27 */
28
29
30 /*
31 * XXX - Should this be autoconf'd instead?
32 */
33 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
34
35 #if !defined(USBMOUSE_SUPPORT)
36 #define USBMOUSE_SUPPORT
37 #endif
38 #if !defined(HAS_LIB_USB_HID)
39 #define HAS_LIB_USB_HID
40 #endif
41 #if !defined(XPS2_SUPPORT)
42 #define XPS2_SUPPORT
43 #endif
44
45 #endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) */
46
47 #include <xorg-server.h>
48
49 #include <X11/X.h>
50 #include "xf86.h"
51 #include "xf86Priv.h"
52 #include "xf86_OSlib.h"
53 #include "xf86Xinput.h"
54 #include <exevents.h>
55 #include "mouse.h"
56 #include "xisb.h"
57 #include "mipointer.h"
58 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
59 #define HAVE_PROPERTIES 1
60 #endif
61 #ifdef HAVE_PROPERTIES
62 #include <X11/Xatom.h>
63 #include <xserver-properties.h>
64 /* 1.6 has properties, but no labels */
65 #ifdef AXIS_LABEL_PROP
66 #define HAVE_LABELS
67 #else
68 #undef HAVE_LABELS
69 #endif
70 #endif
71 #ifdef WSCONS_SUPPORT
72 #include <dev/wscons/wsconsio.h>
73 #endif
74 #ifdef USBMOUSE_SUPPORT
75 #ifdef HAS_LIB_USB_HID
76 #include <usbhid.h>
77 #else
78 #include "usb.h"
79 #endif
80
81 #if defined(__DragonFly__)
82 #include <sys/param.h>
83 # if __DragonFly_version < 300703
84 #include <bus/usb/usb.h>
85 # else
86 #include <bus/u4b/usb.h>
87 # endif
88 #else
89 #include <dev/usb/usb.h>
90 #endif
91
92 #define HUP_GENERIC_DESKTOP 0x0001
93 #define HUP_BUTTON 0x0009
94
95 #define HUG_X 0x0030
96 #define HUG_Y 0x0031
97 #define HUG_Z 0x0032
98 #define HUG_WHEEL 0x0038
99
100 #define HID_USAGE2(p,u) (((p) << 16) | u)
101
102 /* The UMS mices have middle button as number 3 */
103 #define UMS_BUT(i) ((i) == 0 ? 2 : (i) == 1 ? 0 : (i) == 2 ? 1 : (i))
104 #endif /* USBMOUSE_SUPPORT */
105
106 #ifdef USBMOUSE_SUPPORT
107 static void usbSigioReadInput (int fd, void *closure);
108 #endif
109 static const char *FindDevice(InputInfoPtr, const char *, int);
110
111 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
112 /* These are for FreeBSD and DragonFly */
113 #define DEFAULT_MOUSE_DEV "/dev/mouse"
114 #define DEFAULT_SYSMOUSE_DEV "/dev/sysmouse"
115 #define DEFAULT_PS2_DEV "/dev/psm0"
116 #define DEFAULT_USB_DEV "/dev/ums0"
117
118 static const char *mouseDevs[] = {
119 DEFAULT_MOUSE_DEV,
120 DEFAULT_SYSMOUSE_DEV,
121 DEFAULT_PS2_DEV,
122 DEFAULT_USB_DEV,
123 NULL
124 };
125 #elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
126 /* Only wsmouse mices are autoconfigured for now on OpenBSD */
127 #define DEFAULT_WSMOUSE_DEV "/dev/wsmouse"
128 #define DEFAULT_WSMOUSE0_DEV "/dev/wsmouse0"
129
130 static const char *mouseDevs[] = {
131 DEFAULT_WSMOUSE_DEV,
132 DEFAULT_WSMOUSE0_DEV,
133 NULL
134 };
135 #endif
136
137 static int
SupportedInterfaces(void)138 SupportedInterfaces(void)
139 {
140 #if defined(__NetBSD__)
141 return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC;
142 #else
143 return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO | MSE_MISC;
144 #endif
145 }
146
147 /* Names of protocols that are handled internally here. */
148 static const char *internalNames[] = {
149 #if defined(WSCONS_SUPPORT)
150 "WSMouse",
151 #endif
152 #if defined(USBMOUSE_SUPPORT)
153 "usb",
154 #endif
155 NULL
156 };
157
158 /*
159 * Names of MSC_MISC protocols that the OS supports. These are decoded by
160 * main "mouse" driver.
161 */
162 static const char *miscNames[] = {
163 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
164 "SysMouse",
165 #endif
166 NULL
167 };
168
169 static const char **
BuiltinNames(void)170 BuiltinNames(void)
171 {
172 return internalNames;
173 }
174
175 static Bool
CheckProtocol(const char * protocol)176 CheckProtocol(const char *protocol)
177 {
178 int i;
179
180 for (i = 0; internalNames[i]; i++)
181 if (xf86NameCmp(protocol, internalNames[i]) == 0)
182 return TRUE;
183 for (i = 0; miscNames[i]; i++)
184 if (xf86NameCmp(protocol, miscNames[i]) == 0)
185 return TRUE;
186 return FALSE;
187 }
188
189 static const char *
DefaultProtocol(void)190 DefaultProtocol(void)
191 {
192 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
193 return "Auto";
194 #elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
195 return "WSMouse";
196 #else
197 return NULL;
198 #endif
199 }
200
201 #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE)
202 static struct {
203 int dproto;
204 const char *name;
205 } devproto[] = {
206 { MOUSE_PROTO_MS, "Microsoft" },
207 { MOUSE_PROTO_MSC, "MouseSystems" },
208 { MOUSE_PROTO_LOGI, "Logitech" },
209 { MOUSE_PROTO_MM, "MMSeries" },
210 { MOUSE_PROTO_LOGIMOUSEMAN, "MouseMan" },
211 { MOUSE_PROTO_BUS, "BusMouse" },
212 { MOUSE_PROTO_INPORT, "BusMouse" },
213 { MOUSE_PROTO_PS2, "PS/2" },
214 { MOUSE_PROTO_HITTAB, "MMHitTab" },
215 { MOUSE_PROTO_GLIDEPOINT, "GlidePoint" },
216 { MOUSE_PROTO_INTELLI, "Intellimouse" },
217 { MOUSE_PROTO_THINK, "ThinkingMouse" },
218 { MOUSE_PROTO_SYSMOUSE, "SysMouse" }
219 };
220
221 #ifdef XPS2_SUPPORT
222 static struct {
223 int dmodel;
224 const char *name;
225 } ps2proto[] = {
226 { MOUSE_MODEL_NETSCROLL, "NetScrollPS/2" },
227 { MOUSE_MODEL_NET, "NetMousePS/2" },
228 { MOUSE_MODEL_GLIDEPOINT, "GlidePointPS/2" },
229 { MOUSE_MODEL_THINK, "ThinkingMousePS/2" },
230 { MOUSE_MODEL_INTELLI, "IMPS/2" },
231 { MOUSE_MODEL_MOUSEMANPLUS, "MouseManPlusPS/2" },
232 { MOUSE_MODEL_EXPLORER, "ExplorerPS/2" },
233 { MOUSE_MODEL_4D, "IMPS/2" },
234 { MOUSE_MODEL_4DPLUS, "IMPS/2" },
235 };
236 #endif
237
238 static const char *
SetupAuto(InputInfoPtr pInfo,int * protoPara)239 SetupAuto(InputInfoPtr pInfo, int *protoPara)
240 {
241 #ifdef XPS2_SUPPORT
242 const char *dev;
243 #endif
244 const char *proto;
245 int i;
246 mousehw_t hw;
247 mousemode_t mode;
248
249 if (pInfo->fd == -1)
250 return NULL;
251
252 #ifdef XPS2_SUPPORT
253 /* set the driver operation level, if applicable */
254 dev = xf86FindOptionValue(pInfo->options, "Device");
255 if (dev != NULL && !strncmp(dev, DEFAULT_PS2_DEV, 8))
256 i = 2;
257 else
258 #endif
259 i = 1;
260 ioctl(pInfo->fd, MOUSE_SETLEVEL, &i);
261
262 /* interrogate the driver and get some intelligence on the device. */
263 hw.iftype = MOUSE_IF_UNKNOWN;
264 hw.model = MOUSE_MODEL_GENERIC;
265 ioctl(pInfo->fd, MOUSE_GETHWINFO, &hw);
266 xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: hw.iftype is %d, hw.model is %d\n",
267 pInfo->name, hw.iftype, hw.model);
268 if (ioctl(pInfo->fd, MOUSE_GETMODE, &mode) == 0) {
269 for (i = 0; i < sizeof(devproto)/sizeof(devproto[0]); ++i) {
270 if (mode.protocol == devproto[i].dproto) {
271 /* override some parameters */
272 if (protoPara) {
273 protoPara[4] = mode.packetsize;
274 protoPara[0] = mode.syncmask[0];
275 protoPara[1] = mode.syncmask[1];
276 }
277 proto = devproto[i].name;
278 #ifdef XPS2_SUPPORT
279 if (mode.protocol == MOUSE_PROTO_PS2)
280 for (i = 0; i < sizeof(ps2proto)/sizeof(ps2proto[0]); ++i)
281 if (hw.model == ps2proto[i].dmodel) {
282 proto = ps2proto[i].name;
283 break;
284 }
285 #endif
286 xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
287 pInfo->name, proto);
288 return proto;
289 }
290 }
291 }
292 return NULL;
293 }
294
295 static void
SetSysMouseRes(InputInfoPtr pInfo,const char * protocol,int rate,int res)296 SetSysMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res)
297 {
298 mousemode_t mode;
299 MouseDevPtr pMse;
300
301 pMse = pInfo->private;
302
303 mode.rate = rate > 0 ? rate : -1;
304 mode.resolution = res > 0 ? res : -1;
305 mode.accelfactor = -1;
306 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
307 if (pMse->autoProbe ||
308 (protocol && xf86NameCmp(protocol, "SysMouse") == 0)) {
309 /*
310 * As the FreeBSD sysmouse driver defaults to protocol level 0
311 * everytime it is closed we enforce protocol level 1 again at
312 * this point.
313 */
314 mode.level = 1;
315 } else
316 #endif
317 mode.level = -1;
318 ioctl(pInfo->fd, MOUSE_SETMODE, &mode);
319 }
320 #endif
321
322 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
323 /*
324 * Try to check if moused is running. DEFAULT_SYSMOUSE_DEV is useless without
325 * it. Also, try to check if the device is used by moused. If it is opened
326 * by moused, we do not want to use it directly. There doesn't seem to be
327 * a better way of checking.
328 */
329 static Bool
MousedRunning(const char * dev)330 MousedRunning(const char *dev)
331 {
332 char cmd[128];
333 FILE *f = NULL;
334 unsigned int i;
335
336 if (dev)
337 sprintf(cmd, "sh -c 'fstat %s | grep -c moused' 2>/dev/null", dev);
338 else
339 sprintf(cmd, "sh -c 'pgrep -nx moused' 2>/dev/null");
340 if ((f = popen(cmd, "r")) != NULL) {
341 if (fscanf(f, "%u", &i) == 1 && i > 0) {
342 pclose(f);
343 return TRUE;
344 }
345 pclose(f);
346 }
347 return FALSE;
348 }
349
350 static const char *
FindDevice(InputInfoPtr pInfo,const char * protocol,int flags)351 FindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
352 {
353 int ret = -1;
354 const char **pdev, *dev = NULL;
355 Bool devMouse = FALSE;
356 struct stat devMouseStat;
357 struct stat sb;
358
359 for (pdev = mouseDevs; *pdev; pdev++) {
360 SYSCALL (ret = stat(*pdev, &sb));
361 if (ret == -1) {
362 #ifdef DEBUG
363 ErrorF("Cannot stat %s (%s)\n", *pdev, strerror(errno));
364 #endif
365 } else {
366 /*
367 * /dev/mouse is held until checks for matches with other devices
368 * are done. This is so that when it points to /dev/sysmouse,
369 * the test for whether /dev/sysmouse is usable can be made.
370 */
371 if (!strcmp(*pdev, DEFAULT_MOUSE_DEV)) {
372 memcpy(&devMouseStat, &sb, sizeof(devMouseStat));
373 devMouse = TRUE;
374 continue;
375 } else if (!strcmp(*pdev, DEFAULT_SYSMOUSE_DEV)) {
376 /* Check if /dev/mouse is the same as /dev/sysmouse. */
377 if (devMouse && devMouseStat.st_dev == sb.st_dev &&
378 devMouseStat.st_ino == sb.st_ino) {
379 /* If the same, use /dev/sysmouse. */
380 devMouse = FALSE;
381 }
382 if (MousedRunning(NULL))
383 break;
384 } else {
385 /* Check if /dev/mouse is the same as this device. */
386 if (devMouse && devMouseStat.st_dev == sb.st_dev &&
387 devMouseStat.st_ino == sb.st_ino) {
388 /* If the same, use this device. */
389 devMouse = FALSE;
390 }
391 if (MousedRunning(*pdev))
392 continue;
393 /* ums(4) does not support anything but SysMouse protocol. */
394 if (!strncmp(*pdev, DEFAULT_USB_DEV, 8) && protocol &&
395 xf86NameCmp(protocol, "auto") != 0 &&
396 xf86NameCmp(protocol, "sysmouse") != 0)
397 continue;
398 break;
399 }
400 }
401 }
402
403 if (*pdev)
404 dev = *pdev;
405 else if (devMouse)
406 dev = DEFAULT_MOUSE_DEV;
407
408 if (dev) {
409 /* Set the Device option. */
410 pInfo->options =
411 xf86AddNewOption(pInfo->options, "Device", dev);
412 xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n",
413 pInfo->name, dev);
414 }
415
416 return *pdev;
417 }
418 #endif
419
420 #if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
421
422 /* Only support wsmouse configuration for now */
423 static const char *
SetupAuto(InputInfoPtr pInfo,int * protoPara)424 SetupAuto(InputInfoPtr pInfo, int *protoPara)
425 {
426
427 xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
428 pInfo->name, "wsmouse");
429 return "wsmouse";
430 }
431
432 static void
SetMouseRes(InputInfoPtr pInfo,const char * protocol,int rate,int res)433 SetMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res)
434 {
435
436 xf86MsgVerb(X_INFO, 3, "%s: SetMouseRes: protocol %s rate %d res %d\n",
437 pInfo->name, protocol, rate, res);
438 }
439
440 static const char *
FindDevice(InputInfoPtr pInfo,const char * protocol,int flags)441 FindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
442 {
443 int fd = -1;
444 const char **pdev;
445
446 for (pdev = mouseDevs; *pdev; pdev++) {
447 SYSCALL(fd = open(*pdev, O_RDWR | O_NONBLOCK));
448 if (fd != -1) {
449 /* Set the Device option. */
450 pInfo->options =
451 xf86AddNewOption(pInfo->options,
452 "Device", *pdev);
453 xf86Msg(X_INFO, "%s: found Device \"%s\"\n",
454 pInfo->name, *pdev);
455 close(fd);
456 break;
457 }
458 }
459 return *pdev;
460 }
461 #endif /* __OpenBSD__ || __NetBSD__ && WSCONS_SUPPORT */
462
463 #ifdef WSCONS_SUPPORT
464 #define NUMEVENTS 64
465
466 static void
wsconsReadInput(InputInfoPtr pInfo)467 wsconsReadInput(InputInfoPtr pInfo)
468 {
469 MouseDevPtr pMse;
470 static struct wscons_event eventList[NUMEVENTS];
471 int n, c;
472 struct wscons_event *event = eventList;
473 unsigned char *pBuf;
474
475 pMse = pInfo->private;
476
477 XisbBlockDuration(pMse->buffer, -1);
478 pBuf = (unsigned char *)eventList;
479 n = 0;
480 while (n < sizeof(eventList) && (c = XisbRead(pMse->buffer)) >= 0) {
481 pBuf[n++] = (unsigned char)c;
482 }
483
484 if (n == 0)
485 return;
486
487 n /= sizeof(struct wscons_event);
488 while( n-- ) {
489 int buttons = pMse->lastButtons;
490 int dx = 0, dy = 0, dz = 0, dw = 0, x, y;
491 switch (event->type) {
492 case WSCONS_EVENT_MOUSE_UP:
493 #define BUTBIT (1 << (event->value <= 2 ? 2 - event->value : event->value))
494 buttons &= ~BUTBIT;
495 break;
496 case WSCONS_EVENT_MOUSE_DOWN:
497 buttons |= BUTBIT;
498 break;
499 case WSCONS_EVENT_MOUSE_DELTA_X:
500 dx = event->value;
501 break;
502 case WSCONS_EVENT_MOUSE_DELTA_Y:
503 dy = -event->value;
504 break;
505 #ifdef WSCONS_EVENT_MOUSE_DELTA_Z
506 case WSCONS_EVENT_MOUSE_DELTA_Z:
507 dz = event->value;
508 break;
509 #endif
510 #ifdef WSCONS_EVENT_MOUSE_DELTA_W
511 case WSCONS_EVENT_MOUSE_DELTA_W:
512 dw = event->value;
513 break;
514 #endif
515 case WSCONS_EVENT_MOUSE_ABSOLUTE_X:
516 x = event->value;
517 xf86PostMotionEvent(pInfo->dev, TRUE, 0, 1, x);
518 ++event;
519 continue;
520 case WSCONS_EVENT_MOUSE_ABSOLUTE_Y:
521 y = event->value;
522 xf86PostMotionEvent(pInfo->dev, TRUE, 1, 1, y);
523 ++event;
524 continue;
525 #ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_Z
526 case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
527 ++event;
528 continue;
529 #endif
530 #ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_W
531 case WSCONS_EVENT_MOUSE_ABSOLUTE_W:
532 ++event;
533 continue;
534 #endif
535 default:
536 LogMessageVerbSigSafe(X_WARNING, -1,
537 "%s: bad wsmouse event type=%d\n", pInfo->name,
538 event->type);
539 ++event;
540 continue;
541 }
542
543 pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
544 ++event;
545 }
546 return;
547 }
548
549
550 /* This function is called when the protocol is "wsmouse". */
551 static Bool
wsconsPreInit(InputInfoPtr pInfo,const char * protocol,int flags)552 wsconsPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
553 {
554 MouseDevPtr pMse = pInfo->private;
555
556 /* Setup the local input proc. */
557 pInfo->read_input = wsconsReadInput;
558 pMse->xisbscale = sizeof(struct wscons_event);
559
560 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
561 pInfo->flags |= XI86_CONFIGURED;
562 #endif
563 return TRUE;
564 }
565 #endif
566
567 #if defined(USBMOUSE_SUPPORT)
568
569 #define MAXRIDS 64
570 #define MAXACOLS 8
571 #define MAXLCOLS 16
572 typedef struct _UsbMseRec {
573 int packetSize;
574 int iid, nrids, nacols, opened;
575 struct {
576 int32_t rid;
577 int size;
578 } rids[MAXRIDS];
579 struct UsbMseAcol {
580 InputInfoPtr pInfo;
581 int nlcols, nbuttons, hasZ, hasW;
582 int xmin, xmax, ymin, ymax, pmin, pmax, px, py;
583 int cxmin, cxmax, cymin, cymax, cpmin, cpmax;
584 struct UsbMseLcol {
585 hid_item_t loc_x; /* x locator item */
586 hid_item_t loc_y; /* y locator item */
587 hid_item_t loc_z; /* z (wheel) locator item */
588 hid_item_t loc_w; /* w (hwheel) locator item */
589 hid_item_t loc_p; /* Tip Pressure */
590 hid_item_t loc_valid; /* Touch Valid */
591 hid_item_t loc_in_range; /* In Range */
592 hid_item_t loc_btn[MSE_MAXBUTTONS]; /* buttons locator items */
593 } lcols[MAXLCOLS];
594 hid_item_t loc_cc; /* contact count */
595 } acols[MAXACOLS];
596 unsigned char *buffer;
597 } UsbMseRec, *UsbMsePtr;
598
599 static int *
usbGetReportSizePtr(UsbMsePtr pUsbMse,int32_t rid)600 usbGetReportSizePtr(UsbMsePtr pUsbMse, int32_t rid)
601 {
602 int i;
603
604 for (i = 0; i < pUsbMse->nrids; i++) {
605 if (pUsbMse->rids[i].rid == rid)
606 return (&pUsbMse->rids[i].size);
607 }
608 for (i = 0; i < MAXRIDS; i++) {
609 if (pUsbMse->rids[i].size == 0) {
610 pUsbMse->rids[i].rid = rid;
611 pUsbMse->nrids = max(pUsbMse->nrids, i + 1);
612 return (&pUsbMse->rids[i].size);
613 }
614 }
615 return (NULL);
616 }
617
618 static int
usbMouseProc(DeviceIntPtr pPointer,int what)619 usbMouseProc(DeviceIntPtr pPointer, int what)
620 {
621 InputInfoPtr pInfo;
622 MouseDevPtr pMse;
623 UsbMsePtr pUsbMse;
624 struct UsbMseAcol *acol;
625 unsigned char map[MSE_MAXBUTTONS + 1];
626 int nacol, nbuttons;
627 #ifdef HAVE_LABELS
628 Atom btn_labels[MSE_MAXBUTTONS] = {0};
629 Atom axes_labels[3] = { 0, 0, 0 };
630 #endif
631
632 pInfo = pPointer->public.devicePrivate;
633 pMse = pInfo->private;
634 pMse->device = pPointer;
635 pUsbMse = pMse->mousePriv;
636 for (nacol = 0; nacol < (pUsbMse->nacols - 1); nacol++) {
637 if (pUsbMse->acols[nacol].pInfo == pInfo)
638 break;
639 }
640 acol = &pUsbMse->acols[nacol];
641
642 switch (what) {
643 case DEVICE_INIT:
644 pPointer->public.on = FALSE;
645
646 for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons)
647 map[nbuttons + 1] = nbuttons + 1;
648
649 #ifdef HAVE_LABELS
650 btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
651 btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
652 btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
653 axes_labels[0] = XIGetKnownProperty((acol->xmin != acol->xmax)
654 ? AXIS_LABEL_PROP_ABS_X : AXIS_LABEL_PROP_REL_X);
655 axes_labels[1] = XIGetKnownProperty((acol->xmin != acol->xmax)
656 ? AXIS_LABEL_PROP_ABS_Y : AXIS_LABEL_PROP_REL_Y);
657 axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
658 #endif
659
660 InitButtonClassDeviceStruct(pPointer, min(pMse->buttons, MSE_MAXBUTTONS),
661 #ifdef HAVE_LABELS
662 btn_labels,
663 #endif
664 map);
665 InitValuatorClassDeviceStruct(pPointer, (acol->pmin != acol->pmax) ? 3 : 2,
666 #ifdef HAVE_LABELS
667 axes_labels,
668 #endif
669 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
670 miPointerGetMotionEvents,
671 #elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
672 GetMotionHistory,
673 #endif
674 GetMotionHistorySize(),
675 (acol->xmin != acol->xmax || acol->ymin != acol->ymax) ?
676 Absolute : Relative);
677 InitPtrFeedbackClassDeviceStruct(pPointer, pMse->Ctrl);
678
679 /* X valuator */
680 xf86InitValuatorAxisStruct(pPointer, 0,
681 #ifdef HAVE_LABELS
682 axes_labels[0],
683 #endif
684 (acol->xmin != acol->xmax) ? acol->xmin : -1,
685 (acol->xmin != acol->xmax) ? acol->xmax : -1,
686 1, 0, 1
687 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
688 , (acol->xmin != acol->xmax) ? Absolute : Relative
689 #endif
690 );
691 xf86InitValuatorDefaults(pPointer, 0);
692 /* Y valuator */
693 xf86InitValuatorAxisStruct(pPointer, 1,
694 #ifdef HAVE_LABELS
695 axes_labels[1],
696 #endif
697 (acol->ymin != acol->ymax) ? acol->ymin : -1,
698 (acol->ymin != acol->ymax) ? acol->ymax : -1,
699 1, 0, 1
700 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
701 , (acol->ymin != acol->ymax) ? Absolute : Relative
702 #endif
703 );
704 xf86InitValuatorDefaults(pPointer, 1);
705 /* Pressure valuator */
706 if (acol->pmin != acol->pmax) {
707 xf86InitValuatorAxisStruct(pPointer, 2,
708 #ifdef HAVE_LABELS
709 axes_labels[2],
710 #endif
711 acol->pmin, acol->pmax, 1, 0, 1
712 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
713 , Absolute
714 #endif
715 );
716 xf86InitValuatorDefaults(pPointer, 2);
717 }
718 xf86MotionHistoryAllocate(pInfo);
719 break;
720
721 case DEVICE_ON:
722 if (pUsbMse->opened++ == 0) {
723 pInfo->fd = xf86OpenSerial(pInfo->options);
724 if (pInfo->fd == -1)
725 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
726 else {
727 pMse->buffer = XisbNew(pInfo->fd, pUsbMse->packetSize);
728 if (!pMse->buffer) {
729 free(pMse);
730 xf86CloseSerial(pInfo->fd);
731 pInfo->fd = -1;
732 } else {
733 xf86FlushInput(pInfo->fd);
734 if (!xf86InstallSIGIOHandler (pInfo->fd, usbSigioReadInput,
735 pInfo))
736 xf86AddEnabledDevice(pInfo);
737 }
738 }
739 }
740 pMse->lastButtons = 0;
741 pMse->lastMappedButtons = 0;
742 pMse->emulateState = 0;
743 pPointer->public.on = TRUE;
744 break;
745
746 case DEVICE_OFF:
747 case DEVICE_CLOSE:
748 if (pInfo->fd != -1) {
749 xf86RemoveEnabledDevice(pInfo);
750 if (pUsbMse->packetSize > 8 && pUsbMse->buffer) {
751 free(pUsbMse->buffer);
752 }
753 if (pMse->buffer) {
754 XisbFree(pMse->buffer);
755 pMse->buffer = NULL;
756 }
757 xf86CloseSerial(pInfo->fd);
758 pInfo->fd = -1;
759 }
760 pUsbMse->opened--;
761 pPointer->public.on = FALSE;
762 usleep(300000);
763 break;
764
765 default:
766 return BadValue;
767 }
768 return Success;
769 }
770
771 static void
usbReadInput(InputInfoPtr pInfo)772 usbReadInput(InputInfoPtr pInfo)
773 {
774 MouseDevPtr pMse;
775 UsbMsePtr pUsbMse;
776 int buttons, cc;
777 int dx, dy, dz, dw, dp, upd, v, nx, ny, np, in_range;
778 int n, c, rid, *sizep, nacol, nlcol;
779 unsigned char *pBuf;
780 struct UsbMseAcol *acol;
781 struct UsbMseLcol *lcol;
782
783 pMse = pInfo->private;
784 pUsbMse = pMse->mousePriv;
785
786 XisbBlockDuration(pMse->buffer, -1);
787 next:
788 pBuf = pUsbMse->buffer;
789 n = 0;
790 if (pUsbMse->iid) {
791 rid = XisbRead(pMse->buffer);
792 if (rid < 0)
793 return;
794 pBuf[n++] = (unsigned char)rid;
795 } else
796 rid = 0;
797 sizep = usbGetReportSizePtr(pUsbMse, rid);
798 if (sizep == NULL || *sizep == 0) {
799 xf86Msg(X_WARNING, "%s: unknown report ID %d\n", pInfo->name, rid);
800 goto next;
801 }
802 while (n < *sizep && (c = XisbRead(pMse->buffer)) >= 0) {
803 pBuf[n++] = (unsigned char)c;
804 }
805 if (n == 0)
806 return;
807 // xf86MsgVerb(X_INFO, 3, "pkt: %d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
808 // n, pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7], pBuf[8], pBuf[9]);
809 if (n != *sizep) {
810 LogMessageVerbSigSafe(X_WARNING, -1,
811 "%s: incomplete packet, size %d\n",
812 pInfo->name, n);
813 }
814 for (nacol = 0; nacol < pUsbMse->nacols; nacol++) {
815 acol = &pUsbMse->acols[nacol];
816 if (acol->pInfo == NULL)
817 continue;
818 nx = ny = np = upd = 0;
819 buttons = cc = 0;
820 dx = dy = dz = dw = dp = 0;
821 for (nlcol = 0; nlcol < pUsbMse->acols[nacol].nlcols; nlcol++) {
822 lcol = &acol->lcols[nlcol];
823
824 if (lcol->loc_valid.usage != 0 && rid == lcol->loc_valid.report_ID &&
825 hid_get_data(pBuf, &lcol->loc_valid) == 0)
826 continue;
827 if (lcol->loc_in_range.usage != 0 && rid == lcol->loc_in_range.report_ID)
828 in_range = hid_get_data(pBuf, &lcol->loc_in_range);
829 else
830 in_range = 1;
831 if (in_range && lcol->loc_x.usage != 0 && rid == lcol->loc_x.report_ID && nx == 0) {
832 v = hid_get_data(pBuf, &lcol->loc_x);
833 if (acol->xmin != acol->xmax) {
834 v = xf86ScaleAxis(v, acol->xmax, acol->xmin,
835 lcol->loc_x.logical_maximum, lcol->loc_x.logical_minimum);
836 if (acol->cxmin != acol->cxmax)
837 v = xf86ScaleAxis(v, acol->xmax, acol->xmin,
838 acol->cxmax, acol->cxmin);
839 }
840 dx += v;
841 nx++;
842 }
843 if (in_range && lcol->loc_y.usage != 0 && rid == lcol->loc_y.report_ID && ny == 0) {
844 v = hid_get_data(pBuf, &lcol->loc_y);
845 if (acol->xmin != acol->xmax) {
846 v = xf86ScaleAxis(v, acol->ymax, acol->ymin,
847 lcol->loc_y.logical_maximum, lcol->loc_y.logical_minimum);
848 if (acol->cymin != acol->cymax)
849 v = xf86ScaleAxis(v, acol->ymax, acol->ymin,
850 acol->cymax, acol->cymin);
851 }
852 dy += v;
853 ny++;
854 }
855 if (lcol->loc_z.usage != 0 && rid == lcol->loc_z.report_ID) {
856 dz -= hid_get_data(pBuf, &lcol->loc_z);
857 upd = 1;
858 }
859 if (lcol->loc_w.usage != 0 && rid == lcol->loc_w.report_ID) {
860 dw += hid_get_data(pBuf, &lcol->loc_w);
861 upd = 1;
862 }
863 if (lcol->loc_p.usage != 0 && rid == lcol->loc_p.report_ID && np == 0) {
864 v = hid_get_data(pBuf, &lcol->loc_p);
865 v = xf86ScaleAxis(v, acol->pmax, acol->pmin,
866 lcol->loc_p.logical_maximum, lcol->loc_p.logical_minimum);
867 if (acol->cpmin != acol->cpmax)
868 v = xf86ScaleAxis(v, acol->pmax, acol->pmin,
869 acol->cpmax, acol->cpmin);
870 dp += v;
871 np++;
872 }
873
874 for (n = 0; n < acol->nbuttons; n++) {
875 if (lcol->loc_btn[n].usage != 0 && rid == lcol->loc_btn[n].report_ID) {
876 if (hid_get_data(pBuf, &lcol->loc_btn[n]))
877 buttons |= (1 << UMS_BUT(n));
878 upd = 1;
879 }
880 }
881 }
882 if (acol->loc_cc.usage != 0 && rid == acol->loc_cc.report_ID)
883 cc = hid_get_data(pBuf, &acol->loc_cc);
884 else
885 cc = (nx || ny) ? 1 : 0;
886 if (cc > 1)
887 buttons = (1 << UMS_BUT(1));
888 if (nx != 0 && acol->xmin != acol->xmax)
889 dx /= nx;
890 if (ny != 0 && acol->ymin != acol->ymax)
891 dy /= ny;
892 if (np != 0 && acol->pmin != acol->pmax)
893 dp /= np;
894 // if (upd || nx || ny || np)
895 // xf86MsgVerb(X_INFO, 3, "%d cc %d dx %d dy %d dz %d dw %d press %d buttons %02x\n",
896 // nacol, cc, dx, dy, dz, dw, dp, buttons);
897 if (nx != 0 || ny != 0) {
898 if (acol->pmin != acol->pmax) {
899 xf86PostMotionEvent(acol->pInfo->dev,
900 /* is_absolute: */ TRUE,
901 /* first_valuator: */ 0,
902 /* num_valuators: */ 3,
903 dx, dy, dp);
904 } else if (acol->xmin != acol->xmax || acol->ymin != acol->ymax) {
905 xf86PostMotionEvent(acol->pInfo->dev,
906 /* is_absolute: */ TRUE,
907 /* first_valuator: */ 0,
908 /* num_valuators: */ 2,
909 dx, dy);
910 }
911 }
912 if (upd || (nx != 0) || (ny != 0)) {
913 ((MouseDevPtr)acol->pInfo->private)->PostEvent(acol->pInfo, buttons,
914 ((acol->xmin != acol->xmax) ? dx - acol->px : dx),
915 ((acol->ymin != acol->ymax) ? dy - acol->py : dy),
916 dz, dw);
917 }
918 if (nx > 0)
919 acol->px = dx;
920 if (ny > 0)
921 acol->py = dy;
922 }
923 goto next;
924 }
925
926 static void
usbSigioReadInput(int fd,void * closure)927 usbSigioReadInput (int fd, void *closure)
928 {
929 usbReadInput ((InputInfoPtr) closure);
930 }
931
932 static Bool
usbInitFirst(InputInfoPtr pInfo)933 usbInitFirst(InputInfoPtr pInfo)
934 {
935 MouseDevPtr pMse = pInfo->private;
936 UsbMsePtr pUsbMse;
937 report_desc_t reportDesc;
938 hid_data_t d;
939 hid_item_t h;
940 struct UsbMseAcol *acol;
941 struct UsbMseLcol *lcol;
942 int mdepth, rsize, *rsizep, acolused, lcolused, used;
943
944 pUsbMse = malloc(sizeof(UsbMseRec));
945 if (pUsbMse == NULL) {
946 xf86Msg(X_ERROR, "%s: cannot allocate UsbMouseRec\n", pInfo->name);
947 free(pMse);
948 return FALSE;
949 }
950
951 bzero(pUsbMse, sizeof(UsbMseRec));
952
953 /* Check if the device can be opened. */
954 pInfo->fd = xf86OpenSerial(pInfo->options);
955 if (pInfo->fd == -1) {
956 if (xf86GetAllowMouseOpenFail())
957 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
958 else {
959 xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
960 free(pUsbMse);
961 free(pMse);
962 return FALSE;
963 }
964 }
965 /* Get USB informations */
966 reportDesc = hid_get_report_desc(pInfo->fd);
967 mdepth = 0;
968 pUsbMse->nacols = 0;
969 acol = &pUsbMse->acols[pUsbMse->nacols];
970 lcol = &acol->lcols[acol->nlcols];
971 acolused = 0;
972 lcolused = 0;
973 d = hid_start_parse(reportDesc, (1 << hid_input) |
974 (1 << hid_collection) | (1 << hid_endcollection), -1);
975 while (hid_get_item(d, &h)) {
976 switch (h.kind) {
977 case hid_collection:
978 if (mdepth != 0)
979 mdepth++;
980 else if (h.collection == 1 &&
981 (h.usage == 0x00010001 || h.usage == 0x00010002 ||
982 (h.usage >= 0x000d0001 && h.usage <= 0x000d000d))) {
983 mdepth++;
984 if (acolused) {
985 if (lcolused) {
986 acol->nlcols++;
987 lcolused = 0;
988 }
989 pUsbMse->nacols++;
990 acolused = 0;
991 acol = &pUsbMse->acols[pUsbMse->nacols];
992 lcol = &acol->lcols[acol->nlcols];
993 }
994 }
995 if (lcolused && (h.collection == 0 ||
996 h.collection == 2 || h.collection == 3)) {
997 acol->nlcols++;
998 lcolused = 0;
999 lcol = &acol->lcols[acol->nlcols];
1000 }
1001 break;
1002 case hid_endcollection:
1003 if (mdepth != 0)
1004 mdepth--;
1005 break;
1006 case hid_input:
1007 if (h.report_ID != 0)
1008 pUsbMse->iid = 1;
1009 rsize = pUsbMse->iid +
1010 (h.pos + (h.report_size * h.report_count) + 7) / 8;
1011 if ((rsizep = usbGetReportSizePtr(pUsbMse, h.report_ID)) != NULL)
1012 *rsizep = max(*rsizep, rsize);
1013 pUsbMse->packetSize = max(pUsbMse->packetSize, rsize);
1014 if (mdepth == 0)
1015 break;
1016 used = 1;
1017 if (h.usage == 0x00010030) { /* X */
1018 lcol->loc_x = h;
1019 if ((h.flags & 0x04) == 0) {
1020 if (acol->xmin == acol->xmax) {
1021 acol->xmin = h.logical_minimum;
1022 acol->xmax = h.logical_maximum;
1023 } else {
1024 acol->xmin = min(acol->xmin, h.logical_minimum);
1025 acol->xmax = max(acol->xmax, h.logical_maximum);
1026 }
1027 }
1028 } else if (h.usage == 0x00010031) { /* Y */
1029 lcol->loc_y = h;
1030 if ((h.flags & 0x04) == 0) {
1031 if (acol->ymin == acol->ymax) {
1032 acol->ymin = h.logical_minimum;
1033 acol->ymax = h.logical_maximum;
1034 } else {
1035 acol->ymin = min(acol->ymin, h.logical_minimum);
1036 acol->ymax = max(acol->ymax, h.logical_maximum);
1037 }
1038 }
1039 } else if (h.usage == 0x00010038) { /* Z */
1040 lcol->loc_z = h;
1041 acol->hasZ = 1;
1042 } else if (h.usage == 0x000c0238) { /* W */
1043 lcol->loc_w = h;
1044 acol->hasW = 1;
1045 } else if (h.usage == 0x000d0030) { /* Press */
1046 lcol->loc_p = h;
1047 if ((h.flags & 0x04) == 0) {
1048 if (acol->pmin == acol->pmax) {
1049 acol->pmin = h.logical_minimum;
1050 acol->pmax = h.logical_maximum;
1051 } else {
1052 acol->pmin = min(acol->pmin, h.logical_minimum);
1053 acol->pmax = max(acol->pmax, h.logical_maximum);
1054 }
1055 }
1056 } else if (h.usage == 0x000d0032) /* In Range */
1057 lcol->loc_in_range = h;
1058 else if (h.usage == 0x000d0047) /* Valid */
1059 lcol->loc_valid = h;
1060 else if (h.usage > 0x00090000 &&
1061 h.usage <= 0x00090000 + MSE_MAXBUTTONS) { /* Buttons */
1062 lcol->loc_btn[(h.usage & 0xffff) - 1] = h;
1063 acol->nbuttons = max(acol->nbuttons, h.usage & 0xffff);
1064 } else if (h.usage == 0x000d0042) { /* Tip Switch */
1065 lcol->loc_btn[0] = h;
1066 acol->nbuttons = max(acol->nbuttons, 1);
1067 } else if (h.usage == 0x000d0044) { /* Barrel Switch */
1068 lcol->loc_btn[1] = h;
1069 acol->nbuttons = max(acol->nbuttons, 2);
1070 } else if (h.usage == 0x000d0045) { /* Eraser */
1071 lcol->loc_btn[3] = h;
1072 acol->nbuttons = max(acol->nbuttons, 4);
1073 } else if (h.usage == 0x000d0046) { /* Tablet Pick */
1074 lcol->loc_btn[2] = h;
1075 acol->nbuttons = max(acol->nbuttons, 3);
1076 } else if (h.usage == 0x000d0054) /* Contact Count */
1077 acol->loc_cc = h;
1078 else
1079 used = 0;
1080 lcolused += used;
1081 acolused += used;
1082 break;
1083 default:
1084 break;
1085 }
1086 }
1087 if (lcolused)
1088 acol->nlcols++;
1089 if (acolused)
1090 pUsbMse->nacols++;
1091 hid_end_parse(d);
1092 xf86Msg(X_DEFAULT, "%s: Found %d usable logical collections\n",
1093 pInfo->name, pUsbMse->nacols);
1094
1095 /* Allocate buffer */
1096 if (pUsbMse->packetSize <= 8) {
1097 pUsbMse->buffer = pMse->protoBuf;
1098 } else {
1099 pUsbMse->buffer = malloc(pUsbMse->packetSize);
1100 }
1101 if (pUsbMse->buffer == NULL) {
1102 xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name);
1103 free(pUsbMse);
1104 xf86CloseSerial(pInfo->fd);
1105 return FALSE;
1106 }
1107
1108 xf86CloseSerial(pInfo->fd);
1109 pInfo->fd = -1;
1110
1111 /* Private structure */
1112 pMse->mousePriv = pUsbMse;
1113 return TRUE;
1114 }
1115
1116 /* This function is called when the protocol is "usb". */
1117 static Bool
usbPreInit(InputInfoPtr pInfo,const char * protocol,int flags)1118 usbPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
1119 {
1120 InputInfoPtr pMatch;
1121 MouseDevPtr pMse = pInfo->private;
1122 UsbMsePtr pUsbMse;
1123 struct UsbMseAcol *acol;
1124 char *str;
1125 int i, colopt;
1126
1127 pMse->protocol = protocol;
1128 xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
1129
1130 /* Collect the options, and process the common options. */
1131 COLLECT_INPUT_OPTIONS(pInfo, NULL);
1132 xf86ProcessCommonOptions(pInfo, pInfo->options);
1133
1134 /* Check if this HID device is already opened. */
1135 for (pMatch = xf86FirstLocalDevice(); pMatch != NULL; pMatch = pMatch->next) {
1136 if ((pInfo != pMatch) && strstr(pMatch->drv->driverName, "mouse")) {
1137 char *dev1, *dev2;
1138
1139 dev1 = xf86SetStrOption(pInfo->options, "Device", NULL);
1140 dev2 = xf86SetStrOption(pMatch->options, "Device", NULL);
1141 if (strcmp(dev1, dev2) == 0) {
1142 free(dev1);
1143 free(dev2);
1144 break;
1145 }
1146 free(dev1);
1147 free(dev2);
1148 }
1149 }
1150 if (pMatch == NULL) {
1151 xf86Msg(X_DEFAULT, "%s: Opening new HID device\n", pInfo->name);
1152 if (!usbInitFirst(pInfo)) {
1153 free(pMse);
1154 return FALSE;
1155 }
1156 } else {
1157 pMse->mousePriv = ((MouseDevPtr)pMatch->private)->mousePriv;
1158 xf86Msg(X_DEFAULT, "%s: Attaching to already opened HID device\n",
1159 pInfo->name);
1160 }
1161 pUsbMse = pMse->mousePriv;
1162
1163 /* Attach to collection, respecting "Collection" option. */
1164 colopt = xf86SetIntOption(pInfo->options, "Collection", 0);
1165 for (i = 0; i < pUsbMse->nacols; i++) {
1166 if (pUsbMse->acols[i].pInfo == NULL &&
1167 (colopt == 0 || i == colopt - 1)) {
1168 pUsbMse->acols[i].pInfo = pInfo;
1169 break;
1170 }
1171 }
1172 xf86Msg(colopt == 0 ? X_DEFAULT : X_CONFIG,
1173 "%s: Collection: %d\n", pInfo->name,
1174 i == pUsbMse->nacols ? colopt : i + 1);
1175 if (i == pUsbMse->nacols) {
1176 xf86Msg(X_ERROR,
1177 "%s: Application collection not found or already handled\n",
1178 pInfo->name);
1179 free(pMse);
1180 return FALSE;
1181 }
1182
1183 acol = &pUsbMse->acols[i];
1184 pMse->buttons = acol->nbuttons;
1185 if (pMse->buttons == 2)
1186 pMse->buttons = 3;
1187 if (acol->xmin != acol->xmax || acol->ymin != acol->ymax)
1188 pMse->disableXY = TRUE;
1189 pMse->hasZ = acol->hasZ;
1190 pMse->hasW = acol->hasW;
1191
1192 /* Process common mouse options (like Emulate3Buttons, etc). */
1193 pMse->CommonOptions(pInfo);
1194
1195 /* Process "Calibration" option. */
1196 str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
1197 if (str != NULL && (acol->xmin != acol->xmax || acol->ymin != acol->ymax)) {
1198 int j, xmin, xmax, ymin, ymax, pmin, pmax;
1199
1200 j = sscanf(str, "%d %d %d %d %d %d", &xmin, &xmax, &ymin, &ymax, &pmin, &pmax);
1201 if (j == 4) {
1202 xf86Msg(X_CONFIG, "%s: Calibration: %d %d %d %d\n",
1203 pInfo->name, xmin, xmax, ymin, ymax);
1204 acol->cxmin = xmin;
1205 acol->cxmax = xmax;
1206 acol->cymin = ymin;
1207 acol->cymax = ymax;
1208 } else if (j == 6) {
1209 xf86Msg(X_CONFIG, "%s: Calibration: %d %d %d %d %d %d\n",
1210 pInfo->name, xmin, xmax, ymin, ymax, pmin, pmax);
1211 acol->cxmin = xmin;
1212 acol->cxmax = xmax;
1213 acol->cymin = ymin;
1214 acol->cymax = ymax;
1215 acol->cpmin = pmin;
1216 acol->cpmax = pmax;
1217 } else
1218 xf86Msg(X_WARNING, "%s: Calibration: Invalid arguments\n",
1219 pInfo->name);
1220 free(str);
1221 } else if (acol->xmin != acol->xmax || acol->ymin != acol->ymax) {
1222 xf86Msg(X_DEFAULT, "%s: Calibration: %d %d %d %d %d %d\n",
1223 pInfo->name, acol->xmin, acol->xmax, acol->ymin, acol->ymax,
1224 acol->pmin, acol->pmax);
1225 }
1226
1227 /* Setup the local procs. */
1228 pInfo->device_control = usbMouseProc;
1229 pInfo->read_input = usbReadInput;
1230
1231 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
1232 pInfo->flags |= XI86_CONFIGURED;
1233 #endif
1234 return TRUE;
1235 }
1236 #endif /* USBMOUSE */
1237
1238 static Bool
bsdMousePreInit(InputInfoPtr pInfo,const char * protocol,int flags)1239 bsdMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags)
1240 {
1241 /* The protocol is guaranteed to be one of the internalNames[] */
1242 #ifdef WSCONS_SUPPORT
1243 if (xf86NameCmp(protocol, "WSMouse") == 0) {
1244 return wsconsPreInit(pInfo, protocol, flags);
1245 }
1246 #endif
1247 #ifdef USBMOUSE_SUPPORT
1248 if (xf86NameCmp(protocol, "usb") == 0) {
1249 return usbPreInit(pInfo, protocol, flags);
1250 }
1251 #endif
1252 return TRUE;
1253 }
1254
1255 OSMouseInfoPtr
OSMouseInit(int flags)1256 OSMouseInit(int flags)
1257 {
1258 OSMouseInfoPtr p;
1259
1260 p = calloc(sizeof(OSMouseInfoRec), 1);
1261 if (!p)
1262 return NULL;
1263 p->SupportedInterfaces = SupportedInterfaces;
1264 p->BuiltinNames = BuiltinNames;
1265 p->DefaultProtocol = DefaultProtocol;
1266 p->CheckProtocol = CheckProtocol;
1267 #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE)
1268 p->SetupAuto = SetupAuto;
1269 #ifndef XPS2_SUPPORT
1270 p->SetPS2Res = SetSysMouseRes;
1271 #endif
1272 p->SetBMRes = SetSysMouseRes;
1273 p->SetMiscRes = SetSysMouseRes;
1274 #endif
1275 #if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
1276 p->SetupAuto = SetupAuto;
1277 p->SetMiscRes = SetMouseRes;
1278 #endif
1279 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
1280 p->FindDevice = FindDevice;
1281 #endif
1282 p->PreInit = bsdMousePreInit;
1283 return p;
1284 }
1285