1/* 2 * Copyright (c) 1999-2001 Vojtech Pavlik 3 */ 4 5/* 6 * Serial mouse driver for Linux 7 */ 8 9/* 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * 24 * Should you need to contact me, the author, you can do so either by 25 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: 26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic 27 */ 28 29#include <linux/delay.h> 30#include <linux/module.h> 31#include <linux/slab.h> 32#include <linux/interrupt.h> 33#include <linux/input.h> 34#include <linux/serio.h> 35 36#define DRIVER_DESC "Serial mouse driver" 37 38MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 39MODULE_DESCRIPTION(DRIVER_DESC); 40MODULE_LICENSE("GPL"); 41 42static const char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse", 43 "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse", 44 "Logitech MZ++ Mouse"}; 45 46struct sermouse { 47 struct input_dev *dev; 48 signed char buf[8]; 49 unsigned char count; 50 unsigned char type; 51 unsigned long last; 52 char phys[32]; 53}; 54 55/* 56 * sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and 57 * applies some prediction to the data, resulting in 96 updates per 58 * second, which is as good as a PS/2 or USB mouse. 59 */ 60 61static void sermouse_process_msc(struct sermouse *sermouse, signed char data) 62{ 63 struct input_dev *dev = sermouse->dev; 64 signed char *buf = sermouse->buf; 65 66 switch (sermouse->count) { 67 68 case 0: 69 if ((data & 0xf8) != 0x80) 70 return; 71 input_report_key(dev, BTN_LEFT, !(data & 4)); 72 input_report_key(dev, BTN_RIGHT, !(data & 1)); 73 input_report_key(dev, BTN_MIDDLE, !(data & 2)); 74 break; 75 76 case 1: 77 case 3: 78 input_report_rel(dev, REL_X, data / 2); 79 input_report_rel(dev, REL_Y, -buf[1]); 80 buf[0] = data - data / 2; 81 break; 82 83 case 2: 84 case 4: 85 input_report_rel(dev, REL_X, buf[0]); 86 input_report_rel(dev, REL_Y, buf[1] - data); 87 buf[1] = data / 2; 88 break; 89 } 90 91 input_sync(dev); 92 93 if (++sermouse->count == 5) 94 sermouse->count = 0; 95} 96 97/* 98 * sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and 99 * generates events. With prediction it gets 80 updates/sec, assuming 100 * standard 3-byte packets and 1200 bps. 101 */ 102 103static void sermouse_process_ms(struct sermouse *sermouse, signed char data) 104{ 105 struct input_dev *dev = sermouse->dev; 106 signed char *buf = sermouse->buf; 107 108 if (data & 0x40) 109 sermouse->count = 0; 110 else if (sermouse->count == 0) 111 return; 112 113 switch (sermouse->count) { 114 115 case 0: 116 buf[1] = data; 117 input_report_key(dev, BTN_LEFT, (data >> 5) & 1); 118 input_report_key(dev, BTN_RIGHT, (data >> 4) & 1); 119 break; 120 121 case 1: 122 buf[2] = data; 123 data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f)); 124 input_report_rel(dev, REL_X, data / 2); 125 input_report_rel(dev, REL_Y, buf[4]); 126 buf[3] = data - data / 2; 127 break; 128 129 case 2: 130 /* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */ 131 if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1])) 132 input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key)); 133 buf[0] = buf[1]; 134 135 data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f)); 136 input_report_rel(dev, REL_X, buf[3]); 137 input_report_rel(dev, REL_Y, data - buf[4]); 138 buf[4] = data / 2; 139 break; 140 141 case 3: 142 143 switch (sermouse->type) { 144 145 case SERIO_MS: 146 sermouse->type = SERIO_MP; 147 148 case SERIO_MP: 149 if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */ 150 input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1); 151 input_report_key(dev, BTN_SIDE, (data >> 4) & 1); 152 break; 153 154 case SERIO_MZP: 155 case SERIO_MZPP: 156 input_report_key(dev, BTN_SIDE, (data >> 5) & 1); 157 158 case SERIO_MZ: 159 input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1); 160 input_report_rel(dev, REL_WHEEL, (data & 8) - (data & 7)); 161 break; 162 } 163 164 break; 165 166 case 4: 167 case 6: /* MZ++ packet type. We can get these bytes for M++ too but we ignore them later. */ 168 buf[1] = (data >> 2) & 0x0f; 169 break; 170 171 case 5: 172 case 7: /* Ignore anything besides MZ++ */ 173 if (sermouse->type != SERIO_MZPP) 174 break; 175 176 switch (buf[1]) { 177 178 case 1: /* Extra mouse info */ 179 180 input_report_key(dev, BTN_SIDE, (data >> 4) & 1); 181 input_report_key(dev, BTN_EXTRA, (data >> 5) & 1); 182 input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8)); 183 184 break; 185 186 default: /* We don't decode anything else yet. */ 187 188 printk(KERN_WARNING 189 "sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]); 190 break; 191 } 192 193 break; 194 } 195 196 input_sync(dev); 197 198 sermouse->count++; 199} 200 201/* 202 * sermouse_interrupt() handles incoming characters, either gathering them into 203 * packets or passing them to the command routine as command output. 204 */ 205 206static irqreturn_t sermouse_interrupt(struct serio *serio, 207 unsigned char data, unsigned int flags) 208{ 209 struct sermouse *sermouse = serio_get_drvdata(serio); 210 211 if (time_after(jiffies, sermouse->last + HZ/10)) 212 sermouse->count = 0; 213 214 sermouse->last = jiffies; 215 216 if (sermouse->type > SERIO_SUN) 217 sermouse_process_ms(sermouse, data); 218 else 219 sermouse_process_msc(sermouse, data); 220 221 return IRQ_HANDLED; 222} 223 224/* 225 * sermouse_disconnect() cleans up after we don't want talk 226 * to the mouse anymore. 227 */ 228 229static void sermouse_disconnect(struct serio *serio) 230{ 231 struct sermouse *sermouse = serio_get_drvdata(serio); 232 233 serio_close(serio); 234 serio_set_drvdata(serio, NULL); 235 input_unregister_device(sermouse->dev); 236 kfree(sermouse); 237} 238 239/* 240 * sermouse_connect() is a callback form the serio module when 241 * an unhandled serio port is found. 242 */ 243 244static int sermouse_connect(struct serio *serio, struct serio_driver *drv) 245{ 246 struct sermouse *sermouse; 247 struct input_dev *input_dev; 248 unsigned char c = serio->id.extra; 249 int err = -ENOMEM; 250 251 sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL); 252 input_dev = input_allocate_device(); 253 if (!sermouse || !input_dev) 254 goto fail1; 255 256 sermouse->dev = input_dev; 257 snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys); 258 sermouse->type = serio->id.proto; 259 260 input_dev->name = sermouse_protocols[sermouse->type]; 261 input_dev->phys = sermouse->phys; 262 input_dev->id.bustype = BUS_RS232; 263 input_dev->id.vendor = sermouse->type; 264 input_dev->id.product = c; 265 input_dev->id.version = 0x0100; 266 input_dev->dev.parent = &serio->dev; 267 268 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 269 input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | 270 BIT_MASK(BTN_RIGHT); 271 input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); 272 273 if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit); 274 if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit); 275 if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit); 276 if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit); 277 if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit); 278 279 serio_set_drvdata(serio, sermouse); 280 281 err = serio_open(serio, drv); 282 if (err) 283 goto fail2; 284 285 err = input_register_device(sermouse->dev); 286 if (err) 287 goto fail3; 288 289 return 0; 290 291 fail3: serio_close(serio); 292 fail2: serio_set_drvdata(serio, NULL); 293 fail1: input_free_device(input_dev); 294 kfree(sermouse); 295 return err; 296} 297 298static struct serio_device_id sermouse_serio_ids[] = { 299 { 300 .type = SERIO_RS232, 301 .proto = SERIO_MSC, 302 .id = SERIO_ANY, 303 .extra = SERIO_ANY, 304 }, 305 { 306 .type = SERIO_RS232, 307 .proto = SERIO_SUN, 308 .id = SERIO_ANY, 309 .extra = SERIO_ANY, 310 }, 311 { 312 .type = SERIO_RS232, 313 .proto = SERIO_MS, 314 .id = SERIO_ANY, 315 .extra = SERIO_ANY, 316 }, 317 { 318 .type = SERIO_RS232, 319 .proto = SERIO_MP, 320 .id = SERIO_ANY, 321 .extra = SERIO_ANY, 322 }, 323 { 324 .type = SERIO_RS232, 325 .proto = SERIO_MZ, 326 .id = SERIO_ANY, 327 .extra = SERIO_ANY, 328 }, 329 { 330 .type = SERIO_RS232, 331 .proto = SERIO_MZP, 332 .id = SERIO_ANY, 333 .extra = SERIO_ANY, 334 }, 335 { 336 .type = SERIO_RS232, 337 .proto = SERIO_MZPP, 338 .id = SERIO_ANY, 339 .extra = SERIO_ANY, 340 }, 341 { 0 } 342}; 343 344MODULE_DEVICE_TABLE(serio, sermouse_serio_ids); 345 346static struct serio_driver sermouse_drv = { 347 .driver = { 348 .name = "sermouse", 349 }, 350 .description = DRIVER_DESC, 351 .id_table = sermouse_serio_ids, 352 .interrupt = sermouse_interrupt, 353 .connect = sermouse_connect, 354 .disconnect = sermouse_disconnect, 355}; 356 357module_serio_driver(sermouse_drv); 358