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