bsd_mouse.c revision f3d19aa6
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 646aab59a7Smrg/* The UMS mices 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 */ 756aab59a7Smrg#define DEFAULT_MOUSE_DEV "/dev/mouse" 766aab59a7Smrg#define DEFAULT_SYSMOUSE_DEV "/dev/sysmouse" 776aab59a7Smrg#define DEFAULT_PS2_DEV "/dev/psm0" 786aab59a7Smrg 796aab59a7Smrgstatic const char *mouseDevs[] = { 806aab59a7Smrg DEFAULT_MOUSE_DEV, 816aab59a7Smrg DEFAULT_SYSMOUSE_DEV, 826aab59a7Smrg DEFAULT_PS2_DEV, 836aab59a7Smrg NULL 846aab59a7Smrg}; 856aab59a7Smrg#elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT) 866aab59a7Smrg/* Only wsmouse mices are autoconfigured for now on OpenBSD */ 876aab59a7Smrg#define DEFAULT_WSMOUSE_DEV "/dev/wsmouse" 886aab59a7Smrg#define DEFAULT_WSMOUSE0_DEV "/dev/wsmouse0" 896aab59a7Smrg 906aab59a7Smrgstatic const char *mouseDevs[] = { 916aab59a7Smrg DEFAULT_WSMOUSE_DEV, 926aab59a7Smrg DEFAULT_WSMOUSE0_DEV, 936aab59a7Smrg NULL 946aab59a7Smrg}; 956aab59a7Smrg#endif 966aab59a7Smrg 976aab59a7Smrgstatic int 986aab59a7SmrgSupportedInterfaces(void) 996aab59a7Smrg{ 1006aab59a7Smrg#if defined(__NetBSD__) 10141ed76f1Smrg return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC; 1026aab59a7Smrg#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 1036aab59a7Smrg return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC; 1046aab59a7Smrg#else 105bd3a1963Smrg return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO | MSE_MISC; 1066aab59a7Smrg#endif 1076aab59a7Smrg} 1086aab59a7Smrg 1096aab59a7Smrg/* Names of protocols that are handled internally here. */ 1106aab59a7Smrgstatic const char *internalNames[] = { 1116aab59a7Smrg#if defined(WSCONS_SUPPORT) 1126aab59a7Smrg "WSMouse", 1136aab59a7Smrg#endif 1146aab59a7Smrg#if defined(USBMOUSE_SUPPORT) 1156aab59a7Smrg "usb", 1166aab59a7Smrg#endif 1176aab59a7Smrg NULL 1186aab59a7Smrg}; 1196aab59a7Smrg 1206aab59a7Smrg/* 1216aab59a7Smrg * Names of MSC_MISC protocols that the OS supports. These are decoded by 1226aab59a7Smrg * main "mouse" driver. 1236aab59a7Smrg */ 1246aab59a7Smrgstatic const char *miscNames[] = { 1256aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 1266aab59a7Smrg "SysMouse", 1276aab59a7Smrg#endif 1286aab59a7Smrg NULL 1296aab59a7Smrg}; 1306aab59a7Smrg 1316aab59a7Smrgstatic const char ** 1326aab59a7SmrgBuiltinNames(void) 1336aab59a7Smrg{ 1346aab59a7Smrg return internalNames; 1356aab59a7Smrg} 1366aab59a7Smrg 1376aab59a7Smrgstatic Bool 1386aab59a7SmrgCheckProtocol(const char *protocol) 1396aab59a7Smrg{ 1406aab59a7Smrg int i; 1416aab59a7Smrg 1426aab59a7Smrg for (i = 0; internalNames[i]; i++) 1436aab59a7Smrg if (xf86NameCmp(protocol, internalNames[i]) == 0) 1446aab59a7Smrg return TRUE; 1456aab59a7Smrg for (i = 0; miscNames[i]; i++) 1466aab59a7Smrg if (xf86NameCmp(protocol, miscNames[i]) == 0) 1476aab59a7Smrg return TRUE; 1486aab59a7Smrg return FALSE; 1496aab59a7Smrg} 1506aab59a7Smrg 1516aab59a7Smrgstatic const char * 1526aab59a7SmrgDefaultProtocol(void) 1536aab59a7Smrg{ 1546aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 1556aab59a7Smrg return "Auto"; 1566aab59a7Smrg#elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT) 1576aab59a7Smrg return "WSMouse"; 1586aab59a7Smrg#else 1596aab59a7Smrg return NULL; 1606aab59a7Smrg#endif 1616aab59a7Smrg} 1626aab59a7Smrg 1636aab59a7Smrg#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE) 1646aab59a7Smrgstatic struct { 1656aab59a7Smrg int dproto; 1666aab59a7Smrg const char *name; 1676aab59a7Smrg} devproto[] = { 1686aab59a7Smrg { MOUSE_PROTO_MS, "Microsoft" }, 1696aab59a7Smrg { MOUSE_PROTO_MSC, "MouseSystems" }, 1706aab59a7Smrg { MOUSE_PROTO_LOGI, "Logitech" }, 1716aab59a7Smrg { MOUSE_PROTO_MM, "MMSeries" }, 1726aab59a7Smrg { MOUSE_PROTO_LOGIMOUSEMAN, "MouseMan" }, 1736aab59a7Smrg { MOUSE_PROTO_BUS, "BusMouse" }, 1746aab59a7Smrg { MOUSE_PROTO_INPORT, "BusMouse" }, 1756aab59a7Smrg { MOUSE_PROTO_PS2, "PS/2" }, 1766aab59a7Smrg { MOUSE_PROTO_HITTAB, "MMHitTab" }, 1776aab59a7Smrg { MOUSE_PROTO_GLIDEPOINT, "GlidePoint" }, 1786aab59a7Smrg { MOUSE_PROTO_INTELLI, "Intellimouse" }, 1796aab59a7Smrg { MOUSE_PROTO_THINK, "ThinkingMouse" }, 1806aab59a7Smrg { MOUSE_PROTO_SYSMOUSE, "SysMouse" } 1816aab59a7Smrg}; 1826aab59a7Smrg 1836aab59a7Smrgstatic const char * 1846aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara) 1856aab59a7Smrg{ 1866aab59a7Smrg int i; 1876aab59a7Smrg mousehw_t hw; 1886aab59a7Smrg mousemode_t mode; 1896aab59a7Smrg 1906aab59a7Smrg if (pInfo->fd == -1) 1916aab59a7Smrg return NULL; 1926aab59a7Smrg 1936aab59a7Smrg /* set the driver operation level, if applicable */ 1946aab59a7Smrg i = 1; 1956aab59a7Smrg ioctl(pInfo->fd, MOUSE_SETLEVEL, &i); 1966aab59a7Smrg 1976aab59a7Smrg /* interrogate the driver and get some intelligence on the device. */ 1986aab59a7Smrg hw.iftype = MOUSE_IF_UNKNOWN; 1996aab59a7Smrg hw.model = MOUSE_MODEL_GENERIC; 2006aab59a7Smrg ioctl(pInfo->fd, MOUSE_GETHWINFO, &hw); 2016aab59a7Smrg xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: hw.iftype is %d, hw.model is %d\n", 2026aab59a7Smrg pInfo->name, hw.iftype, hw.model); 2036aab59a7Smrg if (ioctl(pInfo->fd, MOUSE_GETMODE, &mode) == 0) { 2046aab59a7Smrg for (i = 0; i < sizeof(devproto)/sizeof(devproto[0]); ++i) { 2056aab59a7Smrg if (mode.protocol == devproto[i].dproto) { 2066aab59a7Smrg /* override some parameters */ 2076aab59a7Smrg if (protoPara) { 2086aab59a7Smrg protoPara[4] = mode.packetsize; 2096aab59a7Smrg protoPara[0] = mode.syncmask[0]; 2106aab59a7Smrg protoPara[1] = mode.syncmask[1]; 2116aab59a7Smrg } 2126aab59a7Smrg xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n", 2136aab59a7Smrg pInfo->name, devproto[i].name); 2146aab59a7Smrg return devproto[i].name; 2156aab59a7Smrg } 2166aab59a7Smrg } 2176aab59a7Smrg } 2186aab59a7Smrg return NULL; 2196aab59a7Smrg} 2206aab59a7Smrg 2216aab59a7Smrgstatic void 2226aab59a7SmrgSetSysMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res) 2236aab59a7Smrg{ 2246aab59a7Smrg mousemode_t mode; 2256aab59a7Smrg MouseDevPtr pMse; 2266aab59a7Smrg 2276aab59a7Smrg pMse = pInfo->private; 2286aab59a7Smrg 2296aab59a7Smrg mode.rate = rate > 0 ? rate : -1; 2306aab59a7Smrg mode.resolution = res > 0 ? res : -1; 2316aab59a7Smrg mode.accelfactor = -1; 2326aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 2336aab59a7Smrg if (pMse->autoProbe || 2346aab59a7Smrg (protocol && xf86NameCmp(protocol, "SysMouse") == 0)) { 2356aab59a7Smrg /* 2366aab59a7Smrg * As the FreeBSD sysmouse driver defaults to protocol level 0 2376aab59a7Smrg * everytime it is opened we enforce protocol level 1 again at 2386aab59a7Smrg * this point. 2396aab59a7Smrg */ 2406aab59a7Smrg mode.level = 1; 2416aab59a7Smrg } else 2426aab59a7Smrg mode.level = -1; 2436aab59a7Smrg#else 2446aab59a7Smrg mode.level = -1; 2456aab59a7Smrg#endif 2466aab59a7Smrg ioctl(pInfo->fd, MOUSE_SETMODE, &mode); 2476aab59a7Smrg} 2486aab59a7Smrg#endif 2496aab59a7Smrg 2506aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 2516aab59a7Smrg 2526aab59a7Smrg#define MOUSED_PID_FILE "/var/run/moused.pid" 2536aab59a7Smrg 2546aab59a7Smrg/* 2556aab59a7Smrg * Try to check if moused is running. DEFAULT_SYSMOUSE_DEV is useless without 2566aab59a7Smrg * it. There doesn't seem to be a better way of checking. 2576aab59a7Smrg */ 2586aab59a7Smrgstatic Bool 2596aab59a7SmrgMousedRunning(void) 2606aab59a7Smrg{ 2616aab59a7Smrg FILE *f = NULL; 2626aab59a7Smrg unsigned int pid; 2636aab59a7Smrg 2646aab59a7Smrg if ((f = fopen(MOUSED_PID_FILE, "r")) != NULL) { 2656aab59a7Smrg if (fscanf(f, "%u", &pid) == 1 && pid > 0) { 2666aab59a7Smrg if (kill(pid, 0) == 0) { 2676aab59a7Smrg fclose(f); 2686aab59a7Smrg return TRUE; 2696aab59a7Smrg } 2706aab59a7Smrg } 2716aab59a7Smrg fclose(f); 2726aab59a7Smrg } 2736aab59a7Smrg return FALSE; 2746aab59a7Smrg} 2756aab59a7Smrg 2766aab59a7Smrgstatic const char * 2776aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 2786aab59a7Smrg{ 2796aab59a7Smrg int fd = -1; 2806aab59a7Smrg const char **pdev, *dev = NULL; 2816aab59a7Smrg Bool devMouse = FALSE; 2826aab59a7Smrg struct stat devMouseStat; 2836aab59a7Smrg struct stat sb; 2846aab59a7Smrg 2856aab59a7Smrg for (pdev = mouseDevs; *pdev; pdev++) { 2866aab59a7Smrg SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK)); 2876aab59a7Smrg if (fd == -1) { 2886aab59a7Smrg#ifdef DEBUG 2896aab59a7Smrg ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno)); 2906aab59a7Smrg#endif 2916aab59a7Smrg } else { 2926aab59a7Smrg /* 2936aab59a7Smrg * /dev/mouse is held until checks for matches with other devices 2946aab59a7Smrg * are done. This is so that when it points to /dev/sysmouse, 2956aab59a7Smrg * the test for whether /dev/sysmouse is usable can be made. 2966aab59a7Smrg */ 2976aab59a7Smrg if (!strcmp(*pdev, DEFAULT_MOUSE_DEV)) { 2986aab59a7Smrg if (fstat(fd, &devMouseStat) == 0) 2996aab59a7Smrg devMouse = TRUE; 3006aab59a7Smrg close(fd); 3016aab59a7Smrg continue; 3026aab59a7Smrg } else if (!strcmp(*pdev, DEFAULT_SYSMOUSE_DEV)) { 3036aab59a7Smrg /* Check if /dev/mouse is the same as /dev/sysmouse. */ 3046aab59a7Smrg if (devMouse && fstat(fd, &sb) == 0 && 3056aab59a7Smrg devMouseStat.st_dev == sb.st_dev && 3066aab59a7Smrg devMouseStat.st_ino == sb.st_ino) { 3076aab59a7Smrg /* If the same, use /dev/sysmouse. */ 3086aab59a7Smrg devMouse = FALSE; 3096aab59a7Smrg } 3106aab59a7Smrg close(fd); 3116aab59a7Smrg if (MousedRunning()) 3126aab59a7Smrg break; 3136aab59a7Smrg else { 3146aab59a7Smrg#ifdef DEBUG 3156aab59a7Smrg ErrorF("moused isn't running\n"); 3166aab59a7Smrg#endif 3176aab59a7Smrg } 3186aab59a7Smrg } else { 3196aab59a7Smrg close(fd); 3206aab59a7Smrg break; 3216aab59a7Smrg } 3226aab59a7Smrg } 3236aab59a7Smrg } 3246aab59a7Smrg 3256aab59a7Smrg if (*pdev) 3266aab59a7Smrg dev = *pdev; 3276aab59a7Smrg else if (devMouse) 3286aab59a7Smrg dev = DEFAULT_MOUSE_DEV; 3296aab59a7Smrg 3306aab59a7Smrg if (dev) { 3316aab59a7Smrg /* Set the Device option. */ 332bd3a1963Smrg pInfo->options = 333bd3a1963Smrg xf86AddNewOption(pInfo->options, "Device", dev); 3346aab59a7Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 3356aab59a7Smrg pInfo->name, dev); 3366aab59a7Smrg } 3376aab59a7Smrg 3386aab59a7Smrg return *pdev; 3396aab59a7Smrg} 3406aab59a7Smrg#endif 3416aab59a7Smrg 3426aab59a7Smrg#if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT) 3436aab59a7Smrg 3446aab59a7Smrg/* Only support wsmouse configuration for now */ 3456aab59a7Smrgstatic const char * 3466aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara) 3476aab59a7Smrg{ 3486aab59a7Smrg 3496aab59a7Smrg xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n", 3506aab59a7Smrg pInfo->name, "wsmouse"); 3516aab59a7Smrg return "wsmouse"; 3526aab59a7Smrg} 3536aab59a7Smrg 3546aab59a7Smrgstatic void 3556aab59a7SmrgSetMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res) 3566aab59a7Smrg{ 3576aab59a7Smrg 3586aab59a7Smrg xf86MsgVerb(X_INFO, 3, "%s: SetMouseRes: protocol %s rate %d res %d\n", 3596aab59a7Smrg pInfo->name, protocol, rate, res); 3606aab59a7Smrg} 3616aab59a7Smrg 3626aab59a7Smrgstatic const char * 3636aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 3646aab59a7Smrg{ 3656aab59a7Smrg int fd = -1; 3666aab59a7Smrg const char **pdev; 3676aab59a7Smrg 3686aab59a7Smrg for (pdev = mouseDevs; *pdev; pdev++) { 3696aab59a7Smrg SYSCALL(fd = open(*pdev, O_RDWR | O_NONBLOCK)); 3706aab59a7Smrg if (fd != -1) { 3716aab59a7Smrg /* Set the Device option. */ 372bd3a1963Smrg pInfo->options = 373bd3a1963Smrg xf86AddNewOption(pInfo->options, 3746aab59a7Smrg "Device", *pdev); 3756aab59a7Smrg xf86Msg(X_INFO, "%s: found Device \"%s\"\n", 3766aab59a7Smrg pInfo->name, *pdev); 3776aab59a7Smrg close(fd); 3786aab59a7Smrg break; 3796aab59a7Smrg } 3806aab59a7Smrg } 3816aab59a7Smrg return *pdev; 3826aab59a7Smrg} 3836aab59a7Smrg#endif /* __OpenBSD__ || __NetBSD__ && WSCONS_SUPPORT */ 3846aab59a7Smrg 3856aab59a7Smrg#ifdef WSCONS_SUPPORT 3866aab59a7Smrg#define NUMEVENTS 64 3876aab59a7Smrg 3886aab59a7Smrgstatic void 3896aab59a7SmrgwsconsReadInput(InputInfoPtr pInfo) 3906aab59a7Smrg{ 3916aab59a7Smrg MouseDevPtr pMse; 3926aab59a7Smrg static struct wscons_event eventList[NUMEVENTS]; 3936aab59a7Smrg int n, c; 3946aab59a7Smrg struct wscons_event *event = eventList; 3956aab59a7Smrg unsigned char *pBuf; 3966aab59a7Smrg 3976aab59a7Smrg pMse = pInfo->private; 3986aab59a7Smrg 3996aab59a7Smrg XisbBlockDuration(pMse->buffer, -1); 4006aab59a7Smrg pBuf = (unsigned char *)eventList; 4016aab59a7Smrg n = 0; 4026aab59a7Smrg while (n < sizeof(eventList) && (c = XisbRead(pMse->buffer)) >= 0) { 4036aab59a7Smrg pBuf[n++] = (unsigned char)c; 4046aab59a7Smrg } 4056aab59a7Smrg 4066aab59a7Smrg if (n == 0) 4076aab59a7Smrg return; 4086aab59a7Smrg 4096aab59a7Smrg n /= sizeof(struct wscons_event); 4106aab59a7Smrg while( n-- ) { 4116aab59a7Smrg int buttons = pMse->lastButtons; 412f3d19aa6Schristos int dx = 0, dy = 0, dz = 0, dw = 0, x, y; 4136aab59a7Smrg switch (event->type) { 4146aab59a7Smrg case WSCONS_EVENT_MOUSE_UP: 4156aab59a7Smrg#define BUTBIT (1 << (event->value <= 2 ? 2 - event->value : event->value)) 4166aab59a7Smrg buttons &= ~BUTBIT; 4176aab59a7Smrg break; 4186aab59a7Smrg case WSCONS_EVENT_MOUSE_DOWN: 4196aab59a7Smrg buttons |= BUTBIT; 4206aab59a7Smrg break; 4216aab59a7Smrg case WSCONS_EVENT_MOUSE_DELTA_X: 4226aab59a7Smrg dx = event->value; 4236aab59a7Smrg break; 4246aab59a7Smrg case WSCONS_EVENT_MOUSE_DELTA_Y: 4256aab59a7Smrg dy = -event->value; 4266aab59a7Smrg break; 4276aab59a7Smrg#ifdef WSCONS_EVENT_MOUSE_DELTA_Z 4286aab59a7Smrg case WSCONS_EVENT_MOUSE_DELTA_Z: 4296aab59a7Smrg dz = event->value; 4306aab59a7Smrg break; 4316aab59a7Smrg#endif 4326aab59a7Smrg#ifdef WSCONS_EVENT_MOUSE_DELTA_W 4336aab59a7Smrg case WSCONS_EVENT_MOUSE_DELTA_W: 4346aab59a7Smrg dw = event->value; 4356aab59a7Smrg break; 436f3d19aa6Schristos#endif 437f3d19aa6Schristos case WSCONS_EVENT_MOUSE_ABSOLUTE_X: 438f3d19aa6Schristos miPointerGetPosition (pInfo->dev, &x, &y); 439f3d19aa6Schristos x = event->value; 440f3d19aa6Schristos miPointerSetPosition (pInfo->dev, &x, &y); 441f3d19aa6Schristos xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, x, y); 442f3d19aa6Schristos ++event; 443f3d19aa6Schristos continue; 444f3d19aa6Schristos case WSCONS_EVENT_MOUSE_ABSOLUTE_Y: 445f3d19aa6Schristos miPointerGetPosition (pInfo->dev, &x, &y); 446f3d19aa6Schristos y = event->value; 447f3d19aa6Schristos miPointerSetPosition (pInfo->dev, &x, &y); 448f3d19aa6Schristos xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, x, y); 449f3d19aa6Schristos ++event; 450f3d19aa6Schristos continue; 451f3d19aa6Schristos#ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_Z 452f3d19aa6Schristos case WSCONS_EVENT_MOUSE_ABSOLUTE_Z: 453f3d19aa6Schristos ++event; 454f3d19aa6Schristos continue; 455f3d19aa6Schristos#endif 456f3d19aa6Schristos#ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_W 457f3d19aa6Schristos case WSCONS_EVENT_MOUSE_ABSOLUTE_W: 458f3d19aa6Schristos ++event; 459f3d19aa6Schristos continue; 4606aab59a7Smrg#endif 4616aab59a7Smrg default: 4626aab59a7Smrg xf86Msg(X_WARNING, "%s: bad wsmouse event type=%d\n", pInfo->name, 4636aab59a7Smrg event->type); 4646aab59a7Smrg ++event; 4656aab59a7Smrg continue; 4666aab59a7Smrg } 4676aab59a7Smrg 4686aab59a7Smrg pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 4696aab59a7Smrg ++event; 4706aab59a7Smrg } 4716aab59a7Smrg return; 4726aab59a7Smrg} 4736aab59a7Smrg 4746aab59a7Smrg 4756aab59a7Smrg/* This function is called when the protocol is "wsmouse". */ 4766aab59a7Smrgstatic Bool 4776aab59a7SmrgwsconsPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 4786aab59a7Smrg{ 4796aab59a7Smrg MouseDevPtr pMse = pInfo->private; 4806aab59a7Smrg 4816aab59a7Smrg /* Setup the local input proc. */ 4826aab59a7Smrg pInfo->read_input = wsconsReadInput; 4836aab59a7Smrg pMse->xisbscale = sizeof(struct wscons_event); 4846aab59a7Smrg 485bd3a1963Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 4866aab59a7Smrg pInfo->flags |= XI86_CONFIGURED; 487bd3a1963Smrg#endif 4886aab59a7Smrg return TRUE; 4896aab59a7Smrg} 4906aab59a7Smrg#endif 4916aab59a7Smrg 4926aab59a7Smrg#if defined(USBMOUSE_SUPPORT) 4936aab59a7Smrg 4946aab59a7Smrgtypedef struct _UsbMseRec { 4956aab59a7Smrg int packetSize; 4966aab59a7Smrg int iid; 4976aab59a7Smrg hid_item_t loc_x; /* x locator item */ 4986aab59a7Smrg hid_item_t loc_y; /* y locator item */ 4996aab59a7Smrg hid_item_t loc_z; /* z (wheel) locator item */ 5006aab59a7Smrg hid_item_t loc_w; /* z (wheel) locator item */ 5016aab59a7Smrg hid_item_t loc_btn[MSE_MAXBUTTONS]; /* buttons locator items */ 5026aab59a7Smrg unsigned char *buffer; 5036aab59a7Smrg} UsbMseRec, *UsbMsePtr; 5046aab59a7Smrg 5056aab59a7Smrgstatic int 5066aab59a7SmrgusbMouseProc(DeviceIntPtr pPointer, int what) 5076aab59a7Smrg{ 5086aab59a7Smrg InputInfoPtr pInfo; 5096aab59a7Smrg MouseDevPtr pMse; 5106aab59a7Smrg UsbMsePtr pUsbMse; 5116aab59a7Smrg unsigned char map[MSE_MAXBUTTONS + 1]; 5126aab59a7Smrg int nbuttons; 5136aab59a7Smrg 5146aab59a7Smrg pInfo = pPointer->public.devicePrivate; 5156aab59a7Smrg pMse = pInfo->private; 5166aab59a7Smrg pMse->device = pPointer; 5176aab59a7Smrg pUsbMse = pMse->mousePriv; 5186aab59a7Smrg 5196aab59a7Smrg switch (what) { 5206aab59a7Smrg case DEVICE_INIT: 5216aab59a7Smrg pPointer->public.on = FALSE; 5226aab59a7Smrg 5236aab59a7Smrg for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons) 5246aab59a7Smrg map[nbuttons + 1] = nbuttons + 1; 5256aab59a7Smrg 5266aab59a7Smrg InitPointerDeviceStruct((DevicePtr)pPointer, 5276aab59a7Smrg map, 5286aab59a7Smrg min(pMse->buttons, MSE_MAXBUTTONS), 5296aab59a7Smrg miPointerGetMotionEvents, 5306aab59a7Smrg pMse->Ctrl, 5316aab59a7Smrg miPointerGetMotionBufferSize()); 5326aab59a7Smrg 5336aab59a7Smrg /* X valuator */ 5346aab59a7Smrg xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1); 5356aab59a7Smrg xf86InitValuatorDefaults(pPointer, 0); 5366aab59a7Smrg /* Y valuator */ 5376aab59a7Smrg xf86InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1); 5386aab59a7Smrg xf86InitValuatorDefaults(pPointer, 1); 5396aab59a7Smrg xf86MotionHistoryAllocate(pInfo); 5406aab59a7Smrg break; 5416aab59a7Smrg 5426aab59a7Smrg case DEVICE_ON: 5436aab59a7Smrg pInfo->fd = xf86OpenSerial(pInfo->options); 5446aab59a7Smrg if (pInfo->fd == -1) 5456aab59a7Smrg xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 5466aab59a7Smrg else { 5476aab59a7Smrg pMse->buffer = XisbNew(pInfo->fd, pUsbMse->packetSize); 5486aab59a7Smrg if (!pMse->buffer) { 549bd3a1963Smrg free(pMse); 5506aab59a7Smrg xf86CloseSerial(pInfo->fd); 5516aab59a7Smrg pInfo->fd = -1; 5526aab59a7Smrg } else { 5536aab59a7Smrg xf86FlushInput(pInfo->fd); 5546aab59a7Smrg if (!xf86InstallSIGIOHandler (pInfo->fd, usbSigioReadInput, 5556aab59a7Smrg pInfo)) 5566aab59a7Smrg AddEnabledDevice(pInfo->fd); 5576aab59a7Smrg } 5586aab59a7Smrg } 5596aab59a7Smrg pMse->lastButtons = 0; 5606aab59a7Smrg pMse->lastMappedButtons = 0; 5616aab59a7Smrg pMse->emulateState = 0; 5626aab59a7Smrg pPointer->public.on = TRUE; 5636aab59a7Smrg break; 5646aab59a7Smrg 5656aab59a7Smrg case DEVICE_OFF: 5666aab59a7Smrg case DEVICE_CLOSE: 5676aab59a7Smrg if (pInfo->fd != -1) { 5686aab59a7Smrg RemoveEnabledDevice(pInfo->fd); 5696aab59a7Smrg if (pUsbMse->packetSize > 8 && pUsbMse->buffer) { 570bd3a1963Smrg free(pUsbMse->buffer); 5716aab59a7Smrg } 5726aab59a7Smrg if (pMse->buffer) { 5736aab59a7Smrg XisbFree(pMse->buffer); 5746aab59a7Smrg pMse->buffer = NULL; 5756aab59a7Smrg } 5766aab59a7Smrg xf86CloseSerial(pInfo->fd); 5776aab59a7Smrg pInfo->fd = -1; 5786aab59a7Smrg } 5796aab59a7Smrg pPointer->public.on = FALSE; 5806aab59a7Smrg usleep(300000); 5816aab59a7Smrg break; 5826aab59a7Smrg } 5836aab59a7Smrg return Success; 5846aab59a7Smrg} 5856aab59a7Smrg 5866aab59a7Smrgstatic void 5876aab59a7SmrgusbReadInput(InputInfoPtr pInfo) 5886aab59a7Smrg{ 5896aab59a7Smrg MouseDevPtr pMse; 5906aab59a7Smrg UsbMsePtr pUsbMse; 5916aab59a7Smrg int buttons = pMse->lastButtons; 5926aab59a7Smrg int dx = 0, dy = 0, dz = 0, dw = 0; 5936aab59a7Smrg int n, c; 5946aab59a7Smrg unsigned char *pBuf; 5956aab59a7Smrg 5966aab59a7Smrg pMse = pInfo->private; 5976aab59a7Smrg pUsbMse = pMse->mousePriv; 5986aab59a7Smrg 5996aab59a7Smrg XisbBlockDuration(pMse->buffer, -1); 6006aab59a7Smrg pBuf = pUsbMse->buffer; 6016aab59a7Smrg n = 0; 6026aab59a7Smrg while ((c = XisbRead(pMse->buffer)) >= 0 && n < pUsbMse->packetSize) { 6036aab59a7Smrg pBuf[n++] = (unsigned char)c; 6046aab59a7Smrg } 6056aab59a7Smrg if (n == 0) 6066aab59a7Smrg return; 6076aab59a7Smrg if (n != pUsbMse->packetSize) { 6086aab59a7Smrg xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", pInfo->name, 6096aab59a7Smrg n); 6106aab59a7Smrg } 6116aab59a7Smrg /* discard packets with an id that don't match the mouse */ 6126aab59a7Smrg /* XXX this is probably not the right thing */ 6136aab59a7Smrg if (pUsbMse->iid != 0) { 6146aab59a7Smrg if (*pBuf++ != pUsbMse->iid) 6156aab59a7Smrg return; 6166aab59a7Smrg } 6176aab59a7Smrg dx = hid_get_data(pBuf, &pUsbMse->loc_x); 6186aab59a7Smrg dy = hid_get_data(pBuf, &pUsbMse->loc_y); 6196aab59a7Smrg dz = hid_get_data(pBuf, &pUsbMse->loc_z); 6206aab59a7Smrg dw = hid_get_data(pBuf, &pUsbMse->loc_w); 6216aab59a7Smrg 6226aab59a7Smrg buttons = 0; 6236aab59a7Smrg for (n = 0; n < pMse->buttons; n++) { 6246aab59a7Smrg if (hid_get_data(pBuf, &pUsbMse->loc_btn[n])) 6256aab59a7Smrg buttons |= (1 << UMS_BUT(n)); 6266aab59a7Smrg } 6276aab59a7Smrg pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 6286aab59a7Smrg return; 6296aab59a7Smrg} 6306aab59a7Smrg 6316aab59a7Smrgstatic void 6326aab59a7SmrgusbSigioReadInput (int fd, void *closure) 6336aab59a7Smrg{ 6346aab59a7Smrg usbReadInput ((InputInfoPtr) closure); 6356aab59a7Smrg} 6366aab59a7Smrg 6376aab59a7Smrg/* This function is called when the protocol is "usb". */ 6386aab59a7Smrgstatic Bool 6396aab59a7SmrgusbPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 6406aab59a7Smrg{ 6416aab59a7Smrg MouseDevPtr pMse = pInfo->private; 6426aab59a7Smrg UsbMsePtr pUsbMse; 6436aab59a7Smrg report_desc_t reportDesc; 6446aab59a7Smrg int i; 6456aab59a7Smrg 646bd3a1963Smrg pUsbMse = malloc(sizeof(UsbMseRec)); 6476aab59a7Smrg if (pUsbMse == NULL) { 6486aab59a7Smrg xf86Msg(X_ERROR, "%s: cannot allocate UsbMouseRec\n", pInfo->name); 649bd3a1963Smrg free(pMse); 6506aab59a7Smrg return FALSE; 6516aab59a7Smrg } 6526aab59a7Smrg 6536aab59a7Smrg pMse->protocol = protocol; 6546aab59a7Smrg xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol); 6556aab59a7Smrg 6566aab59a7Smrg /* Collect the options, and process the common options. */ 657bd3a1963Smrg COLLECT_INPUT_OPTIONS(pInfo, NULL); 6586aab59a7Smrg xf86ProcessCommonOptions(pInfo, pInfo->options); 6596aab59a7Smrg 6606aab59a7Smrg /* Check if the device can be opened. */ 6616aab59a7Smrg pInfo->fd = xf86OpenSerial(pInfo->options); 6626aab59a7Smrg if (pInfo->fd == -1) { 6636aab59a7Smrg if (xf86GetAllowMouseOpenFail()) 6646aab59a7Smrg xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 6656aab59a7Smrg else { 6666aab59a7Smrg xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name); 667bd3a1963Smrg free(pUsbMse); 668bd3a1963Smrg free(pMse); 6696aab59a7Smrg return FALSE; 6706aab59a7Smrg } 6716aab59a7Smrg } 6726aab59a7Smrg /* Get USB informations */ 6736aab59a7Smrg reportDesc = hid_get_report_desc(pInfo->fd); 6746aab59a7Smrg /* Get packet size & iid */ 6756aab59a7Smrg#ifdef USB_NEW_HID 6766aab59a7Smrg if (ioctl(pInfo->fd, USB_GET_REPORT_ID, &pUsbMse->iid) == -1) { 6776aab59a7Smrg xf86Msg(X_ERROR, "Error ioctl USB_GET_REPORT_ID on %s : %s\n", 6786aab59a7Smrg pInfo->name, strerror(errno)); 6796aab59a7Smrg return FALSE; 6806aab59a7Smrg } 6816aab59a7Smrg pUsbMse->packetSize = hid_report_size(reportDesc, hid_input, 6826aab59a7Smrg pUsbMse->iid); 6836aab59a7Smrg#else 6846aab59a7Smrg pUsbMse->packetSize = hid_report_size(reportDesc, hid_input, 6856aab59a7Smrg &pUsbMse->iid); 6866aab59a7Smrg#endif 6876aab59a7Smrg /* Allocate buffer */ 6886aab59a7Smrg if (pUsbMse->packetSize <= 8) { 6896aab59a7Smrg pUsbMse->buffer = pMse->protoBuf; 6906aab59a7Smrg } else { 691bd3a1963Smrg pUsbMse->buffer = malloc(pUsbMse->packetSize); 6926aab59a7Smrg } 6936aab59a7Smrg if (pUsbMse->buffer == NULL) { 6946aab59a7Smrg xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name); 695bd3a1963Smrg free(pUsbMse); 696bd3a1963Smrg free(pMse); 6976aab59a7Smrg xf86CloseSerial(pInfo->fd); 6986aab59a7Smrg return FALSE; 6996aab59a7Smrg } 7006aab59a7Smrg#ifdef USB_NEW_HID 7016aab59a7Smrg if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), 7026aab59a7Smrg hid_input, &pUsbMse->loc_x, pUsbMse->iid) < 0) { 7036aab59a7Smrg xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name); 7046aab59a7Smrg } 7056aab59a7Smrg if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), 7066aab59a7Smrg hid_input, &pUsbMse->loc_y, pUsbMse->iid) < 0) { 7076aab59a7Smrg xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name); 7086aab59a7Smrg } 7096aab59a7Smrg if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), 7106aab59a7Smrg hid_input, &pUsbMse->loc_z, pUsbMse->iid) < 0) { 7116aab59a7Smrg } 7126aab59a7Smrg#else 7136aab59a7Smrg if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), 7146aab59a7Smrg hid_input, &pUsbMse->loc_x) < 0) { 7156aab59a7Smrg xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name); 7166aab59a7Smrg } 7176aab59a7Smrg if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), 7186aab59a7Smrg hid_input, &pUsbMse->loc_y) < 0) { 7196aab59a7Smrg xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name); 7206aab59a7Smrg } 7216aab59a7Smrg if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), 7226aab59a7Smrg hid_input, &pUsbMse->loc_z) < 0) { 7236aab59a7Smrg } 7246aab59a7Smrg#endif 7256aab59a7Smrg /* Probe for number of buttons */ 7266aab59a7Smrg for (i = 1; i <= MSE_MAXBUTTONS; i++) { 7276aab59a7Smrg if (!hid_locate(reportDesc, HID_USAGE2(HUP_BUTTON, i), 7286aab59a7Smrg hid_input, &pUsbMse->loc_btn[i-1] 7296aab59a7Smrg#ifdef USB_NEW_HID 7306aab59a7Smrg , pUsbMse->iid 7316aab59a7Smrg#endif 7326aab59a7Smrg )) 7336aab59a7Smrg break; 7346aab59a7Smrg } 7356aab59a7Smrg pMse->buttons = i-1; 7366aab59a7Smrg 7376aab59a7Smrg xf86CloseSerial(pInfo->fd); 7386aab59a7Smrg pInfo->fd = -1; 7396aab59a7Smrg 7406aab59a7Smrg /* Private structure */ 7416aab59a7Smrg pMse->mousePriv = pUsbMse; 7426aab59a7Smrg 7436aab59a7Smrg /* Process common mouse options (like Emulate3Buttons, etc). */ 7446aab59a7Smrg pMse->CommonOptions(pInfo); 7456aab59a7Smrg 7466aab59a7Smrg /* Setup the local procs. */ 7476aab59a7Smrg pInfo->device_control = usbMouseProc; 7486aab59a7Smrg pInfo->read_input = usbReadInput; 7496aab59a7Smrg 750bd3a1963Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 7516aab59a7Smrg pInfo->flags |= XI86_CONFIGURED; 752bd3a1963Smrg#endif 7536aab59a7Smrg return TRUE; 7546aab59a7Smrg} 7556aab59a7Smrg#endif /* USBMOUSE */ 7566aab59a7Smrg 7576aab59a7Smrgstatic Bool 7586aab59a7SmrgbsdMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags) 7596aab59a7Smrg{ 7606aab59a7Smrg /* The protocol is guaranteed to be one of the internalNames[] */ 7616aab59a7Smrg#ifdef WSCONS_SUPPORT 7626aab59a7Smrg if (xf86NameCmp(protocol, "WSMouse") == 0) { 7636aab59a7Smrg return wsconsPreInit(pInfo, protocol, flags); 7646aab59a7Smrg } 7656aab59a7Smrg#endif 7666aab59a7Smrg#ifdef USBMOUSE_SUPPORT 7676aab59a7Smrg if (xf86NameCmp(protocol, "usb") == 0) { 7686aab59a7Smrg return usbPreInit(pInfo, protocol, flags); 7696aab59a7Smrg } 7706aab59a7Smrg#endif 7716aab59a7Smrg return TRUE; 7726aab59a7Smrg} 7736aab59a7Smrg 774bd3a1963SmrgOSMouseInfoPtr 775bd3a1963SmrgOSMouseInit(int flags) 7766aab59a7Smrg{ 7776aab59a7Smrg OSMouseInfoPtr p; 7786aab59a7Smrg 779bd3a1963Smrg p = calloc(sizeof(OSMouseInfoRec), 1); 7806aab59a7Smrg if (!p) 7816aab59a7Smrg return NULL; 7826aab59a7Smrg p->SupportedInterfaces = SupportedInterfaces; 7836aab59a7Smrg p->BuiltinNames = BuiltinNames; 7846aab59a7Smrg p->DefaultProtocol = DefaultProtocol; 7856aab59a7Smrg p->CheckProtocol = CheckProtocol; 7866aab59a7Smrg#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE) 7876aab59a7Smrg p->SetupAuto = SetupAuto; 7886aab59a7Smrg p->SetPS2Res = SetSysMouseRes; 7896aab59a7Smrg p->SetBMRes = SetSysMouseRes; 7906aab59a7Smrg p->SetMiscRes = SetSysMouseRes; 7916aab59a7Smrg#endif 7926aab59a7Smrg#if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT) 7936aab59a7Smrg p->SetupAuto = SetupAuto; 7946aab59a7Smrg p->SetMiscRes = SetMouseRes; 7956aab59a7Smrg#endif 7966aab59a7Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__) 7976aab59a7Smrg p->FindDevice = FindDevice; 7986aab59a7Smrg#endif 7996aab59a7Smrg p->PreInit = bsdMousePreInit; 8006aab59a7Smrg return p; 8016aab59a7Smrg} 802