Annotation of sys/dev/hil/hilms.c, Revision 1.1.1.1
1.1 nbrk 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:
29: #include <sys/param.h>
30: #include <sys/systm.h>
31: #include <sys/device.h>
32: #include <sys/ioctl.h>
33:
34: #include <machine/autoconf.h>
35: #include <machine/bus.h>
36: #include <machine/cpu.h>
37:
38: #include <dev/hil/hilreg.h>
39: #include <dev/hil/hilvar.h>
40: #include <dev/hil/hildevs.h>
41:
42: #include <dev/wscons/wsconsio.h>
43: #include <dev/wscons/wsmousevar.h>
44:
45: struct hilms_softc {
46: struct hildev_softc sc_hildev;
47:
48: int sc_features;
49: u_int sc_buttons;
50: u_int sc_axes;
51: int sc_enabled;
52: int sc_buttonstate;
53:
54: struct device *sc_wsmousedev;
55: };
56:
57: int hilmsprobe(struct device *, void *, void *);
58: void hilmsattach(struct device *, struct device *, void *);
59: int hilmsdetach(struct device *, int);
60:
61: struct cfdriver hilms_cd = {
62: NULL, "hilms", DV_DULL
63: };
64:
65: struct cfattach hilms_ca = {
66: sizeof(struct hilms_softc), hilmsprobe, hilmsattach, hilmsdetach,
67: };
68:
69: int hilms_enable(void *);
70: int hilms_ioctl(void *, u_long, caddr_t, int, struct proc *);
71: void hilms_disable(void *);
72:
73: const struct wsmouse_accessops hilms_accessops = {
74: hilms_enable,
75: hilms_ioctl,
76: hilms_disable,
77: };
78:
79: void hilms_callback(struct hildev_softc *, u_int, u_int8_t *);
80:
81: int
82: hilmsprobe(struct device *parent, void *match, void *aux)
83: {
84: struct hil_attach_args *ha = aux;
85:
86: if (ha->ha_type != HIL_DEVICE_MOUSE)
87: return (0);
88:
89: /*
90: * Reject anything that has only buttons - they are handled as
91: * keyboards, really.
92: */
93: if (ha->ha_infolen > 1 && (ha->ha_info[1] & HIL_AXMASK) == 0)
94: return (0);
95:
96: return (1);
97: }
98:
99: void
100: hilmsattach(struct device *parent, struct device *self, void *aux)
101: {
102: struct hilms_softc *sc = (void *)self;
103: struct hil_attach_args *ha = aux;
104: struct wsmousedev_attach_args a;
105: int iob, rx, ry;
106:
107: sc->hd_code = ha->ha_code;
108: sc->hd_type = ha->ha_type;
109: sc->hd_infolen = ha->ha_infolen;
110: bcopy(ha->ha_info, sc->hd_info, ha->ha_infolen);
111: sc->hd_fn = hilms_callback;
112:
113: /*
114: * Interpret the identification bytes, if any
115: */
116: rx = ry = 0;
117: if (ha->ha_infolen > 1) {
118: sc->sc_features = ha->ha_info[1];
119: sc->sc_axes = sc->sc_features & HIL_AXMASK;
120:
121: if (sc->sc_features & HIL_IOB) {
122: /* skip resolution bytes */
123: iob = 4;
124: if (sc->sc_features & HIL_ABSOLUTE) {
125: /* skip ranges */
126: rx = ha->ha_info[4] | (ha->ha_info[5] << 8);
127: if (sc->sc_axes > 1)
128: ry = ha->ha_info[6] |
129: (ha->ha_info[7] << 8);
130: iob += 2 * sc->sc_axes;
131: }
132:
133: if (iob >= ha->ha_infolen) {
134: sc->sc_features &= ~(HIL_IOB | HILIOB_PIO);
135: } else {
136: iob = ha->ha_info[iob];
137: sc->sc_buttons = iob & HILIOB_BMASK;
138: sc->sc_features |= (iob & HILIOB_PIO);
139: }
140: }
141: }
142:
143: printf(", %d axes", sc->sc_axes);
144: if (sc->sc_buttons == 1)
145: printf(", 1 button");
146: else if (sc->sc_buttons > 1)
147: printf(", %d buttons", sc->sc_buttons);
148: if (sc->sc_features & HILIOB_PIO)
149: printf(", pressure sensor");
150: if (sc->sc_features & HIL_ABSOLUTE) {
151: printf ("\n%s: %d", self->dv_xname, rx);
152: if (ry != 0)
153: printf("x%d", ry);
154: else
155: printf(" linear");
156: printf(" fixed area");
157: }
158:
159: printf("\n");
160:
161: sc->sc_enabled = 0;
162:
163: a.accessops = &hilms_accessops;
164: a.accesscookie = sc;
165:
166: sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
167: }
168:
169: int
170: hilmsdetach(struct device *self, int flags)
171: {
172: struct hilms_softc *sc = (void *)self;
173:
174: if (sc->sc_wsmousedev != NULL)
175: return config_detach(sc->sc_wsmousedev, flags);
176:
177: return (0);
178: }
179:
180: int
181: hilms_enable(void *v)
182: {
183: struct hilms_softc *sc = v;
184:
185: if (sc->sc_enabled)
186: return EBUSY;
187:
188: sc->sc_enabled = 1;
189: sc->sc_buttonstate = 0;
190:
191: return (0);
192: }
193:
194: void
195: hilms_disable(void *v)
196: {
197: struct hilms_softc *sc = v;
198:
199: sc->sc_enabled = 0;
200: }
201:
202: int
203: hilms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
204: {
205: #if 0
206: struct hilms_softc *sc = v;
207: #endif
208:
209: switch (cmd) {
210: case WSMOUSEIO_GTYPE:
211: *(int *)data = WSMOUSE_TYPE_HIL;
212: return 0;
213: }
214:
215: return -1;
216: }
217:
218: void
219: hilms_callback(struct hildev_softc *dev, u_int buflen, u_int8_t *buf)
220: {
221: struct hilms_softc *sc = (struct hilms_softc *)dev;
222: int type, flags;
223: int dx, dy, dz, button;
224: #ifdef DIAGNOSTIC
225: int minlen;
226: #endif
227:
228: /*
229: * Ignore packet if we don't need it
230: */
231: if (sc->sc_enabled == 0)
232: return;
233:
234: type = *buf++;
235:
236: #ifdef DIAGNOSTIC
237: /*
238: * Check that the packet contains all the expected data,
239: * ignore it if too short.
240: */
241: minlen = 1;
242: if (type & HIL_MOUSEMOTION) {
243: minlen += sc->sc_axes <<
244: (sc->sc_features & HIL_16_BITS) ? 1 : 0;
245: }
246: if (type & HIL_MOUSEBUTTON)
247: minlen++;
248:
249: if (minlen > buflen)
250: return;
251: #endif
252:
253: /*
254: * The packet can contain both a mouse motion and a button event.
255: * In this case, the motion data comes first.
256: */
257:
258: if (type & HIL_MOUSEMOTION) {
259: flags = sc->sc_features & HIL_ABSOLUTE ?
260: WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y |
261: WSMOUSE_INPUT_ABSOLUTE_Z : WSMOUSE_INPUT_DELTA;
262: if (sc->sc_features & HIL_16_BITS) {
263: dx = *buf++;
264: dx |= (*buf++) << 8;
265: if (!(sc->sc_features & HIL_ABSOLUTE))
266: dx = (int16_t)dx;
267: } else {
268: dx = *buf++;
269: if (!(sc->sc_features & HIL_ABSOLUTE))
270: dx = (int8_t)dx;
271: }
272: if (sc->sc_axes > 1) {
273: if (sc->sc_features & HIL_16_BITS) {
274: dy = *buf++;
275: dy |= (*buf++) << 8;
276: if (!(sc->sc_features & HIL_ABSOLUTE))
277: dy = (int16_t)dy;
278: } else {
279: dy = *buf++;
280: if (!(sc->sc_features & HIL_ABSOLUTE))
281: dy = (int8_t)dy;
282: }
283: if (sc->sc_axes > 2) {
284: if (sc->sc_features & HIL_16_BITS) {
285: dz = *buf++;
286: dz |= (*buf++) << 8;
287: if (!(sc->sc_features & HIL_ABSOLUTE))
288: dz = (int16_t)dz;
289: } else {
290: dz = *buf++;
291: if (!(sc->sc_features & HIL_ABSOLUTE))
292: dz = (int8_t)dz;
293: }
294: } else
295: dz = 0;
296: } else
297: dy = dz = 0;
298:
299: /*
300: * Correct Y direction for button boxes.
301: */
302: if ((sc->sc_features & HIL_ABSOLUTE) == 0 &&
303: sc->sc_buttons == 0)
304: dy = -dy;
305: } else
306: dx = dy = dz = flags = 0;
307:
308: if (type & HIL_MOUSEBUTTON) {
309: button = *buf;
310: /*
311: * The pressure sensor is very primitive and only has
312: * a boolean behaviour, as an extra mouse button, which is
313: * down if there is pressure or the pen is near the tablet,
314: * and up if there is no pressure or the pen is far from the
315: * tablet - at least for Tablet id 0x94, P/N 46088B
316: *
317: * The corresponding codes are 0x8f and 0x8e. Convert them
318: * to a pseudo fourth button - even if the tablet never
319: * has three buttons.
320: */
321: button = (button - 0x80) >> 1;
322: if (button > 4)
323: button = 4;
324:
325: if (*buf & 1) {
326: /* Button released, or no pressure */
327: sc->sc_buttonstate &= ~(1 << button);
328: } else {
329: /* Button pressed, or pressure */
330: sc->sc_buttonstate |= (1 << button);
331: }
332: /* buf++; */
333: }
334:
335: if (sc->sc_wsmousedev != NULL)
336: wsmouse_input(sc->sc_wsmousedev,
337: sc->sc_buttonstate, dx, dy, dz, 0, flags);
338: }
CVSweb