mouse.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. /*
  2. *
  3. * Copyright © 2001 Keith Packard
  4. *
  5. * Permission to use, copy, modify, distribute, and sell this software and its
  6. * documentation for any purpose is hereby granted without fee, provided that
  7. * the above copyright notice appear in all copies and that both that
  8. * copyright notice and this permission notice appear in supporting
  9. * documentation, and that the name of Keith Packard not be used in
  10. * advertising or publicity pertaining to distribution of the software without
  11. * specific, written prior permission. Keith Packard makes no
  12. * representations about the suitability of this software for any purpose. It
  13. * is provided "as is" without express or implied warranty.
  14. *
  15. * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  16. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  17. * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  18. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  19. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  20. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21. * PERFORMANCE OF THIS SOFTWARE.
  22. */
  23. #ifdef HAVE_CONFIG_H
  24. #include <kdrive-config.h>
  25. #endif
  26. #include <errno.h>
  27. #include <termios.h>
  28. #include <X11/X.h>
  29. #include <X11/Xproto.h>
  30. #include <X11/Xpoll.h>
  31. #include "inputstr.h"
  32. #include "scrnintstr.h"
  33. #include "kdrive.h"
  34. #undef DEBUG
  35. #undef DEBUG_BYTES
  36. #define KBUFIO_SIZE 256
  37. #define MOUSE_TIMEOUT 100
  38. typedef struct _kbufio {
  39. int fd;
  40. unsigned char buf[KBUFIO_SIZE];
  41. int avail;
  42. int used;
  43. } Kbufio;
  44. static Bool MouseWaitForReadable(int fd, int timeout)
  45. {
  46. fd_set set;
  47. struct timeval tv, *tp;
  48. int n;
  49. CARD32 done;
  50. done = GetTimeInMillis() + timeout;
  51. for (;;) {
  52. FD_ZERO(&set);
  53. FD_SET(fd, &set);
  54. if (timeout == -1)
  55. tp = 0;
  56. else {
  57. tv.tv_sec = timeout / 1000;
  58. tv.tv_usec = (timeout % 1000) * 1000;
  59. tp = &tv;
  60. }
  61. n = select(fd + 1, &set, 0, 0, tp);
  62. if (n > 0)
  63. return TRUE;
  64. if (n < 0 && (errno == EAGAIN || errno == EINTR)) {
  65. timeout = (int)(done - GetTimeInMillis());
  66. if (timeout > 0)
  67. continue;
  68. }
  69. break;
  70. }
  71. return FALSE;
  72. }
  73. static int MouseReadByte(Kbufio * b, int timeout)
  74. {
  75. int n;
  76. if (b->avail <= b->used) {
  77. if (timeout && !MouseWaitForReadable(b->fd, timeout)) {
  78. #ifdef DEBUG_BYTES
  79. ErrorF("\tTimeout %d\n", timeout);
  80. #endif
  81. return -1;
  82. }
  83. n = read(b->fd, b->buf, KBUFIO_SIZE);
  84. if (n <= 0)
  85. return -1;
  86. b->avail = n;
  87. b->used = 0;
  88. }
  89. #ifdef DEBUG_BYTES
  90. ErrorF("\tget %02x\n", b->buf[b->used]);
  91. #endif
  92. return b->buf[b->used++];
  93. }
  94. #if NOTUSED
  95. static int MouseFlush(Kbufio * b, char *buf, int size)
  96. {
  97. CARD32 now = GetTimeInMillis();
  98. CARD32 done = now + 100;
  99. int c;
  100. int n = 0;
  101. while ((c = MouseReadByte(b, done - now)) != -1) {
  102. if (buf) {
  103. if (n == size) {
  104. memmove(buf, buf + 1, size - 1);
  105. n--;
  106. }
  107. buf[n++] = c;
  108. }
  109. now = GetTimeInMillis();
  110. if ((INT32) (now - done) >= 0)
  111. break;
  112. }
  113. return n;
  114. }
  115. static int MousePeekByte(Kbufio * b, int timeout)
  116. {
  117. int c;
  118. c = MouseReadByte(b, timeout);
  119. if (c != -1)
  120. --b->used;
  121. return c;
  122. }
  123. #endif /* NOTUSED */
  124. static Bool MouseWaitForWritable(int fd, int timeout)
  125. {
  126. fd_set set;
  127. struct timeval tv, *tp;
  128. int n;
  129. FD_ZERO(&set);
  130. FD_SET(fd, &set);
  131. if (timeout == -1)
  132. tp = 0;
  133. else {
  134. tv.tv_sec = timeout / 1000;
  135. tv.tv_usec = (timeout % 1000) * 1000;
  136. tp = &tv;
  137. }
  138. n = select(fd + 1, 0, &set, 0, tp);
  139. if (n > 0)
  140. return TRUE;
  141. return FALSE;
  142. }
  143. static Bool MouseWriteByte(const int fd, const unsigned char c, const int timeout)
  144. {
  145. int ret;
  146. #ifdef DEBUG_BYTES
  147. ErrorF("\tput %02x\n", c);
  148. #endif
  149. for (;;) {
  150. ret = write(fd, &c, 1);
  151. if (ret == 1)
  152. return TRUE;
  153. if (ret == 0)
  154. return FALSE;
  155. if (errno != EWOULDBLOCK)
  156. return FALSE;
  157. if (!MouseWaitForWritable(fd, timeout))
  158. return FALSE;
  159. }
  160. }
  161. static Bool MouseWriteBytes(const int fd, const unsigned char *c, int n,
  162. const int timeout)
  163. {
  164. while (n--)
  165. if (!MouseWriteByte(fd, *c++, timeout))
  166. return FALSE;
  167. return TRUE;
  168. }
  169. #define MAX_MOUSE 10 /* maximum length of mouse protocol */
  170. #define MAX_SKIP 16 /* number of error bytes before switching */
  171. #define MAX_VALID 4 /* number of valid packets before accepting */
  172. typedef struct _kmouseProt {
  173. char *name;
  174. Bool(*Complete) (KdMouseInfo * mi, unsigned char *ev, int ne);
  175. int (*Valid) (KdMouseInfo * mi, unsigned char *ev, int ne);
  176. Bool(*Parse) (KdMouseInfo * mi, unsigned char *ev, int ne);
  177. Bool(*Init) (KdMouseInfo * mi);
  178. unsigned char headerMask, headerValid;
  179. unsigned char dataMask, dataValid;
  180. Bool tty;
  181. unsigned int c_iflag;
  182. unsigned int c_oflag;
  183. unsigned int c_lflag;
  184. unsigned int c_cflag;
  185. unsigned int speed;
  186. unsigned char *init;
  187. unsigned long state;
  188. } KmouseProt;
  189. typedef enum _kmouseStage {
  190. MouseBroken, MouseTesting, MouseWorking
  191. } KmouseStage;
  192. typedef struct _kmouse {
  193. Kbufio iob;
  194. const KmouseProt *prot;
  195. int i_prot;
  196. KmouseStage stage; /* protocol verification stage */
  197. Bool tty; /* mouse device is a tty */
  198. int valid; /* sequential valid events */
  199. int tested; /* bytes scanned during Testing phase */
  200. int invalid; /* total invalid bytes for this protocol */
  201. unsigned long state; /* private per protocol, init to prot->state */
  202. } Kmouse;
  203. static int mouseValid(KdMouseInfo * mi, unsigned char *ev, int ne)
  204. {
  205. Kmouse *km = mi->driver;
  206. const KmouseProt *prot = km->prot;
  207. int i;
  208. for (i = 0; i < ne; i++)
  209. if ((ev[i] & prot->headerMask) == prot->headerValid)
  210. break;
  211. if (i != 0)
  212. return i;
  213. for (i = 1; i < ne; i++)
  214. if ((ev[i] & prot->dataMask) != prot->dataValid)
  215. return -1;
  216. return 0;
  217. }
  218. static Bool threeComplete(KdMouseInfo * mi, unsigned char *ev, int ne)
  219. {
  220. return ne == 3;
  221. }
  222. static Bool fourComplete(KdMouseInfo * mi, unsigned char *ev, int ne)
  223. {
  224. return ne == 4;
  225. }
  226. static Bool fiveComplete(KdMouseInfo * mi, unsigned char *ev, int ne)
  227. {
  228. return ne == 5;
  229. }
  230. static Bool MouseReasonable(KdMouseInfo * mi, unsigned long flags, int dx,
  231. int dy)
  232. {
  233. Kmouse *km = mi->driver;
  234. if (km->stage == MouseWorking)
  235. return TRUE;
  236. if (dx < -50 || dx > 50) {
  237. #ifdef DEBUG
  238. ErrorF("Large X %d\n", dx);
  239. #endif
  240. return FALSE;
  241. }
  242. if (dy < -50 || dy > 50) {
  243. #ifdef DEBUG
  244. ErrorF("Large Y %d\n", dy);
  245. #endif
  246. return FALSE;
  247. }
  248. return TRUE;
  249. }
  250. /*
  251. * Standard PS/2 mouse protocol
  252. */
  253. static Bool ps2Parse(KdMouseInfo * mi, unsigned char *ev, int ne)
  254. {
  255. Kmouse *km = mi->driver;
  256. int dx, dy, dz;
  257. unsigned long flags;
  258. unsigned long flagsrelease = 0;
  259. flags = KD_MOUSE_DELTA;
  260. if (ev[0] & 4)
  261. flags |= KD_BUTTON_2;
  262. if (ev[0] & 2)
  263. flags |= KD_BUTTON_3;
  264. if (ev[0] & 1)
  265. flags |= KD_BUTTON_1;
  266. if (ne > 3) {
  267. dz = (int)(signed char)ev[3];
  268. if (dz < 0) {
  269. flags |= KD_BUTTON_4;
  270. flagsrelease = KD_BUTTON_4;
  271. } else if (dz > 0) {
  272. flags |= KD_BUTTON_5;
  273. flagsrelease = KD_BUTTON_5;
  274. }
  275. }
  276. dx = ev[1];
  277. if (ev[0] & 0x10)
  278. dx -= 256;
  279. dy = ev[2];
  280. if (ev[0] & 0x20)
  281. dy -= 256;
  282. dy = -dy;
  283. if (!MouseReasonable(mi, flags, dx, dy))
  284. return FALSE;
  285. if (km->stage == MouseWorking) {
  286. KdEnqueueMouseEvent(mi, flags, dx, dy);
  287. if (flagsrelease) {
  288. flags &= ~flagsrelease;
  289. KdEnqueueMouseEvent(mi, flags, dx, dy);
  290. }
  291. }
  292. return TRUE;
  293. }
  294. static Bool ps2Init(KdMouseInfo * mi);
  295. static const KmouseProt ps2Prot = {
  296. "ps/2",
  297. threeComplete, mouseValid, ps2Parse, ps2Init,
  298. 0x08, 0x08, 0x00, 0x00,
  299. FALSE
  300. };
  301. static const KmouseProt imps2Prot = {
  302. "imps/2",
  303. fourComplete, mouseValid, ps2Parse, ps2Init,
  304. 0x08, 0x08, 0x00, 0x00,
  305. FALSE
  306. };
  307. static const KmouseProt exps2Prot = {
  308. "exps/2",
  309. fourComplete, mouseValid, ps2Parse, ps2Init,
  310. 0x08, 0x08, 0x00, 0x00,
  311. FALSE
  312. };
  313. /*
  314. * Once the mouse is known to speak ps/2 protocol, go and find out
  315. * what advanced capabilities it has and turn them on
  316. */
  317. /* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */
  318. /* aux device commands (sent to KBD_DATA_PORT) */
  319. #define PSMC_SET_SCALING11 0x00e6
  320. #define PSMC_SET_SCALING21 0x00e7
  321. #define PSMC_SET_RESOLUTION 0x00e8
  322. #define PSMC_SEND_DEV_STATUS 0x00e9
  323. #define PSMC_SET_STREAM_MODE 0x00ea
  324. #define PSMC_SEND_DEV_DATA 0x00eb
  325. #define PSMC_SET_REMOTE_MODE 0x00f0
  326. #define PSMC_SEND_DEV_ID 0x00f2
  327. #define PSMC_SET_SAMPLING_RATE 0x00f3
  328. #define PSMC_ENABLE_DEV 0x00f4
  329. #define PSMC_DISABLE_DEV 0x00f5
  330. #define PSMC_SET_DEFAULTS 0x00f6
  331. #define PSMC_RESET_DEV 0x00ff
  332. /* PSMC_SET_RESOLUTION argument */
  333. #define PSMD_RES_LOW 0 /* typically 25ppi */
  334. #define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */
  335. #define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */
  336. #define PSMD_RES_HIGH 3 /* typically 200ppi */
  337. #define PSMD_MAX_RESOLUTION PSMD_RES_HIGH
  338. /* PSMC_SET_SAMPLING_RATE */
  339. #define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */
  340. /* aux device ID */
  341. #define PSM_MOUSE_ID 0
  342. #define PSM_BALLPOINT_ID 2
  343. #define PSM_INTELLI_ID 3
  344. #define PSM_EXPLORER_ID 4
  345. #define PSM_4DMOUSE_ID 6
  346. #define PSM_4DPLUS_ID 8
  347. static const unsigned char ps2_init[] = {
  348. PSMC_ENABLE_DEV,
  349. 0,
  350. };
  351. #define NINIT_PS2 1
  352. static const unsigned char wheel_3button_init[] = {
  353. PSMC_SET_SAMPLING_RATE, 200,
  354. PSMC_SET_SAMPLING_RATE, 100,
  355. PSMC_SET_SAMPLING_RATE, 80,
  356. PSMC_SEND_DEV_ID,
  357. 0,
  358. };
  359. #define NINIT_IMPS2 4
  360. static const unsigned char wheel_5button_init[] = {
  361. PSMC_SET_SAMPLING_RATE, 200,
  362. PSMC_SET_SAMPLING_RATE, 100,
  363. PSMC_SET_SAMPLING_RATE, 80,
  364. PSMC_SET_SAMPLING_RATE, 200,
  365. PSMC_SET_SAMPLING_RATE, 200,
  366. PSMC_SET_SAMPLING_RATE, 80,
  367. PSMC_SEND_DEV_ID,
  368. 0
  369. };
  370. #define NINIT_EXPS2 7
  371. static const unsigned char intelli_init[] = {
  372. PSMC_SET_SAMPLING_RATE, 200,
  373. PSMC_SET_SAMPLING_RATE, 100,
  374. PSMC_SET_SAMPLING_RATE, 80,
  375. 0
  376. };
  377. #define NINIT_INTELLI 3
  378. static int ps2SkipInit(KdMouseInfo * const mi, int ninit, const Bool ret_next)
  379. {
  380. Kmouse * const km = mi->driver;
  381. int c = -1;
  382. Bool waiting;
  383. waiting = FALSE;
  384. while (ninit || ret_next) {
  385. c = MouseReadByte(&km->iob, 1); // Minimum timeout like in xf86-input-mouse
  386. if (c == -1)
  387. break;
  388. /* look for ACK */
  389. if (c == 0xfa) {
  390. ninit--;
  391. if (ret_next)
  392. waiting = TRUE;
  393. }
  394. /* look for packet start -- not the response */
  395. else if ((c & 0x08) == 0x08)
  396. waiting = FALSE;
  397. else if (waiting)
  398. break;
  399. }
  400. return c;
  401. }
  402. static Bool ps2Init(KdMouseInfo * mi)
  403. {
  404. Kmouse *km = mi->driver;
  405. int id;
  406. const unsigned char *init;
  407. int ninit;
  408. /* Send Intellimouse initialization sequence */
  409. MouseWriteBytes(km->iob.fd, intelli_init, strlen((char *)intelli_init),
  410. 100);
  411. /*
  412. * Send ID command
  413. */
  414. if (!MouseWriteByte(km->iob.fd, PSMC_SEND_DEV_ID, 100))
  415. return FALSE;
  416. id = ps2SkipInit(mi, 0, TRUE);
  417. switch (id) {
  418. case 3:
  419. init = wheel_3button_init;
  420. ninit = NINIT_IMPS2;
  421. km->prot = &imps2Prot;
  422. break;
  423. case 4:
  424. init = wheel_5button_init;
  425. ninit = NINIT_EXPS2;
  426. km->prot = &exps2Prot;
  427. break;
  428. default:
  429. init = ps2_init;
  430. ninit = NINIT_PS2;
  431. km->prot = &ps2Prot;
  432. break;
  433. }
  434. if (init)
  435. MouseWriteBytes(km->iob.fd, init, strlen((char *)init), 100);
  436. /*
  437. * Flush out the available data to eliminate responses to the
  438. * initialization string. Make sure any partial event is
  439. * skipped
  440. */
  441. (void)ps2SkipInit(mi, ninit, FALSE);
  442. return TRUE;
  443. }
  444. static Bool busParse(KdMouseInfo * mi, unsigned char *ev, int ne)
  445. {
  446. Kmouse *km = mi->driver;
  447. int dx, dy;
  448. unsigned long flags;
  449. flags = KD_MOUSE_DELTA;
  450. dx = (signed char)ev[1];
  451. dy = -(signed char)ev[2];
  452. if ((ev[0] & 4) == 0)
  453. flags |= KD_BUTTON_1;
  454. if ((ev[0] & 2) == 0)
  455. flags |= KD_BUTTON_2;
  456. if ((ev[0] & 1) == 0)
  457. flags |= KD_BUTTON_3;
  458. if (!MouseReasonable(mi, flags, dx, dy))
  459. return FALSE;
  460. if (km->stage == MouseWorking)
  461. KdEnqueueMouseEvent(mi, flags, dx, dy);
  462. return TRUE;
  463. }
  464. static const KmouseProt busProt = {
  465. "bus",
  466. threeComplete, mouseValid, busParse, 0,
  467. 0xf8, 0x00, 0x00, 0x00,
  468. FALSE
  469. };
  470. /*
  471. * Standard MS serial protocol, three bytes
  472. */
  473. static Bool msParse(KdMouseInfo * mi, unsigned char *ev, int ne)
  474. {
  475. Kmouse *km = mi->driver;
  476. int dx, dy;
  477. unsigned long flags;
  478. flags = KD_MOUSE_DELTA;
  479. if (ev[0] & 0x20)
  480. flags |= KD_BUTTON_1;
  481. if (ev[0] & 0x10)
  482. flags |= KD_BUTTON_3;
  483. dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
  484. dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
  485. if (!MouseReasonable(mi, flags, dx, dy))
  486. return FALSE;
  487. if (km->stage == MouseWorking)
  488. KdEnqueueMouseEvent(mi, flags, dx, dy);
  489. return TRUE;
  490. }
  491. static const KmouseProt msProt = {
  492. "ms",
  493. threeComplete, mouseValid, msParse, 0,
  494. 0xc0, 0x40, 0xc0, 0x00,
  495. TRUE,
  496. IGNPAR,
  497. 0,
  498. 0,
  499. CS7 | CSTOPB | CREAD | CLOCAL,
  500. B1200,
  501. };
  502. /*
  503. * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the
  504. * first byte of a synchronized protocol stream and see if it's got
  505. * any bits turned on that can't occur in that fourth byte
  506. */
  507. static Bool logiComplete(KdMouseInfo * mi, unsigned char *ev, int ne)
  508. {
  509. Kmouse *km = mi->driver;
  510. if ((ev[0] & 0x40) == 0x40)
  511. return ne == 3;
  512. if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0)
  513. return ne == 1;
  514. return FALSE;
  515. }
  516. static int logiValid(KdMouseInfo * mi, unsigned char *ev, int ne)
  517. {
  518. Kmouse *km = mi->driver;
  519. const KmouseProt *prot = km->prot;
  520. int i;
  521. for (i = 0; i < ne; i++) {
  522. if ((ev[i] & 0x40) == 0x40)
  523. break;
  524. if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0)
  525. break;
  526. }
  527. if (i != 0)
  528. return i;
  529. for (i = 1; i < ne; i++)
  530. if ((ev[i] & prot->dataMask) != prot->dataValid)
  531. return -1;
  532. return 0;
  533. }
  534. static Bool logiParse(KdMouseInfo * mi, unsigned char *ev, int ne)
  535. {
  536. Kmouse *km = mi->driver;
  537. int dx, dy;
  538. unsigned long flags;
  539. flags = KD_MOUSE_DELTA;
  540. if (ne == 3) {
  541. if (ev[0] & 0x20)
  542. flags |= KD_BUTTON_1;
  543. if (ev[0] & 0x10)
  544. flags |= KD_BUTTON_3;
  545. dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
  546. dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
  547. flags |= km->state & KD_BUTTON_2;
  548. } else {
  549. if (ev[0] & 0x20)
  550. flags |= KD_BUTTON_2;
  551. dx = 0;
  552. dy = 0;
  553. flags |= km->state & (KD_BUTTON_1 | KD_BUTTON_3);
  554. }
  555. if (!MouseReasonable(mi, flags, dx, dy))
  556. return FALSE;
  557. if (km->stage == MouseWorking)
  558. KdEnqueueMouseEvent(mi, flags, dx, dy);
  559. return TRUE;
  560. }
  561. static const KmouseProt logiProt = {
  562. "logitech",
  563. logiComplete, logiValid, logiParse, 0,
  564. 0xc0, 0x40, 0xc0, 0x00,
  565. TRUE,
  566. IGNPAR,
  567. 0,
  568. 0,
  569. CS7 | CSTOPB | CREAD | CLOCAL,
  570. B1200,
  571. };
  572. /*
  573. * Mouse systems protocol, 5 bytes
  574. */
  575. static Bool mscParse(KdMouseInfo * mi, unsigned char *ev, int ne)
  576. {
  577. Kmouse *km = mi->driver;
  578. int dx, dy;
  579. unsigned long flags;
  580. flags = KD_MOUSE_DELTA;
  581. if (!(ev[0] & 0x4))
  582. flags |= KD_BUTTON_1;
  583. if (!(ev[0] & 0x2))
  584. flags |= KD_BUTTON_2;
  585. if (!(ev[0] & 0x1))
  586. flags |= KD_BUTTON_3;
  587. dx = (signed char)(ev[1]) + (signed char)(ev[3]);
  588. dy = -((signed char)(ev[2]) + (signed char)(ev[4]));
  589. if (!MouseReasonable(mi, flags, dx, dy))
  590. return FALSE;
  591. if (km->stage == MouseWorking)
  592. KdEnqueueMouseEvent(mi, flags, dx, dy);
  593. return TRUE;
  594. }
  595. static const KmouseProt mscProt = {
  596. "msc",
  597. fiveComplete, mouseValid, mscParse, 0,
  598. 0xf8, 0x80, 0x00, 0x00,
  599. TRUE,
  600. IGNPAR,
  601. 0,
  602. 0,
  603. CS8 | CSTOPB | CREAD | CLOCAL,
  604. B1200,
  605. };
  606. /*
  607. * Use logitech before ms -- they're the same except that
  608. * logitech sometimes has a fourth byte
  609. */
  610. static const KmouseProt *kmouseProts[] = {
  611. &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt,
  612. &mscProt,
  613. };
  614. #define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0]))
  615. static void MouseInitProtocol(Kmouse * km)
  616. {
  617. int ret;
  618. struct termios t;
  619. if (km->prot->tty) {
  620. ret = tcgetattr(km->iob.fd, &t);
  621. if (ret >= 0) {
  622. t.c_iflag = km->prot->c_iflag;
  623. t.c_oflag = km->prot->c_oflag;
  624. t.c_lflag = km->prot->c_lflag;
  625. t.c_cflag = km->prot->c_cflag;
  626. cfsetispeed(&t, km->prot->speed);
  627. cfsetospeed(&t, km->prot->speed);
  628. tcsetattr(km->iob.fd, TCSANOW, &t);
  629. }
  630. }
  631. km->stage = MouseBroken;
  632. km->valid = 0;
  633. km->tested = 0;
  634. km->invalid = 0;
  635. km->state = km->prot->state;
  636. }
  637. static void MouseFirstProtocol(Kmouse * km, char *prot)
  638. {
  639. if (prot) {
  640. for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++)
  641. if (!strcmp(prot, kmouseProts[km->i_prot]->name))
  642. break;
  643. if (km->i_prot == NUM_PROT) {
  644. int i;
  645. ErrorF("Unknown mouse protocol \"%s\". Pick one of:",
  646. prot);
  647. for (i = 0; i < NUM_PROT; i++)
  648. ErrorF(" %s", kmouseProts[i]->name);
  649. ErrorF("\n");
  650. } else {
  651. km->prot = kmouseProts[km->i_prot];
  652. if (km->tty && !km->prot->tty)
  653. ErrorF
  654. ("Mouse device is serial port, protocol %s is not serial protocol\n",
  655. prot);
  656. else if (!km->tty && km->prot->tty)
  657. ErrorF
  658. ("Mouse device is not serial port, protocol %s is serial protocol\n",
  659. prot);
  660. }
  661. }
  662. if (!km->prot) {
  663. for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty;
  664. km->i_prot++) ;
  665. km->prot = kmouseProts[km->i_prot];
  666. }
  667. MouseInitProtocol(km);
  668. }
  669. static void MouseNextProtocol(Kmouse * km)
  670. {
  671. do {
  672. if (!km->prot)
  673. km->i_prot = 0;
  674. else if (++km->i_prot == NUM_PROT)
  675. km->i_prot = 0;
  676. km->prot = kmouseProts[km->i_prot];
  677. } while (km->prot->tty != km->tty);
  678. MouseInitProtocol(km);
  679. ErrorF("Switching to mouse protocol \"%s\"\n", km->prot->name);
  680. }
  681. static void MouseRead(int mousePort, void *closure)
  682. {
  683. KdMouseInfo *mi = closure;
  684. Kmouse *km = mi->driver;
  685. unsigned char event[MAX_MOUSE];
  686. int ne;
  687. int c;
  688. int i;
  689. int timeout;
  690. timeout = 0;
  691. ne = 0;
  692. for (;;) {
  693. c = MouseReadByte(&km->iob, timeout);
  694. if (c == -1) {
  695. if (ne) {
  696. km->invalid += ne + km->tested;
  697. km->valid = 0;
  698. km->tested = 0;
  699. km->stage = MouseBroken;
  700. }
  701. break;
  702. }
  703. event[ne++] = c;
  704. i = (*km->prot->Valid) (mi, event, ne);
  705. if (i != 0) {
  706. #ifdef DEBUG
  707. ErrorF("Mouse protocol %s broken %d of %d bytes bad\n",
  708. km->prot->name, i > 0 ? i : ne, ne);
  709. #endif
  710. if (i > 0 && i < ne) {
  711. ne -= i;
  712. memmove(event, event + i, ne);
  713. } else {
  714. i = ne;
  715. ne = 0;
  716. }
  717. km->invalid += i + km->tested;
  718. km->valid = 0;
  719. km->tested = 0;
  720. if (km->stage == MouseWorking)
  721. km->i_prot--;
  722. km->stage = MouseBroken;
  723. if (km->invalid > MAX_SKIP) {
  724. MouseNextProtocol(km);
  725. ne = 0;
  726. }
  727. timeout = 0;
  728. } else {
  729. if ((*km->prot->Complete) (mi, event, ne)) {
  730. if ((*km->prot->Parse) (mi, event, ne)) {
  731. switch (km->stage) {
  732. case MouseBroken:
  733. #ifdef DEBUG
  734. ErrorF
  735. ("Mouse protocol %s seems OK\n",
  736. km->prot->name);
  737. #endif
  738. /* do not zero invalid to accumulate invalid bytes */
  739. km->valid = 0;
  740. km->tested = 0;
  741. km->stage = MouseTesting;
  742. /* fall through ... */
  743. case MouseTesting:
  744. km->valid++;
  745. km->tested += ne;
  746. if (km->valid > MAX_VALID) {
  747. #ifdef DEBUG
  748. ErrorF
  749. ("Mouse protocol %s working\n",
  750. km->prot->name);
  751. #endif
  752. km->stage =
  753. MouseWorking;
  754. km->invalid = 0;
  755. km->tested = 0;
  756. km->valid = 0;
  757. if (km->prot->Init
  758. && !(*km->prot->
  759. Init) (mi))
  760. km->stage =
  761. MouseBroken;
  762. }
  763. break;
  764. case MouseWorking:
  765. break;
  766. }
  767. } else {
  768. km->invalid += ne + km->tested;
  769. km->valid = 0;
  770. km->tested = 0;
  771. km->stage = MouseBroken;
  772. }
  773. ne = 0;
  774. timeout = 0;
  775. } else
  776. timeout = MOUSE_TIMEOUT;
  777. }
  778. }
  779. }
  780. static int MouseInputType;
  781. const char * const kdefaultMouse[] = {
  782. "/dev/mouse",
  783. "/dev/psaux",
  784. "/dev/input/mice",
  785. "/dev/adbmouse",
  786. "/dev/ttyS0",
  787. "/dev/ttyS1",
  788. };
  789. #define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))
  790. static Bool MouseInit(void)
  791. {
  792. int i;
  793. int fd = -1;
  794. Kmouse *km;
  795. KdMouseInfo *mi, *next;
  796. int n = 0;
  797. if (!MouseInputType)
  798. MouseInputType = KdAllocInputType();
  799. for (mi = kdMouseInfo; mi; mi = next) {
  800. next = mi->next;
  801. if (mi->inputType)
  802. continue;
  803. if (!mi->name) {
  804. for (i = 0; i < NUM_DEFAULT_MOUSE; i++) {
  805. fd = open(kdefaultMouse[i], 2);
  806. if (fd >= 0) {
  807. mi->name = strdup(kdefaultMouse[i]);
  808. break;
  809. }
  810. }
  811. } else
  812. fd = open(mi->name, 2);
  813. if (fd >= 0) {
  814. km = malloc(sizeof(Kmouse));
  815. if (km) {
  816. km->iob.fd = fd;
  817. km->iob.avail = km->iob.used = 0;
  818. km->prot = 0;
  819. km->i_prot = 0;
  820. km->tty = isatty(fd);
  821. mi->driver = km;
  822. mi->inputType = MouseInputType;
  823. MouseFirstProtocol(km, mi->prot);
  824. if (KdRegisterFd
  825. (MouseInputType, fd, MouseRead, (void *)mi))
  826. n++;
  827. } else
  828. close(fd);
  829. }
  830. }
  831. return TRUE;
  832. }
  833. static void MouseFini(void)
  834. {
  835. KdMouseInfo *mi;
  836. KdUnregisterFds(MouseInputType, TRUE);
  837. for (mi = kdMouseInfo; mi; mi = mi->next) {
  838. if (mi->inputType == MouseInputType) {
  839. free(mi->driver);
  840. mi->driver = 0;
  841. mi->inputType = 0;
  842. }
  843. }
  844. }
  845. const KdMouseFuncs LinuxMouseFuncs = {
  846. MouseInit,
  847. MouseFini,
  848. };