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" 14bd3a1963Smrg#include "mouse.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 32a73597f9Smrg#define DEFAULT_MOUSE_DEV "/dev/input/mice" 33a73597f9Smrg#define DEFAULT_PS2_DEV "/dev/psaux" 34a73597f9Smrg#define DEFAULT_GPM_DATA_DEV "/dev/gpmdata" 35a73597f9Smrg#define DEFAULT_GPM_CTL_DEV "/dev/gpmdata" 366aab59a7Smrg 376aab59a7Smrgstatic const char *mouseDevs[] = { 38a73597f9Smrg DEFAULT_MOUSE_DEV, 39a73597f9Smrg DEFAULT_PS2_DEV, 40a73597f9Smrg DEFAULT_GPM_DATA_DEV, 41a73597f9Smrg NULL 426aab59a7Smrg}; 436aab59a7Smrg 446aab59a7Smrgtypedef enum { 45a73597f9Smrg MOUSE_PROTO_UNKNOWN = 0, 46a73597f9Smrg MOUSE_PROTO_SERIAL, 47a73597f9Smrg MOUSE_PROTO_PS2, 48a73597f9Smrg MOUSE_PROTO_MSC, 49a73597f9Smrg MOUSE_PROTO_GPM, 50a73597f9Smrg MOUSE_PROTO_EXPPS2, 516aab59a7Smrg} protocolTypes; 526aab59a7Smrg 536aab59a7Smrgstatic struct { 54a73597f9Smrg protocolTypes proto; 55a73597f9Smrg const char *name; 566aab59a7Smrg} devproto[] = { 57a73597f9Smrg { MOUSE_PROTO_UNKNOWN, NULL }, 58a73597f9Smrg { MOUSE_PROTO_PS2, "PS/2" }, 59a73597f9Smrg { MOUSE_PROTO_MSC, "MouseSystems" }, 60a73597f9Smrg { MOUSE_PROTO_GPM, "GPM" }, 61a73597f9Smrg { 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++) { 71a73597f9Smrg SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK | O_EXCL)); 72a73597f9Smrg if (fd == -1) { 736aab59a7Smrg#ifdef DEBUG 74a73597f9Smrg ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno)); 756aab59a7Smrg#endif 76a73597f9Smrg } else 77a73597f9Smrg break; 786aab59a7Smrg } 796aab59a7Smrg 806aab59a7Smrg if (*pdev) { 81a73597f9Smrg close(fd); 82a73597f9Smrg /* Set the Device option. */ 83a73597f9Smrg pInfo->options = 84a73597f9Smrg xf86AddNewOption(pInfo->options, "Device", *pdev); 85a73597f9Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 86a73597f9Smrg 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 102bd3a1963Smrg dev = xf86SetStrOption(pInfo->options, "Device", NULL); 1036aab59a7Smrg if (!dev) { 1046aab59a7Smrg#ifdef DEBUG 105a73597f9Smrg ErrorF("xf86SetStrOption failed to return the device name\n"); 1066aab59a7Smrg#endif 107a73597f9Smrg return NULL; 1086aab59a7Smrg } 1096aab59a7Smrg /* Look at the device name to guess the protocol. */ 1106aab59a7Smrg realdev = NULL; 1116aab59a7Smrg if (strcmp(dev, DEFAULT_MOUSE_DEV) == 0) { 112a73597f9Smrg if (lstat(dev, &sbuf) != 0) { 1136aab59a7Smrg#ifdef DEBUG 114a73597f9Smrg ErrorF("lstat failed for %s (%s)\n", dev, strerror(errno)); 1156aab59a7Smrg#endif 116a73597f9Smrg return NULL; 117a73597f9Smrg } 118a73597f9Smrg if (S_ISLNK(sbuf.st_mode)) { 119a73597f9Smrg realdev = xnfalloc(PATH_MAX + 1); 120a73597f9Smrg i = readlink(dev, realdev, PATH_MAX); 121a73597f9Smrg if (i <= 0) { 1226aab59a7Smrg#ifdef DEBUG 123a73597f9Smrg ErrorF("readlink failed for %s (%s)\n", dev, strerror(errno)); 1246aab59a7Smrg#endif 125a73597f9Smrg free(realdev); 126a73597f9Smrg return NULL; 127a73597f9Smrg } 128a73597f9Smrg realdev[i] = '\0'; 129a73597f9Smrg } 1306aab59a7Smrg } 1316aab59a7Smrg if (!realdev) 132a73597f9Smrg realdev = xnfstrdup(dev); 1336aab59a7Smrg else { 134a73597f9Smrg /* If realdev doesn't contain a '/' then prepend "/dev/" */ 135a73597f9Smrg if (!strchr(realdev, '/')) { 136a73597f9Smrg char *tmp = xnfalloc(strlen(realdev) + 5 + 1); 137a73597f9Smrg sprintf(tmp, "/dev/%s", realdev); 138a73597f9Smrg free(realdev); 139a73597f9Smrg realdev = tmp; 140a73597f9Smrg } 1416aab59a7Smrg } 1426aab59a7Smrg 1436aab59a7Smrg if (strcmp(realdev, DEFAULT_MOUSE_DEV) == 0) 144a73597f9Smrg proto = MOUSE_PROTO_EXPPS2; 1456aab59a7Smrg else if (strcmp(realdev, DEFAULT_PS2_DEV) == 0) 146a73597f9Smrg proto = MOUSE_PROTO_EXPPS2; 1476aab59a7Smrg else if (strcmp(realdev, DEFAULT_GPM_DATA_DEV) == 0) 148a73597f9Smrg proto = MOUSE_PROTO_MSC; 1496aab59a7Smrg else if (strcmp(realdev, DEFAULT_GPM_CTL_DEV) == 0) 150a73597f9Smrg proto = MOUSE_PROTO_GPM; 151bd3a1963Smrg free(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) { 157a73597f9Smrg SYSCALL (fd = open(dev, O_RDWR | O_NONBLOCK | O_EXCL)); 158a73597f9Smrg if (isatty(fd)) { 159a73597f9Smrg /* Serial PnP has already failed, so give up. */ 160a73597f9Smrg } else { 161a73597f9Smrg if (fstat(fd, &sbuf) != 0) { 1626aab59a7Smrg#ifdef DEBUG 163a73597f9Smrg ErrorF("fstat failed for %s (%s)\n", dev, strerror(errno)); 1646aab59a7Smrg#endif 165a73597f9Smrg close(fd); 166a73597f9Smrg return NULL; 167a73597f9Smrg } 168a73597f9Smrg if (S_ISFIFO(sbuf.st_mode)) { 169a73597f9Smrg /* Assume GPM data in MSC format. */ 170a73597f9Smrg proto = MOUSE_PROTO_MSC; 171a73597f9Smrg } else { 172a73597f9Smrg /* Default to PS/2 */ 173a73597f9Smrg proto = MOUSE_PROTO_PS2; 174a73597f9Smrg } 175a73597f9Smrg } 176a73597f9Smrg close(fd); 1776aab59a7Smrg } 1786aab59a7Smrg if (proto == MOUSE_PROTO_UNKNOWN) { 179a73597f9Smrg xf86Msg(X_ERROR, "%s: Cannot find mouse protocol.\n", 180a73597f9Smrg pInfo->name); 181a73597f9Smrg return NULL; 1826aab59a7Smrg } else { 183a73597f9Smrg for (i = 0; i < sizeof(devproto)/sizeof(devproto[0]); i++) { 184a73597f9Smrg if (devproto[i].proto == proto) { 185a73597f9Smrg xf86Msg(X_INFO, 186a73597f9Smrg "%s: Setting mouse protocol to \"%s\"\n", 187a73597f9Smrg pInfo->name, devproto[i].name); 188a73597f9Smrg return devproto[i].name; 189a73597f9Smrg } 190a73597f9Smrg } 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 207bd3a1963SmrgOSMouseInfoPtr 208bd3a1963SmrgOSMouseInit(int flags) 2096aab59a7Smrg{ 2106aab59a7Smrg OSMouseInfoPtr p; 2116aab59a7Smrg 212bd3a1963Smrg p = calloc(sizeof(OSMouseInfoRec), 1); 2136aab59a7Smrg if (!p) 214a73597f9Smrg 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