Annotation of sys/dev/pckbc/pms_intelli.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pms_intelli.c,v 1.1 2007/08/01 12:16:59 kettenis Exp $ */
2: /* $NetBSD: psm_intelli.c,v 1.8 2000/06/05 22:20:57 sommerfeld Exp $ */
3:
4: /*-
5: * Copyright (c) 1994 Charles M. Hannum.
6: * Copyright (c) 1992, 1993 Erik Forsberg.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: *
15: * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18: * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: #include <sys/param.h>
28: #include <sys/systm.h>
29: #include <sys/device.h>
30: #include <sys/ioctl.h>
31:
32: #include <machine/bus.h>
33:
34: #include <dev/ic/pckbcvar.h>
35:
36: #include <dev/pckbc/pmsreg.h>
37:
38: #include <dev/wscons/wsconsio.h>
39: #include <dev/wscons/wsmousevar.h>
40:
41: struct pmsi_softc { /* driver status information */
42: struct device sc_dev;
43:
44: pckbc_tag_t sc_kbctag;
45: int sc_kbcslot;
46:
47: int sc_enabled; /* input enabled? */
48: int inputstate;
49: u_int buttons, oldbuttons; /* mouse button status */
50: signed char dx, dy;
51:
52: struct device *sc_wsmousedev;
53: };
54:
55: int pmsiprobe(struct device *, void *, void *);
56: void pmsiattach(struct device *, struct device *, void *);
57: void pmsiinput(void *, int);
58:
59: struct cfattach pmsi_ca = {
60: sizeof(struct pmsi_softc), pmsiprobe, pmsiattach,
61: };
62:
63: int pmsi_enable(void *);
64: int pmsi_ioctl(void *, u_long, caddr_t, int, struct proc *);
65: void pmsi_disable(void *);
66:
67: const struct wsmouse_accessops pmsi_accessops = {
68: pmsi_enable,
69: pmsi_ioctl,
70: pmsi_disable,
71: };
72:
73: static int pmsi_setintellimode(pckbc_tag_t, pckbc_slot_t);
74:
75: static int
76: pmsi_setintellimode(tag, slot)
77: pckbc_tag_t tag;
78: pckbc_slot_t slot;
79: {
80: u_char cmd[2], resp[1];
81: int i, res;
82: static u_char rates[] = {200, 100, 80};
83:
84: cmd[0] = PMS_SET_SAMPLE;
85: for (i = 0; i < 3; i++) {
86: cmd[1] = rates[i];
87: res = pckbc_poll_cmd(tag, slot, cmd, 2, 0, 0, 0);
88: if (res)
89: return (res);
90: }
91:
92: cmd[0] = PMS_SEND_DEV_ID;
93: res = pckbc_poll_cmd(tag, slot, cmd, 1, 1, resp, 0);
94: if (res)
95: return (res);
96: if (resp[0] != 3)
97: return (ENXIO);
98:
99: return (0);
100: }
101:
102: int
103: pmsiprobe(parent, match, aux)
104: struct device *parent;
105: void *match;
106: void *aux;
107: {
108: struct pckbc_attach_args *pa = aux;
109: u_char cmd[1], resp[2];
110: int res;
111:
112: if (pa->pa_slot != PCKBC_AUX_SLOT)
113: return (0);
114:
115: /* Flush any garbage. */
116: pckbc_flush(pa->pa_tag, pa->pa_slot);
117:
118: /* reset the device */
119: cmd[0] = PMS_RESET;
120: res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
121: if (res) {
122: #ifdef DEBUG
123: printf("pmsiprobe: reset error %d\n", res);
124: #endif
125: return (0);
126: }
127: if (resp[0] != PMS_RSTDONE) {
128: printf("pmsiprobe: reset response 0x%x\n", resp[0]);
129: return (0);
130: }
131:
132: /* get type number (0 = mouse) */
133: if (resp[1] != 0) {
134: #ifdef DEBUG
135: printf("pmsiprobe: type 0x%x\n", resp[1]);
136: #endif
137: return (0);
138: }
139:
140: if ((res = pmsi_setintellimode(pa->pa_tag, pa->pa_slot))) {
141: #ifdef DEBUG
142: printf("pmsiprobe: intellimode -> %d\n", res);
143: #endif
144: return (0);
145: }
146:
147: return (20);
148: }
149:
150: void
151: pmsiattach(parent, self, aux)
152: struct device *parent, *self;
153: void *aux;
154: {
155: struct pmsi_softc *sc = (void *)self;
156: struct pckbc_attach_args *pa = aux;
157: struct wsmousedev_attach_args a;
158: u_char cmd[1], resp[2];
159: int res;
160:
161: sc->sc_kbctag = pa->pa_tag;
162: sc->sc_kbcslot = pa->pa_slot;
163:
164: printf("\n");
165:
166: /* Flush any garbage. */
167: pckbc_flush(pa->pa_tag, pa->pa_slot);
168:
169: /* reset the device */
170: cmd[0] = PMS_RESET;
171: res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
172: #ifdef DEBUG
173: if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
174: printf("pmsiattach: reset error\n");
175: return;
176: }
177: #endif
178: res = pmsi_setintellimode(pa->pa_tag, pa->pa_slot);
179: #ifdef DEBUG
180: if (res) {
181: printf("pmsiattach: error setting intelli mode\n");
182: return;
183: }
184: #endif
185:
186: /* Other initialization was done by pmsiprobe. */
187: sc->inputstate = 0;
188: sc->oldbuttons = 0;
189:
190: pckbc_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
191: pmsiinput, sc, sc->sc_dev.dv_xname);
192:
193: a.accessops = &pmsi_accessops;
194: a.accesscookie = sc;
195:
196: /*
197: * Attach the wsmouse, saving a handle to it.
198: * Note that we don't need to check this pointer against NULL
199: * here or in pmsintr, because if this fails pms_enable() will
200: * never be called, so pmsiinput() will never be called.
201: */
202: sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
203:
204: /* no interrupts until enabled */
205: cmd[0] = PMS_DEV_DISABLE;
206: res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0);
207: if (res)
208: printf("pmsiattach: disable error\n");
209: pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
210: }
211:
212: int
213: pmsi_enable(v)
214: void *v;
215: {
216: struct pmsi_softc *sc = v;
217: u_char cmd[1];
218: int res;
219:
220: if (sc->sc_enabled)
221: return EBUSY;
222:
223: sc->sc_enabled = 1;
224: sc->inputstate = 0;
225: sc->oldbuttons = 0;
226:
227: pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
228:
229: cmd[0] = PMS_DEV_ENABLE;
230: res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
231: if (res)
232: printf("pmsi_enable: command error\n");
233:
234: return 0;
235: }
236:
237: void
238: pmsi_disable(v)
239: void *v;
240: {
241: struct pmsi_softc *sc = v;
242: u_char cmd[1];
243: int res;
244:
245: cmd[0] = PMS_DEV_DISABLE;
246: res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
247: if (res)
248: printf("pmsi_disable: command error\n");
249:
250: pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
251:
252: sc->sc_enabled = 0;
253: }
254:
255: int
256: pmsi_ioctl(v, cmd, data, flag, p)
257: void *v;
258: u_long cmd;
259: caddr_t data;
260: int flag;
261: struct proc *p;
262: {
263: struct pmsi_softc *sc = v;
264: u_char kbcmd[2];
265: int i;
266:
267: switch (cmd) {
268: case WSMOUSEIO_GTYPE:
269: *(u_int *)data = WSMOUSE_TYPE_PS2;
270: break;
271:
272: case WSMOUSEIO_SRES:
273: i = ((int) *(u_int *)data - 12) / 25;
274: /* valid values are {0,1,2,3} */
275: if (i < 0)
276: i = 0;
277: if (i > 3)
278: i = 3;
279:
280: kbcmd[0] = PMS_SET_RES;
281: kbcmd[1] = (unsigned char) i;
282: i = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, kbcmd,
283: 2, 0, 1, 0);
284:
285: if (i)
286: printf("pms_ioctl: SET_RES command error\n");
287: break;
288:
289: default:
290: return (-1);
291: }
292: return (0);
293: }
294:
295: /* Masks for the first byte of a packet */
296: #define PS2LBUTMASK 0x01
297: #define PS2RBUTMASK 0x02
298: #define PS2MBUTMASK 0x04
299:
300: void pmsiinput(vsc, data)
301: void *vsc;
302: int data;
303: {
304: struct pmsi_softc *sc = vsc;
305: signed char dz;
306: u_int changed;
307:
308: if (!sc->sc_enabled) {
309: /* Interrupts are not expected. Discard the byte. */
310: return;
311: }
312:
313: switch (sc->inputstate) {
314:
315: case 0:
316: if ((data & 0xc0) == 0) { /* no ovfl, bit 3 == 1 too? */
317: sc->buttons = ((data & PS2LBUTMASK) ? 0x1 : 0) |
318: ((data & PS2MBUTMASK) ? 0x2 : 0) |
319: ((data & PS2RBUTMASK) ? 0x4 : 0);
320: ++sc->inputstate;
321: }
322: break;
323:
324: case 1:
325: sc->dx = data;
326: /* Bounding at -127 avoids a bug in XFree86. */
327: sc->dx = (sc->dx == -128) ? -127 : sc->dx;
328: ++sc->inputstate;
329: break;
330:
331: case 2:
332: sc->dy = data;
333: sc->dy = (sc->dy == -128) ? -127 : sc->dy;
334: ++sc->inputstate;
335: break;
336:
337: case 3:
338: dz = data;
339: dz = (dz == -128) ? -127 : dz;
340: sc->inputstate = 0;
341:
342: changed = (sc->buttons ^ sc->oldbuttons);
343: sc->oldbuttons = sc->buttons;
344:
345: if (sc->dx || sc->dy || dz || changed)
346: wsmouse_input(sc->sc_wsmousedev,
347: sc->buttons, sc->dx, sc->dy, dz, 0,
348: WSMOUSE_INPUT_DELTA);
349: break;
350: }
351:
352: return;
353: }
354:
355: struct cfdriver pmsi_cd = {
356: NULL, "pmsi", DV_DULL
357: };
CVSweb