Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) 1999-2001 Vojtech Pavlik
0004  */
0005 
0006 /*
0007  *  Serial mouse driver for Linux
0008  */
0009 
0010 /*
0011  */
0012 
0013 #include <linux/delay.h>
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/input.h>
0018 #include <linux/serio.h>
0019 
0020 #define DRIVER_DESC "Serial mouse driver"
0021 
0022 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0023 MODULE_DESCRIPTION(DRIVER_DESC);
0024 MODULE_LICENSE("GPL");
0025 
0026 static const char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
0027                     "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse",
0028                     "Logitech MZ++ Mouse"};
0029 
0030 struct sermouse {
0031     struct input_dev *dev;
0032     signed char buf[8];
0033     unsigned char count;
0034     unsigned char type;
0035     unsigned long last;
0036     char phys[32];
0037 };
0038 
0039 /*
0040  * sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and
0041  * applies some prediction to the data, resulting in 96 updates per
0042  * second, which is as good as a PS/2 or USB mouse.
0043  */
0044 
0045 static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
0046 {
0047     struct input_dev *dev = sermouse->dev;
0048     signed char *buf = sermouse->buf;
0049 
0050     switch (sermouse->count) {
0051 
0052         case 0:
0053             if ((data & 0xf8) != 0x80)
0054                 return;
0055             input_report_key(dev, BTN_LEFT,   !(data & 4));
0056             input_report_key(dev, BTN_RIGHT,  !(data & 1));
0057             input_report_key(dev, BTN_MIDDLE, !(data & 2));
0058             break;
0059 
0060         case 1:
0061         case 3:
0062             input_report_rel(dev, REL_X, data / 2);
0063             input_report_rel(dev, REL_Y, -buf[1]);
0064             buf[0] = data - data / 2;
0065             break;
0066 
0067         case 2:
0068         case 4:
0069             input_report_rel(dev, REL_X, buf[0]);
0070             input_report_rel(dev, REL_Y, buf[1] - data);
0071             buf[1] = data / 2;
0072             break;
0073     }
0074 
0075     input_sync(dev);
0076 
0077     if (++sermouse->count == 5)
0078         sermouse->count = 0;
0079 }
0080 
0081 /*
0082  * sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and
0083  * generates events. With prediction it gets 80 updates/sec, assuming
0084  * standard 3-byte packets and 1200 bps.
0085  */
0086 
0087 static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
0088 {
0089     struct input_dev *dev = sermouse->dev;
0090     signed char *buf = sermouse->buf;
0091 
0092     if (data & 0x40)
0093         sermouse->count = 0;
0094     else if (sermouse->count == 0)
0095         return;
0096 
0097     switch (sermouse->count) {
0098 
0099         case 0:
0100             buf[1] = data;
0101             input_report_key(dev, BTN_LEFT,   (data >> 5) & 1);
0102             input_report_key(dev, BTN_RIGHT,  (data >> 4) & 1);
0103             break;
0104 
0105         case 1:
0106             buf[2] = data;
0107             data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f));
0108             input_report_rel(dev, REL_X, data / 2);
0109             input_report_rel(dev, REL_Y, buf[4]);
0110             buf[3] = data - data / 2;
0111             break;
0112 
0113         case 2:
0114             /* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */
0115             if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1]))
0116                 input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key));
0117             buf[0] = buf[1];
0118 
0119             data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f));
0120             input_report_rel(dev, REL_X, buf[3]);
0121             input_report_rel(dev, REL_Y, data - buf[4]);
0122             buf[4] = data / 2;
0123             break;
0124 
0125         case 3:
0126 
0127             switch (sermouse->type) {
0128 
0129                 case SERIO_MS:
0130                     sermouse->type = SERIO_MP;
0131                     fallthrough;
0132 
0133                 case SERIO_MP:
0134                     if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */
0135                     input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1);
0136                     input_report_key(dev, BTN_SIDE,   (data >> 4) & 1);
0137                     break;
0138 
0139                 case SERIO_MZP:
0140                 case SERIO_MZPP:
0141                     input_report_key(dev, BTN_SIDE,   (data >> 5) & 1);
0142                     fallthrough;
0143 
0144                 case SERIO_MZ:
0145                     input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
0146                     input_report_rel(dev, REL_WHEEL,  (data & 8) - (data & 7));
0147                     break;
0148             }
0149 
0150             break;
0151 
0152         case 4:
0153         case 6: /* MZ++ packet type. We can get these bytes for M++ too but we ignore them later. */
0154             buf[1] = (data >> 2) & 0x0f;
0155             break;
0156 
0157         case 5:
0158         case 7: /* Ignore anything besides MZ++ */
0159             if (sermouse->type != SERIO_MZPP)
0160                 break;
0161 
0162             switch (buf[1]) {
0163 
0164                 case 1: /* Extra mouse info */
0165 
0166                     input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
0167                     input_report_key(dev, BTN_EXTRA, (data >> 5) & 1);
0168                     input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8));
0169 
0170                     break;
0171 
0172                 default: /* We don't decode anything else yet. */
0173 
0174                     printk(KERN_WARNING
0175                         "sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]);
0176                     break;
0177             }
0178 
0179             break;
0180     }
0181 
0182     input_sync(dev);
0183 
0184     sermouse->count++;
0185 }
0186 
0187 /*
0188  * sermouse_interrupt() handles incoming characters, either gathering them into
0189  * packets or passing them to the command routine as command output.
0190  */
0191 
0192 static irqreturn_t sermouse_interrupt(struct serio *serio,
0193         unsigned char data, unsigned int flags)
0194 {
0195     struct sermouse *sermouse = serio_get_drvdata(serio);
0196 
0197     if (time_after(jiffies, sermouse->last + HZ/10))
0198         sermouse->count = 0;
0199 
0200     sermouse->last = jiffies;
0201 
0202     if (sermouse->type > SERIO_SUN)
0203         sermouse_process_ms(sermouse, data);
0204     else
0205         sermouse_process_msc(sermouse, data);
0206 
0207     return IRQ_HANDLED;
0208 }
0209 
0210 /*
0211  * sermouse_disconnect() cleans up after we don't want talk
0212  * to the mouse anymore.
0213  */
0214 
0215 static void sermouse_disconnect(struct serio *serio)
0216 {
0217     struct sermouse *sermouse = serio_get_drvdata(serio);
0218 
0219     serio_close(serio);
0220     serio_set_drvdata(serio, NULL);
0221     input_unregister_device(sermouse->dev);
0222     kfree(sermouse);
0223 }
0224 
0225 /*
0226  * sermouse_connect() is a callback form the serio module when
0227  * an unhandled serio port is found.
0228  */
0229 
0230 static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
0231 {
0232     struct sermouse *sermouse;
0233     struct input_dev *input_dev;
0234     unsigned char c = serio->id.extra;
0235     int err = -ENOMEM;
0236 
0237     sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
0238     input_dev = input_allocate_device();
0239     if (!sermouse || !input_dev)
0240         goto fail1;
0241 
0242     sermouse->dev = input_dev;
0243     snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys);
0244     sermouse->type = serio->id.proto;
0245 
0246     input_dev->name = sermouse_protocols[sermouse->type];
0247     input_dev->phys = sermouse->phys;
0248     input_dev->id.bustype = BUS_RS232;
0249     input_dev->id.vendor  = sermouse->type;
0250     input_dev->id.product = c;
0251     input_dev->id.version = 0x0100;
0252     input_dev->dev.parent = &serio->dev;
0253 
0254     input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
0255     input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
0256         BIT_MASK(BTN_RIGHT);
0257     input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
0258 
0259     if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
0260     if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
0261     if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit);
0262     if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit);
0263     if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit);
0264 
0265     serio_set_drvdata(serio, sermouse);
0266 
0267     err = serio_open(serio, drv);
0268     if (err)
0269         goto fail2;
0270 
0271     err = input_register_device(sermouse->dev);
0272     if (err)
0273         goto fail3;
0274 
0275     return 0;
0276 
0277  fail3: serio_close(serio);
0278  fail2: serio_set_drvdata(serio, NULL);
0279  fail1: input_free_device(input_dev);
0280     kfree(sermouse);
0281     return err;
0282 }
0283 
0284 static struct serio_device_id sermouse_serio_ids[] = {
0285     {
0286         .type   = SERIO_RS232,
0287         .proto  = SERIO_MSC,
0288         .id = SERIO_ANY,
0289         .extra  = SERIO_ANY,
0290     },
0291     {
0292         .type   = SERIO_RS232,
0293         .proto  = SERIO_SUN,
0294         .id = SERIO_ANY,
0295         .extra  = SERIO_ANY,
0296     },
0297     {
0298         .type   = SERIO_RS232,
0299         .proto  = SERIO_MS,
0300         .id = SERIO_ANY,
0301         .extra  = SERIO_ANY,
0302     },
0303     {
0304         .type   = SERIO_RS232,
0305         .proto  = SERIO_MP,
0306         .id = SERIO_ANY,
0307         .extra  = SERIO_ANY,
0308     },
0309     {
0310         .type   = SERIO_RS232,
0311         .proto  = SERIO_MZ,
0312         .id = SERIO_ANY,
0313         .extra  = SERIO_ANY,
0314     },
0315     {
0316         .type   = SERIO_RS232,
0317         .proto  = SERIO_MZP,
0318         .id = SERIO_ANY,
0319         .extra  = SERIO_ANY,
0320     },
0321     {
0322         .type   = SERIO_RS232,
0323         .proto  = SERIO_MZPP,
0324         .id = SERIO_ANY,
0325         .extra  = SERIO_ANY,
0326     },
0327     { 0 }
0328 };
0329 
0330 MODULE_DEVICE_TABLE(serio, sermouse_serio_ids);
0331 
0332 static struct serio_driver sermouse_drv = {
0333     .driver     = {
0334         .name   = "sermouse",
0335     },
0336     .description    = DRIVER_DESC,
0337     .id_table   = sermouse_serio_ids,
0338     .interrupt  = sermouse_interrupt,
0339     .connect    = sermouse_connect,
0340     .disconnect = sermouse_disconnect,
0341 };
0342 
0343 module_serio_driver(sermouse_drv);