This source file includes following definitions.
- sermouse_process_msc
- sermouse_process_ms
- sermouse_interrupt
- sermouse_disconnect
- sermouse_connect
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 #include <linux/delay.h>
  14 #include <linux/module.h>
  15 #include <linux/slab.h>
  16 #include <linux/interrupt.h>
  17 #include <linux/input.h>
  18 #include <linux/serio.h>
  19 
  20 #define DRIVER_DESC     "Serial mouse driver"
  21 
  22 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
  23 MODULE_DESCRIPTION(DRIVER_DESC);
  24 MODULE_LICENSE("GPL");
  25 
  26 static const char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
  27                                         "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse",
  28                                         "Logitech MZ++ Mouse"};
  29 
  30 struct sermouse {
  31         struct input_dev *dev;
  32         signed char buf[8];
  33         unsigned char count;
  34         unsigned char type;
  35         unsigned long last;
  36         char phys[32];
  37 };
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
  46 {
  47         struct input_dev *dev = sermouse->dev;
  48         signed char *buf = sermouse->buf;
  49 
  50         switch (sermouse->count) {
  51 
  52                 case 0:
  53                         if ((data & 0xf8) != 0x80)
  54                                 return;
  55                         input_report_key(dev, BTN_LEFT,   !(data & 4));
  56                         input_report_key(dev, BTN_RIGHT,  !(data & 1));
  57                         input_report_key(dev, BTN_MIDDLE, !(data & 2));
  58                         break;
  59 
  60                 case 1:
  61                 case 3:
  62                         input_report_rel(dev, REL_X, data / 2);
  63                         input_report_rel(dev, REL_Y, -buf[1]);
  64                         buf[0] = data - data / 2;
  65                         break;
  66 
  67                 case 2:
  68                 case 4:
  69                         input_report_rel(dev, REL_X, buf[0]);
  70                         input_report_rel(dev, REL_Y, buf[1] - data);
  71                         buf[1] = data / 2;
  72                         break;
  73         }
  74 
  75         input_sync(dev);
  76 
  77         if (++sermouse->count == 5)
  78                 sermouse->count = 0;
  79 }
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
  88 {
  89         struct input_dev *dev = sermouse->dev;
  90         signed char *buf = sermouse->buf;
  91 
  92         if (data & 0x40)
  93                 sermouse->count = 0;
  94         else if (sermouse->count == 0)
  95                 return;
  96 
  97         switch (sermouse->count) {
  98 
  99                 case 0:
 100                         buf[1] = data;
 101                         input_report_key(dev, BTN_LEFT,   (data >> 5) & 1);
 102                         input_report_key(dev, BTN_RIGHT,  (data >> 4) & 1);
 103                         break;
 104 
 105                 case 1:
 106                         buf[2] = data;
 107                         data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f));
 108                         input_report_rel(dev, REL_X, data / 2);
 109                         input_report_rel(dev, REL_Y, buf[4]);
 110                         buf[3] = data - data / 2;
 111                         break;
 112 
 113                 case 2:
 114                         
 115                         if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1]))
 116                                 input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key));
 117                         buf[0] = buf[1];
 118 
 119                         data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f));
 120                         input_report_rel(dev, REL_X, buf[3]);
 121                         input_report_rel(dev, REL_Y, data - buf[4]);
 122                         buf[4] = data / 2;
 123                         break;
 124 
 125                 case 3:
 126 
 127                         switch (sermouse->type) {
 128 
 129                                 case SERIO_MS:
 130                                         sermouse->type = SERIO_MP;
 131                                         
 132 
 133                                 case SERIO_MP:
 134                                         if ((data >> 2) & 3) break;     
 135                                         input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1);
 136                                         input_report_key(dev, BTN_SIDE,   (data >> 4) & 1);
 137                                         break;
 138 
 139                                 case SERIO_MZP:
 140                                 case SERIO_MZPP:
 141                                         input_report_key(dev, BTN_SIDE,   (data >> 5) & 1);
 142                                         
 143 
 144                                 case SERIO_MZ:
 145                                         input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
 146                                         input_report_rel(dev, REL_WHEEL,  (data & 8) - (data & 7));
 147                                         break;
 148                         }
 149 
 150                         break;
 151 
 152                 case 4:
 153                 case 6: 
 154                         buf[1] = (data >> 2) & 0x0f;
 155                         break;
 156 
 157                 case 5:
 158                 case 7: 
 159                         if (sermouse->type != SERIO_MZPP)
 160                                 break;
 161 
 162                         switch (buf[1]) {
 163 
 164                                 case 1: 
 165 
 166                                         input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
 167                                         input_report_key(dev, BTN_EXTRA, (data >> 5) & 1);
 168                                         input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8));
 169 
 170                                         break;
 171 
 172                                 default: 
 173 
 174                                         printk(KERN_WARNING
 175                                                 "sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]);
 176                                         break;
 177                         }
 178 
 179                         break;
 180         }
 181 
 182         input_sync(dev);
 183 
 184         sermouse->count++;
 185 }
 186 
 187 
 188 
 189 
 190 
 191 
 192 static irqreturn_t sermouse_interrupt(struct serio *serio,
 193                 unsigned char data, unsigned int flags)
 194 {
 195         struct sermouse *sermouse = serio_get_drvdata(serio);
 196 
 197         if (time_after(jiffies, sermouse->last + HZ/10))
 198                 sermouse->count = 0;
 199 
 200         sermouse->last = jiffies;
 201 
 202         if (sermouse->type > SERIO_SUN)
 203                 sermouse_process_ms(sermouse, data);
 204         else
 205                 sermouse_process_msc(sermouse, data);
 206 
 207         return IRQ_HANDLED;
 208 }
 209 
 210 
 211 
 212 
 213 
 214 
 215 static void sermouse_disconnect(struct serio *serio)
 216 {
 217         struct sermouse *sermouse = serio_get_drvdata(serio);
 218 
 219         serio_close(serio);
 220         serio_set_drvdata(serio, NULL);
 221         input_unregister_device(sermouse->dev);
 222         kfree(sermouse);
 223 }
 224 
 225 
 226 
 227 
 228 
 229 
 230 static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
 231 {
 232         struct sermouse *sermouse;
 233         struct input_dev *input_dev;
 234         unsigned char c = serio->id.extra;
 235         int err = -ENOMEM;
 236 
 237         sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
 238         input_dev = input_allocate_device();
 239         if (!sermouse || !input_dev)
 240                 goto fail1;
 241 
 242         sermouse->dev = input_dev;
 243         snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys);
 244         sermouse->type = serio->id.proto;
 245 
 246         input_dev->name = sermouse_protocols[sermouse->type];
 247         input_dev->phys = sermouse->phys;
 248         input_dev->id.bustype = BUS_RS232;
 249         input_dev->id.vendor  = sermouse->type;
 250         input_dev->id.product = c;
 251         input_dev->id.version = 0x0100;
 252         input_dev->dev.parent = &serio->dev;
 253 
 254         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
 255         input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
 256                 BIT_MASK(BTN_RIGHT);
 257         input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
 258 
 259         if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
 260         if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
 261         if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit);
 262         if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit);
 263         if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit);
 264 
 265         serio_set_drvdata(serio, sermouse);
 266 
 267         err = serio_open(serio, drv);
 268         if (err)
 269                 goto fail2;
 270 
 271         err = input_register_device(sermouse->dev);
 272         if (err)
 273                 goto fail3;
 274 
 275         return 0;
 276 
 277  fail3: serio_close(serio);
 278  fail2: serio_set_drvdata(serio, NULL);
 279  fail1: input_free_device(input_dev);
 280         kfree(sermouse);
 281         return err;
 282 }
 283 
 284 static struct serio_device_id sermouse_serio_ids[] = {
 285         {
 286                 .type   = SERIO_RS232,
 287                 .proto  = SERIO_MSC,
 288                 .id     = SERIO_ANY,
 289                 .extra  = SERIO_ANY,
 290         },
 291         {
 292                 .type   = SERIO_RS232,
 293                 .proto  = SERIO_SUN,
 294                 .id     = SERIO_ANY,
 295                 .extra  = SERIO_ANY,
 296         },
 297         {
 298                 .type   = SERIO_RS232,
 299                 .proto  = SERIO_MS,
 300                 .id     = SERIO_ANY,
 301                 .extra  = SERIO_ANY,
 302         },
 303         {
 304                 .type   = SERIO_RS232,
 305                 .proto  = SERIO_MP,
 306                 .id     = SERIO_ANY,
 307                 .extra  = SERIO_ANY,
 308         },
 309         {
 310                 .type   = SERIO_RS232,
 311                 .proto  = SERIO_MZ,
 312                 .id     = SERIO_ANY,
 313                 .extra  = SERIO_ANY,
 314         },
 315         {
 316                 .type   = SERIO_RS232,
 317                 .proto  = SERIO_MZP,
 318                 .id     = SERIO_ANY,
 319                 .extra  = SERIO_ANY,
 320         },
 321         {
 322                 .type   = SERIO_RS232,
 323                 .proto  = SERIO_MZPP,
 324                 .id     = SERIO_ANY,
 325                 .extra  = SERIO_ANY,
 326         },
 327         { 0 }
 328 };
 329 
 330 MODULE_DEVICE_TABLE(serio, sermouse_serio_ids);
 331 
 332 static struct serio_driver sermouse_drv = {
 333         .driver         = {
 334                 .name   = "sermouse",
 335         },
 336         .description    = DRIVER_DESC,
 337         .id_table       = sermouse_serio_ids,
 338         .interrupt      = sermouse_interrupt,
 339         .connect        = sermouse_connect,
 340         .disconnect     = sermouse_disconnect,
 341 };
 342 
 343 module_serio_driver(sermouse_drv);