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