hilms.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /* $OpenBSD: hilms.c,v 1.5 2007/04/10 22:37:17 miod Exp $ */
  2. /*
  3. * Copyright (c) 2003, 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
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  19. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  24. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. *
  27. */
  28. #include <sys/param.h>
  29. #include <sys/systm.h>
  30. #include <sys/device.h>
  31. #include <sys/ioctl.h>
  32. #include <machine/autoconf.h>
  33. #include <machine/bus.h>
  34. #include <machine/cpu.h>
  35. #include <dev/hil/hilreg.h>
  36. #include <dev/hil/hilvar.h>
  37. #include <dev/hil/hildevs.h>
  38. #include <dev/wscons/wsconsio.h>
  39. #include <dev/wscons/wsmousevar.h>
  40. struct hilms_softc {
  41. struct hildev_softc sc_hildev;
  42. int sc_features;
  43. u_int sc_buttons;
  44. u_int sc_axes;
  45. int sc_enabled;
  46. int sc_buttonstate;
  47. struct device *sc_wsmousedev;
  48. };
  49. int hilmsprobe(struct device *, void *, void *);
  50. void hilmsattach(struct device *, struct device *, void *);
  51. int hilmsdetach(struct device *, int);
  52. struct cfdriver hilms_cd = {
  53. NULL, "hilms", DV_DULL
  54. };
  55. struct cfattach hilms_ca = {
  56. sizeof(struct hilms_softc), hilmsprobe, hilmsattach, hilmsdetach,
  57. };
  58. int hilms_enable(void *);
  59. int hilms_ioctl(void *, u_long, caddr_t, int, struct proc *);
  60. void hilms_disable(void *);
  61. const struct wsmouse_accessops hilms_accessops = {
  62. hilms_enable,
  63. hilms_ioctl,
  64. hilms_disable,
  65. };
  66. void hilms_callback(struct hildev_softc *, u_int, u_int8_t *);
  67. int
  68. hilmsprobe(struct device *parent, void *match, void *aux)
  69. {
  70. struct hil_attach_args *ha = aux;
  71. if (ha->ha_type != HIL_DEVICE_MOUSE)
  72. return (0);
  73. /*
  74. * Reject anything that has only buttons - they are handled as
  75. * keyboards, really.
  76. */
  77. if (ha->ha_infolen > 1 && (ha->ha_info[1] & HIL_AXMASK) == 0)
  78. return (0);
  79. return (1);
  80. }
  81. void
  82. hilmsattach(struct device *parent, struct device *self, void *aux)
  83. {
  84. struct hilms_softc *sc = (void *)self;
  85. struct hil_attach_args *ha = aux;
  86. struct wsmousedev_attach_args a;
  87. int iob, rx, ry;
  88. sc->hd_code = ha->ha_code;
  89. sc->hd_type = ha->ha_type;
  90. sc->hd_infolen = ha->ha_infolen;
  91. bcopy(ha->ha_info, sc->hd_info, ha->ha_infolen);
  92. sc->hd_fn = hilms_callback;
  93. /*
  94. * Interpret the identification bytes, if any
  95. */
  96. rx = ry = 0;
  97. if (ha->ha_infolen > 1) {
  98. sc->sc_features = ha->ha_info[1];
  99. sc->sc_axes = sc->sc_features & HIL_AXMASK;
  100. if (sc->sc_features & HIL_IOB) {
  101. /* skip resolution bytes */
  102. iob = 4;
  103. if (sc->sc_features & HIL_ABSOLUTE) {
  104. /* skip ranges */
  105. rx = ha->ha_info[4] | (ha->ha_info[5] << 8);
  106. if (sc->sc_axes > 1)
  107. ry = ha->ha_info[6] |
  108. (ha->ha_info[7] << 8);
  109. iob += 2 * sc->sc_axes;
  110. }
  111. if (iob >= ha->ha_infolen) {
  112. sc->sc_features &= ~(HIL_IOB | HILIOB_PIO);
  113. } else {
  114. iob = ha->ha_info[iob];
  115. sc->sc_buttons = iob & HILIOB_BMASK;
  116. sc->sc_features |= (iob & HILIOB_PIO);
  117. }
  118. }
  119. }
  120. printf(", %d axes", sc->sc_axes);
  121. if (sc->sc_buttons == 1)
  122. printf(", 1 button");
  123. else if (sc->sc_buttons > 1)
  124. printf(", %d buttons", sc->sc_buttons);
  125. if (sc->sc_features & HILIOB_PIO)
  126. printf(", pressure sensor");
  127. if (sc->sc_features & HIL_ABSOLUTE) {
  128. printf ("\n%s: %d", self->dv_xname, rx);
  129. if (ry != 0)
  130. printf("x%d", ry);
  131. else
  132. printf(" linear");
  133. printf(" fixed area");
  134. }
  135. printf("\n");
  136. sc->sc_enabled = 0;
  137. a.accessops = &hilms_accessops;
  138. a.accesscookie = sc;
  139. sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
  140. }
  141. int
  142. hilmsdetach(struct device *self, int flags)
  143. {
  144. struct hilms_softc *sc = (void *)self;
  145. if (sc->sc_wsmousedev != NULL)
  146. return config_detach(sc->sc_wsmousedev, flags);
  147. return (0);
  148. }
  149. int
  150. hilms_enable(void *v)
  151. {
  152. struct hilms_softc *sc = v;
  153. if (sc->sc_enabled)
  154. return EBUSY;
  155. sc->sc_enabled = 1;
  156. sc->sc_buttonstate = 0;
  157. return (0);
  158. }
  159. void
  160. hilms_disable(void *v)
  161. {
  162. struct hilms_softc *sc = v;
  163. sc->sc_enabled = 0;
  164. }
  165. int
  166. hilms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  167. {
  168. #if 0
  169. struct hilms_softc *sc = v;
  170. #endif
  171. switch (cmd) {
  172. case WSMOUSEIO_GTYPE:
  173. *(int *)data = WSMOUSE_TYPE_HIL;
  174. return 0;
  175. }
  176. return -1;
  177. }
  178. void
  179. hilms_callback(struct hildev_softc *dev, u_int buflen, u_int8_t *buf)
  180. {
  181. struct hilms_softc *sc = (struct hilms_softc *)dev;
  182. int type, flags;
  183. int dx, dy, dz, button;
  184. #ifdef DIAGNOSTIC
  185. int minlen;
  186. #endif
  187. /*
  188. * Ignore packet if we don't need it
  189. */
  190. if (sc->sc_enabled == 0)
  191. return;
  192. type = *buf++;
  193. #ifdef DIAGNOSTIC
  194. /*
  195. * Check that the packet contains all the expected data,
  196. * ignore it if too short.
  197. */
  198. minlen = 1;
  199. if (type & HIL_MOUSEMOTION) {
  200. minlen += sc->sc_axes <<
  201. (sc->sc_features & HIL_16_BITS) ? 1 : 0;
  202. }
  203. if (type & HIL_MOUSEBUTTON)
  204. minlen++;
  205. if (minlen > buflen)
  206. return;
  207. #endif
  208. /*
  209. * The packet can contain both a mouse motion and a button event.
  210. * In this case, the motion data comes first.
  211. */
  212. if (type & HIL_MOUSEMOTION) {
  213. flags = sc->sc_features & HIL_ABSOLUTE ?
  214. WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y |
  215. WSMOUSE_INPUT_ABSOLUTE_Z : WSMOUSE_INPUT_DELTA;
  216. if (sc->sc_features & HIL_16_BITS) {
  217. dx = *buf++;
  218. dx |= (*buf++) << 8;
  219. if (!(sc->sc_features & HIL_ABSOLUTE))
  220. dx = (int16_t)dx;
  221. } else {
  222. dx = *buf++;
  223. if (!(sc->sc_features & HIL_ABSOLUTE))
  224. dx = (int8_t)dx;
  225. }
  226. if (sc->sc_axes > 1) {
  227. if (sc->sc_features & HIL_16_BITS) {
  228. dy = *buf++;
  229. dy |= (*buf++) << 8;
  230. if (!(sc->sc_features & HIL_ABSOLUTE))
  231. dy = (int16_t)dy;
  232. } else {
  233. dy = *buf++;
  234. if (!(sc->sc_features & HIL_ABSOLUTE))
  235. dy = (int8_t)dy;
  236. }
  237. if (sc->sc_axes > 2) {
  238. if (sc->sc_features & HIL_16_BITS) {
  239. dz = *buf++;
  240. dz |= (*buf++) << 8;
  241. if (!(sc->sc_features & HIL_ABSOLUTE))
  242. dz = (int16_t)dz;
  243. } else {
  244. dz = *buf++;
  245. if (!(sc->sc_features & HIL_ABSOLUTE))
  246. dz = (int8_t)dz;
  247. }
  248. } else
  249. dz = 0;
  250. } else
  251. dy = dz = 0;
  252. /*
  253. * Correct Y direction for button boxes.
  254. */
  255. if ((sc->sc_features & HIL_ABSOLUTE) == 0 &&
  256. sc->sc_buttons == 0)
  257. dy = -dy;
  258. } else
  259. dx = dy = dz = flags = 0;
  260. if (type & HIL_MOUSEBUTTON) {
  261. button = *buf;
  262. /*
  263. * The pressure sensor is very primitive and only has
  264. * a boolean behaviour, as an extra mouse button, which is
  265. * down if there is pressure or the pen is near the tablet,
  266. * and up if there is no pressure or the pen is far from the
  267. * tablet - at least for Tablet id 0x94, P/N 46088B
  268. *
  269. * The corresponding codes are 0x8f and 0x8e. Convert them
  270. * to a pseudo fourth button - even if the tablet never
  271. * has three buttons.
  272. */
  273. button = (button - 0x80) >> 1;
  274. if (button > 4)
  275. button = 4;
  276. if (*buf & 1) {
  277. /* Button released, or no pressure */
  278. sc->sc_buttonstate &= ~(1 << button);
  279. } else {
  280. /* Button pressed, or pressure */
  281. sc->sc_buttonstate |= (1 << button);
  282. }
  283. /* buf++; */
  284. }
  285. if (sc->sc_wsmousedev != NULL)
  286. wsmouse_input(sc->sc_wsmousedev,
  287. sc->sc_buttonstate, dx, dy, dz, 0, flags);
  288. }