xserver-multidpi/hw/xfree86/os-support/linux/lnx_mouse.c
2006-03-25 19:52:05 +00:00

207 lines
4.6 KiB
C

/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_mouse.c,v 1.2 2003/10/08 14:58:30 dawes Exp $ */
/*
* Copyright 1999 by The XFree86 Project, Inc.
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <X11/X.h>
#include "xf86.h"
#include "xf86Xinput.h"
#include "xf86OSmouse.h"
#include "xf86_OSlib.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static int
SupportedInterfaces(void)
{
return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO;
}
static const char *
DefaultProtocol(void)
{
return "Auto";
}
#define DEFAULT_MOUSE_DEV "/dev/mouse"
#define DEFAULT_PS2_DEV "/dev/psaux"
#define DEFAULT_GPM_DATA_DEV "/dev/gpmdata"
#define DEFAULT_GPM_CTL_DEV "/dev/gpmdata"
static const char *mouseDevs[] = {
DEFAULT_MOUSE_DEV,
DEFAULT_PS2_DEV,
DEFAULT_GPM_DATA_DEV,
NULL
};
typedef enum {
MOUSE_PROTO_UNKNOWN = 0,
MOUSE_PROTO_SERIAL,
MOUSE_PROTO_PS2,
MOUSE_PROTO_MSC,
MOUSE_PROTO_GPM
} protocolTypes;
static struct {
protocolTypes proto;
const char *name;
} devproto[] = {
{ MOUSE_PROTO_UNKNOWN, NULL },
{ MOUSE_PROTO_PS2, "PS/2" },
{ MOUSE_PROTO_MSC, "MouseSystems" },
{ MOUSE_PROTO_GPM, "GPM" }
};
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 | O_EXCL));
if (fd == -1) {
#ifdef DEBUG
ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno));
#endif
} else
break;
}
if (*pdev) {
close(fd);
/* Set the Device option. */
pInfo->conf_idev->commonOptions =
xf86AddNewOption(pInfo->conf_idev->commonOptions, "Device", *pdev);
xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n",
pInfo->name, *pdev);
}
return *pdev;
}
static const char *
GuessProtocol(InputInfoPtr pInfo, int flags)
{
int fd = -1;
const char *dev;
char *realdev;
struct stat sbuf;
int i;
int proto = MOUSE_PROTO_UNKNOWN;
dev = xf86SetStrOption(pInfo->conf_idev->commonOptions, "Device", NULL);
if (!dev) {
#ifdef DEBUG
ErrorF("xf86SetStrOption failed to return the device name\n");
#endif
return NULL;
}
/* Look at the device name to guess the protocol. */
realdev = NULL;
if (strcmp(dev, DEFAULT_MOUSE_DEV) == 0) {
if (lstat(dev, &sbuf) != 0) {
#ifdef DEBUG
ErrorF("lstat failed for %s (%s)\n", dev, strerror(errno));
#endif
return NULL;
}
if (S_ISLNK(sbuf.st_mode)) {
realdev = xnfalloc(PATH_MAX + 1);
i = readlink(dev, realdev, PATH_MAX);
if (i <= 0) {
#ifdef DEBUG
ErrorF("readlink failed for %s (%s)\n", dev, strerror(errno));
#endif
xfree(realdev);
return NULL;
}
realdev[i] = '\0';
}
}
if (!realdev)
realdev = xnfstrdup(dev);
else {
/* If realdev doesn't contain a '/' then prepend "/dev/" */
if (!strchr(realdev, '/')) {
char *tmp = xnfalloc(strlen(realdev) + 5 + 1);
sprintf(tmp, "/dev/%s", realdev);
xfree(realdev);
realdev = tmp;
}
}
if (strcmp(realdev, DEFAULT_PS2_DEV) == 0)
proto = MOUSE_PROTO_PS2;
else if (strcmp(realdev, DEFAULT_GPM_DATA_DEV) == 0)
proto = MOUSE_PROTO_MSC;
else if (strcmp(realdev, DEFAULT_GPM_CTL_DEV) == 0)
proto = MOUSE_PROTO_GPM;
xfree(realdev);
/*
* If the protocol can't be guessed from the device name,
* try to characterise it.
*/
if (proto == MOUSE_PROTO_UNKNOWN) {
SYSCALL (fd = open(dev, O_RDWR | O_NONBLOCK | O_EXCL));
if (isatty(fd)) {
/* Serial PnP has already failed, so give up. */
} else {
if (fstat(fd, &sbuf) != 0) {
#ifdef DEBUG
ErrorF("fstat failed for %s (%s)\n", dev, strerror(errno));
#endif
close(fd);
return NULL;
}
if (S_ISFIFO(sbuf.st_mode)) {
/* Assume GPM data in MSC format. */
proto = MOUSE_PROTO_MSC;
} else {
/* Default to PS/2 */
proto = MOUSE_PROTO_PS2;
}
}
close(fd);
}
if (proto == MOUSE_PROTO_UNKNOWN) {
xf86Msg(X_ERROR, "%s: GuessProtocol: Cannot find mouse protocol.\n",
pInfo->name);
return NULL;
} else {
for (i = 0; i < sizeof(devproto)/sizeof(devproto[0]); i++) {
if (devproto[i].proto == proto) {
xf86Msg(X_INFO,
"%s: GuessProtocol: "
"setting mouse protocol to \"%s\"\n",
pInfo->name, devproto[i].name);
return devproto[i].name;
}
}
}
return NULL;
}
_X_EXPORT OSMouseInfoPtr
xf86OSMouseInit(int flags)
{
OSMouseInfoPtr p;
p = xcalloc(sizeof(OSMouseInfoRec), 1);
if (!p)
return NULL;
p->SupportedInterfaces = SupportedInterfaces;
p->DefaultProtocol = DefaultProtocol;
p->FindDevice = FindDevice;
p->GuessProtocol = GuessProtocol;
return p;
}