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