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