sunms.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /* $OpenBSD: sunms.c,v 1.1 2009/05/20 18:22:33 miod Exp $ */
  2. /*
  3. * Copyright (c) 2002, 2009, Miodrag Vallat
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. /*
  27. * Common Sun mouse handling code.
  28. *
  29. * This code supports 3- and 5- byte Mouse Systems protocols, and speeds of
  30. * 1200, 4800 and 9600 bps.
  31. */
  32. #include <sys/param.h>
  33. #include <sys/systm.h>
  34. #include <sys/conf.h>
  35. #include <sys/device.h>
  36. #include <sys/ioctl.h>
  37. #include <sys/kernel.h>
  38. #include <sys/proc.h>
  39. #include <sys/time.h>
  40. #include <sys/timeout.h>
  41. #include <dev/wscons/wsconsio.h>
  42. #include <dev/wscons/wsmousevar.h>
  43. #include <dev/sun/sunmsvar.h>
  44. void
  45. sunms_attach(struct sunms_softc *sc, const struct wsmouse_accessops *ao)
  46. {
  47. struct wsmousedev_attach_args a;
  48. printf("\n");
  49. /* Initialize state machine. */
  50. sc->sc_state = STATE_PROBING;
  51. sc->sc_bps = INIT_SPEED;
  52. timeout_set(&sc->sc_abort_tmo, sunms_abort_input, sc);
  53. /*
  54. * Note that it doesn't matter if a long time elapses between this
  55. * and the moment interrupts are enabled, as we either have the
  56. * right speed, and will switch to decode state, or get a break
  57. * or a framing error, causing an immediate speed change.
  58. */
  59. getmicrotime(&sc->sc_lastbpschange);
  60. a.accessops = ao;
  61. a.accesscookie = sc;
  62. sc->sc_wsmousedev = config_found(&sc->sc_dev, &a, wsmousedevprint);
  63. }
  64. int
  65. sunms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  66. {
  67. #if 0
  68. struct sunms_softc *sc = v;
  69. #endif
  70. switch (cmd) {
  71. case WSMOUSEIO_GTYPE:
  72. *(u_int *)data = WSMOUSE_TYPE_SUN;
  73. break;
  74. default:
  75. return -1;
  76. }
  77. return 0;
  78. }
  79. /*
  80. * Reinitialize the line to a different speed. Invoked at spltty().
  81. */
  82. void
  83. sunms_speed_change(struct sunms_softc *sc)
  84. {
  85. uint bps;
  86. switch (sc->sc_bps) {
  87. default:
  88. case 9600:
  89. bps = 4800;
  90. break;
  91. case 4800:
  92. bps = 1200;
  93. break;
  94. case 1200:
  95. bps = 9600;
  96. break;
  97. }
  98. #ifdef DEBUG
  99. printf("%s: %d bps\n", sc->sc_dev.dv_xname, bps);
  100. #endif
  101. microtime(&sc->sc_lastbpschange);
  102. (*sc->sc_speed_change)(sc, bps);
  103. sc->sc_state = STATE_PROBING;
  104. sc->sc_bps = bps;
  105. sc->sc_brk = 0;
  106. timeout_del(&sc->sc_abort_tmo);
  107. }
  108. /*
  109. * Process actual mouse data. Invoked at spltty().
  110. */
  111. void
  112. sunms_input(struct sunms_softc *sc, int c)
  113. {
  114. struct timeval curtime;
  115. if (sc->sc_wsmousedev == NULL)
  116. return; /* why bother */
  117. if (sc->sc_state == STATE_RATE_CHANGE)
  118. return; /* not ready yet */
  119. /*
  120. * If we have changed speed recently, ignore data for a few
  121. * milliseconds to make sure that either we'll detect the speed
  122. * is still not correct, or discard potential noise resulting
  123. * from the speed change.
  124. */
  125. if (sc->sc_state == STATE_PROBING) {
  126. microtime(&curtime);
  127. timersub(&curtime, &sc->sc_lastbpschange, &curtime);
  128. if (curtime.tv_sec != 0 ||
  129. curtime.tv_usec >= 200 * 1000) {
  130. sc->sc_state = STATE_DECODING;
  131. sc->sc_byteno = -1;
  132. } else
  133. return;
  134. }
  135. /*
  136. * The Sun mice use either 3 byte or 5 byte packets. The
  137. * first byte of each packet has the topmost bit set;
  138. * however motion parts of the packet may have the topmost
  139. * bit set too; so we only check for a first byte pattern
  140. * when we are not currently processing a packet.
  141. */
  142. if (sc->sc_byteno < 0) {
  143. if (ISSET(c, 0x80) && !ISSET(c, 0x30))
  144. sc->sc_byteno = 0;
  145. else
  146. return;
  147. }
  148. switch (sc->sc_byteno) {
  149. case 0:
  150. /*
  151. * First packet has bit 7 set; bits 0-2 are button states,
  152. * and bit 3 is set if it is a short (3 byte) packet.
  153. * On the Tadpole SPARCbook, mice connected to the external
  154. * connector will also have bit 6 set to allow it to be
  155. * differenciated from the onboard pointer.
  156. */
  157. sc->sc_pktlen = ISSET(c, 0x08) ? 3 : 5;
  158. sc->sc_mb = 0;
  159. if (!ISSET(c, 1 << 2)) /* left button */
  160. sc->sc_mb |= 1 << 0;
  161. if (!ISSET(c, 1 << 1)) /* middle button */
  162. sc->sc_mb |= 1 << 1;
  163. if (!ISSET(c, 1 << 0)) /* right button */
  164. sc->sc_mb |= 1 << 2;
  165. sc->sc_byteno++;
  166. /*
  167. * In case we do not receive the whole packet, we need
  168. * to be able to reset sc_byteno.
  169. *
  170. * At 1200bps 8N2, a five byte packet will span 50 bits
  171. * and thus will transmit in 1/24 second, or about 42ms.
  172. *
  173. * A reset timeout of 100ms will be more than enough.
  174. */
  175. timeout_add_msec(&sc->sc_abort_tmo, 100);
  176. break;
  177. case 1:
  178. case 3:
  179. /*
  180. * Following bytes contain signed 7 bit X, then Y deltas.
  181. * Short packets only have one set of deltas (and are
  182. * thus usually used on 4800 baud mice).
  183. */
  184. sc->sc_dx += (int8_t)c;
  185. sc->sc_byteno++;
  186. break;
  187. case 2:
  188. case 4:
  189. sc->sc_dy += (int8_t)c;
  190. sc->sc_byteno++;
  191. break;
  192. }
  193. if (sc->sc_byteno == sc->sc_pktlen) {
  194. timeout_del(&sc->sc_abort_tmo);
  195. sc->sc_byteno = -1;
  196. wsmouse_input(sc->sc_wsmousedev, sc->sc_mb,
  197. sc->sc_dx, sc->sc_dy, 0, 0, WSMOUSE_INPUT_DELTA);
  198. sc->sc_dx = sc->sc_dy = 0;
  199. }
  200. }
  201. void
  202. sunms_abort_input(void *v)
  203. {
  204. struct sunms_softc *sc = v;
  205. int s;
  206. #ifdef DEBUG
  207. printf("aborting incomplete packet\n");
  208. #endif
  209. s = spltty();
  210. sc->sc_byteno = -1;
  211. splx(s);
  212. }