222 lines
4.8 KiB
C
222 lines
4.8 KiB
C
|
|
/*
|
|
* 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/input/mice"
|
|
#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,
|
|
MOUSE_PROTO_EXPPS2,
|
|
} 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" },
|
|
{ MOUSE_PROTO_EXPPS2, "ExplorerPS/2" },
|
|
};
|
|
|
|
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 *
|
|
lnxMouseMagic(InputInfoPtr pInfo)
|
|
{
|
|
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_MOUSE_DEV) == 0)
|
|
proto = MOUSE_PROTO_EXPPS2;
|
|
else if (strcmp(realdev, DEFAULT_PS2_DEV) == 0)
|
|
proto = MOUSE_PROTO_EXPPS2;
|
|
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: 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: Setting mouse protocol to \"%s\"\n",
|
|
pInfo->name, devproto[i].name);
|
|
return devproto[i].name;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static const char *
|
|
GuessProtocol(InputInfoPtr pInfo, int flags)
|
|
{
|
|
return lnxMouseMagic(pInfo);
|
|
}
|
|
|
|
static const char *
|
|
SetupAuto(InputInfoPtr pInfo, int *protoPara)
|
|
{
|
|
return lnxMouseMagic(pInfo);
|
|
}
|
|
|
|
_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;
|
|
p->SetupAuto = SetupAuto;
|
|
return p;
|
|
}
|
|
|