NetBSD Problem Report #50068

From www@NetBSD.org  Mon Jul 20 04:42:32 2015
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 8132CA5674
	for <gnats-bugs@gnats.NetBSD.org>; Mon, 20 Jul 2015 04:42:32 +0000 (UTC)
Message-Id: <20150720044227.C8518A6555@mollari.NetBSD.org>
Date: Mon, 20 Jul 2015 04:42:27 +0000 (UTC)
From: davshao@gmail.com
Reply-To: davshao@gmail.com
To: gnats-bugs@NetBSD.org
Subject: x11/xf86-input-mouse dports patches for DragonFly and FreeBSD
X-Send-Pr-Version: www-1.0

>Number:         50068
>Category:       pkg
>Synopsis:       x11/xf86-input-mouse dports patches for DragonFly and FreeBSD
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Jul 20 04:45:00 +0000 2015
>Last-Modified:  Fri Jul 24 03:40:01 +0000 2015
>Originator:     David Shao
>Release:        pkgsrc current cvs
>Organization:
>Environment:
DragonFly  4.3-DEVELOPMENT DragonFly v4.2.2.63.ga2b9b7-DEVELOPMENT #1: Sun Jul 19 19:22:57 PDT 2015     xxxxx@:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64

>Description:
Patches from DragonFly dports to x11/xf86-input-mouse are needed for DragonFly and FreeBSD to use a USB mouse in newer Xorg.  (There is a workaround for DragonFly using moused called from /etc/rc.conf, but I can't get that workaround to succeed on FreeBSD 10.1.  Also the DragonFly rc.conf invocation of moused has been unreliable for use with pkgsrc in the past.)

There are some complications.  A new options.mk file seems to require 3 new options just to distinguish between three possible include paths for the usb header file depending on the OS.  (This problem applies to other ports.  It is fortunate that sysutils/hal is being phased out.)  Unfortunately older DragonFly, newer DragonFly, and FreeBSD have three different possible paths.  Also one of the patches is gigantic.  Apart from trying to understand such a large patch, it is quite possible I have made mistakes merging the patch from dports.

I have tried to enclose all of the new code in ifdefs on symbol FREEBSD_USB, and supplanted code in !defined(FREEBSD_USB) blocks.  The functionality should be completely unaffected on non-DragonFly and non-FreeBSD platforms.

The patch itself ask why some of the logic for detecting OS and OS version isn't performed by patching configure scripts, but offers no such solution.  
>How-To-Repeat:

>Fix:
A small patch to Makefile for the new options.mk:

--- Makefile.orig	2015-07-18 18:48:26.000000000 -0700
+++ Makefile	2015-07-18 22:40:51.000000000 -0700
@@ -20,6 +20,8 @@
 CONFIGURE_ENV+=	DRIVER_MAN_SUFFIX=4
 .endif

+.include "options.mk"
+
 .include "../../x11/randrproto/buildlink3.mk"
 .include "../../x11/inputproto/buildlink3.mk"
 .include "../../x11/kbproto/buildlink3.mk"

The new options.mk:

PKG_OPTIONS_VAR=        PKG_OPTIONS.xf86-input-mouse
# dflyu4b is for DragonFly BSD newer USB stack, ported from newer FreeBSD
#     #include <bus/u4b/usb.h>
# dflyusb is for DragonFly BSD older USB stack, OS version < 300703
#     #include <bus/usb/usb.h>
# fbsdusb is for FreeBSD USB stack 
#     #include <dev/usb/usb.h>
PKG_SUPPORTED_OPTIONS= dflyu4b dflyusb fbsdusb 
PKG_SUGGESTED_OPTIONS=

.if ${OPSYS} == "DragonFly"
.if !empty(OS_VERSION:M[0-2].*) || !empty(OS_VERSION:M3.0*)
PKG_SUGGESTED_OPTIONS+= dflyusb 
.else
# Assume Dragonfly 3.1 - 3.6 users built U4B stack
# 3.8 and after U4B is the default
PKG_SUGGESTED_OPTIONS+= dflyu4b 
.endif
.endif

.if ${OPSYS} == "FreeBSD"
PKG_SUGGESTED_OPTIONS+= fbsdusb
.endif

.include "../../mk/bsd.options.mk"

.if !empty(PKG_OPTIONS:Mdflyu4b) || !empty(PKG_OPTIONS:Mdflyusb) || !empty(PKG_OPTIONS:Mfbsdusb)
CPPFLAGS+=	-DFREEBSD_USB
.endif

.if !empty(PKG_OPTIONS:Mdflyu4b)
CPPFLAGS+=	-DDRAGONFLY_U4B
.endif

.if !empty(PKG_OPTIONS:Mdflyusb)
CPPFLAGS+=	-DDRAGONFLY_USB
.endif

.if !empty(PKG_OPTIONS:Mdflyu4b) || !empty(PKG_OPTIONS:Mdflyusb) || !empty(PKG_OPTIONS:Mfbsdusb)
SUBST_CLASSES+=                 freebsdusb 
SUBST_STAGE.freebsdusb=		post-extract
SUBST_MESSAGE.freebsdusb=	Patching src/Makefile.in for DragonFly or FreeBSD compatible USB 
SUBST_FILES.freebsdusb+=	src/Makefile.in
SUBST_SED.freebsdusb+=		-e 's|-module -avoid-version|-module -avoid-version -lusbhid|'
.endif

The patch to mouse.h:

$NetBSD$

--- src/mouse.h.orig	2014-08-12 06:36:34.000000000 +0000
+++ src/mouse.h
@@ -27,6 +27,14 @@

 /* Public interface to OS-specific mouse support. */

+/* PKGSRC note: To support newer versions of DragonFly and FreeBSD,
+ * this file is patched using DragonFly dports
+ * x11-drivers/xf86-input-mouse/files/patch-src_mouse.h
+ * as of master commit 4f04bfe0ea83 ... Tue Jul 14 22:56:44 2015 -0700
+ * The patch's code is enclosed in include defined(FREEBSD_USB) while the
+ * original code is enclosed in include !defined(FREEBSD_USB).
+ */
+
 #ifndef _XF86OSMOUSE_H_
 #define _XF86OSMOUSE_H_

@@ -220,10 +228,17 @@ typedef struct _MouseDevRec {
     Bool                emulate3ButtonsSoft;
     int                 emulate3Timeout;/* Timeout for 3 button emulation */
     Bool                chordMiddle;
+#if defined(FREEBSD_USB)
+    Bool		disableXY;
+#endif
     Bool                flipXY;
     int                 invX;
     int                 invY;
     int                 resolution;
+#if defined(FREEBSD_USB)
+    Bool		hasW;
+    Bool		hasZ;
+#endif
     int                 negativeZ;      /* button mask */
     int                 positiveZ;      /* button mask */
     int                 negativeW;      /* button mask */
@@ -262,6 +277,10 @@ typedef struct _MouseDevRec {
     int                 doubleClickOldSourceState;
     int                 lastMappedButtons;
     int                 buttonMap[MSE_MAXBUTTONS];
+#if defined(FREEBSD_USB)
+    float		fracdx, fracdy;
+    float		sensitivity;
+#endif
 } MouseDevRec, *MouseDevPtr;

 #endif /* _XF86OSMOUSE_H_ */

The patch to mousePriv.h:

$NetBSD$

--- src/mousePriv.h.orig	2014-08-12 06:36:34.000000000 +0000
+++ src/mousePriv.h
@@ -2,6 +2,14 @@
  * Copyright (c) 1997-1999 by The XFree86 Project, Inc.
  */

+/* PKGSRC note: To support newer versions of DragonFly and FreeBSD,
+ * this file is patched using DragonFly dports
+ * x11-drivers/xf86-input-mouse/files/patch-src_mousePriv.h
+ * as of master commit 4f04bfe0ea83 ... Tue Jul 14 22:56:44 2015 -0700
+ * The patch's code is enclosed in include defined(FREEBSD_USB) while the
+ * original code is enclosed in include !defined(FREEBSD_USB).
+ */
+
 #ifndef _X_MOUSEPRIV_H
 #define _X_MOUSEPRIV_H

@@ -63,8 +71,10 @@ typedef struct {
     int         acc;
     CARD32      pnpLast;
     Bool        disablePnPauto;
+#if !defined(FREEBSD_USB)
     float       fracdx,fracdy;
     float       sensitivity;
+#endif
 } mousePrivRec, *mousePrivPtr;

 /* mouse proto flags */

A somewhat large patch to mouse.c:

$NetBSD$

--- src/mouse.c.orig	2014-08-12 06:36:34.000000000 +0000
+++ src/mouse.c
@@ -43,6 +43,13 @@
  * and to help limited dexterity persons
  */

+/* PKGSRC note: To support newer versions of DragonFly and FreeBSD,
+ * this file is patched using DragonFly dports
+ * x11-drivers/xf86-input-mouse/files/patch-src_mouse.c
+ * as of master commit 4f04bfe0ea83 ... Tue Jul 14 22:56:44 2015 -0700
+ * The patch's code is enclosed in include defined(FREEBSD_USB) while the
+ * original code is enclosed in include !defined(FREEBSD_USB).
+ */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -293,13 +300,45 @@ MouseCommonOptions(InputInfoPtr pInfo)

     pMse = pInfo->private;

+#if !defined(FREEBSD_USB)
     pMse->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0);
+#else
+    i = xf86SetIntOption(pInfo->options, "Buttons", 0);
+    if (i != 0)
+        pMse->buttons = i;
+#endif
     if (!pMse->buttons) {
         pMse->buttons = MSE_DFLTBUTTONS;
         buttons_from = X_DEFAULT;
     }
     origButtons = pMse->buttons;

+#if defined(FREEBSD_USB)
+    s = xf86SetStrOption(pInfo->options, "ButtonMapping", NULL);
+    if (s) {
+        int b, n = 0;
+        char *s1 = s;
+        /* keep getting numbers which are buttons */
+        while (s1 && n < MSE_MAXBUTTONS && (b = strtol(s1, &s1, 10)) != 0) {
+            /* check sanity for a button */
+            if (b < 0 || b > MSE_MAXBUTTONS) {
+                xf86Msg(X_WARNING,
+                        "ButtonMapping: Invalid button number = %d\n", b);
+                break;
+           };
+           pMse->buttonMap[n++] = 1 << (b-1);
+           if (b > pMse->buttons) pMse->buttons = b;
+        }
+        free(s);
+    }
+    /* get maximum of mapped buttons */
+    for (i = pMse->buttons-1; i >= 0; i--) {
+        int f = ffs (pMse->buttonMap[i]);
+        if (f > pMse->buttons)
+            pMse->buttons = f;
+    }
+#endif
+
     pMse->emulate3Buttons = xf86SetBoolOption(pInfo->options,
                                               "Emulate3Buttons", FALSE);
     if (!xf86FindOptionValue(pInfo->options,"Emulate3Buttons")) {
@@ -311,6 +350,10 @@ MouseCommonOptions(InputInfoPtr pInfo)
                                              "Emulate3Timeout", 50);
     if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft) {
         MessageType from = X_CONFIG;
+#if defined(FREEBSD_USB)
+       if (pMse->buttons < 3)
+            pMse->buttons = 3;
+#endif
         if (pMse->emulate3ButtonsSoft)
             from = X_DEFAULT;
         xf86Msg(from, "%s: Emulate3Buttons, Emulate3Timeout: %d\n",
@@ -318,6 +361,10 @@ MouseCommonOptions(InputInfoPtr pInfo)
     }

     pMse->chordMiddle = xf86SetBoolOption(pInfo->options, "ChordMiddle", FALSE);
+#if defined(FREEBSD_USB)
+    if (pMse->chordMiddle && pMse->buttons < 3)
+           pMse->buttons = 3;
+#endif
     pMse->flipXY = xf86SetBoolOption(pInfo->options, "FlipXY", FALSE);
     if (xf86SetBoolOption(pInfo->options, "InvX", FALSE)) {
         pMse->invX = -1;
@@ -328,7 +375,9 @@ MouseCommonOptions(InputInfoPtr pInfo)
     } else
         pMse->invY = 1;
     pMse->angleOffset = xf86SetIntOption(pInfo->options, "AngleOffset", 0);
-
+#if defined(FREEBSD_USB)
+    pMse->sensitivity = xf86SetRealOption(pInfo->options, "Sensitivity", 1.0);
+#endif

     if (pMse->pDragLock)
         free(pMse->pDragLock);
@@ -438,14 +487,25 @@ MouseCommonOptions(InputInfoPtr pInfo)
         free(s);
     }

+#if !defined(FREEBSD_USB)
     s = xf86SetStrOption(pInfo->options, "ZAxisMapping", "4 5");
+#else
+    s = xf86SetStrOption(pInfo->options, "ZAxisMapping",
+        pMse->hasZ ? ( pMse->hasW ? "4 5 6 7" : "4 5" ) : "off");
+#endif
     if (s) {
         int b1 = 0, b2 = 0, b3 = 0, b4 = 0;
         char *msg = NULL;

         pMse->negativeZ = pMse->positiveZ = MSE_NOAXISMAP;
         pMse->negativeW = pMse->positiveW = MSE_NOAXISMAP;
+#if !defined(FREEBSD_USB)
         if (!xf86NameCmp(s, "x")) {
+#else
+        if (!xf86NameCmp(s, "off")) {
+            msg = xstrdup("off");
+        } else if (!xf86NameCmp(s, "x")) {
+#endif
             pMse->negativeZ = pMse->positiveZ = MSE_MAPTOX;
             msg = xstrdup("X axis");
         } else if (!xf86NameCmp(s, "y")) {
@@ -594,6 +654,7 @@ MouseCommonOptions(InputInfoPtr pInfo)
                 pInfo->name, wheelButton, pMse->wheelInertia,
                 pMse->wheelButtonTimeout);
     }
+#if !defined(FREEBSD_USB)
     s = xf86SetStrOption(pInfo->options, "ButtonMapping", NULL);
     if (s) {
        int b, n = 0;
@@ -617,6 +678,7 @@ MouseCommonOptions(InputInfoPtr pInfo)
         if (f > pMse->buttons)
             pMse->buttons = f;
     }
+#endif
     if (origButtons != pMse->buttons)
         buttons_from = X_CONFIG;
     xf86Msg(buttons_from, "%s: Buttons: %d\n", pInfo->name, pMse->buttons);
@@ -698,7 +760,9 @@ MouseHWOptions(InputInfoPtr pInfo)
     }
     pMse->sampleRate = xf86SetIntOption(pInfo->options, "SampleRate", 0);
     pMse->resolution = xf86SetIntOption(pInfo->options, "Resolution", 0);
+#if !defined(FREEBSD_USB)
     mPriv->sensitivity = xf86SetRealOption(pInfo->options, "Sensitivity", 1.0);
+#endif
 }

 static void
@@ -987,6 +1051,11 @@ MousePreInit(InputDriverPtr drv, InputIn
     for (i = 0; i < MSE_MAXBUTTONS; i++)
         pMse->buttonMap[i] = 1 << (i > 2 && i < MSE_MAXBUTTONS-4 ? i+4 : i);

+#if defined(FREEBSD_USB)
+    pMse->hasZ = 1;
+    pMse->hasW = 0;
+#endif
+
     protocol = MousePickProtocol(pInfo, device, protocol, &protocolID);

     if (!device)
@@ -2271,6 +2340,11 @@ MouseDoPostEvent(InputInfoPtr pInfo, int
                         }
                     }
                 }
+#if defined (FREEBSD_USB)
+            } else {
+                pMse->wheelXDistance = 0;
+                pMse->wheelYDistance = 0;
+#endif
             }

             /* Absorb the mouse movement while the wheel button is pressed. */
@@ -2288,7 +2362,11 @@ MouseDoPostEvent(InputInfoPtr pInfo, int
     if (pMse->emulate3ButtonsSoft && pMse->emulate3Pending && (dx || dy))
         buttonTimer(pInfo);

+#if !defined(FREEBSD_USB)
     if (dx || dy)
+#else
+    if ((dx || dy) && !pMse->disableXY)
+#endif
         xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);

     if (change) {
@@ -2401,12 +2479,16 @@ MousePostEvent(InputInfoPtr pInfo, int t
                int dx, int dy, int dz, int dw)
 {
     MouseDevPtr pMse;
+#if !defined(FREEBSD_USB)
     mousePrivPtr mousepriv;
+#endif
     int zbutton = 0, wbutton = 0, zbuttoncount = 0, wbuttoncount = 0;
     int i, b, buttons = 0;

     pMse = pInfo->private;
+#if !defined(FREEBSD_USB)
     mousepriv = (mousePrivPtr)pMse->mousePriv;
+#endif

     if (pMse->protocolID == PROT_MMHIT)
         b = reverseBits(hitachMap, truebuttons);
@@ -2499,12 +2581,21 @@ MousePostEvent(InputInfoPtr pInfo, int t

     /* Accumulate the scaled dx, dy in the private variables
        fracdx,fracdy and return the integer number part */
+#if !defined(FREEBSD_USB)
     if (mousepriv) {
         mousepriv->fracdx += mousepriv->sensitivity*dx;
         mousepriv->fracdy += mousepriv->sensitivity*dy;
         mousepriv->fracdx -= ( dx=(int)(mousepriv->fracdx) );
         mousepriv->fracdy -= ( dy=(int)(mousepriv->fracdy) );
     }
+#else
+    if (pMse->sensitivity != 0) {
+        pMse->fracdx += pMse->sensitivity*dx;
+        pMse->fracdy += pMse->sensitivity*dy;
+        pMse->fracdx -= ( dx=(int)(pMse->fracdx) );
+        pMse->fracdy -= ( dy=(int)(pMse->fracdy) );
+    }
+#endif

     /* If mouse wheel movement has to be mapped on a button, we need to
      * loop for button press and release events. */

The gigantic patch to bsd_mouse.c:

$NetBSD$

--- src/bsd_mouse.c.orig	2014-08-12 06:36:34.000000000 +0000
+++ src/bsd_mouse.c
@@ -26,6 +26,41 @@
  * authorization from the copyright holder(s) and author(s).
  */

+/* PKGSRC note: To support newer versions of DragonFly and FreeBSD,
+ * this file is patched using DragonFly dports
+ * x11-drivers/xf86-input-mouse/files/patch-src-bsd_mouse.c and
+ * x11-drivers/xf86-input-mouse/dragonfly/patch-src_bsd__mouse.c
+ * as of master commit 4f04bfe0ea83 ... Tue Jul 14 22:56:44 2015 -0700
+ * The patch's code is enclosed in include defined(FREEBSD_USB) while the
+ * original code is enclosed in include !defined(FREEBSD_USB).
+ */
+
+/* DRAGONFLY_U4B is the usb system after OS version 300703
+ * DRAGONFLY_USB is the usb system before OS version 300703
+ * FREEBSD_USB must be defined if either DRAGONFLY_U4B or DRAGONFLY_USB are.
+ */
+
+#if defined(FREEBSD_USB)
+
+/*
+ * XXX - Should this be autoconf'd instead?
+ */
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+
+#if !defined(USBMOUSE_SUPPORT)
+#define USBMOUSE_SUPPORT
+#endif
+#if !defined(HAS_LIB_USB_HID)
+#define HAS_LIB_USB_HID
+#endif
+#if !defined(XPS2_SUPPORT)
+#define XPS2_SUPPORT
+#endif
+
+#endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) */
+
+#endif /* defined(FREEBSD_USB) */
+
 #include <xorg-server.h>

 #include <X11/X.h>
@@ -33,12 +68,33 @@
 #include "xf86Priv.h"
 #include "xf86_OSlib.h"
 #include "xf86Xinput.h"
+#if defined(FREEBSD_USB)
+#include <exevents.h>
+#endif
 #include "mouse.h"
 #include "xisb.h"
 #include "mipointer.h"
+
+#if defined(FREEBSD_USB)
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
+#define HAVE_PROPERTIES 1
+#endif
+#ifdef HAVE_PROPERTIES
+#include <X11/Xatom.h>
+#include <xserver-properties.h>
+/* 1.6 has properties, but no labels */
+#ifdef AXIS_LABEL_PROP
+#define HAVE_LABELS
+#else
+#undef HAVE_LABELS
+#endif
+#endif
+#endif /* defined(FREEBSD_USB) */
+
 #ifdef WSCONS_SUPPORT
 #include <dev/wscons/wsconsio.h>
 #endif
+
 #ifdef USBMOUSE_SUPPORT
 #ifdef HAS_LIB_USB_HID
 #include <usbhid.h>
@@ -46,10 +102,25 @@
 #include "usb.h"
 #endif

+#if defined(FREEBSD_USB)
+
+#if defined(DRAGONFLY_U4B)
+#include <sys/param.h>
+#include <bus/u4b/usb.h>
+#elif defined(DRAGONFLY_USB)
+#include <sys/param.h>
+#include <bus/usb/usb.h>
+#else
 #include <dev/usb/usb.h>
+#endif
+
+#endif /* defined(FREEBSD_USB) */
+
+#if !defined(FREEBSD_USB)
 #ifdef USB_GET_REPORT_ID
 #define USB_NEW_HID
 #endif
+#endif /* !defined(FREEBSD_USB) */

 #define HUP_GENERIC_DESKTOP     0x0001
 #define HUP_BUTTON              0x0009
@@ -76,10 +147,17 @@ static const char *FindDevice(InputInfoP
 #define DEFAULT_SYSMOUSE_DEV            "/dev/sysmouse"
 #define DEFAULT_PS2_DEV                 "/dev/psm0"

+#if defined(FREEBSD_USB)
+#define DEFAULT_USB_DEV                 "/dev/ums0"
+#endif
+
 static const char *mouseDevs[] = {
         DEFAULT_MOUSE_DEV,
         DEFAULT_SYSMOUSE_DEV,
         DEFAULT_PS2_DEV,
+#if defined(FREEBSD_USB)
+        DEFAULT_USB_DEV,
+#endif
         NULL
 };
 #elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
@@ -97,11 +175,23 @@ static const char *mouseDevs[] = {
 static int
 SupportedInterfaces(void)
 {
+#if !defined(FREEBSD_USB)
+
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__NetBSD__)
     return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC;
 #else
     return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO | MSE_MISC;
 #endif
+
+#else /* defined(FREEBSD_USB) */
+
+#if defined(__NetBSD__)
+    return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC;
+#else
+    return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO | MSE_MISC;
+#endif
+
+#endif /* !defined(FREEBSD_USB) */
 }

 /* Names of protocols that are handled internally here. */
@@ -178,9 +268,34 @@ static struct {
         { MOUSE_PROTO_SYSMOUSE,         "SysMouse" }
 };

+#if defined(FREEBSD_USB)
+#ifdef XPS2_SUPPORT
+static struct {
+        int dmodel;
+        const char *name;
+} ps2proto[] = {
+        { MOUSE_MODEL_NETSCROLL,        "NetScrollPS/2" },
+        { MOUSE_MODEL_NET,              "NetMousePS/2" },
+        { MOUSE_MODEL_GLIDEPOINT,       "GlidePointPS/2" },
+        { MOUSE_MODEL_THINK,            "ThinkingMousePS/2" },
+        { MOUSE_MODEL_INTELLI,          "IMPS/2" },
+        { MOUSE_MODEL_MOUSEMANPLUS,     "MouseManPlusPS/2" },
+        { MOUSE_MODEL_EXPLORER,         "ExplorerPS/2" },
+        { MOUSE_MODEL_4D,               "IMPS/2" },
+        { MOUSE_MODEL_4DPLUS,           "IMPS/2" },
+};
+#endif
+#endif /* defined(FREEBSD_USB) */
+
 static const char *
 SetupAuto(InputInfoPtr pInfo, int *protoPara)
 {
+#if defined(FREEBSD_USB)
+#ifdef XPS2_SUPPORT
+    const char *dev;
+#endif
+    const char *proto;
+#endif /* defined(FREEBSD_USB) */
     int i;
     mousehw_t hw;
     mousemode_t mode;
@@ -189,6 +304,14 @@ SetupAuto(InputInfoPtr pInfo, int *proto
         return NULL;

     /* set the driver operation level, if applicable */
+#if defined (FREEBSD_USB)
+#ifdef XPS2_SUPPORT
+    dev = xf86FindOptionValue(pInfo->options, "Device");
+    if (dev != NULL && !strncmp(dev, DEFAULT_PS2_DEV, 8))
+        i = 2;
+    else
+#endif
+#endif /* defined(FREEBSD_USB) */
     i = 1;
     ioctl(pInfo->fd, MOUSE_SETLEVEL, &i);

@@ -207,9 +330,27 @@ SetupAuto(InputInfoPtr pInfo, int *proto
                     protoPara[0] = mode.syncmask[0];
                     protoPara[1] = mode.syncmask[1];
                 }
+#if defined(FREEBSD_USB)
+                proto = devproto[i].name;
+#ifdef XPS2_SUPPORT
+                if (mode.protocol == MOUSE_PROTO_PS2)
+                    for (i = 0; i < sizeof(ps2proto)/sizeof(ps2proto[0]); ++i)
+                        if (hw.model == ps2proto[i].dmodel) {
+                           proto = ps2proto[i].name;
+                           break;
+                }
+#endif
+#endif /* defined(FREEBSD_USB) */
+
+#if !defined(FREEBSD_USB)
                 xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
                             pInfo->name, devproto[i].name);
                 return devproto[i].name;
+#else /* defined(FREEBSD_USB) */
+                xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
+                            pInfo->name, proto);
+                return proto;
+#endif /* !defined(FREEBSD_USB) */
             }
         }
     }
@@ -227,6 +368,9 @@ SetSysMouseRes(InputInfoPtr pInfo, const
     mode.rate = rate > 0 ? rate : -1;
     mode.resolution = res > 0 ? res : -1;
     mode.accelfactor = -1;
+
+#if !defined(FREEBSD_USB)
+
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
     if (pMse->autoProbe ||
         (protocol && xf86NameCmp(protocol, "SysMouse") == 0)) {
@@ -241,13 +385,35 @@ SetSysMouseRes(InputInfoPtr pInfo, const
 #else
     mode.level = -1;
 #endif
+
+#else /* defined(FREEBSD_USB) */
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+    if (pMse->autoProbe ||
+        (protocol && xf86NameCmp(protocol, "SysMouse") == 0)) {
+        /*
+         * As the FreeBSD sysmouse driver defaults to protocol level 0
+         * everytime it is closed we enforce protocol level 1 again at
+         * this point.
+         */
+        mode.level = 1;
+    } else
+#endif
+    mode.level = -1;
+
+#endif /* !defined(FREEBSD_USB) */
+
     ioctl(pInfo->fd, MOUSE_SETMODE, &mode);
 }
 #endif

 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)

+#if !defined(FREEBSD_USB)
 #define MOUSED_PID_FILE "/var/run/moused.pid"
+#endif
+
+#if !defined(FREEBSD_USB)

 /*
  * Try to check if moused is running.  DEFAULT_SYSMOUSE_DEV is useless without
@@ -271,20 +437,66 @@ MousedRunning(void)
     return FALSE;
 }

+#else /* defined(FREEBSD_USB) */
+
+/*
+ * Try to check if moused is running.  DEFAULT_SYSMOUSE_DEV is useless without
+ * it.  Also, try to check if the device is used by moused.  If it is opened
+ * by moused, we do not want to use it directly.  There doesn't seem to be
+ * a better way of checking.
+ */
+static Bool
+MousedRunning(const char *dev)
+{
+    char cmd[128];
+    FILE *f = NULL;
+    unsigned int i;
+
+    if (dev)
+        sprintf(cmd, "sh -c 'fstat %s | grep -c moused' 2>/dev/null", dev);
+    else
+        sprintf(cmd, "sh -c 'pgrep -nx moused' 2>/dev/null");
+    if ((f = popen(cmd, "r")) != NULL) {
+        if (fscanf(f, "%u", &i) == 1 && i > 0) {
+            pclose(f);
+            return TRUE;
+        }
+        pclose(f);
+    }
+    return FALSE;
+}
+
+#endif /* !defined(FREEBSD_USB) */
+
 static const char *
 FindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
 {
+#if !defined(FREEBSD_USB)
     int fd = -1;
+#else
+    int ret = -1;
+#endif
     const char **pdev, *dev = NULL;
     Bool devMouse = FALSE;
     struct stat devMouseStat;
     struct stat sb;

     for (pdev = mouseDevs; *pdev; pdev++) {
+
+#if !defined(FREEBSD_USB)
         SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK));
         if (fd == -1) {
+#else
+        SYSCALL (ret = stat(*pdev, &sb));
+        if (ret == -1) {
+#endif /* !defined(FREEBSD_USB) */
+
 #ifdef DEBUG
+#if !defined(FREEBSD_USB)
             ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno));
+#else
+            ErrorF("Cannot stat %s (%s)\n", *pdev, strerror(errno));
+#endif /* !defined(FREEBSD_USB) */
 #endif
         } else {
             /*
@@ -293,28 +505,70 @@ FindDevice(InputInfoPtr pInfo, const cha
              * the test for whether /dev/sysmouse is usable can be made.
              */
             if (!strcmp(*pdev, DEFAULT_MOUSE_DEV)) {
+#if !defined(FREEBSD_USB)
                 if (fstat(fd, &devMouseStat) == 0)
                     devMouse = TRUE;
                 close(fd);
+#else
+                memcpy(&devMouseStat, &sb, sizeof(devMouseStat));
+                devMouse = TRUE;
+#endif /* !defined(FREEBSD_USB) */
                 continue;
             } else if (!strcmp(*pdev, DEFAULT_SYSMOUSE_DEV)) {
                 /* Check if /dev/mouse is the same as /dev/sysmouse. */
+#if !defined(FREEBSD_USB)
                 if (devMouse && fstat(fd, &sb) == 0 &&
                     devMouseStat.st_dev == sb.st_dev &&
                     devMouseStat.st_ino == sb.st_ino) {
+#else
+                if (devMouse && devMouseStat.st_dev == sb.st_dev &&
+                    devMouseStat.st_ino == sb.st_ino) {
+#endif /* !defined(FREEBSD_USB) */
                     /* If the same, use /dev/sysmouse. */
                     devMouse = FALSE;
                 }
+
+#if !defined(FREEBSD_USB)
                 close(fd);
                 if (MousedRunning())
+#else
+                if (MousedRunning(NULL))
+#endif /* !defined(FREEBSD_USB) */
+
                     break;
+
+#if !defined(FREEBSD_USB)
                 else {
 #ifdef DEBUG
                     ErrorF("moused isn't running\n");
 #endif
                 }
+#endif /* !defined(FREEBSD_USB) */
+
             } else {
+
+#if !defined(FREEBSD_USB)
+
                 close(fd);
+
+#else /* defined(FREEBSD_USB) */
+
+                /* Check if /dev/mouse is the same as this device. */
+                if (devMouse && devMouseStat.st_dev == sb.st_dev &&
+                    devMouseStat.st_ino == sb.st_ino) {
+                    /* If the same, use this device. */
+                    devMouse = FALSE;
+                }
+                if (MousedRunning(*pdev))
+                    continue;
+                /* ums(4) does not support anything but SysMouse protocol. */
+                if (!strncmp(*pdev, DEFAULT_USB_DEV, 8) && protocol &&
+                    xf86NameCmp(protocol, "auto") != 0 &&
+                    xf86NameCmp(protocol, "sysmouse") != 0)
+                    continue;
+
+#endif /* !defined(FREEBSD_USB) */
+
                 break;
             }
         }
@@ -486,8 +740,17 @@ wsconsPreInit(InputInfoPtr pInfo, const

 #if defined(USBMOUSE_SUPPORT)

+#if defined(FREEBSD_USB)
+#define MAXRIDS		64
+#define MAXACOLS	8
+#define MAXLCOLS	16
+#endif
+
 typedef struct _UsbMseRec {
     int packetSize;
+
+#if !defined(FREEBSD_USB)
+
     int iid;
     hid_item_t loc_x;           /* x locator item */
     hid_item_t loc_y;           /* y locator item */
@@ -495,22 +758,92 @@ typedef struct _UsbMseRec {
     hid_item_t loc_w;           /* z (wheel) locator item */
     hid_item_t loc_btn[MSE_MAXBUTTONS]; /* buttons locator items */
    unsigned char *buffer;
+
+#else /* defined(FREEBSD_USB) */
+
+    int iid, nrids, nacols, opened;
+    struct {
+	int32_t rid;
+	int size;
+    } rids[MAXRIDS];
+    struct UsbMseAcol {
+	InputInfoPtr pInfo;
+	int nlcols, nbuttons, hasZ, hasW;
+	int xmin, xmax, ymin, ymax, pmin, pmax, px, py;
+	int cxmin, cxmax, cymin, cymax, cpmin, cpmax;
+	struct UsbMseLcol {
+	    hid_item_t loc_x;		/* x locator item */
+	    hid_item_t loc_y;		/* y locator item */
+	    hid_item_t loc_z;		/* z (wheel) locator item */
+	    hid_item_t loc_w;		/* w (hwheel) locator item */
+	    hid_item_t loc_p;		/* Tip Pressure */
+	    hid_item_t loc_valid;		/* Touch Valid */
+	    hid_item_t loc_in_range;	/* In Range */
+	    hid_item_t loc_btn[MSE_MAXBUTTONS]; /* buttons locator items */
+	} lcols[MAXLCOLS];
+	hid_item_t loc_cc;		/* contact count */
+    } acols[MAXACOLS];
+    unsigned char *buffer;
+
+#endif /* !defined(FREEBSD_USB) */
+
 } UsbMseRec, *UsbMsePtr;

+#if defined(FREEBSD_USB)
+static int *
+usbGetReportSizePtr(UsbMsePtr pUsbMse, int32_t rid)
+{
+    int i;
+
+    for (i = 0; i < pUsbMse->nrids; i++) {
+	if (pUsbMse->rids[i].rid == rid)
+	    return (&pUsbMse->rids[i].size);
+    }
+    for (i = 0; i < MAXRIDS; i++) {
+	if (pUsbMse->rids[i].size == 0) {
+	    pUsbMse->rids[i].rid = rid;
+	    pUsbMse->nrids = max(pUsbMse->nrids, i + 1);
+	    return (&pUsbMse->rids[i].size);
+	}
+    }
+    return (NULL);
+}
+#endif /* defined(FREEBSD_USB) */
+
 static int
 usbMouseProc(DeviceIntPtr pPointer, int what)
 {
     InputInfoPtr pInfo;
     MouseDevPtr pMse;
     UsbMsePtr pUsbMse;
+#if defined(FREEBSD_USB)
+    struct UsbMseAcol *acol;
+#endif
     unsigned char map[MSE_MAXBUTTONS + 1];
+
+#if !defined(FREEBSD_USB)
     int nbuttons;
+#else /* defined (FREEBSD_USB) */
+    int nacol, nbuttons;
+#ifdef HAVE_LABELS
+    Atom btn_labels[MSE_MAXBUTTONS] = {0};
+    Atom axes_labels[3] = { 0, 0, 0 };
+#endif
+#endif /* !defined(FREEBSD_USB) */

     pInfo = pPointer->public.devicePrivate;
     pMse = pInfo->private;
     pMse->device = pPointer;
     pUsbMse = pMse->mousePriv;

+#if defined(FREEBSD_USB)
+    for (nacol = 0; nacol < (pUsbMse->nacols - 1); nacol++) {
+	if (pUsbMse->acols[nacol].pInfo == pInfo)
+	    break;
+    }
+    acol = &pUsbMse->acols[nacol];
+#endif
+
     switch (what) {
     case DEVICE_INIT:
         pPointer->public.on = FALSE;
@@ -518,23 +851,114 @@ usbMouseProc(DeviceIntPtr pPointer, int
         for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons)
             map[nbuttons + 1] = nbuttons + 1;

+#if !defined(FREEBSD_USB)
         InitPointerDeviceStruct((DevicePtr)pPointer,
                                 map,
                                 min(pMse->buttons, MSE_MAXBUTTONS),
                                 miPointerGetMotionEvents,
                                 pMse->Ctrl,
                                 miPointerGetMotionBufferSize());
+#else /* defined(FREEBSD_USB) */
+
+#ifdef HAVE_LABELS
+	btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+	btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+	btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+	axes_labels[0] = XIGetKnownProperty((acol->xmin != acol->xmax)
+	    ? AXIS_LABEL_PROP_ABS_X : AXIS_LABEL_PROP_REL_X);
+	axes_labels[1] = XIGetKnownProperty((acol->xmin != acol->xmax)
+	    ? AXIS_LABEL_PROP_ABS_Y : AXIS_LABEL_PROP_REL_Y);
+	axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
+#endif
+
+	InitButtonClassDeviceStruct(pPointer, min(pMse->buttons, MSE_MAXBUTTONS),
+#ifdef HAVE_LABELS
+	    btn_labels,
+#endif
+	    map);
+	InitValuatorClassDeviceStruct(pPointer, (acol->pmin != acol->pmax) ? 3 : 2,
+#ifdef HAVE_LABELS
+	    axes_labels,
+#endif
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
+	    miPointerGetMotionEvents,
+#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
+	    GetMotionHistory,
+#endif
+	    GetMotionHistorySize(),
+	    (acol->xmin != acol->xmax || acol->ymin != acol->ymax) ?
+	     Absolute : Relative);
+	InitPtrFeedbackClassDeviceStruct(pPointer, pMse->Ctrl);
+
+#endif /* !defined(FREEBSD_USB) */

         /* X valuator */
+#if !defined(FREEBSD_USB)
+
         xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1);
         xf86InitValuatorDefaults(pPointer, 0);
+
+#else /* defined(FREEBSD_USB) */
+
+	xf86InitValuatorAxisStruct(pPointer, 0,
+#ifdef HAVE_LABELS
+	    axes_labels[0],
+#endif
+	    (acol->xmin != acol->xmax) ? acol->xmin : -1,
+	    (acol->xmin != acol->xmax) ? acol->xmax : -1,
+	    1, 0, 1
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+	    , (acol->xmin != acol->xmax) ? Absolute : Relative
+#endif
+	    );
+        xf86InitValuatorDefaults(pPointer, 0);
+
+#endif /* !defined(FREEBSD_USB) */
+
         /* Y valuator */
+
+#if !defined(FREEBSD_USB)
+
         xf86InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1);
         xf86InitValuatorDefaults(pPointer, 1);
+
+#else /* defined(FREEBSD_USB) */
+
+	xf86InitValuatorAxisStruct(pPointer, 1,
+#ifdef HAVE_LABELS
+	    axes_labels[1],
+#endif
+	    (acol->ymin != acol->ymax) ? acol->ymin : -1,
+	    (acol->ymin != acol->ymax) ? acol->ymax : -1,
+	    1, 0, 1
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+	    , (acol->ymin != acol->ymax) ? Absolute : Relative
+#endif
+	    );
+        xf86InitValuatorDefaults(pPointer, 1);
+	/* Pressure valuator */
+	if (acol->pmin != acol->pmax) {
+	    xf86InitValuatorAxisStruct(pPointer, 2,
+#ifdef HAVE_LABELS
+		axes_labels[2],
+#endif
+		acol->pmin, acol->pmax, 1, 0, 1
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+		, Absolute
+#endif
+		);
+	    xf86InitValuatorDefaults(pPointer, 2);
+	}
+
+#endif /* !defined(FREEBSD_USB) */
+
         xf86MotionHistoryAllocate(pInfo);
         break;

     case DEVICE_ON:
+
+#if !defined(FREEBSD_USB)
+
         pInfo->fd = xf86OpenSerial(pInfo->options);
         if (pInfo->fd == -1)
             xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
@@ -551,6 +975,30 @@ usbMouseProc(DeviceIntPtr pPointer, int
                     AddEnabledDevice(pInfo->fd);
             }
         }
+
+#else /* defined(FREEBSD_USB) */
+
+	if (pUsbMse->opened++ == 0) {
+		pInfo->fd = xf86OpenSerial(pInfo->options);
+		if (pInfo->fd == -1)
+		    xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
+		else {
+		    pMse->buffer = XisbNew(pInfo->fd, pUsbMse->packetSize);
+		    if (!pMse->buffer) {
+			free(pMse);
+			xf86CloseSerial(pInfo->fd);
+			pInfo->fd = -1;
+		    } else {
+			xf86FlushInput(pInfo->fd);
+			if (!xf86InstallSIGIOHandler (pInfo->fd, usbSigioReadInput, 
+						      pInfo))
+			    AddEnabledDevice(pInfo->fd);
+		    }
+		}
+        }
+
+#endif /* !defined(FREEBSD_USB) */
+
         pMse->lastButtons = 0;
         pMse->lastMappedButtons = 0;
         pMse->emulateState = 0;
@@ -571,6 +1019,9 @@ usbMouseProc(DeviceIntPtr pPointer, int
             xf86CloseSerial(pInfo->fd);
             pInfo->fd = -1;
         }
+#if defined(FREEBSD_USB)
+        pUsbMse->opened--;
+#endif
         pPointer->public.on = FALSE;
         usleep(300000);
         break;
@@ -586,27 +1037,86 @@ usbReadInput(InputInfoPtr pInfo)
 {
     MouseDevPtr pMse;
     UsbMsePtr pUsbMse;
+
+#if !defined(FREEBSD_USB)
     int buttons = pMse->lastButtons;
     int dx = 0, dy = 0, dz = 0, dw = 0;
     int n, c;
+#else
+    int buttons, cc;
+    int dx, dy, dz, dw, dp, upd, v, nx, ny, np, in_range;
+    int n, c, rid, *sizep, nacol, nlcol;
+#endif /* !defined(FREEBSD_USB) */
+
     unsigned char *pBuf;

+#if defined(FREEBSD_USB)
+    struct UsbMseAcol *acol;
+    struct UsbMseLcol *lcol;
+#endif
     pMse = pInfo->private;
     pUsbMse = pMse->mousePriv;

     XisbBlockDuration(pMse->buffer, -1);
+#if defined(FREEBSD_USB)
+next:
+#endif
     pBuf = pUsbMse->buffer;
     n = 0;
+
+#if !defined(FREEBSD_USB)
+
     while ((c = XisbRead(pMse->buffer)) >= 0 && n < pUsbMse->packetSize) {
         pBuf[n++] = (unsigned char)c;
+
+    }
+#else /* defined(FREEBSD_USB) */
+
+    if (pUsbMse->iid) {
+	rid = XisbRead(pMse->buffer);
+	if (rid < 0)
+	    return;
+	pBuf[n++] = (unsigned char)rid;
+    } else
+	rid = 0;
+    sizep = usbGetReportSizePtr(pUsbMse, rid);
+    if (sizep == NULL || *sizep == 0) {
+	xf86Msg(X_WARNING, "%s: unknown report ID %d\n", pInfo->name, rid);
+	goto next;
     }
+    while (n < *sizep && (c = XisbRead(pMse->buffer)) >= 0) {
+        pBuf[n++] = (unsigned char)c;
+    }
+
+#endif /* !defined(FREEBSD_USB) */
+
     if (n == 0)
         return;
+
+#if !defined(FREEBSD_USB)
+
     if (n != pUsbMse->packetSize) {
         LogMessageVerbSigSafe(X_WARNING, -1,
                               "%s: incomplete packet, size %d\n",
                               pInfo->name, n);
     }
+
+#else /* defined(FREEBSD_USB) */
+
+    if (n == 0)
+        return;
+//    xf86MsgVerb(X_INFO, 3, "pkt: %d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+//	n, pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7], pBuf[8], pBuf[9]);
+    if (n != *sizep) {
+        LogMessageVerbSigSafe(X_WARNING, -1,
+                              "%s: incomplete packet, size %d\n",
+                              pInfo->name, n);
+    }
+
+#endif /* !defined(FREEBSD_USB) */
+
+#if !defined(FREEBSD_USB)
+
     /* discard packets with an id that don't match the mouse */
     /* XXX this is probably not the right thing */
     if (pUsbMse->iid != 0) {
@@ -625,6 +1135,122 @@ usbReadInput(InputInfoPtr pInfo)
     }
     pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
     return;
+
+#else /* defined(FREEBSD_USB) */
+
+    for (nacol = 0; nacol < pUsbMse->nacols; nacol++) {
+	acol = &pUsbMse->acols[nacol];
+	if (acol->pInfo == NULL)
+	    continue;
+	nx = ny = np = upd = 0;
+	buttons = cc = 0;
+	dx = dy = dz = dw = dp = 0;
+	for (nlcol = 0; nlcol < pUsbMse->acols[nacol].nlcols; nlcol++) {
+	    lcol = &acol->lcols[nlcol];
+
+	    if (lcol->loc_valid.usage != 0 && rid == lcol->loc_valid.report_ID &&
+		    hid_get_data(pBuf, &lcol->loc_valid) == 0)
+		continue;
+	    if (lcol->loc_in_range.usage != 0 && rid == lcol->loc_in_range.report_ID)
+		in_range = hid_get_data(pBuf, &lcol->loc_in_range);
+	    else
+		in_range = 1;
+	    if (in_range && lcol->loc_x.usage != 0 && rid == lcol->loc_x.report_ID && nx == 0) {
+		v = hid_get_data(pBuf, &lcol->loc_x);
+		if (acol->xmin != acol->xmax) {
+		    v = xf86ScaleAxis(v, acol->xmax, acol->xmin,
+			lcol->loc_x.logical_maximum, lcol->loc_x.logical_minimum);
+		    if (acol->cxmin != acol->cxmax)
+		        v = xf86ScaleAxis(v, acol->xmax, acol->xmin,
+			    acol->cxmax, acol->cxmin);
+		}
+		dx += v;
+		nx++;
+	    }
+	    if (in_range && lcol->loc_y.usage != 0 && rid == lcol->loc_y.report_ID && ny == 0) {
+		v = hid_get_data(pBuf, &lcol->loc_y);
+		if (acol->xmin != acol->xmax) {
+		    v = xf86ScaleAxis(v, acol->ymax, acol->ymin,
+			lcol->loc_y.logical_maximum, lcol->loc_y.logical_minimum);
+		    if (acol->cymin != acol->cymax)
+		        v = xf86ScaleAxis(v, acol->ymax, acol->ymin,
+			    acol->cymax, acol->cymin);
+		}
+		dy += v;
+		ny++;
+	    }
+	    if (lcol->loc_z.usage != 0 && rid == lcol->loc_z.report_ID) {
+		dz -= hid_get_data(pBuf, &lcol->loc_z);
+		upd = 1;
+	    }
+	    if (lcol->loc_w.usage != 0 && rid == lcol->loc_w.report_ID) {
+		dw += hid_get_data(pBuf, &lcol->loc_w);
+		upd = 1;
+	    }
+	    if (lcol->loc_p.usage != 0 && rid == lcol->loc_p.report_ID && np == 0) {
+		v = hid_get_data(pBuf, &lcol->loc_p);
+		    v = xf86ScaleAxis(v, acol->pmax, acol->pmin,
+			lcol->loc_p.logical_maximum, lcol->loc_p.logical_minimum);
+		    if (acol->cpmin != acol->cpmax)
+		        v = xf86ScaleAxis(v, acol->pmax, acol->pmin,
+			    acol->cpmax, acol->cpmin);
+		dp += v;
+		np++;
+	    }
+
+	    for (n = 0; n < acol->nbuttons; n++) {
+		if (lcol->loc_btn[n].usage != 0 && rid == lcol->loc_btn[n].report_ID) {
+		    if (hid_get_data(pBuf, &lcol->loc_btn[n]))
+			buttons |= (1 << UMS_BUT(n));
+		    upd = 1;
+		}
+	    }
+	}
+	if (acol->loc_cc.usage != 0 && rid == acol->loc_cc.report_ID)
+	    cc = hid_get_data(pBuf, &acol->loc_cc);
+	else
+	    cc = (nx || ny) ? 1 : 0;
+	if (cc > 1)
+	    buttons = (1 << UMS_BUT(1));
+	if (nx != 0 && acol->xmin != acol->xmax)
+	    dx /= nx;
+	if (ny != 0 && acol->ymin != acol->ymax)
+	    dy /= ny;
+	if (np != 0 && acol->pmin != acol->pmax)
+	    dp /= np;
+//	if (upd || nx || ny || np)
+//	    xf86MsgVerb(X_INFO, 3, "%d cc %d dx %d dy %d dz %d dw %d press %d buttons %02x\n",
+//		nacol, cc, dx, dy, dz, dw, dp, buttons);
+	if (nx != 0 || ny != 0) {
+	    if (acol->pmin != acol->pmax) {
+		xf86PostMotionEvent(acol->pInfo->dev,
+			    /* is_absolute: */    TRUE,
+			    /* first_valuator: */ 0,
+			    /* num_valuators: */  3,
+			    dx, dy, dp);
+	    } else if (acol->xmin != acol->xmax || acol->ymin != acol->ymax) {
+		xf86PostMotionEvent(acol->pInfo->dev,
+			    /* is_absolute: */    TRUE,
+			    /* first_valuator: */ 0,
+			    /* num_valuators: */  2,
+			    dx, dy);
+	    }
+	}
+	if (upd || (nx != 0) || (ny != 0)) {
+	    ((MouseDevPtr)acol->pInfo->private)->PostEvent(acol->pInfo, buttons,
+		((acol->xmin != acol->xmax) ? dx - acol->px : dx),
+		((acol->ymin != acol->ymax) ? dy - acol->py : dy),
+		dz, dw);
+	}
+	if (nx > 0)
+	    acol->px = dx;
+	if (ny > 0)
+	    acol->py = dy;
+    }
+    goto next;
+
+#endif /* !defined(FREEBSD_USB) */
+
 }

 static void
@@ -633,15 +1259,27 @@ usbSigioReadInput (int fd, void *closure
     usbReadInput ((InputInfoPtr) closure);
 }

+#if !defined(FREEBSD_USB)
 /* This function is called when the protocol is "usb". */
 static Bool
 usbPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
+#else
+static Bool
+usbInitFirst(InputInfoPtr pInfo)
+#endif /* !defined(FREEBSD_USB) */
 {
     MouseDevPtr pMse = pInfo->private;
     UsbMsePtr pUsbMse;
     report_desc_t reportDesc;
+#if !defined(FREEBSD_USB)
     int i;
-
+#else
+    hid_data_t d;
+    hid_item_t h;
+    struct UsbMseAcol *acol;
+    struct UsbMseLcol *lcol;
+    int mdepth, rsize, *rsizep, acolused, lcolused, used;
+#endif /* !defined(FREEBSD_USB) */
     pUsbMse = malloc(sizeof(UsbMseRec));
     if (pUsbMse == NULL) {
         xf86Msg(X_ERROR, "%s: cannot allocate UsbMouseRec\n", pInfo->name);
@@ -649,12 +1287,16 @@ usbPreInit(InputInfoPtr pInfo, const cha
         return FALSE;
     }

+#if !defined(FREEBSD_USB)
     pMse->protocol = protocol;
     xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);

     /* Collect the options, and process the common options. */
     COLLECT_INPUT_OPTIONS(pInfo, NULL);
     xf86ProcessCommonOptions(pInfo, pInfo->options);
+#else
+    bzero(pUsbMse, sizeof(UsbMseRec));
+#endif /* !defined(FREEBSD_USB) */

     /* Check if the device can be opened. */
     pInfo->fd = xf86OpenSerial(pInfo->options);
@@ -670,6 +1312,9 @@ usbPreInit(InputInfoPtr pInfo, const cha
     }
     /* Get USB informations */
     reportDesc = hid_get_report_desc(pInfo->fd);
+
+#if !defined(FREEBSD_USB)
+
     /* Get packet size & iid */
 #ifdef USB_NEW_HID
     if (ioctl(pInfo->fd, USB_GET_REPORT_ID, &pUsbMse->iid) == -1) {
@@ -683,6 +1328,139 @@ usbPreInit(InputInfoPtr pInfo, const cha
     pUsbMse->packetSize = hid_report_size(reportDesc, hid_input,
                                               &pUsbMse->iid);
 #endif
+
+#else /* defined(FREEBSD_USB) */
+
+    mdepth = 0;
+    pUsbMse->nacols = 0;
+    acol = &pUsbMse->acols[pUsbMse->nacols];
+    lcol = &acol->lcols[acol->nlcols];
+    acolused = 0;
+    lcolused = 0;
+    d = hid_start_parse(reportDesc, (1 << hid_input) |
+	(1 << hid_collection) | (1 << hid_endcollection), -1);
+    while (hid_get_item(d, &h)) {
+	switch (h.kind) {
+	case hid_collection:
+	    if (mdepth != 0)
+		mdepth++;
+	    else if (h.collection == 1 &&
+		    (h.usage == 0x00010001 || h.usage == 0x00010002 ||
+		     (h.usage >= 0x000d0001 && h.usage <= 0x000d000d))) {
+		mdepth++;
+		if (acolused) {
+		    if (lcolused) {
+			acol->nlcols++;
+			lcolused = 0;
+		    }
+		    pUsbMse->nacols++;
+		    acolused = 0;
+		    acol = &pUsbMse->acols[pUsbMse->nacols];
+		    lcol = &acol->lcols[acol->nlcols];
+		}
+	    }
+	    if (lcolused && (h.collection == 0 ||
+		    h.collection == 2 || h.collection == 3)) {
+		acol->nlcols++;
+		lcolused = 0;
+		lcol = &acol->lcols[acol->nlcols];
+	    }
+	    break;
+	case hid_endcollection:
+	    if (mdepth != 0)
+		mdepth--;
+	    break;
+	case hid_input:
+	    if (h.report_ID != 0)
+		pUsbMse->iid = 1;
+	    rsize = pUsbMse->iid +
+		(h.pos + (h.report_size * h.report_count) + 7) / 8;
+	    if ((rsizep = usbGetReportSizePtr(pUsbMse, h.report_ID)) != NULL)
+		*rsizep = max(*rsizep, rsize);
+	    pUsbMse->packetSize = max(pUsbMse->packetSize, rsize);
+	    if (mdepth == 0)
+		break;
+	    used = 1;
+	    if (h.usage == 0x00010030) { /* X */
+		lcol->loc_x = h;
+		if ((h.flags & 0x04) == 0) {
+		    if (acol->xmin == acol->xmax) {
+			acol->xmin = h.logical_minimum;
+			acol->xmax = h.logical_maximum;
+		    } else {
+			acol->xmin = min(acol->xmin, h.logical_minimum);
+			acol->xmax = max(acol->xmax, h.logical_maximum);
+		    }
+		}
+	    } else if (h.usage == 0x00010031) { /* Y */
+		lcol->loc_y = h;
+		if ((h.flags & 0x04) == 0) {
+		    if (acol->ymin == acol->ymax) {
+			acol->ymin = h.logical_minimum;
+			acol->ymax = h.logical_maximum;
+		    } else {
+			acol->ymin = min(acol->ymin, h.logical_minimum);
+			acol->ymax = max(acol->ymax, h.logical_maximum);
+		    }
+		}
+	    } else if (h.usage == 0x00010038) { /* Z */
+		lcol->loc_z = h;
+		acol->hasZ = 1;
+	    } else if (h.usage == 0x000c0238) { /* W */
+		lcol->loc_w = h;
+		acol->hasW = 1;
+	    } else if (h.usage == 0x000d0030) { /* Press */
+		lcol->loc_p = h;
+		if ((h.flags & 0x04) == 0) {
+		    if (acol->pmin == acol->pmax) {
+			acol->pmin = h.logical_minimum;
+			acol->pmax = h.logical_maximum;
+		    } else {
+			acol->pmin = min(acol->pmin, h.logical_minimum);
+			acol->pmax = max(acol->pmax, h.logical_maximum);
+		    }
+		}
+	    } else if (h.usage == 0x000d0032) /* In Range */
+		lcol->loc_in_range = h;
+	    else if (h.usage == 0x000d0047) /* Valid */
+		lcol->loc_valid = h;
+	    else if (h.usage > 0x00090000 &&
+		h.usage <= 0x00090000 + MSE_MAXBUTTONS) { /* Buttons */
+		    lcol->loc_btn[(h.usage & 0xffff) - 1] = h;
+		    acol->nbuttons = max(acol->nbuttons, h.usage & 0xffff);
+	    } else if (h.usage == 0x000d0042) { /* Tip Switch */
+		lcol->loc_btn[0] = h;
+		acol->nbuttons = max(acol->nbuttons, 1);
+	    } else if (h.usage == 0x000d0044) { /* Barrel Switch */
+		lcol->loc_btn[1] = h;
+		acol->nbuttons = max(acol->nbuttons, 2);
+	    } else if (h.usage == 0x000d0045) { /* Eraser */
+		lcol->loc_btn[3] = h;
+		acol->nbuttons = max(acol->nbuttons, 4);
+	    } else if (h.usage == 0x000d0046) { /* Tablet Pick */
+		lcol->loc_btn[2] = h;
+		acol->nbuttons = max(acol->nbuttons, 3);
+	    } else if (h.usage == 0x000d0054) /* Contact Count */
+		acol->loc_cc = h;
+	    else
+		used = 0;
+	    lcolused += used;
+	    acolused += used;
+	    break;
+	default:
+	    break;
+	}
+    }
+    if (lcolused)
+	acol->nlcols++;
+    if (acolused)
+	pUsbMse->nacols++;
+    hid_end_parse(d);
+    xf86Msg(X_DEFAULT, "%s: Found %d usable logical collections\n",
+	pInfo->name, pUsbMse->nacols);
+
+#endif /* !defined(FREEBSD_USB) */
+
     /* Allocate buffer */
     if (pUsbMse->packetSize <= 8) {
         pUsbMse->buffer = pMse->protoBuf;
@@ -692,10 +1470,15 @@ usbPreInit(InputInfoPtr pInfo, const cha
     if (pUsbMse->buffer == NULL) {
         xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name);
         free(pUsbMse);
+#if !defined(FREEBSD_USB)
         free(pMse);
+#endif
         xf86CloseSerial(pInfo->fd);
         return FALSE;
     }
+
+#if !defined(FREEBSD_USB)
+
 #ifdef USB_NEW_HID
     if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
                    hid_input, &pUsbMse->loc_x, pUsbMse->iid) < 0) {
@@ -733,12 +1516,15 @@ usbPreInit(InputInfoPtr pInfo, const cha
     }
     pMse->buttons = i-1;

+#endif /* !defined(FREEBSD_USB) */
+
     xf86CloseSerial(pInfo->fd);
     pInfo->fd = -1;

     /* Private structure */
     pMse->mousePriv = pUsbMse;

+#if !defined(FREEBSD_USB)
     /* Process common mouse options (like Emulate3Buttons, etc). */
     pMse->CommonOptions(pInfo);

@@ -749,8 +1535,137 @@ usbPreInit(InputInfoPtr pInfo, const cha
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
     pInfo->flags |= XI86_CONFIGURED;
 #endif
+
+#endif /* !defined(FREEBSD_USB) */
+
     return TRUE;
 }
+
+#if defined(FREEBSD_USB)
+
+/* This function is called when the protocol is "usb". */
+static Bool
+usbPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
+{
+    InputInfoPtr pMatch;
+    MouseDevPtr pMse = pInfo->private;
+    UsbMsePtr pUsbMse;
+    struct UsbMseAcol *acol;
+    char *str;
+    int i, colopt;
+
+    pMse->protocol = protocol;
+    xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
+
+    /* Collect the options, and process the common options. */
+    COLLECT_INPUT_OPTIONS(pInfo, NULL);
+    xf86ProcessCommonOptions(pInfo, pInfo->options);
+
+    /* Check if this HID device is already opened. */
+    for (pMatch = xf86FirstLocalDevice(); pMatch != NULL; pMatch = pMatch->next) {
+	if ((pInfo != pMatch) && strstr(pMatch->drv->driverName, "mouse")) {
+	    char *dev1, *dev2;
+
+	    dev1 = xf86SetStrOption(pInfo->options, "Device", NULL);
+	    dev2 = xf86SetStrOption(pMatch->options, "Device", NULL);
+	    if (strcmp(dev1, dev2) == 0) {
+		free(dev1);
+		free(dev2);
+		break;
+	    }
+	    free(dev1);
+	    free(dev2);
+	}
+    }
+    if (pMatch == NULL) {
+	xf86Msg(X_DEFAULT, "%s: Opening new HID device\n", pInfo->name);
+	if (!usbInitFirst(pInfo)) {
+	    free(pMse);
+	    return FALSE;
+	}
+    } else {
+	pMse->mousePriv = ((MouseDevPtr)pMatch->private)->mousePriv;
+	xf86Msg(X_DEFAULT, "%s: Attaching to already opened HID device\n",
+	    pInfo->name);
+    }
+    pUsbMse = pMse->mousePriv;
+
+    /* Attach to collection, respecting "Collection" option. */
+    colopt = xf86SetIntOption(pInfo->options, "Collection", 0);
+    for (i = 0; i < pUsbMse->nacols; i++) {
+	if (pUsbMse->acols[i].pInfo == NULL &&
+		(colopt == 0 || i == colopt - 1)) {
+	    pUsbMse->acols[i].pInfo = pInfo;
+	    break;
+	}
+    }
+    xf86Msg(colopt == 0 ? X_DEFAULT : X_CONFIG,
+	"%s: Collection: %d\n", pInfo->name,
+	i == pUsbMse->nacols ? colopt : i + 1);
+    if (i == pUsbMse->nacols) {
+	xf86Msg(X_ERROR,
+	    "%s: Application collection not found or already handled\n",
+	    pInfo->name);
+	free(pMse);
+	return FALSE;
+    }
+
+    acol = &pUsbMse->acols[i];
+    pMse->buttons = acol->nbuttons;
+    if (pMse->buttons == 2)
+	pMse->buttons = 3;
+    if (acol->xmin != acol->xmax || acol->ymin != acol->ymax)
+	pMse->disableXY = TRUE;
+    pMse->hasZ = acol->hasZ;
+    pMse->hasW = acol->hasW;
+
+    /* Process common mouse options (like Emulate3Buttons, etc). */
+    pMse->CommonOptions(pInfo);
+
+    /* Process "Calibration" option. */
+    str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
+    if (str != NULL && (acol->xmin != acol->xmax || acol->ymin != acol->ymax)) {
+	int j, xmin, xmax, ymin, ymax, pmin, pmax;
+
+	j = sscanf(str, "%d %d %d %d %d %d", &xmin, &xmax, &ymin, &ymax, &pmin, &pmax);
+	if (j == 4) {
+	    xf86Msg(X_CONFIG, "%s: Calibration: %d %d %d %d\n",
+		pInfo->name, xmin, xmax, ymin, ymax);
+	    acol->cxmin = xmin;
+	    acol->cxmax = xmax;
+	    acol->cymin = ymin;
+	    acol->cymax = ymax;
+	} else if (j == 6) {
+	    xf86Msg(X_CONFIG, "%s: Calibration: %d %d %d %d %d %d\n",
+		pInfo->name, xmin, xmax, ymin, ymax, pmin, pmax);
+	    acol->cxmin = xmin;
+	    acol->cxmax = xmax;
+	    acol->cymin = ymin;
+	    acol->cymax = ymax;
+	    acol->cpmin = pmin;
+	    acol->cpmax = pmax;
+	} else
+	    xf86Msg(X_WARNING, "%s: Calibration: Invalid arguments\n",
+		pInfo->name);
+	free(str);
+    } else if (acol->xmin != acol->xmax || acol->ymin != acol->ymax) {
+	xf86Msg(X_DEFAULT, "%s: Calibration: %d %d %d %d %d %d\n",
+	    pInfo->name, acol->xmin, acol->xmax, acol->ymin, acol->ymax,
+	    acol->pmin, acol->pmax);
+    }
+
+    /* Setup the local procs. */
+    pInfo->device_control = usbMouseProc;
+    pInfo->read_input = usbReadInput;
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
+    pInfo->flags |= XI86_CONFIGURED;
+#endif
+    return TRUE;
+}
+
+#endif /* defined(FREEBSD_USB) */
+
 #endif /* USBMOUSE */

 static Bool
@@ -784,7 +1699,15 @@ OSMouseInit(int flags)
     p->CheckProtocol = CheckProtocol;
 #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE)
     p->SetupAuto = SetupAuto;
+
+#if !defined(FREEBSD_USB)
+    p->SetPS2Res = SetSysMouseRes;
+#else
+#ifndef XPS2_SUPPORT
     p->SetPS2Res = SetSysMouseRes;
+#endif
+#endif
+
     p->SetBMRes = SetSysMouseRes;
     p->SetMiscRes = SetSysMouseRes;
 #endif




>Audit-Trail:
From: Thomas Klausner <wiz@NetBSD.org>
To: NetBSD bugtracking <gnats-bugs@NetBSD.org>
Cc: 
Subject: Re: pkg/50068: x11/xf86-input-mouse dports patches for DragonFly and
 FreeBSD
Date: Mon, 20 Jul 2015 11:34:08 +0200

 Same question -- what's the xorg state of this patch?
  Thomas

From: David Shao <davshao@gmail.com>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: pkg/50068: x11/xf86-input-mouse dports patches for DragonFly and FreeBSD
Date: Thu, 23 Jul 2015 20:39:13 -0700

 On Mon, Jul 20, 2015 at 2:35 AM, Thomas Klausner <wiz@netbsd.org> wrote:
 > The following reply was made to PR pkg/50068; it has been noted by GNATS.
 >
 > From: Thomas Klausner <wiz@NetBSD.org>
 > To: NetBSD bugtracking <gnats-bugs@NetBSD.org>
 > Cc:
 > Subject: Re: pkg/50068: x11/xf86-input-mouse dports patches for DragonFly and
 >  FreeBSD
 > Date: Mon, 20 Jul 2015 11:34:08 +0200
 >
 >  Same question -- what's the xorg state of this patch?
 >   Thomas

 The patch has changes to at least two files that are in my opinion way
 too large to be properly examined except by the people who wrote the
 changes.  To my untrained eye at this point in time the USB mouse code
 for Net/OpenBSD versus Free/DragonFlyBSD has very little in common,
 let alone whatever Linux does, and needs a major refactoring if it is
 to be understandable for review by upstream.

 Nevertheless the code is all we've got for DragonFly and FreeBSD for
 USB mice.  I didn't just invent it from nowhere, it's the code
 DragonFly dports and FreeBSD ports already uses.  And I have tested it
 to confirm it allows functional desktop usage on DragonFly
 4.3-DEVELOPMENT and FreeBSD 10.1, something that was missing before.

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.