xref: /openbsd-src/sys/dev/adb/ams.c (revision 0f9e9ec23bb2b65cc62a3d17df12827a45dae80c)
1*0f9e9ec2Sjsg /*	$OpenBSD: ams.c,v 1.9 2024/05/13 01:15:50 jsg Exp $	*/
2305d9e87Smiod /*	$NetBSD: ams.c,v 1.11 2000/12/19 03:13:40 tsubai Exp $	*/
3305d9e87Smiod 
4305d9e87Smiod /*
5305d9e87Smiod  * Copyright (C) 1998	Colin Wood
6305d9e87Smiod  * All rights reserved.
7305d9e87Smiod  *
8305d9e87Smiod  * Redistribution and use in source and binary forms, with or without
9305d9e87Smiod  * modification, are permitted provided that the following conditions
10305d9e87Smiod  * are met:
11305d9e87Smiod  * 1. Redistributions of source code must retain the above copyright
12305d9e87Smiod  *    notice, this list of conditions and the following disclaimer.
13305d9e87Smiod  * 2. Redistributions in binary form must reproduce the above copyright
14305d9e87Smiod  *    notice, this list of conditions and the following disclaimer in the
15305d9e87Smiod  *    documentation and/or other materials provided with the distribution.
16305d9e87Smiod  * 3. All advertising materials mentioning features or use of this software
17305d9e87Smiod  *    must display the following acknowledgement:
18305d9e87Smiod  *	This product includes software developed by Colin Wood.
19305d9e87Smiod  * 4. The name of the author may not be used to endorse or promote products
20305d9e87Smiod  *    derived from this software without specific prior written permission.
21305d9e87Smiod  *
22305d9e87Smiod  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23305d9e87Smiod  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24305d9e87Smiod  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25305d9e87Smiod  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26305d9e87Smiod  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27305d9e87Smiod  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28305d9e87Smiod  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29305d9e87Smiod  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30305d9e87Smiod  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31305d9e87Smiod  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32305d9e87Smiod  */
33305d9e87Smiod 
34305d9e87Smiod #include <sys/param.h>
35305d9e87Smiod #include <sys/device.h>
36305d9e87Smiod #include <sys/systm.h>
37305d9e87Smiod 
38305d9e87Smiod #include <machine/autoconf.h>
39305d9e87Smiod 
40305d9e87Smiod #include <dev/wscons/wsconsio.h>
41305d9e87Smiod #include <dev/wscons/wsmousevar.h>
42305d9e87Smiod 
43305d9e87Smiod #include <dev/adb/adb.h>
44305d9e87Smiod #include <dev/adb/amsvar.h>
45305d9e87Smiod 
46305d9e87Smiod /*
47305d9e87Smiod  * Function declarations.
48305d9e87Smiod  */
49305d9e87Smiod int	amsmatch(struct device *, void *, void *);
50305d9e87Smiod void	amsattach(struct device *, struct device *, void *);
51305d9e87Smiod 
52305d9e87Smiod /* Driver definition. */
53471aeecfSnaddy const struct cfattach ams_ca = {
54305d9e87Smiod 	sizeof(struct ams_softc), amsmatch, amsattach
55305d9e87Smiod };
56305d9e87Smiod /* Driver definition. */
57305d9e87Smiod struct cfdriver ams_cd = {
58305d9e87Smiod 	NULL, "ams", DV_DULL
59305d9e87Smiod };
60305d9e87Smiod 
61305d9e87Smiod int	ams_enable(void *);
62305d9e87Smiod int	ams_ioctl(void *, u_long, caddr_t, int, struct proc *);
63305d9e87Smiod void	ams_disable(void *);
64305d9e87Smiod 
65305d9e87Smiod const struct wsmouse_accessops ams_accessops = {
66305d9e87Smiod 	ams_enable,
67305d9e87Smiod 	ams_ioctl,
68305d9e87Smiod 	ams_disable,
69305d9e87Smiod };
70305d9e87Smiod 
71305d9e87Smiod void	ems_init(struct ams_softc *);
72305d9e87Smiod void	ms_adbcomplete(caddr_t buffer, caddr_t data_area, int adb_command);
73305d9e87Smiod void	ms_processevent(adb_event_t *event, struct ams_softc *);
74305d9e87Smiod 
75305d9e87Smiod int
amsmatch(struct device * parent,void * cf,void * aux)76305d9e87Smiod amsmatch(struct device *parent, void *cf, void *aux)
77305d9e87Smiod {
78305d9e87Smiod 	struct adb_attach_args *aa_args = aux;
79305d9e87Smiod 
804425d974Smiod 	if (strcmp(aa_args->name, adb_device_name) != 0)
814425d974Smiod 		return (0);
824425d974Smiod 
83305d9e87Smiod 	if (aa_args->origaddr == ADBADDR_MS)
84305d9e87Smiod 		return 1;
85305d9e87Smiod 	else
86305d9e87Smiod 		return 0;
87305d9e87Smiod }
88305d9e87Smiod 
89305d9e87Smiod void
amsattach(struct device * parent,struct device * self,void * aux)90305d9e87Smiod amsattach(struct device *parent, struct device *self, void   *aux)
91305d9e87Smiod {
92305d9e87Smiod 	ADBSetInfoBlock adbinfo;
93305d9e87Smiod 	struct ams_softc *sc = (struct ams_softc *)self;
94305d9e87Smiod 	struct adb_attach_args *aa_args = aux;
95305d9e87Smiod 	int error;
96305d9e87Smiod 	struct wsmousedev_attach_args a;
97305d9e87Smiod 
98305d9e87Smiod 	sc->origaddr = aa_args->origaddr;
99305d9e87Smiod 	sc->adbaddr = aa_args->adbaddr;
100305d9e87Smiod 	sc->handler_id = aa_args->handler_id;
101305d9e87Smiod 
102305d9e87Smiod 	sc->sc_class = MSCLASS_MOUSE;
103305d9e87Smiod 	sc->sc_buttons = 1;
104305d9e87Smiod 	sc->sc_res = 100;
105305d9e87Smiod 	sc->sc_devid[0] = 0;
106305d9e87Smiod 	sc->sc_devid[4] = 0;
107305d9e87Smiod 
108305d9e87Smiod 	adbinfo.siServiceRtPtr = (Ptr)ms_adbcomplete;
109305d9e87Smiod 	adbinfo.siDataAreaAddr = (caddr_t)sc;
110305d9e87Smiod 
111305d9e87Smiod 	ems_init(sc);
112305d9e87Smiod 
113305d9e87Smiod 	/* print out the type of mouse we have */
114305d9e87Smiod 	printf(": ");
115305d9e87Smiod 	switch (sc->handler_id) {
116305d9e87Smiod 	case ADBMS_200DPI:
117305d9e87Smiod 		sc->sc_res = 200;
118305d9e87Smiod 		/* FALLTHROUGH */
119305d9e87Smiod 	case ADBMS_100DPI:
120305d9e87Smiod 		printf("%d-button, %d dpi mouse\n", sc->sc_buttons,
121305d9e87Smiod 		    (int)(sc->sc_res));
122305d9e87Smiod 		break;
123305d9e87Smiod 	case ADBMS_MSA3:
124305d9e87Smiod 		printf("Mouse Systems A3 mouse, %d-button, %d dpi\n",
125305d9e87Smiod 		    sc->sc_buttons, (int)(sc->sc_res));
126305d9e87Smiod 		break;
127305d9e87Smiod 	case ADBMS_USPEED:
128305d9e87Smiod 		printf("MicroSpeed mouse, default parameters\n");
129305d9e87Smiod 		break;
130305d9e87Smiod 	case ADBMS_UCONTOUR:
131305d9e87Smiod 		printf("Contour mouse, default parameters\n");
132305d9e87Smiod 		break;
133305d9e87Smiod 	case ADBMS_TURBO:
134305d9e87Smiod 		printf("Kensington Turbo Mouse\n");
135305d9e87Smiod 		break;
136305d9e87Smiod 	case ADBMS_EXTENDED:
137305d9e87Smiod 		if (sc->sc_devid[0] == '\0') {
138305d9e87Smiod 			printf("Logitech ");
139305d9e87Smiod 			switch (sc->sc_class) {
140305d9e87Smiod 			case MSCLASS_MOUSE:
141305d9e87Smiod 				printf("MouseMan (non-EMP) mouse");
142305d9e87Smiod 				break;
143305d9e87Smiod 			case MSCLASS_TRACKBALL:
144305d9e87Smiod 				printf("TrackMan (non-EMP) trackball");
145305d9e87Smiod 				break;
146305d9e87Smiod 			default:
147305d9e87Smiod 				printf("non-EMP relative positioning device");
148305d9e87Smiod 				break;
149305d9e87Smiod 			}
150305d9e87Smiod 			printf("\n");
151305d9e87Smiod 		} else {
152305d9e87Smiod 			printf("EMP ");
153305d9e87Smiod 			switch (sc->sc_class) {
154305d9e87Smiod 			case MSCLASS_TABLET:
155305d9e87Smiod 				printf("tablet");
156305d9e87Smiod 				break;
157305d9e87Smiod 			case MSCLASS_MOUSE:
158305d9e87Smiod 				printf("mouse");
159305d9e87Smiod 				break;
160305d9e87Smiod 			case MSCLASS_TRACKBALL:
161305d9e87Smiod 				printf("trackball");
162305d9e87Smiod 				break;
163305d9e87Smiod 			case MSCLASS_TRACKPAD:
164305d9e87Smiod 				printf("trackpad");
165305d9e87Smiod 				break;
166305d9e87Smiod 			default:
167305d9e87Smiod 				printf("unknown device");
168305d9e87Smiod 				break;
169305d9e87Smiod 			}
170305d9e87Smiod 			printf(" <%s> %d-button, %d dpi\n", sc->sc_devid,
171305d9e87Smiod 			    sc->sc_buttons, (int)(sc->sc_res));
172305d9e87Smiod 		}
173305d9e87Smiod 		break;
174305d9e87Smiod 	default:
175305d9e87Smiod 		printf("relative positioning device (mouse?) (%d)\n",
176305d9e87Smiod 			sc->handler_id);
177305d9e87Smiod 		break;
178305d9e87Smiod 	}
179305d9e87Smiod 	error = set_adb_info(&adbinfo, sc->adbaddr);
180305d9e87Smiod #ifdef ADB_DEBUG
181305d9e87Smiod 	if (adb_debug)
182305d9e87Smiod 		printf("ams: returned %d from set_adb_info\n", error);
183305d9e87Smiod #endif
184305d9e87Smiod 
185305d9e87Smiod 	a.accessops = &ams_accessops;
186305d9e87Smiod 	a.accesscookie = sc;
187305d9e87Smiod 	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
188305d9e87Smiod }
189305d9e87Smiod 
190305d9e87Smiod 
191305d9e87Smiod /*
192305d9e87Smiod  * Initialize extended mouse support -- probes devices as described
193305d9e87Smiod  * in Inside Macintosh: Devices, Chapter 5 "ADB Manager".
194305d9e87Smiod  *
195305d9e87Smiod  * Extended Mouse Protocol is documented in TechNote HW1:
196305d9e87Smiod  * 	"ADB - The Untold Story:  Space Aliens Ate My Mouse"
197305d9e87Smiod  *
198305d9e87Smiod  * Supports: Extended Mouse Protocol, MicroSpeed Mouse Deluxe,
199305d9e87Smiod  * 	     Mouse Systems A^3 Mouse, Logitech non-EMP MouseMan
200305d9e87Smiod  */
201305d9e87Smiod void
ems_init(struct ams_softc * sc)202305d9e87Smiod ems_init(struct ams_softc *sc)
203305d9e87Smiod {
204305d9e87Smiod 	int adbaddr;
205305d9e87Smiod 	short cmd;
206305d9e87Smiod 	u_char buffer[9];
207305d9e87Smiod 
208305d9e87Smiod 	adbaddr = sc->adbaddr;
209305d9e87Smiod 	if (sc->origaddr != ADBADDR_MS)
210305d9e87Smiod 		return;
211305d9e87Smiod 	if (sc->handler_id == ADBMS_USPEED ||
212305d9e87Smiod 	    sc->handler_id == ADBMS_UCONTOUR) {
213305d9e87Smiod 		/* Found MicroSpeed Mouse Deluxe Mac or Contour Mouse */
214305d9e87Smiod 		cmd = ADBLISTEN(adbaddr, 1);
215305d9e87Smiod 
216305d9e87Smiod 		/*
217305d9e87Smiod 		 * To setup the MicroSpeed or the Contour, it appears
218305d9e87Smiod 		 * that we can send the following command to the mouse
219305d9e87Smiod 		 * and then expect data back in the form:
220305d9e87Smiod 		 *  buffer[0] = 4 (bytes)
221305d9e87Smiod 		 *  buffer[1], buffer[2] as std. mouse
222305d9e87Smiod 		 *  buffer[3] = buffer[4] = 0xff when no buttons
223305d9e87Smiod 		 *   are down.  When button N down, bit N is clear.
224305d9e87Smiod 		 * buffer[4]'s locking mask enables a
225305d9e87Smiod 		 * click to toggle the button down state--sort of
226305d9e87Smiod 		 * like the "Easy Access" shift/control/etc. keys.
227305d9e87Smiod 		 * buffer[3]'s alternative speed mask enables using
228305d9e87Smiod 		 * different speed when the corr. button is down
229305d9e87Smiod 		 */
230305d9e87Smiod 		buffer[0] = 4;
231305d9e87Smiod 		buffer[1] = 0x00;	/* Alternative speed */
232305d9e87Smiod 		buffer[2] = 0x00;	/* speed = maximum */
233305d9e87Smiod 		buffer[3] = 0x10;	/* enable extended protocol,
234305d9e87Smiod 					 * lower bits = alt. speed mask
235305d9e87Smiod 					 *            = 0000b
236305d9e87Smiod 					 */
237305d9e87Smiod 		buffer[4] = 0x07;	/* Locking mask = 0000b,
238305d9e87Smiod 					 * enable buttons = 0111b
239305d9e87Smiod 					 */
24074a0040aSmiod 		adb_op_sync((Ptr)buffer, cmd);
241305d9e87Smiod 
242305d9e87Smiod 		sc->sc_buttons = 3;
243305d9e87Smiod 		sc->sc_res = 200;
244305d9e87Smiod 		return;
245305d9e87Smiod 	}
246305d9e87Smiod 	if (sc->handler_id == ADBMS_TURBO) {
247305d9e87Smiod 		/* Found Kensington Turbo Mouse */
248305d9e87Smiod 		static u_char data1[] =
249305d9e87Smiod 			{ 8, 0xe7, 0x8c, 0, 0, 0, 0xff, 0xff, 0x94 };
250305d9e87Smiod 		static u_char data2[] =
251305d9e87Smiod 			{ 8, 0xa5, 0x14, 0, 0, 0x69, 0xff, 0xff, 0x27 };
252305d9e87Smiod 
253305d9e87Smiod 		buffer[0] = 0;
25474a0040aSmiod 		adb_op_sync((Ptr)buffer, ADBFLUSH(adbaddr));
255305d9e87Smiod 
25674a0040aSmiod 		adb_op_sync((Ptr)data1, ADBLISTEN(adbaddr, 2));
257305d9e87Smiod 
258305d9e87Smiod 		buffer[0] = 0;
25974a0040aSmiod 		adb_op_sync((Ptr)buffer, ADBFLUSH(adbaddr));
260305d9e87Smiod 
26174a0040aSmiod 		adb_op_sync((Ptr)data2, ADBLISTEN(adbaddr, 2));
262305d9e87Smiod 		return;
263305d9e87Smiod 	}
264305d9e87Smiod 	if ((sc->handler_id == ADBMS_100DPI) ||
265305d9e87Smiod 	    (sc->handler_id == ADBMS_200DPI)) {
266305d9e87Smiod 		/* found a mouse */
267305d9e87Smiod 		cmd = ADBTALK(adbaddr, 3);
26874a0040aSmiod 		if (adb_op_sync((Ptr)buffer, cmd)) {
269305d9e87Smiod #ifdef ADB_DEBUG
270305d9e87Smiod 			if (adb_debug)
271305d9e87Smiod 				printf("adb: ems_init timed out\n");
272305d9e87Smiod #endif
273305d9e87Smiod 			return;
274305d9e87Smiod 		}
275305d9e87Smiod 
276305d9e87Smiod 		/* Attempt to initialize Extended Mouse Protocol */
277305d9e87Smiod 		buffer[2] = 4; /* make handler ID 4 */
278305d9e87Smiod 		cmd = ADBLISTEN(adbaddr, 3);
27974a0040aSmiod 		if (adb_op_sync((Ptr)buffer, cmd)) {
280305d9e87Smiod #ifdef ADB_DEBUG
281305d9e87Smiod 			if (adb_debug)
282305d9e87Smiod 				printf("adb: ems_init timed out\n");
283305d9e87Smiod #endif
284305d9e87Smiod 			return;
285305d9e87Smiod 		}
286305d9e87Smiod 
287305d9e87Smiod 		/*
288305d9e87Smiod 		 * Check to see if successful, if not
289305d9e87Smiod 		 * try to initialize it as other types
290305d9e87Smiod 		 */
291305d9e87Smiod 		cmd = ADBTALK(adbaddr, 3);
29274a0040aSmiod 		if (adb_op_sync((Ptr)buffer, cmd) == 0 &&
293305d9e87Smiod 		    buffer[2] == ADBMS_EXTENDED) {
294305d9e87Smiod 			sc->handler_id = ADBMS_EXTENDED;
295305d9e87Smiod 			cmd = ADBTALK(adbaddr, 1);
29674a0040aSmiod 			if (adb_op_sync((Ptr)buffer, cmd)) {
297305d9e87Smiod #ifdef ADB_DEBUG
298305d9e87Smiod 				if (adb_debug)
299305d9e87Smiod 					printf("adb: ems_init timed out\n");
300305d9e87Smiod #endif
301305d9e87Smiod 			} else if (buffer[0] == 8) {
302305d9e87Smiod 				/* we have a true EMP device */
303305d9e87Smiod 				sc->sc_class = buffer[7];
304305d9e87Smiod 				sc->sc_buttons = buffer[8];
305305d9e87Smiod 				sc->sc_res = (int)*(short *)&buffer[5];
306305d9e87Smiod 				bcopy(&(buffer[1]), sc->sc_devid, 4);
307305d9e87Smiod 			} else if (buffer[1] == 0x9a &&
308305d9e87Smiod 			    ((buffer[2] == 0x20) || (buffer[2] == 0x21))) {
309305d9e87Smiod 				/*
310305d9e87Smiod 				 * Set up non-EMP Mouseman/Trackman to put
311305d9e87Smiod 				 * button bits in 3rd byte instead of sending
312305d9e87Smiod 				 * via pseudo keyboard device.
313305d9e87Smiod 				 */
314305d9e87Smiod 				cmd = ADBLISTEN(adbaddr, 1);
315305d9e87Smiod 				buffer[0]=2;
316305d9e87Smiod 				buffer[1]=0x00;
317305d9e87Smiod 				buffer[2]=0x81;
31874a0040aSmiod 				adb_op_sync((Ptr)buffer, cmd);
319305d9e87Smiod 
320305d9e87Smiod 				cmd = ADBLISTEN(adbaddr, 1);
321305d9e87Smiod 				buffer[0]=2;
322305d9e87Smiod 				buffer[1]=0x01;
323305d9e87Smiod 				buffer[2]=0x81;
32474a0040aSmiod 				adb_op_sync((Ptr)buffer, cmd);
325305d9e87Smiod 
326305d9e87Smiod 				cmd = ADBLISTEN(adbaddr, 1);
327305d9e87Smiod 				buffer[0]=2;
328305d9e87Smiod 				buffer[1]=0x02;
329305d9e87Smiod 				buffer[2]=0x81;
33074a0040aSmiod 				adb_op_sync((Ptr)buffer, cmd);
331305d9e87Smiod 
332305d9e87Smiod 				cmd = ADBLISTEN(adbaddr, 1);
333305d9e87Smiod 				buffer[0]=2;
334305d9e87Smiod 				buffer[1]=0x03;
335305d9e87Smiod 				buffer[2]=0x38;
33674a0040aSmiod 				adb_op_sync((Ptr)buffer, cmd);
337305d9e87Smiod 
338305d9e87Smiod 				sc->sc_buttons = 3;
339305d9e87Smiod 				sc->sc_res = 400;
340305d9e87Smiod 				if (buffer[2] == 0x21)
341305d9e87Smiod 					sc->sc_class = MSCLASS_TRACKBALL;
342305d9e87Smiod 				else
343305d9e87Smiod 					sc->sc_class = MSCLASS_MOUSE;
344305d9e87Smiod 			} else
345305d9e87Smiod 				/* unknown device? */;
346305d9e87Smiod 		} else {
347305d9e87Smiod 			/* Attempt to initialize as an A3 mouse */
348305d9e87Smiod 			buffer[2] = 0x03; /* make handler ID 3 */
349305d9e87Smiod 			cmd = ADBLISTEN(adbaddr, 3);
35074a0040aSmiod 			if (adb_op_sync((Ptr)buffer, cmd)) {
351305d9e87Smiod #ifdef ADB_DEBUG
352305d9e87Smiod 				if (adb_debug)
353305d9e87Smiod 					printf("adb: ems_init timed out\n");
354305d9e87Smiod #endif
355305d9e87Smiod 				return;
356305d9e87Smiod 			}
357305d9e87Smiod 
358305d9e87Smiod 			/*
359305d9e87Smiod 			 * Check to see if successful, if not
360305d9e87Smiod 			 * try to initialize it as other types
361305d9e87Smiod 			 */
362305d9e87Smiod 			cmd = ADBTALK(adbaddr, 3);
36374a0040aSmiod 			if (adb_op_sync((Ptr)buffer, cmd) == 0
364305d9e87Smiod 			    && buffer[2] == ADBMS_MSA3) {
365305d9e87Smiod 				sc->handler_id = ADBMS_MSA3;
366305d9e87Smiod 				/* Initialize as above */
367305d9e87Smiod 				cmd = ADBLISTEN(adbaddr, 2);
368305d9e87Smiod 				/* listen 2 */
369305d9e87Smiod 				buffer[0] = 3;
370305d9e87Smiod 				buffer[1] = 0x00;
371305d9e87Smiod 				/* Irrelevant, buffer has 0x77 */
372305d9e87Smiod 				buffer[2] = 0x07;
373305d9e87Smiod 				/*
374305d9e87Smiod 				 * enable 3 button mode = 0111b,
375305d9e87Smiod 				 * speed = normal
376305d9e87Smiod 				 */
37774a0040aSmiod 				adb_op_sync((Ptr)buffer, cmd);
378305d9e87Smiod 				sc->sc_buttons = 3;
379305d9e87Smiod 				sc->sc_res = 300;
380305d9e87Smiod 			} else {
381305d9e87Smiod 				/* No special support for this mouse */
382305d9e87Smiod 			}
383305d9e87Smiod 		}
384305d9e87Smiod 	}
385305d9e87Smiod }
386305d9e87Smiod 
387305d9e87Smiod /*
388305d9e87Smiod  * Handle putting the mouse data received from the ADB into
389305d9e87Smiod  * an ADB event record.
390305d9e87Smiod  */
391305d9e87Smiod void
ms_adbcomplete(caddr_t buffer,caddr_t data_area,int adb_command)392305d9e87Smiod ms_adbcomplete(caddr_t buffer, caddr_t data_area, int adb_command)
393305d9e87Smiod {
394305d9e87Smiod 	adb_event_t event;
395305d9e87Smiod 	struct ams_softc *sc;
396305d9e87Smiod 	int adbaddr;
397305d9e87Smiod #ifdef ADB_DEBUG
398305d9e87Smiod 	int i;
399305d9e87Smiod 
400305d9e87Smiod 	if (adb_debug)
401305d9e87Smiod 		printf("adb: transaction completion\n");
402305d9e87Smiod #endif
403305d9e87Smiod 
404305d9e87Smiod 	adbaddr = ADB_CMDADDR(adb_command);
405305d9e87Smiod 	sc = (struct ams_softc *)data_area;
406305d9e87Smiod 
407305d9e87Smiod 	if ((sc->handler_id == ADBMS_EXTENDED) && (sc->sc_devid[0] == 0)) {
408305d9e87Smiod 		/* massage the data to look like EMP data */
409305d9e87Smiod 		if ((buffer[3] & 0x04) == 0x04)
410305d9e87Smiod 			buffer[1] &= 0x7f;
411305d9e87Smiod 		else
412305d9e87Smiod 			buffer[1] |= 0x80;
413305d9e87Smiod 		if ((buffer[3] & 0x02) == 0x02)
414305d9e87Smiod 			buffer[2] &= 0x7f;
415305d9e87Smiod 		else
416305d9e87Smiod 			buffer[2] |= 0x80;
417305d9e87Smiod 		if ((buffer[3] & 0x01) == 0x01)
418305d9e87Smiod 			buffer[3] = 0x00;
419305d9e87Smiod 		else
420305d9e87Smiod 			buffer[3] = 0x80;
421305d9e87Smiod 	}
422305d9e87Smiod 
423305d9e87Smiod 	event.byte_count = buffer[0];
424305d9e87Smiod 	memcpy(event.bytes, buffer + 1, event.byte_count);
425305d9e87Smiod 
426305d9e87Smiod #ifdef ADB_DEBUG
427305d9e87Smiod 	if (adb_debug) {
428a1387c96Smiod 		printf("ams: from %d at %d (org %d) %d:", adbaddr,
429a1387c96Smiod 		    sc->handler_id, sc->origaddr, buffer[0]);
430305d9e87Smiod 		for (i = 1; i <= buffer[0]; i++)
431305d9e87Smiod 			printf(" %x", buffer[i]);
432305d9e87Smiod 		printf("\n");
433305d9e87Smiod 	}
434305d9e87Smiod #endif
435305d9e87Smiod 
436305d9e87Smiod 	ms_processevent(&event, sc);
437305d9e87Smiod }
438305d9e87Smiod 
439305d9e87Smiod /*
440305d9e87Smiod  * Given a mouse ADB event, record the button settings, calculate the
441305d9e87Smiod  * x- and y-axis motion, and handoff the event to the appropriate subsystem.
442305d9e87Smiod  */
443305d9e87Smiod void
ms_processevent(adb_event_t * event,struct ams_softc * sc)444305d9e87Smiod ms_processevent(adb_event_t *event, struct ams_softc *sc)
445305d9e87Smiod {
446a1387c96Smiod 	int i, button_bit, max_byte, mask;
447a1387c96Smiod 	int dx, dy, buttons;
448305d9e87Smiod 
449305d9e87Smiod 	buttons = 0;
450305d9e87Smiod 
451305d9e87Smiod 	/*
452305d9e87Smiod 	 * This should handle both plain ol' Apple mice and mice
453305d9e87Smiod 	 * that claim to support the Extended Apple Mouse Protocol.
454305d9e87Smiod 	 */
455305d9e87Smiod 	max_byte = event->byte_count;
456305d9e87Smiod 	button_bit = 1;
457a1387c96Smiod 	switch (sc->handler_id) {
458305d9e87Smiod 	case ADBMS_USPEED:
459305d9e87Smiod 	case ADBMS_UCONTOUR:
460305d9e87Smiod 		/* MicroSpeed mouse and Contour mouse */
461305d9e87Smiod 		if (max_byte == 4)
462305d9e87Smiod 			buttons = (~event->bytes[2]) & 0xff;
463305d9e87Smiod 		else
464305d9e87Smiod 			buttons = (event->bytes[0] & 0x80) ? 0 : 1;
465305d9e87Smiod 		break;
466305d9e87Smiod 	case ADBMS_MSA3:
467305d9e87Smiod 		/* Mouse Systems A3 mouse */
468305d9e87Smiod 		if (max_byte == 3)
469305d9e87Smiod 			buttons = (~event->bytes[2]) & 0x07;
470305d9e87Smiod 		else
471305d9e87Smiod 			buttons = (event->bytes[0] & 0x80) ? 0 : 1;
472305d9e87Smiod 		break;
473305d9e87Smiod 	default:
474305d9e87Smiod 		/* Classic Mouse Protocol (up to 2 buttons) */
475305d9e87Smiod 		for (i = 0; i < 2; i++, button_bit <<= 1)
476305d9e87Smiod 			/* 0 when button down */
477305d9e87Smiod 			if (!(event->bytes[i] & 0x80))
478305d9e87Smiod 				buttons |= button_bit;
479305d9e87Smiod 			else
480305d9e87Smiod 				buttons &= ~button_bit;
481305d9e87Smiod 		/* Extended Protocol (up to 6 more buttons) */
4822379d6daSmatthieu 		if (sc->sc_class == MSCLASS_MOUSE)
483305d9e87Smiod 			for (mask = 0x80; i < max_byte;
484305d9e87Smiod 			     i += (mask == 0x80), button_bit <<= 1) {
485305d9e87Smiod 				/* 0 when button down */
486305d9e87Smiod 				if (!(event->bytes[i] & mask))
487305d9e87Smiod 					buttons |= button_bit;
488305d9e87Smiod 				else
489305d9e87Smiod 					buttons &= ~button_bit;
490305d9e87Smiod 				mask = ((mask >> 4) & 0xf)
491305d9e87Smiod 					| ((mask & 0xf) << 4);
492305d9e87Smiod 			}
493305d9e87Smiod 		break;
494305d9e87Smiod 	}
495a1387c96Smiod 
496a1387c96Smiod 	buttons |= sc->sc_mb;
497a1387c96Smiod 	dx = ((signed int) (event->bytes[1] & 0x3f)) -
498305d9e87Smiod 	    ((event->bytes[1] & 0x40) ? 64 : 0);
499a1387c96Smiod 	dy = ((signed int) (event->bytes[0] & 0x3f)) -
500305d9e87Smiod 	    ((event->bytes[0] & 0x40) ? 64 : 0);
501305d9e87Smiod 
502305d9e87Smiod 	if (sc->sc_wsmousedev)
50394712de5Sbru 		WSMOUSE_INPUT(sc->sc_wsmousedev, buttons, dx, -dy, 0, 0);
504305d9e87Smiod }
505305d9e87Smiod 
506305d9e87Smiod int
ams_enable(void * v)507305d9e87Smiod ams_enable(void *v)
508305d9e87Smiod {
509305d9e87Smiod 	return 0;
510305d9e87Smiod }
511305d9e87Smiod 
512305d9e87Smiod int
ams_ioctl(void * v,u_long cmd,caddr_t data,int flag,struct proc * p)513305d9e87Smiod ams_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
514305d9e87Smiod {
515305d9e87Smiod 	switch (cmd) {
516305d9e87Smiod 	case WSMOUSEIO_GTYPE:
517305d9e87Smiod 		*(u_int *)data = WSMOUSE_TYPE_ADB;
518305d9e87Smiod 		return (0);
519305d9e87Smiod 	}
520305d9e87Smiod 
521305d9e87Smiod 	return -1;
522305d9e87Smiod }
523305d9e87Smiod 
524305d9e87Smiod void
ams_disable(void * v)525305d9e87Smiod ams_disable(void *v)
526305d9e87Smiod {
527305d9e87Smiod }
528