sermouse.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 1999-2001 Vojtech Pavlik
  4. */
  5. /*
  6. * Serial mouse driver for Linux
  7. */
  8. #include <linux/delay.h>
  9. #include <linux/module.h>
  10. #include <linux/slab.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/input.h>
  13. #include <linux/serio.h>
  14. #define DRIVER_DESC "Serial mouse driver"
  15. MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
  16. MODULE_DESCRIPTION(DRIVER_DESC);
  17. MODULE_LICENSE("GPL");
  18. static const char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
  19. "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse",
  20. "Logitech MZ++ Mouse"};
  21. struct sermouse {
  22. struct input_dev *dev;
  23. signed char buf[8];
  24. unsigned char count;
  25. unsigned char type;
  26. unsigned long last;
  27. char phys[32];
  28. };
  29. /*
  30. * sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and
  31. * applies some prediction to the data, resulting in 96 updates per
  32. * second, which is as good as a PS/2 or USB mouse.
  33. */
  34. static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
  35. {
  36. struct input_dev *dev = sermouse->dev;
  37. signed char *buf = sermouse->buf;
  38. switch (sermouse->count) {
  39. case 0:
  40. if ((data & 0xf8) != 0x80)
  41. return;
  42. input_report_key(dev, BTN_LEFT, !(data & 4));
  43. input_report_key(dev, BTN_RIGHT, !(data & 1));
  44. input_report_key(dev, BTN_MIDDLE, !(data & 2));
  45. break;
  46. case 1:
  47. case 3:
  48. input_report_rel(dev, REL_X, data / 2);
  49. input_report_rel(dev, REL_Y, -buf[1]);
  50. buf[0] = data - data / 2;
  51. break;
  52. case 2:
  53. case 4:
  54. input_report_rel(dev, REL_X, buf[0]);
  55. input_report_rel(dev, REL_Y, buf[1] - data);
  56. buf[1] = data / 2;
  57. break;
  58. }
  59. input_sync(dev);
  60. if (++sermouse->count == 5)
  61. sermouse->count = 0;
  62. }
  63. /*
  64. * sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and
  65. * generates events. With prediction it gets 80 updates/sec, assuming
  66. * standard 3-byte packets and 1200 bps.
  67. */
  68. static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
  69. {
  70. struct input_dev *dev = sermouse->dev;
  71. signed char *buf = sermouse->buf;
  72. if (data & 0x40)
  73. sermouse->count = 0;
  74. else if (sermouse->count == 0)
  75. return;
  76. switch (sermouse->count) {
  77. case 0:
  78. buf[1] = data;
  79. input_report_key(dev, BTN_LEFT, (data >> 5) & 1);
  80. input_report_key(dev, BTN_RIGHT, (data >> 4) & 1);
  81. break;
  82. case 1:
  83. buf[2] = data;
  84. data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f));
  85. input_report_rel(dev, REL_X, data / 2);
  86. input_report_rel(dev, REL_Y, buf[4]);
  87. buf[3] = data - data / 2;
  88. break;
  89. case 2:
  90. /* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */
  91. if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1]))
  92. input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key));
  93. buf[0] = buf[1];
  94. data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f));
  95. input_report_rel(dev, REL_X, buf[3]);
  96. input_report_rel(dev, REL_Y, data - buf[4]);
  97. buf[4] = data / 2;
  98. break;
  99. case 3:
  100. switch (sermouse->type) {
  101. case SERIO_MS:
  102. sermouse->type = SERIO_MP;
  103. fallthrough;
  104. case SERIO_MP:
  105. if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */
  106. input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1);
  107. input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
  108. break;
  109. case SERIO_MZP:
  110. case SERIO_MZPP:
  111. input_report_key(dev, BTN_SIDE, (data >> 5) & 1);
  112. fallthrough;
  113. case SERIO_MZ:
  114. input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
  115. input_report_rel(dev, REL_WHEEL, (data & 8) - (data & 7));
  116. break;
  117. }
  118. break;
  119. case 4:
  120. case 6: /* MZ++ packet type. We can get these bytes for M++ too but we ignore them later. */
  121. buf[1] = (data >> 2) & 0x0f;
  122. break;
  123. case 5:
  124. case 7: /* Ignore anything besides MZ++ */
  125. if (sermouse->type != SERIO_MZPP)
  126. break;
  127. switch (buf[1]) {
  128. case 1: /* Extra mouse info */
  129. input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
  130. input_report_key(dev, BTN_EXTRA, (data >> 5) & 1);
  131. input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8));
  132. break;
  133. default: /* We don't decode anything else yet. */
  134. printk(KERN_WARNING
  135. "sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]);
  136. break;
  137. }
  138. break;
  139. }
  140. input_sync(dev);
  141. sermouse->count++;
  142. }
  143. /*
  144. * sermouse_interrupt() handles incoming characters, either gathering them into
  145. * packets or passing them to the command routine as command output.
  146. */
  147. static irqreturn_t sermouse_interrupt(struct serio *serio,
  148. unsigned char data, unsigned int flags)
  149. {
  150. struct sermouse *sermouse = serio_get_drvdata(serio);
  151. if (time_after(jiffies, sermouse->last + HZ/10))
  152. sermouse->count = 0;
  153. sermouse->last = jiffies;
  154. if (sermouse->type > SERIO_SUN)
  155. sermouse_process_ms(sermouse, data);
  156. else
  157. sermouse_process_msc(sermouse, data);
  158. return IRQ_HANDLED;
  159. }
  160. /*
  161. * sermouse_disconnect() cleans up after we don't want talk
  162. * to the mouse anymore.
  163. */
  164. static void sermouse_disconnect(struct serio *serio)
  165. {
  166. struct sermouse *sermouse = serio_get_drvdata(serio);
  167. serio_close(serio);
  168. serio_set_drvdata(serio, NULL);
  169. input_unregister_device(sermouse->dev);
  170. kfree(sermouse);
  171. }
  172. /*
  173. * sermouse_connect() is a callback form the serio module when
  174. * an unhandled serio port is found.
  175. */
  176. static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
  177. {
  178. struct sermouse *sermouse;
  179. struct input_dev *input_dev;
  180. unsigned char c = serio->id.extra;
  181. int err = -ENOMEM;
  182. sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
  183. input_dev = input_allocate_device();
  184. if (!sermouse || !input_dev)
  185. goto fail1;
  186. sermouse->dev = input_dev;
  187. snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys);
  188. sermouse->type = serio->id.proto;
  189. input_dev->name = sermouse_protocols[sermouse->type];
  190. input_dev->phys = sermouse->phys;
  191. input_dev->id.bustype = BUS_RS232;
  192. input_dev->id.vendor = sermouse->type;
  193. input_dev->id.product = c;
  194. input_dev->id.version = 0x0100;
  195. input_dev->dev.parent = &serio->dev;
  196. input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
  197. input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
  198. BIT_MASK(BTN_RIGHT);
  199. input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
  200. if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
  201. if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
  202. if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit);
  203. if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit);
  204. if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit);
  205. serio_set_drvdata(serio, sermouse);
  206. err = serio_open(serio, drv);
  207. if (err)
  208. goto fail2;
  209. err = input_register_device(sermouse->dev);
  210. if (err)
  211. goto fail3;
  212. return 0;
  213. fail3: serio_close(serio);
  214. fail2: serio_set_drvdata(serio, NULL);
  215. fail1: input_free_device(input_dev);
  216. kfree(sermouse);
  217. return err;
  218. }
  219. static struct serio_device_id sermouse_serio_ids[] = {
  220. {
  221. .type = SERIO_RS232,
  222. .proto = SERIO_MSC,
  223. .id = SERIO_ANY,
  224. .extra = SERIO_ANY,
  225. },
  226. {
  227. .type = SERIO_RS232,
  228. .proto = SERIO_SUN,
  229. .id = SERIO_ANY,
  230. .extra = SERIO_ANY,
  231. },
  232. {
  233. .type = SERIO_RS232,
  234. .proto = SERIO_MS,
  235. .id = SERIO_ANY,
  236. .extra = SERIO_ANY,
  237. },
  238. {
  239. .type = SERIO_RS232,
  240. .proto = SERIO_MP,
  241. .id = SERIO_ANY,
  242. .extra = SERIO_ANY,
  243. },
  244. {
  245. .type = SERIO_RS232,
  246. .proto = SERIO_MZ,
  247. .id = SERIO_ANY,
  248. .extra = SERIO_ANY,
  249. },
  250. {
  251. .type = SERIO_RS232,
  252. .proto = SERIO_MZP,
  253. .id = SERIO_ANY,
  254. .extra = SERIO_ANY,
  255. },
  256. {
  257. .type = SERIO_RS232,
  258. .proto = SERIO_MZPP,
  259. .id = SERIO_ANY,
  260. .extra = SERIO_ANY,
  261. },
  262. { 0 }
  263. };
  264. MODULE_DEVICE_TABLE(serio, sermouse_serio_ids);
  265. static struct serio_driver sermouse_drv = {
  266. .driver = {
  267. .name = "sermouse",
  268. },
  269. .description = DRIVER_DESC,
  270. .id_table = sermouse_serio_ids,
  271. .interrupt = sermouse_interrupt,
  272. .connect = sermouse_connect,
  273. .disconnect = sermouse_disconnect,
  274. };
  275. module_serio_driver(sermouse_drv);