1/* 2Copyright (c) 2001 by Juliusz Chroboczek 3Copyright (c) 1999 by Keith Packard 4 5Permission is hereby granted, free of charge, to any person obtaining a copy 6of this software and associated documentation files (the "Software"), to deal 7in the Software without restriction, including without limitation the rights 8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9copies of the Software, and to permit persons to whom the Software is 10furnished to do so, subject to the following conditions: 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21THE SOFTWARE. 22*/ 23 24#ifdef HAVE_CONFIG_H 25#include <kdrive-config.h> 26#endif 27#include <errno.h> 28#include <termios.h> 29#include <X11/X.h> 30#include <X11/Xproto.h> 31#include <X11/Xpoll.h> 32#include "inputstr.h" 33#include "scrnintstr.h" 34#include "kdrive.h" 35 36static int 37MsReadBytes (int fd, char *buf, int len, int min) 38{ 39 int n, tot; 40 fd_set set; 41 struct timeval tv; 42 43 tot = 0; 44 while (len) 45 { 46 n = read (fd, buf, len); 47 if (n > 0) 48 { 49 tot += n; 50 buf += n; 51 len -= n; 52 } 53 if (tot % min == 0) 54 break; 55 FD_ZERO (&set); 56 FD_SET (fd, &set); 57 tv.tv_sec = 0; 58 tv.tv_usec = 100 * 1000; 59 n = select (fd + 1, &set, 0, 0, &tv); 60 if (n <= 0) 61 break; 62 } 63 return tot; 64} 65 66static void 67MsRead (int port, void *closure) 68{ 69 unsigned char buf[3 * 200]; 70 unsigned char *b; 71 int n; 72 int dx, dy; 73 unsigned long flags; 74 75 while ((n = MsReadBytes (port, (char *) buf, sizeof (buf), 3)) > 0) 76 { 77 b = buf; 78 while (n >= 3) 79 { 80 flags = KD_MOUSE_DELTA; 81 82 if (b[0] & 0x20) 83 flags |= KD_BUTTON_1; 84 if (b[0] & 0x10) 85 flags |= KD_BUTTON_3; 86 87 dx = (char)(((b[0] & 0x03) << 6) | (b[1] & 0x3F)); 88 dy = (char)(((b[0] & 0x0C) << 4) | (b[2] & 0x3F)); 89 n -= 3; 90 b += 3; 91 KdEnqueuePointerEvent (closure, flags, dx, dy, 0); 92 } 93 } 94} 95 96static Status 97MsInit (KdPointerInfo *pi) 98{ 99 if (!pi) 100 return BadImplementation; 101 102 if (!pi->path || strcmp(pi->path, "auto")) 103 pi->path = strdup("/dev/mouse"); 104 if (!pi->name) 105 pi->name = strdup("Microsoft protocol mouse"); 106 107 return Success; 108} 109 110static Status 111MsEnable (KdPointerInfo *pi) 112{ 113 int port; 114 struct termios t; 115 int ret; 116 117 port = open (pi->path, O_RDWR | O_NONBLOCK); 118 if(port < 0) { 119 ErrorF("Couldn't open %s (%d)\n", pi->path, (int)errno); 120 return 0; 121 } else if (port == 0) { 122 ErrorF("Opening %s returned 0! Please complain to Keith.\n", 123 pi->path); 124 goto bail; 125 } 126 127 if(!isatty(port)) { 128 ErrorF("%s is not a tty\n", pi->path); 129 goto bail; 130 } 131 132 ret = tcgetattr(port, &t); 133 if(ret < 0) { 134 ErrorF("Couldn't tcgetattr(%s): %d\n", pi->path, errno); 135 goto bail; 136 } 137 t.c_iflag &= ~ (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | 138 IGNCR | ICRNL | IXON | IXOFF); 139 t.c_oflag &= ~ OPOST; 140 t.c_lflag &= ~ (ECHO | ECHONL | ICANON | ISIG | IEXTEN); 141 t.c_cflag &= ~ (CSIZE | PARENB); 142 t.c_cflag |= CS8 | CLOCAL | CSTOPB; 143 144 cfsetispeed (&t, B1200); 145 cfsetospeed (&t, B1200); 146 t.c_cc[VMIN] = 1; 147 t.c_cc[VTIME] = 0; 148 ret = tcsetattr(port, TCSANOW, &t); 149 if(ret < 0) { 150 ErrorF("Couldn't tcsetattr(%s): %d\n", pi->path, errno); 151 goto bail; 152 } 153 if (KdRegisterFd (port, MsRead, pi)) 154 return TRUE; 155 pi->driverPrivate = (void *)(intptr_t)port; 156 157 return Success; 158 159 bail: 160 close(port); 161 return BadMatch; 162} 163 164static void 165MsDisable (KdPointerInfo *pi) 166{ 167 KdUnregisterFd (pi, (int)(intptr_t)pi->driverPrivate, TRUE); 168} 169 170static void 171MsFini (KdPointerInfo *pi) 172{ 173} 174 175KdPointerDriver MsMouseDriver = { 176 "ms", 177 MsInit, 178 MsEnable, 179 MsDisable, 180 MsFini, 181 NULL, 182}; 183