16aab59a7Smrg
26aab59a7Smrg/*
36aab59a7Smrg * Copyright (c) 1999-2003 by The XFree86 Project, Inc.
46aab59a7Smrg *
56aab59a7Smrg * Permission is hereby granted, free of charge, to any person obtaining a
66aab59a7Smrg * copy of this software and associated documentation files (the "Software"),
76aab59a7Smrg * to deal in the Software without restriction, including without limitation
86aab59a7Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
96aab59a7Smrg * and/or sell copies of the Software, and to permit persons to whom the
106aab59a7Smrg * Software is furnished to do so, subject to the following conditions:
116aab59a7Smrg *
126aab59a7Smrg * The above copyright notice and this permission notice shall be included in
136aab59a7Smrg * all copies or substantial portions of the Software.
146aab59a7Smrg *
156aab59a7Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166aab59a7Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176aab59a7Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186aab59a7Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
196aab59a7Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
206aab59a7Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
216aab59a7Smrg * OTHER DEALINGS IN THE SOFTWARE.
226aab59a7Smrg *
236aab59a7Smrg * Except as contained in this notice, the name of the copyright holder(s)
246aab59a7Smrg * and author(s) shall not be used in advertising or otherwise to promote
256aab59a7Smrg * the sale, use or other dealings in this Software without prior written
266aab59a7Smrg * authorization from the copyright holder(s) and author(s).
276aab59a7Smrg */
286aab59a7Smrg
296aab59a7Smrg#include <xorg-server.h>
306aab59a7Smrg
316aab59a7Smrg#include <X11/X.h>
326aab59a7Smrg#include "xf86.h"
336aab59a7Smrg#include "xf86Priv.h"
346aab59a7Smrg#include "xf86_OSlib.h"
356aab59a7Smrg#include "xf86Xinput.h"
36bd3a1963Smrg#include "mouse.h"
376aab59a7Smrg#include "xisb.h"
386aab59a7Smrg#include "mipointer.h"
396aab59a7Smrg#ifdef WSCONS_SUPPORT
406aab59a7Smrg#include <dev/wscons/wsconsio.h>
416aab59a7Smrg#endif
426aab59a7Smrg#ifdef USBMOUSE_SUPPORT
436aab59a7Smrg#ifdef HAS_LIB_USB_HID
446aab59a7Smrg#include <usbhid.h>
456aab59a7Smrg#else
466aab59a7Smrg#include "usb.h"
476aab59a7Smrg#endif
486aab59a7Smrg
496aab59a7Smrg#include <dev/usb/usb.h>
506aab59a7Smrg#ifdef USB_GET_REPORT_ID
516aab59a7Smrg#define USB_NEW_HID
526aab59a7Smrg#endif
536aab59a7Smrg
546aab59a7Smrg#define HUP_GENERIC_DESKTOP     0x0001
556aab59a7Smrg#define HUP_BUTTON              0x0009
566aab59a7Smrg
576aab59a7Smrg#define HUG_X                   0x0030
586aab59a7Smrg#define HUG_Y                   0x0031
596aab59a7Smrg#define HUG_Z                   0x0032
606aab59a7Smrg#define HUG_WHEEL               0x0038
616aab59a7Smrg
626aab59a7Smrg#define HID_USAGE2(p,u) (((p) << 16) | u)
636aab59a7Smrg
644d6d3f96Smrg/* The UMS mice have middle button as number 3 */
656aab59a7Smrg#define UMS_BUT(i) ((i) == 0 ? 2 : (i) == 1 ? 0 : (i) == 2 ? 1 : (i))
666aab59a7Smrg#endif /* USBMOUSE_SUPPORT */
676aab59a7Smrg
686aab59a7Smrg#ifdef USBMOUSE_SUPPORT
696aab59a7Smrgstatic void usbSigioReadInput (int fd, void *closure);
706aab59a7Smrg#endif
716aab59a7Smrgstatic const char *FindDevice(InputInfoPtr, const char *, int);
726aab59a7Smrg
736aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
746aab59a7Smrg/* These are for FreeBSD and DragonFly */
751450c749Smrg#define DEFAULT_MOUSE_DEV               "/dev/mouse"
761450c749Smrg#define DEFAULT_SYSMOUSE_DEV            "/dev/sysmouse"
771450c749Smrg#define DEFAULT_PS2_DEV                 "/dev/psm0"
786aab59a7Smrg
796aab59a7Smrgstatic const char *mouseDevs[] = {
801450c749Smrg        DEFAULT_MOUSE_DEV,
811450c749Smrg        DEFAULT_SYSMOUSE_DEV,
821450c749Smrg        DEFAULT_PS2_DEV,
831450c749Smrg        NULL
846aab59a7Smrg};
856aab59a7Smrg#elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
864d6d3f96Smrg/* Only wsmouse mice are autoconfigured for now on OpenBSD */
871450c749Smrg#define DEFAULT_WSMOUSE_DEV             "/dev/wsmouse"
881450c749Smrg#define DEFAULT_WSMOUSE0_DEV            "/dev/wsmouse0"
896aab59a7Smrg
906aab59a7Smrgstatic const char *mouseDevs[] = {
911450c749Smrg        DEFAULT_WSMOUSE_DEV,
921450c749Smrg        DEFAULT_WSMOUSE0_DEV,
931450c749Smrg        NULL
946aab59a7Smrg};
956aab59a7Smrg#endif
966aab59a7Smrg
976aab59a7Smrgstatic int
986aab59a7SmrgSupportedInterfaces(void)
996aab59a7Smrg{
100352aa7aeSmrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__NetBSD__)
1016aab59a7Smrg    return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC;
1026aab59a7Smrg#else
103bd3a1963Smrg    return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO | MSE_MISC;
1046aab59a7Smrg#endif
1056aab59a7Smrg}
1066aab59a7Smrg
1076aab59a7Smrg/* Names of protocols that are handled internally here. */
1086aab59a7Smrgstatic const char *internalNames[] = {
1096aab59a7Smrg#if defined(WSCONS_SUPPORT)
1101450c749Smrg        "WSMouse",
1116aab59a7Smrg#endif
1126aab59a7Smrg#if defined(USBMOUSE_SUPPORT)
1131450c749Smrg        "usb",
1146aab59a7Smrg#endif
1151450c749Smrg        NULL
1166aab59a7Smrg};
1176aab59a7Smrg
1186aab59a7Smrg/*
1196aab59a7Smrg * Names of MSC_MISC protocols that the OS supports.  These are decoded by
1206aab59a7Smrg * main "mouse" driver.
1216aab59a7Smrg */
1226aab59a7Smrgstatic const char *miscNames[] = {
1236aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
1241450c749Smrg        "SysMouse",
1256aab59a7Smrg#endif
1261450c749Smrg        NULL
1276aab59a7Smrg};
1286aab59a7Smrg
1296aab59a7Smrgstatic const char **
1306aab59a7SmrgBuiltinNames(void)
1316aab59a7Smrg{
1326aab59a7Smrg    return internalNames;
1336aab59a7Smrg}
1346aab59a7Smrg
1356aab59a7Smrgstatic Bool
1366aab59a7SmrgCheckProtocol(const char *protocol)
1376aab59a7Smrg{
1386aab59a7Smrg    int i;
1396aab59a7Smrg
1406aab59a7Smrg    for (i = 0; internalNames[i]; i++)
1411450c749Smrg        if (xf86NameCmp(protocol, internalNames[i]) == 0)
1421450c749Smrg            return TRUE;
1436aab59a7Smrg    for (i = 0; miscNames[i]; i++)
1441450c749Smrg        if (xf86NameCmp(protocol, miscNames[i]) == 0)
1451450c749Smrg            return TRUE;
1466aab59a7Smrg    return FALSE;
1476aab59a7Smrg}
1486aab59a7Smrg
1496aab59a7Smrgstatic const char *
1506aab59a7SmrgDefaultProtocol(void)
1516aab59a7Smrg{
1526aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
1536aab59a7Smrg    return "Auto";
1546aab59a7Smrg#elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
1556aab59a7Smrg    return "WSMouse";
1566aab59a7Smrg#else
1576aab59a7Smrg    return NULL;
1586aab59a7Smrg#endif
1596aab59a7Smrg}
1606aab59a7Smrg
1616aab59a7Smrg#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE)
1626aab59a7Smrgstatic struct {
1631450c749Smrg        int dproto;
1641450c749Smrg        const char *name;
1656aab59a7Smrg} devproto[] = {
1661450c749Smrg        { MOUSE_PROTO_MS,               "Microsoft" },
1671450c749Smrg        { MOUSE_PROTO_MSC,              "MouseSystems" },
1681450c749Smrg        { MOUSE_PROTO_LOGI,             "Logitech" },
1691450c749Smrg        { MOUSE_PROTO_MM,               "MMSeries" },
1701450c749Smrg        { MOUSE_PROTO_LOGIMOUSEMAN,     "MouseMan" },
1711450c749Smrg        { MOUSE_PROTO_BUS,              "BusMouse" },
1721450c749Smrg        { MOUSE_PROTO_INPORT,           "BusMouse" },
1731450c749Smrg        { MOUSE_PROTO_PS2,              "PS/2" },
1741450c749Smrg        { MOUSE_PROTO_HITTAB,           "MMHitTab" },
1751450c749Smrg        { MOUSE_PROTO_GLIDEPOINT,       "GlidePoint" },
1761450c749Smrg        { MOUSE_PROTO_INTELLI,          "Intellimouse" },
1771450c749Smrg        { MOUSE_PROTO_THINK,            "ThinkingMouse" },
1781450c749Smrg        { MOUSE_PROTO_SYSMOUSE,         "SysMouse" }
1796aab59a7Smrg};
1801450c749Smrg
1816aab59a7Smrgstatic const char *
1826aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara)
1836aab59a7Smrg{
1846aab59a7Smrg    int i;
1856aab59a7Smrg    mousehw_t hw;
1866aab59a7Smrg    mousemode_t mode;
1876aab59a7Smrg
1886aab59a7Smrg    if (pInfo->fd == -1)
1891450c749Smrg        return NULL;
1906aab59a7Smrg
1916aab59a7Smrg    /* set the driver operation level, if applicable */
1926aab59a7Smrg    i = 1;
1936aab59a7Smrg    ioctl(pInfo->fd, MOUSE_SETLEVEL, &i);
1941450c749Smrg
1956aab59a7Smrg    /* interrogate the driver and get some intelligence on the device. */
1966aab59a7Smrg    hw.iftype = MOUSE_IF_UNKNOWN;
1976aab59a7Smrg    hw.model = MOUSE_MODEL_GENERIC;
1986aab59a7Smrg    ioctl(pInfo->fd, MOUSE_GETHWINFO, &hw);
1996aab59a7Smrg    xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: hw.iftype is %d, hw.model is %d\n",
2001450c749Smrg                pInfo->name, hw.iftype, hw.model);
2016aab59a7Smrg    if (ioctl(pInfo->fd, MOUSE_GETMODE, &mode) == 0) {
2021450c749Smrg        for (i = 0; i < sizeof(devproto)/sizeof(devproto[0]); ++i) {
2031450c749Smrg            if (mode.protocol == devproto[i].dproto) {
2041450c749Smrg                /* override some parameters */
2051450c749Smrg                if (protoPara) {
2061450c749Smrg                    protoPara[4] = mode.packetsize;
2071450c749Smrg                    protoPara[0] = mode.syncmask[0];
2081450c749Smrg                    protoPara[1] = mode.syncmask[1];
2091450c749Smrg                }
2101450c749Smrg                xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
2111450c749Smrg                            pInfo->name, devproto[i].name);
2121450c749Smrg                return devproto[i].name;
2131450c749Smrg            }
2141450c749Smrg        }
2156aab59a7Smrg    }
2166aab59a7Smrg    return NULL;
2176aab59a7Smrg}
2186aab59a7Smrg
2196aab59a7Smrgstatic void
2206aab59a7SmrgSetSysMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res)
2216aab59a7Smrg{
2226aab59a7Smrg    mousemode_t mode;
2236aab59a7Smrg    MouseDevPtr pMse;
2246aab59a7Smrg
2256aab59a7Smrg    pMse = pInfo->private;
2266aab59a7Smrg
2276aab59a7Smrg    mode.rate = rate > 0 ? rate : -1;
2286aab59a7Smrg    mode.resolution = res > 0 ? res : -1;
2296aab59a7Smrg    mode.accelfactor = -1;
2306aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
2316aab59a7Smrg    if (pMse->autoProbe ||
2321450c749Smrg        (protocol && xf86NameCmp(protocol, "SysMouse") == 0)) {
2331450c749Smrg        /*
2341450c749Smrg         * As the FreeBSD sysmouse driver defaults to protocol level 0
2354d6d3f96Smrg         * every time it is opened we enforce protocol level 1 again at
2361450c749Smrg         * this point.
2371450c749Smrg         */
2381450c749Smrg        mode.level = 1;
2396aab59a7Smrg    } else
2401450c749Smrg        mode.level = -1;
2416aab59a7Smrg#else
2426aab59a7Smrg    mode.level = -1;
2436aab59a7Smrg#endif
2446aab59a7Smrg    ioctl(pInfo->fd, MOUSE_SETMODE, &mode);
2456aab59a7Smrg}
2466aab59a7Smrg#endif
2476aab59a7Smrg
2486aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
2496aab59a7Smrg
2506aab59a7Smrg#define MOUSED_PID_FILE "/var/run/moused.pid"
2516aab59a7Smrg
2526aab59a7Smrg/*
2536aab59a7Smrg * Try to check if moused is running.  DEFAULT_SYSMOUSE_DEV is useless without
2546aab59a7Smrg * it.  There doesn't seem to be a better way of checking.
2556aab59a7Smrg */
2566aab59a7Smrgstatic Bool
2576aab59a7SmrgMousedRunning(void)
2586aab59a7Smrg{
2596aab59a7Smrg    FILE *f = NULL;
2606aab59a7Smrg    unsigned int pid;
2616aab59a7Smrg
2626aab59a7Smrg    if ((f = fopen(MOUSED_PID_FILE, "r")) != NULL) {
2631450c749Smrg        if (fscanf(f, "%u", &pid) == 1 && pid > 0) {
2641450c749Smrg            if (kill(pid, 0) == 0) {
2651450c749Smrg                fclose(f);
2661450c749Smrg                return TRUE;
2671450c749Smrg            }
2681450c749Smrg        }
2691450c749Smrg        fclose(f);
2706aab59a7Smrg    }
2716aab59a7Smrg    return FALSE;
2726aab59a7Smrg}
2736aab59a7Smrg
2746aab59a7Smrgstatic const char *
2756aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
2766aab59a7Smrg{
2776aab59a7Smrg    int fd = -1;
2786aab59a7Smrg    const char **pdev, *dev = NULL;
2796aab59a7Smrg    Bool devMouse = FALSE;
2806aab59a7Smrg    struct stat devMouseStat;
2816aab59a7Smrg    struct stat sb;
2826aab59a7Smrg
2836aab59a7Smrg    for (pdev = mouseDevs; *pdev; pdev++) {
2841450c749Smrg        SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK));
2851450c749Smrg        if (fd == -1) {
2866aab59a7Smrg#ifdef DEBUG
2871450c749Smrg            ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno));
2886aab59a7Smrg#endif
2891450c749Smrg        } else {
2901450c749Smrg            /*
2911450c749Smrg             * /dev/mouse is held until checks for matches with other devices
2921450c749Smrg             * are done.  This is so that when it points to /dev/sysmouse,
2931450c749Smrg             * the test for whether /dev/sysmouse is usable can be made.
2941450c749Smrg             */
2951450c749Smrg            if (!strcmp(*pdev, DEFAULT_MOUSE_DEV)) {
2961450c749Smrg                if (fstat(fd, &devMouseStat) == 0)
2971450c749Smrg                    devMouse = TRUE;
2981450c749Smrg                close(fd);
2991450c749Smrg                continue;
3001450c749Smrg            } else if (!strcmp(*pdev, DEFAULT_SYSMOUSE_DEV)) {
3011450c749Smrg                /* Check if /dev/mouse is the same as /dev/sysmouse. */
3021450c749Smrg                if (devMouse && fstat(fd, &sb) == 0 &&
3031450c749Smrg                    devMouseStat.st_dev == sb.st_dev &&
3041450c749Smrg                    devMouseStat.st_ino == sb.st_ino) {
3051450c749Smrg                    /* If the same, use /dev/sysmouse. */
3061450c749Smrg                    devMouse = FALSE;
3071450c749Smrg                }
3081450c749Smrg                close(fd);
3091450c749Smrg                if (MousedRunning())
3101450c749Smrg                    break;
3111450c749Smrg                else {
3126aab59a7Smrg#ifdef DEBUG
3131450c749Smrg                    ErrorF("moused isn't running\n");
3146aab59a7Smrg#endif
3151450c749Smrg                }
3161450c749Smrg            } else {
3171450c749Smrg                close(fd);
3181450c749Smrg                break;
3191450c749Smrg            }
3201450c749Smrg        }
3216aab59a7Smrg    }
3226aab59a7Smrg
3236aab59a7Smrg    if (*pdev)
3241450c749Smrg        dev = *pdev;
3256aab59a7Smrg    else if (devMouse)
3261450c749Smrg        dev = DEFAULT_MOUSE_DEV;
3276aab59a7Smrg
3286aab59a7Smrg    if (dev) {
3291450c749Smrg        /* Set the Device option. */
3301450c749Smrg        pInfo->options =
3311450c749Smrg            xf86AddNewOption(pInfo->options, "Device", dev);
3321450c749Smrg        xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n",
3331450c749Smrg                pInfo->name, dev);
3346aab59a7Smrg    }
3356aab59a7Smrg
3366aab59a7Smrg    return *pdev;
3376aab59a7Smrg}
3386aab59a7Smrg#endif
3396aab59a7Smrg
3406aab59a7Smrg#if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
3416aab59a7Smrg
3426aab59a7Smrg/* Only support wsmouse configuration for now */
3436aab59a7Smrgstatic const char *
3446aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara)
3456aab59a7Smrg{
3466aab59a7Smrg
3476aab59a7Smrg    xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
3481450c749Smrg                pInfo->name, "wsmouse");
3496aab59a7Smrg    return "wsmouse";
3506aab59a7Smrg}
3516aab59a7Smrg
3526aab59a7Smrgstatic void
3536aab59a7SmrgSetMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res)
3546aab59a7Smrg{
3556aab59a7Smrg
3566aab59a7Smrg    xf86MsgVerb(X_INFO, 3, "%s: SetMouseRes: protocol %s rate %d res %d\n",
3571450c749Smrg            pInfo->name, protocol, rate, res);
3586aab59a7Smrg}
3596aab59a7Smrg
3606aab59a7Smrgstatic const char *
3616aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
3626aab59a7Smrg{
3636aab59a7Smrg    int fd = -1;
3646aab59a7Smrg    const char **pdev;
3656aab59a7Smrg
3666aab59a7Smrg    for (pdev = mouseDevs; *pdev; pdev++) {
3671450c749Smrg        SYSCALL(fd = open(*pdev, O_RDWR | O_NONBLOCK));
3681450c749Smrg        if (fd != -1) {
3691450c749Smrg            /* Set the Device option. */
3701450c749Smrg            pInfo->options =
3711450c749Smrg                xf86AddNewOption(pInfo->options,
3721450c749Smrg                                 "Device", *pdev);
3731450c749Smrg            xf86Msg(X_INFO, "%s: found Device \"%s\"\n",
3741450c749Smrg                    pInfo->name, *pdev);
3751450c749Smrg            close(fd);
3761450c749Smrg            break;
3771450c749Smrg        }
3786aab59a7Smrg    }
3796aab59a7Smrg    return *pdev;
3806aab59a7Smrg}
3816aab59a7Smrg#endif /* __OpenBSD__ || __NetBSD__ && WSCONS_SUPPORT */
3826aab59a7Smrg
3836aab59a7Smrg#ifdef WSCONS_SUPPORT
3846aab59a7Smrg#define NUMEVENTS 64
3856aab59a7Smrg
386216a823bSjmcneillstatic void
387216a823bSjmcneillwsconsAutoCalibrate(InputInfoPtr pInfo)
388216a823bSjmcneill{
389216a823bSjmcneill    MouseDevPtr pMse;
390216a823bSjmcneill    int width, height;
391216a823bSjmcneill    struct wsmouse_calibcoords cal;
392216a823bSjmcneill
393216a823bSjmcneill    pMse = pInfo->private;
394216a823bSjmcneill    width = screenInfo.screens[pMse->screenNo]->width;
395216a823bSjmcneill    height = screenInfo.screens[pMse->screenNo]->height;
396216a823bSjmcneill
397216a823bSjmcneill    if (width != pMse->lastScreenWidth || height != pMse->lastScreenHeight) {
398216a823bSjmcneill        if (ioctl(pInfo->fd, WSMOUSEIO_GCALIBCOORDS, &cal) == 0 &&
399216a823bSjmcneill            cal.minx != cal.maxy && cal.miny != cal.maxy) {
400216a823bSjmcneill
401216a823bSjmcneill            xf86Msg(X_INFO, "%s: auto-calibrating abs pointer for %dx%d screen\n",
402216a823bSjmcneill                    pInfo->name, width, height);
403216a823bSjmcneill
404216a823bSjmcneill            pMse->minX = cal.minx;
405216a823bSjmcneill            pMse->minY = cal.miny;
406216a823bSjmcneill            pMse->maxX = cal.maxx;
407216a823bSjmcneill            pMse->maxY = cal.maxy;
408216a823bSjmcneill            pMse->translateAbs =
409216a823bSjmcneill                cal.samplelen == WSMOUSE_CALIBCOORDS_RESET;
410216a823bSjmcneill        }
411216a823bSjmcneill        pMse->lastScreenWidth = width;
412216a823bSjmcneill        pMse->lastScreenHeight = height;
413216a823bSjmcneill    }
414216a823bSjmcneill}
415216a823bSjmcneill
416216a823bSjmcneillstatic int
417216a823bSjmcneillwsconsTranslate(InputInfoPtr pInfo, int scrRange, int rawMin, int rawMax, int rawVal)
418216a823bSjmcneill{
419216a823bSjmcneill    return ((rawVal - rawMin) * scrRange) / (rawMax - rawMin);
420216a823bSjmcneill}
421216a823bSjmcneill
4226aab59a7Smrgstatic void
4236aab59a7SmrgwsconsReadInput(InputInfoPtr pInfo)
4246aab59a7Smrg{
4256aab59a7Smrg    MouseDevPtr pMse;
4266aab59a7Smrg    static struct wscons_event eventList[NUMEVENTS];
4271450c749Smrg    int n, c;
4286aab59a7Smrg    struct wscons_event *event = eventList;
4296aab59a7Smrg    unsigned char *pBuf;
4306aab59a7Smrg
4316aab59a7Smrg    pMse = pInfo->private;
4326aab59a7Smrg
433216a823bSjmcneill    if (pMse->autoCalibrate)
434216a823bSjmcneill        wsconsAutoCalibrate(pInfo);
435216a823bSjmcneill
4366aab59a7Smrg    XisbBlockDuration(pMse->buffer, -1);
4376aab59a7Smrg    pBuf = (unsigned char *)eventList;
4386aab59a7Smrg    n = 0;
4396aab59a7Smrg    while (n < sizeof(eventList) && (c = XisbRead(pMse->buffer)) >= 0) {
4401450c749Smrg        pBuf[n++] = (unsigned char)c;
4416aab59a7Smrg    }
4426aab59a7Smrg
4436aab59a7Smrg    if (n == 0)
4441450c749Smrg        return;
4456aab59a7Smrg
4466aab59a7Smrg    n /= sizeof(struct wscons_event);
4476aab59a7Smrg    while( n-- ) {
4481450c749Smrg        int buttons = pMse->lastButtons;
4491450c749Smrg        int dx = 0, dy = 0, dz = 0, dw = 0, x, y;
4501450c749Smrg        switch (event->type) {
4511450c749Smrg        case WSCONS_EVENT_MOUSE_UP:
4526aab59a7Smrg#define BUTBIT (1 << (event->value <= 2 ? 2 - event->value : event->value))
4531450c749Smrg            buttons &= ~BUTBIT;
4541450c749Smrg            break;
4551450c749Smrg        case WSCONS_EVENT_MOUSE_DOWN:
4561450c749Smrg            buttons |= BUTBIT;
4571450c749Smrg            break;
4581450c749Smrg        case WSCONS_EVENT_MOUSE_DELTA_X:
4591450c749Smrg            dx = event->value;
4601450c749Smrg            break;
4611450c749Smrg        case WSCONS_EVENT_MOUSE_DELTA_Y:
4621450c749Smrg            dy = -event->value;
4631450c749Smrg            break;
4646aab59a7Smrg#ifdef WSCONS_EVENT_MOUSE_DELTA_Z
4651450c749Smrg        case WSCONS_EVENT_MOUSE_DELTA_Z:
4661450c749Smrg            dz = event->value;
4671450c749Smrg            break;
4686aab59a7Smrg#endif
4696aab59a7Smrg#ifdef WSCONS_EVENT_MOUSE_DELTA_W
4701450c749Smrg        case WSCONS_EVENT_MOUSE_DELTA_W:
4711450c749Smrg            dw = event->value;
4721450c749Smrg            break;
473f3d19aa6Schristos#endif
474f3d19aa6Schristos	case WSCONS_EVENT_MOUSE_ABSOLUTE_X:
475f3d19aa6Schristos	    x = event->value;
476216a823bSjmcneill            if (pMse->translateAbs)
477216a823bSjmcneill                x = wsconsTranslate(pInfo, pMse->lastScreenWidth,
478216a823bSjmcneill                                    pMse->minX, pMse->maxX, x);
479352aa7aeSmrg	    xf86PostMotionEvent(pInfo->dev, TRUE, 0, 1, x);
480f3d19aa6Schristos	    ++event;
481f3d19aa6Schristos	    continue;
482f3d19aa6Schristos	case WSCONS_EVENT_MOUSE_ABSOLUTE_Y:
483f3d19aa6Schristos	    y = event->value;
484216a823bSjmcneill            if (pMse->translateAbs)
485216a823bSjmcneill                y = wsconsTranslate(pInfo, pMse->lastScreenWidth,
486216a823bSjmcneill                                    pMse->minY, pMse->maxY, y);
487352aa7aeSmrg	    xf86PostMotionEvent(pInfo->dev, TRUE, 1, 1, y);
488f3d19aa6Schristos	    ++event;
489f3d19aa6Schristos	    continue;
490f3d19aa6Schristos#ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_Z
491f3d19aa6Schristos	case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
492f3d19aa6Schristos	    ++event;
493f3d19aa6Schristos	    continue;
494f3d19aa6Schristos#endif
495f3d19aa6Schristos#ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_W
496f3d19aa6Schristos	case WSCONS_EVENT_MOUSE_ABSOLUTE_W:
497f3d19aa6Schristos	    ++event;
498f3d19aa6Schristos	    continue;
4996aab59a7Smrg#endif
5001450c749Smrg        default:
5011450c749Smrg            LogMessageVerbSigSafe(X_WARNING, -1,
5021450c749Smrg                                  "%s: bad wsmouse event type=%d\n", pInfo->name,
5031450c749Smrg                                  event->type);
5041450c749Smrg            ++event;
5051450c749Smrg            continue;
5061450c749Smrg        }
5071450c749Smrg
5081450c749Smrg        pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
5091450c749Smrg        ++event;
5106aab59a7Smrg    }
5116aab59a7Smrg    return;
5126aab59a7Smrg}
5136aab59a7Smrg
5146aab59a7Smrg
5156aab59a7Smrg/* This function is called when the protocol is "wsmouse". */
5166aab59a7Smrgstatic Bool
5176aab59a7SmrgwsconsPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
5186aab59a7Smrg{
5196aab59a7Smrg    MouseDevPtr pMse = pInfo->private;
5206aab59a7Smrg
5216aab59a7Smrg    /* Setup the local input proc. */
5226aab59a7Smrg    pInfo->read_input = wsconsReadInput;
5236aab59a7Smrg    pMse->xisbscale = sizeof(struct wscons_event);
5246aab59a7Smrg
525bd3a1963Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
5266aab59a7Smrg    pInfo->flags |= XI86_CONFIGURED;
527bd3a1963Smrg#endif
528216a823bSjmcneill
529216a823bSjmcneill    pMse->autoCalibrate = xf86SetBoolOption(pInfo->options, "AutoCalibrate", TRUE);
530216a823bSjmcneill    xf86Msg(X_CONFIG, "%s: auto calibration %sabled\n",
531216a823bSjmcneill            pInfo->name, pMse->autoCalibrate ? "en" : "dis");
532216a823bSjmcneill
533216a823bSjmcneill    pMse->screenNo = xf86SetIntOption(pInfo->options, "ScreenNo", 0);
534216a823bSjmcneill    if (pMse->screenNo >= screenInfo.numScreens ||
535216a823bSjmcneill        pMse->screenNo < 0) {
536216a823bSjmcneill            pMse->screenNo = 0;
537216a823bSjmcneill    }
538216a823bSjmcneill    xf86Msg(X_CONFIG, "%s: associated screen: %d\n",
539216a823bSjmcneill            pInfo->name, pMse->screenNo);
540216a823bSjmcneill
5416aab59a7Smrg    return TRUE;
5426aab59a7Smrg}
5436aab59a7Smrg#endif
5446aab59a7Smrg
5456aab59a7Smrg#if defined(USBMOUSE_SUPPORT)
5466aab59a7Smrg
5476aab59a7Smrgtypedef struct _UsbMseRec {
5486aab59a7Smrg    int packetSize;
5496aab59a7Smrg    int iid;
5501450c749Smrg    hid_item_t loc_x;           /* x locator item */
5511450c749Smrg    hid_item_t loc_y;           /* y locator item */
5521450c749Smrg    hid_item_t loc_z;           /* z (wheel) locator item */
5531450c749Smrg    hid_item_t loc_w;           /* z (wheel) locator item */
5546aab59a7Smrg    hid_item_t loc_btn[MSE_MAXBUTTONS]; /* buttons locator items */
5556aab59a7Smrg   unsigned char *buffer;
5566aab59a7Smrg} UsbMseRec, *UsbMsePtr;
5576aab59a7Smrg
5586aab59a7Smrgstatic int
5596aab59a7SmrgusbMouseProc(DeviceIntPtr pPointer, int what)
5606aab59a7Smrg{
5616aab59a7Smrg    InputInfoPtr pInfo;
5626aab59a7Smrg    MouseDevPtr pMse;
5636aab59a7Smrg    UsbMsePtr pUsbMse;
5646aab59a7Smrg    unsigned char map[MSE_MAXBUTTONS + 1];
5656aab59a7Smrg    int nbuttons;
5666aab59a7Smrg
5676aab59a7Smrg    pInfo = pPointer->public.devicePrivate;
5686aab59a7Smrg    pMse = pInfo->private;
5696aab59a7Smrg    pMse->device = pPointer;
5706aab59a7Smrg    pUsbMse = pMse->mousePriv;
5716aab59a7Smrg
5726aab59a7Smrg    switch (what) {
5731450c749Smrg    case DEVICE_INIT:
5741450c749Smrg        pPointer->public.on = FALSE;
5751450c749Smrg
5761450c749Smrg        for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons)
5771450c749Smrg            map[nbuttons + 1] = nbuttons + 1;
5781450c749Smrg
5791450c749Smrg        InitPointerDeviceStruct((DevicePtr)pPointer,
5801450c749Smrg                                map,
5811450c749Smrg                                min(pMse->buttons, MSE_MAXBUTTONS),
5821450c749Smrg                                miPointerGetMotionEvents,
5831450c749Smrg                                pMse->Ctrl,
5841450c749Smrg                                miPointerGetMotionBufferSize());
5851450c749Smrg
5861450c749Smrg        /* X valuator */
5871450c749Smrg        xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1);
5881450c749Smrg        xf86InitValuatorDefaults(pPointer, 0);
5891450c749Smrg        /* Y valuator */
5901450c749Smrg        xf86InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1);
5911450c749Smrg        xf86InitValuatorDefaults(pPointer, 1);
5921450c749Smrg        xf86MotionHistoryAllocate(pInfo);
5931450c749Smrg        break;
5946aab59a7Smrg
5956aab59a7Smrg    case DEVICE_ON:
5961450c749Smrg        pInfo->fd = xf86OpenSerial(pInfo->options);
5971450c749Smrg        if (pInfo->fd == -1)
5981450c749Smrg            xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
5991450c749Smrg        else {
6001450c749Smrg            pMse->buffer = XisbNew(pInfo->fd, pUsbMse->packetSize);
6011450c749Smrg            if (!pMse->buffer) {
6021450c749Smrg                free(pMse);
6031450c749Smrg                xf86CloseSerial(pInfo->fd);
6041450c749Smrg                pInfo->fd = -1;
6051450c749Smrg            } else {
6061450c749Smrg                xf86FlushInput(pInfo->fd);
6074d6d3f96Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 23
6081450c749Smrg                if (!xf86InstallSIGIOHandler (pInfo->fd, usbSigioReadInput,
6091450c749Smrg                                              pInfo))
6104d6d3f96Smrg#endif
6111450c749Smrg                    AddEnabledDevice(pInfo->fd);
6121450c749Smrg            }
6131450c749Smrg        }
6141450c749Smrg        pMse->lastButtons = 0;
6151450c749Smrg        pMse->lastMappedButtons = 0;
6161450c749Smrg        pMse->emulateState = 0;
6171450c749Smrg        pPointer->public.on = TRUE;
6181450c749Smrg        break;
6196aab59a7Smrg
6206aab59a7Smrg    case DEVICE_OFF:
6216aab59a7Smrg    case DEVICE_CLOSE:
6221450c749Smrg        if (pInfo->fd != -1) {
6231450c749Smrg            RemoveEnabledDevice(pInfo->fd);
6241450c749Smrg            if (pUsbMse->packetSize > 8 && pUsbMse->buffer) {
6251450c749Smrg                free(pUsbMse->buffer);
6261450c749Smrg            }
6271450c749Smrg            if (pMse->buffer) {
6281450c749Smrg                XisbFree(pMse->buffer);
6291450c749Smrg                pMse->buffer = NULL;
6301450c749Smrg            }
6311450c749Smrg            xf86CloseSerial(pInfo->fd);
6321450c749Smrg            pInfo->fd = -1;
6331450c749Smrg        }
6341450c749Smrg        pPointer->public.on = FALSE;
6351450c749Smrg        usleep(300000);
6361450c749Smrg        break;
6371450c749Smrg
6381450c749Smrg    default:
6391450c749Smrg        return BadValue;
6406aab59a7Smrg    }
6416aab59a7Smrg    return Success;
6426aab59a7Smrg}
6436aab59a7Smrg
6446aab59a7Smrgstatic void
6456aab59a7SmrgusbReadInput(InputInfoPtr pInfo)
6466aab59a7Smrg{
6476aab59a7Smrg    MouseDevPtr pMse;
6486aab59a7Smrg    UsbMsePtr pUsbMse;
6496aab59a7Smrg    int buttons = pMse->lastButtons;
6506aab59a7Smrg    int dx = 0, dy = 0, dz = 0, dw = 0;
6511450c749Smrg    int n, c;
6526aab59a7Smrg    unsigned char *pBuf;
6536aab59a7Smrg
6546aab59a7Smrg    pMse = pInfo->private;
6556aab59a7Smrg    pUsbMse = pMse->mousePriv;
6566aab59a7Smrg
6576aab59a7Smrg    XisbBlockDuration(pMse->buffer, -1);
6586aab59a7Smrg    pBuf = pUsbMse->buffer;
6596aab59a7Smrg    n = 0;
6606aab59a7Smrg    while ((c = XisbRead(pMse->buffer)) >= 0 && n < pUsbMse->packetSize) {
6611450c749Smrg        pBuf[n++] = (unsigned char)c;
6626aab59a7Smrg    }
6636aab59a7Smrg    if (n == 0)
6641450c749Smrg        return;
6656aab59a7Smrg    if (n != pUsbMse->packetSize) {
6661450c749Smrg        LogMessageVerbSigSafe(X_WARNING, -1,
6671450c749Smrg                              "%s: incomplete packet, size %d\n",
6681450c749Smrg                              pInfo->name, n);
6696aab59a7Smrg    }
6706aab59a7Smrg    /* discard packets with an id that don't match the mouse */
6716aab59a7Smrg    /* XXX this is probably not the right thing */
6726aab59a7Smrg    if (pUsbMse->iid != 0) {
6731450c749Smrg        if (*pBuf++ != pUsbMse->iid)
6741450c749Smrg            return;
6756aab59a7Smrg    }
6766aab59a7Smrg    dx = hid_get_data(pBuf, &pUsbMse->loc_x);
6776aab59a7Smrg    dy = hid_get_data(pBuf, &pUsbMse->loc_y);
6786aab59a7Smrg    dz = hid_get_data(pBuf, &pUsbMse->loc_z);
6796aab59a7Smrg    dw = hid_get_data(pBuf, &pUsbMse->loc_w);
6806aab59a7Smrg
6816aab59a7Smrg    buttons = 0;
6826aab59a7Smrg    for (n = 0; n < pMse->buttons; n++) {
6831450c749Smrg        if (hid_get_data(pBuf, &pUsbMse->loc_btn[n]))
6841450c749Smrg            buttons |= (1 << UMS_BUT(n));
6856aab59a7Smrg    }
6866aab59a7Smrg    pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
6876aab59a7Smrg    return;
6886aab59a7Smrg}
6896aab59a7Smrg
6906aab59a7Smrgstatic void
6916aab59a7SmrgusbSigioReadInput (int fd, void *closure)
6926aab59a7Smrg{
6936aab59a7Smrg    usbReadInput ((InputInfoPtr) closure);
6946aab59a7Smrg}
6956aab59a7Smrg
6966aab59a7Smrg/* This function is called when the protocol is "usb". */
6976aab59a7Smrgstatic Bool
6986aab59a7SmrgusbPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
6996aab59a7Smrg{
7006aab59a7Smrg    MouseDevPtr pMse = pInfo->private;
7016aab59a7Smrg    UsbMsePtr pUsbMse;
7026aab59a7Smrg    report_desc_t reportDesc;
7036aab59a7Smrg    int i;
7046aab59a7Smrg
705bd3a1963Smrg    pUsbMse = malloc(sizeof(UsbMseRec));
7066aab59a7Smrg    if (pUsbMse == NULL) {
7071450c749Smrg        xf86Msg(X_ERROR, "%s: cannot allocate UsbMouseRec\n", pInfo->name);
7081450c749Smrg        free(pMse);
7091450c749Smrg        return FALSE;
7106aab59a7Smrg    }
7116aab59a7Smrg
7126aab59a7Smrg    pMse->protocol = protocol;
7136aab59a7Smrg    xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
7146aab59a7Smrg
7156aab59a7Smrg    /* Collect the options, and process the common options. */
716bd3a1963Smrg    COLLECT_INPUT_OPTIONS(pInfo, NULL);
7176aab59a7Smrg    xf86ProcessCommonOptions(pInfo, pInfo->options);
7186aab59a7Smrg
7196aab59a7Smrg    /* Check if the device can be opened. */
7206aab59a7Smrg    pInfo->fd = xf86OpenSerial(pInfo->options);
7216aab59a7Smrg    if (pInfo->fd == -1) {
7221450c749Smrg        if (xf86GetAllowMouseOpenFail())
7231450c749Smrg            xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
7241450c749Smrg        else {
7251450c749Smrg            xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
7261450c749Smrg            free(pUsbMse);
7271450c749Smrg            free(pMse);
7281450c749Smrg            return FALSE;
7291450c749Smrg        }
7306aab59a7Smrg    }
7314d6d3f96Smrg    /* Get USB information */
7326aab59a7Smrg    reportDesc = hid_get_report_desc(pInfo->fd);
7336aab59a7Smrg    /* Get packet size & iid */
7346aab59a7Smrg#ifdef USB_NEW_HID
7356aab59a7Smrg    if (ioctl(pInfo->fd, USB_GET_REPORT_ID, &pUsbMse->iid) == -1) {
7361450c749Smrg            xf86Msg(X_ERROR, "Error ioctl USB_GET_REPORT_ID on %s : %s\n",
7371450c749Smrg                    pInfo->name, strerror(errno));
7381450c749Smrg            return FALSE;
7396aab59a7Smrg    }
7406aab59a7Smrg    pUsbMse->packetSize = hid_report_size(reportDesc, hid_input,
7411450c749Smrg                                              pUsbMse->iid);
7426aab59a7Smrg#else
7436aab59a7Smrg    pUsbMse->packetSize = hid_report_size(reportDesc, hid_input,
7441450c749Smrg                                              &pUsbMse->iid);
7456aab59a7Smrg#endif
7466aab59a7Smrg    /* Allocate buffer */
7476aab59a7Smrg    if (pUsbMse->packetSize <= 8) {
7481450c749Smrg        pUsbMse->buffer = pMse->protoBuf;
7496aab59a7Smrg    } else {
7501450c749Smrg        pUsbMse->buffer = malloc(pUsbMse->packetSize);
7516aab59a7Smrg    }
7526aab59a7Smrg    if (pUsbMse->buffer == NULL) {
7531450c749Smrg        xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name);
7541450c749Smrg        free(pUsbMse);
7551450c749Smrg        free(pMse);
7561450c749Smrg        xf86CloseSerial(pInfo->fd);
7571450c749Smrg        return FALSE;
7586aab59a7Smrg    }
7596aab59a7Smrg#ifdef USB_NEW_HID
7606aab59a7Smrg    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
7611450c749Smrg                   hid_input, &pUsbMse->loc_x, pUsbMse->iid) < 0) {
7621450c749Smrg        xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name);
7636aab59a7Smrg    }
7646aab59a7Smrg    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
7651450c749Smrg                   hid_input, &pUsbMse->loc_y, pUsbMse->iid) < 0) {
7661450c749Smrg        xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name);
7676aab59a7Smrg    }
7686aab59a7Smrg    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
7691450c749Smrg                   hid_input, &pUsbMse->loc_z, pUsbMse->iid) < 0) {
7706aab59a7Smrg    }
7716aab59a7Smrg#else
7726aab59a7Smrg    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
7731450c749Smrg                   hid_input, &pUsbMse->loc_x) < 0) {
7741450c749Smrg        xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name);
7756aab59a7Smrg    }
7766aab59a7Smrg    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
7771450c749Smrg                   hid_input, &pUsbMse->loc_y) < 0) {
7781450c749Smrg        xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name);
7796aab59a7Smrg    }
7806aab59a7Smrg    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
7811450c749Smrg                   hid_input, &pUsbMse->loc_z) < 0) {
7826aab59a7Smrg    }
7836aab59a7Smrg#endif
7846aab59a7Smrg    /* Probe for number of buttons */
7856aab59a7Smrg    for (i = 1; i <= MSE_MAXBUTTONS; i++) {
7861450c749Smrg        if (!hid_locate(reportDesc, HID_USAGE2(HUP_BUTTON, i),
7871450c749Smrg                        hid_input, &pUsbMse->loc_btn[i-1]
7886aab59a7Smrg#ifdef USB_NEW_HID
7891450c749Smrg                        , pUsbMse->iid
7906aab59a7Smrg#endif
7911450c749Smrg                        ))
7921450c749Smrg            break;
7936aab59a7Smrg    }
7946aab59a7Smrg    pMse->buttons = i-1;
7956aab59a7Smrg
7966aab59a7Smrg    xf86CloseSerial(pInfo->fd);
7976aab59a7Smrg    pInfo->fd = -1;
7986aab59a7Smrg
7996aab59a7Smrg    /* Private structure */
8006aab59a7Smrg    pMse->mousePriv = pUsbMse;
8016aab59a7Smrg
8026aab59a7Smrg    /* Process common mouse options (like Emulate3Buttons, etc). */
8036aab59a7Smrg    pMse->CommonOptions(pInfo);
8046aab59a7Smrg
8056aab59a7Smrg    /* Setup the local procs. */
8066aab59a7Smrg    pInfo->device_control = usbMouseProc;
8076aab59a7Smrg    pInfo->read_input = usbReadInput;
8086aab59a7Smrg
809bd3a1963Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
8106aab59a7Smrg    pInfo->flags |= XI86_CONFIGURED;
811bd3a1963Smrg#endif
8126aab59a7Smrg    return TRUE;
8136aab59a7Smrg}
8146aab59a7Smrg#endif /* USBMOUSE */
8156aab59a7Smrg
8166aab59a7Smrgstatic Bool
8176aab59a7SmrgbsdMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags)
8186aab59a7Smrg{
8196aab59a7Smrg    /* The protocol is guaranteed to be one of the internalNames[] */
8206aab59a7Smrg#ifdef WSCONS_SUPPORT
8216aab59a7Smrg    if (xf86NameCmp(protocol, "WSMouse") == 0) {
8221450c749Smrg        return wsconsPreInit(pInfo, protocol, flags);
8236aab59a7Smrg    }
8246aab59a7Smrg#endif
8256aab59a7Smrg#ifdef USBMOUSE_SUPPORT
8266aab59a7Smrg    if (xf86NameCmp(protocol, "usb") == 0) {
8271450c749Smrg        return usbPreInit(pInfo, protocol, flags);
8286aab59a7Smrg    }
8296aab59a7Smrg#endif
8306aab59a7Smrg    return TRUE;
8311450c749Smrg}
8326aab59a7Smrg
833bd3a1963SmrgOSMouseInfoPtr
834bd3a1963SmrgOSMouseInit(int flags)
8356aab59a7Smrg{
8366aab59a7Smrg    OSMouseInfoPtr p;
8376aab59a7Smrg
838bd3a1963Smrg    p = calloc(sizeof(OSMouseInfoRec), 1);
8396aab59a7Smrg    if (!p)
8401450c749Smrg        return NULL;
8416aab59a7Smrg    p->SupportedInterfaces = SupportedInterfaces;
8426aab59a7Smrg    p->BuiltinNames = BuiltinNames;
8436aab59a7Smrg    p->DefaultProtocol = DefaultProtocol;
8446aab59a7Smrg    p->CheckProtocol = CheckProtocol;
8456aab59a7Smrg#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE)
8466aab59a7Smrg    p->SetupAuto = SetupAuto;
8476aab59a7Smrg    p->SetPS2Res = SetSysMouseRes;
8486aab59a7Smrg    p->SetBMRes = SetSysMouseRes;
8496aab59a7Smrg    p->SetMiscRes = SetSysMouseRes;
8506aab59a7Smrg#endif
8516aab59a7Smrg#if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
8526aab59a7Smrg    p->SetupAuto = SetupAuto;
8536aab59a7Smrg    p->SetMiscRes = SetMouseRes;
8546aab59a7Smrg#endif
8556aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
8566aab59a7Smrg    p->FindDevice = FindDevice;
8576aab59a7Smrg#endif
8586aab59a7Smrg    p->PreInit = bsdMousePreInit;
8596aab59a7Smrg    return p;
8606aab59a7Smrg}
861