Ravenports generated: 29 Dec 2023 04:24
[ravenports.git] / bucket_85 / xorg-driver-input-mouse
1 # Buildsheet autogenerated by ravenadm tool -- Do not edit.
2
3 NAMEBASE=               xorg-driver-input-mouse
4 VERSION=                1.9.5
5 KEYWORDS=               x11_drivers
6 VARIANTS=               standard
7 SDESC[standard]=        X.org mouse input driver
8 HOMEPAGE=               https://www.x.org/
9 CONTACT=                nobody
10
11 DOWNLOAD_GROUPS=        main
12 SITES[main]=            XORG/individual/driver
13 DISTFILE[1]=            xf86-input-mouse-1.9.5.tar.xz:main
14 DF_INDEX=               1
15 SPKGS[standard]=        complete
16                         primary
17                         dev
18                         man
19
20 OPTIONS_AVAILABLE=      none
21 OPTIONS_STANDARD=       none
22
23 BUILD_DEPENDS=          xorg-server:dev:standard
24 BUILDRUN_DEPENDS=       xorg-server:primary:standard
25
26 USES=                   libtool
27 XORG_COMPONENTS=        xorgproto
28
29 DISTNAME=               xf86-input-mouse-1.9.5
30
31 LICENSE=                MIT:primary
32 LICENSE_FILE=           MIT:{{WRKSRC}}/COPYING
33 LICENSE_SCHEME=         solo
34
35 FPC_EQUIVALENT=         x11-drivers/xf86-input-mouse
36
37 MUST_CONFIGURE=         gnu
38 CONFIGURE_ENV=          DRIVER_MAN_SUFFIX=4
39
40 INSTALL_TARGET=         install-strip
41
42 [FILE:57:descriptions/desc.primary]
43 This package contains the X.Org xf86-input-mouse driver.
44
45
46 [FILE:108:distinfo]
47 4fde8ae9b44352e2a208584c36528ee3ed13cf5fe4417208a9785daccefd9968       326896 xf86-input-mouse-1.9.5.tar.xz
48
49
50 [FILE:36:manifests/plist.primary]
51 lib/xorg/modules/input/mouse_drv.so
52
53
54 [FILE:65:manifests/plist.dev]
55 include/xorg/xf86-mouse-properties.h
56 lib/pkgconfig/xorg-mouse.pc
57
58
59 [FILE:29:manifests/plist.man]
60 share/man/man4/mousedrv.4.gz
61
62
63 [FILE:304:patches/patch-configure]
64 --- configure.orig      2023-05-05 00:25:26 UTC
65 +++ configure
66 @@ -19610,7 +19610,7 @@ case $host_os in
67    linux*)
68      OS_MOUSE_NAME=lnx
69      ;;
70 -  freebsd*|kfreebsd*-gnu|dragonfly*|netbsd*|openbsd*)
71 +  freebsd*|kfreebsd*-gnu|dragonfly*|netbsd*|openbsd*|midnight*)
72      OS_MOUSE_NAME=bsd
73      ;;
74    solaris*)
75
76
77 [FILE:34219:patches/patch-src_bsd__mouse.c]
78 --- src/bsd_mouse.c.orig        2023-05-05 00:25:20 UTC
79 +++ src/bsd_mouse.c
80 @@ -26,6 +26,24 @@
81   * authorization from the copyright holder(s) and author(s).
82   */
83  
84 +
85 +/*
86 + * XXX - Should this be autoconf'd instead?
87 + */
88 +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
89 +
90 +#if !defined(USBMOUSE_SUPPORT)
91 +#define USBMOUSE_SUPPORT
92 +#endif
93 +#if !defined(HAS_LIB_USB_HID)
94 +#define HAS_LIB_USB_HID
95 +#endif
96 +#if !defined(XPS2_SUPPORT)
97 +#define XPS2_SUPPORT
98 +#endif
99 +
100 +#endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) */
101 +
102  #include <xorg-server.h>
103  
104  #include <X11/X.h>
105 @@ -33,9 +51,23 @@
106  #include "xf86Priv.h"
107  #include "xf86_OSlib.h"
108  #include "xf86Xinput.h"
109 +#include <exevents.h>
110  #include "mouse.h"
111  #include "xisb.h"
112  #include "mipointer.h"
113 +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
114 +#define HAVE_PROPERTIES 1
115 +#endif
116 +#ifdef HAVE_PROPERTIES
117 +#include <X11/Xatom.h>
118 +#include <xserver-properties.h>
119 +/* 1.6 has properties, but no labels */
120 +#ifdef AXIS_LABEL_PROP
121 +#define HAVE_LABELS
122 +#else
123 +#undef HAVE_LABELS
124 +#endif
125 +#endif
126  #ifdef WSCONS_SUPPORT
127  #include <dev/wscons/wsconsio.h>
128  #endif
129 @@ -46,9 +78,10 @@
130  #include "usb.h"
131  #endif
132  
133 +#if defined __DragonFly__
134 +#include <bus/u4b/usb.h>
135 +#else
136  #include <dev/usb/usb.h>
137 -#ifdef USB_GET_REPORT_ID
138 -#define USB_NEW_HID
139  #endif
140  
141  #define HUP_GENERIC_DESKTOP     0x0001
142 @@ -75,11 +108,13 @@ static const char *FindDevice(InputInfoP
143  #define DEFAULT_MOUSE_DEV               "/dev/mouse"
144  #define DEFAULT_SYSMOUSE_DEV            "/dev/sysmouse"
145  #define DEFAULT_PS2_DEV                 "/dev/psm0"
146 +#define DEFAULT_USB_DEV                 "/dev/ums0"
147  
148  static const char *mouseDevs[] = {
149          DEFAULT_MOUSE_DEV,
150          DEFAULT_SYSMOUSE_DEV,
151          DEFAULT_PS2_DEV,
152 +        DEFAULT_USB_DEV,
153          NULL
154  };
155  #elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
156 @@ -97,7 +132,7 @@ static const char *mouseDevs[] = {
157  static int
158  SupportedInterfaces(void)
159  {
160 -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__NetBSD__)
161 +#if defined(__NetBSD__)
162      return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC;
163  #else
164      return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO | MSE_MISC;
165 @@ -178,9 +213,30 @@ static struct {
166          { MOUSE_PROTO_SYSMOUSE,         "SysMouse" }
167  };
168  
169 +#ifdef XPS2_SUPPORT
170 +static struct {
171 +        int dmodel;
172 +        const char *name;
173 +} ps2proto[] = {
174 +        { MOUSE_MODEL_NETSCROLL,        "NetScrollPS/2" },
175 +        { MOUSE_MODEL_NET,              "NetMousePS/2" },
176 +        { MOUSE_MODEL_GLIDEPOINT,       "GlidePointPS/2" },
177 +        { MOUSE_MODEL_THINK,            "ThinkingMousePS/2" },
178 +        { MOUSE_MODEL_INTELLI,          "IMPS/2" },
179 +        { MOUSE_MODEL_MOUSEMANPLUS,     "MouseManPlusPS/2" },
180 +        { MOUSE_MODEL_EXPLORER,         "ExplorerPS/2" },
181 +        { MOUSE_MODEL_4D,               "IMPS/2" },
182 +        { MOUSE_MODEL_4DPLUS,           "IMPS/2" },
183 +};
184 +#endif
185 +
186  static const char *
187  SetupAuto(InputInfoPtr pInfo, int *protoPara)
188  {
189 +#ifdef XPS2_SUPPORT
190 +    const char *dev;
191 +#endif
192 +    const char *proto;
193      int i;
194      mousehw_t hw;
195      mousemode_t mode;
196 @@ -188,7 +244,13 @@ SetupAuto(InputInfoPtr pInfo, int *proto
197      if (pInfo->fd == -1)
198          return NULL;
199  
200 +#ifdef XPS2_SUPPORT
201      /* set the driver operation level, if applicable */
202 +    dev = xf86FindOptionValue(pInfo->options, "Device");
203 +    if (dev != NULL && !strncmp(dev, DEFAULT_PS2_DEV, 8))
204 +        i = 2;
205 +    else
206 +#endif
207      i = 1;
208      ioctl(pInfo->fd, MOUSE_SETLEVEL, &i);
209  
210 @@ -207,9 +269,18 @@ SetupAuto(InputInfoPtr pInfo, int *proto
211                      protoPara[0] = mode.syncmask[0];
212                      protoPara[1] = mode.syncmask[1];
213                  }
214 +                proto = devproto[i].name;
215 +#ifdef XPS2_SUPPORT
216 +                if (mode.protocol == MOUSE_PROTO_PS2)
217 +                    for (i = 0; i < sizeof(ps2proto)/sizeof(ps2proto[0]); ++i)
218 +                        if (hw.model == ps2proto[i].dmodel) {
219 +                           proto = ps2proto[i].name;
220 +                           break;
221 +                }
222 +#endif
223                  xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
224 -                            pInfo->name, devproto[i].name);
225 -                return devproto[i].name;
226 +                            pInfo->name, proto);
227 +                return proto;
228              }
229          }
230      }
231 @@ -232,41 +303,41 @@ SetSysMouseRes(InputInfoPtr pInfo, const
232          (protocol && xf86NameCmp(protocol, "SysMouse") == 0)) {
233          /*
234           * As the FreeBSD sysmouse driver defaults to protocol level 0
235 -         * every time it is opened we enforce protocol level 1 again at
236 +         * every time it is closed we enforce protocol level 1 again at
237           * this point.
238           */
239          mode.level = 1;
240      } else
241 -        mode.level = -1;
242 -#else
243 -    mode.level = -1;
244  #endif
245 +    mode.level = -1;
246      ioctl(pInfo->fd, MOUSE_SETMODE, &mode);
247  }
248  #endif
249  
250  #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
251 -
252 -#define MOUSED_PID_FILE "/var/run/moused.pid"
253 -
254  /*
255   * Try to check if moused is running.  DEFAULT_SYSMOUSE_DEV is useless without
256 - * it.  There doesn't seem to be a better way of checking.
257 + * it.  Also, try to check if the device is used by moused.  If it is opened
258 + * by moused, we do not want to use it directly.  There doesn't seem to be
259 + * a better way of checking.
260   */
261  static Bool
262 -MousedRunning(void)
263 +MousedRunning(const char *dev)
264  {
265 +    char cmd[128];
266      FILE *f = NULL;
267 -    unsigned int pid;
268 +    unsigned int i;
269  
270 -    if ((f = fopen(MOUSED_PID_FILE, "r")) != NULL) {
271 -        if (fscanf(f, "%u", &pid) == 1 && pid > 0) {
272 -            if (kill(pid, 0) == 0) {
273 -                fclose(f);
274 -                return TRUE;
275 -            }
276 +    if (dev)
277 +        sprintf(cmd, "sh -c 'fstat %s | grep -c moused' 2>/dev/null", dev);
278 +    else
279 +        sprintf(cmd, "sh -c 'pgrep -nx moused' 2>/dev/null");
280 +    if ((f = popen(cmd, "r")) != NULL) {
281 +        if (fscanf(f, "%u", &i) == 1 && i > 0) {
282 +            pclose(f);
283 +            return TRUE;
284          }
285 -        fclose(f);
286 +        pclose(f);
287      }
288      return FALSE;
289  }
290 @@ -274,17 +345,17 @@ MousedRunning(void)
291  static const char *
292  FindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
293  {
294 -    int fd = -1;
295 +    int ret = -1;
296      const char **pdev, *dev = NULL;
297      Bool devMouse = FALSE;
298      struct stat devMouseStat;
299      struct stat sb;
300  
301      for (pdev = mouseDevs; *pdev; pdev++) {
302 -        SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK));
303 -        if (fd == -1) {
304 +        SYSCALL (ret = stat(*pdev, &sb));
305 +        if (ret == -1) {
306  #ifdef DEBUG
307 -            ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno));
308 +            ErrorF("Cannot stat %s (%s)\n", *pdev, strerror(errno));
309  #endif
310          } else {
311              /*
312 @@ -293,28 +364,32 @@ FindDevice(InputInfoPtr pInfo, const cha
313               * the test for whether /dev/sysmouse is usable can be made.
314               */
315              if (!strcmp(*pdev, DEFAULT_MOUSE_DEV)) {
316 -                if (fstat(fd, &devMouseStat) == 0)
317 -                    devMouse = TRUE;
318 -                close(fd);
319 +                memcpy(&devMouseStat, &sb, sizeof(devMouseStat));
320 +                devMouse = TRUE;
321                  continue;
322              } else if (!strcmp(*pdev, DEFAULT_SYSMOUSE_DEV)) {
323                  /* Check if /dev/mouse is the same as /dev/sysmouse. */
324 -                if (devMouse && fstat(fd, &sb) == 0 &&
325 -                    devMouseStat.st_dev == sb.st_dev &&
326 +                if (devMouse && devMouseStat.st_dev == sb.st_dev &&
327                      devMouseStat.st_ino == sb.st_ino) {
328                      /* If the same, use /dev/sysmouse. */
329                      devMouse = FALSE;
330                  }
331 -                close(fd);
332 -                if (MousedRunning())
333 +                if (MousedRunning(NULL))
334                      break;
335 -                else {
336 -#ifdef DEBUG
337 -                    ErrorF("moused isn't running\n");
338 -#endif
339 -                }
340              } else {
341 -                close(fd);
342 +                /* Check if /dev/mouse is the same as this device. */
343 +                if (devMouse && devMouseStat.st_dev == sb.st_dev &&
344 +                    devMouseStat.st_ino == sb.st_ino) {
345 +                    /* If the same, use this device. */
346 +                    devMouse = FALSE;
347 +                }
348 +                if (MousedRunning(*pdev))
349 +                    continue;
350 +                /* ums(4) does not support anything but SysMouse protocol. */
351 +                if (!strncmp(*pdev, DEFAULT_USB_DEV, 8) && protocol &&
352 +                    xf86NameCmp(protocol, "auto") != 0 &&
353 +                    xf86NameCmp(protocol, "sysmouse") != 0)
354 +                    continue;
355                  break;
356              }
357          }
358 @@ -486,30 +561,78 @@ wsconsPreInit(InputInfoPtr pInfo, const
359  
360  #if defined(USBMOUSE_SUPPORT)
361  
362 +#define MAXRIDS                64
363 +#define MAXACOLS       8
364 +#define MAXLCOLS       16
365  typedef struct _UsbMseRec {
366      int packetSize;
367 -    int iid;
368 -    hid_item_t loc_x;           /* x locator item */
369 -    hid_item_t loc_y;           /* y locator item */
370 -    hid_item_t loc_z;           /* z (wheel) locator item */
371 -    hid_item_t loc_w;           /* z (wheel) locator item */
372 -    hid_item_t loc_btn[MSE_MAXBUTTONS]; /* buttons locator items */
373 -   unsigned char *buffer;
374 +    int iid, nrids, nacols, opened;
375 +    struct {
376 +       int32_t rid;
377 +       int size;
378 +    } rids[MAXRIDS];
379 +    struct UsbMseAcol {
380 +       InputInfoPtr pInfo;
381 +       int nlcols, nbuttons, hasZ, hasW;
382 +       int xmin, xmax, ymin, ymax, pmin, pmax, px, py;
383 +       int cxmin, cxmax, cymin, cymax, cpmin, cpmax;
384 +       struct UsbMseLcol {
385 +           hid_item_t loc_x;           /* x locator item */
386 +           hid_item_t loc_y;           /* y locator item */
387 +           hid_item_t loc_z;           /* z (wheel) locator item */
388 +           hid_item_t loc_w;           /* w (hwheel) locator item */
389 +           hid_item_t loc_p;           /* Tip Pressure */
390 +           hid_item_t loc_valid;               /* Touch Valid */
391 +           hid_item_t loc_in_range;    /* In Range */
392 +           hid_item_t loc_btn[MSE_MAXBUTTONS]; /* buttons locator items */
393 +       } lcols[MAXLCOLS];
394 +       hid_item_t loc_cc;              /* contact count */
395 +    } acols[MAXACOLS];
396 +    unsigned char *buffer;
397  } UsbMseRec, *UsbMsePtr;
398  
399 +static int *
400 +usbGetReportSizePtr(UsbMsePtr pUsbMse, int32_t rid)
401 +{
402 +    int i;
403 +
404 +    for (i = 0; i < pUsbMse->nrids; i++) {
405 +       if (pUsbMse->rids[i].rid == rid)
406 +           return (&pUsbMse->rids[i].size);
407 +    }
408 +    for (i = 0; i < MAXRIDS; i++) {
409 +       if (pUsbMse->rids[i].size == 0) {
410 +           pUsbMse->rids[i].rid = rid;
411 +           pUsbMse->nrids = max(pUsbMse->nrids, i + 1);
412 +           return (&pUsbMse->rids[i].size);
413 +       }
414 +    }
415 +    return (NULL);
416 +}
417 +
418  static int
419  usbMouseProc(DeviceIntPtr pPointer, int what)
420  {
421      InputInfoPtr pInfo;
422      MouseDevPtr pMse;
423      UsbMsePtr pUsbMse;
424 +    struct UsbMseAcol *acol;
425      unsigned char map[MSE_MAXBUTTONS + 1];
426 -    int nbuttons;
427 +    int nacol, nbuttons;
428 +#ifdef HAVE_LABELS
429 +    Atom btn_labels[MSE_MAXBUTTONS] = {0};
430 +    Atom axes_labels[3] = { 0, 0, 0 };
431 +#endif
432  
433      pInfo = pPointer->public.devicePrivate;
434      pMse = pInfo->private;
435      pMse->device = pPointer;
436      pUsbMse = pMse->mousePriv;
437 +    for (nacol = 0; nacol < (pUsbMse->nacols - 1); nacol++) {
438 +       if (pUsbMse->acols[nacol].pInfo == pInfo)
439 +           break;
440 +    }
441 +    acol = &pUsbMse->acols[nacol];
442  
443      switch (what) {
444      case DEVICE_INIT:
445 @@ -518,40 +641,96 @@ usbMouseProc(DeviceIntPtr pPointer, int
446          for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons)
447              map[nbuttons + 1] = nbuttons + 1;
448  
449 -        InitPointerDeviceStruct((DevicePtr)pPointer,
450 -                                map,
451 -                                min(pMse->buttons, MSE_MAXBUTTONS),
452 -                                miPointerGetMotionEvents,
453 -                                pMse->Ctrl,
454 -                                miPointerGetMotionBufferSize());
455 +#ifdef HAVE_LABELS
456 +       btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
457 +       btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
458 +       btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
459 +       axes_labels[0] = XIGetKnownProperty((acol->xmin != acol->xmax)
460 +           ? AXIS_LABEL_PROP_ABS_X : AXIS_LABEL_PROP_REL_X);
461 +       axes_labels[1] = XIGetKnownProperty((acol->xmin != acol->xmax)
462 +           ? AXIS_LABEL_PROP_ABS_Y : AXIS_LABEL_PROP_REL_Y);
463 +       axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
464 +#endif
465 +
466 +       InitButtonClassDeviceStruct(pPointer, min(pMse->buttons, MSE_MAXBUTTONS),
467 +#ifdef HAVE_LABELS
468 +           btn_labels,
469 +#endif
470 +           map);
471 +       InitValuatorClassDeviceStruct(pPointer, (acol->pmin != acol->pmax) ? 3 : 2,
472 +#ifdef HAVE_LABELS
473 +           axes_labels,
474 +#endif
475 +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
476 +           miPointerGetMotionEvents,
477 +#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
478 +           GetMotionHistory,
479 +#endif
480 +           GetMotionHistorySize(),
481 +           (acol->xmin != acol->xmax || acol->ymin != acol->ymax) ?
482 +            Absolute : Relative);
483 +       InitPtrFeedbackClassDeviceStruct(pPointer, pMse->Ctrl);
484  
485          /* X valuator */
486 -        xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1);
487 +       xf86InitValuatorAxisStruct(pPointer, 0,
488 +#ifdef HAVE_LABELS
489 +           axes_labels[0],
490 +#endif
491 +           (acol->xmin != acol->xmax) ? acol->xmin : -1,
492 +           (acol->xmin != acol->xmax) ? acol->xmax : -1,
493 +           1, 0, 1
494 +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
495 +           , (acol->xmin != acol->xmax) ? Absolute : Relative
496 +#endif
497 +           );
498          xf86InitValuatorDefaults(pPointer, 0);
499          /* Y valuator */
500 -        xf86InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1);
501 +       xf86InitValuatorAxisStruct(pPointer, 1,
502 +#ifdef HAVE_LABELS
503 +           axes_labels[1],
504 +#endif
505 +           (acol->ymin != acol->ymax) ? acol->ymin : -1,
506 +           (acol->ymin != acol->ymax) ? acol->ymax : -1,
507 +           1, 0, 1
508 +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
509 +           , (acol->ymin != acol->ymax) ? Absolute : Relative
510 +#endif
511 +           );
512          xf86InitValuatorDefaults(pPointer, 1);
513 +       /* Pressure valuator */
514 +       if (acol->pmin != acol->pmax) {
515 +           xf86InitValuatorAxisStruct(pPointer, 2,
516 +#ifdef HAVE_LABELS
517 +               axes_labels[2],
518 +#endif
519 +               acol->pmin, acol->pmax, 1, 0, 1
520 +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
521 +               , Absolute
522 +#endif
523 +               );
524 +           xf86InitValuatorDefaults(pPointer, 2);
525 +       }
526          xf86MotionHistoryAllocate(pInfo);
527          break;
528  
529      case DEVICE_ON:
530 -        pInfo->fd = xf86OpenSerial(pInfo->options);
531 -        if (pInfo->fd == -1)
532 -            xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
533 -        else {
534 -            pMse->buffer = XisbNew(pInfo->fd, pUsbMse->packetSize);
535 -            if (!pMse->buffer) {
536 -                free(pMse);
537 -                xf86CloseSerial(pInfo->fd);
538 -                pInfo->fd = -1;
539 -            } else {
540 -                xf86FlushInput(pInfo->fd);
541 -#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 23
542 -                if (!xf86InstallSIGIOHandler (pInfo->fd, usbSigioReadInput,
543 -                                              pInfo))
544 -#endif
545 -                    AddEnabledDevice(pInfo->fd);
546 -            }
547 +       if (pUsbMse->opened++ == 0) {
548 +               pInfo->fd = xf86OpenSerial(pInfo->options);
549 +               if (pInfo->fd == -1)
550 +                   xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
551 +               else {
552 +                   pMse->buffer = XisbNew(pInfo->fd, pUsbMse->packetSize);
553 +                   if (!pMse->buffer) {
554 +                       free(pMse);
555 +                       xf86CloseSerial(pInfo->fd);
556 +                       pInfo->fd = -1;
557 +                   } else {
558 +                       xf86FlushInput(pInfo->fd);
559 +                       if (!xf86InstallSIGIOHandler (pInfo->fd, usbSigioReadInput, 
560 +                                                     pInfo))
561 +                           xf86AddEnabledDevice(pInfo);
562 +                   }
563 +               }
564          }
565          pMse->lastButtons = 0;
566          pMse->lastMappedButtons = 0;
567 @@ -562,7 +741,7 @@ usbMouseProc(DeviceIntPtr pPointer, int
568      case DEVICE_OFF:
569      case DEVICE_CLOSE:
570          if (pInfo->fd != -1) {
571 -            RemoveEnabledDevice(pInfo->fd);
572 +            xf86RemoveEnabledDevice(pInfo);
573              if (pUsbMse->packetSize > 8 && pUsbMse->buffer) {
574                  free(pUsbMse->buffer);
575              }
576 @@ -573,6 +752,7 @@ usbMouseProc(DeviceIntPtr pPointer, int
577              xf86CloseSerial(pInfo->fd);
578              pInfo->fd = -1;
579          }
580 +        pUsbMse->opened--;
581          pPointer->public.on = FALSE;
582          usleep(300000);
583          break;
584 @@ -588,45 +768,154 @@ usbReadInput(InputInfoPtr pInfo)
585  {
586      MouseDevPtr pMse;
587      UsbMsePtr pUsbMse;
588 -    int buttons = pMse->lastButtons;
589 -    int dx = 0, dy = 0, dz = 0, dw = 0;
590 -    int n, c;
591 +    int buttons, cc;
592 +    int dx, dy, dz, dw, dp, upd, v, nx, ny, np, in_range;
593 +    int n, c, rid, *sizep, nacol, nlcol;
594      unsigned char *pBuf;
595 +    struct UsbMseAcol *acol;
596 +    struct UsbMseLcol *lcol;
597  
598      pMse = pInfo->private;
599      pUsbMse = pMse->mousePriv;
600  
601      XisbBlockDuration(pMse->buffer, -1);
602 +next:
603      pBuf = pUsbMse->buffer;
604      n = 0;
605 -    while ((c = XisbRead(pMse->buffer)) >= 0 && n < pUsbMse->packetSize) {
606 +    if (pUsbMse->iid) {
607 +       rid = XisbRead(pMse->buffer);
608 +       if (rid < 0)
609 +           return;
610 +       pBuf[n++] = (unsigned char)rid;
611 +    } else
612 +       rid = 0;
613 +    sizep = usbGetReportSizePtr(pUsbMse, rid);
614 +    if (sizep == NULL || *sizep == 0) {
615 +       xf86Msg(X_WARNING, "%s: unknown report ID %d\n", pInfo->name, rid);
616 +       goto next;
617 +    }
618 +    while (n < *sizep && (c = XisbRead(pMse->buffer)) >= 0) {
619          pBuf[n++] = (unsigned char)c;
620      }
621      if (n == 0)
622          return;
623 -    if (n != pUsbMse->packetSize) {
624 +//    xf86MsgVerb(X_INFO, 3, "pkt: %d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
625 +//     n, pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7], pBuf[8], pBuf[9]);
626 +    if (n != *sizep) {
627          LogMessageVerbSigSafe(X_WARNING, -1,
628                                "%s: incomplete packet, size %d\n",
629                                pInfo->name, n);
630      }
631 -    /* discard packets with an id that don't match the mouse */
632 -    /* XXX this is probably not the right thing */
633 -    if (pUsbMse->iid != 0) {
634 -        if (*pBuf++ != pUsbMse->iid)
635 -            return;
636 -    }
637 -    dx = hid_get_data(pBuf, &pUsbMse->loc_x);
638 -    dy = hid_get_data(pBuf, &pUsbMse->loc_y);
639 -    dz = hid_get_data(pBuf, &pUsbMse->loc_z);
640 -    dw = hid_get_data(pBuf, &pUsbMse->loc_w);
641 -
642 -    buttons = 0;
643 -    for (n = 0; n < pMse->buttons; n++) {
644 -        if (hid_get_data(pBuf, &pUsbMse->loc_btn[n]))
645 -            buttons |= (1 << UMS_BUT(n));
646 +    for (nacol = 0; nacol < pUsbMse->nacols; nacol++) {
647 +       acol = &pUsbMse->acols[nacol];
648 +       if (acol->pInfo == NULL)
649 +           continue;
650 +       nx = ny = np = upd = 0;
651 +       buttons = cc = 0;
652 +       dx = dy = dz = dw = dp = 0;
653 +       for (nlcol = 0; nlcol < pUsbMse->acols[nacol].nlcols; nlcol++) {
654 +           lcol = &acol->lcols[nlcol];
655 +
656 +           if (lcol->loc_valid.usage != 0 && rid == lcol->loc_valid.report_ID &&
657 +                   hid_get_data(pBuf, &lcol->loc_valid) == 0)
658 +               continue;
659 +           if (lcol->loc_in_range.usage != 0 && rid == lcol->loc_in_range.report_ID)
660 +               in_range = hid_get_data(pBuf, &lcol->loc_in_range);
661 +           else
662 +               in_range = 1;
663 +           if (in_range && lcol->loc_x.usage != 0 && rid == lcol->loc_x.report_ID && nx == 0) {
664 +               v = hid_get_data(pBuf, &lcol->loc_x);
665 +               if (acol->xmin != acol->xmax) {
666 +                   v = xf86ScaleAxis(v, acol->xmax, acol->xmin,
667 +                       lcol->loc_x.logical_maximum, lcol->loc_x.logical_minimum);
668 +                   if (acol->cxmin != acol->cxmax)
669 +                       v = xf86ScaleAxis(v, acol->xmax, acol->xmin,
670 +                           acol->cxmax, acol->cxmin);
671 +               }
672 +               dx += v;
673 +               nx++;
674 +           }
675 +           if (in_range && lcol->loc_y.usage != 0 && rid == lcol->loc_y.report_ID && ny == 0) {
676 +               v = hid_get_data(pBuf, &lcol->loc_y);
677 +               if (acol->xmin != acol->xmax) {
678 +                   v = xf86ScaleAxis(v, acol->ymax, acol->ymin,
679 +                       lcol->loc_y.logical_maximum, lcol->loc_y.logical_minimum);
680 +                   if (acol->cymin != acol->cymax)
681 +                       v = xf86ScaleAxis(v, acol->ymax, acol->ymin,
682 +                           acol->cymax, acol->cymin);
683 +               }
684 +               dy += v;
685 +               ny++;
686 +           }
687 +           if (lcol->loc_z.usage != 0 && rid == lcol->loc_z.report_ID) {
688 +               dz -= hid_get_data(pBuf, &lcol->loc_z);
689 +               upd = 1;
690 +           }
691 +           if (lcol->loc_w.usage != 0 && rid == lcol->loc_w.report_ID) {
692 +               dw += hid_get_data(pBuf, &lcol->loc_w);
693 +               upd = 1;
694 +           }
695 +           if (lcol->loc_p.usage != 0 && rid == lcol->loc_p.report_ID && np == 0) {
696 +               v = hid_get_data(pBuf, &lcol->loc_p);
697 +                   v = xf86ScaleAxis(v, acol->pmax, acol->pmin,
698 +                       lcol->loc_p.logical_maximum, lcol->loc_p.logical_minimum);
699 +                   if (acol->cpmin != acol->cpmax)
700 +                       v = xf86ScaleAxis(v, acol->pmax, acol->pmin,
701 +                           acol->cpmax, acol->cpmin);
702 +               dp += v;
703 +               np++;
704 +           }
705 +
706 +           for (n = 0; n < acol->nbuttons; n++) {
707 +               if (lcol->loc_btn[n].usage != 0 && rid == lcol->loc_btn[n].report_ID) {
708 +                   if (hid_get_data(pBuf, &lcol->loc_btn[n]))
709 +                       buttons |= (1 << UMS_BUT(n));
710 +                   upd = 1;
711 +               }
712 +           }
713 +       }
714 +       if (acol->loc_cc.usage != 0 && rid == acol->loc_cc.report_ID)
715 +           cc = hid_get_data(pBuf, &acol->loc_cc);
716 +       else
717 +           cc = (nx || ny) ? 1 : 0;
718 +       if (cc > 1)
719 +           buttons = (1 << UMS_BUT(1));
720 +       if (nx != 0 && acol->xmin != acol->xmax)
721 +           dx /= nx;
722 +       if (ny != 0 && acol->ymin != acol->ymax)
723 +           dy /= ny;
724 +       if (np != 0 && acol->pmin != acol->pmax)
725 +           dp /= np;
726 +//     if (upd || nx || ny || np)
727 +//         xf86MsgVerb(X_INFO, 3, "%d cc %d dx %d dy %d dz %d dw %d press %d buttons %02x\n",
728 +//             nacol, cc, dx, dy, dz, dw, dp, buttons);
729 +       if (nx != 0 || ny != 0) {
730 +           if (acol->pmin != acol->pmax) {
731 +               xf86PostMotionEvent(acol->pInfo->dev,
732 +                           /* is_absolute: */    TRUE,
733 +                           /* first_valuator: */ 0,
734 +                           /* num_valuators: */  3,
735 +                           dx, dy, dp);
736 +           } else if (acol->xmin != acol->xmax || acol->ymin != acol->ymax) {
737 +               xf86PostMotionEvent(acol->pInfo->dev,
738 +                           /* is_absolute: */    TRUE,
739 +                           /* first_valuator: */ 0,
740 +                           /* num_valuators: */  2,
741 +                           dx, dy);
742 +           }
743 +       }
744 +       if (upd || (nx != 0) || (ny != 0)) {
745 +           ((MouseDevPtr)acol->pInfo->private)->PostEvent(acol->pInfo, buttons,
746 +               ((acol->xmin != acol->xmax) ? dx - acol->px : dx),
747 +               ((acol->ymin != acol->ymax) ? dy - acol->py : dy),
748 +               dz, dw);
749 +       }
750 +       if (nx > 0)
751 +           acol->px = dx;
752 +       if (ny > 0)
753 +           acol->py = dy;
754      }
755 -    pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
756 -    return;
757 +    goto next;
758  }
759  
760  static void
761 @@ -635,14 +924,17 @@ usbSigioReadInput (int fd, void *closure
762      usbReadInput ((InputInfoPtr) closure);
763  }
764  
765 -/* This function is called when the protocol is "usb". */
766  static Bool
767 -usbPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
768 +usbInitFirst(InputInfoPtr pInfo)
769  {
770      MouseDevPtr pMse = pInfo->private;
771      UsbMsePtr pUsbMse;
772      report_desc_t reportDesc;
773 -    int i;
774 +    hid_data_t d;
775 +    hid_item_t h;
776 +    struct UsbMseAcol *acol;
777 +    struct UsbMseLcol *lcol;
778 +    int mdepth, rsize, *rsizep, acolused, lcolused, used;
779  
780      pUsbMse = malloc(sizeof(UsbMseRec));
781      if (pUsbMse == NULL) {
782 @@ -651,12 +943,7 @@ usbPreInit(InputInfoPtr pInfo, const cha
783          return FALSE;
784      }
785  
786 -    pMse->protocol = protocol;
787 -    xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
788 -
789 -    /* Collect the options, and process the common options. */
790 -    COLLECT_INPUT_OPTIONS(pInfo, NULL);
791 -    xf86ProcessCommonOptions(pInfo, pInfo->options);
792 +    bzero(pUsbMse, sizeof(UsbMseRec));
793  
794      /* Check if the device can be opened. */
795      pInfo->fd = xf86OpenSerial(pInfo->options);
796 @@ -672,19 +959,134 @@ usbPreInit(InputInfoPtr pInfo, const cha
797      }
798      /* Get USB information */
799      reportDesc = hid_get_report_desc(pInfo->fd);
800 -    /* Get packet size & iid */
801 -#ifdef USB_NEW_HID
802 -    if (ioctl(pInfo->fd, USB_GET_REPORT_ID, &pUsbMse->iid) == -1) {
803 -            xf86Msg(X_ERROR, "Error ioctl USB_GET_REPORT_ID on %s : %s\n",
804 -                    pInfo->name, strerror(errno));
805 -            return FALSE;
806 -    }
807 -    pUsbMse->packetSize = hid_report_size(reportDesc, hid_input,
808 -                                              pUsbMse->iid);
809 -#else
810 -    pUsbMse->packetSize = hid_report_size(reportDesc, hid_input,
811 -                                              &pUsbMse->iid);
812 -#endif
813 +    mdepth = 0;
814 +    pUsbMse->nacols = 0;
815 +    acol = &pUsbMse->acols[pUsbMse->nacols];
816 +    lcol = &acol->lcols[acol->nlcols];
817 +    acolused = 0;
818 +    lcolused = 0;
819 +    d = hid_start_parse(reportDesc, (1 << hid_input) |
820 +       (1 << hid_collection) | (1 << hid_endcollection), -1);
821 +    while (hid_get_item(d, &h)) {
822 +       switch (h.kind) {
823 +       case hid_collection:
824 +           if (mdepth != 0)
825 +               mdepth++;
826 +           else if (h.collection == 1 &&
827 +                   (h.usage == 0x00010001 || h.usage == 0x00010002 ||
828 +                    (h.usage >= 0x000d0001 && h.usage <= 0x000d000d))) {
829 +               mdepth++;
830 +               if (acolused) {
831 +                   if (lcolused) {
832 +                       acol->nlcols++;
833 +                       lcolused = 0;
834 +                   }
835 +                   pUsbMse->nacols++;
836 +                   acolused = 0;
837 +                   acol = &pUsbMse->acols[pUsbMse->nacols];
838 +                   lcol = &acol->lcols[acol->nlcols];
839 +               }
840 +           }
841 +           if (lcolused && (h.collection == 0 ||
842 +                   h.collection == 2 || h.collection == 3)) {
843 +               acol->nlcols++;
844 +               lcolused = 0;
845 +               lcol = &acol->lcols[acol->nlcols];
846 +           }
847 +           break;
848 +       case hid_endcollection:
849 +           if (mdepth != 0)
850 +               mdepth--;
851 +           break;
852 +       case hid_input:
853 +           if (h.report_ID != 0)
854 +               pUsbMse->iid = 1;
855 +           rsize = pUsbMse->iid +
856 +               (h.pos + (h.report_size * h.report_count) + 7) / 8;
857 +           if ((rsizep = usbGetReportSizePtr(pUsbMse, h.report_ID)) != NULL)
858 +               *rsizep = max(*rsizep, rsize);
859 +           pUsbMse->packetSize = max(pUsbMse->packetSize, rsize);
860 +           if (mdepth == 0)
861 +               break;
862 +           used = 1;
863 +           if (h.usage == 0x00010030) { /* X */
864 +               lcol->loc_x = h;
865 +               if ((h.flags & 0x04) == 0) {
866 +                   if (acol->xmin == acol->xmax) {
867 +                       acol->xmin = h.logical_minimum;
868 +                       acol->xmax = h.logical_maximum;
869 +                   } else {
870 +                       acol->xmin = min(acol->xmin, h.logical_minimum);
871 +                       acol->xmax = max(acol->xmax, h.logical_maximum);
872 +                   }
873 +               }
874 +           } else if (h.usage == 0x00010031) { /* Y */
875 +               lcol->loc_y = h;
876 +               if ((h.flags & 0x04) == 0) {
877 +                   if (acol->ymin == acol->ymax) {
878 +                       acol->ymin = h.logical_minimum;
879 +                       acol->ymax = h.logical_maximum;
880 +                   } else {
881 +                       acol->ymin = min(acol->ymin, h.logical_minimum);
882 +                       acol->ymax = max(acol->ymax, h.logical_maximum);
883 +                   }
884 +               }
885 +           } else if (h.usage == 0x00010038) { /* Z */
886 +               lcol->loc_z = h;
887 +               acol->hasZ = 1;
888 +           } else if (h.usage == 0x000c0238) { /* W */
889 +               lcol->loc_w = h;
890 +               acol->hasW = 1;
891 +           } else if (h.usage == 0x000d0030) { /* Press */
892 +               lcol->loc_p = h;
893 +               if ((h.flags & 0x04) == 0) {
894 +                   if (acol->pmin == acol->pmax) {
895 +                       acol->pmin = h.logical_minimum;
896 +                       acol->pmax = h.logical_maximum;
897 +                   } else {
898 +                       acol->pmin = min(acol->pmin, h.logical_minimum);
899 +                       acol->pmax = max(acol->pmax, h.logical_maximum);
900 +                   }
901 +               }
902 +           } else if (h.usage == 0x000d0032) /* In Range */
903 +               lcol->loc_in_range = h;
904 +           else if (h.usage == 0x000d0047) /* Valid */
905 +               lcol->loc_valid = h;
906 +           else if (h.usage > 0x00090000 &&
907 +               h.usage <= 0x00090000 + MSE_MAXBUTTONS) { /* Buttons */
908 +                   lcol->loc_btn[(h.usage & 0xffff) - 1] = h;
909 +                   acol->nbuttons = max(acol->nbuttons, h.usage & 0xffff);
910 +           } else if (h.usage == 0x000d0042) { /* Tip Switch */
911 +               lcol->loc_btn[0] = h;
912 +               acol->nbuttons = max(acol->nbuttons, 1);
913 +           } else if (h.usage == 0x000d0044) { /* Barrel Switch */
914 +               lcol->loc_btn[1] = h;
915 +               acol->nbuttons = max(acol->nbuttons, 2);
916 +           } else if (h.usage == 0x000d0045) { /* Eraser */
917 +               lcol->loc_btn[3] = h;
918 +               acol->nbuttons = max(acol->nbuttons, 4);
919 +           } else if (h.usage == 0x000d0046) { /* Tablet Pick */
920 +               lcol->loc_btn[2] = h;
921 +               acol->nbuttons = max(acol->nbuttons, 3);
922 +           } else if (h.usage == 0x000d0054) /* Contact Count */
923 +               acol->loc_cc = h;
924 +           else
925 +               used = 0;
926 +           lcolused += used;
927 +           acolused += used;
928 +           break;
929 +       default:
930 +           break;
931 +       }
932 +    }
933 +    if (lcolused)
934 +       acol->nlcols++;
935 +    if (acolused)
936 +       pUsbMse->nacols++;
937 +    hid_end_parse(d);
938 +    xf86Msg(X_DEFAULT, "%s: Found %d usable logical collections\n",
939 +       pInfo->name, pUsbMse->nacols);
940 +
941      /* Allocate buffer */
942      if (pUsbMse->packetSize <= 8) {
943          pUsbMse->buffer = pMse->protoBuf;
944 @@ -694,56 +1096,129 @@ usbPreInit(InputInfoPtr pInfo, const cha
945      if (pUsbMse->buffer == NULL) {
946          xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name);
947          free(pUsbMse);
948 -        free(pMse);
949          xf86CloseSerial(pInfo->fd);
950          return FALSE;
951      }
952 -#ifdef USB_NEW_HID
953 -    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
954 -                   hid_input, &pUsbMse->loc_x, pUsbMse->iid) < 0) {
955 -        xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name);
956 -    }
957 -    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
958 -                   hid_input, &pUsbMse->loc_y, pUsbMse->iid) < 0) {
959 -        xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name);
960 -    }
961 -    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
962 -                   hid_input, &pUsbMse->loc_z, pUsbMse->iid) < 0) {
963 -    }
964 -#else
965 -    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
966 -                   hid_input, &pUsbMse->loc_x) < 0) {
967 -        xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name);
968 -    }
969 -    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
970 -                   hid_input, &pUsbMse->loc_y) < 0) {
971 -        xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name);
972 -    }
973 -    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
974 -                   hid_input, &pUsbMse->loc_z) < 0) {
975 -    }
976 -#endif
977 -    /* Probe for number of buttons */
978 -    for (i = 1; i <= MSE_MAXBUTTONS; i++) {
979 -        if (!hid_locate(reportDesc, HID_USAGE2(HUP_BUTTON, i),
980 -                        hid_input, &pUsbMse->loc_btn[i-1]
981 -#ifdef USB_NEW_HID
982 -                        , pUsbMse->iid
983 -#endif
984 -                        ))
985 -            break;
986 -    }
987 -    pMse->buttons = i-1;
988  
989      xf86CloseSerial(pInfo->fd);
990      pInfo->fd = -1;
991  
992      /* Private structure */
993      pMse->mousePriv = pUsbMse;
994 +    return TRUE;
995 +}
996 +
997 +/* This function is called when the protocol is "usb". */
998 +static Bool
999 +usbPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
1000 +{
1001 +    InputInfoPtr pMatch;
1002 +    MouseDevPtr pMse = pInfo->private;
1003 +    UsbMsePtr pUsbMse;
1004 +    struct UsbMseAcol *acol;
1005 +    char *str;
1006 +    int i, colopt;
1007 +
1008 +    pMse->protocol = protocol;
1009 +    xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
1010 +
1011 +    /* Collect the options, and process the common options. */
1012 +    COLLECT_INPUT_OPTIONS(pInfo, NULL);
1013 +    xf86ProcessCommonOptions(pInfo, pInfo->options);
1014 +
1015 +    /* Check if this HID device is already opened. */
1016 +    for (pMatch = xf86FirstLocalDevice(); pMatch != NULL; pMatch = pMatch->next) {
1017 +       if ((pInfo != pMatch) && strstr(pMatch->drv->driverName, "mouse")) {
1018 +           char *dev1, *dev2;
1019 +
1020 +           dev1 = xf86SetStrOption(pInfo->options, "Device", NULL);
1021 +           dev2 = xf86SetStrOption(pMatch->options, "Device", NULL);
1022 +           if (strcmp(dev1, dev2) == 0) {
1023 +               free(dev1);
1024 +               free(dev2);
1025 +               break;
1026 +           }
1027 +           free(dev1);
1028 +           free(dev2);
1029 +       }
1030 +    }
1031 +    if (pMatch == NULL) {
1032 +       xf86Msg(X_DEFAULT, "%s: Opening new HID device\n", pInfo->name);
1033 +       if (!usbInitFirst(pInfo)) {
1034 +           free(pMse);
1035 +           return FALSE;
1036 +       }
1037 +    } else {
1038 +       pMse->mousePriv = ((MouseDevPtr)pMatch->private)->mousePriv;
1039 +       xf86Msg(X_DEFAULT, "%s: Attaching to already opened HID device\n",
1040 +           pInfo->name);
1041 +    }
1042 +    pUsbMse = pMse->mousePriv;
1043 +
1044 +    /* Attach to collection, respecting "Collection" option. */
1045 +    colopt = xf86SetIntOption(pInfo->options, "Collection", 0);
1046 +    for (i = 0; i < pUsbMse->nacols; i++) {
1047 +       if (pUsbMse->acols[i].pInfo == NULL &&
1048 +               (colopt == 0 || i == colopt - 1)) {
1049 +           pUsbMse->acols[i].pInfo = pInfo;
1050 +           break;
1051 +       }
1052 +    }
1053 +    xf86Msg(colopt == 0 ? X_DEFAULT : X_CONFIG,
1054 +       "%s: Collection: %d\n", pInfo->name,
1055 +       i == pUsbMse->nacols ? colopt : i + 1);
1056 +    if (i == pUsbMse->nacols) {
1057 +       xf86Msg(X_ERROR,
1058 +           "%s: Application collection not found or already handled\n",
1059 +           pInfo->name);
1060 +       free(pMse);
1061 +       return FALSE;
1062 +    }
1063 +
1064 +    acol = &pUsbMse->acols[i];
1065 +    pMse->buttons = acol->nbuttons;
1066 +    if (pMse->buttons == 2)
1067 +       pMse->buttons = 3;
1068 +    if (acol->xmin != acol->xmax || acol->ymin != acol->ymax)
1069 +       pMse->disableXY = TRUE;
1070 +    pMse->hasZ = acol->hasZ;
1071 +    pMse->hasW = acol->hasW;
1072  
1073      /* Process common mouse options (like Emulate3Buttons, etc). */
1074      pMse->CommonOptions(pInfo);
1075  
1076 +    /* Process "Calibration" option. */
1077 +    str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
1078 +    if (str != NULL && (acol->xmin != acol->xmax || acol->ymin != acol->ymax)) {
1079 +       int j, xmin, xmax, ymin, ymax, pmin, pmax;
1080 +
1081 +       j = sscanf(str, "%d %d %d %d %d %d", &xmin, &xmax, &ymin, &ymax, &pmin, &pmax);
1082 +       if (j == 4) {
1083 +           xf86Msg(X_CONFIG, "%s: Calibration: %d %d %d %d\n",
1084 +               pInfo->name, xmin, xmax, ymin, ymax);
1085 +           acol->cxmin = xmin;
1086 +           acol->cxmax = xmax;
1087 +           acol->cymin = ymin;
1088 +           acol->cymax = ymax;
1089 +       } else if (j == 6) {
1090 +           xf86Msg(X_CONFIG, "%s: Calibration: %d %d %d %d %d %d\n",
1091 +               pInfo->name, xmin, xmax, ymin, ymax, pmin, pmax);
1092 +           acol->cxmin = xmin;
1093 +           acol->cxmax = xmax;
1094 +           acol->cymin = ymin;
1095 +           acol->cymax = ymax;
1096 +           acol->cpmin = pmin;
1097 +           acol->cpmax = pmax;
1098 +       } else
1099 +           xf86Msg(X_WARNING, "%s: Calibration: Invalid arguments\n",
1100 +               pInfo->name);
1101 +       free(str);
1102 +    } else if (acol->xmin != acol->xmax || acol->ymin != acol->ymax) {
1103 +       xf86Msg(X_DEFAULT, "%s: Calibration: %d %d %d %d %d %d\n",
1104 +           pInfo->name, acol->xmin, acol->xmax, acol->ymin, acol->ymax,
1105 +           acol->pmin, acol->pmax);
1106 +    }
1107 +
1108      /* Setup the local procs. */
1109      pInfo->device_control = usbMouseProc;
1110      pInfo->read_input = usbReadInput;
1111 @@ -786,7 +1261,9 @@ OSMouseInit(int flags)
1112      p->CheckProtocol = CheckProtocol;
1113  #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE)
1114      p->SetupAuto = SetupAuto;
1115 +#ifndef XPS2_SUPPORT
1116      p->SetPS2Res = SetSysMouseRes;
1117 +#endif
1118      p->SetBMRes = SetSysMouseRes;
1119      p->SetMiscRes = SetSysMouseRes;
1120  #endif
1121
1122
1123 [FILE:7410:patches/patch-src_mouse.c]
1124 --- src/mouse.c.orig    2023-05-05 00:25:20 UTC
1125 +++ src/mouse.c
1126 @@ -310,13 +310,39 @@ MouseCommonOptions(InputInfoPtr pInfo)
1127  
1128      pMse = pInfo->private;
1129  
1130 -    pMse->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0);
1131 +    i = xf86SetIntOption(pInfo->options, "Buttons", 0);
1132 +    if (i != 0)
1133 +        pMse->buttons = i;
1134      if (!pMse->buttons) {
1135          pMse->buttons = MSE_DFLTBUTTONS;
1136          buttons_from = X_DEFAULT;
1137      }
1138      origButtons = pMse->buttons;
1139  
1140 +    s = xf86SetStrOption(pInfo->options, "ButtonMapping", NULL);
1141 +    if (s) {
1142 +        int b, n = 0;
1143 +        char *s1 = s;
1144 +        /* keep getting numbers which are buttons */
1145 +        while (s1 && n < MSE_MAXBUTTONS && (b = strtol(s1, &s1, 10)) != 0) {
1146 +            /* check sanity for a button */
1147 +            if (b < 0 || b > MSE_MAXBUTTONS) {
1148 +                xf86Msg(X_WARNING,
1149 +                        "ButtonMapping: Invalid button number = %d\n", b);
1150 +                break;
1151 +           };
1152 +           pMse->buttonMap[n++] = 1 << (b-1);
1153 +           if (b > pMse->buttons) pMse->buttons = b;
1154 +        }
1155 +        free(s);
1156 +    }
1157 +    /* get maximum of mapped buttons */
1158 +    for (i = pMse->buttons-1; i >= 0; i--) {
1159 +        int f = ffs (pMse->buttonMap[i]);
1160 +        if (f > pMse->buttons)
1161 +            pMse->buttons = f;
1162 +    }
1163 +
1164      pMse->emulate3Buttons = xf86SetBoolOption(pInfo->options,
1165                                                "Emulate3Buttons", FALSE);
1166      if (!xf86FindOptionValue(pInfo->options,"Emulate3Buttons")) {
1167 @@ -328,6 +354,8 @@ MouseCommonOptions(InputInfoPtr pInfo)
1168                                               "Emulate3Timeout", 50);
1169      if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft) {
1170          MessageType from = X_CONFIG;
1171 +       if (pMse->buttons < 3)
1172 +            pMse->buttons = 3;
1173          if (pMse->emulate3ButtonsSoft)
1174              from = X_DEFAULT;
1175          xf86Msg(from, "%s: Emulate3Buttons, Emulate3Timeout: %d\n",
1176 @@ -335,6 +363,8 @@ MouseCommonOptions(InputInfoPtr pInfo)
1177      }
1178  
1179      pMse->chordMiddle = xf86SetBoolOption(pInfo->options, "ChordMiddle", FALSE);
1180 +    if (pMse->chordMiddle && pMse->buttons < 3)
1181 +           pMse->buttons = 3;
1182      pMse->flipXY = xf86SetBoolOption(pInfo->options, "FlipXY", FALSE);
1183      if (xf86SetBoolOption(pInfo->options, "InvX", FALSE)) {
1184          pMse->invX = -1;
1185 @@ -345,7 +375,7 @@ MouseCommonOptions(InputInfoPtr pInfo)
1186      } else
1187          pMse->invY = 1;
1188      pMse->angleOffset = xf86SetIntOption(pInfo->options, "AngleOffset", 0);
1189 -
1190 +    pMse->sensitivity = xf86SetRealOption(pInfo->options, "Sensitivity", 1.0);
1191  
1192      if (pMse->pDragLock)
1193          free(pMse->pDragLock);
1194 @@ -455,14 +485,17 @@ MouseCommonOptions(InputInfoPtr pInfo)
1195          free(s);
1196      }
1197  
1198 -    s = xf86SetStrOption(pInfo->options, "ZAxisMapping", "4 5");
1199 +    s = xf86SetStrOption(pInfo->options, "ZAxisMapping",
1200 +        pMse->hasZ ? ( pMse->hasW ? "4 5 6 7" : "4 5" ) : "off");
1201      if (s) {
1202          int b1 = 0, b2 = 0, b3 = 0, b4 = 0;
1203          char *msg = NULL;
1204  
1205          pMse->negativeZ = pMse->positiveZ = MSE_NOAXISMAP;
1206          pMse->negativeW = pMse->positiveW = MSE_NOAXISMAP;
1207 -        if (!xf86NameCmp(s, "x")) {
1208 +        if (!xf86NameCmp(s, "off")) {
1209 +            msg = xstrdup("off");
1210 +       } else if (!xf86NameCmp(s, "x")) {
1211              pMse->negativeZ = pMse->positiveZ = MSE_MAPTOX;
1212              msg = xstrdup("X axis");
1213          } else if (!xf86NameCmp(s, "y")) {
1214 @@ -611,29 +644,6 @@ MouseCommonOptions(InputInfoPtr pInfo)
1215                  pInfo->name, wheelButton, pMse->wheelInertia,
1216                  pMse->wheelButtonTimeout);
1217      }
1218 -    s = xf86SetStrOption(pInfo->options, "ButtonMapping", NULL);
1219 -    if (s) {
1220 -       int b, n = 0;
1221 -       char *s1 = s;
1222 -       /* keep getting numbers which are buttons */
1223 -       while (s1 && n < MSE_MAXBUTTONS && (b = strtol(s1, &s1, 10)) != 0) {
1224 -           /* check sanity for a button */
1225 -           if (b < 0 || b > MSE_MAXBUTTONS) {
1226 -               xf86Msg(X_WARNING,
1227 -                       "ButtonMapping: Invalid button number = %d\n", b);
1228 -               break;
1229 -           };
1230 -           pMse->buttonMap[n++] = 1 << (b-1);
1231 -           if (b > pMse->buttons) pMse->buttons = b;
1232 -       }
1233 -       free(s);
1234 -    }
1235 -    /* get maximum of mapped buttons */
1236 -    for (i = pMse->buttons-1; i >= 0; i--) {
1237 -        int f = ffs (pMse->buttonMap[i]);
1238 -        if (f > pMse->buttons)
1239 -            pMse->buttons = f;
1240 -    }
1241      if (origButtons != pMse->buttons)
1242          buttons_from = X_CONFIG;
1243      xf86Msg(buttons_from, "%s: Buttons: %d\n", pInfo->name, pMse->buttons);
1244 @@ -715,7 +725,6 @@ MouseHWOptions(InputInfoPtr pInfo)
1245      }
1246      pMse->sampleRate = xf86SetIntOption(pInfo->options, "SampleRate", 0);
1247      pMse->resolution = xf86SetIntOption(pInfo->options, "Resolution", 0);
1248 -    mPriv->sensitivity = xf86SetRealOption(pInfo->options, "Sensitivity", 1.0);
1249  }
1250  
1251  static void
1252 @@ -1002,6 +1011,8 @@ MousePreInit(InputDriverPtr drv, InputIn
1253      /* Default Mapping: 1 2 3 8 9 10 11 ... */
1254      for (i = 0; i < MSE_MAXBUTTONS; i++)
1255          pMse->buttonMap[i] = 1 << (i > 2 && i < MSE_MAXBUTTONS-4 ? i+4 : i);
1256 +    pMse->hasZ = 1;
1257 +    pMse->hasW = 0;
1258  
1259      protocol = MousePickProtocol(pInfo, device, protocol, &protocolID);
1260  
1261 @@ -2203,7 +2214,7 @@ MouseDoPostEvent(InputInfoPtr pInfo, int
1262  
1263      if (pMse->emulateWheel) {
1264          /* Emulate wheel button handling */
1265 -        if(pMse->wheelButton == 0)
1266 +        if (pMse->wheelButton == 0)
1267              wheelButtonMask = 0;
1268          else
1269              wheelButtonMask = 1 << (pMse->wheelButton - 1);
1270 @@ -2293,6 +2304,9 @@ MouseDoPostEvent(InputInfoPtr pInfo, int
1271                          }
1272                      }
1273                  }
1274 +            } else {
1275 +                pMse->wheelXDistance = 0;
1276 +                pMse->wheelYDistance = 0;
1277              }
1278  
1279              /* Absorb the mouse movement while the wheel button is pressed. */
1280 @@ -2310,7 +2324,7 @@ MouseDoPostEvent(InputInfoPtr pInfo, int
1281      if (pMse->emulate3ButtonsSoft && pMse->emulate3Pending && (dx || dy))
1282          buttonTimer(pInfo);
1283  
1284 -    if (dx || dy)
1285 +    if ((dx || dy) && !pMse->disableXY)
1286          xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
1287  
1288      if (change) {
1289 @@ -2423,12 +2437,10 @@ MousePostEvent(InputInfoPtr pInfo, int t
1290                 int dx, int dy, int dz, int dw)
1291  {
1292      MouseDevPtr pMse;
1293 -    mousePrivPtr mousepriv;
1294      int zbutton = 0, wbutton = 0, zbuttoncount = 0, wbuttoncount = 0;
1295      int i, b, buttons = 0;
1296  
1297      pMse = pInfo->private;
1298 -    mousepriv = (mousePrivPtr)pMse->mousePriv;
1299  
1300      if (pMse->protocolID == PROT_MMHIT)
1301          b = reverseBits(hitachMap, truebuttons);
1302 @@ -2521,11 +2533,11 @@ MousePostEvent(InputInfoPtr pInfo, int t
1303  
1304      /* Accumulate the scaled dx, dy in the private variables
1305         fracdx,fracdy and return the integer number part */
1306 -    if (mousepriv) {
1307 -        mousepriv->fracdx += mousepriv->sensitivity*dx;
1308 -        mousepriv->fracdy += mousepriv->sensitivity*dy;
1309 -        mousepriv->fracdx -= ( dx=(int)(mousepriv->fracdx) );
1310 -        mousepriv->fracdy -= ( dy=(int)(mousepriv->fracdy) );
1311 +    if (pMse->sensitivity != 0) {
1312 +        pMse->fracdx += pMse->sensitivity*dx;
1313 +        pMse->fracdy += pMse->sensitivity*dy;
1314 +        pMse->fracdx -= ( dx=(int)(pMse->fracdx) );
1315 +        pMse->fracdy -= ( dy=(int)(pMse->fracdy) );
1316      }
1317  
1318      /* If mouse wheel movement has to be mapped on a button, we need to
1319
1320
1321 [FILE:1020:patches/patch-src_mouse.h]
1322 --- src/mouse.h.orig    2023-05-05 00:25:20 UTC
1323 +++ src/mouse.h
1324 @@ -220,10 +220,13 @@ typedef struct _MouseDevRec {
1325      Bool                emulate3ButtonsSoft;
1326      int                 emulate3Timeout;/* Timeout for 3 button emulation */
1327      Bool                chordMiddle;
1328 +    Bool                disableXY;
1329      Bool                flipXY;
1330      int                 invX;
1331      int                 invY;
1332      int                 resolution;
1333 +    Bool                hasW;
1334 +    Bool                hasZ;
1335      int                 negativeZ;      /* button mask */
1336      int                 positiveZ;      /* button mask */
1337      int                 negativeW;      /* button mask */
1338 @@ -262,6 +265,8 @@ typedef struct _MouseDevRec {
1339      int                 doubleClickOldSourceState;
1340      int                 lastMappedButtons;
1341      int                 buttonMap[MSE_MAXBUTTONS];
1342 +    float               fracdx,fracdy;
1343 +    float               sensitivity;
1344  } MouseDevRec, *MouseDevPtr;
1345  
1346  #endif /* _XF86OSMOUSE_H_ */
1347
1348
1349 [FILE:306:patches/patch-src_mousePriv.h]
1350 --- src/mousePriv.h.orig        2023-05-05 00:25:20 UTC
1351 +++ src/mousePriv.h
1352 @@ -63,8 +63,6 @@ typedef struct {
1353      int         acc;
1354      CARD32      pnpLast;
1355      Bool        disablePnPauto;
1356 -    float       fracdx,fracdy;
1357 -    float       sensitivity;
1358  } mousePrivRec, *mousePrivPtr;
1359  
1360  /* mouse proto flags */
1361
1362
1363 [FILE:577:dragonfly/patch-src_Makefile.in]
1364 --- src/Makefile.in.orig        2023-05-05 00:25:27 UTC
1365 +++ src/Makefile.in
1366 @@ -363,7 +363,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include $(
1367  # _ladir passes a dummy rpath to libtool so the thing will actually link
1368  # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
1369  @DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
1370 -@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
1371 +@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version -lusbhid
1372  @DRIVER_NAME@_drv_ladir = @inputdir@
1373  
1374  # We have to list all the mouse drivers here, even if we don't build them, so
1375
1376
1377 [FILE:577:freebsd/patch-src_Makefile.in]
1378 --- src/Makefile.in.orig        2023-05-05 00:25:27 UTC
1379 +++ src/Makefile.in
1380 @@ -363,7 +363,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include $(
1381  # _ladir passes a dummy rpath to libtool so the thing will actually link
1382  # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
1383  @DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
1384 -@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
1385 +@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version -lusbhid
1386  @DRIVER_NAME@_drv_ladir = @inputdir@
1387  
1388  # We have to list all the mouse drivers here, even if we don't build them, so
1389