lnx_mouse.c revision b73be646
16aab59a7Smrg
26aab59a7Smrg/*
36aab59a7Smrg * Copyright 1999 by The XFree86 Project, Inc.
46aab59a7Smrg */
56aab59a7Smrg
66aab59a7Smrg#ifdef HAVE_CONFIG_H
76aab59a7Smrg#include "config.h"
86aab59a7Smrg#endif
96aab59a7Smrg
10b73be646Smrg#include <xorg-server.h>
116aab59a7Smrg#include <X11/X.h>
126aab59a7Smrg#include "xf86.h"
136aab59a7Smrg#include "xf86Xinput.h"
146aab59a7Smrg#include "xf86OSmouse.h"
156aab59a7Smrg#include "xf86_OSlib.h"
166aab59a7Smrg#include <sys/types.h>
176aab59a7Smrg#include <sys/stat.h>
186aab59a7Smrg#include <unistd.h>
196aab59a7Smrg
206aab59a7Smrgstatic int
216aab59a7SmrgSupportedInterfaces(void)
226aab59a7Smrg{
236aab59a7Smrg    return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO;
246aab59a7Smrg}
256aab59a7Smrg
266aab59a7Smrgstatic const char *
276aab59a7SmrgDefaultProtocol(void)
286aab59a7Smrg{
296aab59a7Smrg    return "Auto";
306aab59a7Smrg}
316aab59a7Smrg
326aab59a7Smrg#define DEFAULT_MOUSE_DEV		"/dev/input/mice"
336aab59a7Smrg#define DEFAULT_PS2_DEV			"/dev/psaux"
346aab59a7Smrg#define DEFAULT_GPM_DATA_DEV		"/dev/gpmdata"
356aab59a7Smrg#define DEFAULT_GPM_CTL_DEV		"/dev/gpmdata"
366aab59a7Smrg
376aab59a7Smrgstatic const char *mouseDevs[] = {
386aab59a7Smrg	DEFAULT_MOUSE_DEV,
396aab59a7Smrg	DEFAULT_PS2_DEV,
406aab59a7Smrg	DEFAULT_GPM_DATA_DEV,
416aab59a7Smrg	NULL
426aab59a7Smrg};
436aab59a7Smrg
446aab59a7Smrgtypedef enum {
456aab59a7Smrg	MOUSE_PROTO_UNKNOWN = 0,
466aab59a7Smrg	MOUSE_PROTO_SERIAL,
476aab59a7Smrg	MOUSE_PROTO_PS2,
486aab59a7Smrg	MOUSE_PROTO_MSC,
496aab59a7Smrg	MOUSE_PROTO_GPM,
506aab59a7Smrg	MOUSE_PROTO_EXPPS2,
516aab59a7Smrg} protocolTypes;
526aab59a7Smrg
536aab59a7Smrgstatic struct {
546aab59a7Smrg	protocolTypes proto;
556aab59a7Smrg	const char *name;
566aab59a7Smrg} devproto[] = {
576aab59a7Smrg	{ MOUSE_PROTO_UNKNOWN,	NULL },
586aab59a7Smrg	{ MOUSE_PROTO_PS2,	"PS/2" },
596aab59a7Smrg	{ MOUSE_PROTO_MSC,	"MouseSystems" },
606aab59a7Smrg	{ MOUSE_PROTO_GPM,	"GPM" },
616aab59a7Smrg	{ MOUSE_PROTO_EXPPS2,   "ExplorerPS/2" },
626aab59a7Smrg};
636aab59a7Smrg
646aab59a7Smrgstatic const char *
656aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
666aab59a7Smrg{
676aab59a7Smrg    int fd = -1;
686aab59a7Smrg    const char **pdev;
696aab59a7Smrg
706aab59a7Smrg    for (pdev = mouseDevs; *pdev; pdev++) {
716aab59a7Smrg	SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK | O_EXCL));
726aab59a7Smrg	if (fd == -1) {
736aab59a7Smrg#ifdef DEBUG
746aab59a7Smrg	    ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno));
756aab59a7Smrg#endif
766aab59a7Smrg	} else
776aab59a7Smrg	    break;
786aab59a7Smrg    }
796aab59a7Smrg
806aab59a7Smrg    if (*pdev) {
816aab59a7Smrg	close(fd);
826aab59a7Smrg	/* Set the Device option. */
836aab59a7Smrg	pInfo->conf_idev->commonOptions =
846aab59a7Smrg	    xf86AddNewOption(pInfo->conf_idev->commonOptions, "Device", *pdev);
856aab59a7Smrg	xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n",
866aab59a7Smrg		pInfo->name, *pdev);
876aab59a7Smrg    }
886aab59a7Smrg
896aab59a7Smrg    return *pdev;
906aab59a7Smrg}
916aab59a7Smrg
926aab59a7Smrgstatic const char *
936aab59a7SmrglnxMouseMagic(InputInfoPtr pInfo)
946aab59a7Smrg{
956aab59a7Smrg    int fd = -1;
966aab59a7Smrg    const char *dev;
976aab59a7Smrg    char *realdev;
986aab59a7Smrg    struct stat sbuf;
996aab59a7Smrg    int i;
1006aab59a7Smrg    int proto = MOUSE_PROTO_UNKNOWN;
1016aab59a7Smrg
1026aab59a7Smrg    dev = xf86SetStrOption(pInfo->conf_idev->commonOptions, "Device", NULL);
1036aab59a7Smrg    if (!dev) {
1046aab59a7Smrg#ifdef DEBUG
1056aab59a7Smrg	ErrorF("xf86SetStrOption failed to return the device name\n");
1066aab59a7Smrg#endif
1076aab59a7Smrg	return NULL;
1086aab59a7Smrg    }
1096aab59a7Smrg    /* Look at the device name to guess the protocol. */
1106aab59a7Smrg    realdev = NULL;
1116aab59a7Smrg    if (strcmp(dev, DEFAULT_MOUSE_DEV) == 0) {
1126aab59a7Smrg	if (lstat(dev, &sbuf) != 0) {
1136aab59a7Smrg#ifdef DEBUG
1146aab59a7Smrg	    ErrorF("lstat failed for %s (%s)\n", dev, strerror(errno));
1156aab59a7Smrg#endif
1166aab59a7Smrg	    return NULL;
1176aab59a7Smrg	}
1186aab59a7Smrg	if (S_ISLNK(sbuf.st_mode)) {
1196aab59a7Smrg	    realdev = xnfalloc(PATH_MAX + 1);
1206aab59a7Smrg	    i = readlink(dev, realdev, PATH_MAX);
1216aab59a7Smrg	    if (i <= 0) {
1226aab59a7Smrg#ifdef DEBUG
1236aab59a7Smrg		ErrorF("readlink failed for %s (%s)\n", dev, strerror(errno));
1246aab59a7Smrg#endif
1256aab59a7Smrg		xfree(realdev);
1266aab59a7Smrg		return NULL;
1276aab59a7Smrg	    }
1286aab59a7Smrg	    realdev[i] = '\0';
1296aab59a7Smrg	}
1306aab59a7Smrg    }
1316aab59a7Smrg    if (!realdev)
1326aab59a7Smrg	realdev = xnfstrdup(dev);
1336aab59a7Smrg    else {
1346aab59a7Smrg	/* If realdev doesn't contain a '/' then prepend "/dev/" */
1356aab59a7Smrg	if (!strchr(realdev, '/')) {
1366aab59a7Smrg	    char *tmp = xnfalloc(strlen(realdev) + 5 + 1);
1376aab59a7Smrg	    sprintf(tmp, "/dev/%s", realdev);
1386aab59a7Smrg	    xfree(realdev);
1396aab59a7Smrg	    realdev = tmp;
1406aab59a7Smrg	}
1416aab59a7Smrg    }
1426aab59a7Smrg
1436aab59a7Smrg    if (strcmp(realdev, DEFAULT_MOUSE_DEV) == 0)
1446aab59a7Smrg	proto = MOUSE_PROTO_EXPPS2;
1456aab59a7Smrg    else if (strcmp(realdev, DEFAULT_PS2_DEV) == 0)
1466aab59a7Smrg	proto = MOUSE_PROTO_EXPPS2;
1476aab59a7Smrg    else if (strcmp(realdev, DEFAULT_GPM_DATA_DEV) == 0)
1486aab59a7Smrg	proto = MOUSE_PROTO_MSC;
1496aab59a7Smrg    else if (strcmp(realdev, DEFAULT_GPM_CTL_DEV) == 0)
1506aab59a7Smrg	proto = MOUSE_PROTO_GPM;
1516aab59a7Smrg    xfree(realdev);
1526aab59a7Smrg    /*
1536aab59a7Smrg     * If the protocol can't be guessed from the device name,
1546aab59a7Smrg     * try to characterise it.
1556aab59a7Smrg     */
1566aab59a7Smrg    if (proto == MOUSE_PROTO_UNKNOWN) {
1576aab59a7Smrg	SYSCALL (fd = open(dev, O_RDWR | O_NONBLOCK | O_EXCL));
1586aab59a7Smrg	if (isatty(fd)) {
1596aab59a7Smrg	    /* Serial PnP has already failed, so give up. */
1606aab59a7Smrg	} else {
1616aab59a7Smrg	    if (fstat(fd, &sbuf) != 0) {
1626aab59a7Smrg#ifdef DEBUG
1636aab59a7Smrg		ErrorF("fstat failed for %s (%s)\n", dev, strerror(errno));
1646aab59a7Smrg#endif
1656aab59a7Smrg		close(fd);
1666aab59a7Smrg		return NULL;
1676aab59a7Smrg	    }
1686aab59a7Smrg	    if (S_ISFIFO(sbuf.st_mode)) {
1696aab59a7Smrg		/* Assume GPM data in MSC format. */
1706aab59a7Smrg		proto = MOUSE_PROTO_MSC;
1716aab59a7Smrg	    } else {
1726aab59a7Smrg		/* Default to PS/2 */
1736aab59a7Smrg		proto = MOUSE_PROTO_PS2;
1746aab59a7Smrg	    }
1756aab59a7Smrg	}
1766aab59a7Smrg	close(fd);
1776aab59a7Smrg    }
1786aab59a7Smrg    if (proto == MOUSE_PROTO_UNKNOWN) {
1796aab59a7Smrg	xf86Msg(X_ERROR, "%s: Cannot find mouse protocol.\n",
1806aab59a7Smrg		pInfo->name);
1816aab59a7Smrg	return NULL;
1826aab59a7Smrg    } else {
1836aab59a7Smrg	for (i = 0; i < sizeof(devproto)/sizeof(devproto[0]); i++) {
1846aab59a7Smrg	    if (devproto[i].proto == proto) {
1856aab59a7Smrg		xf86Msg(X_INFO,
1866aab59a7Smrg			"%s: Setting mouse protocol to \"%s\"\n",
1876aab59a7Smrg			pInfo->name, devproto[i].name);
1886aab59a7Smrg		return devproto[i].name;
1896aab59a7Smrg	    }
1906aab59a7Smrg	}
1916aab59a7Smrg    }
1926aab59a7Smrg    return NULL;
1936aab59a7Smrg}
1946aab59a7Smrg
1956aab59a7Smrgstatic const char *
1966aab59a7SmrgGuessProtocol(InputInfoPtr pInfo, int flags)
1976aab59a7Smrg{
1986aab59a7Smrg    return lnxMouseMagic(pInfo);
1996aab59a7Smrg}
2006aab59a7Smrg
2016aab59a7Smrgstatic const char *
2026aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara)
2036aab59a7Smrg{
2046aab59a7Smrg    return lnxMouseMagic(pInfo);
2056aab59a7Smrg}
2066aab59a7Smrg
2076aab59a7Smrg_X_EXPORT OSMouseInfoPtr
2086aab59a7Smrgxf86OSMouseInit(int flags)
2096aab59a7Smrg{
2106aab59a7Smrg    OSMouseInfoPtr p;
2116aab59a7Smrg
2126aab59a7Smrg    p = xcalloc(sizeof(OSMouseInfoRec), 1);
2136aab59a7Smrg    if (!p)
2146aab59a7Smrg	return NULL;
2156aab59a7Smrg    p->SupportedInterfaces = SupportedInterfaces;
2166aab59a7Smrg    p->DefaultProtocol = DefaultProtocol;
2176aab59a7Smrg    p->FindDevice = FindDevice;
2186aab59a7Smrg    p->GuessProtocol = GuessProtocol;
2196aab59a7Smrg    p->SetupAuto = SetupAuto;
2206aab59a7Smrg    return p;
2216aab59a7Smrg}
2226aab59a7Smrg
223