Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / adb / adb_ms.c
blob8420f6fc65de2d7f8734866050de490baa6ff88f
1 /* $NetBSD: adb_ms.c,v 1.7 2007/04/16 00:22:55 macallan Exp $ */
3 /*
4 * Copyright (C) 1998 Colin Wood
5 * Copyright (C) 2006, 2007 Michael Lorenz
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Colin Wood.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: adb_ms.c,v 1.7 2007/04/16 00:22:55 macallan Exp $");
37 #include <sys/param.h>
38 #include <sys/device.h>
39 #include <sys/fcntl.h>
40 #include <sys/poll.h>
41 #include <sys/select.h>
42 #include <sys/proc.h>
43 #include <sys/signalvar.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/sysctl.h>
48 #include <machine/autoconf.h>
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/wscons/wsmousevar.h>
53 #include <machine/adbsys.h>
54 #include <dev/adb/adbvar.h>
56 #include "adbdebug.h"
58 #ifdef ADBMS_DEBUG
59 #define DPRINTF printf
60 #else
61 #define DPRINTF while (0) printf
62 #endif
65 * State info, per mouse instance.
67 struct adbms_softc {
68 device_t sc_dev;
69 struct adb_device *sc_adbdev;
70 struct adb_bus_accessops *sc_ops;
72 /* Extended Mouse Protocol info, faked for non-EMP mice */
73 u_int8_t sc_class; /* mouse class (mouse, trackball) */
74 u_int8_t sc_buttons; /* number of buttons */
75 u_int32_t sc_res; /* mouse resolution (dpi) */
76 char sc_devid[5]; /* device indentifier */
77 uint8_t sc_us; /* cmd to watch for */
78 int sc_mb; /* current button state */
79 struct device *sc_wsmousedev;
80 /* helpers for trackpads */
81 int sc_down;
83 * trackpad protocol variant. Known so far:
84 * 2 buttons - PowerBook 3400, single events on button 3 and 4 indicate
85 * finger down and up
86 * 4 buttons - iBook G4, button 6 indicates finger down, button 4 is
87 * always down
89 int sc_x, sc_y;
90 int sc_tapping;
91 /* buffers */
92 int sc_poll;
93 int sc_msg_len;
94 int sc_event;
95 uint8_t sc_buffer[16];
98 /* EMP device classes */
99 #define MSCLASS_TABLET 0
100 #define MSCLASS_MOUSE 1
101 #define MSCLASS_TRACKBALL 2
102 #define MSCLASS_TRACKPAD 3
105 * Function declarations.
107 static int adbms_match(device_t, cfdata_t, void *);
108 static void adbms_attach(device_t, device_t, void *);
109 static void ems_init(struct adbms_softc *);
110 //static void ms_processevent(adb_event_t *event, struct adbms_softc *);
111 static void init_trackpad(struct adbms_softc *);
112 static void adbms_init_mouse(struct adbms_softc *);
113 static void adbms_init_turbo(struct adbms_softc *);
114 static void adbms_init_uspeed(struct adbms_softc *);
115 static void adbms_process_event(struct adbms_softc *, int, uint8_t *);
116 static int adbms_send_sync(struct adbms_softc *, uint8_t, int, uint8_t *);
118 /* Driver definition. */
119 CFATTACH_DECL_NEW(adbms, sizeof(struct adbms_softc),
120 adbms_match, adbms_attach, NULL, NULL);
122 static int adbms_enable(void *);
123 static int adbms_ioctl(void *, u_long, void *, int, struct lwp *);
124 static void adbms_disable(void *);
127 * handle tapping the trackpad
128 * different pads report different button counts and use slightly different
129 * protocols
131 static void adbms_mangle_2(struct adbms_softc *, int);
132 static void adbms_mangle_4(struct adbms_softc *, int);
133 static void adbms_handler(void *, int, uint8_t *);
134 static int adbms_wait(struct adbms_softc *, int);
135 static int sysctl_adbms_tap(SYSCTLFN_ARGS);
137 const struct wsmouse_accessops adbms_accessops = {
138 adbms_enable,
139 adbms_ioctl,
140 adbms_disable,
143 static int
144 adbms_match(device_t parent, cfdata_t cf, void *aux)
146 struct adb_attach_args *aaa = aux;
148 if (aaa->dev->original_addr == ADBADDR_MS)
149 return 1;
150 else
151 return 0;
154 static void
155 adbms_attach(device_t parent, device_t self, void *aux)
157 struct adbms_softc *sc = device_private(self);
158 struct adb_attach_args *aaa = aux;
159 struct wsmousedev_attach_args a;
161 sc->sc_dev = self;
162 sc->sc_ops = aaa->ops;
163 sc->sc_adbdev = aaa->dev;
164 sc->sc_adbdev->cookie = sc;
165 sc->sc_adbdev->handler = adbms_handler;
166 sc->sc_us = ADBTALK(sc->sc_adbdev->current_addr, 0);
167 printf(" addr %d: ", sc->sc_adbdev->current_addr);
169 sc->sc_class = MSCLASS_MOUSE;
170 sc->sc_buttons = 1;
171 sc->sc_res = 100;
172 sc->sc_devid[0] = 0;
173 sc->sc_devid[4] = 0;
174 sc->sc_poll = 0;
175 sc->sc_msg_len = 0;
176 sc->sc_tapping = 1;
178 ems_init(sc);
180 /* print out the type of mouse we have */
181 switch (sc->sc_adbdev->handler_id) {
182 case ADBMS_100DPI:
183 printf("%d-button, %d dpi mouse\n", sc->sc_buttons,
184 (int)(sc->sc_res));
185 break;
186 case ADBMS_200DPI:
187 sc->sc_res = 200;
188 printf("%d-button, %d dpi mouse\n", sc->sc_buttons,
189 (int)(sc->sc_res));
190 break;
191 case ADBMS_MSA3:
192 printf("Mouse Systems A3 mouse, %d-button, %d dpi\n",
193 sc->sc_buttons, (int)(sc->sc_res));
194 break;
195 case ADBMS_USPEED:
196 printf("MicroSpeed mouse, default parameters\n");
197 break;
198 case ADBMS_UCONTOUR:
199 printf("Contour mouse, default parameters\n");
200 break;
201 case ADBMS_TURBO:
202 printf("Kensington Turbo Mouse\n");
203 break;
204 case ADBMS_EXTENDED:
205 if (sc->sc_devid[0] == '\0') {
206 printf("Logitech ");
207 switch (sc->sc_class) {
208 case MSCLASS_MOUSE:
209 printf("MouseMan (non-EMP) mouse");
210 break;
211 case MSCLASS_TRACKBALL:
212 printf("TrackMan (non-EMP) trackball");
213 break;
214 default:
215 printf("non-EMP relative positioning device");
216 break;
218 printf("\n");
219 } else {
220 printf("EMP ");
221 switch (sc->sc_class) {
222 case MSCLASS_TABLET:
223 printf("tablet");
224 break;
225 case MSCLASS_MOUSE:
226 printf("mouse");
227 break;
228 case MSCLASS_TRACKBALL:
229 printf("trackball");
230 break;
231 case MSCLASS_TRACKPAD:
232 printf("trackpad");
233 init_trackpad(sc);
234 break;
235 default:
236 printf("unknown device");
237 break;
239 printf(" <%s> %d-button, %d dpi\n", sc->sc_devid,
240 sc->sc_buttons, (int)(sc->sc_res));
242 break;
243 default:
244 printf("relative positioning device (mouse?) (%d)\n",
245 sc->sc_adbdev->handler_id);
246 break;
249 a.accessops = &adbms_accessops;
250 a.accesscookie = sc;
251 sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
256 * Initialize extended mouse support -- probes devices as described
257 * in Inside Macintosh: Devices, Chapter 5 "ADB Manager".
259 * Extended Mouse Protocol is documented in TechNote HW1:
260 * "ADB - The Untold Story: Space Aliens Ate My Mouse"
262 * Supports: Extended Mouse Protocol, MicroSpeed Mouse Deluxe,
263 * Mouse Systems A^3 Mouse, Logitech non-EMP MouseMan
265 void
266 ems_init(struct adbms_softc *sc)
269 DPRINTF("ems_init %d\n", sc->sc_adbdev->handler_id);
271 switch (sc->sc_adbdev->handler_id) {
272 case ADBMS_USPEED:
273 case ADBMS_UCONTOUR:
274 adbms_init_uspeed(sc);
275 return;
276 case ADBMS_TURBO:
277 adbms_init_turbo(sc);
278 return;
279 case ADBMS_100DPI:
280 case ADBMS_200DPI:
281 adbms_init_mouse(sc);
285 static void
286 adbms_init_uspeed(struct adbms_softc *sc)
288 uint8_t cmd, addr, buffer[4];
290 addr = sc->sc_adbdev->current_addr;
292 /* Found MicroSpeed Mouse Deluxe Mac or Contour Mouse */
293 cmd = ADBLISTEN(addr, 1);
296 * To setup the MicroSpeed or the Contour, it appears
297 * that we can send the following command to the mouse
298 * and then expect data back in the form:
299 * buffer[0] = 4 (bytes)
300 * buffer[1], buffer[2] as std. mouse
301 * buffer[3] = buffer[4] = 0xff when no buttons
302 * are down. When button N down, bit N is clear.
303 * buffer[4]'s locking mask enables a
304 * click to toggle the button down state--sort of
305 * like the "Easy Access" shift/control/etc. keys.
306 * buffer[3]'s alternative speed mask enables using
307 * different speed when the corr. button is down
309 buffer[0] = 0x00; /* Alternative speed */
310 buffer[1] = 0x00; /* speed = maximum */
311 buffer[2] = 0x10; /* enable extended protocol,
312 * lower bits = alt. speed mask
313 * = 0000b
315 buffer[3] = 0x07; /* Locking mask = 0000b,
316 * enable buttons = 0111b
318 adbms_send_sync(sc, cmd, 4, buffer);
320 sc->sc_buttons = 3;
321 sc->sc_res = 200;
324 static void
325 adbms_init_turbo(struct adbms_softc *sc)
327 uint8_t addr;
329 /* Found Kensington Turbo Mouse */
330 static u_char data1[] =
331 { 0xe7, 0x8c, 0, 0, 0, 0xff, 0xff, 0x94 };
332 static u_char data2[] =
333 { 0xa5, 0x14, 0, 0, 0x69, 0xff, 0xff, 0x27 };
335 addr = sc->sc_adbdev->current_addr;
337 adbms_send_sync(sc, ADBFLUSH(addr), 0, NULL);
338 adbms_send_sync(sc, ADBLISTEN(addr, 2), 8, data1);
339 adbms_send_sync(sc, ADBFLUSH(addr), 0, NULL);
340 adbms_send_sync(sc, ADBLISTEN(addr, 2), 8, data2);
343 static void
344 adbms_init_mouse(struct adbms_softc *sc)
346 int len;
347 uint8_t cmd, addr, buffer[16];
349 addr = sc->sc_adbdev->current_addr;
350 /* found a mouse */
351 cmd = ADBTALK(addr, 3);
352 if (!adbms_send_sync(sc, cmd, 0, NULL)) {
353 #ifdef ADBMS_DEBUG
354 printf("adb: ems_init timed out\n");
355 #endif
356 return;
359 /* Attempt to initialize Extended Mouse Protocol */
360 len = sc->sc_msg_len;
361 memcpy(buffer, sc->sc_buffer, len);
362 DPRINTF("buffer: %02x %02x\n", buffer[0], buffer[1]);
363 buffer[1] = 4; /* make handler ID 4 */
364 cmd = ADBLISTEN(addr, 3);
365 if (!adbms_send_sync(sc, cmd, len, buffer)) {
366 #ifdef ADBMS_DEBUG
367 printf("adb: ems_init timed out\n");
368 #endif
369 return;
373 * Check to see if successful, if not
374 * try to initialize it as other types
376 cmd = ADBTALK(addr, 3);
377 if (!adbms_send_sync(sc, cmd, 0, NULL)) {
378 DPRINTF("timeout checking for EMP switch\n");
379 return;
381 DPRINTF("new handler ID: %02x\n", sc->sc_buffer[1]);
382 if (sc->sc_buffer[1] == ADBMS_EXTENDED) {
383 sc->sc_adbdev->handler_id = ADBMS_EXTENDED;
384 cmd = ADBTALK(addr, 1);
385 if(!adbms_send_sync(sc, cmd, 0, NULL)) {
386 DPRINTF("adb: ems_init timed out\n");
387 return;
390 len = sc->sc_msg_len;
391 memcpy(buffer, sc->sc_buffer, len);
393 if (sc->sc_msg_len == 8) {
394 /* we have a true EMP device */
395 #ifdef ADB_PRINT_EMP
397 printf("EMP: %02x %02x %02x %02x %02x %02x %02x %02x\n",
398 buffer[0], buffer[1], buffer[2], buffer[3],
399 buffer[4], buffer[5], buffer[6], buffer[7]);
400 #endif
401 sc->sc_class = buffer[6];
402 sc->sc_buttons = buffer[7];
403 sc->sc_res = (int)*(short *)&buffer[4];
404 memcpy(sc->sc_devid, &(buffer[0]), 4);
405 } else if (buffer[0] == 0x9a &&
406 ((buffer[1] == 0x20) || (buffer[1] == 0x21))) {
408 * Set up non-EMP Mouseman/Trackman to put
409 * button bits in 3rd byte instead of sending
410 * via pseudo keyboard device.
412 if (buffer[1] == 0x21)
413 sc->sc_class = MSCLASS_TRACKBALL;
414 else
415 sc->sc_class = MSCLASS_MOUSE;
417 cmd = ADBLISTEN(addr, 1);
418 buffer[0]=0x00;
419 buffer[1]=0x81;
420 adbms_send_sync(sc, cmd, 2, buffer);
422 cmd = ADBLISTEN(addr, 1);
423 buffer[0]=0x01;
424 buffer[1]=0x81;
425 adbms_send_sync(sc, cmd, 2, buffer);
427 cmd = ADBLISTEN(addr, 1);
428 buffer[0]=0x02;
429 buffer[1]=0x81;
430 adbms_send_sync(sc, cmd, 2, buffer);
432 cmd = ADBLISTEN(addr, 1);
433 buffer[0]=0x03;
434 buffer[1]=0x38;
435 adbms_send_sync(sc, cmd, 2, buffer);
437 sc->sc_buttons = 3;
438 sc->sc_res = 400;
440 } else {
441 /* Attempt to initialize as an A3 mouse */
442 buffer[1] = 0x03; /* make handler ID 3 */
443 cmd = ADBLISTEN(addr, 3);
444 if (!adbms_send_sync(sc, cmd, len, buffer)) {
445 #ifdef ADBMS_DEBUG
446 printf("adb: ems_init timed out\n");
447 #endif
448 return;
452 * Check to see if successful, if not
453 * try to initialize it as other types
455 cmd = ADBTALK(addr, 3);
456 if(adbms_send_sync(sc, cmd, 0, NULL)) {
457 len = sc->sc_msg_len;
458 memcpy(buffer, sc->sc_buffer, len);
459 if (buffer[1] == ADBMS_MSA3) {
460 sc->sc_adbdev->handler_id = ADBMS_MSA3;
461 /* Initialize as above */
462 cmd = ADBLISTEN(addr, 2);
463 /* listen 2 */
464 buffer[0] = 0x00;
465 /* Irrelevant, buffer has 0x77 */
466 buffer[2] = 0x07;
468 * enable 3 button mode = 0111b,
469 * speed = normal
471 adbms_send_sync(sc, cmd, 3, buffer);
472 sc->sc_buttons = 3;
473 sc->sc_res = 300;
479 static void
480 adbms_handler(void *cookie, int len, uint8_t *data)
482 struct adbms_softc *sc = cookie;
484 #ifdef ADBMS_DEBUG
485 int i;
486 printf("%s: %02x - ", device_xname(sc->sc_dev), sc->sc_us);
487 for (i = 0; i < len; i++) {
488 printf(" %02x", data[i]);
490 printf("\n");
491 #endif
492 if (len >= 2) {
493 memcpy(sc->sc_buffer, &data[2], len - 2);
494 sc->sc_msg_len = len - 2;
495 if (data[1] == sc->sc_us) {
496 /* make sense of the mouse message */
497 adbms_process_event(sc, sc->sc_msg_len, sc->sc_buffer);
498 return;
500 wakeup(&sc->sc_event);
501 } else {
502 DPRINTF("bogus message\n");
506 static void
507 adbms_process_event(struct adbms_softc *sc, int len, uint8_t *buffer)
509 int buttons = 0, mask, dx, dy, i;
510 int button_bit = 1;
512 if ((sc->sc_adbdev->handler_id == ADBMS_EXTENDED) && (sc->sc_devid[0] == 0)) {
513 /* massage the data to look like EMP data */
514 if ((buffer[2] & 0x04) == 0x04)
515 buffer[0] &= 0x7f;
516 else
517 buffer[0] |= 0x80;
518 if ((buffer[2] & 0x02) == 0x02)
519 buffer[1] &= 0x7f;
520 else
521 buffer[1] |= 0x80;
522 if ((buffer[2] & 0x01) == 0x01)
523 buffer[2] = 0x00;
524 else
525 buffer[2] = 0x80;
528 switch (sc->sc_adbdev->handler_id) {
529 case ADBMS_USPEED:
530 case ADBMS_UCONTOUR:
531 /* MicroSpeed mouse and Contour mouse */
532 if (len == 4)
533 buttons = (~buffer[3]) & 0xff;
534 else
535 buttons = (buffer[1] & 0x80) ? 0 : 1;
536 break;
537 case ADBMS_MSA3:
538 /* Mouse Systems A3 mouse */
539 if (len == 3)
540 buttons = (~buffer[2]) & 0x07;
541 else
542 buttons = (buffer[0] & 0x80) ? 0 : 1;
543 break;
544 default:
545 /* Classic Mouse Protocol (up to 2 buttons) */
546 for (i = 0; i < 2; i++, button_bit <<= 1)
547 /* 0 when button down */
548 if (!(buffer[i] & 0x80))
549 buttons |= button_bit;
550 else
551 buttons &= ~button_bit;
552 /* Extended Protocol (up to 6 more buttons) */
553 for (mask = 0x80; i < len;
554 i += (mask == 0x80), button_bit <<= 1) {
555 /* 0 when button down */
556 if (!(buffer[i] & mask))
557 buttons |= button_bit;
558 else
559 buttons &= ~button_bit;
560 mask = ((mask >> 4) & 0xf)
561 | ((mask & 0xf) << 4);
563 break;
566 dx = ((int)(buffer[1] & 0x3f)) - ((buffer[1] & 0x40) ? 64 : 0);
567 dy = ((int)(buffer[0] & 0x3f)) - ((buffer[0] & 0x40) ? 64 : 0);
569 if (sc->sc_class == MSCLASS_TRACKPAD) {
571 if (sc->sc_tapping == 1) {
572 if (sc->sc_down) {
573 /* finger is down - collect motion data */
574 sc->sc_x += dx;
575 sc->sc_y += dy;
577 DPRINTF("buttons: %02x\n", buttons);
578 switch (sc->sc_buttons) {
579 case 2:
580 buttons |= ((buttons & 2) >> 1);
581 adbms_mangle_2(sc, buttons);
582 break;
583 case 4:
584 adbms_mangle_4(sc, buttons);
585 break;
588 /* filter the pseudo-buttons out */
589 buttons &= 1;
592 if (sc->sc_wsmousedev)
593 wsmouse_input(sc->sc_wsmousedev, sc->sc_mb | buttons,
594 dx, -dy, 0, 0,
595 WSMOUSE_INPUT_DELTA);
596 #if NAED > 0
597 aed_input(&new_event);
598 #endif
601 static void
602 adbms_mangle_2(struct adbms_softc *sc, int buttons)
605 if (buttons & 4) {
606 /* finger down on pad */
607 if (sc->sc_down == 0) {
608 sc->sc_down = 1;
609 sc->sc_x = 0;
610 sc->sc_y = 0;
613 if (buttons & 8) {
614 /* finger up */
615 if (sc->sc_down) {
616 if (((sc->sc_x * sc->sc_x +
617 sc->sc_y * sc->sc_y) < 20) &&
618 (sc->sc_wsmousedev)) {
620 * if there wasn't much movement between
621 * finger down and up again we assume
622 * someone tapped the pad and we just
623 * send a mouse button event
625 wsmouse_input(sc->sc_wsmousedev,
626 1, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
628 sc->sc_down = 0;
633 static void
634 adbms_mangle_4(struct adbms_softc *sc, int buttons)
637 if (buttons & 0x20) {
638 /* finger down on pad */
639 if (sc->sc_down == 0) {
640 sc->sc_down = 1;
641 sc->sc_x = 0;
642 sc->sc_y = 0;
645 if ((buttons & 0x20) == 0) {
646 /* finger up */
647 if (sc->sc_down) {
648 if (((sc->sc_x * sc->sc_x +
649 sc->sc_y * sc->sc_y) < 20) &&
650 (sc->sc_wsmousedev)) {
652 * if there wasn't much movement between
653 * finger down and up again we assume
654 * someone tapped the pad and we just
655 * send a mouse button event
657 wsmouse_input(sc->sc_wsmousedev,
658 1, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
660 sc->sc_down = 0;
665 static int
666 adbms_enable(void *v)
668 return 0;
671 static int
672 adbms_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
675 switch (cmd) {
676 case WSMOUSEIO_GTYPE:
677 *(u_int *)data = WSMOUSE_TYPE_ADB;
678 break;
680 default:
681 return (EPASSTHROUGH);
683 return (0);
686 static void
687 adbms_disable(void *v)
691 static void
692 init_trackpad(struct adbms_softc *sc)
694 struct sysctlnode *me = NULL, *node = NULL;
695 int cmd, addr, ret;
696 uint8_t buffer[16];
697 uint8_t b2[] = {0x99, 0x94, 0x19, 0xff, 0xb2, 0x8a, 0x1b, 0x50};
699 addr = sc->sc_adbdev->current_addr;
700 cmd = ADBTALK(addr, 1);
701 if (!adbms_send_sync(sc, cmd, 0, NULL))
702 return;
704 if (sc->sc_msg_len != 8)
705 return;
707 memcpy(buffer, sc->sc_buffer, 8);
709 /* now whack the pad */
710 cmd = ADBLISTEN(addr, 1);
711 buffer[6] = 0x0d;
712 adbms_send_sync(sc, cmd, 8, buffer);
714 delay(1000);
715 cmd = ADBLISTEN(addr, 2);
716 adbms_send_sync(sc, cmd, 8, b2);
718 delay(1000);
719 cmd = ADBLISTEN(addr, 1);
720 buffer[6] = 0x03;
721 adbms_send_sync(sc, cmd, 8, buffer);
723 cmd = ADBFLUSH(addr);
724 adbms_send_sync(sc, cmd, 0, NULL);
725 delay(1000);
728 * setup a sysctl node to control wether tapping the pad should
729 * trigger mouse button events
732 sc->sc_tapping = 1;
734 ret = sysctl_createv(NULL, 0, NULL, (const struct sysctlnode **)&me,
735 CTLFLAG_READWRITE,
736 CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
737 NULL, 0, NULL, 0,
738 CTL_MACHDEP, CTL_CREATE, CTL_EOL);
740 ret = sysctl_createv(NULL, 0, NULL, (const struct sysctlnode **)&node,
741 CTLFLAG_READWRITE | CTLFLAG_OWNDESC | CTLFLAG_IMMEDIATE,
742 CTLTYPE_INT, "tapping", "tapping the pad causes button events",
743 sysctl_adbms_tap, 1, NULL, 0,
744 CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL);
745 if (node != NULL) {
746 node->sysctl_data = sc;
750 static int
751 adbms_wait(struct adbms_softc *sc, int timeout)
753 int cnt = 0;
755 if (sc->sc_poll) {
756 while (sc->sc_msg_len == -1) {
757 sc->sc_ops->poll(sc->sc_ops->cookie);
759 } else {
760 while ((sc->sc_msg_len == -1) && (cnt < timeout)) {
761 tsleep(&sc->sc_event, 0, "adbkbdio", hz);
762 cnt++;
765 return (sc->sc_msg_len > 0);
768 static int
769 adbms_send_sync(struct adbms_softc *sc, uint8_t cmd, int len, uint8_t *msg)
771 int i;
773 sc->sc_msg_len = -1;
774 DPRINTF("send: %02x", cmd);
775 for (i = 0; i < len; i++)
776 DPRINTF(" %02x", msg[i]);
777 DPRINTF("\n");
778 sc->sc_ops->send(sc->sc_ops->cookie, sc->sc_poll, cmd, len, msg);
779 adbms_wait(sc, 1000);
780 return (sc->sc_msg_len != -1);
783 static int
784 sysctl_adbms_tap(SYSCTLFN_ARGS)
786 struct sysctlnode node = *rnode;
787 struct adbms_softc *sc = node.sysctl_data;
789 node.sysctl_idata = sc->sc_tapping;
791 if (newp) {
793 /* we're asked to write */
794 node.sysctl_data = &sc->sc_tapping;
795 if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
797 sc->sc_tapping = (node.sysctl_idata == 0) ? 0 : 1;
798 return 0;
800 return EINVAL;
801 } else {
803 node.sysctl_size = 4;
804 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
807 return 0;
810 SYSCTL_SETUP(sysctl_ams_setup, "sysctl ams subtree setup")
813 sysctl_createv(NULL, 0, NULL, NULL,
814 CTLFLAG_PERMANENT,
815 CTLTYPE_NODE, "machdep", NULL,
816 NULL, 0, NULL, 0,
817 CTL_MACHDEP, CTL_EOL);