792 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			792 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bsd/bsd_mouse.c,v 1.28 2004/02/06 17:15:36 tsi Exp $ */
 | |
| 
 | |
| /*
 | |
|  * Copyright (c) 1999-2003 by The XFree86 Project, Inc.
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining a
 | |
|  * copy of this software and associated documentation files (the "Software"),
 | |
|  * to deal in the Software without restriction, including without limitation
 | |
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | |
|  * and/or sell copies of the Software, and to permit persons to whom the
 | |
|  * Software is furnished to do so, subject to the following conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice shall be included in
 | |
|  * all copies or substantial portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | |
|  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 | |
|  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 | |
|  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | |
|  * OTHER DEALINGS IN THE SOFTWARE.
 | |
|  *
 | |
|  * Except as contained in this notice, the name of the copyright holder(s)
 | |
|  * and author(s) shall not be used in advertising or otherwise to promote
 | |
|  * the sale, use or other dealings in this Software without prior written
 | |
|  * authorization from the copyright holder(s) and author(s).
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_XORG_CONFIG_H
 | |
| #include <xorg-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <X11/X.h>
 | |
| #include "xf86.h"
 | |
| #include "xf86Priv.h"
 | |
| #include "xf86_OSlib.h"
 | |
| #include "xf86Xinput.h"
 | |
| #include "xf86OSmouse.h"
 | |
| #include "xisb.h"
 | |
| #include "mipointer.h"
 | |
| #ifdef WSCONS_SUPPORT
 | |
| #include <dev/wscons/wsconsio.h>
 | |
| #endif
 | |
| #ifdef USBMOUSE_SUPPORT
 | |
| #ifdef HAS_LIB_USB_HID
 | |
| #include <usbhid.h>
 | |
| #else
 | |
| #include "usb.h"
 | |
| #endif
 | |
| 
 | |
| #include <dev/usb/usb.h>
 | |
| #ifdef USB_GET_REPORT_ID
 | |
| #define USB_NEW_HID
 | |
| #endif
 | |
| 
 | |
| #define HUP_GENERIC_DESKTOP     0x0001
 | |
| #define HUP_BUTTON              0x0009
 | |
| 
 | |
| #define HUG_X                   0x0030
 | |
| #define HUG_Y                   0x0031
 | |
| #define HUG_Z                   0x0032
 | |
| #define HUG_WHEEL               0x0038
 | |
| 
 | |
| #define HID_USAGE2(p,u) (((p) << 16) | u)
 | |
| 
 | |
| /* The UMS mices have middle button as number 3 */
 | |
| #define UMS_BUT(i) ((i) == 0 ? 2 : (i) == 1 ? 0 : (i) == 2 ? 1 : (i))
 | |
| #endif /* USBMOUSE_SUPPORT */
 | |
| 
 | |
| #ifdef USBMOUSE_SUPPORT
 | |
| static void usbSigioReadInput (int fd, void *closure);
 | |
| #endif
 | |
| 
 | |
| #if defined(__FreeBSD__)
 | |
| /* These are for FreeBSD */
 | |
| #define DEFAULT_MOUSE_DEV		"/dev/mouse"
 | |
| #define DEFAULT_SYSMOUSE_DEV		"/dev/sysmouse"
 | |
| #define DEFAULT_PS2_DEV			"/dev/psm0"
 | |
| 
 | |
| static const char *mouseDevs[] = {
 | |
| 	DEFAULT_MOUSE_DEV,
 | |
| 	DEFAULT_SYSMOUSE_DEV,
 | |
| 	DEFAULT_PS2_DEV,
 | |
| 	NULL
 | |
| };
 | |
| #elif defined(__OpenBSD__) && defined(WSCONS_SUPPORT)
 | |
| /* Only wsmouse mices are autoconfigured for now on OpenBSD */
 | |
| #define DEFAULT_WSMOUSE_DEV		"/dev/wsmouse"
 | |
| #define DEFAULT_WSMOUSE0_DEV		"/dev/wsmouse0"
 | |
| 
 | |
| static const char *mouseDevs[] = {
 | |
| 	DEFAULT_WSMOUSE_DEV,
 | |
| 	DEFAULT_WSMOUSE0_DEV,
 | |
| 	NULL
 | |
| };
 | |
| #endif
 | |
| 
 | |
| static int
 | |
| SupportedInterfaces(void)
 | |
| {
 | |
| #if defined(__NetBSD__)
 | |
|     return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO;
 | |
| #elif defined(__FreeBSD__)
 | |
|     return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC;
 | |
| #else
 | |
|     return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /* Names of protocols that are handled internally here. */
 | |
| static const char *internalNames[] = {
 | |
| #if defined(WSCONS_SUPPORT)
 | |
| 	"WSMouse",
 | |
| #endif
 | |
| #if defined(USBMOUSE_SUPPORT)
 | |
| 	"usb",
 | |
| #endif
 | |
| 	NULL
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * Names of MSC_MISC protocols that the OS supports.  These are decoded by
 | |
|  * main "mouse" driver.
 | |
|  */
 | |
| static const char *miscNames[] = {
 | |
| #if defined(__FreeBSD__)
 | |
| 	"SysMouse",
 | |
| #endif
 | |
| 	NULL
 | |
| };
 | |
| 
 | |
| static const char **
 | |
| BuiltinNames(void)
 | |
| {
 | |
|     return internalNames;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| CheckProtocol(const char *protocol)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; internalNames[i]; i++)
 | |
| 	if (xf86NameCmp(protocol, internalNames[i]) == 0)
 | |
| 	    return TRUE;
 | |
|     for (i = 0; miscNames[i]; i++)
 | |
| 	if (xf86NameCmp(protocol, miscNames[i]) == 0)
 | |
| 	    return TRUE;
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| static const char *
 | |
| DefaultProtocol(void)
 | |
| {
 | |
| #if defined(__FreeBSD__)
 | |
|     return "Auto";
 | |
| #elif defined(__OpenBSD__) && defined(WSCONS_SUPPORT)
 | |
|     return "WSMouse";
 | |
| #else
 | |
|     return NULL;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #if defined(__FreeBSD__) && defined(MOUSE_PROTO_SYSMOUSE)
 | |
| static struct {
 | |
| 	int dproto;
 | |
| 	const char *name;
 | |
| } devproto[] = {
 | |
| 	{ MOUSE_PROTO_MS,		"Microsoft" },
 | |
| 	{ MOUSE_PROTO_MSC,		"MouseSystems" },
 | |
| 	{ MOUSE_PROTO_LOGI,		"Logitech" },
 | |
| 	{ MOUSE_PROTO_MM,		"MMSeries" },
 | |
| 	{ MOUSE_PROTO_LOGIMOUSEMAN,	"MouseMan" },
 | |
| 	{ MOUSE_PROTO_BUS,		"BusMouse" },
 | |
| 	{ MOUSE_PROTO_INPORT,		"BusMouse" },
 | |
| 	{ MOUSE_PROTO_PS2,		"PS/2" },
 | |
| 	{ MOUSE_PROTO_HITTAB,		"MMHitTab" },
 | |
| 	{ MOUSE_PROTO_GLIDEPOINT,	"GlidePoint" },
 | |
| 	{ MOUSE_PROTO_INTELLI,		"Intellimouse" },
 | |
| 	{ MOUSE_PROTO_THINK,		"ThinkingMouse" },
 | |
| 	{ MOUSE_PROTO_SYSMOUSE,		"SysMouse" }
 | |
| };
 | |
| 	
 | |
| static const char *
 | |
| SetupAuto(InputInfoPtr pInfo, int *protoPara)
 | |
| {
 | |
|     int i;
 | |
|     mousehw_t hw;
 | |
|     mousemode_t mode;
 | |
| 
 | |
|     if (pInfo->fd == -1)
 | |
| 	return NULL;
 | |
| 
 | |
|     /* set the driver operation level, if applicable */
 | |
|     i = 1;
 | |
|     ioctl(pInfo->fd, MOUSE_SETLEVEL, &i);
 | |
|     
 | |
|     /* interrogate the driver and get some intelligence on the device. */
 | |
|     hw.iftype = MOUSE_IF_UNKNOWN;
 | |
|     hw.model = MOUSE_MODEL_GENERIC;
 | |
|     ioctl(pInfo->fd, MOUSE_GETHWINFO, &hw);
 | |
|     xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: hw.iftype is %d, hw.model is %d\n",
 | |
| 		pInfo->name, hw.iftype, hw.model);
 | |
|     if (ioctl(pInfo->fd, MOUSE_GETMODE, &mode) == 0) {
 | |
| 	for (i = 0; i < sizeof(devproto)/sizeof(devproto[0]); ++i) {
 | |
| 	    if (mode.protocol == devproto[i].dproto) {
 | |
| 		/* override some parameters */
 | |
| 		if (protoPara) {
 | |
| 		    protoPara[4] = mode.packetsize;
 | |
| 		    protoPara[0] = mode.syncmask[0];
 | |
| 		    protoPara[1] = mode.syncmask[1];
 | |
| 		}
 | |
| 		xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
 | |
| 			    pInfo->name, devproto[i].name);
 | |
| 		return devproto[i].name;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static void
 | |
| SetSysMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res)
 | |
| {
 | |
|     mousemode_t mode;
 | |
|     MouseDevPtr pMse;
 | |
| 
 | |
|     pMse = pInfo->private;
 | |
| 
 | |
|     mode.rate = rate > 0 ? rate : -1;
 | |
|     mode.resolution = res > 0 ? res : -1;
 | |
|     mode.accelfactor = -1;
 | |
| #if defined(__FreeBSD__)
 | |
|     if (pMse->autoProbe ||
 | |
| 	(protocol && xf86NameCmp(protocol, "SysMouse") == 0)) {
 | |
| 	/*
 | |
| 	 * As the FreeBSD sysmouse driver defaults to protocol level 0
 | |
| 	 * everytime it is opened we enforce protocol level 1 again at
 | |
| 	 * this point.
 | |
| 	 */
 | |
| 	mode.level = 1;
 | |
|     } else
 | |
| 	mode.level = -1;
 | |
| #else
 | |
|     mode.level = -1;
 | |
| #endif
 | |
|     ioctl(pInfo->fd, MOUSE_SETMODE, &mode);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if defined(__FreeBSD__)
 | |
| 
 | |
| #define MOUSED_PID_FILE "/var/run/moused.pid"
 | |
| 
 | |
| /*
 | |
|  * Try to check if moused is running.  DEFAULT_SYSMOUSE_DEV is useless without
 | |
|  * it.  There doesn't seem to be a better way of checking.
 | |
|  */
 | |
| static Bool
 | |
| MousedRunning(void)
 | |
| {
 | |
|     FILE *f = NULL;
 | |
|     unsigned int pid;
 | |
| 
 | |
|     if ((f = fopen(MOUSED_PID_FILE, "r")) != NULL) {
 | |
| 	if (fscanf(f, "%u", &pid) == 1 && pid > 0) {
 | |
| 	    if (kill(pid, 0) == 0) {
 | |
| 		fclose(f);
 | |
| 		return TRUE;
 | |
| 	    }
 | |
| 	}
 | |
| 	fclose(f);
 | |
|     }
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| static const char *
 | |
| FindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
 | |
| {
 | |
|     int fd = -1;
 | |
|     const char **pdev, *dev = NULL;
 | |
|     Bool devMouse = FALSE;
 | |
|     struct stat devMouseStat;
 | |
|     struct stat sb;
 | |
| 
 | |
|     for (pdev = mouseDevs; *pdev; pdev++) {
 | |
| 	SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK));
 | |
| 	if (fd == -1) {
 | |
| #ifdef DEBUG
 | |
| 	    ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno));
 | |
| #endif
 | |
| 	} else {
 | |
| 	    /*
 | |
| 	     * /dev/mouse is held until checks for matches with other devices
 | |
| 	     * are done.  This is so that when it points to /dev/sysmouse,
 | |
| 	     * the test for whether /dev/sysmouse is usable can be made.
 | |
| 	     */
 | |
| 	    if (!strcmp(*pdev, DEFAULT_MOUSE_DEV)) {
 | |
| 		if (fstat(fd, &devMouseStat) == 0)
 | |
| 		    devMouse = TRUE;
 | |
| 		close(fd);
 | |
| 		continue;
 | |
| 	    } else if (!strcmp(*pdev, DEFAULT_SYSMOUSE_DEV)) {
 | |
| 		/* Check if /dev/mouse is the same as /dev/sysmouse. */
 | |
| 		if (devMouse && fstat(fd, &sb) == 0 && 
 | |
| 		    devMouseStat.st_dev == sb.st_dev &&
 | |
| 		    devMouseStat.st_ino == sb.st_ino) {
 | |
| 		    /* If the same, use /dev/sysmouse. */
 | |
| 		    devMouse = FALSE;
 | |
| 		}
 | |
| 		close(fd);
 | |
| 		if (MousedRunning())
 | |
| 		    break;
 | |
| 		else {
 | |
| #ifdef DEBUG
 | |
| 	    	    ErrorF("moused isn't running\n");
 | |
| #endif
 | |
| 		}
 | |
| 	    } else {
 | |
| 		close(fd);
 | |
| 		break;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if (*pdev)
 | |
| 	dev = *pdev;
 | |
|     else if (devMouse)
 | |
| 	dev = DEFAULT_MOUSE_DEV;
 | |
| 
 | |
|     if (dev) {
 | |
| 	/* Set the Device option. */
 | |
| 	pInfo->conf_idev->commonOptions =
 | |
| 	    xf86AddNewOption(pInfo->conf_idev->commonOptions, "Device", dev);
 | |
| 	xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n",
 | |
| 		pInfo->name, dev);
 | |
|     }
 | |
| 
 | |
|     return *pdev;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if defined(__OpenBSD__) && defined(WSCONS_SUPPORT)
 | |
| 
 | |
| /* Only support wsmouse configuration for now */
 | |
| static const char *
 | |
| SetupAuto(InputInfoPtr pInfo, int *protoPara)
 | |
| {
 | |
| 
 | |
|     xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
 | |
| 		pInfo->name, "wsmouse");
 | |
|     return "wsmouse";
 | |
| }
 | |
| 
 | |
| static void
 | |
| SetMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res)
 | |
| {
 | |
| 
 | |
|     xf86MsgVerb(X_INFO, 3, "%s: SetMouseRes: protocol %s rate %d res %d\n",
 | |
| 	    pInfo->name, protocol, rate, res);
 | |
| }
 | |
| 
 | |
| static const char *
 | |
| FindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
 | |
| {
 | |
|     int fd = -1;
 | |
|     const char **pdev;
 | |
| 
 | |
|     for (pdev = mouseDevs; *pdev; pdev++) {
 | |
| 	SYSCALL(fd = open(*pdev, O_RDWR | O_NONBLOCK));
 | |
| 	if (fd != -1) {
 | |
| 	    /* Set the Device option. */
 | |
| 	    pInfo->conf_idev->commonOptions =
 | |
| 		xf86AddNewOption(pInfo->conf_idev->commonOptions, 
 | |
| 				 "Device", *pdev);
 | |
| 	    xf86Msg(X_INFO, "%s: found Device \"%s\"\n",
 | |
| 		    pInfo->name, *pdev);
 | |
| 	    close(fd);
 | |
| 	    break;
 | |
| 	}
 | |
|     }
 | |
|     return *pdev;
 | |
| }
 | |
| #endif /* __OpenBSD__ && WSCONS_SUPPORT */
 | |
| 
 | |
| #ifdef WSCONS_SUPPORT
 | |
| #define NUMEVENTS 64
 | |
| 
 | |
| static void
 | |
| wsconsReadInput(InputInfoPtr pInfo)
 | |
| {
 | |
|     MouseDevPtr pMse;
 | |
|     static struct wscons_event eventList[NUMEVENTS];
 | |
|     int n, c; 
 | |
|     struct wscons_event *event = eventList;
 | |
|     unsigned char *pBuf;
 | |
| 
 | |
|     pMse = pInfo->private;
 | |
| 
 | |
|     XisbBlockDuration(pMse->buffer, -1);
 | |
|     pBuf = (unsigned char *)eventList;
 | |
|     n = 0;
 | |
|     while ((c = XisbRead(pMse->buffer)) >= 0 && n < sizeof(eventList)) {
 | |
| 	pBuf[n++] = (unsigned char)c;
 | |
|     }
 | |
| 
 | |
|     if (n == 0)
 | |
| 	return;
 | |
| 
 | |
|     n /= sizeof(struct wscons_event);
 | |
|     while( n-- ) {
 | |
| 	int buttons = pMse->lastButtons;
 | |
| 	int dx = 0, dy = 0, dz = 0, dw = 0;
 | |
| 	switch (event->type) {
 | |
| 	case WSCONS_EVENT_MOUSE_UP:
 | |
| #define BUTBIT (1 << (event->value <= 2 ? 2 - event->value : event->value))
 | |
| 	    buttons &= ~BUTBIT;
 | |
| 	    break;
 | |
| 	case WSCONS_EVENT_MOUSE_DOWN:
 | |
| 	    buttons |= BUTBIT;
 | |
| 	    break;
 | |
| 	case WSCONS_EVENT_MOUSE_DELTA_X:
 | |
| 	    dx = event->value;
 | |
| 	    break;
 | |
| 	case WSCONS_EVENT_MOUSE_DELTA_Y:
 | |
| 	    dy = -event->value;
 | |
| 	    break;
 | |
| #ifdef WSCONS_EVENT_MOUSE_DELTA_Z
 | |
| 	case WSCONS_EVENT_MOUSE_DELTA_Z:
 | |
| 	    dz = event->value;
 | |
| 	    break;
 | |
| #endif
 | |
| 	default:
 | |
| 	    xf86Msg(X_WARNING, "%s: bad wsmouse event type=%d\n", pInfo->name,
 | |
| 		    event->type);
 | |
| 	    ++event;
 | |
| 	    continue;
 | |
| 	}
 | |
| 
 | |
| 	pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
 | |
| 	++event;
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* This function is called when the protocol is "wsmouse". */
 | |
| static Bool
 | |
| wsconsPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
 | |
| {
 | |
|     MouseDevPtr pMse = pInfo->private;
 | |
| 
 | |
|     pMse->protocol = protocol;
 | |
|     xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
 | |
| 
 | |
|     /* Collect the options, and process the common options. */
 | |
|     xf86CollectInputOptions(pInfo, NULL, NULL);
 | |
|     xf86ProcessCommonOptions(pInfo, pInfo->options);
 | |
| 
 | |
|     /* Check if the device can be opened. */
 | |
|     pInfo->fd = xf86OpenSerial(pInfo->options);
 | |
|     if (pInfo->fd == -1) {
 | |
| 	if (xf86GetAllowMouseOpenFail())
 | |
| 	    xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
 | |
| 	else {
 | |
| 	    xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
 | |
| 	    xfree(pMse);
 | |
| 	    return FALSE;
 | |
| 	}
 | |
|     }
 | |
|     xf86CloseSerial(pInfo->fd);
 | |
|     pInfo->fd = -1;
 | |
| 
 | |
|     /* Process common mouse options (like Emulate3Buttons, etc). */
 | |
|     pMse->CommonOptions(pInfo);
 | |
| 
 | |
|     /* Setup the local input proc. */
 | |
|     pInfo->read_input = wsconsReadInput;
 | |
|     pMse->xisbscale = sizeof(struct wscons_event);
 | |
| 
 | |
|     pInfo->flags |= XI86_CONFIGURED;
 | |
|     return TRUE;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if defined(USBMOUSE_SUPPORT)
 | |
| 
 | |
| typedef struct _UsbMseRec {
 | |
|     int packetSize;
 | |
|     int iid;
 | |
|     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_btn[MSE_MAXBUTTONS]; /* buttons locator items */
 | |
|    unsigned char *buffer;
 | |
| } UsbMseRec, *UsbMsePtr;
 | |
| 
 | |
| static int
 | |
| usbMouseProc(DeviceIntPtr pPointer, int what)
 | |
| {
 | |
|     InputInfoPtr pInfo;
 | |
|     MouseDevPtr pMse;
 | |
|     UsbMsePtr pUsbMse;
 | |
|     unsigned char map[MSE_MAXBUTTONS + 1];
 | |
|     int nbuttons;
 | |
| 
 | |
|     pInfo = pPointer->public.devicePrivate;
 | |
|     pMse = pInfo->private;
 | |
|     pMse->device = pPointer;
 | |
|     pUsbMse = pMse->mousePriv;
 | |
| 
 | |
|     switch (what) {
 | |
|     case DEVICE_INIT: 
 | |
| 	pPointer->public.on = FALSE;
 | |
| 
 | |
| 	for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons)
 | |
| 	    map[nbuttons + 1] = nbuttons + 1;
 | |
| 
 | |
| 	InitPointerDeviceStruct((DevicePtr)pPointer, 
 | |
| 				map, 
 | |
| 				min(pMse->buttons, MSE_MAXBUTTONS),
 | |
| 				miPointerGetMotionEvents, 
 | |
| 				pMse->Ctrl,
 | |
| 				miPointerGetMotionBufferSize());
 | |
| 
 | |
| 	/* X valuator */
 | |
| 	xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1);
 | |
| 	xf86InitValuatorDefaults(pPointer, 0);
 | |
| 	/* Y valuator */
 | |
| 	xf86InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1);
 | |
| 	xf86InitValuatorDefaults(pPointer, 1);
 | |
| 	xf86MotionHistoryAllocate(pInfo);
 | |
| 	break;
 | |
| 
 | |
|     case DEVICE_ON:
 | |
| 	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) {
 | |
| 		xfree(pMse);
 | |
| 		xf86CloseSerial(pInfo->fd);
 | |
| 		pInfo->fd = -1;
 | |
| 	    } else {
 | |
| 		xf86FlushInput(pInfo->fd);
 | |
| 		if (!xf86InstallSIGIOHandler (pInfo->fd, usbSigioReadInput, 
 | |
| 					      pInfo))
 | |
| 		    AddEnabledDevice(pInfo->fd);
 | |
| 	    }
 | |
| 	}
 | |
| 	pMse->lastButtons = 0;
 | |
| 	pMse->emulateState = 0;
 | |
| 	pPointer->public.on = TRUE;
 | |
| 	break;
 | |
| 
 | |
|     case DEVICE_OFF:
 | |
|     case DEVICE_CLOSE:
 | |
| 	if (pInfo->fd != -1) {
 | |
| 	    RemoveEnabledDevice(pInfo->fd);
 | |
| 	    if (pUsbMse->packetSize > 8 && pUsbMse->buffer) {
 | |
| 		xfree(pUsbMse->buffer);
 | |
| 	    }
 | |
| 	    if (pMse->buffer) {
 | |
| 		XisbFree(pMse->buffer);
 | |
| 		pMse->buffer = NULL;
 | |
| 	    }
 | |
| 	    xf86CloseSerial(pInfo->fd);
 | |
| 	    pInfo->fd = -1;
 | |
| 	}
 | |
| 	pPointer->public.on = FALSE;
 | |
| 	usleep(300000);
 | |
| 	break;
 | |
|     }
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static void
 | |
| usbReadInput(InputInfoPtr pInfo)
 | |
| {
 | |
|     MouseDevPtr pMse;
 | |
|     UsbMsePtr pUsbMse;
 | |
|     int buttons = pMse->lastButtons;
 | |
|     int dx = 0, dy = 0, dz = 0, dw = 0;
 | |
|     int n, c; 
 | |
|     unsigned char *pBuf;
 | |
| 
 | |
|     pMse = pInfo->private;
 | |
|     pUsbMse = pMse->mousePriv;
 | |
| 
 | |
|     XisbBlockDuration(pMse->buffer, -1);
 | |
|     pBuf = pUsbMse->buffer;
 | |
|     n = 0;
 | |
|     while ((c = XisbRead(pMse->buffer)) >= 0 && n < pUsbMse->packetSize) {
 | |
| 	pBuf[n++] = (unsigned char)c;
 | |
|     }
 | |
|     if (n == 0)
 | |
| 	return;
 | |
|     if (n != pUsbMse->packetSize) {
 | |
| 	xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", pInfo->name,
 | |
| 		n);
 | |
|     }
 | |
|     /* discard packets with an id that don't match the mouse */
 | |
|     /* XXX this is probably not the right thing */
 | |
|     if (pUsbMse->iid != 0) {
 | |
| 	if (*pBuf++ != pUsbMse->iid) 
 | |
| 	    return;
 | |
|     }
 | |
|     dx = hid_get_data(pBuf, &pUsbMse->loc_x);
 | |
|     dy = hid_get_data(pBuf, &pUsbMse->loc_y);
 | |
|     dz = hid_get_data(pBuf, &pUsbMse->loc_z);
 | |
| 
 | |
|     buttons = 0;
 | |
|     for (n = 0; n < pMse->buttons; n++) {
 | |
| 	if (hid_get_data(pBuf, &pUsbMse->loc_btn[n])) 
 | |
| 	    buttons |= (1 << UMS_BUT(n));
 | |
|     }
 | |
|     pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static void
 | |
| usbSigioReadInput (int fd, void *closure)
 | |
| {
 | |
|     usbReadInput ((InputInfoPtr) closure);
 | |
| }
 | |
| 
 | |
| /* This function is called when the protocol is "usb". */
 | |
| static Bool
 | |
| usbPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
 | |
| {
 | |
|     MouseDevPtr pMse = pInfo->private;
 | |
|     UsbMsePtr pUsbMse;
 | |
|     report_desc_t reportDesc;
 | |
|     int i;
 | |
| 
 | |
|     pUsbMse = xalloc(sizeof(UsbMseRec));
 | |
|     if (pUsbMse == NULL) {
 | |
| 	xf86Msg(X_ERROR, "%s: cannot allocate UsbMouseRec\n", pInfo->name);
 | |
| 	xfree(pMse);
 | |
| 	return FALSE;
 | |
|     }
 | |
| 
 | |
|     pMse->protocol = protocol;
 | |
|     xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
 | |
| 
 | |
|     /* Collect the options, and process the common options. */
 | |
|     xf86CollectInputOptions(pInfo, NULL, NULL);
 | |
|     xf86ProcessCommonOptions(pInfo, pInfo->options);
 | |
| 
 | |
|     /* Check if the device can be opened. */
 | |
|     pInfo->fd = xf86OpenSerial(pInfo->options);
 | |
|     if (pInfo->fd == -1) {
 | |
| 	if (xf86GetAllowMouseOpenFail())
 | |
| 	    xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
 | |
| 	else {
 | |
| 	    xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
 | |
| 	    xfree(pUsbMse);
 | |
| 	    xfree(pMse);
 | |
| 	    return FALSE;
 | |
| 	}
 | |
|     }
 | |
|     /* Get USB informations */
 | |
|     reportDesc = hid_get_report_desc(pInfo->fd);
 | |
|     /* Get packet size & iid */
 | |
| #ifdef USB_NEW_HID
 | |
|     if (ioctl(pInfo->fd, USB_GET_REPORT_ID, &pUsbMse->iid) == -1) {
 | |
| 	    xf86Msg(X_ERROR, "Error ioctl USB_GET_REPORT_ID on %s : %s\n",
 | |
| 		    pInfo->name, strerror(errno));
 | |
| 	    return FALSE;
 | |
|     }
 | |
|     pUsbMse->packetSize = hid_report_size(reportDesc, hid_input,
 | |
| 					      pUsbMse->iid);
 | |
| #else
 | |
|     pUsbMse->packetSize = hid_report_size(reportDesc, hid_input,
 | |
| 					      &pUsbMse->iid);
 | |
| #endif
 | |
|     /* Allocate buffer */
 | |
|     if (pUsbMse->packetSize <= 8) {
 | |
| 	pUsbMse->buffer = pMse->protoBuf;
 | |
|     } else {
 | |
| 	pUsbMse->buffer = xalloc(pUsbMse->packetSize);
 | |
|     }
 | |
|     if (pUsbMse->buffer == NULL) {
 | |
| 	xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name);
 | |
| 	xfree(pUsbMse);
 | |
| 	xfree(pMse);
 | |
| 	xf86CloseSerial(pInfo->fd);
 | |
| 	return FALSE;
 | |
|     }
 | |
| #ifdef USB_NEW_HID
 | |
|     if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
 | |
| 		   hid_input, &pUsbMse->loc_x, pUsbMse->iid) < 0) {
 | |
| 	xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name);
 | |
|     }
 | |
|     if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
 | |
| 		   hid_input, &pUsbMse->loc_y, pUsbMse->iid) < 0) {
 | |
| 	xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name);
 | |
|     }
 | |
|     if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
 | |
| 		   hid_input, &pUsbMse->loc_z, pUsbMse->iid) < 0) {
 | |
|     }
 | |
| #else
 | |
|     if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
 | |
| 		   hid_input, &pUsbMse->loc_x) < 0) {
 | |
| 	xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name);
 | |
|     }
 | |
|     if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
 | |
| 		   hid_input, &pUsbMse->loc_y) < 0) {
 | |
| 	xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name);
 | |
|     }
 | |
|     if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
 | |
| 		   hid_input, &pUsbMse->loc_z) < 0) {
 | |
|     }
 | |
| #endif
 | |
|     /* Probe for number of buttons */
 | |
|     for (i = 1; i <= MSE_MAXBUTTONS; i++) {
 | |
| 	if (!hid_locate(reportDesc, HID_USAGE2(HUP_BUTTON, i),
 | |
| 			hid_input, &pUsbMse->loc_btn[i-1]
 | |
| #ifdef USB_NEW_HID
 | |
| 			, pUsbMse->iid
 | |
| #endif
 | |
| 			))
 | |
| 	    break;
 | |
|     }
 | |
|     pMse->buttons = i-1;
 | |
| 
 | |
|     xf86CloseSerial(pInfo->fd);
 | |
|     pInfo->fd = -1;
 | |
| 
 | |
|     /* Private structure */
 | |
|     pMse->mousePriv = pUsbMse;
 | |
| 
 | |
|     /* Process common mouse options (like Emulate3Buttons, etc). */
 | |
|     pMse->CommonOptions(pInfo);
 | |
| 
 | |
|     /* Setup the local procs. */
 | |
|     pInfo->device_control = usbMouseProc;
 | |
|     pInfo->read_input = usbReadInput;
 | |
| 
 | |
|     pInfo->flags |= XI86_CONFIGURED;
 | |
|     return TRUE;
 | |
| }
 | |
| #endif /* USBMOUSE */
 | |
| 
 | |
| static Bool
 | |
| bsdMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags)
 | |
| {
 | |
|     /* The protocol is guaranteed to be one of the internalNames[] */
 | |
| #ifdef WSCONS_SUPPORT
 | |
|     if (xf86NameCmp(protocol, "WSMouse") == 0) {
 | |
| 	return wsconsPreInit(pInfo, protocol, flags);
 | |
|     }
 | |
| #endif
 | |
| #ifdef USBMOUSE_SUPPORT
 | |
|     if (xf86NameCmp(protocol, "usb") == 0) {
 | |
| 	return usbPreInit(pInfo, protocol, flags);
 | |
|     }
 | |
| #endif
 | |
|     return TRUE;
 | |
| }    
 | |
| 
 | |
| OSMouseInfoPtr
 | |
| xf86OSMouseInit(int flags)
 | |
| {
 | |
|     OSMouseInfoPtr p;
 | |
| 
 | |
|     p = xcalloc(sizeof(OSMouseInfoRec), 1);
 | |
|     if (!p)
 | |
| 	return NULL;
 | |
|     p->SupportedInterfaces = SupportedInterfaces;
 | |
|     p->BuiltinNames = BuiltinNames;
 | |
|     p->DefaultProtocol = DefaultProtocol;
 | |
|     p->CheckProtocol = CheckProtocol;
 | |
| #if defined(__FreeBSD__) && defined(MOUSE_PROTO_SYSMOUSE)
 | |
|     p->SetupAuto = SetupAuto;
 | |
|     p->SetPS2Res = SetSysMouseRes;
 | |
|     p->SetBMRes = SetSysMouseRes;
 | |
|     p->SetMiscRes = SetSysMouseRes;
 | |
| #endif
 | |
| #if defined(__OpenBSD__) && defined(WSCONS_SUPPORT)
 | |
|     p->SetupAuto = SetupAuto;
 | |
|     p->SetMiscRes = SetMouseRes;
 | |
| #endif
 | |
| #if defined(__FreeBSD__) || defined(__OpenBSD__)
 | |
|     p->FindDevice = FindDevice;
 | |
| #endif
 | |
|     p->PreInit = bsdMousePreInit;
 | |
|     return p;
 | |
| }
 |