<https://bugs.freedesktop.org/attachment.cgi?id=3463> GNU/kFreeBSD Xserver support (Robert Millan)
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__) || defined(__FreeBSD_kernel__)
|
|
/* 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__) || defined(__FreeBSD_kernel__)
|
|
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__) || defined(__FreeBSD_kernel__)
|
|
"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__) || defined(__FreeBSD_kernel__)
|
|
return "Auto";
|
|
#elif defined(__OpenBSD__) && defined(WSCONS_SUPPORT)
|
|
return "WSMouse";
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && 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__) || defined(__FreeBSD_kernel__)
|
|
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__) || defined(__FreeBSD_kernel__)
|
|
|
|
#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(__FreeBSD_kernel__)) && 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(__FreeBSD_kernel__) || defined(__OpenBSD__)
|
|
p->FindDevice = FindDevice;
|
|
#endif
|
|
p->PreInit = bsdMousePreInit;
|
|
return p;
|
|
}
|