1706f2543Smrg/* 2706f2543SmrgCopyright (c) 2001 by Juliusz Chroboczek 3706f2543SmrgCopyright (c) 1999 by Keith Packard 4706f2543Smrg 5706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy 6706f2543Smrgof this software and associated documentation files (the "Software"), to deal 7706f2543Smrgin the Software without restriction, including without limitation the rights 8706f2543Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9706f2543Smrgcopies of the Software, and to permit persons to whom the Software is 10706f2543Smrgfurnished to do so, subject to the following conditions: 11706f2543Smrg 12706f2543SmrgThe above copyright notice and this permission notice shall be included in 13706f2543Smrgall copies or substantial portions of the Software. 14706f2543Smrg 15706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18706f2543SmrgAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19706f2543SmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20706f2543SmrgOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21706f2543SmrgTHE SOFTWARE. 22706f2543Smrg*/ 23706f2543Smrg 24706f2543Smrg#ifdef HAVE_CONFIG_H 25706f2543Smrg#include <kdrive-config.h> 26706f2543Smrg#endif 27706f2543Smrg#include <errno.h> 28706f2543Smrg#include <termios.h> 29706f2543Smrg#include <X11/X.h> 30706f2543Smrg#include <X11/Xproto.h> 31706f2543Smrg#include <X11/Xpoll.h> 32706f2543Smrg#include "inputstr.h" 33706f2543Smrg#include "scrnintstr.h" 34706f2543Smrg#include "kdrive.h" 35706f2543Smrg 36706f2543Smrgstatic int 37706f2543SmrgMsReadBytes (int fd, char *buf, int len, int min) 38706f2543Smrg{ 39706f2543Smrg int n, tot; 40706f2543Smrg fd_set set; 41706f2543Smrg struct timeval tv; 42706f2543Smrg 43706f2543Smrg tot = 0; 44706f2543Smrg while (len) 45706f2543Smrg { 46706f2543Smrg n = read (fd, buf, len); 47706f2543Smrg if (n > 0) 48706f2543Smrg { 49706f2543Smrg tot += n; 50706f2543Smrg buf += n; 51706f2543Smrg len -= n; 52706f2543Smrg } 53706f2543Smrg if (tot % min == 0) 54706f2543Smrg break; 55706f2543Smrg FD_ZERO (&set); 56706f2543Smrg FD_SET (fd, &set); 57706f2543Smrg tv.tv_sec = 0; 58706f2543Smrg tv.tv_usec = 100 * 1000; 59706f2543Smrg n = select (fd + 1, &set, 0, 0, &tv); 60706f2543Smrg if (n <= 0) 61706f2543Smrg break; 62706f2543Smrg } 63706f2543Smrg return tot; 64706f2543Smrg} 65706f2543Smrg 66706f2543Smrgstatic void 67706f2543SmrgMsRead (int port, void *closure) 68706f2543Smrg{ 69706f2543Smrg unsigned char buf[3 * 200]; 70706f2543Smrg unsigned char *b; 71706f2543Smrg int n; 72706f2543Smrg int dx, dy; 73706f2543Smrg unsigned long flags; 74706f2543Smrg 75706f2543Smrg while ((n = MsReadBytes (port, (char *) buf, sizeof (buf), 3)) > 0) 76706f2543Smrg { 77706f2543Smrg b = buf; 78706f2543Smrg while (n >= 3) 79706f2543Smrg { 80706f2543Smrg flags = KD_MOUSE_DELTA; 81706f2543Smrg 82706f2543Smrg if (b[0] & 0x20) 83706f2543Smrg flags |= KD_BUTTON_1; 84706f2543Smrg if (b[0] & 0x10) 85706f2543Smrg flags |= KD_BUTTON_3; 86706f2543Smrg 87706f2543Smrg dx = (char)(((b[0] & 0x03) << 6) | (b[1] & 0x3F)); 88706f2543Smrg dy = (char)(((b[0] & 0x0C) << 4) | (b[2] & 0x3F)); 89706f2543Smrg n -= 3; 90706f2543Smrg b += 3; 91706f2543Smrg KdEnqueuePointerEvent (closure, flags, dx, dy, 0); 92706f2543Smrg } 93706f2543Smrg } 94706f2543Smrg} 95706f2543Smrg 96706f2543Smrgstatic Status 97706f2543SmrgMsInit (KdPointerInfo *pi) 98706f2543Smrg{ 99706f2543Smrg if (!pi) 100706f2543Smrg return BadImplementation; 101706f2543Smrg 102706f2543Smrg if (!pi->path || strcmp(pi->path, "auto")) 103706f2543Smrg pi->path = strdup("/dev/mouse"); 104706f2543Smrg if (!pi->name) 105706f2543Smrg pi->name = strdup("Microsoft protocol mouse"); 106706f2543Smrg 107706f2543Smrg return Success; 108706f2543Smrg} 109706f2543Smrg 110706f2543Smrgstatic Status 111706f2543SmrgMsEnable (KdPointerInfo *pi) 112706f2543Smrg{ 113706f2543Smrg int port; 114706f2543Smrg struct termios t; 115706f2543Smrg int ret; 116706f2543Smrg 117706f2543Smrg port = open (pi->path, O_RDWR | O_NONBLOCK); 118706f2543Smrg if(port < 0) { 119706f2543Smrg ErrorF("Couldn't open %s (%d)\n", pi->path, (int)errno); 120706f2543Smrg return 0; 121706f2543Smrg } else if (port == 0) { 122706f2543Smrg ErrorF("Opening %s returned 0! Please complain to Keith.\n", 123706f2543Smrg pi->path); 124706f2543Smrg goto bail; 125706f2543Smrg } 126706f2543Smrg 127706f2543Smrg if(!isatty(port)) { 128706f2543Smrg ErrorF("%s is not a tty\n", pi->path); 129706f2543Smrg goto bail; 130706f2543Smrg } 131706f2543Smrg 132706f2543Smrg ret = tcgetattr(port, &t); 133706f2543Smrg if(ret < 0) { 134706f2543Smrg ErrorF("Couldn't tcgetattr(%s): %d\n", pi->path, errno); 135706f2543Smrg goto bail; 136706f2543Smrg } 137706f2543Smrg t.c_iflag &= ~ (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | 138706f2543Smrg IGNCR | ICRNL | IXON | IXOFF); 139706f2543Smrg t.c_oflag &= ~ OPOST; 140706f2543Smrg t.c_lflag &= ~ (ECHO | ECHONL | ICANON | ISIG | IEXTEN); 141706f2543Smrg t.c_cflag &= ~ (CSIZE | PARENB); 142706f2543Smrg t.c_cflag |= CS8 | CLOCAL | CSTOPB; 143706f2543Smrg 144706f2543Smrg cfsetispeed (&t, B1200); 145706f2543Smrg cfsetospeed (&t, B1200); 146706f2543Smrg t.c_cc[VMIN] = 1; 147706f2543Smrg t.c_cc[VTIME] = 0; 148706f2543Smrg ret = tcsetattr(port, TCSANOW, &t); 149706f2543Smrg if(ret < 0) { 150706f2543Smrg ErrorF("Couldn't tcsetattr(%s): %d\n", pi->path, errno); 151706f2543Smrg goto bail; 152706f2543Smrg } 153706f2543Smrg if (KdRegisterFd (port, MsRead, pi)) 154706f2543Smrg return TRUE; 155706f2543Smrg pi->driverPrivate = (void *)(intptr_t)port; 156706f2543Smrg 157706f2543Smrg return Success; 158706f2543Smrg 159706f2543Smrg bail: 160706f2543Smrg close(port); 161706f2543Smrg return BadMatch; 162706f2543Smrg} 163706f2543Smrg 164706f2543Smrgstatic void 165706f2543SmrgMsDisable (KdPointerInfo *pi) 166706f2543Smrg{ 167706f2543Smrg KdUnregisterFd (pi, (int)(intptr_t)pi->driverPrivate, TRUE); 168706f2543Smrg} 169706f2543Smrg 170706f2543Smrgstatic void 171706f2543SmrgMsFini (KdPointerInfo *pi) 172706f2543Smrg{ 173706f2543Smrg} 174706f2543Smrg 175706f2543SmrgKdPointerDriver MsMouseDriver = { 176706f2543Smrg "ms", 177706f2543Smrg MsInit, 178706f2543Smrg MsEnable, 179706f2543Smrg MsDisable, 180706f2543Smrg MsFini, 181706f2543Smrg NULL, 182706f2543Smrg}; 183