1/* 2 * Copyright � 1999 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Keith Packard not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Keith Packard makes no 11 * representations about the suitability of this software for any purpose. It 12 * is provided "as is" without express or implied warranty. 13 * 14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include <kdrive-config.h> 25#endif 26#include <X11/X.h> 27#include <X11/Xproto.h> 28#include <X11/Xpoll.h> 29#include "inputstr.h" 30#include "scrnintstr.h" 31#include "kdrive.h" 32 33static int 34Ps2ReadBytes (int fd, char *buf, int len, int min) 35{ 36 int n, tot; 37 fd_set set; 38 struct timeval tv; 39 40 tot = 0; 41 while (len) 42 { 43 n = read (fd, buf, len); 44 if (n > 0) 45 { 46 tot += n; 47 buf += n; 48 len -= n; 49 } 50 if (tot % min == 0) 51 break; 52 FD_ZERO (&set); 53 FD_SET (fd, &set); 54 tv.tv_sec = 0; 55 tv.tv_usec = 100 * 1000; 56 n = select (fd + 1, &set, 0, 0, &tv); 57 if (n <= 0) 58 break; 59 } 60 return tot; 61} 62 63char *Ps2Names[] = { 64 "/dev/psaux", 65/* "/dev/mouse", */ 66 "/dev/input/mice", 67}; 68 69#define NUM_PS2_NAMES (sizeof (Ps2Names) / sizeof (Ps2Names[0])) 70 71static void 72Ps2Read (int ps2Port, void *closure) 73{ 74 unsigned char buf[3 * 200]; 75 unsigned char *b; 76 int n; 77 int dx, dy; 78 unsigned long flags; 79 unsigned long left_button = KD_BUTTON_1; 80 unsigned long right_button = KD_BUTTON_3; 81 82#undef SWAP_USB 83#ifdef SWAP_USB 84 if (id == 2) 85 { 86 left_button = KD_BUTTON_3; 87 right_button = KD_BUTTON_1; 88 } 89#endif 90 while ((n = Ps2ReadBytes (ps2Port, (char *) buf, sizeof (buf), 3)) > 0) 91 { 92 b = buf; 93 while (n >= 3) 94 { 95 flags = KD_MOUSE_DELTA; 96 if (b[0] & 4) 97 flags |= KD_BUTTON_2; 98 if (b[0] & 2) 99 flags |= right_button; 100 if (b[0] & 1) 101 flags |= left_button; 102 103 dx = b[1]; 104 if (b[0] & 0x10) 105 dx -= 256; 106 dy = b[2]; 107 if (b[0] & 0x20) 108 dy -= 256; 109 dy = -dy; 110 n -= 3; 111 b += 3; 112 KdEnqueuePointerEvent (closure, flags, dx, dy, 0); 113 } 114 } 115} 116 117static Status 118Ps2Init (KdPointerInfo *pi) 119{ 120 int ps2Port, i; 121 122 if (!pi->path) { 123 for (i = 0; i < NUM_PS2_NAMES; i++) { 124 ps2Port = open (Ps2Names[i], 0); 125 if (ps2Port >= 0) { 126 pi->path = strdup (Ps2Names[i]); 127 break; 128 } 129 } 130 } 131 else { 132 ps2Port = open (pi->path, 0); 133 } 134 135 if (ps2Port < 0) 136 return BadMatch; 137 138 close(ps2Port); 139 if (!pi->name) 140 pi->name = strdup ("PS/2 Mouse"); 141 142 return Success; 143} 144 145static Status 146Ps2Enable (KdPointerInfo *pi) 147{ 148 int fd; 149 150 if (!pi) 151 return BadImplementation; 152 153 fd = open (pi->path, 0); 154 if (fd < 0) 155 return BadMatch; 156 157 if (!KdRegisterFd (fd, Ps2Read, pi)) { 158 close(fd); 159 return BadAlloc; 160 } 161 162 pi->driverPrivate = (void *)(intptr_t)fd; 163 164 return Success; 165} 166 167 168static void 169Ps2Disable (KdPointerInfo *pi) 170{ 171 KdUnregisterFd (pi, (int)(intptr_t)pi->driverPrivate, TRUE); 172} 173 174static void 175Ps2Fini (KdPointerInfo *pi) 176{ 177} 178 179KdPointerDriver Ps2MouseDriver = { 180 "ps2", 181 Ps2Init, 182 Ps2Enable, 183 Ps2Disable, 184 Ps2Fini, 185 NULL, 186}; 187