Annotation of sys/dev/pckbc/pms.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pms.c,v 1.1 2007/08/01 12:16:59 kettenis Exp $ */
2: /* $NetBSD: psm.c,v 1.11 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 pms_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;
51:
52: struct device *sc_wsmousedev;
53: };
54:
55: int pmsprobe(struct device *, void *, void *);
56: void pmsattach(struct device *, struct device *, void *);
57: void pmsinput(void *, int);
58:
59: struct cfattach pms_ca = {
60: sizeof(struct pms_softc), pmsprobe, pmsattach,
61: };
62:
63: int pms_enable(void *);
64: int pms_ioctl(void *, u_long, caddr_t, int, struct proc *);
65: void pms_disable(void *);
66:
67: const struct wsmouse_accessops pms_accessops = {
68: pms_enable,
69: pms_ioctl,
70: pms_disable,
71: };
72:
73: int
74: pmsprobe(parent, match, aux)
75: struct device *parent;
76: void *match;
77: void *aux;
78: {
79: struct pckbc_attach_args *pa = aux;
80: u_char cmd[1], resp[2];
81: int res;
82:
83: if (pa->pa_slot != PCKBC_AUX_SLOT)
84: return (0);
85:
86: /* Flush any garbage. */
87: pckbc_flush(pa->pa_tag, pa->pa_slot);
88:
89: /* reset the device */
90: cmd[0] = PMS_RESET;
91: res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
92: if (res) {
93: #ifdef DEBUG
94: printf("pmsprobe: reset error %d\n", res);
95: #endif
96: return (0);
97: }
98: if (resp[0] != PMS_RSTDONE) {
99: printf("pmsprobe: reset response 0x%x\n", resp[0]);
100: return (0);
101: }
102:
103: /* get type number (0 = mouse) */
104: if (resp[1] != 0) {
105: #ifdef DEBUG
106: printf("pmsprobe: type 0x%x\n", resp[1]);
107: #endif
108: return (0);
109: }
110:
111: return (10);
112: }
113:
114: void
115: pmsattach(parent, self, aux)
116: struct device *parent, *self;
117: void *aux;
118: {
119: struct pms_softc *sc = (void *)self;
120: struct pckbc_attach_args *pa = aux;
121: struct wsmousedev_attach_args a;
122: u_char cmd[1], resp[2];
123: int res;
124:
125: sc->sc_kbctag = pa->pa_tag;
126: sc->sc_kbcslot = pa->pa_slot;
127:
128: printf("\n");
129:
130: /* Flush any garbage. */
131: pckbc_flush(pa->pa_tag, pa->pa_slot);
132:
133: /* reset the device */
134: cmd[0] = PMS_RESET;
135: res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
136: #ifdef DEBUG
137: if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
138: printf("pmsattach: reset error\n");
139: return;
140: }
141: #endif
142:
143: sc->inputstate = 0;
144: sc->oldbuttons = 0;
145:
146: pckbc_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
147: pmsinput, sc, sc->sc_dev.dv_xname);
148:
149: a.accessops = &pms_accessops;
150: a.accesscookie = sc;
151:
152: /*
153: * Attach the wsmouse, saving a handle to it.
154: * Note that we don't need to check this pointer against NULL
155: * here or in pmsintr, because if this fails pms_enable() will
156: * never be called, so pmsinput() will never be called.
157: */
158: sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
159:
160: /* no interrupts until enabled */
161: cmd[0] = PMS_DEV_DISABLE;
162: res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0);
163: if (res)
164: printf("pmsattach: disable error\n");
165: pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
166: }
167:
168: int
169: pms_enable(v)
170: void *v;
171: {
172: struct pms_softc *sc = v;
173: u_char cmd[1];
174: int res;
175:
176: if (sc->sc_enabled)
177: return EBUSY;
178:
179: sc->sc_enabled = 1;
180: sc->inputstate = 0;
181: sc->oldbuttons = 0;
182:
183: pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
184:
185: cmd[0] = PMS_DEV_ENABLE;
186: res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
187: if (res)
188: printf("pms_enable: command error\n");
189: #if 0
190: {
191: u_char scmd[2];
192:
193: scmd[0] = PMS_SET_RES;
194: scmd[1] = 3; /* 8 counts/mm */
195: res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
196: 2, 0, 1, 0);
197: if (res)
198: printf("pms_enable: setup error1 (%d)\n", res);
199:
200: scmd[0] = PMS_SET_SCALE21;
201: res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
202: 1, 0, 1, 0);
203: if (res)
204: printf("pms_enable: setup error2 (%d)\n", res);
205:
206: scmd[0] = PMS_SET_SAMPLE;
207: scmd[1] = 100; /* 100 samples/sec */
208: res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
209: 2, 0, 1, 0);
210: if (res)
211: printf("pms_enable: setup error3 (%d)\n", res);
212: }
213: #endif
214:
215: return 0;
216: }
217:
218: void
219: pms_disable(v)
220: void *v;
221: {
222: struct pms_softc *sc = v;
223: u_char cmd[1];
224: int res;
225:
226: cmd[0] = PMS_DEV_DISABLE;
227: res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
228: if (res)
229: printf("pms_disable: command error\n");
230:
231: pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
232:
233: sc->sc_enabled = 0;
234: }
235:
236: int
237: pms_ioctl(v, cmd, data, flag, p)
238: void *v;
239: u_long cmd;
240: caddr_t data;
241: int flag;
242: struct proc *p;
243: {
244: struct pms_softc *sc = v;
245: u_char kbcmd[2];
246: int i;
247:
248: switch (cmd) {
249: case WSMOUSEIO_GTYPE:
250: *(u_int *)data = WSMOUSE_TYPE_PS2;
251: break;
252:
253: case WSMOUSEIO_SRES:
254: i = ((int) *(u_int *)data - 12) / 25;
255: /* valid values are {0,1,2,3} */
256: if (i < 0)
257: i = 0;
258: if (i > 3)
259: i = 3;
260:
261: kbcmd[0] = PMS_SET_RES;
262: kbcmd[1] = (unsigned char) i;
263: i = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, kbcmd,
264: 2, 0, 1, 0);
265:
266: if (i)
267: printf("pms_ioctl: SET_RES command error\n");
268: break;
269:
270: default:
271: return (-1);
272: }
273: return (0);
274: }
275:
276: /* Masks for the first byte of a packet */
277: #define PS2LBUTMASK 0x01
278: #define PS2RBUTMASK 0x02
279: #define PS2MBUTMASK 0x04
280:
281: void pmsinput(vsc, data)
282: void *vsc;
283: int data;
284: {
285: struct pms_softc *sc = vsc;
286: signed char dy;
287: u_int changed;
288:
289: if (!sc->sc_enabled) {
290: /* Interrupts are not expected. Discard the byte. */
291: return;
292: }
293:
294: switch (sc->inputstate) {
295:
296: case 0:
297: if ((data & 0xc0) == 0) { /* no ovfl, bit 3 == 1 too? */
298: sc->buttons = ((data & PS2LBUTMASK) ? 0x1 : 0) |
299: ((data & PS2MBUTMASK) ? 0x2 : 0) |
300: ((data & PS2RBUTMASK) ? 0x4 : 0);
301: ++sc->inputstate;
302: }
303: break;
304:
305: case 1:
306: sc->dx = data;
307: /* Bounding at -127 avoids a bug in XFree86. */
308: sc->dx = (sc->dx == -128) ? -127 : sc->dx;
309: ++sc->inputstate;
310: break;
311:
312: case 2:
313: dy = data;
314: dy = (dy == -128) ? -127 : dy;
315: sc->inputstate = 0;
316:
317: changed = (sc->buttons ^ sc->oldbuttons);
318: sc->oldbuttons = sc->buttons;
319:
320: if (sc->dx || dy || changed)
321: wsmouse_input(sc->sc_wsmousedev,
322: sc->buttons, sc->dx, dy, 0, 0,
323: WSMOUSE_INPUT_DELTA);
324: break;
325: }
326:
327: return;
328: }
329:
330: struct cfdriver pms_cd = {
331: NULL, "pms", DV_DULL
332: };
CVSweb